• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 
3     Manage Usb Descriptor List
4 
5 Copyright (c) 2007 - 2016, 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
UsbFreeInterfaceDesc(IN USB_INTERFACE_SETTING * Setting)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
UsbFreeConfigDesc(IN USB_CONFIG_DESC * Config)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
UsbFreeDevDesc(IN USB_DEVICE_DESC * DevDesc)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 *
UsbCreateDesc(IN UINT8 * DescBuf,IN UINTN Len,IN UINT8 Type,OUT UINTN * Consumed)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 + 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 **/
231 USB_INTERFACE_SETTING *
UsbParseInterfaceDesc(IN UINT8 * DescBuf,IN UINTN Len,OUT UINTN * Consumed)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 *
UsbParseConfigDesc(IN UINT8 * DescBuf,IN UINTN Len)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
UsbCtrlRequest(IN USB_DEVICE * UsbDev,IN EFI_USB_DATA_DIRECTION Direction,IN UINTN Type,IN UINTN Target,IN UINTN Request,IN UINT16 Value,IN UINT16 Index,IN OUT VOID * Buf,IN UINTN Length)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
UsbCtrlGetDesc(IN USB_DEVICE * UsbDev,IN UINTN DescType,IN UINTN DescIndex,IN UINT16 LangId,OUT VOID * Buf,IN UINTN Length)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
UsbGetMaxPacketSize0(IN USB_DEVICE * UsbDev)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
UsbGetDevDesc(IN USB_DEVICE * UsbDev)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 *
UsbGetOneString(IN USB_DEVICE * UsbDev,IN UINT8 Index,IN UINT16 LangId)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
UsbBuildLangTable(IN USB_DEVICE * UsbDev)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 *
UsbGetOneConfig(IN USB_DEVICE * UsbDev,IN UINT8 Index)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
UsbBuildDescTable(IN USB_DEVICE * UsbDev)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
UsbSetAddress(IN USB_DEVICE * UsbDev,IN UINT8 Address)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
UsbSetConfig(IN USB_DEVICE * UsbDev,IN UINT8 ConfigIndex)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
UsbIoClearFeature(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINTN Target,IN UINT16 Feature,IN UINT16 Index)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