Home | History | Annotate | Download | only in UsbBusDxe
      1 /** @file
      2 
      3     Unified interface for RootHub and Hub.
      4 
      5 Copyright (c) 2007 - 2012, 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 //
     19 // Array that maps the change bit to feature value which is
     20 // used to clear these change bit. USB HUB API will clear
     21 // these change bit automatically. For non-root hub, these
     22 // bits determine whether hub will report the port in changed
     23 // bit maps.
     24 //
     25 USB_CHANGE_FEATURE_MAP  mHubFeatureMap[] = {
     26   {USB_PORT_STAT_C_CONNECTION,  EfiUsbPortConnectChange},
     27   {USB_PORT_STAT_C_ENABLE,      EfiUsbPortEnableChange},
     28   {USB_PORT_STAT_C_SUSPEND,     EfiUsbPortSuspendChange},
     29   {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},
     30   {USB_PORT_STAT_C_RESET,       EfiUsbPortResetChange}
     31 };
     32 
     33 USB_CHANGE_FEATURE_MAP  mRootHubFeatureMap[] = {
     34   {USB_PORT_STAT_C_CONNECTION,  EfiUsbPortConnectChange},
     35   {USB_PORT_STAT_C_ENABLE,      EfiUsbPortEnableChange},
     36   {USB_PORT_STAT_C_SUSPEND,     EfiUsbPortSuspendChange},
     37   {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},
     38   {USB_PORT_STAT_C_RESET,       EfiUsbPortResetChange},
     39 };
     40 
     41 //
     42 // USB hub class specific requests. Although USB hub
     43 // is related to an interface, these requests are sent
     44 // to the control endpoint of the device.
     45 //
     46 /**
     47   USB hub control transfer to set the hub depth.
     48 
     49   @param  HubDev                The device of the hub.
     50   @param  Depth                 The depth to set.
     51 
     52   @retval EFI_SUCCESS           Depth of the hub is set.
     53   @retval Others                Failed to set the depth.
     54 
     55 **/
     56 EFI_STATUS
     57 UsbHubCtrlSetHubDepth (
     58   IN  USB_DEVICE          *HubDev,
     59   IN  UINT16              Depth
     60   )
     61 {
     62   EFI_STATUS              Status;
     63 
     64   Status = UsbCtrlRequest (
     65              HubDev,
     66              EfiUsbNoData,
     67              USB_REQ_TYPE_CLASS,
     68              USB_HUB_TARGET_HUB,
     69              USB_HUB_REQ_SET_DEPTH,
     70              Depth,
     71              0,
     72              NULL,
     73              0
     74              );
     75 
     76   return Status;
     77 }
     78 
     79 /**
     80   USB hub control transfer to clear the hub feature.
     81 
     82   @param  HubDev                The device of the hub.
     83   @param  Feature               The feature to clear.
     84 
     85   @retval EFI_SUCCESS           Feature of the hub is cleared.
     86   @retval Others                Failed to clear the feature.
     87 
     88 **/
     89 EFI_STATUS
     90 UsbHubCtrlClearHubFeature (
     91   IN USB_DEVICE           *HubDev,
     92   IN UINT16               Feature
     93   )
     94 {
     95   EFI_STATUS              Status;
     96 
     97   Status = UsbCtrlRequest (
     98              HubDev,
     99              EfiUsbNoData,
    100              USB_REQ_TYPE_CLASS,
    101              USB_HUB_TARGET_HUB,
    102              USB_HUB_REQ_CLEAR_FEATURE,
    103              Feature,
    104              0,
    105              NULL,
    106              0
    107              );
    108 
    109   return Status;
    110 }
    111 
    112 
    113 /**
    114   Clear the feature of the device's port.
    115 
    116   @param  HubDev                The hub device.
    117   @param  Port                  The port to clear feature.
    118   @param  Feature               The feature to clear.
    119 
    120   @retval EFI_SUCCESS           The feature of the port is cleared.
    121   @retval Others                Failed to clear the feature.
    122 
    123 **/
    124 EFI_STATUS
    125 UsbHubCtrlClearPortFeature (
    126   IN USB_DEVICE           *HubDev,
    127   IN UINT8                Port,
    128   IN UINT16               Feature
    129   )
    130 {
    131   EFI_STATUS              Status;
    132 
    133   //
    134   // In USB bus, all the port index starts from 0. But HUB
    135   // indexes its port from 1. So, port number is added one.
    136   //
    137   Status = UsbCtrlRequest (
    138              HubDev,
    139              EfiUsbNoData,
    140              USB_REQ_TYPE_CLASS,
    141              USB_HUB_TARGET_PORT,
    142              USB_HUB_REQ_CLEAR_FEATURE,
    143              Feature,
    144              (UINT16) (Port + 1),
    145              NULL,
    146              0
    147              );
    148 
    149   return Status;
    150 }
    151 
    152 
    153 /**
    154   Clear the transaction translate buffer if full/low
    155   speed control/bulk transfer failed and the transfer
    156   uses this hub as translator.Remember to clear the TT
    157   buffer of transaction translator, not that of the
    158   parent.
    159 
    160   @param  HubDev                The hub device.
    161   @param  Port                  The port of the hub.
    162   @param  DevAddr               Address of the failed transaction.
    163   @param  EpNum                 The endpoint number of the failed transaction.
    164   @param  EpType                The type of failed transaction.
    165 
    166   @retval EFI_SUCCESS           The TT buffer is cleared.
    167   @retval Others                Failed to clear the TT buffer.
    168 
    169 **/
    170 EFI_STATUS
    171 UsbHubCtrlClearTTBuffer (
    172   IN USB_DEVICE           *HubDev,
    173   IN UINT8                Port,
    174   IN UINT16               DevAddr,
    175   IN UINT16               EpNum,
    176   IN UINT16               EpType
    177   )
    178 {
    179   EFI_STATUS              Status;
    180   UINT16                  Value;
    181 
    182   //
    183   // Check USB2.0 spec page 424 for wValue's encoding
    184   //
    185   Value = (UINT16) ((EpNum & 0x0F) | (DevAddr << 4) |
    186           ((EpType & 0x03) << 11) | ((EpNum & 0x80) << 15));
    187 
    188   Status = UsbCtrlRequest (
    189              HubDev,
    190              EfiUsbNoData,
    191              USB_REQ_TYPE_CLASS,
    192              USB_HUB_TARGET_PORT,
    193              USB_HUB_REQ_CLEAR_TT,
    194              Value,
    195              (UINT16) (Port + 1),
    196              NULL,
    197              0
    198              );
    199 
    200   return Status;
    201 }
    202 
    203 /**
    204   Usb hub control transfer to get the super speed hub descriptor.
    205 
    206   @param  HubDev                The hub device.
    207   @param  Buf                   The buffer to hold the descriptor.
    208 
    209   @retval EFI_SUCCESS           The hub descriptor is retrieved.
    210   @retval Others                Failed to retrieve the hub descriptor.
    211 
    212 **/
    213 EFI_STATUS
    214 UsbHubCtrlGetSuperSpeedHubDesc (
    215   IN  USB_DEVICE          *HubDev,
    216   OUT VOID                *Buf
    217   )
    218 {
    219   EFI_STATUS              Status;
    220 
    221   Status = EFI_INVALID_PARAMETER;
    222 
    223   Status = UsbCtrlRequest (
    224              HubDev,
    225              EfiUsbDataIn,
    226              USB_REQ_TYPE_CLASS,
    227              USB_HUB_TARGET_HUB,
    228              USB_HUB_REQ_GET_DESC,
    229              (UINT16) (USB_DESC_TYPE_HUB_SUPER_SPEED << 8),
    230              0,
    231              Buf,
    232              32
    233              );
    234 
    235   return Status;
    236 }
    237 
    238 /**
    239   Usb hub control transfer to get the hub descriptor.
    240 
    241   @param  HubDev                The hub device.
    242   @param  Buf                   The buffer to hold the descriptor.
    243   @param  Len                   The length to retrieve.
    244 
    245   @retval EFI_SUCCESS           The hub descriptor is retrieved.
    246   @retval Others                Failed to retrieve the hub descriptor.
    247 
    248 **/
    249 EFI_STATUS
    250 UsbHubCtrlGetHubDesc (
    251   IN  USB_DEVICE          *HubDev,
    252   OUT VOID                *Buf,
    253   IN  UINTN               Len
    254   )
    255 {
    256   EFI_STATUS              Status;
    257 
    258   Status = UsbCtrlRequest (
    259              HubDev,
    260              EfiUsbDataIn,
    261              USB_REQ_TYPE_CLASS,
    262              USB_HUB_TARGET_HUB,
    263              USB_HUB_REQ_GET_DESC,
    264              (UINT16) (USB_DESC_TYPE_HUB << 8),
    265              0,
    266              Buf,
    267              Len
    268              );
    269 
    270   return Status;
    271 }
    272 
    273 
    274 /**
    275   Usb hub control transfer to get the hub status.
    276 
    277   @param  HubDev                The hub device.
    278   @param  State                 The variable to return the status.
    279 
    280   @retval EFI_SUCCESS           The hub status is returned in State.
    281   @retval Others                Failed to get the hub status.
    282 
    283 **/
    284 EFI_STATUS
    285 UsbHubCtrlGetHubStatus (
    286   IN  USB_DEVICE          *HubDev,
    287   OUT UINT32              *State
    288   )
    289 {
    290   EFI_STATUS              Status;
    291 
    292   Status = UsbCtrlRequest (
    293              HubDev,
    294              EfiUsbDataIn,
    295              USB_REQ_TYPE_CLASS,
    296              USB_HUB_TARGET_HUB,
    297              USB_HUB_REQ_GET_STATUS,
    298              0,
    299              0,
    300              State,
    301              4
    302              );
    303 
    304   return Status;
    305 }
    306 
    307 
    308 /**
    309   Usb hub control transfer to get the port status.
    310 
    311   @param  HubDev                The hub device.
    312   @param  Port                  The port of the hub.
    313   @param  State                 Variable to return the hub port state.
    314 
    315   @retval EFI_SUCCESS           The port state is returned in State.
    316   @retval Others                Failed to retrieve the port state.
    317 
    318 **/
    319 EFI_STATUS
    320 UsbHubCtrlGetPortStatus (
    321   IN  USB_DEVICE          *HubDev,
    322   IN  UINT8               Port,
    323   OUT VOID                *State
    324   )
    325 {
    326   EFI_STATUS              Status;
    327 
    328   //
    329   // In USB bus, all the port index starts from 0. But HUB
    330   // indexes its port from 1. So, port number is added one.
    331   // No need to convert the hub bit to UEFI definition, they
    332   // are the same
    333   //
    334   Status = UsbCtrlRequest (
    335              HubDev,
    336              EfiUsbDataIn,
    337              USB_REQ_TYPE_CLASS,
    338              USB_HUB_TARGET_PORT,
    339              USB_HUB_REQ_GET_STATUS,
    340              0,
    341              (UINT16) (Port + 1),
    342              State,
    343              4
    344              );
    345 
    346   return Status;
    347 }
    348 
    349 
    350 /**
    351   Usb hub control transfer to reset the TT (Transaction Transaltor).
    352 
    353   @param  HubDev                The hub device.
    354   @param  Port                  The port of the hub.
    355 
    356   @retval EFI_SUCCESS           The TT of the hub is reset.
    357   @retval Others                Failed to reset the port.
    358 
    359 **/
    360 EFI_STATUS
    361 UsbHubCtrlResetTT (
    362   IN  USB_DEVICE          *HubDev,
    363   IN  UINT8               Port
    364   )
    365 {
    366   EFI_STATUS              Status;
    367 
    368   Status = UsbCtrlRequest (
    369              HubDev,
    370              EfiUsbNoData,
    371              USB_REQ_TYPE_CLASS,
    372              USB_HUB_TARGET_HUB,
    373              USB_HUB_REQ_RESET_TT,
    374              0,
    375              (UINT16) (Port + 1),
    376              NULL,
    377              0
    378              );
    379 
    380   return Status;
    381 }
    382 
    383 
    384 /**
    385   Usb hub control transfer to set the hub feature.
    386 
    387   @param  HubDev                The hub device.
    388   @param  Feature               The feature to set.
    389 
    390   @retval EFI_SUCESS            The feature is set for the hub.
    391   @retval Others                Failed to set the feature.
    392 
    393 **/
    394 EFI_STATUS
    395 UsbHubCtrlSetHubFeature (
    396   IN  USB_DEVICE          *HubDev,
    397   IN  UINT8               Feature
    398   )
    399 {
    400   EFI_STATUS              Status;
    401 
    402   Status = UsbCtrlRequest (
    403              HubDev,
    404              EfiUsbNoData,
    405              USB_REQ_TYPE_CLASS,
    406              USB_HUB_TARGET_HUB,
    407              USB_HUB_REQ_SET_FEATURE,
    408              Feature,
    409              0,
    410              NULL,
    411              0
    412              );
    413 
    414   return Status;
    415 }
    416 
    417 
    418 /**
    419   Usb hub control transfer to set the port feature.
    420 
    421   @param  HubDev                The Usb hub device.
    422   @param  Port                  The Usb port to set feature for.
    423   @param  Feature               The feature to set.
    424 
    425   @retval EFI_SUCCESS           The feature is set for the port.
    426   @retval Others                Failed to set the feature.
    427 
    428 **/
    429 EFI_STATUS
    430 UsbHubCtrlSetPortFeature (
    431   IN USB_DEVICE           *HubDev,
    432   IN UINT8                Port,
    433   IN UINT8                Feature
    434   )
    435 {
    436   EFI_STATUS              Status;
    437 
    438   //
    439   // In USB bus, all the port index starts from 0. But HUB
    440   // indexes its port from 1. So, port number is added one.
    441   //
    442   Status = UsbCtrlRequest (
    443              HubDev,
    444              EfiUsbNoData,
    445              USB_REQ_TYPE_CLASS,
    446              USB_HUB_TARGET_PORT,
    447              USB_HUB_REQ_SET_FEATURE,
    448              Feature,
    449              (UINT16) (Port + 1),
    450              NULL,
    451              0
    452              );
    453 
    454   return Status;
    455 }
    456 
    457 
    458 /**
    459   Read the whole usb hub descriptor. It is necessary
    460   to do it in two steps because hub descriptor is of
    461   variable length.
    462 
    463   @param  HubDev                The hub device.
    464   @param  HubDesc               The variable to return the descriptor.
    465 
    466   @retval EFI_SUCCESS           The hub descriptor is read.
    467   @retval Others                Failed to read the hub descriptor.
    468 
    469 **/
    470 EFI_STATUS
    471 UsbHubReadDesc (
    472   IN  USB_DEVICE              *HubDev,
    473   OUT EFI_USB_HUB_DESCRIPTOR  *HubDesc
    474   )
    475 {
    476   EFI_STATUS              Status;
    477 
    478   if (HubDev->Speed == EFI_USB_SPEED_SUPER) {
    479     //
    480     // Get the super speed hub descriptor
    481     //
    482     Status = UsbHubCtrlGetSuperSpeedHubDesc (HubDev, HubDesc);
    483   } else {
    484 
    485     //
    486     // First get the hub descriptor length
    487     //
    488     Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);
    489 
    490     if (EFI_ERROR (Status)) {
    491       return Status;
    492     }
    493 
    494     //
    495     // Get the whole hub descriptor
    496     //
    497     Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);
    498   }
    499 
    500   return Status;
    501 }
    502 
    503 
    504 
    505 /**
    506   Ack the hub change bits. If these bits are not ACKed, Hub will
    507   always return changed bit map from its interrupt endpoint.
    508 
    509   @param  HubDev                The hub device.
    510 
    511   @retval EFI_SUCCESS           The hub change status is ACKed.
    512   @retval Others                Failed to ACK the hub status.
    513 
    514 **/
    515 EFI_STATUS
    516 UsbHubAckHubStatus (
    517   IN  USB_DEVICE         *HubDev
    518   )
    519 {
    520   EFI_USB_PORT_STATUS     HubState;
    521   EFI_STATUS              Status;
    522 
    523   Status = UsbHubCtrlGetHubStatus (HubDev, (UINT32 *) &HubState);
    524 
    525   if (EFI_ERROR (Status)) {
    526     return Status;
    527   }
    528 
    529   if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_LOCAL_POWER)) {
    530     UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_LOCAL_POWER);
    531   }
    532 
    533   if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_OVER_CURRENT)) {
    534     UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_OVER_CURRENT);
    535   }
    536 
    537   return EFI_SUCCESS;
    538 }
    539 
    540 
    541 /**
    542   Test whether the interface is a hub interface.
    543 
    544   @param  UsbIf                 The interface to test.
    545 
    546   @retval TRUE                  The interface is a hub interface.
    547   @retval FALSE                 The interface isn't a hub interface.
    548 
    549 **/
    550 BOOLEAN
    551 UsbIsHubInterface (
    552   IN USB_INTERFACE        *UsbIf
    553   )
    554 {
    555   EFI_USB_INTERFACE_DESCRIPTOR  *Setting;
    556 
    557   //
    558   // If the hub is a high-speed hub with multiple TT,
    559   // the hub will has a default setting of single TT.
    560   //
    561   Setting = &UsbIf->IfSetting->Desc;
    562 
    563   if ((Setting->InterfaceClass == USB_HUB_CLASS_CODE) &&
    564       (Setting->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {
    565 
    566     return TRUE;
    567   }
    568 
    569   return FALSE;
    570 }
    571 
    572 
    573 /**
    574   The callback function to the USB hub status change
    575   interrupt endpoint. It is called periodically by
    576   the underlying host controller.
    577 
    578   @param  Data                  The data read.
    579   @param  DataLength            The length of the data read.
    580   @param  Context               The context.
    581   @param  Result                The result of the last interrupt transfer.
    582 
    583   @retval EFI_SUCCESS           The process is OK.
    584   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource.
    585 
    586 **/
    587 EFI_STATUS
    588 EFIAPI
    589 UsbOnHubInterrupt (
    590   IN  VOID                *Data,
    591   IN  UINTN               DataLength,
    592   IN  VOID                *Context,
    593   IN  UINT32              Result
    594   )
    595 {
    596   USB_INTERFACE               *HubIf;
    597   EFI_USB_IO_PROTOCOL         *UsbIo;
    598   EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc;
    599   EFI_STATUS                  Status;
    600 
    601   HubIf   = (USB_INTERFACE *) Context;
    602   UsbIo   = &(HubIf->UsbIo);
    603   EpDesc  = &(HubIf->HubEp->Desc);
    604 
    605   if (Result != EFI_USB_NOERROR) {
    606     //
    607     // If endpoint is stalled, clear the stall. Use UsbIo to access
    608     // the control transfer so internal status are maintained.
    609     //
    610     if (USB_BIT_IS_SET (Result, EFI_USB_ERR_STALL)) {
    611       UsbIoClearFeature (
    612         UsbIo,
    613         USB_TARGET_ENDPOINT,
    614         USB_FEATURE_ENDPOINT_HALT,
    615         EpDesc->EndpointAddress
    616         );
    617     }
    618 
    619     //
    620     // Delete and submit a new async interrupt
    621     //
    622     Status = UsbIo->UsbAsyncInterruptTransfer (
    623                       UsbIo,
    624                       EpDesc->EndpointAddress,
    625                       FALSE,
    626                       0,
    627                       0,
    628                       NULL,
    629                       NULL
    630                       );
    631 
    632     if (EFI_ERROR (Status)) {
    633       DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to remove async transfer - %r\n", Status));
    634       return Status;
    635     }
    636 
    637     Status = UsbIo->UsbAsyncInterruptTransfer (
    638                       UsbIo,
    639                       EpDesc->EndpointAddress,
    640                       TRUE,
    641                       USB_HUB_POLL_INTERVAL,
    642                       HubIf->NumOfPort / 8 + 1,
    643                       UsbOnHubInterrupt,
    644                       HubIf
    645                       );
    646 
    647     if (EFI_ERROR (Status)) {
    648       DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to submit new async transfer - %r\n", Status));
    649     }
    650 
    651     return Status;
    652   }
    653 
    654   if ((DataLength == 0) || (Data == NULL)) {
    655     return EFI_SUCCESS;
    656   }
    657 
    658   //
    659   // OK, actually something is changed, save the change map
    660   // then signal the HUB to do enumeration. This is a good
    661   // practise since UsbOnHubInterrupt is called in the context
    662   // of host contrller's AsyncInterrupt monitor.
    663   //
    664   HubIf->ChangeMap = AllocateZeroPool (DataLength);
    665 
    666   if (HubIf->ChangeMap == NULL) {
    667     return EFI_OUT_OF_RESOURCES;
    668   }
    669 
    670   CopyMem (HubIf->ChangeMap, Data, DataLength);
    671   gBS->SignalEvent (HubIf->HubNotify);
    672 
    673   return EFI_SUCCESS;
    674 }
    675 
    676 
    677 
    678 
    679 /**
    680   Initialize the device for a non-root hub.
    681 
    682   @param  HubIf                 The USB hub interface.
    683 
    684   @retval EFI_SUCCESS           The hub is initialized.
    685   @retval EFI_DEVICE_ERROR      Failed to initialize the hub.
    686 
    687 **/
    688 EFI_STATUS
    689 UsbHubInit (
    690   IN USB_INTERFACE        *HubIf
    691   )
    692 {
    693   EFI_USB_HUB_DESCRIPTOR  HubDesc;
    694   USB_ENDPOINT_DESC       *EpDesc;
    695   USB_INTERFACE_SETTING   *Setting;
    696   EFI_USB_IO_PROTOCOL     *UsbIo;
    697   USB_DEVICE              *HubDev;
    698   EFI_STATUS              Status;
    699   UINT8                   Index;
    700   UINT8                   NumEndpoints;
    701   UINT16                  Depth;
    702 
    703   //
    704   // Locate the interrupt endpoint for port change map
    705   //
    706   HubIf->IsHub  = FALSE;
    707   Setting       = HubIf->IfSetting;
    708   HubDev        = HubIf->Device;
    709   EpDesc        = NULL;
    710   NumEndpoints  = Setting->Desc.NumEndpoints;
    711 
    712   for (Index = 0; Index < NumEndpoints; Index++) {
    713     ASSERT ((Setting->Endpoints != NULL) && (Setting->Endpoints[Index] != NULL));
    714 
    715     EpDesc = Setting->Endpoints[Index];
    716 
    717     if (USB_BIT_IS_SET (EpDesc->Desc.EndpointAddress, USB_ENDPOINT_DIR_IN) &&
    718        (USB_ENDPOINT_TYPE (&EpDesc->Desc) == USB_ENDPOINT_INTERRUPT)) {
    719       break;
    720     }
    721   }
    722 
    723   if (Index == NumEndpoints) {
    724     DEBUG (( EFI_D_ERROR, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev->Address));
    725     return EFI_DEVICE_ERROR;
    726   }
    727 
    728   Status = UsbHubReadDesc (HubDev, &HubDesc);
    729 
    730   if (EFI_ERROR (Status)) {
    731     DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status));
    732     return Status;
    733   }
    734 
    735   HubIf->NumOfPort = HubDesc.NumPorts;
    736 
    737   DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort));
    738 
    739   //
    740   // OK, set IsHub to TRUE. Now usb bus can handle this device
    741   // as a working HUB. If failed eariler, bus driver will not
    742   // recognize it as a hub. Other parts of the bus should be able
    743   // to work.
    744   //
    745   HubIf->IsHub  = TRUE;
    746   HubIf->HubApi = &mUsbHubApi;
    747   HubIf->HubEp  = EpDesc;
    748 
    749   if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {
    750     Depth = (UINT16)(HubIf->Device->Tier - 1);
    751     DEBUG ((EFI_D_INFO, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth));
    752     UsbHubCtrlSetHubDepth (HubIf->Device, Depth);
    753 
    754     for (Index = 0; Index < HubDesc.NumPorts; Index++) {
    755       UsbHubCtrlSetPortFeature (HubIf->Device, Index, USB_HUB_PORT_REMOTE_WAKE_MASK);
    756     }
    757   } else {
    758     //
    759     // Feed power to all the hub ports. It should be ok
    760     // for both gang/individual powered hubs.
    761     //
    762     for (Index = 0; Index < HubDesc.NumPorts; Index++) {
    763       UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);
    764     }
    765 
    766     //
    767     // Update for the usb hub has no power on delay requirement
    768     //
    769     if (HubDesc.PwrOn2PwrGood > 0) {
    770       gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
    771     }
    772     UsbHubAckHubStatus (HubIf->Device);
    773   }
    774 
    775   //
    776   // Create an event to enumerate the hub's port. On
    777   //
    778   Status = gBS->CreateEvent (
    779                   EVT_NOTIFY_SIGNAL,
    780                   TPL_CALLBACK,
    781                   UsbHubEnumeration,
    782                   HubIf,
    783                   &HubIf->HubNotify
    784                   );
    785 
    786   if (EFI_ERROR (Status)) {
    787     DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to create signal for hub %d - %r\n",
    788                 HubDev->Address, Status));
    789 
    790     return Status;
    791   }
    792 
    793   //
    794   // Create AsyncInterrupt to query hub port change endpoint
    795   // periodically. If the hub ports are changed, hub will return
    796   // changed port map from the interrupt endpoint. The port map
    797   // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for
    798   // host change status).
    799   //
    800   UsbIo  = &HubIf->UsbIo;
    801   Status = UsbIo->UsbAsyncInterruptTransfer (
    802                     UsbIo,
    803                     EpDesc->Desc.EndpointAddress,
    804                     TRUE,
    805                     USB_HUB_POLL_INTERVAL,
    806                     HubIf->NumOfPort / 8 + 1,
    807                     UsbOnHubInterrupt,
    808                     HubIf
    809                     );
    810 
    811   if (EFI_ERROR (Status)) {
    812     DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n",
    813                 HubDev->Address, Status));
    814 
    815     gBS->CloseEvent (HubIf->HubNotify);
    816     HubIf->HubNotify = NULL;
    817 
    818     return Status;
    819   }
    820 
    821   DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address));
    822   return Status;
    823 }
    824 
    825 
    826 
    827 /**
    828   Get the port status. This function is required to
    829   ACK the port change bits although it will return
    830   the port changes in PortState. Bus enumeration code
    831   doesn't need to ACK the port change bits.
    832 
    833   @param  HubIf                 The hub interface.
    834   @param  Port                  The port of the hub to get state.
    835   @param  PortState             Variable to return the port state.
    836 
    837   @retval EFI_SUCCESS           The port status is successfully returned.
    838   @retval Others                Failed to return the status.
    839 
    840 **/
    841 EFI_STATUS
    842 UsbHubGetPortStatus (
    843   IN  USB_INTERFACE       *HubIf,
    844   IN  UINT8               Port,
    845   OUT EFI_USB_PORT_STATUS *PortState
    846   )
    847 {
    848   EFI_STATUS              Status;
    849 
    850   Status  = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);
    851 
    852   return Status;
    853 }
    854 
    855 
    856 
    857 /**
    858   Clear the port change status.
    859 
    860   @param  HubIf                 The hub interface.
    861   @param  Port                  The hub port.
    862 
    863 **/
    864 VOID
    865 UsbHubClearPortChange (
    866   IN USB_INTERFACE        *HubIf,
    867   IN UINT8                Port
    868   )
    869 {
    870   EFI_USB_PORT_STATUS     PortState;
    871   USB_CHANGE_FEATURE_MAP  *Map;
    872   UINTN                   Index;
    873   EFI_STATUS              Status;
    874 
    875   Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
    876 
    877   if (EFI_ERROR (Status)) {
    878     return;
    879   }
    880 
    881   //
    882   // OK, get the usb port status, now ACK the change bits.
    883   // Don't return error when failed to clear the change bits.
    884   // It may lead to extra port state report. USB bus should
    885   // be able to handle this.
    886   //
    887   for (Index = 0; Index < sizeof (mHubFeatureMap) / sizeof (mHubFeatureMap[0]); Index++) {
    888     Map = &mHubFeatureMap[Index];
    889 
    890     if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {
    891       UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT16) Map->Feature);
    892     }
    893   }
    894 }
    895 
    896 
    897 
    898 /**
    899   Function to set the port feature for non-root hub.
    900 
    901   @param  HubIf                 The hub interface.
    902   @param  Port                  The port of the hub.
    903   @param  Feature               The feature of the port to set.
    904 
    905   @retval EFI_SUCCESS           The hub port feature is set.
    906   @retval Others                Failed to set the port feature.
    907 
    908 **/
    909 EFI_STATUS
    910 UsbHubSetPortFeature (
    911   IN USB_INTERFACE        *HubIf,
    912   IN UINT8                Port,
    913   IN EFI_USB_PORT_FEATURE Feature
    914   )
    915 {
    916   EFI_STATUS              Status;
    917 
    918   Status = UsbHubCtrlSetPortFeature (HubIf->Device, Port, (UINT8) Feature);
    919 
    920   return Status;
    921 }
    922 
    923 
    924 /**
    925   Interface function to clear the port feature for non-root hub.
    926 
    927   @param  HubIf                 The hub interface.
    928   @param  Port                  The port of the hub to clear feature for.
    929   @param  Feature               The feature to clear.
    930 
    931   @retval EFI_SUCCESS           The port feature is cleared.
    932   @retval Others                Failed to clear the port feature.
    933 
    934 **/
    935 EFI_STATUS
    936 UsbHubClearPortFeature (
    937   IN USB_INTERFACE        *HubIf,
    938   IN UINT8                Port,
    939   IN EFI_USB_PORT_FEATURE Feature
    940   )
    941 {
    942   EFI_STATUS              Status;
    943 
    944   Status = UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT8) Feature);
    945 
    946   return Status;
    947 }
    948 
    949 
    950 /**
    951   Interface function to reset the port.
    952 
    953   @param  HubIf                 The hub interface.
    954   @param  Port                  The port to reset.
    955 
    956   @retval EFI_SUCCESS           The hub port is reset.
    957   @retval EFI_TIMEOUT           Failed to reset the port in time.
    958   @retval Others                Failed to reset the port.
    959 
    960 **/
    961 EFI_STATUS
    962 UsbHubResetPort (
    963   IN USB_INTERFACE        *HubIf,
    964   IN UINT8                Port
    965   )
    966 {
    967   EFI_USB_PORT_STATUS     PortState;
    968   UINTN                   Index;
    969   EFI_STATUS              Status;
    970 
    971   Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
    972 
    973   if (EFI_ERROR (Status)) {
    974     return Status;
    975   } else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
    976     DEBUG (( EFI_D_INFO, "UsbHubResetPort: skip reset on hub %p port %d\n", HubIf, Port));
    977     return EFI_SUCCESS;
    978   }
    979 
    980   Status  = UsbHubSetPortFeature (HubIf, Port, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_RESET);
    981 
    982   if (EFI_ERROR (Status)) {
    983     return Status;
    984   }
    985 
    986   //
    987   // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
    988   // section 7.1.7.5 for timing requirements.
    989   //
    990   gBS->Stall (USB_SET_PORT_RESET_STALL);
    991 
    992   //
    993   // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
    994   //
    995   ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));
    996 
    997   for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
    998     Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
    999 
   1000     if (EFI_ERROR (Status)) {
   1001       return Status;
   1002     }
   1003 
   1004     if (!EFI_ERROR (Status) &&
   1005         USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
   1006       gBS->Stall (USB_SET_PORT_RECOVERY_STALL);
   1007       return EFI_SUCCESS;
   1008     }
   1009 
   1010     gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
   1011   }
   1012 
   1013   return EFI_TIMEOUT;
   1014 }
   1015 
   1016 
   1017 /**
   1018   Release the hub's control of the interface.
   1019 
   1020   @param  HubIf                 The hub interface.
   1021 
   1022   @retval EFI_SUCCESS           The interface is release of hub control.
   1023 
   1024 **/
   1025 EFI_STATUS
   1026 UsbHubRelease (
   1027   IN USB_INTERFACE        *HubIf
   1028   )
   1029 {
   1030   EFI_USB_IO_PROTOCOL     *UsbIo;
   1031   EFI_STATUS              Status;
   1032 
   1033   UsbIo  = &HubIf->UsbIo;
   1034   Status = UsbIo->UsbAsyncInterruptTransfer (
   1035                     UsbIo,
   1036                     HubIf->HubEp->Desc.EndpointAddress,
   1037                     FALSE,
   1038                     USB_HUB_POLL_INTERVAL,
   1039                     0,
   1040                     NULL,
   1041                     0
   1042                     );
   1043 
   1044   if (EFI_ERROR (Status)) {
   1045     return Status;
   1046   }
   1047 
   1048   gBS->CloseEvent (HubIf->HubNotify);
   1049 
   1050   HubIf->IsHub      = FALSE;
   1051   HubIf->HubApi     = NULL;
   1052   HubIf->HubEp      = NULL;
   1053   HubIf->HubNotify  = NULL;
   1054 
   1055   DEBUG (( EFI_D_INFO, "UsbHubRelease: hub device %d released\n", HubIf->Device->Address));
   1056   return EFI_SUCCESS;
   1057 }
   1058 
   1059 
   1060 
   1061 /**
   1062   Initialize the interface for root hub.
   1063 
   1064   @param  HubIf                 The root hub interface.
   1065 
   1066   @retval EFI_SUCCESS           The interface is initialized for root hub.
   1067   @retval Others                Failed to initialize the hub.
   1068 
   1069 **/
   1070 EFI_STATUS
   1071 UsbRootHubInit (
   1072   IN USB_INTERFACE        *HubIf
   1073   )
   1074 {
   1075   EFI_STATUS              Status;
   1076   UINT8                   MaxSpeed;
   1077   UINT8                   NumOfPort;
   1078   UINT8                   Support64;
   1079 
   1080   Status = UsbHcGetCapability (HubIf->Device->Bus, &MaxSpeed, &NumOfPort, &Support64);
   1081 
   1082   if (EFI_ERROR (Status)) {
   1083     return Status;
   1084   }
   1085 
   1086   DEBUG (( EFI_D_INFO, "UsbRootHubInit: root hub %p - max speed %d, %d ports\n",
   1087               HubIf, MaxSpeed, NumOfPort));
   1088 
   1089   HubIf->IsHub      = TRUE;
   1090   HubIf->HubApi     = &mUsbRootHubApi;
   1091   HubIf->HubEp      = NULL;
   1092   HubIf->MaxSpeed   = MaxSpeed;
   1093   HubIf->NumOfPort  = NumOfPort;
   1094   HubIf->HubNotify  = NULL;
   1095 
   1096   //
   1097   // Create a timer to poll root hub ports periodically
   1098   //
   1099   Status = gBS->CreateEvent (
   1100                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
   1101                   TPL_CALLBACK,
   1102                   UsbRootHubEnumeration,
   1103                   HubIf,
   1104                   &HubIf->HubNotify
   1105                   );
   1106 
   1107   if (EFI_ERROR (Status)) {
   1108     return Status;
   1109   }
   1110 
   1111   //
   1112   // It should signal the event immediately here, or device detection
   1113   // by bus enumeration might be delayed by the timer interval.
   1114   //
   1115   gBS->SignalEvent (HubIf->HubNotify);
   1116 
   1117   Status = gBS->SetTimer (
   1118                   HubIf->HubNotify,
   1119                   TimerPeriodic,
   1120                   USB_ROOTHUB_POLL_INTERVAL
   1121                   );
   1122 
   1123   if (EFI_ERROR (Status)) {
   1124     gBS->CloseEvent (HubIf->HubNotify);
   1125   }
   1126 
   1127   return Status;
   1128 }
   1129 
   1130 
   1131 /**
   1132   Get the port status. This function is required to
   1133   ACK the port change bits although it will return
   1134   the port changes in PortState. Bus enumeration code
   1135   doesn't need to ACK the port change bits.
   1136 
   1137   @param  HubIf                 The root hub interface.
   1138   @param  Port                  The root hub port to get the state.
   1139   @param  PortState             Variable to return the port state.
   1140 
   1141   @retval EFI_SUCCESS           The port state is returned.
   1142   @retval Others                Failed to retrieve the port state.
   1143 
   1144 **/
   1145 EFI_STATUS
   1146 UsbRootHubGetPortStatus (
   1147   IN  USB_INTERFACE       *HubIf,
   1148   IN  UINT8               Port,
   1149   OUT EFI_USB_PORT_STATUS *PortState
   1150   )
   1151 {
   1152   USB_BUS                 *Bus;
   1153   EFI_STATUS              Status;
   1154 
   1155   Bus     = HubIf->Device->Bus;
   1156   Status  = UsbHcGetRootHubPortStatus (Bus, Port, PortState);
   1157 
   1158   return Status;
   1159 }
   1160 
   1161 
   1162 /**
   1163   Clear the port change status.
   1164 
   1165   @param  HubIf                 The root hub interface.
   1166   @param  Port                  The root hub port.
   1167 
   1168 **/
   1169 VOID
   1170 UsbRootHubClearPortChange (
   1171   IN USB_INTERFACE        *HubIf,
   1172   IN UINT8                Port
   1173   )
   1174 {
   1175   EFI_USB_PORT_STATUS     PortState;
   1176   USB_CHANGE_FEATURE_MAP  *Map;
   1177   UINTN                   Index;
   1178   EFI_STATUS              Status;
   1179 
   1180   Status = UsbRootHubGetPortStatus (HubIf, Port, &PortState);
   1181 
   1182   if (EFI_ERROR (Status)) {
   1183     return;
   1184   }
   1185 
   1186   //
   1187   // OK, get the usb port status, now ACK the change bits.
   1188   // Don't return error when failed to clear the change bits.
   1189   // It may lead to extra port state report. USB bus should
   1190   // be able to handle this.
   1191   //
   1192   for (Index = 0; Index < sizeof (mRootHubFeatureMap) / sizeof (mRootHubFeatureMap[0]); Index++) {
   1193     Map = &mRootHubFeatureMap[Index];
   1194 
   1195     if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {
   1196       UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, (EFI_USB_PORT_FEATURE) Map->Feature);
   1197     }
   1198   }
   1199 }
   1200 
   1201 
   1202 /**
   1203   Set the root hub port feature.
   1204 
   1205   @param  HubIf                 The Usb hub interface.
   1206   @param  Port                  The hub port.
   1207   @param  Feature               The feature to set.
   1208 
   1209   @retval EFI_SUCCESS           The root hub port is set with the feature.
   1210   @retval Others                Failed to set the feature.
   1211 
   1212 **/
   1213 EFI_STATUS
   1214 UsbRootHubSetPortFeature (
   1215   IN USB_INTERFACE        *HubIf,
   1216   IN UINT8                Port,
   1217   IN EFI_USB_PORT_FEATURE Feature
   1218   )
   1219 {
   1220   EFI_STATUS              Status;
   1221 
   1222   Status  = UsbHcSetRootHubPortFeature (HubIf->Device->Bus, Port, Feature);
   1223 
   1224   return Status;
   1225 }
   1226 
   1227 
   1228 /**
   1229   Clear the root hub port feature.
   1230 
   1231   @param  HubIf                 The root hub interface.
   1232   @param  Port                  The root hub port.
   1233   @param  Feature               The feature to clear.
   1234 
   1235   @retval EFI_SUCCESS           The root hub port is cleared of the feature.
   1236   @retval Others                Failed to clear the feature.
   1237 
   1238 **/
   1239 EFI_STATUS
   1240 UsbRootHubClearPortFeature (
   1241   IN USB_INTERFACE        *HubIf,
   1242   IN UINT8                Port,
   1243   IN EFI_USB_PORT_FEATURE Feature
   1244   )
   1245 {
   1246   EFI_STATUS              Status;
   1247 
   1248   Status  = UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, Feature);
   1249 
   1250   return Status;
   1251 }
   1252 
   1253 
   1254 /**
   1255   Interface function to reset the root hub port.
   1256 
   1257   @param  RootIf                The root hub interface.
   1258   @param  Port                  The port to reset.
   1259 
   1260   @retval EFI_SUCCESS           The hub port is reset.
   1261   @retval EFI_TIMEOUT           Failed to reset the port in time.
   1262   @retval EFI_NOT_FOUND         The low/full speed device connected to high  speed.
   1263                                 root hub is released to the companion UHCI.
   1264   @retval Others                Failed to reset the port.
   1265 
   1266 **/
   1267 EFI_STATUS
   1268 UsbRootHubResetPort (
   1269   IN USB_INTERFACE        *RootIf,
   1270   IN UINT8                Port
   1271   )
   1272 {
   1273   USB_BUS                 *Bus;
   1274   EFI_STATUS              Status;
   1275   EFI_USB_PORT_STATUS     PortState;
   1276   UINTN                   Index;
   1277 
   1278   //
   1279   // Notice: although EHCI requires that ENABLED bit be cleared
   1280   // when reset the port, we don't need to care that here. It
   1281   // should be handled in the EHCI driver.
   1282   //
   1283   Bus     = RootIf->Device->Bus;
   1284 
   1285   Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);
   1286 
   1287   if (EFI_ERROR (Status)) {
   1288     return Status;
   1289   } else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
   1290     DEBUG (( EFI_D_INFO, "UsbRootHubResetPort: skip reset on root port %d\n", Port));
   1291     return EFI_SUCCESS;
   1292   }
   1293 
   1294   Status  = UsbHcSetRootHubPortFeature (Bus, Port, EfiUsbPortReset);
   1295 
   1296   if (EFI_ERROR (Status)) {
   1297     DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to start reset on port %d\n", Port));
   1298     return Status;
   1299   }
   1300 
   1301   //
   1302   // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
   1303   // section 7.1.7.5 for timing requirements.
   1304   //
   1305   gBS->Stall (USB_SET_ROOT_PORT_RESET_STALL);
   1306 
   1307   Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset);
   1308 
   1309   if (EFI_ERROR (Status)) {
   1310     DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to clear reset on port %d\n", Port));
   1311     return Status;
   1312   }
   1313 
   1314   gBS->Stall (USB_CLR_ROOT_PORT_RESET_STALL);
   1315 
   1316   //
   1317   // USB host controller won't clear the RESET bit until
   1318   // reset is actually finished.
   1319   //
   1320   ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));
   1321 
   1322   for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
   1323     Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);
   1324 
   1325     if (EFI_ERROR (Status)) {
   1326       return Status;
   1327     }
   1328 
   1329     if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {
   1330       break;
   1331     }
   1332 
   1333     gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
   1334   }
   1335 
   1336   if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
   1337     DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port));
   1338     return EFI_TIMEOUT;
   1339   }
   1340 
   1341   if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_ENABLE)) {
   1342     //
   1343     // OK, the port is reset. If root hub is of high speed and
   1344     // the device is of low/full speed, release the ownership to
   1345     // companion UHCI. If root hub is of full speed, it won't
   1346     // automatically enable the port, we need to enable it manually.
   1347     //
   1348     if (RootIf->MaxSpeed == EFI_USB_SPEED_HIGH) {
   1349       DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: release low/full speed device (%d) to UHCI\n", Port));
   1350 
   1351       UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortOwner);
   1352       return EFI_NOT_FOUND;
   1353 
   1354     } else {
   1355 
   1356       Status = UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortEnable);
   1357 
   1358       if (EFI_ERROR (Status)) {
   1359         DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to enable port %d for UHCI\n", Port));
   1360         return Status;
   1361       }
   1362 
   1363       gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL);
   1364     }
   1365   }
   1366 
   1367   return EFI_SUCCESS;
   1368 }
   1369 
   1370 
   1371 /**
   1372   Release the root hub's control of the interface.
   1373 
   1374   @param  HubIf                 The root hub interface.
   1375 
   1376   @retval EFI_SUCCESS           The root hub's control of the interface is
   1377                                 released.
   1378 
   1379 **/
   1380 EFI_STATUS
   1381 UsbRootHubRelease (
   1382   IN USB_INTERFACE        *HubIf
   1383   )
   1384 {
   1385   DEBUG (( EFI_D_INFO, "UsbRootHubRelease: root hub released for hub %p\n", HubIf));
   1386 
   1387   gBS->SetTimer (HubIf->HubNotify, TimerCancel, USB_ROOTHUB_POLL_INTERVAL);
   1388   gBS->CloseEvent (HubIf->HubNotify);
   1389 
   1390   return EFI_SUCCESS;
   1391 }
   1392 
   1393 USB_HUB_API mUsbHubApi = {
   1394   UsbHubInit,
   1395   UsbHubGetPortStatus,
   1396   UsbHubClearPortChange,
   1397   UsbHubSetPortFeature,
   1398   UsbHubClearPortFeature,
   1399   UsbHubResetPort,
   1400   UsbHubRelease
   1401 };
   1402 
   1403 USB_HUB_API mUsbRootHubApi = {
   1404   UsbRootHubInit,
   1405   UsbRootHubGetPortStatus,
   1406   UsbRootHubClearPortChange,
   1407   UsbRootHubSetPortFeature,
   1408   UsbRootHubClearPortFeature,
   1409   UsbRootHubResetPort,
   1410   UsbRootHubRelease
   1411 };
   1412