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