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