git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1037 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1179 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1179 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2006, Intel Corporation                                                         
 | |
| All rights reserved. This program and the accompanying materials                          
 | |
| are licensed and made available under the terms and conditions of the BSD License         
 | |
| which accompanies this distribution.  The full text of the license may be found at        
 | |
| http://opensource.org/licenses/bsd-license.php                                            
 | |
|                                                                                           
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | |
| 
 | |
|   Module Name:
 | |
| 
 | |
|     UsbIo.c
 | |
| 
 | |
|   Abstract:
 | |
| 
 | |
|     USB I/O Abstraction Driver
 | |
| 
 | |
|   Revision History
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include "usbbus.h"
 | |
| 
 | |
| //
 | |
| // USB I/O Support Function Prototypes
 | |
| //
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbControlTransfer (
 | |
|   IN       EFI_USB_IO_PROTOCOL        *This,
 | |
|   IN       EFI_USB_DEVICE_REQUEST     *Request,
 | |
|   IN       EFI_USB_DATA_DIRECTION     Direction,
 | |
|   IN       UINT32                     Timeout,
 | |
|   IN OUT   VOID                       *Data, OPTIONAL
 | |
|   IN       UINTN                      DataLength, OPTIONAL
 | |
|   OUT      UINT32                     *Status
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbBulkTransfer (
 | |
|   IN       EFI_USB_IO_PROTOCOL     *This,
 | |
|   IN       UINT8                   DeviceEndpoint,
 | |
|   IN OUT   VOID                    *Data,
 | |
|   IN OUT   UINTN                   *DataLength,
 | |
|   IN       UINTN                   Timeout,
 | |
|   OUT      UINT32                  *Status
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbAsyncInterruptTransfer (
 | |
|   IN EFI_USB_IO_PROTOCOL                 * This,
 | |
|   IN UINT8                               DeviceEndpoint,
 | |
|   IN BOOLEAN                             IsNewTransfer,
 | |
|   IN UINTN                               PollingInterval, OPTIONAL
 | |
|   IN UINTN                               DataLength, OPTIONAL
 | |
|   IN EFI_ASYNC_USB_TRANSFER_CALLBACK     InterruptCallBack, OPTIONAL
 | |
|   IN VOID                                *Context OPTIONAL
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbSyncInterruptTransfer (
 | |
|   IN       EFI_USB_IO_PROTOCOL     *This,
 | |
|   IN       UINT8                   DeviceEndpoint,
 | |
|   IN OUT   VOID                    *Data,
 | |
|   IN OUT   UINTN                   *DataLength,
 | |
|   IN       UINTN                   Timeout,
 | |
|   OUT      UINT32                  *Status
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbIsochronousTransfer (
 | |
|   IN       EFI_USB_IO_PROTOCOL     *This,
 | |
|   IN       UINT8                   DeviceEndpoint,
 | |
|   IN OUT   VOID                    *Data,
 | |
|   IN       UINTN                   DataLength,
 | |
|   OUT      UINT32                  *Status
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbAsyncIsochronousTransfer (
 | |
|   IN        EFI_USB_IO_PROTOCOL                 * This,
 | |
|   IN        UINT8                               DeviceEndpoint,
 | |
|   IN OUT    VOID                                *Data,
 | |
|   IN        UINTN                               DataLength,
 | |
|   IN        EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
 | |
|   IN        VOID                                *Context OPTIONAL
 | |
|   );
 | |
| 
 | |
| extern
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbPortReset (
 | |
|   IN EFI_USB_IO_PROTOCOL     *This
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetDeviceDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL           *This,
 | |
|   OUT EFI_USB_DEVICE_DESCRIPTOR     *DeviceDescriptor
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetActiveConfigDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL           *This,
 | |
|   OUT EFI_USB_CONFIG_DESCRIPTOR     *ConfigurationDescriptor
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetInterfaceDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL              *This,
 | |
|   OUT EFI_USB_INTERFACE_DESCRIPTOR     *InterfaceDescriptor
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetEndpointDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL             *This,
 | |
|   IN  UINT8                           EndpointIndex,
 | |
|   OUT EFI_USB_ENDPOINT_DESCRIPTOR     *EndpointDescriptor
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetStringDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL     *This,
 | |
|   IN  UINT16                  LangID,
 | |
|   IN  UINT8                   StringIndex,
 | |
|   OUT CHAR16                  **String
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetSupportedLanguages (
 | |
|   IN  EFI_USB_IO_PROTOCOL      *This,
 | |
|   OUT UINT16                   **LangIDTable,
 | |
|   OUT UINT16                   *TableSize
 | |
|   );
 | |
| 
 | |
| //
 | |
| // USB I/O Interface structure
 | |
| //
 | |
| STATIC EFI_USB_IO_PROTOCOL  UsbIoInterface = {
 | |
|   UsbControlTransfer,
 | |
|   UsbBulkTransfer,
 | |
|   UsbAsyncInterruptTransfer,
 | |
|   UsbSyncInterruptTransfer,
 | |
|   UsbIsochronousTransfer,
 | |
|   UsbAsyncIsochronousTransfer,
 | |
|   UsbGetDeviceDescriptor,
 | |
|   UsbGetActiveConfigDescriptor,
 | |
|   UsbGetInterfaceDescriptor,
 | |
|   UsbGetEndpointDescriptor,
 | |
|   UsbGetStringDescriptor,
 | |
|   UsbGetSupportedLanguages,
 | |
|   UsbPortReset
 | |
| };
 | |
| 
 | |
| VOID
 | |
| InitializeUsbIoInstance (
 | |
|   IN USB_IO_CONTROLLER_DEVICE     *UsbIoController
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Copy EFI_USB_IO protocol instance
 | |
|   //
 | |
|   CopyMem (
 | |
|     &UsbIoController->UsbIo,
 | |
|     &UsbIoInterface,
 | |
|     sizeof (EFI_USB_IO_PROTOCOL)
 | |
|     );
 | |
| }
 | |
| //
 | |
| // Implementation
 | |
| //
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbControlTransfer (
 | |
|   IN       EFI_USB_IO_PROTOCOL        *This,
 | |
|   IN       EFI_USB_DEVICE_REQUEST     *Request,
 | |
|   IN       EFI_USB_DATA_DIRECTION     Direction,
 | |
|   IN       UINT32                     Timeout,
 | |
|   IN OUT   VOID                       *Data, OPTIONAL
 | |
|   IN       UINTN                      DataLength, OPTIONAL
 | |
|   OUT      UINT32                     *Status
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     This function is used to manage a USB device with a control transfer pipe.
 | |
| 
 | |
|   Arguments:
 | |
|     This        -   Indicates calling context.
 | |
|     Request     -   A pointer to the USB device request that will be sent to
 | |
|                     the USB device.
 | |
|     Direction   -   Indicates the data direction.
 | |
|     Data        -   A pointer to the buffer of data that will be transmitted
 | |
|                     to USB device or received from USB device.
 | |
|     Timeout     -   Indicates the transfer should be completed within this time
 | |
|                     frame.
 | |
|     DataLength  -   The size, in bytes, of the data buffer specified by Data.
 | |
|     Status      -   A pointer to the result of the USB transfer.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|     EFI_TIMEOUT
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
| 
 | |
|   EFI_STATUS                RetStatus;
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
|   UINT8                     MaxPacketLength;
 | |
|   UINT32                    TransferResult;
 | |
|   BOOLEAN                   Disconnected;
 | |
|   //
 | |
|   // Parameters Checking
 | |
|   //
 | |
|   if (Status == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // leave the HostController's ControlTransfer
 | |
|   // to perform other parameters checking
 | |
|   //
 | |
|   UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
|   UsbIoDev        = UsbIoController->UsbDevice;
 | |
| 
 | |
|   MaxPacketLength = UsbIoDev->DeviceDescriptor.MaxPacketSize0;
 | |
| 
 | |
|  
 | |
|   if (Request->Request     == USB_DEV_CLEAR_FEATURE && 
 | |
|       Request->RequestType == 0x02                  && 
 | |
|       Request->Value       == EfiUsbEndpointHalt) {
 | |
|      //
 | |
|      //Reduce the remove delay time for system response
 | |
|      //
 | |
|      IsDeviceDisconnected (UsbIoController, &Disconnected);
 | |
|      if (!EFI_ERROR (Status) && Disconnected == TRUE) {
 | |
|       DEBUG ((gUSBErrorLevel, "Device is disconnected when trying reset\n"));
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // using HostController's ControlTransfer to complete the request
 | |
|   //
 | |
|   RetStatus = UsbVirtualHcControlTransfer (
 | |
|                 UsbIoDev->BusController,
 | |
|                 UsbIoDev->DeviceAddress,
 | |
|                 UsbIoDev->DeviceSpeed,
 | |
|                 MaxPacketLength,
 | |
|                 Request,
 | |
|                 Direction,
 | |
|                 Data,
 | |
|                 &DataLength,
 | |
|                 (UINTN) Timeout,
 | |
|                 UsbIoDev->Translator,
 | |
|                 &TransferResult
 | |
|                 );
 | |
| 
 | |
|   *Status = TransferResult;
 | |
| 
 | |
|   if (Request->Request     == USB_DEV_CLEAR_FEATURE && 
 | |
|       Request->RequestType == 0x02                  && 
 | |
|       Request->Value       == EfiUsbEndpointHalt) {
 | |
|     //
 | |
|     // This is a UsbClearEndpointHalt request
 | |
|     // Need to clear data toggle
 | |
|     // Request.Index == EndpointAddress
 | |
|     //
 | |
|     if (!EFI_ERROR (RetStatus) && TransferResult == EFI_USB_NOERROR) {
 | |
|       SetDataToggleBit (
 | |
|         This,
 | |
|         (UINT8) Request->Index,
 | |
|         0
 | |
|         );
 | |
|     }
 | |
|   }
 | |
|   return RetStatus;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbBulkTransfer (
 | |
|   IN       EFI_USB_IO_PROTOCOL     *This,
 | |
|   IN       UINT8                   DeviceEndpoint,
 | |
|   IN OUT   VOID                    *Data,
 | |
|   IN OUT   UINTN                   *DataLength,
 | |
|   IN       UINTN                   Timeout,
 | |
|   OUT      UINT32                  *Status
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     This function is used to manage a USB device with the bulk transfer pipe.
 | |
| 
 | |
|   Arguments:
 | |
|     This            - Indicates calling context.
 | |
|     DeviceEndpoint  - The destination USB device endpoint to which the device
 | |
|                       request is being sent.
 | |
|     Data            - A pointer to the buffer of data that will be transmitted
 | |
|                       to USB device or received from USB device.
 | |
|     DataLength      - On input, the size, in bytes, of the data buffer
 | |
|                       specified by Data.  On output, the number of bytes that
 | |
|                       were actually transferred.
 | |
|     Timeout         - Indicates the transfer should be completed within this
 | |
|                       time frame.
 | |
|     Status          - This parameter indicates the USB transfer status.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|     EFI_TIMEOUT
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_DEVICE               *UsbIoDev;
 | |
|   UINTN                       MaxPacketLength;
 | |
|   UINT8                       DataToggle;
 | |
|   UINT8                       OldToggle;
 | |
|   EFI_STATUS                  RetStatus;
 | |
| 
 | |
|   USB_IO_CONTROLLER_DEVICE    *UsbIoController;
 | |
|   ENDPOINT_DESC_LIST_ENTRY    *EndPointListEntry;
 | |
|   UINT32                      TransferResult;
 | |
|   UINT8                       DataBuffersNumber;
 | |
|   
 | |
|   DataBuffersNumber = 1;
 | |
|   UsbIoController   = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
|   UsbIoDev          = UsbIoController->UsbDevice;
 | |
| 
 | |
|   //
 | |
|   // Parameters Checking
 | |
|   //
 | |
|   if ((DeviceEndpoint & 0x7F) == 0) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if ((DeviceEndpoint & 0x7F) > 15) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Status == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   EndPointListEntry = FindEndPointListEntry (
 | |
|                         This,
 | |
|                         DeviceEndpoint
 | |
|                         );
 | |
| 
 | |
|   if (EndPointListEntry == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if ((EndPointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x02) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|                         
 | |
|   //
 | |
|   // leave the HostController's BulkTransfer
 | |
|   // to perform other parameters checking
 | |
|   //
 | |
|   GetDeviceEndPointMaxPacketLength (
 | |
|     This,
 | |
|     DeviceEndpoint,
 | |
|     &MaxPacketLength
 | |
|     );
 | |
| 
 | |
|   GetDataToggleBit (
 | |
|     This,
 | |
|     DeviceEndpoint,
 | |
|     &DataToggle
 | |
|     );
 | |
| 
 | |
|   OldToggle = DataToggle;
 | |
| 
 | |
|   //
 | |
|   // using HostController's BulkTransfer to complete the request
 | |
|   //
 | |
|   RetStatus = UsbVirtualHcBulkTransfer (
 | |
|                 UsbIoDev->BusController,
 | |
|                 UsbIoDev->DeviceAddress,
 | |
|                 DeviceEndpoint,
 | |
|                 UsbIoDev->DeviceSpeed,
 | |
|                 MaxPacketLength,
 | |
|                 DataBuffersNumber,
 | |
|                 &Data,
 | |
|                 DataLength,
 | |
|                 &DataToggle,
 | |
|                 Timeout,
 | |
|                 UsbIoDev->Translator,
 | |
|                 &TransferResult
 | |
|                 );
 | |
| 
 | |
|   if (OldToggle != DataToggle) {
 | |
|     //
 | |
|     // Write the toggle back
 | |
|     //
 | |
|     SetDataToggleBit (
 | |
|       This,
 | |
|       DeviceEndpoint,
 | |
|       DataToggle
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   *Status = TransferResult;
 | |
| 
 | |
|   return RetStatus;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbSyncInterruptTransfer (
 | |
|   IN       EFI_USB_IO_PROTOCOL     *This,
 | |
|   IN       UINT8                   DeviceEndpoint,
 | |
|   IN OUT   VOID                    *Data,
 | |
|   IN OUT   UINTN                   *DataLength,
 | |
|   IN       UINTN                   Timeout,
 | |
|   OUT      UINT32                  *Status
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Usb Sync Interrupt Transfer
 | |
| 
 | |
|   Arguments:
 | |
|     This            - Indicates calling context.
 | |
|     DeviceEndpoint  - The destination USB device endpoint to which the device
 | |
|                       request is being sent.
 | |
|     Data            - A pointer to the buffer of data that will be transmitted
 | |
|                       to USB device or received from USB device.
 | |
|     DataLength      - On input, the size, in bytes, of the data buffer
 | |
|                       specified by Data.  On output, the number of bytes that
 | |
|                       were actually transferred.
 | |
|     Timeout         - Indicates the transfer should be completed within this
 | |
|                       time frame.
 | |
|     Status          - This parameter indicates the USB transfer status.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|     EFI_TIMEOUT
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
|   UINTN                     MaxPacketLength;
 | |
|   UINT8                     DataToggle;
 | |
|   UINT8                     OldToggle;
 | |
|   EFI_STATUS                RetStatus;
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
|   ENDPOINT_DESC_LIST_ENTRY  *EndPointListEntry;
 | |
| 
 | |
|   //
 | |
|   // Parameters Checking
 | |
|   //
 | |
|   if ((DeviceEndpoint & 0x7F) == 0) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if ((DeviceEndpoint & 0x7F) > 15) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Status == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   EndPointListEntry = FindEndPointListEntry (
 | |
|                         This,
 | |
|                         DeviceEndpoint
 | |
|                         );
 | |
| 
 | |
|   if (EndPointListEntry == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if ((EndPointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x03) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // leave the HostController's SyncInterruptTransfer
 | |
|   // to perform other parameters checking
 | |
|   //
 | |
|   UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
|   UsbIoDev        = UsbIoController->UsbDevice;
 | |
|   GetDeviceEndPointMaxPacketLength (
 | |
|     This,
 | |
|     DeviceEndpoint,
 | |
|     &MaxPacketLength
 | |
|     );
 | |
| 
 | |
|   GetDataToggleBit (
 | |
|     This,
 | |
|     DeviceEndpoint,
 | |
|     &DataToggle
 | |
|     );
 | |
| 
 | |
|   OldToggle = DataToggle;
 | |
|   //
 | |
|   // using HostController's SyncInterruptTransfer to complete the request
 | |
|   //
 | |
|   RetStatus = UsbVirtualHcSyncInterruptTransfer (
 | |
|                 UsbIoDev->BusController,
 | |
|                 UsbIoDev->DeviceAddress,
 | |
|                 DeviceEndpoint,
 | |
|                 UsbIoDev->DeviceSpeed,
 | |
|                 MaxPacketLength,
 | |
|                 Data,
 | |
|                 DataLength,
 | |
|                 &DataToggle,
 | |
|                 Timeout,
 | |
|                 UsbIoDev->Translator,
 | |
|                 Status
 | |
|                 );
 | |
| 
 | |
|   if (OldToggle != DataToggle) {
 | |
|     //
 | |
|     // Write the toggle back
 | |
|     //
 | |
|     SetDataToggleBit (
 | |
|       This,
 | |
|       DeviceEndpoint,
 | |
|       DataToggle
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   return RetStatus;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbAsyncInterruptTransfer (
 | |
|   IN EFI_USB_IO_PROTOCOL                 *This,
 | |
|   IN UINT8                               DeviceEndpoint,
 | |
|   IN BOOLEAN                             IsNewTransfer,
 | |
|   IN UINTN                               PollingInterval, OPTIONAL
 | |
|   IN UINTN                               DataLength, OPTIONAL
 | |
|   IN EFI_ASYNC_USB_TRANSFER_CALLBACK     InterruptCallBack, OPTIONAL
 | |
|   IN VOID                                *Context OPTIONAL
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Usb Async Interrput Transfer
 | |
| 
 | |
|   Arguments:
 | |
|     This              -   Indicates calling context.
 | |
|     DeviceEndpoint    -   The destination USB device endpoint to which the
 | |
|                           device request is being sent.
 | |
|     IsNewTransfer     -   If TRUE, a new transfer will be submitted to USB
 | |
|                           controller.  If FALSE,  the interrupt transfer is
 | |
|                           deleted from the device's interrupt transfer queue.
 | |
|     PollingInterval   -   Indicates the periodic rate, in milliseconds, that
 | |
|                           the transfer is to be executed.
 | |
|     DataLength        -   Specifies the length, in bytes, of the data to be
 | |
|                           received from the USB device.
 | |
|     InterruptCallBack -   The Callback function.  This function is called if
 | |
|                           the asynchronous interrupt transfer is completed.
 | |
|     Context           -   Passed to InterruptCallback 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_OUT_OF_RESOURCES
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
|   UINTN                     MaxPacketLength;
 | |
|   UINT8                     DataToggle;
 | |
|   EFI_STATUS                RetStatus;
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
|   ENDPOINT_DESC_LIST_ENTRY  *EndpointListEntry;
 | |
| 
 | |
|   //
 | |
|   // Check endpoint
 | |
|   //
 | |
|   if ((DeviceEndpoint & 0x7F) == 0) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if ((DeviceEndpoint & 0x7F) > 15) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   EndpointListEntry = FindEndPointListEntry (
 | |
|                         This,
 | |
|                         DeviceEndpoint
 | |
|                         );
 | |
| 
 | |
|   if (EndpointListEntry == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if ((EndpointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x03) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
|   UsbIoDev        = UsbIoController->UsbDevice;
 | |
| 
 | |
|   if (!IsNewTransfer) {
 | |
|     //
 | |
|     // Delete this transfer
 | |
|     //
 | |
|     UsbVirtualHcAsyncInterruptTransfer (
 | |
|       UsbIoDev->BusController,
 | |
|       UsbIoDev->DeviceAddress,
 | |
|       DeviceEndpoint,
 | |
|       UsbIoDev->DeviceSpeed,
 | |
|       0,
 | |
|       FALSE,
 | |
|       &DataToggle,
 | |
|       PollingInterval,
 | |
|       DataLength,
 | |
|       UsbIoDev->Translator,
 | |
|       NULL,
 | |
|       NULL
 | |
|       );
 | |
| 
 | |
|     //
 | |
|     // We need to store the toggle value
 | |
|     //
 | |
|     SetDataToggleBit (
 | |
|       This,
 | |
|       DeviceEndpoint,
 | |
|       DataToggle
 | |
|       );
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   GetDeviceEndPointMaxPacketLength (
 | |
|     This,
 | |
|     DeviceEndpoint,
 | |
|     &MaxPacketLength
 | |
|     );
 | |
| 
 | |
|   GetDataToggleBit (
 | |
|     This,
 | |
|     DeviceEndpoint,
 | |
|     &DataToggle
 | |
|     );
 | |
| 
 | |
|   RetStatus = UsbVirtualHcAsyncInterruptTransfer (
 | |
|                 UsbIoDev->BusController,
 | |
|                 UsbIoDev->DeviceAddress,
 | |
|                 DeviceEndpoint,
 | |
|                 UsbIoDev->DeviceSpeed,
 | |
|                 MaxPacketLength,
 | |
|                 TRUE,
 | |
|                 &DataToggle,
 | |
|                 PollingInterval,
 | |
|                 DataLength,
 | |
|                 UsbIoDev->Translator,
 | |
|                 InterruptCallBack,
 | |
|                 Context
 | |
|                 );
 | |
| 
 | |
|   return RetStatus;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbIsochronousTransfer (
 | |
|   IN       EFI_USB_IO_PROTOCOL     *This,
 | |
|   IN       UINT8                   DeviceEndpoint,
 | |
|   IN OUT   VOID                    *Data,
 | |
|   IN       UINTN                   DataLength,
 | |
|   OUT      UINT32                  *Status
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Usb Isochronous Transfer
 | |
| 
 | |
|   Arguments:
 | |
|     This              -   Indicates calling context.
 | |
|     DeviceEndpoint    -   The destination USB device endpoint to which the
 | |
|                           device request is being sent.
 | |
|     Data              -   A pointer to the buffer of data that will be
 | |
|                           transmitted to USB device or received from USB device.
 | |
|     DataLength        -   The size, in bytes, of the data buffer specified by
 | |
|                           Data.
 | |
|     Status            -   This parameter indicates the USB transfer status.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|     EFI_TIMEOUT
 | |
|     EFI_DEVICE_ERROR
 | |
|     EFI_UNSUPPORTED
 | |
| --*/
 | |
| {
 | |
|   //
 | |
|   // Currently we don't support this transfer
 | |
|   //
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbAsyncIsochronousTransfer (
 | |
|   IN        EFI_USB_IO_PROTOCOL                 *This,
 | |
|   IN        UINT8                               DeviceEndpoint,
 | |
|   IN OUT    VOID                                *Data,
 | |
|   IN        UINTN                               DataLength,
 | |
|   IN        EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
 | |
|   IN        VOID                                *Context OPTIONAL
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Usb Async Isochronous Transfer
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This                - EFI_USB_IO_PROTOCOL
 | |
|   DeviceEndpoint      - DeviceEndpoint number
 | |
|   Data                - Data to transfer
 | |
|   DataLength          - DataLength
 | |
|   IsochronousCallBack - Isochronous CallBack function
 | |
|   Context             - Passed to IsochronousCallBack function
 | |
| Returns:
 | |
| 
 | |
|   EFI_UNSUPPORTED     - Unsupported now
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   //
 | |
|   // Currently we don't support this transfer
 | |
|   //
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| //
 | |
| // Here is new definitions
 | |
| //
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetDeviceDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL           *This,
 | |
|   OUT EFI_USB_DEVICE_DESCRIPTOR     *DeviceDescriptor
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Retrieves the USB Device Descriptor.
 | |
| 
 | |
|   Arguments:
 | |
|     This              -   Indicates the calling context.
 | |
|     DeviceDescriptor  -   A pointer to the caller allocated USB Device
 | |
|                           Descriptor.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_NOT_FOUND
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
| 
 | |
|   //
 | |
|   // This function just wrapps UsbGetDeviceDescriptor.
 | |
|   //
 | |
|   
 | |
|   if (DeviceDescriptor == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
|   UsbIoDev        = UsbIoController->UsbDevice;
 | |
| 
 | |
|   if (!UsbIoDev->IsConfigured) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   CopyMem (
 | |
|     DeviceDescriptor,
 | |
|     &UsbIoDev->DeviceDescriptor,
 | |
|     sizeof (EFI_USB_DEVICE_DESCRIPTOR)
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetActiveConfigDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL           *This,
 | |
|   OUT EFI_USB_CONFIG_DESCRIPTOR     *ConfigurationDescriptor
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Retrieves the current USB configuration Descriptor.
 | |
| 
 | |
|   Arguments:
 | |
|     This                     -   Indicates the calling context.
 | |
|     ConfigurationDescriptor  -   A pointer to the caller allocated USB active
 | |
|                                  Configuration Descriptor.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_NOT_FOUND
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
| 
 | |
|   //
 | |
|   // This function just wrapps UsbGetActiveConfigDescriptor.
 | |
|   //
 | |
|   if (ConfigurationDescriptor == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
|   UsbIoDev        = UsbIoController->UsbDevice;
 | |
| 
 | |
|   if (!UsbIoDev->IsConfigured) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   CopyMem (
 | |
|     ConfigurationDescriptor,
 | |
|     &(UsbIoDev->ActiveConfig->CongfigDescriptor),
 | |
|     sizeof (EFI_USB_CONFIG_DESCRIPTOR)
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetInterfaceDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL              *This,
 | |
|   OUT EFI_USB_INTERFACE_DESCRIPTOR     *InterfaceDescriptor
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Retrieves the interface Descriptor for that controller.
 | |
| 
 | |
|   Arguments:
 | |
|     This                  -   Indicates the calling context.
 | |
|     InterfaceDescriptor   -   A pointer to the caller allocated USB interface
 | |
|                               Descriptor.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_NOT_FOUND
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
 | |
| 
 | |
|   if (InterfaceDescriptor == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   InterfaceListEntry = FindInterfaceListEntry (This);
 | |
| 
 | |
|   if (InterfaceListEntry == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   CopyMem (
 | |
|     InterfaceDescriptor,
 | |
|     &(InterfaceListEntry->InterfaceDescriptor),
 | |
|     sizeof (EFI_USB_INTERFACE_DESCRIPTOR)
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetEndpointDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL             *This,
 | |
|   IN  UINT8                           EndpointIndex,
 | |
|   OUT EFI_USB_ENDPOINT_DESCRIPTOR     *EndpointDescriptor
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Retrieves the endpoint Descriptor for a given endpoint.
 | |
| 
 | |
|   Arguments:
 | |
|     This                  -   Indicates the calling context.
 | |
|     EndpointIndex         -   Indicates which endpoint descriptor to retrieve.
 | |
|                               The valid range is 0..15.
 | |
|     EndpointDescriptor    -   A pointer to the caller allocated USB Endpoint
 | |
|                               Descriptor of a USB controller.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS           -   The endpoint descriptor was retrieved successfully.
 | |
|     EFI_INVALID_PARAMETER -   EndpointIndex is not valid.
 | |
|                           -   EndpointDescriptor is NULL.
 | |
|     EFI_NOT_FOUND         -   The endpoint descriptor cannot be found.
 | |
|                               The device may not be correctly configured.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
 | |
|   LIST_ENTRY            *EndpointListHead;
 | |
|   ENDPOINT_DESC_LIST_ENTRY  *EndpointListEntry;
 | |
| 
 | |
|   if (EndpointDescriptor == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (EndpointIndex > 15) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   InterfaceListEntry = FindInterfaceListEntry (This);
 | |
| 
 | |
|   if (InterfaceListEntry == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   EndpointListHead  = (LIST_ENTRY *) (&InterfaceListEntry->EndpointDescListHead);
 | |
|   EndpointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointListHead->ForwardLink);
 | |
| 
 | |
|   if (EndpointIndex >= InterfaceListEntry->InterfaceDescriptor.NumEndpoints) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
|   //
 | |
|   // Loop all endpoint descriptor to get match one.
 | |
|   //
 | |
|   while (EndpointIndex != 0) {
 | |
|     EndpointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointListEntry->Link.ForwardLink);
 | |
|     EndpointIndex--;
 | |
|   }
 | |
| 
 | |
|   CopyMem (
 | |
|     EndpointDescriptor,
 | |
|     &EndpointListEntry->EndpointDescriptor,
 | |
|     sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetSupportedLanguages (
 | |
|   IN  EFI_USB_IO_PROTOCOL     *This,
 | |
|   OUT UINT16                  **LangIDTable,
 | |
|   OUT UINT16                  *TableSize
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Get all the languages that the USB device supports
 | |
| 
 | |
|   Arguments:
 | |
|     This        -   Indicates the calling context.
 | |
|     LangIDTable -   Language ID for the string the caller wants to get.
 | |
|     TableSize   -   The size, in bytes, of the table LangIDTable.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_NOT_FOUND
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
|   UINTN                     Index;
 | |
|   BOOLEAN                   Found;
 | |
| 
 | |
|   UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
|   UsbIoDev        = UsbIoController->UsbDevice;
 | |
| 
 | |
|   Found           = FALSE;
 | |
|   Index           = 0;
 | |
|   //
 | |
|   // Loop language table
 | |
|   //
 | |
|   while (UsbIoDev->LangID[Index]) {
 | |
|     Found = TRUE;
 | |
|     Index++;
 | |
|   }
 | |
| 
 | |
|   if (!Found) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   *LangIDTable  = UsbIoDev->LangID;
 | |
|   *TableSize    = (UINT16) Index;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbGetStringDescriptor (
 | |
|   IN  EFI_USB_IO_PROTOCOL     *This,
 | |
|   IN  UINT16                  LangID,
 | |
|   IN  UINT8                   StringIndex,
 | |
|   OUT CHAR16                  **String
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Get a given string descriptor
 | |
| 
 | |
|   Arguments:
 | |
|     This          -   Indicates the calling context.
 | |
|     LangID        -   The Language ID for the string being retrieved.
 | |
|     StringIndex  -   The ID of the string being retrieved.
 | |
|     String        -   A pointer to a buffer allocated by this function
 | |
|                       with AllocatePool() to store the string.  If this
 | |
|                       function returns EFI_SUCCESS, it stores the string
 | |
|                       the caller wants to get.  The caller should release
 | |
|                       the string buffer with FreePool() after the string
 | |
|                       is not used any more.
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_NOT_FOUND
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|     EFI_UNSUPPORTED
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT32                    Status;
 | |
|   EFI_STATUS                Result;
 | |
|   EFI_USB_STRING_DESCRIPTOR *StrDescriptor;
 | |
|   UINT8                     *Buffer;
 | |
|   CHAR16                    *UsbString;
 | |
|   UINT16                    TempBuffer;
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
|   UINT8                     Index;
 | |
|   BOOLEAN                   Found;
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
| 
 | |
|   if (StringIndex == 0) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
|   //
 | |
|   // Search LanguageID, check if it is supported by this device
 | |
|   //
 | |
|   if (LangID == 0) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
|   UsbIoDev        = UsbIoController->UsbDevice;
 | |
| 
 | |
|   Found           = FALSE;
 | |
|   Index           = 0;
 | |
|   while (UsbIoDev->LangID[Index]) {
 | |
|     if (UsbIoDev->LangID[Index] == LangID) {
 | |
|       Found = TRUE;
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Index++;
 | |
|   }
 | |
| 
 | |
|   if (!Found) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
|   //
 | |
|   // Get String Length
 | |
|   //
 | |
|   Result = UsbGetString (
 | |
|             This,
 | |
|             LangID,
 | |
|             StringIndex,
 | |
|             &TempBuffer,
 | |
|             2,
 | |
|             &Status
 | |
|             );
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   StrDescriptor = (EFI_USB_STRING_DESCRIPTOR *) &TempBuffer;
 | |
| 
 | |
|   if (StrDescriptor->Length == 0) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   Buffer = AllocateZeroPool (StrDescriptor->Length);
 | |
|   if (Buffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Result = UsbGetString (
 | |
|             This,
 | |
|             LangID,
 | |
|             StringIndex,
 | |
|             Buffer,
 | |
|             StrDescriptor->Length,
 | |
|             &Status
 | |
|             );
 | |
| 
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     gBS->FreePool (Buffer);
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   StrDescriptor = (EFI_USB_STRING_DESCRIPTOR *) Buffer;
 | |
| 
 | |
|   //
 | |
|   // UsbString is a UNICODE string
 | |
|   //
 | |
|   UsbString = AllocateZeroPool (StrDescriptor->Length);
 | |
|   if (UsbString == NULL) {
 | |
|     gBS->FreePool (Buffer);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   CopyMem (
 | |
|     (VOID *) UsbString,
 | |
|     Buffer + 2,
 | |
|     StrDescriptor->Length - 2
 | |
|     );
 | |
| 
 | |
|   *String = UsbString;
 | |
| 
 | |
|   gBS->FreePool (Buffer);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |