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