3 Manage Usb Descriptor List
5 Copyright (c) 2007 - 2018, 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
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.
20 Free the interface setting descriptor.
22 @param Setting The descriptor to free.
26 UsbFreeInterfaceDesc (
27 IN USB_INTERFACE_SETTING
*Setting
30 USB_ENDPOINT_DESC
*Ep
;
33 if (Setting
->Endpoints
!= NULL
) {
35 // Each interface setting may have several endpoints, free them first.
37 for (Index
= 0; Index
< Setting
->Desc
.NumEndpoints
; Index
++) {
38 Ep
= Setting
->Endpoints
[Index
];
46 // Only call FreePool() if NumEndpoints > 0.
48 if (Setting
->Desc
.NumEndpoints
> 0) {
49 FreePool (Setting
->Endpoints
);
58 Free a configuration descriptor with its interface
59 descriptors. It may be initialized partially.
61 @param Config The configuration descriptor to free.
66 IN USB_CONFIG_DESC
*Config
69 USB_INTERFACE_DESC
*Interface
;
73 if (Config
->Interfaces
!= NULL
) {
75 // A configuration may have several interfaces, free the interface
77 for (Index
= 0; Index
< Config
->Desc
.NumInterfaces
; Index
++) {
78 Interface
= Config
->Interfaces
[Index
];
80 if (Interface
== NULL
) {
85 // Each interface may have several settings, free the settings
87 for (SetIndex
= 0; SetIndex
< Interface
->NumOfSetting
; SetIndex
++) {
88 if (Interface
->Settings
[SetIndex
] != NULL
) {
89 UsbFreeInterfaceDesc (Interface
->Settings
[SetIndex
]);
96 FreePool (Config
->Interfaces
);
105 Free a device descriptor with its configurations.
107 @param DevDesc The device descriptor.
112 IN USB_DEVICE_DESC
*DevDesc
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
]);
124 FreePool (DevDesc
->Configs
);
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.
139 @return Created descriptor or NULL.
161 case USB_DESC_TYPE_DEVICE
:
162 DescLen
= sizeof (EFI_USB_DEVICE_DESCRIPTOR
);
163 CtrlLen
= sizeof (USB_DEVICE_DESC
);
166 case USB_DESC_TYPE_CONFIG
:
167 DescLen
= sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
168 CtrlLen
= sizeof (USB_CONFIG_DESC
);
171 case USB_DESC_TYPE_INTERFACE
:
172 DescLen
= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
173 CtrlLen
= sizeof (USB_INTERFACE_SETTING
);
176 case USB_DESC_TYPE_ENDPOINT
:
177 DescLen
= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
178 CtrlLen
= sizeof (USB_ENDPOINT_DESC
);
187 // Total length is too small that cannot hold the single descriptor header plus data.
189 if (Len
<= sizeof (USB_DESC_HEAD
)) {
190 DEBUG ((DEBUG_ERROR
, "UsbCreateDesc: met mal-format descriptor, total length = %d!\n", Len
));
195 // All the descriptor has a common LTV (Length, Type, Value)
196 // format. Skip the descriptor that isn't of this Type
199 Head
= (USB_DESC_HEAD
*)DescBuf
;
200 while (Offset
< Len
- sizeof (USB_DESC_HEAD
)) {
202 // Above condition make sure Head->Len and Head->Type are safe to access
204 Head
= (USB_DESC_HEAD
*)&DescBuf
[Offset
];
206 if (Head
->Len
== 0) {
207 DEBUG ((DEBUG_ERROR
, "UsbCreateDesc: met mal-format descriptor, Head->Len = 0!\n"));
212 // Make sure no overflow when adding Head->Len to Offset.
214 if (Head
->Len
> MAX_UINTN
- Offset
) {
215 DEBUG ((DEBUG_ERROR
, "UsbCreateDesc: met mal-format descriptor, Head->Len = %d!\n", Head
->Len
));
221 if (Head
->Type
== Type
) {
227 // Head->Len is invalid resulting data beyond boundary, or
228 // Descriptor cannot be found: No such type.
231 DEBUG ((DEBUG_ERROR
, "UsbCreateDesc: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset
, Len
));
235 if ((Head
->Type
!= Type
) || (Head
->Len
< DescLen
)) {
236 DEBUG ((DEBUG_ERROR
, "UsbCreateDesc: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head
->Type
, Head
->Len
));
240 Desc
= AllocateZeroPool ((UINTN
) CtrlLen
);
245 CopyMem (Desc
, Head
, (UINTN
) DescLen
);
254 Parse an interface descriptor and its endpoints.
256 @param DescBuf The buffer of raw descriptor.
257 @param Len The length of the raw descriptor buffer.
258 @param Consumed The number of raw descriptor consumed.
260 @return The create interface setting or NULL if failed.
263 USB_INTERFACE_SETTING
*
264 UsbParseInterfaceDesc (
270 USB_INTERFACE_SETTING
*Setting
;
271 USB_ENDPOINT_DESC
*Ep
;
278 Setting
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_INTERFACE
, &Used
);
280 if (Setting
== NULL
) {
281 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));
288 // Create an array to hold the interface's endpoints
290 NumEp
= Setting
->Desc
.NumEndpoints
;
292 DEBUG (( EFI_D_INFO
, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
293 Setting
->Desc
.InterfaceNumber
, Setting
->Desc
.AlternateSetting
, (UINT32
)NumEp
));
299 Setting
->Endpoints
= AllocateZeroPool (sizeof (USB_ENDPOINT_DESC
*) * NumEp
);
301 if (Setting
->Endpoints
== NULL
) {
306 // Create the endpoints for this interface
308 for (Index
= 0; (Index
< NumEp
) && (Offset
< Len
); Index
++) {
309 Ep
= UsbCreateDesc (DescBuf
+ Offset
, Len
- Offset
, USB_DESC_TYPE_ENDPOINT
, &Used
);
312 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32
)Index
));
316 Setting
->Endpoints
[Index
] = Ep
;
326 UsbFreeInterfaceDesc (Setting
);
332 Parse the configuration descriptor and its interfaces.
334 @param DescBuf The buffer of raw descriptor.
335 @param Len The length of the raw descriptor buffer.
337 @return The created configuration descriptor.
346 USB_CONFIG_DESC
*Config
;
347 USB_INTERFACE_SETTING
*Setting
;
348 USB_INTERFACE_DESC
*Interface
;
353 ASSERT (DescBuf
!= NULL
);
355 Config
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_CONFIG
, &Consumed
);
357 if (Config
== NULL
) {
362 // Initialize an array of setting for the configuration's interfaces.
364 NumIf
= Config
->Desc
.NumInterfaces
;
365 Config
->Interfaces
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
*) * NumIf
);
367 if (Config
->Interfaces
== NULL
) {
371 DEBUG (( EFI_D_INFO
, "UsbParseConfigDesc: config %d has %d interfaces\n",
372 Config
->Desc
.ConfigurationValue
, (UINT32
)NumIf
));
374 for (Index
= 0; Index
< NumIf
; Index
++) {
375 Interface
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
));
377 if (Interface
== NULL
) {
381 Config
->Interfaces
[Index
] = Interface
;
385 // If a configuration has several interfaces, these interfaces are
386 // numbered from zero to n. If a interface has several settings,
387 // these settings are also number from zero to m. The interface
388 // setting must be organized as |interface 0, setting 0|interface 0
389 // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
390 // USB2.0 spec, page 267.
396 // Make allowances for devices that return extra data at the
397 // end of their config descriptors
399 while (Len
>= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
)) {
400 Setting
= UsbParseInterfaceDesc (DescBuf
, Len
, &Consumed
);
402 if (Setting
== NULL
) {
403 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));
406 } else if (Setting
->Desc
.InterfaceNumber
>= NumIf
) {
407 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
409 UsbFreeInterfaceDesc (Setting
);
414 // Insert the descriptor to the corresponding set.
416 Interface
= Config
->Interfaces
[Setting
->Desc
.InterfaceNumber
];
418 if (Interface
->NumOfSetting
>= USB_MAX_INTERFACE_SETTING
) {
422 Interface
->Settings
[Interface
->NumOfSetting
] = Setting
;
423 Interface
->NumOfSetting
++;
432 UsbFreeConfigDesc (Config
);
438 USB standard control transfer support routine. This
439 function is used by USB device. It is possible that
440 the device's interfaces are still waiting to be
443 @param UsbDev The usb device.
444 @param Direction The direction of data transfer.
445 @param Type Standard / class specific / vendor specific.
446 @param Target The receiving target.
447 @param Request Which request.
448 @param Value The wValue parameter of the request.
449 @param Index The wIndex parameter of the request.
450 @param Buf The buffer to receive data into / transmit from.
451 @param Length The length of the buffer.
453 @retval EFI_SUCCESS The control request is executed.
454 @retval EFI_DEVICE_ERROR Failed to execute the control transfer.
459 IN USB_DEVICE
*UsbDev
,
460 IN EFI_USB_DATA_DIRECTION Direction
,
470 EFI_USB_DEVICE_REQUEST DevReq
;
475 ASSERT ((UsbDev
!= NULL
) && (UsbDev
->Bus
!= NULL
));
477 DevReq
.RequestType
= USB_REQUEST_TYPE (Direction
, Type
, Target
);
478 DevReq
.Request
= (UINT8
) Request
;
479 DevReq
.Value
= Value
;
480 DevReq
.Index
= Index
;
481 DevReq
.Length
= (UINT16
) Length
;
484 Status
= UsbHcControlTransfer (
493 USB_GENERAL_DEVICE_REQUEST_TIMEOUT
,
503 Get the standard descriptors.
505 @param UsbDev The USB device to read descriptor from.
506 @param DescType The type of descriptor to read.
507 @param DescIndex The index of descriptor to read.
508 @param LangId Language ID, only used to get string, otherwise set
510 @param Buf The buffer to hold the descriptor read.
511 @param Length The length of the buffer.
513 @retval EFI_SUCCESS The descriptor is read OK.
514 @retval Others Failed to retrieve the descriptor.
519 IN USB_DEVICE
*UsbDev
,
529 Status
= UsbCtrlRequest (
532 USB_REQ_TYPE_STANDARD
,
534 USB_REQ_GET_DESCRIPTOR
,
535 (UINT16
) ((DescType
<< 8) | DescIndex
),
546 Return the max packet size for endpoint zero. This function
547 is the first function called to get descriptors during bus
550 @param UsbDev The usb device.
552 @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved.
553 @retval EFI_DEVICE_ERROR Failed to retrieve it.
557 UsbGetMaxPacketSize0 (
558 IN USB_DEVICE
*UsbDev
561 EFI_USB_DEVICE_DESCRIPTOR DevDesc
;
567 // Get the first 8 bytes of the device descriptor which contains
568 // max packet size for endpoint 0, which is at least 8.
570 for (Index
= 0; Index
< 3; Index
++) {
571 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_DEVICE
, 0, 0, &DevDesc
, 8);
573 if (!EFI_ERROR (Status
)) {
574 if ((DevDesc
.BcdUSB
>= 0x0300) && (DevDesc
.MaxPacketSize0
== 9)) {
575 UsbDev
->MaxPacket0
= 1 << 9;
578 UsbDev
->MaxPacket0
= DevDesc
.MaxPacketSize0
;
582 gBS
->Stall (USB_RETRY_MAX_PACK_SIZE_STALL
);
585 return EFI_DEVICE_ERROR
;
590 Get the device descriptor for the device.
592 @param UsbDev The Usb device to retrieve descriptor from.
594 @retval EFI_SUCCESS The device descriptor is returned.
595 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
600 IN USB_DEVICE
*UsbDev
603 USB_DEVICE_DESC
*DevDesc
;
606 DevDesc
= AllocateZeroPool (sizeof (USB_DEVICE_DESC
));
608 if (DevDesc
== NULL
) {
609 return EFI_OUT_OF_RESOURCES
;
612 Status
= UsbCtrlGetDesc (
614 USB_DESC_TYPE_DEVICE
,
618 sizeof (EFI_USB_DEVICE_DESCRIPTOR
)
621 if (EFI_ERROR (Status
)) {
622 gBS
->FreePool (DevDesc
);
624 UsbDev
->DevDesc
= DevDesc
;
632 Retrieve the indexed string for the language. It requires two
633 steps to get a string, first to get the string's length. Then
636 @param UsbDev The usb device.
637 @param Index The index the string to retrieve.
638 @param LangId Language ID.
640 @return The created string descriptor or NULL.
643 EFI_USB_STRING_DESCRIPTOR
*
645 IN USB_DEVICE
*UsbDev
,
650 EFI_USB_STRING_DESCRIPTOR Desc
;
655 // First get two bytes which contains the string length.
657 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_STRING
, Index
, LangId
, &Desc
, 2);
660 // Reject if Length even cannot cover itself, or odd because Unicode string byte length should be even.
662 if (EFI_ERROR (Status
) ||
663 (Desc
.Length
< OFFSET_OF (EFI_USB_STRING_DESCRIPTOR
, Length
) + sizeof (Desc
.Length
)) ||
664 (Desc
.Length
% 2 != 0)
669 Buf
= AllocateZeroPool (Desc
.Length
);
675 Status
= UsbCtrlGetDesc (
677 USB_DESC_TYPE_STRING
,
684 if (EFI_ERROR (Status
)) {
689 return (EFI_USB_STRING_DESCRIPTOR
*) Buf
;
694 Build the language ID table for string descriptors.
696 @param UsbDev The Usb device.
698 @retval EFI_UNSUPPORTED This device doesn't support string table.
703 IN USB_DEVICE
*UsbDev
706 EFI_USB_STRING_DESCRIPTOR
*Desc
;
713 // The string of language ID zero returns the supported languages
715 Desc
= UsbGetOneString (UsbDev
, 0, 0);
718 return EFI_UNSUPPORTED
;
721 if (Desc
->Length
< 4) {
722 Status
= EFI_UNSUPPORTED
;
726 Status
= EFI_SUCCESS
;
728 Max
= (Desc
->Length
- 2) / 2;
729 Max
= MIN(Max
, USB_MAX_LANG_ID
);
731 Point
= Desc
->String
;
732 for (Index
= 0; Index
< Max
; Index
++) {
733 UsbDev
->LangId
[Index
] = *Point
;
737 UsbDev
->TotalLangId
= (UINT16
)Max
;
740 gBS
->FreePool (Desc
);
746 Retrieve the indexed configure for the device. USB device
747 returns the configuration together with the interfaces for
748 this configuration. Configuration descriptor is also of
751 @param UsbDev The Usb interface.
752 @param Index The index of the configuration.
754 @return The created configuration descriptor.
757 EFI_USB_CONFIG_DESCRIPTOR
*
759 IN USB_DEVICE
*UsbDev
,
763 EFI_USB_CONFIG_DESCRIPTOR Desc
;
768 // First get four bytes which contains the total length
769 // for this configuration.
771 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, &Desc
, 8);
773 if (EFI_ERROR (Status
)) {
774 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get descript length(%d) %r\n",
775 Desc
.TotalLength
, Status
));
780 DEBUG (( EFI_D_INFO
, "UsbGetOneConfig: total length is %d\n", Desc
.TotalLength
));
783 // Reject if TotalLength even cannot cover itself.
785 if (Desc
.TotalLength
< OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR
, TotalLength
) + sizeof (Desc
.TotalLength
)) {
789 Buf
= AllocateZeroPool (Desc
.TotalLength
);
795 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, Buf
, Desc
.TotalLength
);
797 if (EFI_ERROR (Status
)) {
798 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get full descript %r\n", Status
));
809 Build the whole array of descriptors. This function must
810 be called after UsbGetMaxPacketSize0 returns the max packet
811 size correctly for endpoint 0.
813 @param UsbDev The Usb device.
815 @retval EFI_SUCCESS The descriptor table is build.
816 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor.
821 IN USB_DEVICE
*UsbDev
824 EFI_USB_CONFIG_DESCRIPTOR
*Config
;
825 USB_DEVICE_DESC
*DevDesc
;
826 USB_CONFIG_DESC
*ConfigDesc
;
832 // Get the device descriptor, then allocate the configure
833 // descriptor pointer array to hold configurations.
835 Status
= UsbGetDevDesc (UsbDev
);
837 if (EFI_ERROR (Status
)) {
838 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status
));
842 DevDesc
= UsbDev
->DevDesc
;
843 NumConfig
= DevDesc
->Desc
.NumConfigurations
;
844 if (NumConfig
== 0) {
845 return EFI_DEVICE_ERROR
;
848 DevDesc
->Configs
= AllocateZeroPool (NumConfig
* sizeof (USB_CONFIG_DESC
*));
849 if (DevDesc
->Configs
== NULL
) {
850 return EFI_OUT_OF_RESOURCES
;
853 DEBUG (( EFI_D_INFO
, "UsbBuildDescTable: device has %d configures\n", NumConfig
));
856 // Read each configurations, then parse them
858 for (Index
= 0; Index
< NumConfig
; Index
++) {
859 Config
= UsbGetOneConfig (UsbDev
, Index
);
861 if (Config
== NULL
) {
862 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get configure (index %d)\n", Index
));
865 // If we can get the default descriptor, it is likely that the
866 // device is still operational.
869 return EFI_DEVICE_ERROR
;
875 ConfigDesc
= UsbParseConfigDesc ((UINT8
*) Config
, Config
->TotalLength
);
879 if (ConfigDesc
== NULL
) {
880 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index
));
883 // If we can get the default descriptor, it is likely that the
884 // device is still operational.
887 return EFI_DEVICE_ERROR
;
893 DevDesc
->Configs
[Index
] = ConfigDesc
;
897 // Don't return error even this function failed because
898 // it is possible for the device to not support strings.
900 Status
= UsbBuildLangTable (UsbDev
);
902 if (EFI_ERROR (Status
)) {
903 DEBUG (( EFI_D_INFO
, "UsbBuildDescTable: get language ID table %r\n", Status
));
911 Set the device's address.
913 @param UsbDev The device to set address to.
914 @param Address The address to set.
916 @retval EFI_SUCCESS The device is set to the address.
917 @retval Others Failed to set the device address.
922 IN USB_DEVICE
*UsbDev
,
928 Status
= UsbCtrlRequest (
931 USB_REQ_TYPE_STANDARD
,
945 Set the device's configuration. This function changes
946 the device's internal state. UsbSelectConfig changes
947 the Usb bus's internal state.
949 @param UsbDev The USB device to set configure to.
950 @param ConfigIndex The configure index to set.
952 @retval EFI_SUCCESS The device is configured now.
953 @retval Others Failed to set the device configure.
958 IN USB_DEVICE
*UsbDev
,
964 Status
= UsbCtrlRequest (
967 USB_REQ_TYPE_STANDARD
,
981 Usb UsbIo interface to clear the feature. This is should
982 only be used by HUB which is considered a device driver
983 on top of the UsbIo interface.
985 @param UsbIo The UsbIo interface.
986 @param Target The target of the transfer: endpoint/device.
987 @param Feature The feature to clear.
988 @param Index The wIndex parameter.
990 @retval EFI_SUCCESS The device feature is cleared.
991 @retval Others Failed to clear the feature.
996 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
1002 EFI_USB_DEVICE_REQUEST DevReq
;
1006 DevReq
.RequestType
= USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, Target
);
1007 DevReq
.Request
= USB_REQ_CLEAR_FEATURE
;
1008 DevReq
.Value
= Feature
;
1009 DevReq
.Index
= Index
;
1012 Status
= UsbIo
->UsbControlTransfer (
1016 USB_CLEAR_FEATURE_REQUEST_TIMEOUT
,