Home | History | Annotate | Download | only in UsbBusDxe
      1 /** @file
      2 
      3     Usb bus enumeration support.
      4 
      5 Copyright (c) 2007 - 2014, 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   Return the endpoint descriptor in this interface.
     20 
     21   @param  UsbIf                 The interface to search in.
     22   @param  EpAddr                The address of the endpoint to return.
     23 
     24   @return The endpoint descriptor or NULL.
     25 
     26 **/
     27 USB_ENDPOINT_DESC *
     28 UsbGetEndpointDesc (
     29   IN USB_INTERFACE        *UsbIf,
     30   IN UINT8                EpAddr
     31   )
     32 {
     33   USB_ENDPOINT_DESC       *EpDesc;
     34   UINT8                   Index;
     35   UINT8                   NumEndpoints;
     36 
     37   NumEndpoints = UsbIf->IfSetting->Desc.NumEndpoints;
     38 
     39   for (Index = 0; Index < NumEndpoints; Index++) {
     40     EpDesc = UsbIf->IfSetting->Endpoints[Index];
     41 
     42     if (EpDesc->Desc.EndpointAddress == EpAddr) {
     43       return EpDesc;
     44     }
     45   }
     46 
     47   return NULL;
     48 }
     49 
     50 
     51 /**
     52   Free the resource used by USB interface.
     53 
     54   @param  UsbIf                 The USB interface to free.
     55 
     56 **/
     57 VOID
     58 UsbFreeInterface (
     59   IN USB_INTERFACE        *UsbIf
     60   )
     61 {
     62   UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
     63 
     64   gBS->UninstallMultipleProtocolInterfaces (
     65          UsbIf->Handle,
     66          &gEfiDevicePathProtocolGuid,
     67          UsbIf->DevicePath,
     68          &gEfiUsbIoProtocolGuid,
     69          &UsbIf->UsbIo,
     70          NULL
     71          );
     72 
     73   if (UsbIf->DevicePath != NULL) {
     74     FreePool (UsbIf->DevicePath);
     75   }
     76 
     77   FreePool (UsbIf);
     78 }
     79 
     80 
     81 /**
     82   Create an interface for the descriptor IfDesc. Each
     83   device's configuration can have several interfaces.
     84 
     85   @param  Device                The device has the interface descriptor.
     86   @param  IfDesc                The interface descriptor.
     87 
     88   @return The created USB interface for the descriptor, or NULL.
     89 
     90 **/
     91 USB_INTERFACE *
     92 UsbCreateInterface (
     93   IN USB_DEVICE           *Device,
     94   IN USB_INTERFACE_DESC   *IfDesc
     95   )
     96 {
     97   USB_DEVICE_PATH         UsbNode;
     98   USB_INTERFACE           *UsbIf;
     99   USB_INTERFACE           *HubIf;
    100   EFI_STATUS              Status;
    101 
    102   UsbIf = AllocateZeroPool (sizeof (USB_INTERFACE));
    103 
    104   if (UsbIf == NULL) {
    105     return NULL;
    106   }
    107 
    108   UsbIf->Signature  = USB_INTERFACE_SIGNATURE;
    109   UsbIf->Device     = Device;
    110   UsbIf->IfDesc     = IfDesc;
    111   ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);
    112   UsbIf->IfSetting  = IfDesc->Settings[IfDesc->ActiveIndex];
    113 
    114   CopyMem (
    115     &(UsbIf->UsbIo),
    116     &mUsbIoProtocol,
    117     sizeof (EFI_USB_IO_PROTOCOL)
    118     );
    119 
    120   //
    121   // Install protocols for USBIO and device path
    122   //
    123   UsbNode.Header.Type       = MESSAGING_DEVICE_PATH;
    124   UsbNode.Header.SubType    = MSG_USB_DP;
    125   UsbNode.ParentPortNumber  = Device->ParentPort;
    126   UsbNode.InterfaceNumber   = UsbIf->IfSetting->Desc.InterfaceNumber;
    127 
    128   SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
    129 
    130   HubIf = Device->ParentIf;
    131   ASSERT (HubIf != NULL);
    132 
    133   UsbIf->DevicePath = AppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header);
    134 
    135   if (UsbIf->DevicePath == NULL) {
    136     DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to create device path\n"));
    137 
    138     Status = EFI_OUT_OF_RESOURCES;
    139     goto ON_ERROR;
    140   }
    141 
    142   Status = gBS->InstallMultipleProtocolInterfaces (
    143                   &UsbIf->Handle,
    144                   &gEfiDevicePathProtocolGuid,
    145                   UsbIf->DevicePath,
    146                   &gEfiUsbIoProtocolGuid,
    147                   &UsbIf->UsbIo,
    148                   NULL
    149                   );
    150 
    151   if (EFI_ERROR (Status)) {
    152     DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to install UsbIo - %r\n", Status));
    153     goto ON_ERROR;
    154   }
    155 
    156   //
    157   // Open USB Host Controller Protocol by Child
    158   //
    159   Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);
    160 
    161   if (EFI_ERROR (Status)) {
    162     gBS->UninstallMultipleProtocolInterfaces (
    163            &UsbIf->Handle,
    164            &gEfiDevicePathProtocolGuid,
    165            UsbIf->DevicePath,
    166            &gEfiUsbIoProtocolGuid,
    167            &UsbIf->UsbIo,
    168            NULL
    169            );
    170 
    171     DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to open host for child - %r\n", Status));
    172     goto ON_ERROR;
    173   }
    174 
    175   return UsbIf;
    176 
    177 ON_ERROR:
    178   if (UsbIf->DevicePath != NULL) {
    179     FreePool (UsbIf->DevicePath);
    180   }
    181 
    182   FreePool (UsbIf);
    183   return NULL;
    184 }
    185 
    186 
    187 /**
    188   Free the resource used by this USB device.
    189 
    190   @param  Device                The USB device to free.
    191 
    192 **/
    193 VOID
    194 UsbFreeDevice (
    195   IN USB_DEVICE           *Device
    196   )
    197 {
    198   if (Device->DevDesc != NULL) {
    199     UsbFreeDevDesc (Device->DevDesc);
    200   }
    201 
    202   gBS->FreePool (Device);
    203 }
    204 
    205 
    206 /**
    207   Create a device which is on the parent's ParentPort port.
    208 
    209   @param  ParentIf              The parent HUB interface.
    210   @param  ParentPort            The port on the HUB this device is connected to.
    211 
    212   @return Created USB device, Or NULL.
    213 
    214 **/
    215 USB_DEVICE *
    216 UsbCreateDevice (
    217   IN USB_INTERFACE        *ParentIf,
    218   IN UINT8                ParentPort
    219   )
    220 {
    221   USB_DEVICE              *Device;
    222 
    223   ASSERT (ParentIf != NULL);
    224 
    225   Device = AllocateZeroPool (sizeof (USB_DEVICE));
    226 
    227   if (Device == NULL) {
    228     return NULL;
    229   }
    230 
    231   Device->Bus         = ParentIf->Device->Bus;
    232   Device->MaxPacket0  = 8;
    233   Device->ParentAddr  = ParentIf->Device->Address;
    234   Device->ParentIf    = ParentIf;
    235   Device->ParentPort  = ParentPort;
    236   Device->Tier        = (UINT8)(ParentIf->Device->Tier + 1);
    237   return Device;
    238 }
    239 
    240 
    241 /**
    242   Connect the USB interface with its driver. EFI USB bus will
    243   create a USB interface for each separate interface descriptor.
    244 
    245   @param  UsbIf             The interface to connect driver to.
    246 
    247   @return EFI_SUCCESS       Interface is managed by some driver.
    248   @return Others            Failed to locate a driver for this interface.
    249 
    250 **/
    251 EFI_STATUS
    252 UsbConnectDriver (
    253   IN USB_INTERFACE        *UsbIf
    254   )
    255 {
    256   EFI_STATUS              Status;
    257   EFI_TPL                 OldTpl;
    258 
    259   Status = EFI_SUCCESS;
    260 
    261   //
    262   // Hub is maintained by the USB bus driver. Otherwise try to
    263   // connect drivers with this interface
    264   //
    265   if (UsbIsHubInterface (UsbIf)) {
    266     DEBUG ((EFI_D_INFO, "UsbConnectDriver: found a hub device\n"));
    267     Status = mUsbHubApi.Init (UsbIf);
    268 
    269   } else {
    270     //
    271     // This function is called in both UsbIoControlTransfer and
    272     // the timer callback in hub enumeration. So, at least it is
    273     // called at TPL_CALLBACK. Some driver sitting on USB has
    274     // twisted TPL used. It should be no problem for us to connect
    275     // or disconnect at CALLBACK.
    276     //
    277 
    278     //
    279     // Only recursively wanted usb child device
    280     //
    281     if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {
    282       OldTpl            = UsbGetCurrentTpl ();
    283       DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
    284 
    285       gBS->RestoreTPL (TPL_CALLBACK);
    286 
    287       Status            = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
    288       UsbIf->IsManaged  = (BOOLEAN)!EFI_ERROR (Status);
    289 
    290       DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl()));
    291       ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
    292 
    293       gBS->RaiseTPL (OldTpl);
    294     }
    295   }
    296 
    297   return Status;
    298 }
    299 
    300 
    301 /**
    302   Select an alternate setting for the interface.
    303   Each interface can have several mutually exclusive
    304   settings. Only one setting is active. It will
    305   also reset its endpoints' toggle to zero.
    306 
    307   @param  IfDesc                The interface descriptor to set.
    308   @param  Alternate             The alternate setting number to locate.
    309 
    310   @retval EFI_NOT_FOUND         There is no setting with this alternate index.
    311   @retval EFI_SUCCESS           The interface is set to Alternate setting.
    312 
    313 **/
    314 EFI_STATUS
    315 UsbSelectSetting (
    316   IN USB_INTERFACE_DESC   *IfDesc,
    317   IN UINT8                Alternate
    318   )
    319 {
    320   USB_INTERFACE_SETTING   *Setting;
    321   UINTN                   Index;
    322 
    323   //
    324   // Locate the active alternate setting
    325   //
    326   Setting = NULL;
    327 
    328   for (Index = 0; Index < IfDesc->NumOfSetting; Index++) {
    329     ASSERT (Index < USB_MAX_INTERFACE_SETTING);
    330     Setting = IfDesc->Settings[Index];
    331 
    332     if (Setting->Desc.AlternateSetting == Alternate) {
    333       break;
    334     }
    335   }
    336 
    337   if (Index == IfDesc->NumOfSetting) {
    338     return EFI_NOT_FOUND;
    339   }
    340 
    341   IfDesc->ActiveIndex = Index;
    342 
    343   ASSERT (Setting != NULL);
    344   DEBUG ((EFI_D_INFO, "UsbSelectSetting: setting %d selected for interface %d\n",
    345               Alternate, Setting->Desc.InterfaceNumber));
    346 
    347   //
    348   // Reset the endpoint toggle to zero
    349   //
    350   for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {
    351     Setting->Endpoints[Index]->Toggle = 0;
    352   }
    353 
    354   return EFI_SUCCESS;
    355 }
    356 
    357 
    358 /**
    359   Select a new configuration for the device. Each
    360   device may support several configurations.
    361 
    362   @param  Device                The device to select configuration.
    363   @param  ConfigValue           The index of the configuration ( != 0).
    364 
    365   @retval EFI_NOT_FOUND         There is no configuration with the index.
    366   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource.
    367   @retval EFI_SUCCESS           The configuration is selected.
    368 
    369 **/
    370 EFI_STATUS
    371 UsbSelectConfig (
    372   IN USB_DEVICE           *Device,
    373   IN UINT8                ConfigValue
    374   )
    375 {
    376   USB_DEVICE_DESC         *DevDesc;
    377   USB_CONFIG_DESC         *ConfigDesc;
    378   USB_INTERFACE_DESC      *IfDesc;
    379   USB_INTERFACE           *UsbIf;
    380   EFI_STATUS              Status;
    381   UINT8                   Index;
    382 
    383   //
    384   // Locate the active config, then set the device's pointer
    385   //
    386   DevDesc     = Device->DevDesc;
    387   ConfigDesc  = NULL;
    388 
    389   for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {
    390     ConfigDesc = DevDesc->Configs[Index];
    391 
    392     if (ConfigDesc->Desc.ConfigurationValue == ConfigValue) {
    393       break;
    394     }
    395   }
    396 
    397   if (Index == DevDesc->Desc.NumConfigurations) {
    398     return EFI_NOT_FOUND;
    399   }
    400 
    401   Device->ActiveConfig = ConfigDesc;
    402 
    403   DEBUG ((EFI_D_INFO, "UsbSelectConfig: config %d selected for device %d\n",
    404               ConfigValue, Device->Address));
    405 
    406   //
    407   // Create interfaces for each USB interface descriptor.
    408   //
    409   for (Index = 0; Index < ConfigDesc->Desc.NumInterfaces; Index++) {
    410     //
    411     // First select the default interface setting, and reset
    412     // the endpoint toggles to zero for its endpoints.
    413     //
    414     IfDesc = ConfigDesc->Interfaces[Index];
    415     UsbSelectSetting (IfDesc, IfDesc->Settings[0]->Desc.AlternateSetting);
    416 
    417     //
    418     // Create a USB_INTERFACE and install USB_IO and other protocols
    419     //
    420     UsbIf = UsbCreateInterface (Device, ConfigDesc->Interfaces[Index]);
    421 
    422     if (UsbIf == NULL) {
    423       Device->NumOfInterface = Index;
    424       return EFI_OUT_OF_RESOURCES;
    425     }
    426 
    427     ASSERT (Index < USB_MAX_INTERFACE);
    428     Device->Interfaces[Index] = UsbIf;
    429 
    430     //
    431     // Connect the device to drivers, if it failed, ignore
    432     // the error. Don't let the unsupported interfaces to block
    433     // the supported interfaces.
    434     //
    435     Status = UsbConnectDriver (UsbIf);
    436 
    437     if (EFI_ERROR (Status)) {
    438       DEBUG ((EFI_D_ERROR, "UsbSelectConfig: failed to connect driver %r, ignored\n", Status));
    439     }
    440   }
    441 
    442   Device->NumOfInterface = Index;
    443 
    444   return EFI_SUCCESS;
    445 }
    446 
    447 
    448 /**
    449   Disconnect the USB interface with its driver.
    450 
    451   @param  UsbIf                 The interface to disconnect driver from.
    452 
    453 **/
    454 EFI_STATUS
    455 UsbDisconnectDriver (
    456   IN USB_INTERFACE        *UsbIf
    457   )
    458 {
    459   EFI_TPL                 OldTpl;
    460   EFI_STATUS              Status;
    461 
    462   //
    463   // Release the hub if it's a hub controller, otherwise
    464   // disconnect the driver if it is managed by other drivers.
    465   //
    466   Status = EFI_SUCCESS;
    467   if (UsbIf->IsHub) {
    468     Status = UsbIf->HubApi->Release (UsbIf);
    469 
    470   } else if (UsbIf->IsManaged) {
    471     //
    472     // This function is called in both UsbIoControlTransfer and
    473     // the timer callback in hub enumeration. So, at least it is
    474     // called at TPL_CALLBACK. Some driver sitting on USB has
    475     // twisted TPL used. It should be no problem for us to connect
    476     // or disconnect at CALLBACK.
    477     //
    478     OldTpl           = UsbGetCurrentTpl ();
    479     DEBUG ((EFI_D_INFO, "UsbDisconnectDriver: old TPL is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
    480 
    481     gBS->RestoreTPL (TPL_CALLBACK);
    482 
    483     Status = gBS->DisconnectController (UsbIf->Handle, NULL, NULL);
    484     if (!EFI_ERROR (Status)) {
    485       UsbIf->IsManaged = FALSE;
    486     }
    487 
    488     DEBUG (( EFI_D_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl(), Status));
    489     ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
    490 
    491     gBS->RaiseTPL (OldTpl);
    492   }
    493 
    494   return Status;
    495 }
    496 
    497 
    498 /**
    499   Remove the current device configuration.
    500 
    501   @param  Device                The USB device to remove configuration from.
    502 
    503 **/
    504 EFI_STATUS
    505 UsbRemoveConfig (
    506   IN USB_DEVICE           *Device
    507   )
    508 {
    509   USB_INTERFACE           *UsbIf;
    510   UINTN                   Index;
    511   EFI_STATUS              Status;
    512   EFI_STATUS              ReturnStatus;
    513 
    514   //
    515   // Remove each interface of the device
    516   //
    517   ReturnStatus = EFI_SUCCESS;
    518   for (Index = 0; Index < Device->NumOfInterface; Index++) {
    519     ASSERT (Index < USB_MAX_INTERFACE);
    520     UsbIf = Device->Interfaces[Index];
    521 
    522     if (UsbIf == NULL) {
    523       continue;
    524     }
    525 
    526     Status = UsbDisconnectDriver (UsbIf);
    527     if (!EFI_ERROR (Status)) {
    528       UsbFreeInterface (UsbIf);
    529       Device->Interfaces[Index] = NULL;
    530     } else {
    531       ReturnStatus = Status;
    532     }
    533   }
    534 
    535   Device->ActiveConfig    = NULL;
    536   return ReturnStatus;
    537 }
    538 
    539 
    540 /**
    541   Remove the device and all its children from the bus.
    542 
    543   @param  Device                The device to remove.
    544 
    545   @retval EFI_SUCCESS           The device is removed.
    546 
    547 **/
    548 EFI_STATUS
    549 UsbRemoveDevice (
    550   IN USB_DEVICE           *Device
    551   )
    552 {
    553   USB_BUS                 *Bus;
    554   USB_DEVICE              *Child;
    555   EFI_STATUS              Status;
    556   EFI_STATUS              ReturnStatus;
    557   UINTN                   Index;
    558 
    559   Bus = Device->Bus;
    560 
    561   //
    562   // Remove all the devices on its downstream ports. Search from devices[1].
    563   // Devices[0] is the root hub.
    564   //
    565   ReturnStatus = EFI_SUCCESS;
    566   for (Index = 1; Index < Bus->MaxDevices; Index++) {
    567     Child = Bus->Devices[Index];
    568 
    569     if ((Child == NULL) || (Child->ParentAddr != Device->Address)) {
    570       continue;
    571     }
    572 
    573     Status = UsbRemoveDevice (Child);
    574 
    575     if (!EFI_ERROR (Status)) {
    576       Bus->Devices[Index] = NULL;
    577     } else {
    578       Bus->Devices[Index]->DisconnectFail = TRUE;
    579       ReturnStatus = Status;
    580       DEBUG ((EFI_D_INFO, "UsbRemoveDevice: failed to remove child %p at parent %p\n", Child, Device));
    581     }
    582   }
    583 
    584   if (EFI_ERROR (ReturnStatus)) {
    585     return ReturnStatus;
    586   }
    587 
    588   Status = UsbRemoveConfig (Device);
    589 
    590   if (!EFI_ERROR (Status)) {
    591     DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address));
    592 
    593     ASSERT (Device->Address < Bus->MaxDevices);
    594     Bus->Devices[Device->Address] = NULL;
    595     UsbFreeDevice (Device);
    596   } else {
    597     Bus->Devices[Device->Address]->DisconnectFail = TRUE;
    598   }
    599   return Status;
    600 }
    601 
    602 
    603 /**
    604   Find the child device on the hub's port.
    605 
    606   @param  HubIf                 The hub interface.
    607   @param  Port                  The port of the hub this child is connected to.
    608 
    609   @return The device on the hub's port, or NULL if there is none.
    610 
    611 **/
    612 USB_DEVICE *
    613 UsbFindChild (
    614   IN USB_INTERFACE        *HubIf,
    615   IN UINT8                Port
    616   )
    617 {
    618   USB_DEVICE              *Device;
    619   USB_BUS                 *Bus;
    620   UINTN                   Index;
    621 
    622   Bus = HubIf->Device->Bus;
    623 
    624   //
    625   // Start checking from device 1, device 0 is the root hub
    626   //
    627   for (Index = 1; Index < Bus->MaxDevices; Index++) {
    628     Device = Bus->Devices[Index];
    629 
    630     if ((Device != NULL) && (Device->ParentAddr == HubIf->Device->Address) &&
    631         (Device->ParentPort == Port)) {
    632 
    633       return Device;
    634     }
    635   }
    636 
    637   return NULL;
    638 }
    639 
    640 
    641 /**
    642   Enumerate and configure the new device on the port of this HUB interface.
    643 
    644   @param  HubIf                 The HUB that has the device connected.
    645   @param  Port                  The port index of the hub (started with zero).
    646   @param  ResetIsNeeded         The boolean to control whether skip the reset of the port.
    647 
    648   @retval EFI_SUCCESS           The device is enumerated (added or removed).
    649   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource for the device.
    650   @retval Others                Failed to enumerate the device.
    651 
    652 **/
    653 EFI_STATUS
    654 UsbEnumerateNewDev (
    655   IN USB_INTERFACE        *HubIf,
    656   IN UINT8                Port,
    657   IN BOOLEAN              ResetIsNeeded
    658   )
    659 {
    660   USB_BUS                 *Bus;
    661   USB_HUB_API             *HubApi;
    662   USB_DEVICE              *Child;
    663   USB_DEVICE              *Parent;
    664   EFI_USB_PORT_STATUS     PortState;
    665   UINTN                   Address;
    666   UINT8                   Config;
    667   EFI_STATUS              Status;
    668 
    669   Parent  = HubIf->Device;
    670   Bus     = Parent->Bus;
    671   HubApi  = HubIf->HubApi;
    672   Address = Bus->MaxDevices;
    673 
    674   gBS->Stall (USB_WAIT_PORT_STABLE_STALL);
    675 
    676   //
    677   // Hub resets the device for at least 10 milliseconds.
    678   // Host learns device speed. If device is of low/full speed
    679   // and the hub is a EHCI root hub, ResetPort will release
    680   // the device to its companion UHCI and return an error.
    681   //
    682   if (ResetIsNeeded) {
    683     Status = HubApi->ResetPort (HubIf, Port);
    684     if (EFI_ERROR (Status)) {
    685       DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));
    686 
    687       return Status;
    688     }
    689     DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port));
    690   } else {
    691     DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d reset is skipped\n", Port));
    692   }
    693 
    694   Child = UsbCreateDevice (HubIf, Port);
    695 
    696   if (Child == NULL) {
    697     return EFI_OUT_OF_RESOURCES;
    698   }
    699 
    700   //
    701   // OK, now identify the device speed. After reset, hub
    702   // fully knows the actual device speed.
    703   //
    704   Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
    705 
    706   if (EFI_ERROR (Status)) {
    707     DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get speed of port %d\n", Port));
    708     goto ON_ERROR;
    709   }
    710 
    711   if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
    712     DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: No device present at port %d\n", Port));
    713     goto ON_ERROR;
    714   } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
    715     Child->Speed      = EFI_USB_SPEED_SUPER;
    716     Child->MaxPacket0 = 512;
    717   } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
    718     Child->Speed      = EFI_USB_SPEED_HIGH;
    719     Child->MaxPacket0 = 64;
    720   } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
    721     Child->Speed      = EFI_USB_SPEED_LOW;
    722     Child->MaxPacket0 = 8;
    723   } else {
    724     Child->Speed      = EFI_USB_SPEED_FULL;
    725     Child->MaxPacket0 = 8;
    726   }
    727 
    728   DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));
    729 
    730   if (((Child->Speed == EFI_USB_SPEED_LOW) || (Child->Speed == EFI_USB_SPEED_FULL)) &&
    731       (Parent->Speed == EFI_USB_SPEED_HIGH)) {
    732     //
    733     // If the child is a low or full speed device, it is necessary to
    734     // set the transaction translator. Port TT is 1-based.
    735     // This is quite simple:
    736     //  1. if parent is of high speed, then parent is our translator
    737     //  2. otherwise use parent's translator.
    738     //
    739     Child->Translator.TranslatorHubAddress  = Parent->Address;
    740     Child->Translator.TranslatorPortNumber  = (UINT8) (Port + 1);
    741   } else {
    742     Child->Translator = Parent->Translator;
    743   }
    744   DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device uses translator (%d, %d)\n",
    745            Child->Translator.TranslatorHubAddress,
    746            Child->Translator.TranslatorPortNumber));
    747 
    748   //
    749   // After port is reset, hub establishes a signal path between
    750   // the device and host (DEFALUT state). Device's registers are
    751   // reset, use default address 0 (host enumerates one device at
    752   // a time) , and ready to respond to control transfer at EP 0.
    753   //
    754 
    755   //
    756   // Host assigns an address to the device. Device completes the
    757   // status stage with default address, then switches to new address.
    758   // ADDRESS state. Address zero is reserved for root hub.
    759   //
    760   ASSERT (Bus->MaxDevices <= 256);
    761   for (Address = 1; Address < Bus->MaxDevices; Address++) {
    762     if (Bus->Devices[Address] == NULL) {
    763       break;
    764     }
    765   }
    766 
    767   if (Address >= Bus->MaxDevices) {
    768     DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: address pool is full for port %d\n", Port));
    769 
    770     Status = EFI_ACCESS_DENIED;
    771     goto ON_ERROR;
    772   }
    773 
    774   Status                = UsbSetAddress (Child, (UINT8)Address);
    775   Child->Address        = (UINT8)Address;
    776   Bus->Devices[Address] = Child;
    777 
    778   if (EFI_ERROR (Status)) {
    779     DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status));
    780     goto ON_ERROR;
    781   }
    782 
    783   gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
    784 
    785   DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));
    786 
    787   //
    788   // Host sends a Get_Descriptor request to learn the max packet
    789   // size of default pipe (only part of the device's descriptor).
    790   //
    791   Status = UsbGetMaxPacketSize0 (Child);
    792 
    793   if (EFI_ERROR (Status)) {
    794     DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status));
    795     goto ON_ERROR;
    796   }
    797 
    798   DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0));
    799 
    800   //
    801   // Host learns about the device's abilities by requesting device's
    802   // entire descriptions.
    803   //
    804   Status = UsbBuildDescTable (Child);
    805 
    806   if (EFI_ERROR (Status)) {
    807     DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status));
    808     goto ON_ERROR;
    809   }
    810 
    811   //
    812   // Select a default configuration: UEFI must set the configuration
    813   // before the driver can connect to the device.
    814   //
    815   Config = Child->DevDesc->Configs[0]->Desc.ConfigurationValue;
    816   Status = UsbSetConfig (Child, Config);
    817 
    818   if (EFI_ERROR (Status)) {
    819     DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status));
    820     goto ON_ERROR;
    821   }
    822 
    823   DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address));
    824 
    825   //
    826   // Host assigns and loads a device driver.
    827   //
    828   Status = UsbSelectConfig (Child, Config);
    829 
    830   if (EFI_ERROR (Status)) {
    831     DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to create interfaces - %r\n", Status));
    832     goto ON_ERROR;
    833   }
    834 
    835   //
    836   // Report Status Code to indicate USB device has been detected by hotplug
    837   //
    838   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    839     EFI_PROGRESS_CODE,
    840     (EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG),
    841     Bus->DevicePath
    842     );
    843   return EFI_SUCCESS;
    844 
    845 ON_ERROR:
    846   //
    847   // If reach here, it means the enumeration process on a given port is interrupted due to error.
    848   // The s/w resources, including the assigned address(Address) and the allocated usb device data
    849   // structure(Bus->Devices[Address]), will NOT be freed here. These resources will be freed when
    850   // the device is unplugged from the port or DriverBindingStop() is invoked.
    851   //
    852   // This way is used to co-work with the lower layer EDKII UHCI/EHCI/XHCI host controller driver.
    853   // It's mainly because to keep UEFI spec unchanged EDKII XHCI driver have to maintain a state machine
    854   // to keep track of the mapping between actual address and request address. If the request address
    855   // (Address) is freed here, the Address value will be used by next enumerated device. Then EDKII XHCI
    856   // host controller driver will have wrong information, which will cause further transaction error.
    857   //
    858   // EDKII UHCI/EHCI doesn't get impacted as it's make sense to reserve s/w resource till it gets unplugged.
    859   //
    860   return Status;
    861 }
    862 
    863 
    864 /**
    865   Process the events on the port.
    866 
    867   @param  HubIf                 The HUB that has the device connected.
    868   @param  Port                  The port index of the hub (started with zero).
    869 
    870   @retval EFI_SUCCESS           The device is enumerated (added or removed).
    871   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource for the device.
    872   @retval Others                Failed to enumerate the device.
    873 
    874 **/
    875 EFI_STATUS
    876 UsbEnumeratePort (
    877   IN USB_INTERFACE        *HubIf,
    878   IN UINT8                Port
    879   )
    880 {
    881   USB_HUB_API             *HubApi;
    882   USB_DEVICE              *Child;
    883   EFI_USB_PORT_STATUS     PortState;
    884   EFI_STATUS              Status;
    885 
    886   Child   = NULL;
    887   HubApi  = HubIf->HubApi;
    888 
    889   //
    890   // Host learns of the new device by polling the hub for port changes.
    891   //
    892   Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
    893 
    894   if (EFI_ERROR (Status)) {
    895     DEBUG ((EFI_D_ERROR, "UsbEnumeratePort: failed to get state of port %d\n", Port));
    896     return Status;
    897   }
    898 
    899   //
    900   // Only handle connection/enable/overcurrent/reset change.
    901   // Usb super speed hub may report other changes, such as warm reset change. Ignore them.
    902   //
    903   if ((PortState.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
    904     return EFI_SUCCESS;
    905   }
    906 
    907   DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",
    908               Port, PortState.PortStatus, PortState.PortChangeStatus, HubIf));
    909 
    910   //
    911   // This driver only process two kinds of events now: over current and
    912   // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.
    913   // ENABLE/RESET is used to reset port. SUSPEND isn't supported.
    914   //
    915 
    916   if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {
    917 
    918     if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
    919       //
    920       // Case1:
    921       //   Both OverCurrent and OverCurrentChange set, means over current occurs,
    922       //   which probably is caused by short circuit. It has to wait system hardware
    923       //   to perform recovery.
    924       //
    925       DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port));
    926       return EFI_DEVICE_ERROR;
    927 
    928     }
    929     //
    930     // Case2:
    931     //   Only OverCurrentChange set, means system has been recoveried from
    932     //   over current. As a result, all ports are nearly power-off, so
    933     //   it's necessary to detach and enumerate all ports again.
    934     //
    935     DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port));
    936   }
    937 
    938   if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {
    939     //
    940     // Case3:
    941     //   1.1 roothub port reg doesn't reflect over-current state, while its counterpart
    942     //   on 2.0 roothub does. When over-current has influence on 1.1 device, the port
    943     //   would be disabled, so it's also necessary to detach and enumerate again.
    944     //
    945     DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port));
    946   }
    947 
    948   if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
    949     //
    950     // Case4:
    951     //   Device connected or disconnected normally.
    952     //
    953     DEBUG ((EFI_D_INFO, "UsbEnumeratePort: Device Connect/Disconnect Normally\n", Port));
    954   }
    955 
    956   //
    957   // Following as the above cases, it's safety to remove and create again.
    958   //
    959   Child = UsbFindChild (HubIf, Port);
    960 
    961   if (Child != NULL) {
    962     DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device at port %d removed from root hub %p\n", Port, HubIf));
    963     UsbRemoveDevice (Child);
    964   }
    965 
    966   if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
    967     //
    968     // Now, new device connected, enumerate and configure the device
    969     //
    970     DEBUG (( EFI_D_INFO, "UsbEnumeratePort: new device connected at port %d\n", Port));
    971     if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
    972       Status = UsbEnumerateNewDev (HubIf, Port, FALSE);
    973     } else {
    974       Status = UsbEnumerateNewDev (HubIf, Port, TRUE);
    975     }
    976 
    977   } else {
    978     DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device disconnected event on port %d\n", Port));
    979   }
    980 
    981   HubApi->ClearPortChange (HubIf, Port);
    982   return Status;
    983 }
    984 
    985 
    986 /**
    987   Enumerate all the changed hub ports.
    988 
    989   @param  Event                 The event that is triggered.
    990   @param  Context               The context to the event.
    991 
    992 **/
    993 VOID
    994 EFIAPI
    995 UsbHubEnumeration (
    996   IN EFI_EVENT            Event,
    997   IN VOID                 *Context
    998   )
    999 {
   1000   USB_INTERFACE           *HubIf;
   1001   UINT8                   Byte;
   1002   UINT8                   Bit;
   1003   UINT8                   Index;
   1004   USB_DEVICE              *Child;
   1005 
   1006   ASSERT (Context != NULL);
   1007 
   1008   HubIf = (USB_INTERFACE *) Context;
   1009 
   1010   for (Index = 0; Index < HubIf->NumOfPort; Index++) {
   1011     Child = UsbFindChild (HubIf, Index);
   1012     if ((Child != NULL) && (Child->DisconnectFail == TRUE)) {
   1013       DEBUG (( EFI_D_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from hub %p, try again\n", Index, HubIf));
   1014       UsbRemoveDevice (Child);
   1015     }
   1016   }
   1017 
   1018   if (HubIf->ChangeMap == NULL) {
   1019     return ;
   1020   }
   1021 
   1022   //
   1023   // HUB starts its port index with 1.
   1024   //
   1025   Byte  = 0;
   1026   Bit   = 1;
   1027 
   1028   for (Index = 0; Index < HubIf->NumOfPort; Index++) {
   1029     if (USB_BIT_IS_SET (HubIf->ChangeMap[Byte], USB_BIT (Bit))) {
   1030       UsbEnumeratePort (HubIf, Index);
   1031     }
   1032 
   1033     USB_NEXT_BIT (Byte, Bit);
   1034   }
   1035 
   1036   UsbHubAckHubStatus (HubIf->Device);
   1037 
   1038   gBS->FreePool (HubIf->ChangeMap);
   1039   HubIf->ChangeMap = NULL;
   1040   return ;
   1041 }
   1042 
   1043 
   1044 /**
   1045   Enumerate all the changed hub ports.
   1046 
   1047   @param  Event                 The event that is triggered.
   1048   @param  Context               The context to the event.
   1049 
   1050 **/
   1051 VOID
   1052 EFIAPI
   1053 UsbRootHubEnumeration (
   1054   IN EFI_EVENT            Event,
   1055   IN VOID                 *Context
   1056   )
   1057 {
   1058   USB_INTERFACE           *RootHub;
   1059   UINT8                   Index;
   1060   USB_DEVICE              *Child;
   1061 
   1062   RootHub = (USB_INTERFACE *) Context;
   1063 
   1064   for (Index = 0; Index < RootHub->NumOfPort; Index++) {
   1065     Child = UsbFindChild (RootHub, Index);
   1066     if ((Child != NULL) && (Child->DisconnectFail == TRUE)) {
   1067       DEBUG (( EFI_D_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from root hub %p, try again\n", Index, RootHub));
   1068       UsbRemoveDevice (Child);
   1069     }
   1070 
   1071     UsbEnumeratePort (RootHub, Index);
   1072   }
   1073 }
   1074