]> git.proxmox.com Git - mirror_edk2.git/commitdiff
edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c:
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 26 Feb 2008 01:13:29 +0000 (01:13 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 26 Feb 2008 01:13:29 +0000 (01:13 +0000)
  Rename to 'UsbBus.c' to match file naming conventions.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4754 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c [new file with mode: 0644]
MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c [deleted file]

diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
new file mode 100644 (file)
index 0000000..332871a
--- /dev/null
@@ -0,0 +1,1470 @@
+/** @file\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The 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
+  Module Name:\r
+\r
+    UsbBus.c\r
+\r
+  Abstract:\r
+\r
+    Usb Bus Driver Binding and Bus IO Protocol\r
+\r
+  Revision History\r
+\r
+\r
+**/\r
+\r
+#include "UsbBus.h"\r
+\r
+//\r
+// USB_BUS_PROTOCOL is only used to locate USB_BUS\r
+//\r
+EFI_GUID  mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;\r
+\r
+\r
+/**\r
+  USB_IO function to execute a control transfer. This\r
+  function will execute the USB transfer. If transfer\r
+  successes, it will sync the internal state of USB bus\r
+  with device state.\r
+\r
+  @param  This                   The USB_IO instance\r
+  @param  Request                The control transfer request\r
+  @param  Direction              Direction for data stage\r
+  @param  Timeout                The time to wait before timeout\r
+  @param  Data                   The buffer holding the data\r
+  @param  DataLength             Then length of the data\r
+  @param  UsbStatus              USB result\r
+\r
+  @retval EFI_INVALID_PARAMETER  The parameters are invalid\r
+  @retval EFI_SUCCESS            The control transfer succeded.\r
+  @retval Others                 Failed to execute the transfer\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoControlTransfer (\r
+  IN  EFI_USB_IO_PROTOCOL     *This,\r
+  IN  EFI_USB_DEVICE_REQUEST  *Request,\r
+  IN  EFI_USB_DATA_DIRECTION  Direction,\r
+  IN  UINT32                  Timeout,\r
+  IN  OUT VOID                *Data,      OPTIONAL\r
+  IN  UINTN                   DataLength, OPTIONAL\r
+  OUT UINT32                  *UsbStatus\r
+  )\r
+{\r
+  USB_DEVICE              *Dev;\r
+  USB_INTERFACE           *UsbIf;\r
+  USB_ENDPOINT_DESC       *EpDesc;\r
+  EFI_TPL                 OldTpl;\r
+  EFI_STATUS              Status;\r
+\r
+  if (UsbStatus == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev    = UsbIf->Device;\r
+\r
+  Status = UsbHcControlTransfer (\r
+             Dev->Bus,\r
+             Dev->Address,\r
+             Dev->Speed,\r
+             Dev->MaxPacket0,\r
+             Request,\r
+             Direction,\r
+             Data,\r
+             &DataLength,\r
+             (UINTN) Timeout,\r
+             &Dev->Translator,\r
+             UsbStatus\r
+             );\r
+\r
+  if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
+    //\r
+    // Clear TT buffer when CTRL/BULK split transaction failes\r
+    // Clear the TRANSLATOR TT buffer, not parent's buffer\r
+    //\r
+    if (Dev->Translator.TranslatorHubAddress != 0) {\r
+      UsbHubCtrlClearTTBuffer (\r
+        Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
+        Dev->Translator.TranslatorPortNumber,\r
+        Dev->Address,\r
+        0,\r
+        USB_ENDPOINT_CONTROL\r
+        );\r
+    }\r
+\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Some control transfer will change the device's internal\r
+  // status, such as Set_Configuration and Set_Interface.\r
+  // We must synchronize the bus driver's status with that in\r
+  // device. We ignore the Set_Descriptor request because it's\r
+  // hardly used by any device, especially in pre-boot environment\r
+  //\r
+\r
+  //\r
+  // Reset the endpoint toggle when endpoint stall is cleared\r
+  //\r
+  if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&\r
+      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
+                                                 USB_TARGET_ENDPOINT)) &&\r
+      (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {\r
+\r
+    EpDesc = UsbGetEndpointDesc (UsbIf, (UINT8) Request->Index);\r
+\r
+    if (EpDesc != NULL) {\r
+      EpDesc->Toggle = 0;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Select a new configuration. This is a dangerous action. Upper driver\r
+  // should stop use its current UsbIo after calling this driver. The old\r
+  // UsbIo will be uninstalled and new UsbIo be installed. We can't use\r
+  // ReinstallProtocol since interfaces in different configuration may be\r
+  // completely irrellvant.\r
+  //\r
+  if ((Request->Request == USB_REQ_SET_CONFIG) &&\r
+      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
+                                                 USB_TARGET_DEVICE))) {\r
+    //\r
+    // Don't re-create the USB interfaces if configuration isn't changed.\r
+    //\r
+    if ((Dev->ActiveConfig != NULL) &&\r
+        (Request->Value == Dev->ActiveConfig->Desc.ConfigurationValue)) {\r
+\r
+      goto ON_EXIT;\r
+    }\r
+    DEBUG ((EFI_D_INFO, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));\r
+\r
+    if (Dev->ActiveConfig != NULL) {\r
+      UsbRemoveConfig (Dev);\r
+    }\r
+\r
+    if (Request->Value != 0) {\r
+      Status = UsbSelectConfig (Dev, (UINT8) Request->Value);\r
+    }\r
+\r
+    //\r
+    // Exit now, Old USB_IO is invalid now\r
+    //\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // A new alternative setting is selected for the interface.\r
+  // No need to reinstall UsbIo in this case because only\r
+  // underlying communication endpoints are changed. Functionality\r
+  // should remains the same.\r
+  //\r
+  if ((Request->Request     == USB_REQ_SET_INTERFACE) &&\r
+      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
+                                                 USB_TARGET_INTERFACE)) &&\r
+      (Request->Index       == UsbIf->IfSetting->Desc.InterfaceNumber)) {\r
+\r
+    Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];\r
+    }\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Execute a bulk transfer to the device endpoint\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  Endpoint               The device endpoint\r
+  @param  Data                   The data to transfer\r
+  @param  DataLength             The length of the data to transfer\r
+  @param  Timeout                Time to wait before timeout\r
+  @param  UsbStatus              The result of USB transfer\r
+\r
+  @retval EFI_SUCCESS            The bulk transfer is OK\r
+  @retval EFI_INVALID_PARAMETER  Some parameters are invalid\r
+  @retval Others                 Failed to execute transfer, reason returned in\r
+                                 UsbStatus\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoBulkTransfer (\r
+  IN  EFI_USB_IO_PROTOCOL *This,\r
+  IN  UINT8               Endpoint,\r
+  IN  OUT VOID            *Data,\r
+  IN  OUT UINTN           *DataLength,\r
+  IN  UINTN               Timeout,\r
+  OUT UINT32              *UsbStatus\r
+  )\r
+{\r
+  USB_DEVICE              *Dev;\r
+  USB_INTERFACE           *UsbIf;\r
+  USB_ENDPOINT_DESC       *EpDesc;\r
+  UINT8                   BufNum;\r
+  UINT8                   Toggle;\r
+  EFI_TPL                 OldTpl;\r
+  EFI_STATUS              Status;\r
+\r
+  if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
+      (UsbStatus == NULL)) {\r
+\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf   = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev     = UsbIf->Device;\r
+\r
+  EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);\r
+\r
+  if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_BULK)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  BufNum  = 1;\r
+  Toggle  = EpDesc->Toggle;\r
+  Status  = UsbHcBulkTransfer (\r
+              Dev->Bus,\r
+              Dev->Address,\r
+              Endpoint,\r
+              Dev->Speed,\r
+              EpDesc->Desc.MaxPacketSize,\r
+              BufNum,\r
+              &Data,\r
+              DataLength,\r
+              &Toggle,\r
+              Timeout,\r
+              &Dev->Translator,\r
+              UsbStatus\r
+              );\r
+\r
+  EpDesc->Toggle = Toggle;\r
+\r
+  if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
+    //\r
+    // Clear TT buffer when CTRL/BULK split transaction failes.\r
+    // Clear the TRANSLATOR TT buffer, not parent's buffer\r
+    //\r
+    if (Dev->Translator.TranslatorHubAddress != 0) {\r
+      UsbHubCtrlClearTTBuffer (\r
+        Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
+        Dev->Translator.TranslatorPortNumber,\r
+        Dev->Address,\r
+        0,\r
+        USB_ENDPOINT_BULK\r
+        );\r
+    }\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Execute a synchronous interrupt transfer\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  Endpoint               The device endpoint\r
+  @param  Data                   The data to transfer\r
+  @param  DataLength             The length of the data to transfer\r
+  @param  Timeout                Time to wait before timeout\r
+  @param  UsbStatus              The result of USB transfer\r
+\r
+  @retval EFI_SUCCESS            The synchronous interrupt transfer is OK\r
+  @retval EFI_INVALID_PARAMETER  Some parameters are invalid\r
+  @retval Others                 Failed to execute transfer, reason returned in\r
+                                 UsbStatus\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoSyncInterruptTransfer (\r
+  IN  EFI_USB_IO_PROTOCOL *This,\r
+  IN  UINT8               Endpoint,\r
+  IN  OUT VOID            *Data,\r
+  IN  OUT UINTN           *DataLength,\r
+  IN  UINTN               Timeout,\r
+  OUT UINT32              *UsbStatus\r
+  )\r
+{\r
+  USB_DEVICE              *Dev;\r
+  USB_INTERFACE           *UsbIf;\r
+  USB_ENDPOINT_DESC       *EpDesc;\r
+  EFI_TPL                 OldTpl;\r
+  UINT8                   Toggle;\r
+  EFI_STATUS              Status;\r
+\r
+  if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
+      (UsbStatus == NULL)) {\r
+\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf   = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev     = UsbIf->Device;\r
+\r
+  EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);\r
+\r
+  if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Toggle = EpDesc->Toggle;\r
+  Status = UsbHcSyncInterruptTransfer (\r
+             Dev->Bus,\r
+             Dev->Address,\r
+             Endpoint,\r
+             Dev->Speed,\r
+             EpDesc->Desc.MaxPacketSize,\r
+             Data,\r
+             DataLength,\r
+             &Toggle,\r
+             Timeout,\r
+             &Dev->Translator,\r
+             UsbStatus\r
+             );\r
+\r
+  EpDesc->Toggle = Toggle;\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Queue a new asynchronous interrupt transfer, or remove the old\r
+  request if (IsNewTransfer == FALSE)\r
+\r
+  @param  This                   The USB_IO instance\r
+  @param  Endpoint               The device endpoint\r
+  @param  IsNewTransfer          Whether this is a new request, if it's old, remove\r
+                                 the request\r
+  @param  PollInterval           The interval to poll the transfer result, (in ms)\r
+  @param  DataLength             The length of perodic data transfer\r
+  @param  Callback               The function to call periodicaly when transfer is\r
+                                 ready\r
+  @param  Context                The context to the callback\r
+\r
+  @retval EFI_SUCCESS            New transfer is queued or old request is removed\r
+  @retval EFI_INVALID_PARAMETER  Some parameters are invalid\r
+  @retval Others                 Failed to queue the new request or remove the old\r
+                                 request\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoAsyncInterruptTransfer (\r
+  IN EFI_USB_IO_PROTOCOL              *This,\r
+  IN UINT8                            Endpoint,\r
+  IN BOOLEAN                          IsNewTransfer,\r
+  IN UINTN                            PollInterval,       OPTIONAL\r
+  IN UINTN                            DataLength,         OPTIONAL\r
+  IN EFI_ASYNC_USB_TRANSFER_CALLBACK  Callback,           OPTIONAL\r
+  IN VOID                             *Context            OPTIONAL\r
+  )\r
+{\r
+  USB_DEVICE              *Dev;\r
+  USB_INTERFACE           *UsbIf;\r
+  USB_ENDPOINT_DESC       *EpDesc;\r
+  EFI_TPL                 OldTpl;\r
+  UINT8                   Toggle;\r
+  EFI_STATUS              Status;\r
+\r
+  if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR (Endpoint) > 15)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);\r
+  UsbIf   = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev     = UsbIf->Device;\r
+\r
+  EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);\r
+\r
+  if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Toggle  = EpDesc->Toggle;\r
+  Status  = UsbHcAsyncInterruptTransfer (\r
+              Dev->Bus,\r
+              Dev->Address,\r
+              Endpoint,\r
+              Dev->Speed,\r
+              EpDesc->Desc.MaxPacketSize,\r
+              IsNewTransfer,\r
+              &Toggle,\r
+              PollInterval,\r
+              DataLength,\r
+              &Dev->Translator,\r
+              Callback,\r
+              Context\r
+              );\r
+\r
+  EpDesc->Toggle = Toggle;\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Execute a synchronous isochronous transfer\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  DeviceEndpoint         The device endpoint\r
+  @param  Data                   The data to transfer\r
+  @param  DataLength             The length of the data to transfer\r
+  @param  UsbStatus              The result of USB transfer\r
+\r
+  @retval EFI_UNSUPPORTED        Currently isochronous transfer isn't supported\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoIsochronousTransfer (\r
+  IN  EFI_USB_IO_PROTOCOL *This,\r
+  IN  UINT8               DeviceEndpoint,\r
+  IN  OUT VOID            *Data,\r
+  IN  UINTN               DataLength,\r
+  OUT UINT32              *Status\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+  Queue an asynchronous isochronous transfer\r
+\r
+  @param  This                   The USB_IO instance\r
+  @param  DeviceEndpoint         The device endpoint\r
+  @param  DataLength             The length of perodic data transfer\r
+  @param  IsochronousCallBack    The function to call periodicaly when transfer is\r
+                                 ready\r
+  @param  Context                The context to the callback\r
+\r
+  @retval EFI_UNSUPPORTED        Currently isochronous transfer isn't supported\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoAsyncIsochronousTransfer (\r
+  IN EFI_USB_IO_PROTOCOL              *This,\r
+  IN UINT8                            DeviceEndpoint,\r
+  IN OUT VOID                         *Data,\r
+  IN UINTN                            DataLength,\r
+  IN EFI_ASYNC_USB_TRANSFER_CALLBACK  IsochronousCallBack,\r
+  IN VOID                             *Context              OPTIONAL\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+  Retrieve the device descriptor of the device\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  Descriptor             The variable to receive the device descriptor\r
+\r
+  @retval EFI_SUCCESS            The device descriptor is returned\r
+  @retval EFI_INVALID_PARAMETER  The parameter is invalid\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetDeviceDescriptor (\r
+  IN  EFI_USB_IO_PROTOCOL       *This,\r
+  OUT EFI_USB_DEVICE_DESCRIPTOR *Descriptor\r
+  )\r
+{\r
+  USB_DEVICE              *Dev;\r
+  USB_INTERFACE           *UsbIf;\r
+  EFI_TPL                 OldTpl;\r
+\r
+  if (Descriptor == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev    = UsbIf->Device;\r
+\r
+  CopyMem (Descriptor, &Dev->DevDesc->Desc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Return the configuration descriptor of the current active configuration\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  Descriptor             The USB configuration descriptor\r
+\r
+  @retval EFI_SUCCESS            The active configuration descriptor is returned\r
+  @retval EFI_INVALID_PARAMETER  Some parameter is invalid\r
+  @retval EFI_NOT_FOUND          Currently no active configuration is selected.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetActiveConfigDescriptor (\r
+  IN  EFI_USB_IO_PROTOCOL       *This,\r
+  OUT EFI_USB_CONFIG_DESCRIPTOR *Descriptor\r
+  )\r
+{\r
+  USB_DEVICE              *Dev;\r
+  USB_INTERFACE           *UsbIf;\r
+  EFI_STATUS              Status;\r
+  EFI_TPL                 OldTpl;\r
+\r
+  if (Descriptor == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev    = UsbIf->Device;\r
+\r
+  if (Dev->ActiveConfig == NULL) {\r
+    Status = EFI_NOT_FOUND;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  CopyMem (Descriptor, &(Dev->ActiveConfig->Desc), sizeof (EFI_USB_CONFIG_DESCRIPTOR));\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Retrieve the active interface setting descriptor for this USB IO instance\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  Descriptor             The variable to receive active interface setting\r
+\r
+  @retval EFI_SUCCESS            The active interface setting is returned\r
+  @retval EFI_INVALID_PARAMETER  Some parameter is invalid\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetInterfaceDescriptor (\r
+  IN  EFI_USB_IO_PROTOCOL           *This,\r
+  OUT EFI_USB_INTERFACE_DESCRIPTOR  *Descriptor\r
+  )\r
+{\r
+  USB_INTERFACE           *UsbIf;\r
+  EFI_TPL                 OldTpl;\r
+\r
+  if (Descriptor == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
+  CopyMem (Descriptor, &(UsbIf->IfSetting->Desc), sizeof (EFI_USB_INTERFACE_DESCRIPTOR));\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Retrieve the endpoint descriptor from this interface setting\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  Index                  The index (start from zero) of the endpoint to\r
+                                 retrieve\r
+  @param  Descriptor             The variable to receive the descriptor\r
+\r
+  @retval EFI_SUCCESS            The endpoint descriptor is returned\r
+  @retval EFI_INVALID_PARAMETER  Some parameter is invalid\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetEndpointDescriptor (\r
+  IN  EFI_USB_IO_PROTOCOL         *This,\r
+  IN  UINT8                       Index,\r
+  OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor\r
+  )\r
+{\r
+  USB_INTERFACE           *UsbIf;\r
+  EFI_TPL                 OldTpl;\r
+\r
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
+\r
+  if ((Descriptor == NULL) || (Index > 15)) {\r
+    gBS->RestoreTPL (OldTpl);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {\r
+    gBS->RestoreTPL (OldTpl);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  CopyMem (\r
+    Descriptor,\r
+    &(UsbIf->IfSetting->Endpoints[Index]->Desc),\r
+    sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)\r
+    );\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Retrieve the supported language ID table from the device\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  LangIDTable            The table to return the language IDs\r
+  @param  TableSize              The number of supported languanges\r
+\r
+  @retval EFI_SUCCESS            The language ID is return\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetSupportedLanguages (\r
+  IN  EFI_USB_IO_PROTOCOL *This,\r
+  OUT UINT16              **LangIDTable,\r
+  OUT UINT16              *TableSize\r
+  )\r
+{\r
+  USB_DEVICE              *Dev;\r
+  USB_INTERFACE           *UsbIf;\r
+  EFI_TPL                 OldTpl;\r
+\r
+  OldTpl        = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf         = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev           = UsbIf->Device;\r
+\r
+  *LangIDTable  = Dev->LangId;\r
+  *TableSize    = Dev->TotalLangId;\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Retrieve an indexed string in the language of LangID\r
+\r
+  @param  This                   The USB IO instance\r
+  @param  LangID                 The language ID of the string to retrieve\r
+  @param  StringIndex            The index of the string\r
+  @param  String                 The variable to receive the string\r
+\r
+  @retval EFI_SUCCESS            The string is returned\r
+  @retval EFI_NOT_FOUND          No such string existed\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetStringDescriptor (\r
+  IN  EFI_USB_IO_PROTOCOL   *This,\r
+  IN  UINT16                LangID,\r
+  IN  UINT8                 StringIndex,\r
+  OUT CHAR16                **String\r
+  )\r
+{\r
+  USB_DEVICE                *Dev;\r
+  USB_INTERFACE             *UsbIf;\r
+  EFI_USB_STRING_DESCRIPTOR *StrDesc;\r
+  EFI_TPL                   OldTpl;\r
+  UINT8                     *Buf;\r
+  UINT8                     Index;\r
+  EFI_STATUS                Status;\r
+\r
+  if ((StringIndex == 0) || (LangID == 0)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev    = UsbIf->Device;\r
+\r
+  //\r
+  // Check whether language ID is supported\r
+  //\r
+  Status = EFI_NOT_FOUND;\r
+\r
+  for (Index = 0; Index < Dev->TotalLangId; Index++) {\r
+    if (Dev->LangId[Index] == LangID) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index == Dev->TotalLangId) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Retrieve the string descriptor then allocate a buffer\r
+  // to hold the string itself.\r
+  //\r
+  StrDesc = UsbGetOneString (Dev, StringIndex, LangID);\r
+\r
+  if (StrDesc == NULL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (StrDesc->Length <= 2) {\r
+    goto FREE_STR;\r
+  }\r
+\r
+  Buf = AllocateZeroPool (StrDesc->Length);\r
+\r
+  if (Buf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FREE_STR;\r
+  }\r
+\r
+  CopyMem (Buf, StrDesc->String, StrDesc->Length - 2);\r
+  *String = (CHAR16 *) Buf;\r
+  Status  = EFI_SUCCESS;\r
+\r
+FREE_STR:\r
+  gBS->FreePool (StrDesc);\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Reset the device, then if that succeeds, reconfigure the\r
+  device with its address and current active configuration.\r
+\r
+  @param  This                   The USB IO instance\r
+\r
+  @retval EFI_SUCCESS            The device is reset and configured\r
+  @retval Others                 Failed to reset the device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoPortReset (\r
+  IN EFI_USB_IO_PROTOCOL  *This\r
+  )\r
+{\r
+  USB_INTERFACE           *UsbIf;\r
+  USB_INTERFACE           *HubIf;\r
+  USB_DEVICE              *Dev;\r
+  UINT8                   Address;\r
+  EFI_TPL                 OldTpl;\r
+  EFI_STATUS              Status;\r
+\r
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
+  Dev    = UsbIf->Device;\r
+\r
+  if (UsbIf->IsHub == TRUE) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  HubIf  = Dev->ParentIf;\r
+  Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub  %d, %r \n",\r
+                Dev->ParentPort, Dev->ParentAddr, Status));\r
+\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Reset the device to its current address. The device now has a\r
+  // address of ZERO, so need to set Dev->Address to zero first for\r
+  // host to communicate with the device\r
+  //\r
+  Address       = Dev->Address;\r
+  Dev->Address  = 0;\r
+  Status        = UsbSetAddress (Dev, Address);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",\r
+                Address, Status));\r
+\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Dev->Address  = Address;\r
+\r
+  //\r
+  // Reset the current active configure, after this device\r
+  // is in CONFIGURED state.\r
+  //\r
+  if (Dev->ActiveConfig != NULL) {\r
+    Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",\r
+                  Address, Status));\r
+    }\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Install Usb Bus Protocol on host controller, and start the Usb bus\r
+\r
+  @param This                    The USB bus driver binding instance\r
+  @param Controller              The controller to check\r
+  @param RemainingDevicePath     The remaining device patch\r
+\r
+  @retval EFI_SUCCESS            The controller is controlled by the usb bus\r
+  @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb bus\r
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusBuildProtocol (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  USB_BUS                 *UsbBus;\r
+  USB_DEVICE              *RootHub;\r
+  USB_INTERFACE           *RootIf;\r
+  EFI_STATUS              Status;\r
+  EFI_STATUS              Status2;\r
+\r
+  UsbBus = AllocateZeroPool (sizeof (USB_BUS));\r
+\r
+  if (UsbBus == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  UsbBus->Signature   = USB_BUS_SIGNATURE;\r
+  UsbBus->HostHandle  = Controller;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &UsbBus->DevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));\r
+\r
+    gBS->FreePool (UsbBus);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).\r
+  // This is for backward compatbility with EFI 1.x. In UEFI\r
+  // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2\r
+  // and USB_HC because EHCI driver will install both protocols\r
+  // (for the same reason). If we don't consume both of them,\r
+  // the unconsumed one may be opened by others.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiUsb2HcProtocolGuid,\r
+                  (VOID **) &(UsbBus->Usb2Hc),\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  Status2 = gBS->OpenProtocol (\r
+                   Controller,\r
+                   &gEfiUsbHcProtocolGuid,\r
+                   (VOID **) &(UsbBus->UsbHc),\r
+                   This->DriverBindingHandle,\r
+                   Controller,\r
+                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                   );\r
+\r
+  if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {\r
+    DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));\r
+\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto CLOSE_HC;\r
+  }\r
+\r
+  UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
+  UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
+\r
+  //\r
+  // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Controller,\r
+                  &mUsbBusProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &UsbBus->BusId\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));\r
+    goto CLOSE_HC;\r
+  }\r
+\r
+  //\r
+  // Initial the wanted child device path list, and add first RemainingDevicePath\r
+  //\r
+  InitializeListHead (&UsbBus->WantedUsbIoDPList);\r
+  Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);\r
+  ASSERT (!EFI_ERROR (Status));\r
+  //\r
+  // Create a fake usb device for root hub\r
+  //\r
+  RootHub = AllocateZeroPool (sizeof (USB_DEVICE));\r
+\r
+  if (RootHub == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto UNINSTALL_USBBUS;\r
+  }\r
+\r
+  RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
+\r
+  if (RootIf == NULL) {\r
+    gBS->FreePool (RootHub);\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FREE_ROOTHUB;\r
+  }\r
+\r
+  RootHub->Bus            = UsbBus;\r
+  RootHub->NumOfInterface = 1;\r
+  RootHub->Interfaces[0]  = RootIf;\r
+  RootIf->Signature       = USB_INTERFACE_SIGNATURE;\r
+  RootIf->Device          = RootHub;\r
+  RootIf->DevicePath      = UsbBus->DevicePath;\r
+\r
+  Status                  = mUsbRootHubApi.Init (RootIf);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));\r
+    goto FREE_ROOTHUB;\r
+  }\r
+\r
+  UsbBus->Devices[0] = RootHub;\r
+\r
+  DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));\r
+  return EFI_SUCCESS;\r
+\r
+FREE_ROOTHUB:\r
+  if (RootIf != NULL) {\r
+    gBS->FreePool (RootIf);\r
+  }\r
+  if (RootHub != NULL) {\r
+    gBS->FreePool (RootHub);\r
+  }\r
+\r
+UNINSTALL_USBBUS:\r
+  gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);\r
+\r
+CLOSE_HC:\r
+  if (UsbBus->Usb2Hc != NULL) {\r
+    gBS->CloseProtocol (\r
+          Controller,\r
+          &gEfiUsb2HcProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          Controller\r
+          );\r
+  }\r
+  if (UsbBus->UsbHc != NULL) {\r
+    gBS->CloseProtocol (\r
+          Controller,\r
+          &gEfiUsbHcProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          Controller\r
+          );\r
+  }\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiDevicePathProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+  gBS->FreePool (UsbBus);\r
+\r
+  DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));\r
+  return Status;\r
+}\r
+\r
+EFI_USB_IO_PROTOCOL mUsbIoProtocol = {\r
+  UsbIoControlTransfer,\r
+  UsbIoBulkTransfer,\r
+  UsbIoAsyncInterruptTransfer,\r
+  UsbIoSyncInterruptTransfer,\r
+  UsbIoIsochronousTransfer,\r
+  UsbIoAsyncIsochronousTransfer,\r
+  UsbIoGetDeviceDescriptor,\r
+  UsbIoGetActiveConfigDescriptor,\r
+  UsbIoGetInterfaceDescriptor,\r
+  UsbIoGetEndpointDescriptor,\r
+  UsbIoGetStringDescriptor,\r
+  UsbIoGetSupportedLanguages,\r
+  UsbIoPortReset\r
+};\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusDriverEntryPoint (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The USB bus driver entry pointer\r
+\r
+Arguments:\r
+\r
+  ImageHandle - The driver image handle\r
+  SystemTable - The system table\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - The component name protocol is installed\r
+  Others      - Failed to init the usb driver\r
+\r
+--*/\r
+{\r
+  return EfiLibInstallDriverBindingComponentName2 (\r
+           ImageHandle,\r
+           SystemTable,\r
+           &mUsbBusDriverBinding,\r
+           ImageHandle,\r
+           &mUsbBusComponentName,\r
+           &mUsbBusComponentName2\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Check whether USB bus driver support this device\r
+\r
+  @param  This                   The USB bus driver binding protocol\r
+  @param  Controller             The controller handle to test againist\r
+  @param  RemainingDevicePath    The remaining device path\r
+\r
+  @retval EFI_SUCCESS            The bus supports this controller.\r
+  @retval EFI_UNSUPPORTED        This device isn't supported\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusControllerDriverSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_DEV_PATH_PTR          DevicePathNode;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
+  EFI_USB2_HC_PROTOCOL      *Usb2Hc;\r
+  EFI_USB_HC_PROTOCOL       *UsbHc;\r
+  EFI_STATUS                Status;\r
+\r
+  //\r
+  // Check whether device path is valid\r
+  //\r
+  if (RemainingDevicePath != NULL) {\r
+    DevicePathNode.DevPath = RemainingDevicePath;\r
+\r
+    if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||\r
+        (DevicePathNode.DevPath->SubType != MSG_USB_DP &&\r
+         DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP\r
+         && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP\r
+         )) {\r
+\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiDevicePathProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  //\r
+  // Check whether USB_HC2 protocol is installed\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiUsb2HcProtocolGuid,\r
+                  (VOID **) &Usb2Hc,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    gBS->CloseProtocol (\r
+          Controller,\r
+          &gEfiUsb2HcProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          Controller\r
+          );\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // If failed to open USB_HC2, fall back to USB_HC\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiUsbHcProtocolGuid,\r
+                  (VOID **) &UsbHc,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    gBS->CloseProtocol (\r
+          Controller,\r
+          &gEfiUsbHcProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          Controller\r
+          );\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start to process the controller\r
+\r
+  @param  This                   The USB bus driver binding instance\r
+  @param  Controller             The controller to check\r
+  @param  RemainingDevicePath    The remaining device patch\r
+\r
+  @retval EFI_SUCCESS            The controller is controlled by the usb bus\r
+  @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb\r
+                                 bus\r
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusControllerDriverStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_USB_BUS_PROTOCOL          *UsbBusId;\r
+  EFI_STATUS                    Status;\r
+\r
+  //\r
+  // Locate the USB bus protocol, if it is found, USB bus\r
+  // is already started on this controller.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &mUsbBusProtocolGuid,\r
+                  (VOID **) &UsbBusId,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // If first start, build the bus execute enviorment and install bus protocol\r
+    //\r
+    Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    //\r
+    // Try get the Usb Bus protocol interface again\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &mUsbBusProtocolGuid,\r
+                    (VOID **) &UsbBusId,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  } else {\r
+    //\r
+    // USB Bus driver need to control the recursive connect policy of the bus, only those wanted\r
+    // usb child device will be recursively connected.\r
+    // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.\r
+    // All wanted usb child devices will be remembered by the usb bus driver itself.\r
+    // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.\r
+    //\r
+    // Save the passed in RemainingDevicePath this time\r
+    //\r
+    Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);\r
+    ASSERT (!EFI_ERROR (Status));\r
+    //\r
+    // Ensure all wanted child usb devices are fully recursively connected\r
+    //\r
+    Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Stop handle the controller by this USB bus driver\r
+\r
+  @param  This                   The USB bus driver binding protocol\r
+  @param  Controller             The controller to release\r
+  @param  NumberOfChildren       The child of USB bus that opened controller\r
+                                 BY_CHILD\r
+  @param  ChildHandleBuffer      The array of child handle\r
+\r
+  @retval EFI_SUCCESS            The controller or children are stopped\r
+  @retval EFI_DEVICE_ERROR       Failed to stop the driver\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusControllerDriverStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  USB_BUS               *Bus;\r
+  USB_DEVICE            *RootHub;\r
+  USB_DEVICE            *UsbDev;\r
+  USB_INTERFACE         *RootIf;\r
+  USB_INTERFACE         *UsbIf;\r
+  EFI_USB_BUS_PROTOCOL  *BusId;\r
+  EFI_USB_IO_PROTOCOL   *UsbIo;\r
+  EFI_TPL               OldTpl;\r
+  UINTN                 Index;\r
+  EFI_STATUS            Status;\r
+\r
+  Status  = EFI_SUCCESS;\r
+\r
+  if (NumberOfChildren > 0) {\r
+    //\r
+    // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
+    //\r
+    OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+    for (Index = 0; Index < NumberOfChildren; Index++) {\r
+      Status = gBS->OpenProtocol (\r
+                      ChildHandleBuffer[Index],\r
+                      &gEfiUsbIoProtocolGuid,\r
+                      (VOID **) &UsbIo,\r
+                      This->DriverBindingHandle,\r
+                      Controller,\r
+                      EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                      );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // It is possible that the child has already been released:\r
+        // 1. For combo device, free one device will release others.\r
+        // 2. If a hub is released, all devices on its down facing\r
+        //    ports are released also.\r
+        //\r
+        continue;\r
+      }\r
+\r
+      UsbIf   = USB_INTERFACE_FROM_USBIO (UsbIo);\r
+      UsbDev  = UsbIf->Device;\r
+\r
+      UsbRemoveDevice (UsbDev);\r
+    }\r
+\r
+    gBS->RestoreTPL (OldTpl);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %x\n", Controller));\r
+\r
+  //\r
+  // Locate USB_BUS for the current host controller\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &mUsbBusProtocolGuid,\r
+                  (VOID **) &BusId,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Bus = USB_BUS_FROM_THIS (BusId);\r
+\r
+  //\r
+  // Stop the root hub, then free all the devices\r
+  //\r
+  // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
+  //\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
+  UsbHcSetState (Bus, EfiUsbHcStateHalt);\r
+\r
+  RootHub = Bus->Devices[0];\r
+  RootIf  = RootHub->Interfaces[0];\r
+\r
+  mUsbRootHubApi.Release (RootIf);\r
+\r
+  for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
+    if (Bus->Devices[Index] != NULL) {\r
+      UsbRemoveDevice (Bus->Devices[Index]);\r
+    }\r
+  }\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  gBS->FreePool   (RootIf);\r
+  gBS->FreePool   (RootHub);\r
+  Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
+  ASSERT (!EFI_ERROR (Status));\r
+\r
+  //\r
+  // Uninstall the bus identifier and close USB_HC/USB2_HC protocols\r
+  //\r
+  gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);\r
+\r
+  if (Bus->Usb2Hc != NULL) {\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiUsb2HcProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+  }\r
+\r
+  if (Bus->UsbHc != NULL) {\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiUsbHcProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiDevicePathProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  gBS->FreePool (Bus);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {\r
+  UsbBusControllerDriverSupported,\r
+  UsbBusControllerDriverStart,\r
+  UsbBusControllerDriverStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
deleted file mode 100644 (file)
index 332871a..0000000
+++ /dev/null
@@ -1,1470 +0,0 @@
-/** @file\r
-\r
-Copyright (c) 2004 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The 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
-  Module Name:\r
-\r
-    UsbBus.c\r
-\r
-  Abstract:\r
-\r
-    Usb Bus Driver Binding and Bus IO Protocol\r
-\r
-  Revision History\r
-\r
-\r
-**/\r
-\r
-#include "UsbBus.h"\r
-\r
-//\r
-// USB_BUS_PROTOCOL is only used to locate USB_BUS\r
-//\r
-EFI_GUID  mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;\r
-\r
-\r
-/**\r
-  USB_IO function to execute a control transfer. This\r
-  function will execute the USB transfer. If transfer\r
-  successes, it will sync the internal state of USB bus\r
-  with device state.\r
-\r
-  @param  This                   The USB_IO instance\r
-  @param  Request                The control transfer request\r
-  @param  Direction              Direction for data stage\r
-  @param  Timeout                The time to wait before timeout\r
-  @param  Data                   The buffer holding the data\r
-  @param  DataLength             Then length of the data\r
-  @param  UsbStatus              USB result\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid\r
-  @retval EFI_SUCCESS            The control transfer succeded.\r
-  @retval Others                 Failed to execute the transfer\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoControlTransfer (\r
-  IN  EFI_USB_IO_PROTOCOL     *This,\r
-  IN  EFI_USB_DEVICE_REQUEST  *Request,\r
-  IN  EFI_USB_DATA_DIRECTION  Direction,\r
-  IN  UINT32                  Timeout,\r
-  IN  OUT VOID                *Data,      OPTIONAL\r
-  IN  UINTN                   DataLength, OPTIONAL\r
-  OUT UINT32                  *UsbStatus\r
-  )\r
-{\r
-  USB_DEVICE              *Dev;\r
-  USB_INTERFACE           *UsbIf;\r
-  USB_ENDPOINT_DESC       *EpDesc;\r
-  EFI_TPL                 OldTpl;\r
-  EFI_STATUS              Status;\r
-\r
-  if (UsbStatus == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev    = UsbIf->Device;\r
-\r
-  Status = UsbHcControlTransfer (\r
-             Dev->Bus,\r
-             Dev->Address,\r
-             Dev->Speed,\r
-             Dev->MaxPacket0,\r
-             Request,\r
-             Direction,\r
-             Data,\r
-             &DataLength,\r
-             (UINTN) Timeout,\r
-             &Dev->Translator,\r
-             UsbStatus\r
-             );\r
-\r
-  if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
-    //\r
-    // Clear TT buffer when CTRL/BULK split transaction failes\r
-    // Clear the TRANSLATOR TT buffer, not parent's buffer\r
-    //\r
-    if (Dev->Translator.TranslatorHubAddress != 0) {\r
-      UsbHubCtrlClearTTBuffer (\r
-        Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
-        Dev->Translator.TranslatorPortNumber,\r
-        Dev->Address,\r
-        0,\r
-        USB_ENDPOINT_CONTROL\r
-        );\r
-    }\r
-\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Some control transfer will change the device's internal\r
-  // status, such as Set_Configuration and Set_Interface.\r
-  // We must synchronize the bus driver's status with that in\r
-  // device. We ignore the Set_Descriptor request because it's\r
-  // hardly used by any device, especially in pre-boot environment\r
-  //\r
-\r
-  //\r
-  // Reset the endpoint toggle when endpoint stall is cleared\r
-  //\r
-  if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&\r
-      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
-                                                 USB_TARGET_ENDPOINT)) &&\r
-      (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {\r
-\r
-    EpDesc = UsbGetEndpointDesc (UsbIf, (UINT8) Request->Index);\r
-\r
-    if (EpDesc != NULL) {\r
-      EpDesc->Toggle = 0;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Select a new configuration. This is a dangerous action. Upper driver\r
-  // should stop use its current UsbIo after calling this driver. The old\r
-  // UsbIo will be uninstalled and new UsbIo be installed. We can't use\r
-  // ReinstallProtocol since interfaces in different configuration may be\r
-  // completely irrellvant.\r
-  //\r
-  if ((Request->Request == USB_REQ_SET_CONFIG) &&\r
-      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
-                                                 USB_TARGET_DEVICE))) {\r
-    //\r
-    // Don't re-create the USB interfaces if configuration isn't changed.\r
-    //\r
-    if ((Dev->ActiveConfig != NULL) &&\r
-        (Request->Value == Dev->ActiveConfig->Desc.ConfigurationValue)) {\r
-\r
-      goto ON_EXIT;\r
-    }\r
-    DEBUG ((EFI_D_INFO, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));\r
-\r
-    if (Dev->ActiveConfig != NULL) {\r
-      UsbRemoveConfig (Dev);\r
-    }\r
-\r
-    if (Request->Value != 0) {\r
-      Status = UsbSelectConfig (Dev, (UINT8) Request->Value);\r
-    }\r
-\r
-    //\r
-    // Exit now, Old USB_IO is invalid now\r
-    //\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // A new alternative setting is selected for the interface.\r
-  // No need to reinstall UsbIo in this case because only\r
-  // underlying communication endpoints are changed. Functionality\r
-  // should remains the same.\r
-  //\r
-  if ((Request->Request     == USB_REQ_SET_INTERFACE) &&\r
-      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
-                                                 USB_TARGET_INTERFACE)) &&\r
-      (Request->Index       == UsbIf->IfSetting->Desc.InterfaceNumber)) {\r
-\r
-    Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);\r
-\r
-    if (!EFI_ERROR (Status)) {\r
-      UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];\r
-    }\r
-  }\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Execute a bulk transfer to the device endpoint\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  Endpoint               The device endpoint\r
-  @param  Data                   The data to transfer\r
-  @param  DataLength             The length of the data to transfer\r
-  @param  Timeout                Time to wait before timeout\r
-  @param  UsbStatus              The result of USB transfer\r
-\r
-  @retval EFI_SUCCESS            The bulk transfer is OK\r
-  @retval EFI_INVALID_PARAMETER  Some parameters are invalid\r
-  @retval Others                 Failed to execute transfer, reason returned in\r
-                                 UsbStatus\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoBulkTransfer (\r
-  IN  EFI_USB_IO_PROTOCOL *This,\r
-  IN  UINT8               Endpoint,\r
-  IN  OUT VOID            *Data,\r
-  IN  OUT UINTN           *DataLength,\r
-  IN  UINTN               Timeout,\r
-  OUT UINT32              *UsbStatus\r
-  )\r
-{\r
-  USB_DEVICE              *Dev;\r
-  USB_INTERFACE           *UsbIf;\r
-  USB_ENDPOINT_DESC       *EpDesc;\r
-  UINT8                   BufNum;\r
-  UINT8                   Toggle;\r
-  EFI_TPL                 OldTpl;\r
-  EFI_STATUS              Status;\r
-\r
-  if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
-      (UsbStatus == NULL)) {\r
-\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf   = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev     = UsbIf->Device;\r
-\r
-  EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);\r
-\r
-  if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_BULK)) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  BufNum  = 1;\r
-  Toggle  = EpDesc->Toggle;\r
-  Status  = UsbHcBulkTransfer (\r
-              Dev->Bus,\r
-              Dev->Address,\r
-              Endpoint,\r
-              Dev->Speed,\r
-              EpDesc->Desc.MaxPacketSize,\r
-              BufNum,\r
-              &Data,\r
-              DataLength,\r
-              &Toggle,\r
-              Timeout,\r
-              &Dev->Translator,\r
-              UsbStatus\r
-              );\r
-\r
-  EpDesc->Toggle = Toggle;\r
-\r
-  if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
-    //\r
-    // Clear TT buffer when CTRL/BULK split transaction failes.\r
-    // Clear the TRANSLATOR TT buffer, not parent's buffer\r
-    //\r
-    if (Dev->Translator.TranslatorHubAddress != 0) {\r
-      UsbHubCtrlClearTTBuffer (\r
-        Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
-        Dev->Translator.TranslatorPortNumber,\r
-        Dev->Address,\r
-        0,\r
-        USB_ENDPOINT_BULK\r
-        );\r
-    }\r
-  }\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Execute a synchronous interrupt transfer\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  Endpoint               The device endpoint\r
-  @param  Data                   The data to transfer\r
-  @param  DataLength             The length of the data to transfer\r
-  @param  Timeout                Time to wait before timeout\r
-  @param  UsbStatus              The result of USB transfer\r
-\r
-  @retval EFI_SUCCESS            The synchronous interrupt transfer is OK\r
-  @retval EFI_INVALID_PARAMETER  Some parameters are invalid\r
-  @retval Others                 Failed to execute transfer, reason returned in\r
-                                 UsbStatus\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoSyncInterruptTransfer (\r
-  IN  EFI_USB_IO_PROTOCOL *This,\r
-  IN  UINT8               Endpoint,\r
-  IN  OUT VOID            *Data,\r
-  IN  OUT UINTN           *DataLength,\r
-  IN  UINTN               Timeout,\r
-  OUT UINT32              *UsbStatus\r
-  )\r
-{\r
-  USB_DEVICE              *Dev;\r
-  USB_INTERFACE           *UsbIf;\r
-  USB_ENDPOINT_DESC       *EpDesc;\r
-  EFI_TPL                 OldTpl;\r
-  UINT8                   Toggle;\r
-  EFI_STATUS              Status;\r
-\r
-  if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
-      (UsbStatus == NULL)) {\r
-\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf   = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev     = UsbIf->Device;\r
-\r
-  EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);\r
-\r
-  if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Toggle = EpDesc->Toggle;\r
-  Status = UsbHcSyncInterruptTransfer (\r
-             Dev->Bus,\r
-             Dev->Address,\r
-             Endpoint,\r
-             Dev->Speed,\r
-             EpDesc->Desc.MaxPacketSize,\r
-             Data,\r
-             DataLength,\r
-             &Toggle,\r
-             Timeout,\r
-             &Dev->Translator,\r
-             UsbStatus\r
-             );\r
-\r
-  EpDesc->Toggle = Toggle;\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Queue a new asynchronous interrupt transfer, or remove the old\r
-  request if (IsNewTransfer == FALSE)\r
-\r
-  @param  This                   The USB_IO instance\r
-  @param  Endpoint               The device endpoint\r
-  @param  IsNewTransfer          Whether this is a new request, if it's old, remove\r
-                                 the request\r
-  @param  PollInterval           The interval to poll the transfer result, (in ms)\r
-  @param  DataLength             The length of perodic data transfer\r
-  @param  Callback               The function to call periodicaly when transfer is\r
-                                 ready\r
-  @param  Context                The context to the callback\r
-\r
-  @retval EFI_SUCCESS            New transfer is queued or old request is removed\r
-  @retval EFI_INVALID_PARAMETER  Some parameters are invalid\r
-  @retval Others                 Failed to queue the new request or remove the old\r
-                                 request\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoAsyncInterruptTransfer (\r
-  IN EFI_USB_IO_PROTOCOL              *This,\r
-  IN UINT8                            Endpoint,\r
-  IN BOOLEAN                          IsNewTransfer,\r
-  IN UINTN                            PollInterval,       OPTIONAL\r
-  IN UINTN                            DataLength,         OPTIONAL\r
-  IN EFI_ASYNC_USB_TRANSFER_CALLBACK  Callback,           OPTIONAL\r
-  IN VOID                             *Context            OPTIONAL\r
-  )\r
-{\r
-  USB_DEVICE              *Dev;\r
-  USB_INTERFACE           *UsbIf;\r
-  USB_ENDPOINT_DESC       *EpDesc;\r
-  EFI_TPL                 OldTpl;\r
-  UINT8                   Toggle;\r
-  EFI_STATUS              Status;\r
-\r
-  if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR (Endpoint) > 15)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);\r
-  UsbIf   = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev     = UsbIf->Device;\r
-\r
-  EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);\r
-\r
-  if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Toggle  = EpDesc->Toggle;\r
-  Status  = UsbHcAsyncInterruptTransfer (\r
-              Dev->Bus,\r
-              Dev->Address,\r
-              Endpoint,\r
-              Dev->Speed,\r
-              EpDesc->Desc.MaxPacketSize,\r
-              IsNewTransfer,\r
-              &Toggle,\r
-              PollInterval,\r
-              DataLength,\r
-              &Dev->Translator,\r
-              Callback,\r
-              Context\r
-              );\r
-\r
-  EpDesc->Toggle = Toggle;\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Execute a synchronous isochronous transfer\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  DeviceEndpoint         The device endpoint\r
-  @param  Data                   The data to transfer\r
-  @param  DataLength             The length of the data to transfer\r
-  @param  UsbStatus              The result of USB transfer\r
-\r
-  @retval EFI_UNSUPPORTED        Currently isochronous transfer isn't supported\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoIsochronousTransfer (\r
-  IN  EFI_USB_IO_PROTOCOL *This,\r
-  IN  UINT8               DeviceEndpoint,\r
-  IN  OUT VOID            *Data,\r
-  IN  UINTN               DataLength,\r
-  OUT UINT32              *Status\r
-  )\r
-{\r
-  return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-/**\r
-  Queue an asynchronous isochronous transfer\r
-\r
-  @param  This                   The USB_IO instance\r
-  @param  DeviceEndpoint         The device endpoint\r
-  @param  DataLength             The length of perodic data transfer\r
-  @param  IsochronousCallBack    The function to call periodicaly when transfer is\r
-                                 ready\r
-  @param  Context                The context to the callback\r
-\r
-  @retval EFI_UNSUPPORTED        Currently isochronous transfer isn't supported\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoAsyncIsochronousTransfer (\r
-  IN EFI_USB_IO_PROTOCOL              *This,\r
-  IN UINT8                            DeviceEndpoint,\r
-  IN OUT VOID                         *Data,\r
-  IN UINTN                            DataLength,\r
-  IN EFI_ASYNC_USB_TRANSFER_CALLBACK  IsochronousCallBack,\r
-  IN VOID                             *Context              OPTIONAL\r
-  )\r
-{\r
-  return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-/**\r
-  Retrieve the device descriptor of the device\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  Descriptor             The variable to receive the device descriptor\r
-\r
-  @retval EFI_SUCCESS            The device descriptor is returned\r
-  @retval EFI_INVALID_PARAMETER  The parameter is invalid\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetDeviceDescriptor (\r
-  IN  EFI_USB_IO_PROTOCOL       *This,\r
-  OUT EFI_USB_DEVICE_DESCRIPTOR *Descriptor\r
-  )\r
-{\r
-  USB_DEVICE              *Dev;\r
-  USB_INTERFACE           *UsbIf;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  if (Descriptor == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev    = UsbIf->Device;\r
-\r
-  CopyMem (Descriptor, &Dev->DevDesc->Desc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Return the configuration descriptor of the current active configuration\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  Descriptor             The USB configuration descriptor\r
-\r
-  @retval EFI_SUCCESS            The active configuration descriptor is returned\r
-  @retval EFI_INVALID_PARAMETER  Some parameter is invalid\r
-  @retval EFI_NOT_FOUND          Currently no active configuration is selected.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetActiveConfigDescriptor (\r
-  IN  EFI_USB_IO_PROTOCOL       *This,\r
-  OUT EFI_USB_CONFIG_DESCRIPTOR *Descriptor\r
-  )\r
-{\r
-  USB_DEVICE              *Dev;\r
-  USB_INTERFACE           *UsbIf;\r
-  EFI_STATUS              Status;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  if (Descriptor == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Status = EFI_SUCCESS;\r
-  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev    = UsbIf->Device;\r
-\r
-  if (Dev->ActiveConfig == NULL) {\r
-    Status = EFI_NOT_FOUND;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  CopyMem (Descriptor, &(Dev->ActiveConfig->Desc), sizeof (EFI_USB_CONFIG_DESCRIPTOR));\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Retrieve the active interface setting descriptor for this USB IO instance\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  Descriptor             The variable to receive active interface setting\r
-\r
-  @retval EFI_SUCCESS            The active interface setting is returned\r
-  @retval EFI_INVALID_PARAMETER  Some parameter is invalid\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetInterfaceDescriptor (\r
-  IN  EFI_USB_IO_PROTOCOL           *This,\r
-  OUT EFI_USB_INTERFACE_DESCRIPTOR  *Descriptor\r
-  )\r
-{\r
-  USB_INTERFACE           *UsbIf;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  if (Descriptor == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
-  CopyMem (Descriptor, &(UsbIf->IfSetting->Desc), sizeof (EFI_USB_INTERFACE_DESCRIPTOR));\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Retrieve the endpoint descriptor from this interface setting\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  Index                  The index (start from zero) of the endpoint to\r
-                                 retrieve\r
-  @param  Descriptor             The variable to receive the descriptor\r
-\r
-  @retval EFI_SUCCESS            The endpoint descriptor is returned\r
-  @retval EFI_INVALID_PARAMETER  Some parameter is invalid\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetEndpointDescriptor (\r
-  IN  EFI_USB_IO_PROTOCOL         *This,\r
-  IN  UINT8                       Index,\r
-  OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor\r
-  )\r
-{\r
-  USB_INTERFACE           *UsbIf;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
-\r
-  if ((Descriptor == NULL) || (Index > 15)) {\r
-    gBS->RestoreTPL (OldTpl);\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {\r
-    gBS->RestoreTPL (OldTpl);\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  CopyMem (\r
-    Descriptor,\r
-    &(UsbIf->IfSetting->Endpoints[Index]->Desc),\r
-    sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)\r
-    );\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Retrieve the supported language ID table from the device\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  LangIDTable            The table to return the language IDs\r
-  @param  TableSize              The number of supported languanges\r
-\r
-  @retval EFI_SUCCESS            The language ID is return\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetSupportedLanguages (\r
-  IN  EFI_USB_IO_PROTOCOL *This,\r
-  OUT UINT16              **LangIDTable,\r
-  OUT UINT16              *TableSize\r
-  )\r
-{\r
-  USB_DEVICE              *Dev;\r
-  USB_INTERFACE           *UsbIf;\r
-  EFI_TPL                 OldTpl;\r
-\r
-  OldTpl        = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf         = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev           = UsbIf->Device;\r
-\r
-  *LangIDTable  = Dev->LangId;\r
-  *TableSize    = Dev->TotalLangId;\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Retrieve an indexed string in the language of LangID\r
-\r
-  @param  This                   The USB IO instance\r
-  @param  LangID                 The language ID of the string to retrieve\r
-  @param  StringIndex            The index of the string\r
-  @param  String                 The variable to receive the string\r
-\r
-  @retval EFI_SUCCESS            The string is returned\r
-  @retval EFI_NOT_FOUND          No such string existed\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetStringDescriptor (\r
-  IN  EFI_USB_IO_PROTOCOL   *This,\r
-  IN  UINT16                LangID,\r
-  IN  UINT8                 StringIndex,\r
-  OUT CHAR16                **String\r
-  )\r
-{\r
-  USB_DEVICE                *Dev;\r
-  USB_INTERFACE             *UsbIf;\r
-  EFI_USB_STRING_DESCRIPTOR *StrDesc;\r
-  EFI_TPL                   OldTpl;\r
-  UINT8                     *Buf;\r
-  UINT8                     Index;\r
-  EFI_STATUS                Status;\r
-\r
-  if ((StringIndex == 0) || (LangID == 0)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev    = UsbIf->Device;\r
-\r
-  //\r
-  // Check whether language ID is supported\r
-  //\r
-  Status = EFI_NOT_FOUND;\r
-\r
-  for (Index = 0; Index < Dev->TotalLangId; Index++) {\r
-    if (Dev->LangId[Index] == LangID) {\r
-      break;\r
-    }\r
-  }\r
-\r
-  if (Index == Dev->TotalLangId) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Retrieve the string descriptor then allocate a buffer\r
-  // to hold the string itself.\r
-  //\r
-  StrDesc = UsbGetOneString (Dev, StringIndex, LangID);\r
-\r
-  if (StrDesc == NULL) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (StrDesc->Length <= 2) {\r
-    goto FREE_STR;\r
-  }\r
-\r
-  Buf = AllocateZeroPool (StrDesc->Length);\r
-\r
-  if (Buf == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto FREE_STR;\r
-  }\r
-\r
-  CopyMem (Buf, StrDesc->String, StrDesc->Length - 2);\r
-  *String = (CHAR16 *) Buf;\r
-  Status  = EFI_SUCCESS;\r
-\r
-FREE_STR:\r
-  gBS->FreePool (StrDesc);\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Reset the device, then if that succeeds, reconfigure the\r
-  device with its address and current active configuration.\r
-\r
-  @param  This                   The USB IO instance\r
-\r
-  @retval EFI_SUCCESS            The device is reset and configured\r
-  @retval Others                 Failed to reset the device\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoPortReset (\r
-  IN EFI_USB_IO_PROTOCOL  *This\r
-  )\r
-{\r
-  USB_INTERFACE           *UsbIf;\r
-  USB_INTERFACE           *HubIf;\r
-  USB_DEVICE              *Dev;\r
-  UINT8                   Address;\r
-  EFI_TPL                 OldTpl;\r
-  EFI_STATUS              Status;\r
-\r
-  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
-  UsbIf  = USB_INTERFACE_FROM_USBIO (This);\r
-  Dev    = UsbIf->Device;\r
-\r
-  if (UsbIf->IsHub == TRUE) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  HubIf  = Dev->ParentIf;\r
-  Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub  %d, %r \n",\r
-                Dev->ParentPort, Dev->ParentAddr, Status));\r
-\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Reset the device to its current address. The device now has a\r
-  // address of ZERO, so need to set Dev->Address to zero first for\r
-  // host to communicate with the device\r
-  //\r
-  Address       = Dev->Address;\r
-  Dev->Address  = 0;\r
-  Status        = UsbSetAddress (Dev, Address);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",\r
-                Address, Status));\r
-\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Dev->Address  = Address;\r
-\r
-  //\r
-  // Reset the current active configure, after this device\r
-  // is in CONFIGURED state.\r
-  //\r
-  if (Dev->ActiveConfig != NULL) {\r
-    Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",\r
-                  Address, Status));\r
-    }\r
-  }\r
-\r
-ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Install Usb Bus Protocol on host controller, and start the Usb bus\r
-\r
-  @param This                    The USB bus driver binding instance\r
-  @param Controller              The controller to check\r
-  @param RemainingDevicePath     The remaining device patch\r
-\r
-  @retval EFI_SUCCESS            The controller is controlled by the usb bus\r
-  @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb bus\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusBuildProtocol (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
-  IN EFI_HANDLE                   Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
-  )\r
-{\r
-  USB_BUS                 *UsbBus;\r
-  USB_DEVICE              *RootHub;\r
-  USB_INTERFACE           *RootIf;\r
-  EFI_STATUS              Status;\r
-  EFI_STATUS              Status2;\r
-\r
-  UsbBus = AllocateZeroPool (sizeof (USB_BUS));\r
-\r
-  if (UsbBus == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  UsbBus->Signature   = USB_BUS_SIGNATURE;\r
-  UsbBus->HostHandle  = Controller;\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &UsbBus->DevicePath,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));\r
-\r
-    gBS->FreePool (UsbBus);\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).\r
-  // This is for backward compatbility with EFI 1.x. In UEFI\r
-  // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2\r
-  // and USB_HC because EHCI driver will install both protocols\r
-  // (for the same reason). If we don't consume both of them,\r
-  // the unconsumed one may be opened by others.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiUsb2HcProtocolGuid,\r
-                  (VOID **) &(UsbBus->Usb2Hc),\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  Status2 = gBS->OpenProtocol (\r
-                   Controller,\r
-                   &gEfiUsbHcProtocolGuid,\r
-                   (VOID **) &(UsbBus->UsbHc),\r
-                   This->DriverBindingHandle,\r
-                   Controller,\r
-                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                   );\r
-\r
-  if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {\r
-    DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));\r
-\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto CLOSE_HC;\r
-  }\r
-\r
-  UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
-  UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
-\r
-  //\r
-  // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.\r
-  //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &Controller,\r
-                  &mUsbBusProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &UsbBus->BusId\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));\r
-    goto CLOSE_HC;\r
-  }\r
-\r
-  //\r
-  // Initial the wanted child device path list, and add first RemainingDevicePath\r
-  //\r
-  InitializeListHead (&UsbBus->WantedUsbIoDPList);\r
-  Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);\r
-  ASSERT (!EFI_ERROR (Status));\r
-  //\r
-  // Create a fake usb device for root hub\r
-  //\r
-  RootHub = AllocateZeroPool (sizeof (USB_DEVICE));\r
-\r
-  if (RootHub == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto UNINSTALL_USBBUS;\r
-  }\r
-\r
-  RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
-\r
-  if (RootIf == NULL) {\r
-    gBS->FreePool (RootHub);\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto FREE_ROOTHUB;\r
-  }\r
-\r
-  RootHub->Bus            = UsbBus;\r
-  RootHub->NumOfInterface = 1;\r
-  RootHub->Interfaces[0]  = RootIf;\r
-  RootIf->Signature       = USB_INTERFACE_SIGNATURE;\r
-  RootIf->Device          = RootHub;\r
-  RootIf->DevicePath      = UsbBus->DevicePath;\r
-\r
-  Status                  = mUsbRootHubApi.Init (RootIf);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));\r
-    goto FREE_ROOTHUB;\r
-  }\r
-\r
-  UsbBus->Devices[0] = RootHub;\r
-\r
-  DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));\r
-  return EFI_SUCCESS;\r
-\r
-FREE_ROOTHUB:\r
-  if (RootIf != NULL) {\r
-    gBS->FreePool (RootIf);\r
-  }\r
-  if (RootHub != NULL) {\r
-    gBS->FreePool (RootHub);\r
-  }\r
-\r
-UNINSTALL_USBBUS:\r
-  gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);\r
-\r
-CLOSE_HC:\r
-  if (UsbBus->Usb2Hc != NULL) {\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiUsb2HcProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-  }\r
-  if (UsbBus->UsbHc != NULL) {\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiUsbHcProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-  }\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiDevicePathProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
-  gBS->FreePool (UsbBus);\r
-\r
-  DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));\r
-  return Status;\r
-}\r
-\r
-EFI_USB_IO_PROTOCOL mUsbIoProtocol = {\r
-  UsbIoControlTransfer,\r
-  UsbIoBulkTransfer,\r
-  UsbIoAsyncInterruptTransfer,\r
-  UsbIoSyncInterruptTransfer,\r
-  UsbIoIsochronousTransfer,\r
-  UsbIoAsyncIsochronousTransfer,\r
-  UsbIoGetDeviceDescriptor,\r
-  UsbIoGetActiveConfigDescriptor,\r
-  UsbIoGetInterfaceDescriptor,\r
-  UsbIoGetEndpointDescriptor,\r
-  UsbIoGetStringDescriptor,\r
-  UsbIoGetSupportedLanguages,\r
-  UsbIoPortReset\r
-};\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusDriverEntryPoint (\r
-  IN EFI_HANDLE           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE     *SystemTable\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  The USB bus driver entry pointer\r
-\r
-Arguments:\r
-\r
-  ImageHandle - The driver image handle\r
-  SystemTable - The system table\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS - The component name protocol is installed\r
-  Others      - Failed to init the usb driver\r
-\r
---*/\r
-{\r
-  return EfiLibInstallDriverBindingComponentName2 (\r
-           ImageHandle,\r
-           SystemTable,\r
-           &mUsbBusDriverBinding,\r
-           ImageHandle,\r
-           &mUsbBusComponentName,\r
-           &mUsbBusComponentName2\r
-           );\r
-}\r
-\r
-\r
-/**\r
-  Check whether USB bus driver support this device\r
-\r
-  @param  This                   The USB bus driver binding protocol\r
-  @param  Controller             The controller handle to test againist\r
-  @param  RemainingDevicePath    The remaining device path\r
-\r
-  @retval EFI_SUCCESS            The bus supports this controller.\r
-  @retval EFI_UNSUPPORTED        This device isn't supported\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusControllerDriverSupported (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
-  IN EFI_HANDLE                   Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
-  )\r
-{\r
-  EFI_DEV_PATH_PTR          DevicePathNode;\r
-  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
-  EFI_USB2_HC_PROTOCOL      *Usb2Hc;\r
-  EFI_USB_HC_PROTOCOL       *UsbHc;\r
-  EFI_STATUS                Status;\r
-\r
-  //\r
-  // Check whether device path is valid\r
-  //\r
-  if (RemainingDevicePath != NULL) {\r
-    DevicePathNode.DevPath = RemainingDevicePath;\r
-\r
-    if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||\r
-        (DevicePathNode.DevPath->SubType != MSG_USB_DP &&\r
-         DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP\r
-         && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP\r
-         )) {\r
-\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  }\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  if (Status == EFI_ALREADY_STARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiDevicePathProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
-\r
-  //\r
-  // Check whether USB_HC2 protocol is installed\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiUsb2HcProtocolGuid,\r
-                  (VOID **) &Usb2Hc,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  if (Status == EFI_ALREADY_STARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiUsb2HcProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // If failed to open USB_HC2, fall back to USB_HC\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiUsbHcProtocolGuid,\r
-                  (VOID **) &UsbHc,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  if (Status == EFI_ALREADY_STARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiUsbHcProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Start to process the controller\r
-\r
-  @param  This                   The USB bus driver binding instance\r
-  @param  Controller             The controller to check\r
-  @param  RemainingDevicePath    The remaining device patch\r
-\r
-  @retval EFI_SUCCESS            The controller is controlled by the usb bus\r
-  @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb\r
-                                 bus\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusControllerDriverStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
-  IN EFI_HANDLE                   Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
-  )\r
-{\r
-  EFI_USB_BUS_PROTOCOL          *UsbBusId;\r
-  EFI_STATUS                    Status;\r
-\r
-  //\r
-  // Locate the USB bus protocol, if it is found, USB bus\r
-  // is already started on this controller.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &mUsbBusProtocolGuid,\r
-                  (VOID **) &UsbBusId,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // If first start, build the bus execute enviorment and install bus protocol\r
-    //\r
-    Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-    //\r
-    // Try get the Usb Bus protocol interface again\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    Controller,\r
-                    &mUsbBusProtocolGuid,\r
-                    (VOID **) &UsbBusId,\r
-                    This->DriverBindingHandle,\r
-                    Controller,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-    ASSERT (!EFI_ERROR (Status));\r
-  } else {\r
-    //\r
-    // USB Bus driver need to control the recursive connect policy of the bus, only those wanted\r
-    // usb child device will be recursively connected.\r
-    // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.\r
-    // All wanted usb child devices will be remembered by the usb bus driver itself.\r
-    // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.\r
-    //\r
-    // Save the passed in RemainingDevicePath this time\r
-    //\r
-    Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);\r
-    ASSERT (!EFI_ERROR (Status));\r
-    //\r
-    // Ensure all wanted child usb devices are fully recursively connected\r
-    //\r
-    Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);\r
-    ASSERT (!EFI_ERROR (Status));\r
-  }\r
-\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Stop handle the controller by this USB bus driver\r
-\r
-  @param  This                   The USB bus driver binding protocol\r
-  @param  Controller             The controller to release\r
-  @param  NumberOfChildren       The child of USB bus that opened controller\r
-                                 BY_CHILD\r
-  @param  ChildHandleBuffer      The array of child handle\r
-\r
-  @retval EFI_SUCCESS            The controller or children are stopped\r
-  @retval EFI_DEVICE_ERROR       Failed to stop the driver\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusControllerDriverStop (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
-  IN EFI_HANDLE                   Controller,\r
-  IN UINTN                        NumberOfChildren,\r
-  IN EFI_HANDLE                   *ChildHandleBuffer\r
-  )\r
-{\r
-  USB_BUS               *Bus;\r
-  USB_DEVICE            *RootHub;\r
-  USB_DEVICE            *UsbDev;\r
-  USB_INTERFACE         *RootIf;\r
-  USB_INTERFACE         *UsbIf;\r
-  EFI_USB_BUS_PROTOCOL  *BusId;\r
-  EFI_USB_IO_PROTOCOL   *UsbIo;\r
-  EFI_TPL               OldTpl;\r
-  UINTN                 Index;\r
-  EFI_STATUS            Status;\r
-\r
-  Status  = EFI_SUCCESS;\r
-\r
-  if (NumberOfChildren > 0) {\r
-    //\r
-    // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
-    //\r
-    OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-    for (Index = 0; Index < NumberOfChildren; Index++) {\r
-      Status = gBS->OpenProtocol (\r
-                      ChildHandleBuffer[Index],\r
-                      &gEfiUsbIoProtocolGuid,\r
-                      (VOID **) &UsbIo,\r
-                      This->DriverBindingHandle,\r
-                      Controller,\r
-                      EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                      );\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        //\r
-        // It is possible that the child has already been released:\r
-        // 1. For combo device, free one device will release others.\r
-        // 2. If a hub is released, all devices on its down facing\r
-        //    ports are released also.\r
-        //\r
-        continue;\r
-      }\r
-\r
-      UsbIf   = USB_INTERFACE_FROM_USBIO (UsbIo);\r
-      UsbDev  = UsbIf->Device;\r
-\r
-      UsbRemoveDevice (UsbDev);\r
-    }\r
-\r
-    gBS->RestoreTPL (OldTpl);\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %x\n", Controller));\r
-\r
-  //\r
-  // Locate USB_BUS for the current host controller\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &mUsbBusProtocolGuid,\r
-                  (VOID **) &BusId,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Bus = USB_BUS_FROM_THIS (BusId);\r
-\r
-  //\r
-  // Stop the root hub, then free all the devices\r
-  //\r
-  // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
-  //\r
-  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
-  UsbHcSetState (Bus, EfiUsbHcStateHalt);\r
-\r
-  RootHub = Bus->Devices[0];\r
-  RootIf  = RootHub->Interfaces[0];\r
-\r
-  mUsbRootHubApi.Release (RootIf);\r
-\r
-  for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
-    if (Bus->Devices[Index] != NULL) {\r
-      UsbRemoveDevice (Bus->Devices[Index]);\r
-    }\r
-  }\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  gBS->FreePool   (RootIf);\r
-  gBS->FreePool   (RootHub);\r
-  Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
-  ASSERT (!EFI_ERROR (Status));\r
-\r
-  //\r
-  // Uninstall the bus identifier and close USB_HC/USB2_HC protocols\r
-  //\r
-  gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);\r
-\r
-  if (Bus->Usb2Hc != NULL) {\r
-    gBS->CloseProtocol (\r
-           Controller,\r
-           &gEfiUsb2HcProtocolGuid,\r
-           This->DriverBindingHandle,\r
-           Controller\r
-           );\r
-  }\r
-\r
-  if (Bus->UsbHc != NULL) {\r
-    gBS->CloseProtocol (\r
-           Controller,\r
-           &gEfiUsbHcProtocolGuid,\r
-           This->DriverBindingHandle,\r
-           Controller\r
-           );\r
-  }\r
-\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiDevicePathProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
-\r
-  gBS->FreePool (Bus);\r
-\r
-  return Status;\r
-}\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {\r
-  UsbBusControllerDriverSupported,\r
-  UsbBusControllerDriverStart,\r
-  UsbBusControllerDriverStop,\r
-  0xa,\r
-  NULL,\r
-  NULL\r
-};\r