Home | History | Annotate | Download | only in UsbBusDxe
      1 /** @file
      2 
      3     Manage Usb Descriptor List
      4 
      5 Copyright (c) 2007 - 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 
     19 /**
     20   Free the interface setting descriptor.
     21 
     22   @param  Setting               The descriptor to free.
     23 
     24 **/
     25 VOID
     26 UsbFreeInterfaceDesc (
     27   IN USB_INTERFACE_SETTING  *Setting
     28   )
     29 {
     30   USB_ENDPOINT_DESC       *Ep;
     31   UINTN                   Index;
     32 
     33   if (Setting->Endpoints != NULL) {
     34     //
     35     // Each interface setting may have several endpoints, free them first.
     36     //
     37     for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {
     38       Ep = Setting->Endpoints[Index];
     39 
     40       if (Ep != NULL) {
     41         FreePool (Ep);
     42       }
     43     }
     44 
     45     //
     46     // Only call FreePool() if NumEndpoints > 0.
     47     //
     48     if (Setting->Desc.NumEndpoints > 0) {
     49       FreePool (Setting->Endpoints);
     50     }
     51   }
     52 
     53   FreePool (Setting);
     54 }
     55 
     56 
     57 /**
     58   Free a configuration descriptor with its interface
     59   descriptors. It may be initialized partially.
     60 
     61   @param  Config                The configuration descriptor to free.
     62 
     63 **/
     64 VOID
     65 UsbFreeConfigDesc (
     66   IN USB_CONFIG_DESC      *Config
     67   )
     68 {
     69   USB_INTERFACE_DESC      *Interface;
     70   UINTN                   Index;
     71   UINTN                   SetIndex;
     72 
     73   if (Config->Interfaces != NULL) {
     74     //
     75     // A configuration may have several interfaces, free the interface
     76     //
     77     for (Index = 0; Index < Config->Desc.NumInterfaces; Index++) {
     78       Interface = Config->Interfaces[Index];
     79 
     80       if (Interface == NULL) {
     81         continue;
     82       }
     83 
     84       //
     85       // Each interface may have several settings, free the settings
     86       //
     87       for (SetIndex = 0; SetIndex < Interface->NumOfSetting; SetIndex++) {
     88         if (Interface->Settings[SetIndex] != NULL) {
     89           UsbFreeInterfaceDesc (Interface->Settings[SetIndex]);
     90         }
     91       }
     92 
     93       FreePool (Interface);
     94     }
     95 
     96     FreePool (Config->Interfaces);
     97   }
     98 
     99   FreePool (Config);
    100 
    101 }
    102 
    103 
    104 /**
    105   Free a device descriptor with its configurations.
    106 
    107   @param  DevDesc               The device descriptor.
    108 
    109 **/
    110 VOID
    111 UsbFreeDevDesc (
    112   IN USB_DEVICE_DESC      *DevDesc
    113   )
    114 {
    115   UINTN                   Index;
    116 
    117   if (DevDesc->Configs != NULL) {
    118     for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {
    119       if (DevDesc->Configs[Index] != NULL) {
    120         UsbFreeConfigDesc (DevDesc->Configs[Index]);
    121       }
    122     }
    123 
    124     FreePool (DevDesc->Configs);
    125   }
    126 
    127   FreePool (DevDesc);
    128 }
    129 
    130 
    131 /**
    132   Create a descriptor.
    133 
    134   @param  DescBuf               The buffer of raw descriptor.
    135   @param  Len                   The length of the raw descriptor buffer.
    136   @param  Type                  The type of descriptor to create.
    137   @param  Consumed              Number of bytes consumed.
    138 
    139   @return Created descriptor or NULL.
    140 
    141 **/
    142 VOID *
    143 UsbCreateDesc (
    144   IN  UINT8               *DescBuf,
    145   IN  UINTN               Len,
    146   IN  UINT8               Type,
    147   OUT UINTN               *Consumed
    148   )
    149 {
    150   USB_DESC_HEAD           *Head;
    151   UINTN                   DescLen;
    152   UINTN                   CtrlLen;
    153   UINTN                   Offset;
    154   VOID                    *Desc;
    155 
    156   DescLen   = 0;
    157   CtrlLen   = 0;
    158   *Consumed = 0;
    159 
    160   switch (Type) {
    161   case USB_DESC_TYPE_DEVICE:
    162     DescLen = sizeof (EFI_USB_DEVICE_DESCRIPTOR);
    163     CtrlLen = sizeof (USB_DEVICE_DESC);
    164     break;
    165 
    166   case USB_DESC_TYPE_CONFIG:
    167     DescLen = sizeof (EFI_USB_CONFIG_DESCRIPTOR);
    168     CtrlLen = sizeof (USB_CONFIG_DESC);
    169     break;
    170 
    171   case USB_DESC_TYPE_INTERFACE:
    172     DescLen = sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
    173     CtrlLen = sizeof (USB_INTERFACE_SETTING);
    174     break;
    175 
    176   case USB_DESC_TYPE_ENDPOINT:
    177     DescLen = sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
    178     CtrlLen = sizeof (USB_ENDPOINT_DESC);
    179     break;
    180   }
    181 
    182   //
    183   // All the descriptor has a common LTV (Length, Type, Value)
    184   // format. Skip the descriptor that isn't of this Type
    185   //
    186   Offset = 0;
    187   Head   = (USB_DESC_HEAD*)DescBuf;
    188 
    189   while ((Offset < Len) && (Head->Type != Type)) {
    190     Offset += Head->Len;
    191     if (Len <= Offset) {
    192       DEBUG (( EFI_D_ERROR, "UsbCreateDesc: met mal-format descriptor, Beyond boundary!\n"));
    193       return NULL;
    194     }
    195     Head    = (USB_DESC_HEAD*)(DescBuf + Offset);
    196     if (Head->Len == 0) {
    197       DEBUG (( EFI_D_ERROR, "UsbCreateDesc: met mal-format descriptor, Head->Len = 0!\n"));
    198       return NULL;
    199     }
    200   }
    201 
    202   if ((Len <= Offset)      || (Len < Offset + DescLen) ||
    203       (Head->Type != Type) || (Head->Len != DescLen)) {
    204     DEBUG (( EFI_D_ERROR, "UsbCreateDesc: met mal-format descriptor\n"));
    205     return NULL;
    206   }
    207 
    208   Desc = AllocateZeroPool ((UINTN) CtrlLen);
    209   if (Desc == NULL) {
    210     return NULL;
    211   }
    212 
    213   CopyMem (Desc, Head, (UINTN) DescLen);
    214 
    215   *Consumed = Offset + Head->Len;
    216 
    217   return Desc;
    218 }
    219 
    220 
    221 /**
    222   Parse an interface descriptor and its endpoints.
    223 
    224   @param  DescBuf               The buffer of raw descriptor.
    225   @param  Len                   The length of the raw descriptor buffer.
    226   @param  Consumed              The number of raw descriptor consumed.
    227 
    228   @return The create interface setting or NULL if failed.
    229 
    230 **/
    231 USB_INTERFACE_SETTING *
    232 UsbParseInterfaceDesc (
    233   IN  UINT8               *DescBuf,
    234   IN  UINTN               Len,
    235   OUT UINTN               *Consumed
    236   )
    237 {
    238   USB_INTERFACE_SETTING   *Setting;
    239   USB_ENDPOINT_DESC       *Ep;
    240   UINTN                   Index;
    241   UINTN                   NumEp;
    242   UINTN                   Used;
    243   UINTN                   Offset;
    244 
    245   *Consumed = 0;
    246   Setting   = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_INTERFACE, &Used);
    247 
    248   if (Setting == NULL) {
    249     DEBUG (( EFI_D_ERROR, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));
    250     return NULL;
    251   }
    252 
    253   Offset = Used;
    254 
    255   //
    256   // Create an array to hold the interface's endpoints
    257   //
    258   NumEp  = Setting->Desc.NumEndpoints;
    259 
    260   DEBUG (( EFI_D_INFO, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
    261               Setting->Desc.InterfaceNumber, Setting->Desc.AlternateSetting, (UINT32)NumEp));
    262 
    263   if (NumEp == 0) {
    264     goto ON_EXIT;
    265   }
    266 
    267   Setting->Endpoints  = AllocateZeroPool (sizeof (USB_ENDPOINT_DESC *) * NumEp);
    268 
    269   if (Setting->Endpoints == NULL) {
    270     goto ON_ERROR;
    271   }
    272 
    273   //
    274   // Create the endpoints for this interface
    275   //
    276   for (Index = 0; (Index < NumEp) && (Offset < Len); Index++) {
    277     Ep = UsbCreateDesc (DescBuf + Offset, Len - Offset, USB_DESC_TYPE_ENDPOINT, &Used);
    278 
    279     if (Ep == NULL) {
    280       DEBUG (( EFI_D_ERROR, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32)Index));
    281       goto ON_ERROR;
    282     }
    283 
    284     Setting->Endpoints[Index]  = Ep;
    285     Offset                    += Used;
    286   }
    287 
    288 
    289 ON_EXIT:
    290   *Consumed = Offset;
    291   return Setting;
    292 
    293 ON_ERROR:
    294   UsbFreeInterfaceDesc (Setting);
    295   return NULL;
    296 }
    297 
    298 
    299 /**
    300   Parse the configuration descriptor and its interfaces.
    301 
    302   @param  DescBuf               The buffer of raw descriptor.
    303   @param  Len                   The length of the raw descriptor buffer.
    304 
    305   @return The created configuration descriptor.
    306 
    307 **/
    308 USB_CONFIG_DESC *
    309 UsbParseConfigDesc (
    310   IN UINT8                *DescBuf,
    311   IN UINTN                Len
    312   )
    313 {
    314   USB_CONFIG_DESC         *Config;
    315   USB_INTERFACE_SETTING   *Setting;
    316   USB_INTERFACE_DESC      *Interface;
    317   UINTN                   Index;
    318   UINTN                   NumIf;
    319   UINTN                   Consumed;
    320 
    321   ASSERT (DescBuf != NULL);
    322 
    323   Config = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_CONFIG, &Consumed);
    324 
    325   if (Config == NULL) {
    326     return NULL;
    327   }
    328 
    329   //
    330   // Initialize an array of setting for the configuration's interfaces.
    331   //
    332   NumIf               = Config->Desc.NumInterfaces;
    333   Config->Interfaces  = AllocateZeroPool (sizeof (USB_INTERFACE_DESC *) * NumIf);
    334 
    335   if (Config->Interfaces == NULL) {
    336     goto ON_ERROR;
    337   }
    338 
    339   DEBUG (( EFI_D_INFO, "UsbParseConfigDesc: config %d has %d interfaces\n",
    340                 Config->Desc.ConfigurationValue, (UINT32)NumIf));
    341 
    342   for (Index = 0; Index < NumIf; Index++) {
    343     Interface = AllocateZeroPool (sizeof (USB_INTERFACE_DESC));
    344 
    345     if (Interface == NULL) {
    346       goto ON_ERROR;
    347     }
    348 
    349     Config->Interfaces[Index] = Interface;
    350   }
    351 
    352   //
    353   // If a configuration has several interfaces, these interfaces are
    354   // numbered from zero to n. If a interface has several settings,
    355   // these settings are also number from zero to m. The interface
    356   // setting must be organized as |interface 0, setting 0|interface 0
    357   // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
    358   // USB2.0 spec, page 267.
    359   //
    360   DescBuf += Consumed;
    361   Len     -= Consumed;
    362 
    363   //
    364   // Make allowances for devices that return extra data at the
    365   // end of their config descriptors
    366   //
    367   while (Len >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) {
    368     Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);
    369 
    370     if (Setting == NULL) {
    371       DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));
    372       break;
    373 
    374     } else if (Setting->Desc.InterfaceNumber >= NumIf) {
    375       DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
    376 
    377       UsbFreeInterfaceDesc (Setting);
    378       goto ON_ERROR;
    379     }
    380 
    381     //
    382     // Insert the descriptor to the corresponding set.
    383     //
    384     Interface = Config->Interfaces[Setting->Desc.InterfaceNumber];
    385 
    386     if (Interface->NumOfSetting >= USB_MAX_INTERFACE_SETTING) {
    387       goto ON_ERROR;
    388     }
    389 
    390     Interface->Settings[Interface->NumOfSetting] = Setting;
    391     Interface->NumOfSetting++;
    392 
    393     DescBuf += Consumed;
    394     Len     -= Consumed;
    395   }
    396 
    397   return Config;
    398 
    399 ON_ERROR:
    400   UsbFreeConfigDesc (Config);
    401   return NULL;
    402 }
    403 
    404 
    405 /**
    406   USB standard control transfer support routine. This
    407   function is used by USB device. It is possible that
    408   the device's interfaces are still waiting to be
    409   enumerated.
    410 
    411   @param  UsbDev                The usb device.
    412   @param  Direction             The direction of data transfer.
    413   @param  Type                  Standard / class specific / vendor specific.
    414   @param  Target                The receiving target.
    415   @param  Request               Which request.
    416   @param  Value                 The wValue parameter of the request.
    417   @param  Index                 The wIndex parameter of the request.
    418   @param  Buf                   The buffer to receive data into / transmit from.
    419   @param  Length                The length of the buffer.
    420 
    421   @retval EFI_SUCCESS           The control request is executed.
    422   @retval EFI_DEVICE_ERROR      Failed to execute the control transfer.
    423 
    424 **/
    425 EFI_STATUS
    426 UsbCtrlRequest (
    427   IN USB_DEVICE             *UsbDev,
    428   IN EFI_USB_DATA_DIRECTION Direction,
    429   IN UINTN                  Type,
    430   IN UINTN                  Target,
    431   IN UINTN                  Request,
    432   IN UINT16                 Value,
    433   IN UINT16                 Index,
    434   IN OUT VOID               *Buf,
    435   IN UINTN                  Length
    436   )
    437 {
    438   EFI_USB_DEVICE_REQUEST  DevReq;
    439   EFI_STATUS              Status;
    440   UINT32                  Result;
    441   UINTN                   Len;
    442 
    443   ASSERT ((UsbDev != NULL) && (UsbDev->Bus != NULL));
    444 
    445   DevReq.RequestType  = USB_REQUEST_TYPE (Direction, Type, Target);
    446   DevReq.Request      = (UINT8) Request;
    447   DevReq.Value        = Value;
    448   DevReq.Index        = Index;
    449   DevReq.Length       = (UINT16) Length;
    450 
    451   Len                 = Length;
    452   Status = UsbHcControlTransfer (
    453              UsbDev->Bus,
    454              UsbDev->Address,
    455              UsbDev->Speed,
    456              UsbDev->MaxPacket0,
    457              &DevReq,
    458              Direction,
    459              Buf,
    460              &Len,
    461              USB_GENERAL_DEVICE_REQUEST_TIMEOUT,
    462              &UsbDev->Translator,
    463              &Result
    464              );
    465 
    466   return Status;
    467 }
    468 
    469 
    470 /**
    471   Get the standard descriptors.
    472 
    473   @param  UsbDev                The USB device to read descriptor from.
    474   @param  DescType              The type of descriptor to read.
    475   @param  DescIndex             The index of descriptor to read.
    476   @param  LangId                Language ID, only used to get string, otherwise set
    477                                 it to 0.
    478   @param  Buf                   The buffer to hold the descriptor read.
    479   @param  Length                The length of the buffer.
    480 
    481   @retval EFI_SUCCESS           The descriptor is read OK.
    482   @retval Others                Failed to retrieve the descriptor.
    483 
    484 **/
    485 EFI_STATUS
    486 UsbCtrlGetDesc (
    487   IN  USB_DEVICE          *UsbDev,
    488   IN  UINTN               DescType,
    489   IN  UINTN               DescIndex,
    490   IN  UINT16              LangId,
    491   OUT VOID                *Buf,
    492   IN  UINTN               Length
    493   )
    494 {
    495   EFI_STATUS              Status;
    496 
    497   Status = UsbCtrlRequest (
    498              UsbDev,
    499              EfiUsbDataIn,
    500              USB_REQ_TYPE_STANDARD,
    501              USB_TARGET_DEVICE,
    502              USB_REQ_GET_DESCRIPTOR,
    503              (UINT16) ((DescType << 8) | DescIndex),
    504              LangId,
    505              Buf,
    506              Length
    507              );
    508 
    509   return Status;
    510 }
    511 
    512 
    513 /**
    514   Return the max packet size for endpoint zero. This function
    515   is the first function called to get descriptors during bus
    516   enumeration.
    517 
    518   @param  UsbDev                The usb device.
    519 
    520   @retval EFI_SUCCESS           The max packet size of endpoint zero is retrieved.
    521   @retval EFI_DEVICE_ERROR      Failed to retrieve it.
    522 
    523 **/
    524 EFI_STATUS
    525 UsbGetMaxPacketSize0 (
    526   IN USB_DEVICE           *UsbDev
    527   )
    528 {
    529   EFI_USB_DEVICE_DESCRIPTOR DevDesc;
    530   EFI_STATUS                Status;
    531   UINTN                     Index;
    532 
    533 
    534   //
    535   // Get the first 8 bytes of the device descriptor which contains
    536   // max packet size for endpoint 0, which is at least 8.
    537   //
    538   for (Index = 0; Index < 3; Index++) {
    539     Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_DEVICE, 0, 0, &DevDesc, 8);
    540 
    541     if (!EFI_ERROR (Status)) {
    542       if ((DevDesc.BcdUSB == 0x0300) && (DevDesc.MaxPacketSize0 == 9)) {
    543         UsbDev->MaxPacket0 = 1 << 9;
    544         return EFI_SUCCESS;
    545       }
    546       UsbDev->MaxPacket0 = DevDesc.MaxPacketSize0;
    547       return EFI_SUCCESS;
    548     }
    549 
    550     gBS->Stall (USB_RETRY_MAX_PACK_SIZE_STALL);
    551   }
    552 
    553   return EFI_DEVICE_ERROR;
    554 }
    555 
    556 
    557 /**
    558   Get the device descriptor for the device.
    559 
    560   @param  UsbDev                The Usb device to retrieve descriptor from.
    561 
    562   @retval EFI_SUCCESS           The device descriptor is returned.
    563   @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory.
    564 
    565 **/
    566 EFI_STATUS
    567 UsbGetDevDesc (
    568   IN USB_DEVICE           *UsbDev
    569   )
    570 {
    571   USB_DEVICE_DESC         *DevDesc;
    572   EFI_STATUS              Status;
    573 
    574   DevDesc = AllocateZeroPool (sizeof (USB_DEVICE_DESC));
    575 
    576   if (DevDesc == NULL) {
    577     return EFI_OUT_OF_RESOURCES;
    578   }
    579 
    580   Status  = UsbCtrlGetDesc (
    581               UsbDev,
    582               USB_DESC_TYPE_DEVICE,
    583               0,
    584               0,
    585               DevDesc,
    586               sizeof (EFI_USB_DEVICE_DESCRIPTOR)
    587               );
    588 
    589   if (EFI_ERROR (Status)) {
    590     gBS->FreePool (DevDesc);
    591   } else {
    592     UsbDev->DevDesc = DevDesc;
    593   }
    594 
    595   return Status;
    596 }
    597 
    598 
    599 /**
    600   Retrieve the indexed string for the language. It requires two
    601   steps to get a string, first to get the string's length. Then
    602   the string itself.
    603 
    604   @param  UsbDev                The usb device.
    605   @param  Index                 The index the string to retrieve.
    606   @param  LangId                Language ID.
    607 
    608   @return The created string descriptor or NULL.
    609 
    610 **/
    611 EFI_USB_STRING_DESCRIPTOR *
    612 UsbGetOneString (
    613   IN     USB_DEVICE       *UsbDev,
    614   IN     UINT8            Index,
    615   IN     UINT16           LangId
    616   )
    617 {
    618   EFI_USB_STRING_DESCRIPTOR Desc;
    619   EFI_STATUS                Status;
    620   UINT8                     *Buf;
    621 
    622   //
    623   // First get two bytes which contains the string length.
    624   //
    625   Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2);
    626 
    627   if (EFI_ERROR (Status)) {
    628     return NULL;
    629   }
    630 
    631   Buf = AllocateZeroPool (Desc.Length);
    632 
    633   if (Buf == NULL) {
    634     return NULL;
    635   }
    636 
    637   Status = UsbCtrlGetDesc (
    638              UsbDev,
    639              USB_DESC_TYPE_STRING,
    640              Index,
    641              LangId,
    642              Buf,
    643              Desc.Length
    644              );
    645 
    646   if (EFI_ERROR (Status)) {
    647     FreePool (Buf);
    648     return NULL;
    649   }
    650 
    651   return (EFI_USB_STRING_DESCRIPTOR *) Buf;
    652 }
    653 
    654 
    655 /**
    656   Build the language ID table for string descriptors.
    657 
    658   @param  UsbDev                The Usb device.
    659 
    660   @retval EFI_UNSUPPORTED       This device doesn't support string table.
    661 
    662 **/
    663 EFI_STATUS
    664 UsbBuildLangTable (
    665   IN USB_DEVICE           *UsbDev
    666   )
    667 {
    668   EFI_USB_STRING_DESCRIPTOR *Desc;
    669   EFI_STATUS                Status;
    670   UINTN                     Index;
    671   UINTN                     Max;
    672   UINT16                    *Point;
    673 
    674   //
    675   // The string of language ID zero returns the supported languages
    676   //
    677   Desc = UsbGetOneString (UsbDev, 0, 0);
    678 
    679   if (Desc == NULL) {
    680     return EFI_UNSUPPORTED;
    681   }
    682 
    683   if (Desc->Length < 4) {
    684     Status = EFI_UNSUPPORTED;
    685     goto ON_EXIT;
    686   }
    687 
    688   Status = EFI_SUCCESS;
    689 
    690   Max   = (Desc->Length - 2) / 2;
    691   Max   = MIN(Max, USB_MAX_LANG_ID);
    692 
    693   Point = Desc->String;
    694   for (Index = 0; Index < Max; Index++) {
    695     UsbDev->LangId[Index] = *Point;
    696     Point++;
    697   }
    698 
    699   UsbDev->TotalLangId = (UINT16)Max;
    700 
    701 ON_EXIT:
    702   gBS->FreePool (Desc);
    703   return Status;
    704 }
    705 
    706 
    707 /**
    708   Retrieve the indexed configure for the device. USB device
    709   returns the configuration together with the interfaces for
    710   this configuration. Configuration descriptor is also of
    711   variable length.
    712 
    713   @param  UsbDev                The Usb interface.
    714   @param  Index                 The index of the configuration.
    715 
    716   @return The created configuration descriptor.
    717 
    718 **/
    719 EFI_USB_CONFIG_DESCRIPTOR *
    720 UsbGetOneConfig (
    721   IN USB_DEVICE           *UsbDev,
    722   IN UINT8                Index
    723   )
    724 {
    725   EFI_USB_CONFIG_DESCRIPTOR Desc;
    726   EFI_STATUS                Status;
    727   VOID                      *Buf;
    728 
    729   //
    730   // First get four bytes which contains the total length
    731   // for this configuration.
    732   //
    733   Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, &Desc, 8);
    734 
    735   if (EFI_ERROR (Status)) {
    736     DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get descript length(%d) %r\n",
    737                 Desc.TotalLength, Status));
    738 
    739     return NULL;
    740   }
    741 
    742   DEBUG (( EFI_D_INFO, "UsbGetOneConfig: total length is %d\n", Desc.TotalLength));
    743 
    744   Buf = AllocateZeroPool (Desc.TotalLength);
    745 
    746   if (Buf == NULL) {
    747     return NULL;
    748   }
    749 
    750   Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, Buf, Desc.TotalLength);
    751 
    752   if (EFI_ERROR (Status)) {
    753     DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get full descript %r\n", Status));
    754 
    755     FreePool (Buf);
    756     return NULL;
    757   }
    758 
    759   return Buf;
    760 }
    761 
    762 
    763 /**
    764   Build the whole array of descriptors. This function must
    765   be called after UsbGetMaxPacketSize0 returns the max packet
    766   size correctly for endpoint 0.
    767 
    768   @param  UsbDev                The Usb device.
    769 
    770   @retval EFI_SUCCESS           The descriptor table is build.
    771   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource for the descriptor.
    772 
    773 **/
    774 EFI_STATUS
    775 UsbBuildDescTable (
    776   IN USB_DEVICE           *UsbDev
    777   )
    778 {
    779   EFI_USB_CONFIG_DESCRIPTOR *Config;
    780   USB_DEVICE_DESC           *DevDesc;
    781   USB_CONFIG_DESC           *ConfigDesc;
    782   UINT8                     NumConfig;
    783   EFI_STATUS                Status;
    784   UINT8                     Index;
    785 
    786   //
    787   // Get the device descriptor, then allocate the configure
    788   // descriptor pointer array to hold configurations.
    789   //
    790   Status = UsbGetDevDesc (UsbDev);
    791 
    792   if (EFI_ERROR (Status)) {
    793     DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status));
    794     return Status;
    795   }
    796 
    797   DevDesc   = UsbDev->DevDesc;
    798   NumConfig = DevDesc->Desc.NumConfigurations;
    799   if (NumConfig == 0) {
    800     return EFI_DEVICE_ERROR;
    801   }
    802 
    803   DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));
    804   if (DevDesc->Configs == NULL) {
    805     return EFI_OUT_OF_RESOURCES;
    806   }
    807 
    808   DEBUG (( EFI_D_INFO, "UsbBuildDescTable: device has %d configures\n", NumConfig));
    809 
    810   //
    811   // Read each configurations, then parse them
    812   //
    813   for (Index = 0; Index < NumConfig; Index++) {
    814     Config = UsbGetOneConfig (UsbDev, Index);
    815 
    816     if (Config == NULL) {
    817       DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to get configure (index %d)\n", Index));
    818 
    819       //
    820       // If we can get the default descriptor, it is likely that the
    821       // device is still operational.
    822       //
    823       if (Index == 0) {
    824         return EFI_DEVICE_ERROR;
    825       }
    826 
    827       break;
    828     }
    829 
    830     ConfigDesc = UsbParseConfigDesc ((UINT8 *) Config, Config->TotalLength);
    831 
    832     FreePool (Config);
    833 
    834     if (ConfigDesc == NULL) {
    835       DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index));
    836 
    837       //
    838       // If we can get the default descriptor, it is likely that the
    839       // device is still operational.
    840       //
    841       if (Index == 0) {
    842         return EFI_DEVICE_ERROR;
    843       }
    844 
    845       break;
    846     }
    847 
    848     DevDesc->Configs[Index] = ConfigDesc;
    849   }
    850 
    851   //
    852   // Don't return error even this function failed because
    853   // it is possible for the device to not support strings.
    854   //
    855   Status = UsbBuildLangTable (UsbDev);
    856 
    857   if (EFI_ERROR (Status)) {
    858     DEBUG (( EFI_D_INFO, "UsbBuildDescTable: get language ID table %r\n", Status));
    859   }
    860 
    861   return EFI_SUCCESS;
    862 }
    863 
    864 
    865 /**
    866   Set the device's address.
    867 
    868   @param  UsbDev                The device to set address to.
    869   @param  Address               The address to set.
    870 
    871   @retval EFI_SUCCESS           The device is set to the address.
    872   @retval Others                Failed to set the device address.
    873 
    874 **/
    875 EFI_STATUS
    876 UsbSetAddress (
    877   IN USB_DEVICE           *UsbDev,
    878   IN UINT8                Address
    879   )
    880 {
    881   EFI_STATUS              Status;
    882 
    883   Status = UsbCtrlRequest (
    884              UsbDev,
    885              EfiUsbNoData,
    886              USB_REQ_TYPE_STANDARD,
    887              USB_TARGET_DEVICE,
    888              USB_REQ_SET_ADDRESS,
    889              Address,
    890              0,
    891              NULL,
    892              0
    893              );
    894 
    895   return Status;
    896 }
    897 
    898 
    899 /**
    900   Set the device's configuration. This function changes
    901   the device's internal state. UsbSelectConfig changes
    902   the Usb bus's internal state.
    903 
    904   @param  UsbDev                The USB device to set configure to.
    905   @param  ConfigIndex           The configure index to set.
    906 
    907   @retval EFI_SUCCESS           The device is configured now.
    908   @retval Others                Failed to set the device configure.
    909 
    910 **/
    911 EFI_STATUS
    912 UsbSetConfig (
    913   IN USB_DEVICE           *UsbDev,
    914   IN UINT8                ConfigIndex
    915   )
    916 {
    917   EFI_STATUS              Status;
    918 
    919   Status = UsbCtrlRequest (
    920              UsbDev,
    921              EfiUsbNoData,
    922              USB_REQ_TYPE_STANDARD,
    923              USB_TARGET_DEVICE,
    924              USB_REQ_SET_CONFIG,
    925              ConfigIndex,
    926              0,
    927              NULL,
    928              0
    929             );
    930 
    931   return Status;
    932 }
    933 
    934 
    935 /**
    936   Usb UsbIo interface to clear the feature. This is should
    937   only be used by HUB which is considered a device driver
    938   on top of the UsbIo interface.
    939 
    940   @param  UsbIo                 The UsbIo interface.
    941   @param  Target                The target of the transfer: endpoint/device.
    942   @param  Feature               The feature to clear.
    943   @param  Index                 The wIndex parameter.
    944 
    945   @retval EFI_SUCCESS           The device feature is cleared.
    946   @retval Others                Failed to clear the feature.
    947 
    948 **/
    949 EFI_STATUS
    950 UsbIoClearFeature (
    951   IN  EFI_USB_IO_PROTOCOL *UsbIo,
    952   IN  UINTN               Target,
    953   IN  UINT16              Feature,
    954   IN  UINT16              Index
    955   )
    956 {
    957   EFI_USB_DEVICE_REQUEST  DevReq;
    958   UINT32                  UsbResult;
    959   EFI_STATUS              Status;
    960 
    961   DevReq.RequestType  = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, Target);
    962   DevReq.Request      = USB_REQ_CLEAR_FEATURE;
    963   DevReq.Value        = Feature;
    964   DevReq.Index        = Index;
    965   DevReq.Length       = 0;
    966 
    967   Status = UsbIo->UsbControlTransfer (
    968                     UsbIo,
    969                     &DevReq,
    970                     EfiUsbNoData,
    971                     USB_CLEAR_FEATURE_REQUEST_TIMEOUT,
    972                     NULL,
    973                     0,
    974                     &UsbResult
    975                     );
    976 
    977   return Status;
    978 }
    979