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