/*++ 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 ); 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 ) /*++ Routine Description: Initialize the instance of UsbIo controller Arguments: UsbIoController - A pointer to controller structure of UsbIo Returns: --*/ { // // 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; UINT8 DataBuffersNumber; UINT32 TransferResult; 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; }