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