--- /dev/null
+/** @file\r
+Common Libarary for PEI USB\r
+\r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>\r
+ \r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution. The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "UsbPeim.h"\r
+#include "PeiUsbLib.h"\r
+\r
+/**\r
+ Get a given usb descriptor.\r
+\r
+ @param PeiServices General-purpose services that are available to every PEIM.\r
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
+ @param Value Request Value.\r
+ @param Index Request Index.\r
+ @param DescriptorLength Request descriptor Length.\r
+ @param Descriptor Request descriptor.\r
+\r
+\r
+ @retval EFI_SUCCESS Usb descriptor is obtained successfully.\r
+ @retval EFI_DEVICE_ERROR Cannot get the usb descriptor due to a hardware error.\r
+ @retval Others Other failure occurs.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiUsbGetDescriptor (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_USB_IO_PPI *UsbIoPpi,\r
+ IN UINT16 Value,\r
+ IN UINT16 Index,\r
+ IN UINT16 DescriptorLength,\r
+ OUT VOID *Descriptor\r
+ )\r
+{\r
+ EFI_USB_DEVICE_REQUEST DevReq;\r
+\r
+ ASSERT (UsbIoPpi != NULL);\r
+\r
+ DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;\r
+ DevReq.Request = USB_DEV_GET_DESCRIPTOR;\r
+ DevReq.Value = Value;\r
+ DevReq.Index = Index;\r
+ DevReq.Length = DescriptorLength;\r
+\r
+ return UsbIoPpi->UsbControlTransfer (\r
+ PeiServices,\r
+ UsbIoPpi,\r
+ &DevReq,\r
+ EfiUsbDataIn,\r
+ PcdGet32 (PcdUsbTransferTimeoutValue),\r
+ Descriptor,\r
+ DescriptorLength\r
+ );\r
+}\r
+\r
+/**\r
+ Set a usb device with a specified address.\r
+\r
+ @param PeiServices General-purpose services that are available to every PEIM.\r
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
+ @param AddressValue The address to assign.\r
+\r
+ @retval EFI_SUCCESS Usb device address is set successfully.\r
+ @retval EFI_DEVICE_ERROR Cannot set the usb address due to a hardware error.\r
+ @retval Others Other failure occurs.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiUsbSetDeviceAddress (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_USB_IO_PPI *UsbIoPpi,\r
+ IN UINT16 AddressValue\r
+ )\r
+{\r
+ EFI_USB_DEVICE_REQUEST DevReq;\r
+\r
+ ASSERT (UsbIoPpi != NULL);\r
+\r
+ DevReq.RequestType = USB_DEV_SET_ADDRESS_REQ_TYPE;\r
+ DevReq.Request = USB_DEV_SET_ADDRESS;\r
+ DevReq.Value = AddressValue;\r
+ DevReq.Index = 0;\r
+ DevReq.Length = 0;\r
+\r
+ return UsbIoPpi->UsbControlTransfer (\r
+ PeiServices,\r
+ UsbIoPpi,\r
+ &DevReq,\r
+ EfiUsbNoData,\r
+ PcdGet32 (PcdUsbTransferTimeoutValue),\r
+ NULL,\r
+ 0\r
+ );\r
+}\r
+\r
+/**\r
+ Clear a given usb feature.\r
+\r
+ @param PeiServices General-purpose services that are available to every PEIM.\r
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
+ @param Recipient The recipient of ClearFeature Request, should be one of Device/Interface/Endpoint.\r
+ @param Value Request Value.\r
+ @param Target Request Index.\r
+\r
+ @retval EFI_SUCCESS Usb feature is cleared successfully.\r
+ @retval EFI_DEVICE_ERROR Cannot clear the usb feature due to a hardware error.\r
+ @retval Others Other failure occurs.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiUsbClearDeviceFeature (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_USB_IO_PPI *UsbIoPpi,\r
+ IN EFI_USB_RECIPIENT Recipient,\r
+ IN UINT16 Value,\r
+ IN UINT16 Target\r
+ )\r
+{\r
+ EFI_USB_DEVICE_REQUEST DevReq;\r
+\r
+ ASSERT (UsbIoPpi != NULL);\r
+\r
+ switch (Recipient) {\r
+ case EfiUsbDevice:\r
+ DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D;\r
+ break;\r
+\r
+ case EfiUsbInterface:\r
+ DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I;\r
+ break;\r
+\r
+ case EfiUsbEndpoint:\r
+ DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E;\r
+ break;\r
+ }\r
+\r
+ DevReq.Request = USB_DEV_CLEAR_FEATURE;\r
+ DevReq.Value = Value;\r
+ DevReq.Index = Target;\r
+ DevReq.Length = 0;\r
+\r
+ return UsbIoPpi->UsbControlTransfer (\r
+ PeiServices,\r
+ UsbIoPpi,\r
+ &DevReq,\r
+ EfiUsbNoData,\r
+ PcdGet32 (PcdUsbTransferTimeoutValue),\r
+ NULL,\r
+ 0\r
+ );\r
+}\r
+\r
+/**\r
+ Configure a usb device to Configuration 1.\r
+\r
+ @param PeiServices General-purpose services that are available to every PEIM.\r
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
+\r
+ @retval EFI_SUCCESS Usb device is set to use Configuration 1 successfully.\r
+ @retval EFI_DEVICE_ERROR Cannot set the usb device due to a hardware error.\r
+ @retval Others Other failure occurs.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiUsbSetConfiguration (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_USB_IO_PPI *UsbIoPpi\r
+ )\r
+{\r
+ EFI_USB_DEVICE_REQUEST DevReq;\r
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));\r
+\r
+ DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE;\r
+ DevReq.Request = USB_DEV_SET_CONFIGURATION;\r
+ DevReq.Value = 1;\r
+\r
+ return UsbIoPpi->UsbControlTransfer (\r
+ PeiServices,\r
+ UsbIoPpi,\r
+ &DevReq,\r
+ EfiUsbNoData,\r
+ PcdGet32 (PcdUsbTransferTimeoutValue),\r
+ NULL,\r
+ 0\r
+ );\r
+}\r
+\r
+/**\r
+ Clear Endpoint Halt.\r
+\r
+ @param PeiServices General-purpose services that are available to every PEIM.\r
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
+ @param EndpointAddress The endpoint address.\r
+\r
+ @retval EFI_SUCCESS Endpoint halt is cleared successfully.\r
+ @retval EFI_DEVICE_ERROR Cannot clear the endpoint halt status due to a hardware error.\r
+ @retval Others Other failure occurs.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiUsbClearEndpointHalt (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_USB_IO_PPI *UsbIoPpi,\r
+ IN UINT8 EndpointAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PEI_USB_DEVICE *PeiUsbDev;\r
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;\r
+ UINT8 EndpointIndex;\r
+\r
+ EndpointIndex = 0;\r
+ PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (UsbIoPpi);\r
+\r
+ while (EndpointIndex < MAX_ENDPOINT) {\r
+ Status = UsbIoPpi->UsbGetEndpointDescriptor (PeiServices, UsbIoPpi, EndpointIndex, &EndpointDescriptor);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (EndpointDescriptor->EndpointAddress == EndpointAddress) {\r
+ break;\r
+ }\r
+\r
+ EndpointIndex++;\r
+ }\r
+\r
+ if (EndpointIndex == MAX_ENDPOINT) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PeiUsbClearDeviceFeature (\r
+ PeiServices,\r
+ UsbIoPpi,\r
+ EfiUsbEndpoint,\r
+ EfiUsbEndpointHalt,\r
+ EndpointAddress\r
+ );\r
+\r
+ //\r
+ // set data toggle to zero.\r
+ //\r
+ if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {\r
+ PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Judge if the port is connected with a usb device or not.\r
+\r
+ @param PortStatus The usb port status gotten.\r
+\r
+ @retval TRUE A usb device is connected with the port.\r
+ @retval FALSE No usb device is connected with the port.\r
+\r
+**/\r
+BOOLEAN\r
+IsPortConnect (\r
+ IN UINT16 PortStatus\r
+ )\r
+{\r
+ //\r
+ // return the bit 0 value of PortStatus\r
+ //\r
+ if ((PortStatus & USB_PORT_STAT_CONNECTION) != 0) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Judge if the port is connected with a low-speed usb device or not.\r
+\r
+ @param PortStatus The usb port status gotten.\r
+\r
+ @retval TRUE A low-speed usb device is connected with the port.\r
+ @retval FALSE No low-speed usb device is connected with the port.\r
+\r
+**/\r
+UINTN\r
+IsPortLowSpeedDeviceAttached (\r
+ IN UINT16 PortStatus\r
+ )\r
+{\r
+ //\r
+ // return the bit 9 value of PortStatus\r
+ //\r
+ if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {\r
+ return EFI_USB_SPEED_LOW;\r
+ } else if ((PortStatus & USB_PORT_STAT_HIGH_SPEED) != 0){\r
+ return EFI_USB_SPEED_HIGH;\r
+ } else {\r
+ return EFI_USB_SPEED_FULL;\r
+ }\r
+}\r
+\r
+/**\r
+ Judge if the port is in "connection change" status or not.\r
+\r
+ @param PortChangeStatus The usb port change status gotten.\r
+\r
+ @retval TRUE The port is in "connection change" status.\r
+ @retval FALSE The port is NOT in "connection change" status.\r
+\r
+**/\r
+BOOLEAN\r
+IsPortConnectChange (\r
+ IN UINT16 PortChangeStatus\r
+ )\r
+{\r
+ //\r
+ // return the bit 0 value of PortChangeStatus\r
+ //\r
+ if ((PortChangeStatus & USB_PORT_STAT_C_CONNECTION) != 0) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r