+/**\r
+ Get a given SuperSpeed hub 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 HubDescriptor Caller allocated buffer to store the hub descriptor if\r
+ successfully returned.\r
+\r
+ @retval EFI_SUCCESS Hub descriptor is obtained successfully.\r
+ @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.\r
+ @retval Others Other failure occurs.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiGetSuperSpeedHubDesc (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_USB_IO_PPI *UsbIoPpi,\r
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor\r
+ )\r
+{\r
+ EFI_USB_DEVICE_REQUEST DevReq;\r
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));\r
+\r
+ //\r
+ // Fill Device request packet\r
+ //\r
+ DevReq.RequestType = USB_RT_HUB | 0x80;\r
+ DevReq.Request = USB_HUB_GET_DESCRIPTOR;\r
+ DevReq.Value = USB_DT_SUPERSPEED_HUB << 8;\r
+ DevReq.Length = 12;\r
+\r
+ return UsbIoPpi->UsbControlTransfer (\r
+ PeiServices,\r
+ UsbIoPpi,\r
+ &DevReq,\r
+ EfiUsbDataIn,\r
+ PcdGet32 (PcdUsbTransferTimeoutValue),\r
+ HubDescriptor,\r
+ 12\r
+ );\r
+}\r
+\r
+/**\r
+ Read the whole usb hub descriptor. It is necessary\r
+ to do it in two steps because hub descriptor is of\r
+ variable length.\r
+\r
+ @param PeiServices General-purpose services that are available to every PEIM.\r
+ @param PeiUsbDevice Indicates the hub controller device.\r
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
+ @param HubDescriptor Caller allocated buffer to store the hub descriptor if\r
+ successfully returned.\r
+\r
+ @retval EFI_SUCCESS Hub descriptor is obtained successfully.\r
+ @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.\r
+ @retval Others Other failure occurs.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiUsbHubReadDesc (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_USB_DEVICE *PeiUsbDevice,\r
+ IN PEI_USB_IO_PPI *UsbIoPpi,\r
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
+ //\r
+ // Get the super speed hub descriptor\r
+ //\r
+ Status = PeiGetSuperSpeedHubDesc (PeiServices, UsbIoPpi, HubDescriptor);\r
+ } else {\r
+\r
+ //\r
+ // First get the hub descriptor length\r
+ //\r
+ Status = PeiGetHubDescriptor (PeiServices, UsbIoPpi, 2, HubDescriptor);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the whole hub descriptor\r
+ //\r
+ Status = PeiGetHubDescriptor (PeiServices, UsbIoPpi, HubDescriptor->Length, HubDescriptor);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ USB hub control transfer to set the hub depth.\r
+\r
+ @param PeiServices General-purpose services that are available to every PEIM.\r
+ @param PeiUsbDevice Indicates the hub controller device.\r
+ @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
+\r
+ @retval EFI_SUCCESS Depth of the hub is set.\r
+ @retval Others Failed to set the depth.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiUsbHubCtrlSetHubDepth (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_USB_DEVICE *PeiUsbDevice,\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
+ //\r
+ // Fill Device request packet\r
+ //\r
+ DevReq.RequestType = USB_RT_HUB;\r
+ DevReq.Request = USB_HUB_REQ_SET_DEPTH;\r
+ DevReq.Value = PeiUsbDevice->Tier;\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