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