1/** @file
2
3    Manage Usb Descriptor List
4
5Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
6This program and the accompanying materials
7are licensed and made available under the terms and conditions of the BSD License
8which accompanies this distribution.  The full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT 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**/
25VOID
26UsbFreeInterfaceDesc (
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**/
64VOID
65UsbFreeConfigDesc (
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**/
110VOID
111UsbFreeDevDesc (
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**/
142VOID *
143UsbCreateDesc (
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 + Head->Len) ||
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**/
231USB_INTERFACE_SETTING *
232UsbParseInterfaceDesc (
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
289ON_EXIT:
290  *Consumed = Offset;
291  return Setting;
292
293ON_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**/
308USB_CONFIG_DESC *
309UsbParseConfigDesc (
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
399ON_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**/
425EFI_STATUS
426UsbCtrlRequest (
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**/
485EFI_STATUS
486UsbCtrlGetDesc (
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**/
524EFI_STATUS
525UsbGetMaxPacketSize0 (
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**/
566EFI_STATUS
567UsbGetDevDesc (
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**/
611EFI_USB_STRING_DESCRIPTOR *
612UsbGetOneString (
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**/
663EFI_STATUS
664UsbBuildLangTable (
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
701ON_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**/
719EFI_USB_CONFIG_DESCRIPTOR *
720UsbGetOneConfig (
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**/
774EFI_STATUS
775UsbBuildDescTable (
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**/
875EFI_STATUS
876UsbSetAddress (
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**/
911EFI_STATUS
912UsbSetConfig (
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**/
949EFI_STATUS
950UsbIoClearFeature (
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