summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MdePkg/Include/Library/UefiUsbLib.h131
-rw-r--r--MdePkg/Library/UefiUsbLib/UefiUsbLib.inf3
-rw-r--r--MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h2
-rw-r--r--MdePkg/Library/UefiUsbLib/UsbDxeLib.c533
4 files changed, 669 insertions, 0 deletions
diff --git a/MdePkg/Include/Library/UefiUsbLib.h b/MdePkg/Include/Library/UefiUsbLib.h
index a8ab47aeff..fd85be0670 100644
--- a/MdePkg/Include/Library/UefiUsbLib.h
+++ b/MdePkg/Include/Library/UefiUsbLib.h
@@ -3,6 +3,7 @@
and the standard requests defined in USB 1.1 spec.
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2024, American Megatrends Intenational LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -552,4 +553,134 @@ UsbClearEndpointHalt (
OUT UINT32 *Status
);
+/**
+ Retrieve the interface descriptor details from the interface setting.
+
+ This is an extended version of UsbIo->GetInterfaceDescriptor. It returns the interface
+ descriptor for an alternate setting of the interface without executing SET_INTERFACE
+ transfer. It also returns the number of class specific interfaces.
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[out] Descriptor The caller allocated buffer to return the contents of the Interface descriptor.
+ @param[out] CsInterfaceNumber Number of class specific interfaces for this interface setting.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER Descriptor or CsInterfaceNumber is NULL.
+ @retval EFI_UNSUPPORTED Setting is greater than the number of alternate settings in this interface.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetInterfaceDescriptorSetting (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ OUT EFI_USB_INTERFACE_DESCRIPTOR *Descriptor,
+ OUT UINTN *CsInterfacesNumber
+ );
+
+/**
+ Retrieve the endpoint descriptor from the interface setting.
+
+ This is an extended version of UsbIo->GetEndpointDescriptor. It returns the endpoint
+ descriptor for an alternate setting of a given interface.
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ Note: The total number of endpoints can be retrieved from the interface descriptor
+ returned by EDKII_USBIO_EXT_GET_INTERFACE_DESCRIPTOR function.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Index of the endpoint to retrieve. The valid range is 0..15.
+ @param[out] Descriptor A pointer to the caller allocated USB Interface Descriptor.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+ @retval EFI_UNSUPPORTED Setting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of endpoints in this interface.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetEndpointDescriptorSetting (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor
+ );
+
+/**
+ Retrieve class specific interface descriptor.
+
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Zero-based index of the class specific interface.
+ @param[in][out] BufferSize On input, the size in bytes of the return Descriptor buffer.
+ On output the size of data returned in Descriptor.
+ @param[out] Descriptor The buffer to return the contents of the class specific interface descriptor. May
+ be NULL with a zero BufferSize in order to determine the size buffer needed.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL.
+ Buffer is NULL and *BufferSize is not zero.
+ @retval EFI_UNSUPPORTED Setting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of class specific interfaces.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. BufferSize has been updated with the size
+ needed to complete the request.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetCsInterfaceDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Retrieve class specific endpoint descriptor.
+
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Zero-based index of the non-zero endpoint.
+ @param[in][out] BufferSize On input, the size in bytes of the return Descriptor buffer.
+ On output the size of data returned in Descriptor.
+ @param[out] Descriptor The buffer to return the contents of the class specific endpoint descriptor. May
+ be NULL with a zero BufferSize in order to determine the size buffer needed.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL.
+ Buffer is NULL and *BufferSize is not zero.
+ @retval EFI_UNSUPPORTED Setting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of endpoints in this interface.
+ Endpoint does not have class specific endpoint descriptor.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. BufferSize has been updated with the size
+ needed to complete the request.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetCsEndpointDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
#endif
diff --git a/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf b/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
index bb483b922f..ae6d598f23 100644
--- a/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+++ b/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
@@ -5,6 +5,7 @@
# Usb Hid 1.1 spec and the standard requests defined in Usb 1.1 spec.
#
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2024, American Megatrends International LLC. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -19,6 +20,7 @@
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = UefiUsbLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ DESTRUCTOR = UefiUsbLibDestructor
#
@@ -37,6 +39,7 @@
DebugLib
BaseMemoryLib
PcdLib
+ UefiBootServicesTableLib
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdUsbTransferTimeoutValue ## CONSUMES
diff --git a/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h b/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h
index 185fc6d86e..9112983452 100644
--- a/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h
+++ b/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h
@@ -5,6 +5,7 @@
This file includes package header files, library classes and protocol, PPI & GUID definitions.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2024, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -17,6 +18,7 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
#include <IndustryStandard/Usb.h>
diff --git a/MdePkg/Library/UefiUsbLib/UsbDxeLib.c b/MdePkg/Library/UefiUsbLib/UsbDxeLib.c
index 53b90984f7..b783a31620 100644
--- a/MdePkg/Library/UefiUsbLib/UsbDxeLib.c
+++ b/MdePkg/Library/UefiUsbLib/UsbDxeLib.c
@@ -4,12 +4,16 @@
in Usb specification 9.4 section.
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2024, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UefiUsbLibInternal.h"
+static UINT8 *mConfigData = NULL;
+static EFI_USB_DEVICE_DESCRIPTOR mDeviceDescriptor;
+
/**
Get the descriptor of the specified USB device.
@@ -650,3 +654,532 @@ UsbClearEndpointHalt (
return Result;
}
+
+/**
+ Global library data initialization.
+
+ Library public functions' input is the instance of UsbIo protocol. Check if the global
+ data relevant to the UsbIo. If not, read the device and update the global data.
+
+ @param UsbIo The instance of EFI_USB_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The global data is updated.
+ @retval EFI_NOT_FOUND The UsbIo configuration was not found.
+
+**/
+static
+EFI_STATUS
+InitUsbConfigDescriptorData (
+ EFI_USB_IO_PROTOCOL *UsbIo
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc;
+ EFI_USB_CONFIG_DESCRIPTOR CnfDesc;
+ UINT8 ConfigNum;
+ UINT8 ConfigValue;
+ UINT32 UsbStatus;
+
+ //
+ // Get UsbIo device and configuration descriptors.
+ //
+ Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = UsbIo->UsbGetConfigDescriptor (UsbIo, &CnfDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ if (mConfigData != NULL) {
+ if ( (CompareMem (&DevDesc, &mDeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR)) == 0)
+ && (CompareMem (&CnfDesc, mConfigData, sizeof (EFI_USB_CONFIG_DESCRIPTOR)) == 0))
+ {
+ return EFI_SUCCESS;
+ }
+
+ gBS->FreePool (mConfigData);
+ mConfigData = NULL;
+ }
+
+ CopyMem (&mDeviceDescriptor, &DevDesc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
+
+ //
+ // Examine device with multiple configurations: find configuration index of UsbIo config descriptor.
+ //
+ // Use EFI_USB_DEVICE_DESCRIPTOR.NumConfigurations to loop through configuration descriptors, match
+ // EFI_USB_CONFIG_DESCRIPTOR.ConfigurationValue to the configuration value reported by UsbIo->UsbGetConfigDescriptor.
+ // The index of the matched configuration is used in wValue of the following GET_DESCRIPTOR request.
+ //
+ ConfigValue = CnfDesc.ConfigurationValue;
+ for (ConfigNum = 0; ConfigNum < DevDesc.NumConfigurations; ConfigNum++) {
+ Status = UsbGetDescriptor (
+ UsbIo,
+ (USB_DESC_TYPE_CONFIG << 8) | ConfigNum,
+ 0,
+ sizeof (EFI_USB_CONFIG_DESCRIPTOR),
+ &CnfDesc,
+ &UsbStatus
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (CnfDesc.ConfigurationValue == ConfigValue) {
+ break;
+ }
+ }
+
+ ASSERT (ConfigNum < DevDesc.NumConfigurations);
+ if (ConfigNum == DevDesc.NumConfigurations) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // ConfigNum has zero based index of the configuration that UsbIo belongs to. Use this index to retrieve
+ // full configuration descriptor data.
+ //
+ Status = gBS->AllocatePool (EfiBootServicesData, CnfDesc.TotalLength, (VOID **)&mConfigData);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = UsbGetDescriptor (
+ UsbIo,
+ (USB_DESC_TYPE_CONFIG << 8) | ConfigNum,
+ 0,
+ CnfDesc.TotalLength,
+ mConfigData,
+ &UsbStatus
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Find descriptor of a given type within data area pointed by mConfigData.
+
+ The following are the assumptions of the configuration descriptor layout:
+ - mConfigData is populated with the configuration data that contains USB interface referenced by UsbIo.
+ - Endpoint may have only one class specific descriptor that immediately follows the endpoint descriptor.
+
+ @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] DescType Type of descriptor to look for.
+ @param[in] Setting Interface alternate setting.
+ @param[in] Index Index of the descriptor. This descriptor index is used to find a specific
+ descriptor (only for endpoint descriptors and class specific interface descriptors)
+ when several descriptors of the same type are implemented in a device. For other
+ descriptor types, a descriptor index of zero must be used.
+ @param[out] Data A pointer to the caller allocated Descriptor.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_UNSUPPORTED Setting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of descriptors of the requested type in this
+ interface.
+**/
+static
+EFI_STATUS
+FindUsbDescriptor (
+ EFI_USB_IO_PROTOCOL *UsbIo,
+ UINT8 DescType,
+ UINT16 Setting,
+ UINTN Index,
+ VOID **Data
+ )
+{
+ EFI_USB_INTERFACE_DESCRIPTOR IntfDesc;
+ EFI_STATUS Status;
+ UINT8 *BufferPtr;
+ UINT8 *BufferEnd;
+ UINT8 *ConfigEnd;
+ UINTN Idx;
+
+ //
+ // Find the interface descriptor referenced by UsbIo in the current configuration
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IntfDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ ConfigEnd = mConfigData + ((EFI_USB_CONFIG_DESCRIPTOR *)mConfigData)->TotalLength;
+
+ for (BufferPtr = mConfigData; BufferPtr < ConfigEnd; BufferPtr += BufferPtr[0]) {
+ if (BufferPtr[1] == USB_DESC_TYPE_INTERFACE) {
+ if ((BufferPtr[2] == IntfDesc.InterfaceNumber) && (BufferPtr[3] == (UINT8)Setting)) {
+ break;
+ }
+ }
+ }
+
+ if (BufferPtr >= ConfigEnd) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Found the beginning of the interface, find the ending
+ //
+ for (BufferEnd = BufferPtr + BufferPtr[0]; BufferEnd < ConfigEnd; BufferEnd += BufferEnd[0]) {
+ if (BufferEnd[1] == USB_DESC_TYPE_INTERFACE) {
+ break;
+ }
+ }
+
+ Idx = 0;
+
+ if (DescType == USB_DESC_TYPE_INTERFACE) {
+ *Data = BufferPtr;
+ return EFI_SUCCESS;
+ }
+
+ if ((DescType == USB_DESC_TYPE_ENDPOINT) || (DescType == USB_DESC_TYPE_CS_ENDPOINT)) {
+ while (BufferPtr < BufferEnd) {
+ BufferPtr += BufferPtr[0];
+ if (BufferPtr[1] == USB_DESC_TYPE_ENDPOINT) {
+ if (Idx == Index) {
+ if (DescType == USB_DESC_TYPE_CS_ENDPOINT) {
+ BufferPtr += BufferPtr[0];
+ if (BufferPtr[1] != USB_DESC_TYPE_CS_ENDPOINT) {
+ break;
+ }
+ }
+
+ *Data = BufferPtr;
+ return EFI_SUCCESS;
+ }
+
+ Idx++;
+ }
+ }
+ }
+
+ if (DescType == USB_DESC_TYPE_CS_INTERFACE) {
+ while (BufferPtr < BufferEnd) {
+ BufferPtr += BufferPtr[0];
+ if (BufferPtr[1] == USB_DESC_TYPE_CS_INTERFACE) {
+ if (Idx == Index) {
+ *Data = BufferPtr;
+ return EFI_SUCCESS;
+ }
+
+ Idx++;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Retrieve the number of class specific interface descriptors.
+
+ @param[in] Data A pointer to the USB interface descriptor that may contain class code descriptors.
+
+ @retval UINT8 Number of the class code interface descriptors.
+
+**/
+static
+UINT8
+FindNumberOfCsInterfaces (
+ VOID *Data
+ )
+{
+ UINT8 *Buffer;
+ UINT8 *ConfigEnd;
+ UINT8 Index;
+
+ Buffer = Data;
+ ConfigEnd = mConfigData + ((EFI_USB_CONFIG_DESCRIPTOR *)mConfigData)->TotalLength;
+
+ Index = 0;
+
+ for (Buffer += Buffer[0]; Buffer < ConfigEnd; Buffer += Buffer[0]) {
+ if (Buffer[1] == USB_DESC_TYPE_INTERFACE) {
+ break;
+ }
+
+ if (Buffer[1] == USB_DESC_TYPE_CS_INTERFACE) {
+ Index++;
+ }
+ }
+
+ return Index;
+}
+
+/**
+ Retrieve the interface descriptor details from the interface setting.
+
+ This is an extended version of UsbIo->GetInterfaceDescriptor. It returns the interface
+ descriptor for an alternate setting of the interface without executing SET_INTERFACE
+ transfer. It also returns the number of class specific interfaces.
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[out] Descriptor The caller allocated buffer to return the contents of the Interface descriptor.
+ @param[out] CsInterfaceNumber Number of class specific interfaces for this interface setting.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER Descriptor or CsInterfaceNumber is NULL.
+ @retval EFI_UNSUPPORTED AlternateSetting is greater than the number of alternate settings in this interface.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetInterfaceDescriptorSetting (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ OUT EFI_USB_INTERFACE_DESCRIPTOR *Descriptor,
+ OUT UINTN *CsInterfacesNumber
+ )
+{
+ EFI_STATUS Status;
+ VOID *Data;
+ EFI_TPL OldTpl;
+
+ if ((Descriptor == NULL) || (CsInterfacesNumber == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = InitUsbConfigDescriptorData (This);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ Status = FindUsbDescriptor (This, USB_DESC_TYPE_INTERFACE, AlternateSetting, 0, &Data);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ *CsInterfacesNumber = FindNumberOfCsInterfaces (Data);
+ CopyMem (Descriptor, Data, sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Retrieve the endpoint descriptor from the interface setting.
+
+ This is an extended version of UsbIo->GetEndpointDescriptor. It returns the endpoint
+ descriptor for an alternate setting of a given interface.
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ Note: The total number of endpoints can be retrieved from the interface descriptor
+ returned by EDKII_USBIO_EXT_GET_INTERFACE_DESCRIPTOR function.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Index of the endpoint to retrieve. The valid range is 0..15.
+ @param[out] Descriptor A pointer to the caller allocated USB Interface Descriptor.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+ @retval EFI_UNSUPPORTED AlternateSetting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of endpoints in this interface.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetEndpointDescriptorSetting (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor
+ )
+{
+ EFI_STATUS Status;
+ VOID *Data;
+ EFI_TPL OldTpl;
+
+ if (Descriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = InitUsbConfigDescriptorData (This);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ Status = FindUsbDescriptor (This, USB_DESC_TYPE_ENDPOINT, AlternateSetting, Index, &Data);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ CopyMem (Descriptor, Data, sizeof (EFI_USB_ENDPOINT_DESCRIPTOR));
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Retrieve class specific interface descriptor.
+
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Zero-based index of the class specific interface.
+ @param[in][out] BufferSize On input, the size in bytes of the return Descriptor buffer.
+ On output the size of data returned in Descriptor.
+ @param[out] Descriptor The buffer to return the contents of the class specific interface descriptor. May
+ be NULL with a zero BufferSize in order to determine the size buffer needed.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL.
+ Buffer is NULL and *BufferSize is not zero.
+ @retval EFI_UNSUPPORTED AlternateSetting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of class specific interfaces.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. BufferSize has been updated with the size
+ needed to complete the request.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetCsInterfaceDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ VOID *Data;
+ UINT8 DescLength;
+ EFI_TPL OldTpl;
+
+ if ((BufferSize == NULL) || ((Buffer == NULL) && (*BufferSize != 0))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = InitUsbConfigDescriptorData (This);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ Status = FindUsbDescriptor (This, USB_DESC_TYPE_CS_INTERFACE, AlternateSetting, Index, &Data);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ DescLength = ((UINT8 *)Data)[0];
+
+ if ((Buffer == NULL) || (DescLength > *BufferSize)) {
+ *BufferSize = DescLength;
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+
+ CopyMem (Buffer, Data, DescLength);
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Retrieve class specific endpoint descriptor.
+
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Zero-based index of the non-zero endpoint.
+ @param[in][out] BufferSize On input, the size in bytes of the return Descriptor buffer.
+ On output the size of data returned in Descriptor.
+ @param[out] Descriptor The buffer to return the contents of the class specific endpoint descriptor. May
+ be NULL with a zero BufferSize in order to determine the size buffer needed.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL.
+ Buffer is NULL and *BufferSize is not zero.
+ @retval EFI_UNSUPPORTED AlternateSetting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of endpoints in this interface.
+ Endpoint does not have class specific endpoint descriptor.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. BufferSize has been updated with the size
+ needed to complete the request.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetCsEndpointDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ VOID *Data;
+ UINT8 DescLength;
+ EFI_TPL OldTpl;
+
+ if ((BufferSize == NULL) || ((Buffer == NULL) && (*BufferSize != 0))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = InitUsbConfigDescriptorData (This);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ Status = FindUsbDescriptor (This, USB_DESC_TYPE_CS_ENDPOINT, AlternateSetting, Index, &Data);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ DescLength = ((UINT8 *)Data)[0];
+
+ if ((Buffer == NULL) || (DescLength > *BufferSize)) {
+ *BufferSize = DescLength;
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+
+ CopyMem (Buffer, Data, DescLength);
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Destructor frees memory which was allocated by the library functions.
+
+ @param ImageHandle Handle that identifies the image to be unloaded.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiUsbLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (mConfigData != NULL) {
+ gBS->FreePool (mConfigData);
+ }
+
+ return EFI_SUCCESS;
+}