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