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
));
234 if ((Head
->Type
!= Type
) || (Head
->Len
< DescLen
)) {
235 DEBUG ((DEBUG_ERROR
, "UsbCreateDesc: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head
->Type
, Head
->Len
));
239 Desc
= AllocateZeroPool ((UINTN
) CtrlLen
);
244 CopyMem (Desc
, Head
, (UINTN
) DescLen
);
253 Parse an interface descriptor and its endpoints.
255 @param DescBuf The buffer of raw descriptor.
256 @param Len The length of the raw descriptor buffer.
257 @param Consumed The number of raw descriptor consumed.
259 @return The create interface setting or NULL if failed.
262 USB_INTERFACE_SETTING
*
263 UsbParseInterfaceDesc (
269 USB_INTERFACE_SETTING
*Setting
;
270 USB_ENDPOINT_DESC
*Ep
;
277 Setting
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_INTERFACE
, &Used
);
279 if (Setting
== NULL
) {
280 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));
287 // Create an array to hold the interface's endpoints
289 NumEp
= Setting
->Desc
.NumEndpoints
;
291 DEBUG (( EFI_D_INFO
, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
292 Setting
->Desc
.InterfaceNumber
, Setting
->Desc
.AlternateSetting
, (UINT32
)NumEp
));
298 Setting
->Endpoints
= AllocateZeroPool (sizeof (USB_ENDPOINT_DESC
*) * NumEp
);
300 if (Setting
->Endpoints
== NULL
) {
305 // Create the endpoints for this interface
307 for (Index
= 0; (Index
< NumEp
) && (Offset
< Len
); Index
++) {
308 Ep
= UsbCreateDesc (DescBuf
+ Offset
, Len
- Offset
, USB_DESC_TYPE_ENDPOINT
, &Used
);
311 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32
)Index
));
315 Setting
->Endpoints
[Index
] = Ep
;
325 UsbFreeInterfaceDesc (Setting
);
331 Parse the configuration descriptor and its interfaces.
333 @param DescBuf The buffer of raw descriptor.
334 @param Len The length of the raw descriptor buffer.
336 @return The created configuration descriptor.
345 USB_CONFIG_DESC
*Config
;
346 USB_INTERFACE_SETTING
*Setting
;
347 USB_INTERFACE_DESC
*Interface
;
352 ASSERT (DescBuf
!= NULL
);
354 Config
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_CONFIG
, &Consumed
);
356 if (Config
== NULL
) {
361 // Initialize an array of setting for the configuration's interfaces.
363 NumIf
= Config
->Desc
.NumInterfaces
;
364 Config
->Interfaces
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
*) * NumIf
);
366 if (Config
->Interfaces
== NULL
) {
370 DEBUG (( EFI_D_INFO
, "UsbParseConfigDesc: config %d has %d interfaces\n",
371 Config
->Desc
.ConfigurationValue
, (UINT32
)NumIf
));
373 for (Index
= 0; Index
< NumIf
; Index
++) {
374 Interface
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
));
376 if (Interface
== NULL
) {
380 Config
->Interfaces
[Index
] = Interface
;
384 // If a configuration has several interfaces, these interfaces are
385 // numbered from zero to n. If a interface has several settings,
386 // these settings are also number from zero to m. The interface
387 // setting must be organized as |interface 0, setting 0|interface 0
388 // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
389 // USB2.0 spec, page 267.
395 // Make allowances for devices that return extra data at the
396 // end of their config descriptors
398 while (Len
>= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
)) {
399 Setting
= UsbParseInterfaceDesc (DescBuf
, Len
, &Consumed
);
401 if (Setting
== NULL
) {
402 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));
405 } else if (Setting
->Desc
.InterfaceNumber
>= NumIf
) {
406 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
408 UsbFreeInterfaceDesc (Setting
);
413 // Insert the descriptor to the corresponding set.
415 Interface
= Config
->Interfaces
[Setting
->Desc
.InterfaceNumber
];
417 if (Interface
->NumOfSetting
>= USB_MAX_INTERFACE_SETTING
) {
421 Interface
->Settings
[Interface
->NumOfSetting
] = Setting
;
422 Interface
->NumOfSetting
++;
431 UsbFreeConfigDesc (Config
);
437 USB standard control transfer support routine. This
438 function is used by USB device. It is possible that
439 the device's interfaces are still waiting to be
442 @param UsbDev The usb device.
443 @param Direction The direction of data transfer.
444 @param Type Standard / class specific / vendor specific.
445 @param Target The receiving target.
446 @param Request Which request.
447 @param Value The wValue parameter of the request.
448 @param Index The wIndex parameter of the request.
449 @param Buf The buffer to receive data into / transmit from.
450 @param Length The length of the buffer.
452 @retval EFI_SUCCESS The control request is executed.
453 @retval EFI_DEVICE_ERROR Failed to execute the control transfer.
458 IN USB_DEVICE
*UsbDev
,
459 IN EFI_USB_DATA_DIRECTION Direction
,
469 EFI_USB_DEVICE_REQUEST DevReq
;
474 ASSERT ((UsbDev
!= NULL
) && (UsbDev
->Bus
!= NULL
));
476 DevReq
.RequestType
= USB_REQUEST_TYPE (Direction
, Type
, Target
);
477 DevReq
.Request
= (UINT8
) Request
;
478 DevReq
.Value
= Value
;
479 DevReq
.Index
= Index
;
480 DevReq
.Length
= (UINT16
) Length
;
483 Status
= UsbHcControlTransfer (
492 USB_GENERAL_DEVICE_REQUEST_TIMEOUT
,
502 Get the standard descriptors.
504 @param UsbDev The USB device to read descriptor from.
505 @param DescType The type of descriptor to read.
506 @param DescIndex The index of descriptor to read.
507 @param LangId Language ID, only used to get string, otherwise set
509 @param Buf The buffer to hold the descriptor read.
510 @param Length The length of the buffer.
512 @retval EFI_SUCCESS The descriptor is read OK.
513 @retval Others Failed to retrieve the descriptor.
518 IN USB_DEVICE
*UsbDev
,
528 Status
= UsbCtrlRequest (
531 USB_REQ_TYPE_STANDARD
,
533 USB_REQ_GET_DESCRIPTOR
,
534 (UINT16
) ((DescType
<< 8) | DescIndex
),
545 Return the max packet size for endpoint zero. This function
546 is the first function called to get descriptors during bus
549 @param UsbDev The usb device.
551 @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved.
552 @retval EFI_DEVICE_ERROR Failed to retrieve it.
556 UsbGetMaxPacketSize0 (
557 IN USB_DEVICE
*UsbDev
560 EFI_USB_DEVICE_DESCRIPTOR DevDesc
;
566 // Get the first 8 bytes of the device descriptor which contains
567 // max packet size for endpoint 0, which is at least 8.
569 for (Index
= 0; Index
< 3; Index
++) {
570 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_DEVICE
, 0, 0, &DevDesc
, 8);
572 if (!EFI_ERROR (Status
)) {
573 if ((DevDesc
.BcdUSB
>= 0x0300) && (DevDesc
.MaxPacketSize0
== 9)) {
574 UsbDev
->MaxPacket0
= 1 << 9;
577 UsbDev
->MaxPacket0
= DevDesc
.MaxPacketSize0
;
581 gBS
->Stall (USB_RETRY_MAX_PACK_SIZE_STALL
);
584 return EFI_DEVICE_ERROR
;
589 Get the device descriptor for the device.
591 @param UsbDev The Usb device to retrieve descriptor from.
593 @retval EFI_SUCCESS The device descriptor is returned.
594 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
599 IN USB_DEVICE
*UsbDev
602 USB_DEVICE_DESC
*DevDesc
;
605 DevDesc
= AllocateZeroPool (sizeof (USB_DEVICE_DESC
));
607 if (DevDesc
== NULL
) {
608 return EFI_OUT_OF_RESOURCES
;
611 Status
= UsbCtrlGetDesc (
613 USB_DESC_TYPE_DEVICE
,
617 sizeof (EFI_USB_DEVICE_DESCRIPTOR
)
620 if (EFI_ERROR (Status
)) {
621 gBS
->FreePool (DevDesc
);
623 UsbDev
->DevDesc
= DevDesc
;
631 Retrieve the indexed string for the language. It requires two
632 steps to get a string, first to get the string's length. Then
635 @param UsbDev The usb device.
636 @param Index The index the string to retrieve.
637 @param LangId Language ID.
639 @return The created string descriptor or NULL.
642 EFI_USB_STRING_DESCRIPTOR
*
644 IN USB_DEVICE
*UsbDev
,
649 EFI_USB_STRING_DESCRIPTOR Desc
;
654 // First get two bytes which contains the string length.
656 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_STRING
, Index
, LangId
, &Desc
, 2);
658 if (EFI_ERROR (Status
)) {
662 Buf
= AllocateZeroPool (Desc
.Length
);
668 Status
= UsbCtrlGetDesc (
670 USB_DESC_TYPE_STRING
,
677 if (EFI_ERROR (Status
)) {
682 return (EFI_USB_STRING_DESCRIPTOR
*) Buf
;
687 Build the language ID table for string descriptors.
689 @param UsbDev The Usb device.
691 @retval EFI_UNSUPPORTED This device doesn't support string table.
696 IN USB_DEVICE
*UsbDev
699 EFI_USB_STRING_DESCRIPTOR
*Desc
;
706 // The string of language ID zero returns the supported languages
708 Desc
= UsbGetOneString (UsbDev
, 0, 0);
711 return EFI_UNSUPPORTED
;
714 if (Desc
->Length
< 4) {
715 Status
= EFI_UNSUPPORTED
;
719 Status
= EFI_SUCCESS
;
721 Max
= (Desc
->Length
- 2) / 2;
722 Max
= MIN(Max
, USB_MAX_LANG_ID
);
724 Point
= Desc
->String
;
725 for (Index
= 0; Index
< Max
; Index
++) {
726 UsbDev
->LangId
[Index
] = *Point
;
730 UsbDev
->TotalLangId
= (UINT16
)Max
;
733 gBS
->FreePool (Desc
);
739 Retrieve the indexed configure for the device. USB device
740 returns the configuration together with the interfaces for
741 this configuration. Configuration descriptor is also of
744 @param UsbDev The Usb interface.
745 @param Index The index of the configuration.
747 @return The created configuration descriptor.
750 EFI_USB_CONFIG_DESCRIPTOR
*
752 IN USB_DEVICE
*UsbDev
,
756 EFI_USB_CONFIG_DESCRIPTOR Desc
;
761 // First get four bytes which contains the total length
762 // for this configuration.
764 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, &Desc
, 8);
766 if (EFI_ERROR (Status
)) {
767 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get descript length(%d) %r\n",
768 Desc
.TotalLength
, Status
));
773 DEBUG (( EFI_D_INFO
, "UsbGetOneConfig: total length is %d\n", Desc
.TotalLength
));
776 // Reject if TotalLength even cannot cover itself.
778 if (Desc
.TotalLength
< OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR
, TotalLength
) + sizeof (Desc
.TotalLength
)) {
782 Buf
= AllocateZeroPool (Desc
.TotalLength
);
788 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, Buf
, Desc
.TotalLength
);
790 if (EFI_ERROR (Status
)) {
791 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get full descript %r\n", Status
));
802 Build the whole array of descriptors. This function must
803 be called after UsbGetMaxPacketSize0 returns the max packet
804 size correctly for endpoint 0.
806 @param UsbDev The Usb device.
808 @retval EFI_SUCCESS The descriptor table is build.
809 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor.
814 IN USB_DEVICE
*UsbDev
817 EFI_USB_CONFIG_DESCRIPTOR
*Config
;
818 USB_DEVICE_DESC
*DevDesc
;
819 USB_CONFIG_DESC
*ConfigDesc
;
825 // Get the device descriptor, then allocate the configure
826 // descriptor pointer array to hold configurations.
828 Status
= UsbGetDevDesc (UsbDev
);
830 if (EFI_ERROR (Status
)) {
831 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status
));
835 DevDesc
= UsbDev
->DevDesc
;
836 NumConfig
= DevDesc
->Desc
.NumConfigurations
;
837 if (NumConfig
== 0) {
838 return EFI_DEVICE_ERROR
;
841 DevDesc
->Configs
= AllocateZeroPool (NumConfig
* sizeof (USB_CONFIG_DESC
*));
842 if (DevDesc
->Configs
== NULL
) {
843 return EFI_OUT_OF_RESOURCES
;
846 DEBUG (( EFI_D_INFO
, "UsbBuildDescTable: device has %d configures\n", NumConfig
));
849 // Read each configurations, then parse them
851 for (Index
= 0; Index
< NumConfig
; Index
++) {
852 Config
= UsbGetOneConfig (UsbDev
, Index
);
854 if (Config
== NULL
) {
855 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get configure (index %d)\n", Index
));
858 // If we can get the default descriptor, it is likely that the
859 // device is still operational.
862 return EFI_DEVICE_ERROR
;
868 ConfigDesc
= UsbParseConfigDesc ((UINT8
*) Config
, Config
->TotalLength
);
872 if (ConfigDesc
== NULL
) {
873 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index
));
876 // If we can get the default descriptor, it is likely that the
877 // device is still operational.
880 return EFI_DEVICE_ERROR
;
886 DevDesc
->Configs
[Index
] = ConfigDesc
;
890 // Don't return error even this function failed because
891 // it is possible for the device to not support strings.
893 Status
= UsbBuildLangTable (UsbDev
);
895 if (EFI_ERROR (Status
)) {
896 DEBUG (( EFI_D_INFO
, "UsbBuildDescTable: get language ID table %r\n", Status
));
904 Set the device's address.
906 @param UsbDev The device to set address to.
907 @param Address The address to set.
909 @retval EFI_SUCCESS The device is set to the address.
910 @retval Others Failed to set the device address.
915 IN USB_DEVICE
*UsbDev
,
921 Status
= UsbCtrlRequest (
924 USB_REQ_TYPE_STANDARD
,
938 Set the device's configuration. This function changes
939 the device's internal state. UsbSelectConfig changes
940 the Usb bus's internal state.
942 @param UsbDev The USB device to set configure to.
943 @param ConfigIndex The configure index to set.
945 @retval EFI_SUCCESS The device is configured now.
946 @retval Others Failed to set the device configure.
951 IN USB_DEVICE
*UsbDev
,
957 Status
= UsbCtrlRequest (
960 USB_REQ_TYPE_STANDARD
,
974 Usb UsbIo interface to clear the feature. This is should
975 only be used by HUB which is considered a device driver
976 on top of the UsbIo interface.
978 @param UsbIo The UsbIo interface.
979 @param Target The target of the transfer: endpoint/device.
980 @param Feature The feature to clear.
981 @param Index The wIndex parameter.
983 @retval EFI_SUCCESS The device feature is cleared.
984 @retval Others Failed to clear the feature.
989 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
995 EFI_USB_DEVICE_REQUEST DevReq
;
999 DevReq
.RequestType
= USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, Target
);
1000 DevReq
.Request
= USB_REQ_CLEAR_FEATURE
;
1001 DevReq
.Value
= Feature
;
1002 DevReq
.Index
= Index
;
1005 Status
= UsbIo
->UsbControlTransfer (
1009 USB_CLEAR_FEATURE_REQUEST_TIMEOUT
,