Home | History | Annotate | Download | only in UsbBusDxe
      1 /** @file
      2 
      3     Usb Bus Driver Binding and Bus IO Protocol.
      4 
      5 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "UsbBus.h"
     17 
     18 EFI_USB_IO_PROTOCOL mUsbIoProtocol = {
     19   UsbIoControlTransfer,
     20   UsbIoBulkTransfer,
     21   UsbIoAsyncInterruptTransfer,
     22   UsbIoSyncInterruptTransfer,
     23   UsbIoIsochronousTransfer,
     24   UsbIoAsyncIsochronousTransfer,
     25   UsbIoGetDeviceDescriptor,
     26   UsbIoGetActiveConfigDescriptor,
     27   UsbIoGetInterfaceDescriptor,
     28   UsbIoGetEndpointDescriptor,
     29   UsbIoGetStringDescriptor,
     30   UsbIoGetSupportedLanguages,
     31   UsbIoPortReset
     32 };
     33 
     34 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {
     35   UsbBusControllerDriverSupported,
     36   UsbBusControllerDriverStart,
     37   UsbBusControllerDriverStop,
     38   0xa,
     39   NULL,
     40   NULL
     41 };
     42 
     43 /**
     44   USB_IO function to execute a control transfer. This
     45   function will execute the USB transfer. If transfer
     46   successes, it will sync the internal state of USB bus
     47   with device state.
     48 
     49   @param  This                   The USB_IO instance
     50   @param  Request                The control transfer request
     51   @param  Direction              Direction for data stage
     52   @param  Timeout                The time to wait before timeout
     53   @param  Data                   The buffer holding the data
     54   @param  DataLength             Then length of the data
     55   @param  UsbStatus              USB result
     56 
     57   @retval EFI_INVALID_PARAMETER  The parameters are invalid
     58   @retval EFI_SUCCESS            The control transfer succeeded.
     59   @retval Others                 Failed to execute the transfer
     60 
     61 **/
     62 EFI_STATUS
     63 EFIAPI
     64 UsbIoControlTransfer (
     65   IN  EFI_USB_IO_PROTOCOL     *This,
     66   IN  EFI_USB_DEVICE_REQUEST  *Request,
     67   IN  EFI_USB_DATA_DIRECTION  Direction,
     68   IN  UINT32                  Timeout,
     69   IN  OUT VOID                *Data,      OPTIONAL
     70   IN  UINTN                   DataLength, OPTIONAL
     71   OUT UINT32                  *UsbStatus
     72   )
     73 {
     74   USB_DEVICE              *Dev;
     75   USB_INTERFACE           *UsbIf;
     76   USB_ENDPOINT_DESC       *EpDesc;
     77   EFI_TPL                 OldTpl;
     78   EFI_STATUS              Status;
     79 
     80   if (UsbStatus == NULL) {
     81     return EFI_INVALID_PARAMETER;
     82   }
     83 
     84   OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
     85 
     86   UsbIf  = USB_INTERFACE_FROM_USBIO (This);
     87   Dev    = UsbIf->Device;
     88 
     89   Status = UsbHcControlTransfer (
     90              Dev->Bus,
     91              Dev->Address,
     92              Dev->Speed,
     93              Dev->MaxPacket0,
     94              Request,
     95              Direction,
     96              Data,
     97              &DataLength,
     98              (UINTN) Timeout,
     99              &Dev->Translator,
    100              UsbStatus
    101              );
    102 
    103   if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {
    104     //
    105     // Clear TT buffer when CTRL/BULK split transaction failes
    106     // Clear the TRANSLATOR TT buffer, not parent's buffer
    107     //
    108     ASSERT (Dev->Translator.TranslatorHubAddress < Dev->Bus->MaxDevices);
    109     if (Dev->Translator.TranslatorHubAddress != 0) {
    110       UsbHubCtrlClearTTBuffer (
    111         Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],
    112         Dev->Translator.TranslatorPortNumber,
    113         Dev->Address,
    114         0,
    115         USB_ENDPOINT_CONTROL
    116         );
    117     }
    118 
    119     goto ON_EXIT;
    120   }
    121 
    122   //
    123   // Some control transfer will change the device's internal
    124   // status, such as Set_Configuration and Set_Interface.
    125   // We must synchronize the bus driver's status with that in
    126   // device. We ignore the Set_Descriptor request because it's
    127   // hardly used by any device, especially in pre-boot environment
    128   //
    129 
    130   //
    131   // Reset the endpoint toggle when endpoint stall is cleared
    132   //
    133   if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&
    134       (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,
    135                                                  USB_TARGET_ENDPOINT)) &&
    136       (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {
    137 
    138     EpDesc = UsbGetEndpointDesc (UsbIf, (UINT8) Request->Index);
    139 
    140     if (EpDesc != NULL) {
    141       EpDesc->Toggle = 0;
    142     }
    143   }
    144 
    145   //
    146   // Select a new configuration. This is a dangerous action. Upper driver
    147   // should stop use its current UsbIo after calling this driver. The old
    148   // UsbIo will be uninstalled and new UsbIo be installed. We can't use
    149   // ReinstallProtocol since interfaces in different configuration may be
    150   // completely irrelevant.
    151   //
    152   if ((Request->Request == USB_REQ_SET_CONFIG) &&
    153       (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,
    154                                                  USB_TARGET_DEVICE))) {
    155     //
    156     // Don't re-create the USB interfaces if configuration isn't changed.
    157     //
    158     if ((Dev->ActiveConfig != NULL) &&
    159         (Request->Value == Dev->ActiveConfig->Desc.ConfigurationValue)) {
    160 
    161       goto ON_EXIT;
    162     }
    163     DEBUG ((EFI_D_INFO, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
    164 
    165     if (Dev->ActiveConfig != NULL) {
    166       UsbRemoveConfig (Dev);
    167     }
    168 
    169     if (Request->Value != 0) {
    170       Status = UsbSelectConfig (Dev, (UINT8) Request->Value);
    171     }
    172 
    173     //
    174     // Exit now, Old USB_IO is invalid now
    175     //
    176     goto ON_EXIT;
    177   }
    178 
    179   //
    180   // A new alternative setting is selected for the interface.
    181   // No need to reinstall UsbIo in this case because only
    182   // underlying communication endpoints are changed. Functionality
    183   // should remains the same.
    184   //
    185   if ((Request->Request     == USB_REQ_SET_INTERFACE) &&
    186       (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,
    187                                                  USB_TARGET_INTERFACE)) &&
    188       (Request->Index       == UsbIf->IfSetting->Desc.InterfaceNumber)) {
    189 
    190     Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);
    191 
    192     if (!EFI_ERROR (Status)) {
    193       ASSERT (UsbIf->IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);
    194       UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];
    195     }
    196   }
    197 
    198 ON_EXIT:
    199   gBS->RestoreTPL (OldTpl);
    200   return Status;
    201 }
    202 
    203 
    204 /**
    205   Execute a bulk transfer to the device endpoint.
    206 
    207   @param  This                   The USB IO instance.
    208   @param  Endpoint               The device endpoint.
    209   @param  Data                   The data to transfer.
    210   @param  DataLength             The length of the data to transfer.
    211   @param  Timeout                Time to wait before timeout.
    212   @param  UsbStatus              The result of USB transfer.
    213 
    214   @retval EFI_SUCCESS            The bulk transfer is OK.
    215   @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
    216   @retval Others                 Failed to execute transfer, reason returned in
    217                                  UsbStatus.
    218 
    219 **/
    220 EFI_STATUS
    221 EFIAPI
    222 UsbIoBulkTransfer (
    223   IN  EFI_USB_IO_PROTOCOL *This,
    224   IN  UINT8               Endpoint,
    225   IN  OUT VOID            *Data,
    226   IN  OUT UINTN           *DataLength,
    227   IN  UINTN               Timeout,
    228   OUT UINT32              *UsbStatus
    229   )
    230 {
    231   USB_DEVICE              *Dev;
    232   USB_INTERFACE           *UsbIf;
    233   USB_ENDPOINT_DESC       *EpDesc;
    234   UINT8                   BufNum;
    235   UINT8                   Toggle;
    236   EFI_TPL                 OldTpl;
    237   EFI_STATUS              Status;
    238 
    239   if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||
    240       (UsbStatus == NULL)) {
    241 
    242     return EFI_INVALID_PARAMETER;
    243   }
    244 
    245   OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);
    246 
    247   UsbIf   = USB_INTERFACE_FROM_USBIO (This);
    248   Dev     = UsbIf->Device;
    249 
    250   EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);
    251 
    252   if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_BULK)) {
    253     Status = EFI_INVALID_PARAMETER;
    254     goto ON_EXIT;
    255   }
    256 
    257   BufNum  = 1;
    258   Toggle  = EpDesc->Toggle;
    259   Status  = UsbHcBulkTransfer (
    260               Dev->Bus,
    261               Dev->Address,
    262               Endpoint,
    263               Dev->Speed,
    264               EpDesc->Desc.MaxPacketSize,
    265               BufNum,
    266               &Data,
    267               DataLength,
    268               &Toggle,
    269               Timeout,
    270               &Dev->Translator,
    271               UsbStatus
    272               );
    273 
    274   EpDesc->Toggle = Toggle;
    275 
    276   if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {
    277     //
    278     // Clear TT buffer when CTRL/BULK split transaction failes.
    279     // Clear the TRANSLATOR TT buffer, not parent's buffer
    280     //
    281     ASSERT (Dev->Translator.TranslatorHubAddress < Dev->Bus->MaxDevices);
    282     if (Dev->Translator.TranslatorHubAddress != 0) {
    283       UsbHubCtrlClearTTBuffer (
    284         Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],
    285         Dev->Translator.TranslatorPortNumber,
    286         Dev->Address,
    287         0,
    288         USB_ENDPOINT_BULK
    289         );
    290     }
    291   }
    292 
    293 ON_EXIT:
    294   gBS->RestoreTPL (OldTpl);
    295   return Status;
    296 }
    297 
    298 
    299 /**
    300   Execute a synchronous interrupt transfer.
    301 
    302   @param  This                   The USB IO instance.
    303   @param  Endpoint               The device endpoint.
    304   @param  Data                   The data to transfer.
    305   @param  DataLength             The length of the data to transfer.
    306   @param  Timeout                Time to wait before timeout.
    307   @param  UsbStatus              The result of USB transfer.
    308 
    309   @retval EFI_SUCCESS            The synchronous interrupt transfer is OK.
    310   @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
    311   @retval Others                 Failed to execute transfer, reason returned in
    312                                  UsbStatus.
    313 
    314 **/
    315 EFI_STATUS
    316 EFIAPI
    317 UsbIoSyncInterruptTransfer (
    318   IN  EFI_USB_IO_PROTOCOL *This,
    319   IN  UINT8               Endpoint,
    320   IN  OUT VOID            *Data,
    321   IN  OUT UINTN           *DataLength,
    322   IN  UINTN               Timeout,
    323   OUT UINT32              *UsbStatus
    324   )
    325 {
    326   USB_DEVICE              *Dev;
    327   USB_INTERFACE           *UsbIf;
    328   USB_ENDPOINT_DESC       *EpDesc;
    329   EFI_TPL                 OldTpl;
    330   UINT8                   Toggle;
    331   EFI_STATUS              Status;
    332 
    333   if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||
    334       (UsbStatus == NULL)) {
    335 
    336     return EFI_INVALID_PARAMETER;
    337   }
    338 
    339   OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);
    340 
    341   UsbIf   = USB_INTERFACE_FROM_USBIO (This);
    342   Dev     = UsbIf->Device;
    343 
    344   EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);
    345 
    346   if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {
    347     Status = EFI_INVALID_PARAMETER;
    348     goto ON_EXIT;
    349   }
    350 
    351   Toggle = EpDesc->Toggle;
    352   Status = UsbHcSyncInterruptTransfer (
    353              Dev->Bus,
    354              Dev->Address,
    355              Endpoint,
    356              Dev->Speed,
    357              EpDesc->Desc.MaxPacketSize,
    358              Data,
    359              DataLength,
    360              &Toggle,
    361              Timeout,
    362              &Dev->Translator,
    363              UsbStatus
    364              );
    365 
    366   EpDesc->Toggle = Toggle;
    367 
    368 ON_EXIT:
    369   gBS->RestoreTPL (OldTpl);
    370   return Status;
    371 }
    372 
    373 
    374 /**
    375   Queue a new asynchronous interrupt transfer, or remove the old
    376   request if (IsNewTransfer == FALSE).
    377 
    378   @param  This                   The USB_IO instance.
    379   @param  Endpoint               The device endpoint.
    380   @param  IsNewTransfer          Whether this is a new request, if it's old, remove
    381                                  the request.
    382   @param  PollInterval           The interval to poll the transfer result, (in ms).
    383   @param  DataLength             The length of perodic data transfer.
    384   @param  Callback               The function to call periodicaly when transfer is
    385                                  ready.
    386   @param  Context                The context to the callback.
    387 
    388   @retval EFI_SUCCESS            New transfer is queued or old request is removed.
    389   @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
    390   @retval Others                 Failed to queue the new request or remove the old
    391                                  request.
    392 
    393 **/
    394 EFI_STATUS
    395 EFIAPI
    396 UsbIoAsyncInterruptTransfer (
    397   IN EFI_USB_IO_PROTOCOL              *This,
    398   IN UINT8                            Endpoint,
    399   IN BOOLEAN                          IsNewTransfer,
    400   IN UINTN                            PollInterval,       OPTIONAL
    401   IN UINTN                            DataLength,         OPTIONAL
    402   IN EFI_ASYNC_USB_TRANSFER_CALLBACK  Callback,           OPTIONAL
    403   IN VOID                             *Context            OPTIONAL
    404   )
    405 {
    406   USB_DEVICE              *Dev;
    407   USB_INTERFACE           *UsbIf;
    408   USB_ENDPOINT_DESC       *EpDesc;
    409   EFI_TPL                 OldTpl;
    410   UINT8                   Toggle;
    411   EFI_STATUS              Status;
    412 
    413   if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR (Endpoint) > 15)) {
    414     return EFI_INVALID_PARAMETER;
    415   }
    416 
    417   OldTpl  = gBS->RaiseTPL (USB_BUS_TPL);
    418   UsbIf   = USB_INTERFACE_FROM_USBIO (This);
    419   Dev     = UsbIf->Device;
    420 
    421   EpDesc  = UsbGetEndpointDesc (UsbIf, Endpoint);
    422 
    423   if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {
    424     Status = EFI_INVALID_PARAMETER;
    425     goto ON_EXIT;
    426   }
    427 
    428   Toggle  = EpDesc->Toggle;
    429   Status  = UsbHcAsyncInterruptTransfer (
    430               Dev->Bus,
    431               Dev->Address,
    432               Endpoint,
    433               Dev->Speed,
    434               EpDesc->Desc.MaxPacketSize,
    435               IsNewTransfer,
    436               &Toggle,
    437               PollInterval,
    438               DataLength,
    439               &Dev->Translator,
    440               Callback,
    441               Context
    442               );
    443 
    444   EpDesc->Toggle = Toggle;
    445 
    446 ON_EXIT:
    447   gBS->RestoreTPL (OldTpl);
    448   return Status;
    449 }
    450 
    451 
    452 /**
    453   Execute a synchronous isochronous transfer.
    454 
    455   @param  This                   The USB IO instance.
    456   @param  DeviceEndpoint         The device endpoint.
    457   @param  Data                   The data to transfer.
    458   @param  DataLength             The length of the data to transfer.
    459   @param  UsbStatus              The result of USB transfer.
    460 
    461   @retval EFI_UNSUPPORTED        Currently isochronous transfer isn't supported.
    462 
    463 **/
    464 EFI_STATUS
    465 EFIAPI
    466 UsbIoIsochronousTransfer (
    467   IN  EFI_USB_IO_PROTOCOL *This,
    468   IN  UINT8               DeviceEndpoint,
    469   IN  OUT VOID            *Data,
    470   IN  UINTN               DataLength,
    471   OUT UINT32              *Status
    472   )
    473 {
    474   return EFI_UNSUPPORTED;
    475 }
    476 
    477 
    478 /**
    479   Queue an asynchronous isochronous transfer.
    480 
    481   @param  This                   The USB_IO instance.
    482   @param  DeviceEndpoint         The device endpoint.
    483   @param  Data                   The data to transfer.
    484   @param  DataLength             The length of perodic data transfer.
    485   @param  IsochronousCallBack    The function to call periodicaly when transfer is
    486                                  ready.
    487   @param  Context                The context to the callback.
    488 
    489   @retval EFI_UNSUPPORTED        Currently isochronous transfer isn't supported.
    490 
    491 **/
    492 EFI_STATUS
    493 EFIAPI
    494 UsbIoAsyncIsochronousTransfer (
    495   IN EFI_USB_IO_PROTOCOL              *This,
    496   IN UINT8                            DeviceEndpoint,
    497   IN OUT VOID                         *Data,
    498   IN UINTN                            DataLength,
    499   IN EFI_ASYNC_USB_TRANSFER_CALLBACK  IsochronousCallBack,
    500   IN VOID                             *Context              OPTIONAL
    501   )
    502 {
    503   return EFI_UNSUPPORTED;
    504 }
    505 
    506 
    507 /**
    508   Retrieve the device descriptor of the device.
    509 
    510   @param  This                   The USB IO instance.
    511   @param  Descriptor             The variable to receive the device descriptor.
    512 
    513   @retval EFI_SUCCESS            The device descriptor is returned.
    514   @retval EFI_INVALID_PARAMETER  The parameter is invalid.
    515 
    516 **/
    517 EFI_STATUS
    518 EFIAPI
    519 UsbIoGetDeviceDescriptor (
    520   IN  EFI_USB_IO_PROTOCOL       *This,
    521   OUT EFI_USB_DEVICE_DESCRIPTOR *Descriptor
    522   )
    523 {
    524   USB_DEVICE              *Dev;
    525   USB_INTERFACE           *UsbIf;
    526   EFI_TPL                 OldTpl;
    527 
    528   if (Descriptor == NULL) {
    529     return EFI_INVALID_PARAMETER;
    530   }
    531 
    532   OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
    533 
    534   UsbIf  = USB_INTERFACE_FROM_USBIO (This);
    535   Dev    = UsbIf->Device;
    536 
    537   CopyMem (Descriptor, &Dev->DevDesc->Desc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
    538 
    539   gBS->RestoreTPL (OldTpl);
    540   return EFI_SUCCESS;
    541 }
    542 
    543 
    544 /**
    545   Return the configuration descriptor of the current active configuration.
    546 
    547   @param  This                   The USB IO instance.
    548   @param  Descriptor             The USB configuration descriptor.
    549 
    550   @retval EFI_SUCCESS            The active configuration descriptor is returned.
    551   @retval EFI_INVALID_PARAMETER  Some parameter is invalid.
    552   @retval EFI_NOT_FOUND          Currently no active configuration is selected.
    553 
    554 **/
    555 EFI_STATUS
    556 EFIAPI
    557 UsbIoGetActiveConfigDescriptor (
    558   IN  EFI_USB_IO_PROTOCOL       *This,
    559   OUT EFI_USB_CONFIG_DESCRIPTOR *Descriptor
    560   )
    561 {
    562   USB_DEVICE              *Dev;
    563   USB_INTERFACE           *UsbIf;
    564   EFI_STATUS              Status;
    565   EFI_TPL                 OldTpl;
    566 
    567   if (Descriptor == NULL) {
    568     return EFI_INVALID_PARAMETER;
    569   }
    570 
    571   Status = EFI_SUCCESS;
    572   OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
    573 
    574   UsbIf  = USB_INTERFACE_FROM_USBIO (This);
    575   Dev    = UsbIf->Device;
    576 
    577   if (Dev->ActiveConfig == NULL) {
    578     Status = EFI_NOT_FOUND;
    579     goto ON_EXIT;
    580   }
    581 
    582   CopyMem (Descriptor, &(Dev->ActiveConfig->Desc), sizeof (EFI_USB_CONFIG_DESCRIPTOR));
    583 
    584 ON_EXIT:
    585   gBS->RestoreTPL (OldTpl);
    586   return Status;
    587 }
    588 
    589 
    590 /**
    591   Retrieve the active interface setting descriptor for this USB IO instance.
    592 
    593   @param  This                   The USB IO instance.
    594   @param  Descriptor             The variable to receive active interface setting.
    595 
    596   @retval EFI_SUCCESS            The active interface setting is returned.
    597   @retval EFI_INVALID_PARAMETER  Some parameter is invalid.
    598 
    599 **/
    600 EFI_STATUS
    601 EFIAPI
    602 UsbIoGetInterfaceDescriptor (
    603   IN  EFI_USB_IO_PROTOCOL           *This,
    604   OUT EFI_USB_INTERFACE_DESCRIPTOR  *Descriptor
    605   )
    606 {
    607   USB_INTERFACE           *UsbIf;
    608   EFI_TPL                 OldTpl;
    609 
    610   if (Descriptor == NULL) {
    611     return EFI_INVALID_PARAMETER;
    612   }
    613 
    614   OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
    615 
    616   UsbIf  = USB_INTERFACE_FROM_USBIO (This);
    617   CopyMem (Descriptor, &(UsbIf->IfSetting->Desc), sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
    618 
    619   gBS->RestoreTPL (OldTpl);
    620   return EFI_SUCCESS;
    621 }
    622 
    623 
    624 /**
    625   Retrieve the endpoint descriptor from this interface setting.
    626 
    627   @param  This                   The USB IO instance.
    628   @param  Index                  The index (start from zero) of the endpoint to
    629                                  retrieve.
    630   @param  Descriptor             The variable to receive the descriptor.
    631 
    632   @retval EFI_SUCCESS            The endpoint descriptor is returned.
    633   @retval EFI_INVALID_PARAMETER  Some parameter is invalid.
    634 
    635 **/
    636 EFI_STATUS
    637 EFIAPI
    638 UsbIoGetEndpointDescriptor (
    639   IN  EFI_USB_IO_PROTOCOL         *This,
    640   IN  UINT8                       Index,
    641   OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor
    642   )
    643 {
    644   USB_INTERFACE           *UsbIf;
    645   EFI_TPL                 OldTpl;
    646 
    647   OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
    648 
    649   UsbIf  = USB_INTERFACE_FROM_USBIO (This);
    650 
    651   if ((Descriptor == NULL) || (Index > 15)) {
    652     gBS->RestoreTPL (OldTpl);
    653     return EFI_INVALID_PARAMETER;
    654   }
    655 
    656   if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {
    657     gBS->RestoreTPL (OldTpl);
    658     return EFI_NOT_FOUND;
    659   }
    660 
    661   CopyMem (
    662     Descriptor,
    663     &(UsbIf->IfSetting->Endpoints[Index]->Desc),
    664     sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
    665     );
    666 
    667   gBS->RestoreTPL (OldTpl);
    668   return EFI_SUCCESS;
    669 }
    670 
    671 
    672 /**
    673   Retrieve the supported language ID table from the device.
    674 
    675   @param  This                   The USB IO instance.
    676   @param  LangIDTable            The table to return the language IDs.
    677   @param  TableSize              The size, in bytes, of the table LangIDTable.
    678 
    679   @retval EFI_SUCCESS            The language ID is return.
    680 
    681 **/
    682 EFI_STATUS
    683 EFIAPI
    684 UsbIoGetSupportedLanguages (
    685   IN  EFI_USB_IO_PROTOCOL *This,
    686   OUT UINT16              **LangIDTable,
    687   OUT UINT16              *TableSize
    688   )
    689 {
    690   USB_DEVICE              *Dev;
    691   USB_INTERFACE           *UsbIf;
    692   EFI_TPL                 OldTpl;
    693 
    694   OldTpl        = gBS->RaiseTPL (USB_BUS_TPL);
    695 
    696   UsbIf         = USB_INTERFACE_FROM_USBIO (This);
    697   Dev           = UsbIf->Device;
    698 
    699   *LangIDTable  = Dev->LangId;
    700   *TableSize    = (UINT16) (Dev->TotalLangId * sizeof (UINT16));
    701 
    702   gBS->RestoreTPL (OldTpl);
    703   return EFI_SUCCESS;
    704 }
    705 
    706 
    707 /**
    708   Retrieve an indexed string in the language of LangID.
    709 
    710   @param  This                   The USB IO instance.
    711   @param  LangID                 The language ID of the string to retrieve.
    712   @param  StringIndex            The index of the string.
    713   @param  String                 The variable to receive the string.
    714 
    715   @retval EFI_SUCCESS            The string is returned.
    716   @retval EFI_NOT_FOUND          No such string existed.
    717 
    718 **/
    719 EFI_STATUS
    720 EFIAPI
    721 UsbIoGetStringDescriptor (
    722   IN  EFI_USB_IO_PROTOCOL   *This,
    723   IN  UINT16                LangID,
    724   IN  UINT8                 StringIndex,
    725   OUT CHAR16                **String
    726   )
    727 {
    728   USB_DEVICE                *Dev;
    729   USB_INTERFACE             *UsbIf;
    730   EFI_USB_STRING_DESCRIPTOR *StrDesc;
    731   EFI_TPL                   OldTpl;
    732   UINT8                     *Buf;
    733   UINT8                     Index;
    734   EFI_STATUS                Status;
    735 
    736   if ((StringIndex == 0) || (LangID == 0)) {
    737     return EFI_NOT_FOUND;
    738   }
    739 
    740   OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
    741 
    742   UsbIf  = USB_INTERFACE_FROM_USBIO (This);
    743   Dev    = UsbIf->Device;
    744 
    745   //
    746   // Check whether language ID is supported
    747   //
    748   Status = EFI_NOT_FOUND;
    749 
    750   for (Index = 0; Index < Dev->TotalLangId; Index++) {
    751     ASSERT (Index < USB_MAX_LANG_ID);
    752     if (Dev->LangId[Index] == LangID) {
    753       break;
    754     }
    755   }
    756 
    757   if (Index == Dev->TotalLangId) {
    758     goto ON_EXIT;
    759   }
    760 
    761   //
    762   // Retrieve the string descriptor then allocate a buffer
    763   // to hold the string itself.
    764   //
    765   StrDesc = UsbGetOneString (Dev, StringIndex, LangID);
    766 
    767   if (StrDesc == NULL) {
    768     goto ON_EXIT;
    769   }
    770 
    771   if (StrDesc->Length <= 2) {
    772     goto FREE_STR;
    773   }
    774 
    775   Buf = AllocateZeroPool (StrDesc->Length);
    776 
    777   if (Buf == NULL) {
    778     Status = EFI_OUT_OF_RESOURCES;
    779     goto FREE_STR;
    780   }
    781 
    782   CopyMem (Buf, StrDesc->String, StrDesc->Length - 2);
    783   *String = (CHAR16 *) Buf;
    784   Status  = EFI_SUCCESS;
    785 
    786 FREE_STR:
    787   gBS->FreePool (StrDesc);
    788 
    789 ON_EXIT:
    790   gBS->RestoreTPL (OldTpl);
    791   return Status;
    792 }
    793 
    794 
    795 /**
    796   Reset the device, then if that succeeds, reconfigure the
    797   device with its address and current active configuration.
    798 
    799   @param  This                   The USB IO instance.
    800 
    801   @retval EFI_SUCCESS            The device is reset and configured.
    802   @retval Others                 Failed to reset the device.
    803 
    804 **/
    805 EFI_STATUS
    806 EFIAPI
    807 UsbIoPortReset (
    808   IN EFI_USB_IO_PROTOCOL  *This
    809   )
    810 {
    811   USB_INTERFACE           *UsbIf;
    812   USB_INTERFACE           *HubIf;
    813   USB_DEVICE              *Dev;
    814   EFI_TPL                 OldTpl;
    815   EFI_STATUS              Status;
    816   UINT8                   DevAddress;
    817 
    818   OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
    819 
    820   UsbIf  = USB_INTERFACE_FROM_USBIO (This);
    821   Dev    = UsbIf->Device;
    822 
    823   if (UsbIf->IsHub) {
    824     Status = EFI_INVALID_PARAMETER;
    825     goto ON_EXIT;
    826   }
    827 
    828   HubIf  = Dev->ParentIf;
    829   Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);
    830 
    831   if (EFI_ERROR (Status)) {
    832     DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub  %d, %r \n",
    833                 Dev->ParentPort, Dev->ParentAddr, Status));
    834 
    835     goto ON_EXIT;
    836   }
    837 
    838   HubIf->HubApi->ClearPortChange (HubIf, Dev->ParentPort);
    839 
    840   //
    841   // Reset the device to its current address. The device now has an address
    842   // of ZERO after port reset, so need to set Dev->Address to the device again for
    843   // host to communicate with it.
    844   //
    845   DevAddress   = Dev->Address;
    846   Dev->Address = 0;
    847   Status  = UsbSetAddress (Dev, DevAddress);
    848   Dev->Address = DevAddress;
    849 
    850   gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
    851 
    852   if (EFI_ERROR (Status)) {
    853     //
    854     // It may fail due to device disconnection or other reasons.
    855     //
    856     DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",
    857                 Dev->Address, Status));
    858 
    859     goto ON_EXIT;
    860   }
    861 
    862   DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev->Address));
    863 
    864   //
    865   // Reset the current active configure, after this device
    866   // is in CONFIGURED state.
    867   //
    868   if (Dev->ActiveConfig != NULL) {
    869     Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);
    870 
    871     if (EFI_ERROR (Status)) {
    872       DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",
    873                   Dev->Address, Status));
    874     }
    875   }
    876 
    877 ON_EXIT:
    878   gBS->RestoreTPL (OldTpl);
    879   return Status;
    880 }
    881 
    882 
    883 /**
    884   Install Usb Bus Protocol on host controller, and start the Usb bus.
    885 
    886   @param This                    The USB bus driver binding instance.
    887   @param Controller              The controller to check.
    888   @param RemainingDevicePath     The remaining device patch.
    889 
    890   @retval EFI_SUCCESS            The controller is controlled by the usb bus.
    891   @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb bus.
    892   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
    893 
    894 **/
    895 EFI_STATUS
    896 EFIAPI
    897 UsbBusBuildProtocol (
    898   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    899   IN EFI_HANDLE                   Controller,
    900   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    901   )
    902 {
    903   USB_BUS                 *UsbBus;
    904   USB_DEVICE              *RootHub;
    905   USB_INTERFACE           *RootIf;
    906   EFI_STATUS              Status;
    907   EFI_STATUS              Status2;
    908 
    909   UsbBus = AllocateZeroPool (sizeof (USB_BUS));
    910 
    911   if (UsbBus == NULL) {
    912     return EFI_OUT_OF_RESOURCES;
    913   }
    914 
    915   UsbBus->Signature  = USB_BUS_SIGNATURE;
    916   UsbBus->HostHandle = Controller;
    917   UsbBus->MaxDevices = USB_MAX_DEVICES;
    918 
    919   Status = gBS->OpenProtocol (
    920                   Controller,
    921                   &gEfiDevicePathProtocolGuid,
    922                   (VOID **) &UsbBus->DevicePath,
    923                   This->DriverBindingHandle,
    924                   Controller,
    925                   EFI_OPEN_PROTOCOL_BY_DRIVER
    926                   );
    927 
    928   if (EFI_ERROR (Status)) {
    929     DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));
    930 
    931     FreePool (UsbBus);
    932     return Status;
    933   }
    934 
    935   //
    936   // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
    937   // This is for backward compatibility with EFI 1.x. In UEFI
    938   // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
    939   // and USB_HC because EHCI driver will install both protocols
    940   // (for the same reason). If we don't consume both of them,
    941   // the unconsumed one may be opened by others.
    942   //
    943   Status = gBS->OpenProtocol (
    944                   Controller,
    945                   &gEfiUsb2HcProtocolGuid,
    946                   (VOID **) &(UsbBus->Usb2Hc),
    947                   This->DriverBindingHandle,
    948                   Controller,
    949                   EFI_OPEN_PROTOCOL_BY_DRIVER
    950                   );
    951 
    952   Status2 = gBS->OpenProtocol (
    953                    Controller,
    954                    &gEfiUsbHcProtocolGuid,
    955                    (VOID **) &(UsbBus->UsbHc),
    956                    This->DriverBindingHandle,
    957                    Controller,
    958                    EFI_OPEN_PROTOCOL_BY_DRIVER
    959                    );
    960 
    961   if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
    962     DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));
    963 
    964     Status = EFI_DEVICE_ERROR;
    965     goto CLOSE_HC;
    966   }
    967 
    968   if (!EFI_ERROR (Status)) {
    969     //
    970     // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
    971     // Then its max supported devices are 256. Otherwise it's 128.
    972     //
    973     ASSERT (UsbBus->Usb2Hc != NULL);
    974     if (UsbBus->Usb2Hc->MajorRevision == 0x3) {
    975       UsbBus->MaxDevices = 256;
    976     }
    977   }
    978 
    979   UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
    980   UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
    981 
    982   //
    983   // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
    984   //
    985   Status = gBS->InstallProtocolInterface (
    986                   &Controller,
    987                   &gEfiCallerIdGuid,
    988                   EFI_NATIVE_INTERFACE,
    989                   &UsbBus->BusId
    990                   );
    991 
    992   if (EFI_ERROR (Status)) {
    993     DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
    994     goto CLOSE_HC;
    995   }
    996 
    997   //
    998   // Initial the wanted child device path list, and add first RemainingDevicePath
    999   //
   1000   InitializeListHead (&UsbBus->WantedUsbIoDPList);
   1001   Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);
   1002   ASSERT (!EFI_ERROR (Status));
   1003   //
   1004   // Create a fake usb device for root hub
   1005   //
   1006   RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
   1007 
   1008   if (RootHub == NULL) {
   1009     Status = EFI_OUT_OF_RESOURCES;
   1010     goto UNINSTALL_USBBUS;
   1011   }
   1012 
   1013   RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
   1014 
   1015   if (RootIf == NULL) {
   1016     FreePool (RootHub);
   1017     Status = EFI_OUT_OF_RESOURCES;
   1018     goto FREE_ROOTHUB;
   1019   }
   1020 
   1021   RootHub->Bus            = UsbBus;
   1022   RootHub->NumOfInterface = 1;
   1023   RootHub->Interfaces[0]  = RootIf;
   1024   RootHub->Tier           = 0;
   1025   RootIf->Signature       = USB_INTERFACE_SIGNATURE;
   1026   RootIf->Device          = RootHub;
   1027   RootIf->DevicePath      = UsbBus->DevicePath;
   1028 
   1029   //
   1030   // Report Status Code here since we will enumerate the USB devices
   1031   //
   1032   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
   1033     EFI_PROGRESS_CODE,
   1034     (EFI_IO_BUS_USB | EFI_IOB_PC_DETECT),
   1035     UsbBus->DevicePath
   1036     );
   1037 
   1038   Status                  = mUsbRootHubApi.Init (RootIf);
   1039 
   1040   if (EFI_ERROR (Status)) {
   1041     DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
   1042     goto FREE_ROOTHUB;
   1043   }
   1044 
   1045   UsbBus->Devices[0] = RootHub;
   1046 
   1047   DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf));
   1048   return EFI_SUCCESS;
   1049 
   1050 FREE_ROOTHUB:
   1051   if (RootIf != NULL) {
   1052     FreePool (RootIf);
   1053   }
   1054   if (RootHub != NULL) {
   1055     FreePool (RootHub);
   1056   }
   1057 
   1058 UNINSTALL_USBBUS:
   1059   gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &UsbBus->BusId);
   1060 
   1061 CLOSE_HC:
   1062   if (UsbBus->Usb2Hc != NULL) {
   1063     gBS->CloseProtocol (
   1064           Controller,
   1065           &gEfiUsb2HcProtocolGuid,
   1066           This->DriverBindingHandle,
   1067           Controller
   1068           );
   1069   }
   1070   if (UsbBus->UsbHc != NULL) {
   1071     gBS->CloseProtocol (
   1072           Controller,
   1073           &gEfiUsbHcProtocolGuid,
   1074           This->DriverBindingHandle,
   1075           Controller
   1076           );
   1077   }
   1078   gBS->CloseProtocol (
   1079          Controller,
   1080          &gEfiDevicePathProtocolGuid,
   1081          This->DriverBindingHandle,
   1082          Controller
   1083          );
   1084   FreePool (UsbBus);
   1085 
   1086   DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
   1087   return Status;
   1088 }
   1089 
   1090 
   1091 /**
   1092   The USB bus driver entry pointer.
   1093 
   1094   @param ImageHandle       The driver image handle.
   1095   @param SystemTable       The system table.
   1096 
   1097   @return EFI_SUCCESS      The component name protocol is installed.
   1098   @return Others           Failed to init the usb driver.
   1099 
   1100 **/
   1101 EFI_STATUS
   1102 EFIAPI
   1103 UsbBusDriverEntryPoint (
   1104   IN EFI_HANDLE           ImageHandle,
   1105   IN EFI_SYSTEM_TABLE     *SystemTable
   1106   )
   1107 {
   1108   return EfiLibInstallDriverBindingComponentName2 (
   1109            ImageHandle,
   1110            SystemTable,
   1111            &mUsbBusDriverBinding,
   1112            ImageHandle,
   1113            &mUsbBusComponentName,
   1114            &mUsbBusComponentName2
   1115            );
   1116 }
   1117 
   1118 
   1119 /**
   1120   Check whether USB bus driver support this device.
   1121 
   1122   @param  This                   The USB bus driver binding protocol.
   1123   @param  Controller             The controller handle to check.
   1124   @param  RemainingDevicePath    The remaining device path.
   1125 
   1126   @retval EFI_SUCCESS            The bus supports this controller.
   1127   @retval EFI_UNSUPPORTED        This device isn't supported.
   1128 
   1129 **/
   1130 EFI_STATUS
   1131 EFIAPI
   1132 UsbBusControllerDriverSupported (
   1133   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1134   IN EFI_HANDLE                   Controller,
   1135   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
   1136   )
   1137 {
   1138   EFI_DEV_PATH_PTR          DevicePathNode;
   1139   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
   1140   EFI_USB2_HC_PROTOCOL      *Usb2Hc;
   1141   EFI_USB_HC_PROTOCOL       *UsbHc;
   1142   EFI_STATUS                Status;
   1143 
   1144   //
   1145   // Check whether device path is valid
   1146   //
   1147   if (RemainingDevicePath != NULL) {
   1148     //
   1149     // Check if RemainingDevicePath is the End of Device Path Node,
   1150     // if yes, go on checking other conditions
   1151     //
   1152     if (!IsDevicePathEnd (RemainingDevicePath)) {
   1153       //
   1154       // If RemainingDevicePath isn't the End of Device Path Node,
   1155       // check its validation
   1156       //
   1157       DevicePathNode.DevPath = RemainingDevicePath;
   1158 
   1159       if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||
   1160           (DevicePathNode.DevPath->SubType != MSG_USB_DP &&
   1161            DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP
   1162            && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP
   1163            )) {
   1164 
   1165         return EFI_UNSUPPORTED;
   1166       }
   1167     }
   1168   }
   1169 
   1170   //
   1171   // Check whether USB_HC2 protocol is installed
   1172   //
   1173   Status = gBS->OpenProtocol (
   1174                   Controller,
   1175                   &gEfiUsb2HcProtocolGuid,
   1176                   (VOID **) &Usb2Hc,
   1177                   This->DriverBindingHandle,
   1178                   Controller,
   1179                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1180                   );
   1181   if (Status == EFI_ALREADY_STARTED) {
   1182     return EFI_SUCCESS;
   1183   }
   1184 
   1185   if (EFI_ERROR (Status)) {
   1186     //
   1187     // If failed to open USB_HC2, fall back to USB_HC
   1188     //
   1189     Status = gBS->OpenProtocol (
   1190                     Controller,
   1191                     &gEfiUsbHcProtocolGuid,
   1192                     (VOID **) &UsbHc,
   1193                     This->DriverBindingHandle,
   1194                     Controller,
   1195                     EFI_OPEN_PROTOCOL_BY_DRIVER
   1196                     );
   1197     if (Status == EFI_ALREADY_STARTED) {
   1198       return EFI_SUCCESS;
   1199     }
   1200 
   1201     if (EFI_ERROR (Status)) {
   1202       return Status;
   1203     }
   1204 
   1205     //
   1206     // Close the USB_HC used to perform the supported test
   1207     //
   1208     gBS->CloseProtocol (
   1209           Controller,
   1210           &gEfiUsbHcProtocolGuid,
   1211           This->DriverBindingHandle,
   1212           Controller
   1213           );
   1214 
   1215   } else {
   1216 
   1217     //
   1218     // Close the USB_HC2 used to perform the supported test
   1219     //
   1220     gBS->CloseProtocol (
   1221            Controller,
   1222            &gEfiUsb2HcProtocolGuid,
   1223            This->DriverBindingHandle,
   1224            Controller
   1225            );
   1226   }
   1227 
   1228   //
   1229   // Open the EFI Device Path protocol needed to perform the supported test
   1230   //
   1231   Status = gBS->OpenProtocol (
   1232                   Controller,
   1233                   &gEfiDevicePathProtocolGuid,
   1234                   (VOID **) &ParentDevicePath,
   1235                   This->DriverBindingHandle,
   1236                   Controller,
   1237                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1238                   );
   1239   if (Status == EFI_ALREADY_STARTED) {
   1240     return EFI_SUCCESS;
   1241   }
   1242 
   1243   if (!EFI_ERROR (Status)) {
   1244     //
   1245     // Close protocol, don't use device path protocol in the Support() function
   1246     //
   1247     gBS->CloseProtocol (
   1248           Controller,
   1249           &gEfiDevicePathProtocolGuid,
   1250           This->DriverBindingHandle,
   1251           Controller
   1252           );
   1253 
   1254     return EFI_SUCCESS;
   1255   }
   1256 
   1257   return Status;
   1258 }
   1259 
   1260 
   1261 /**
   1262   Start to process the controller.
   1263 
   1264   @param  This                   The USB bus driver binding instance.
   1265   @param  Controller             The controller to check.
   1266   @param  RemainingDevicePath    The remaining device patch.
   1267 
   1268   @retval EFI_SUCCESS            The controller is controlled by the usb bus.
   1269   @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb
   1270                                  bus.
   1271   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
   1272 
   1273 **/
   1274 EFI_STATUS
   1275 EFIAPI
   1276 UsbBusControllerDriverStart (
   1277   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1278   IN EFI_HANDLE                   Controller,
   1279   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
   1280   )
   1281 {
   1282   EFI_USB_BUS_PROTOCOL          *UsbBusId;
   1283   EFI_STATUS                    Status;
   1284   EFI_DEVICE_PATH_PROTOCOL      *ParentDevicePath;
   1285 
   1286   Status = gBS->OpenProtocol (
   1287                   Controller,
   1288                   &gEfiDevicePathProtocolGuid,
   1289                   (VOID **) &ParentDevicePath,
   1290                   This->DriverBindingHandle,
   1291                   Controller,
   1292                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1293                   );
   1294   ASSERT_EFI_ERROR (Status);
   1295 
   1296   //
   1297   // Report Status Code here since we will initialize the host controller
   1298   //
   1299   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
   1300     EFI_PROGRESS_CODE,
   1301     (EFI_IO_BUS_USB | EFI_IOB_PC_INIT),
   1302     ParentDevicePath
   1303     );
   1304 
   1305   //
   1306   // Locate the USB bus protocol, if it is found, USB bus
   1307   // is already started on this controller.
   1308   //
   1309   Status = gBS->OpenProtocol (
   1310                   Controller,
   1311                   &gEfiCallerIdGuid,
   1312                   (VOID **) &UsbBusId,
   1313                   This->DriverBindingHandle,
   1314                   Controller,
   1315                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1316                   );
   1317 
   1318   if (EFI_ERROR (Status)) {
   1319     //
   1320     // If first start, build the bus execute environment and install bus protocol
   1321     //
   1322     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_P_PC_ENABLE));
   1323     Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);
   1324     if (EFI_ERROR (Status)) {
   1325       return Status;
   1326     }
   1327     //
   1328     // Try get the Usb Bus protocol interface again
   1329     //
   1330     Status = gBS->OpenProtocol (
   1331                     Controller,
   1332                     &gEfiCallerIdGuid,
   1333                     (VOID **) &UsbBusId,
   1334                     This->DriverBindingHandle,
   1335                     Controller,
   1336                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1337                     );
   1338     ASSERT (!EFI_ERROR (Status));
   1339   } else {
   1340     //
   1341     // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
   1342     // usb child device will be recursively connected.
   1343     // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
   1344     // All wanted usb child devices will be remembered by the usb bus driver itself.
   1345     // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
   1346     //
   1347     // Save the passed in RemainingDevicePath this time
   1348     //
   1349     if (RemainingDevicePath != NULL) {
   1350       if (IsDevicePathEnd (RemainingDevicePath)) {
   1351         //
   1352         // If RemainingDevicePath is the End of Device Path Node,
   1353         // skip enumerate any device and return EFI_SUCESSS
   1354         //
   1355         return EFI_SUCCESS;
   1356       }
   1357     }
   1358 
   1359     Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);
   1360     ASSERT (!EFI_ERROR (Status));
   1361     //
   1362     // Ensure all wanted child usb devices are fully recursively connected
   1363     //
   1364     Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);
   1365     ASSERT (!EFI_ERROR (Status));
   1366   }
   1367 
   1368 
   1369   return EFI_SUCCESS;
   1370 }
   1371 
   1372 
   1373 /**
   1374   Stop handle the controller by this USB bus driver.
   1375 
   1376   @param  This                   The USB bus driver binding protocol.
   1377   @param  Controller             The controller to release.
   1378   @param  NumberOfChildren       The child of USB bus that opened controller
   1379                                  BY_CHILD.
   1380   @param  ChildHandleBuffer      The array of child handle.
   1381 
   1382   @retval EFI_SUCCESS            The controller or children are stopped.
   1383   @retval EFI_DEVICE_ERROR       Failed to stop the driver.
   1384 
   1385 **/
   1386 EFI_STATUS
   1387 EFIAPI
   1388 UsbBusControllerDriverStop (
   1389   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1390   IN EFI_HANDLE                   Controller,
   1391   IN UINTN                        NumberOfChildren,
   1392   IN EFI_HANDLE                   *ChildHandleBuffer
   1393   )
   1394 {
   1395   USB_BUS               *Bus;
   1396   USB_DEVICE            *RootHub;
   1397   USB_DEVICE            *UsbDev;
   1398   USB_INTERFACE         *RootIf;
   1399   USB_INTERFACE         *UsbIf;
   1400   EFI_USB_BUS_PROTOCOL  *BusId;
   1401   EFI_USB_IO_PROTOCOL   *UsbIo;
   1402   EFI_TPL               OldTpl;
   1403   UINTN                 Index;
   1404   EFI_STATUS            Status;
   1405   EFI_STATUS            ReturnStatus;
   1406 
   1407   Status  = EFI_SUCCESS;
   1408 
   1409   if (NumberOfChildren > 0) {
   1410     //
   1411     // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
   1412     //
   1413     OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
   1414 
   1415     ReturnStatus = EFI_SUCCESS;
   1416     for (Index = 0; Index < NumberOfChildren; Index++) {
   1417       Status = gBS->OpenProtocol (
   1418                       ChildHandleBuffer[Index],
   1419                       &gEfiUsbIoProtocolGuid,
   1420                       (VOID **) &UsbIo,
   1421                       This->DriverBindingHandle,
   1422                       Controller,
   1423                       EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1424                       );
   1425 
   1426       if (EFI_ERROR (Status)) {
   1427         //
   1428         // It is possible that the child has already been released:
   1429         // 1. For combo device, free one device will release others.
   1430         // 2. If a hub is released, all devices on its down facing
   1431         //    ports are released also.
   1432         //
   1433         continue;
   1434       }
   1435 
   1436       UsbIf   = USB_INTERFACE_FROM_USBIO (UsbIo);
   1437       UsbDev  = UsbIf->Device;
   1438 
   1439       ReturnStatus = UsbRemoveDevice (UsbDev);
   1440     }
   1441 
   1442     gBS->RestoreTPL (OldTpl);
   1443     return ReturnStatus;
   1444   }
   1445 
   1446   DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));
   1447 
   1448   //
   1449   // Locate USB_BUS for the current host controller
   1450   //
   1451   Status = gBS->OpenProtocol (
   1452                   Controller,
   1453                   &gEfiCallerIdGuid,
   1454                   (VOID **) &BusId,
   1455                   This->DriverBindingHandle,
   1456                   Controller,
   1457                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1458                   );
   1459 
   1460   if (EFI_ERROR (Status)) {
   1461     return Status;
   1462   }
   1463 
   1464   Bus = USB_BUS_FROM_THIS (BusId);
   1465 
   1466   //
   1467   // Stop the root hub, then free all the devices
   1468   //
   1469   // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
   1470   //
   1471   OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);
   1472 
   1473   RootHub = Bus->Devices[0];
   1474   RootIf  = RootHub->Interfaces[0];
   1475 
   1476   ASSERT (Bus->MaxDevices <= 256);
   1477   ReturnStatus = EFI_SUCCESS;
   1478   for (Index = 1; Index < Bus->MaxDevices; Index++) {
   1479     if (Bus->Devices[Index] != NULL) {
   1480       Status = UsbRemoveDevice (Bus->Devices[Index]);
   1481       if (EFI_ERROR (Status)) {
   1482         ReturnStatus = Status;
   1483       }
   1484     }
   1485   }
   1486 
   1487   gBS->RestoreTPL (OldTpl);
   1488 
   1489   if (!EFI_ERROR (ReturnStatus)) {
   1490     mUsbRootHubApi.Release (RootIf);
   1491     gBS->FreePool   (RootIf);
   1492     gBS->FreePool   (RootHub);
   1493 
   1494     Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
   1495     ASSERT (!EFI_ERROR (Status));
   1496 
   1497     //
   1498     // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
   1499     //
   1500     gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &Bus->BusId);
   1501 
   1502     if (Bus->Usb2Hc != NULL) {
   1503       Status = gBS->CloseProtocol (
   1504                       Controller,
   1505                       &gEfiUsb2HcProtocolGuid,
   1506                       This->DriverBindingHandle,
   1507                       Controller
   1508                       );
   1509     }
   1510 
   1511     if (Bus->UsbHc != NULL) {
   1512       Status = gBS->CloseProtocol (
   1513                       Controller,
   1514                       &gEfiUsbHcProtocolGuid,
   1515                       This->DriverBindingHandle,
   1516                       Controller
   1517                       );
   1518     }
   1519 
   1520     if (!EFI_ERROR (Status)) {
   1521       gBS->CloseProtocol (
   1522              Controller,
   1523              &gEfiDevicePathProtocolGuid,
   1524              This->DriverBindingHandle,
   1525              Controller
   1526              );
   1527 
   1528       gBS->FreePool (Bus);
   1529     }
   1530   }
   1531   return Status;
   1532 }
   1533