3 Manage Usb Descriptor List
5 Copyright (c) 2007, Intel Corporation
6 All rights reserved. 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
];
45 FreePool (Setting
->Endpoints
);
53 Free a configuration descriptor with its interface
54 descriptors. It may be initialized partially.
56 @param Config The configuration descriptor to free.
61 IN USB_CONFIG_DESC
*Config
64 USB_INTERFACE_DESC
*Interface
;
68 if (Config
->Interfaces
!= NULL
) {
70 // A configuration may have several interfaces, free the interface
72 for (Index
= 0; Index
< Config
->Desc
.NumInterfaces
; Index
++) {
73 Interface
= Config
->Interfaces
[Index
];
75 if (Interface
== NULL
) {
80 // Each interface may have several settings, free the settings
82 for (SetIndex
= 0; SetIndex
< Interface
->NumOfSetting
; SetIndex
++) {
83 if (Interface
->Settings
[SetIndex
] != NULL
) {
84 UsbFreeInterfaceDesc (Interface
->Settings
[SetIndex
]);
91 FreePool (Config
->Interfaces
);
100 Free a device descriptor with its configurations.
102 @param DevDesc The device descriptor.
107 IN USB_DEVICE_DESC
*DevDesc
112 if (DevDesc
->Configs
!= NULL
) {
113 for (Index
= 0; Index
< DevDesc
->Desc
.NumConfigurations
; Index
++) {
114 if (DevDesc
->Configs
[Index
] != NULL
) {
115 UsbFreeConfigDesc (DevDesc
->Configs
[Index
]);
119 FreePool (DevDesc
->Configs
);
129 @param DescBuf The buffer of raw descriptor.
130 @param Len The length of the raw descriptor buffer.
131 @param Type The type of descriptor to create.
132 @param Consumed Number of bytes consumed.
134 @return Created descriptor or NULL.
156 case USB_DESC_TYPE_DEVICE
:
157 DescLen
= sizeof (EFI_USB_DEVICE_DESCRIPTOR
);
158 CtrlLen
= sizeof (USB_DEVICE_DESC
);
161 case USB_DESC_TYPE_CONFIG
:
162 DescLen
= sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
163 CtrlLen
= sizeof (USB_CONFIG_DESC
);
166 case USB_DESC_TYPE_INTERFACE
:
167 DescLen
= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
168 CtrlLen
= sizeof (USB_INTERFACE_SETTING
);
171 case USB_DESC_TYPE_ENDPOINT
:
172 DescLen
= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
173 CtrlLen
= sizeof (USB_ENDPOINT_DESC
);
178 // All the descriptor has a common LTV (Length, Type, Value)
179 // format. Skip the descriptor that isn't of this Type
182 Head
= (USB_DESC_HEAD
*)DescBuf
;
184 while ((Offset
< Len
) && (Head
->Type
!= Type
)) {
186 Head
= (USB_DESC_HEAD
*)(DescBuf
+ Offset
);
189 if ((Len
<= Offset
) || (Len
< Offset
+ DescLen
) ||
190 (Head
->Type
!= Type
) || (Head
->Len
!= DescLen
)) {
191 DEBUG (( EFI_D_ERROR
, "UsbCreateDesc: met mal-format descriptor\n"));
195 Desc
= AllocateCopyPool(CtrlLen
, Head
);
199 *Consumed
= Offset
+ Head
->Len
;
206 Parse an interface descriptor and its endpoints.
208 @param DescBuf The buffer of raw descriptor.
209 @param Len The length of the raw descriptor buffer.
210 @param Consumed The number of raw descriptor consumed.
212 @return The create interface setting or NULL if failed.
215 USB_INTERFACE_SETTING
*
216 UsbParseInterfaceDesc (
222 USB_INTERFACE_SETTING
*Setting
;
223 USB_ENDPOINT_DESC
*Ep
;
230 Setting
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_INTERFACE
, &Used
);
232 if (Setting
== NULL
) {
233 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));
240 // Create an array to hold the interface's endpoints
242 NumEp
= Setting
->Desc
.NumEndpoints
;
244 DEBUG (( EFI_D_INFO
, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
245 Setting
->Desc
.InterfaceNumber
, Setting
->Desc
.AlternateSetting
, (UINT32
)NumEp
));
251 Setting
->Endpoints
= AllocateZeroPool (sizeof (USB_ENDPOINT_DESC
*) * NumEp
);
253 if (Setting
->Endpoints
== NULL
) {
258 // Create the endpoints for this interface
260 for (Index
= 0; Index
< NumEp
; Index
++) {
261 Ep
= UsbCreateDesc (DescBuf
+ Offset
, Len
- Offset
, USB_DESC_TYPE_ENDPOINT
, &Used
);
264 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32
)Index
));
268 Setting
->Endpoints
[Index
] = Ep
;
278 UsbFreeInterfaceDesc (Setting
);
284 Parse the configuration descriptor and its interfaces.
286 @param DescBuf The buffer of raw descriptor.
287 @param Len The length of the raw descriptor buffer.
289 @return The created configuration descriptor.
298 USB_CONFIG_DESC
*Config
;
299 USB_INTERFACE_SETTING
*Setting
;
300 USB_INTERFACE_DESC
*Interface
;
305 ASSERT (DescBuf
!= NULL
);
307 Config
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_CONFIG
, &Consumed
);
309 if (Config
== NULL
) {
314 // Initialize an array of setting for the configuration's interfaces.
316 NumIf
= Config
->Desc
.NumInterfaces
;
317 Config
->Interfaces
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
*) * NumIf
);
319 if (Config
->Interfaces
== NULL
) {
323 DEBUG (( EFI_D_INFO
, "UsbParseConfigDesc: config %d has %d interfaces\n",
324 Config
->Desc
.ConfigurationValue
, (UINT32
)NumIf
));
326 for (Index
= 0; Index
< NumIf
; Index
++) {
327 Interface
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
));
329 if (Interface
== NULL
) {
333 Config
->Interfaces
[Index
] = Interface
;
337 // If a configuration has several interfaces, these interfaces are
338 // numbered from zero to n. If a interface has several settings,
339 // these settings are also number from zero to m. The interface
340 // setting must be organized as |interface 0, setting 0|interface 0
341 // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
342 // USB2.0 spec, page 267.
348 Setting
= UsbParseInterfaceDesc (DescBuf
, Len
, &Consumed
);
350 if ((Setting
== NULL
)) {
351 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: failed to parse interface setting\n"));
354 } else if (Setting
->Desc
.InterfaceNumber
>= NumIf
) {
355 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
357 UsbFreeInterfaceDesc (Setting
);
362 // Insert the descriptor to the corresponding set.
364 Interface
= Config
->Interfaces
[Setting
->Desc
.InterfaceNumber
];
366 if (Interface
->NumOfSetting
>= USB_MAX_INTERFACE_SETTING
) {
370 Interface
->Settings
[Interface
->NumOfSetting
] = Setting
;
371 Interface
->NumOfSetting
++;
380 UsbFreeConfigDesc (Config
);
386 USB standard control transfer support routine. This
387 function is used by USB device. It is possible that
388 the device's interfaces are still waiting to be
391 @param UsbDev The usb device.
392 @param Direction The direction of data transfer.
393 @param Type Standard / class specific / vendor specific.
394 @param Target The receiving target.
395 @param Request Which request.
396 @param Value The wValue parameter of the request.
397 @param Index The wIndex parameter of the request.
398 @param Buf The buffer to receive data into / transmit from.
399 @param Length The length of the buffer.
401 @retval EFI_SUCCESS The control request is executed.
402 @retval EFI_DEVICE_ERROR Failed to execute the control transfer.
407 IN USB_DEVICE
*UsbDev
,
408 IN EFI_USB_DATA_DIRECTION Direction
,
418 EFI_USB_DEVICE_REQUEST DevReq
;
423 ASSERT ((UsbDev
!= NULL
) && (UsbDev
->Bus
!= NULL
));
425 DevReq
.RequestType
= USB_REQUEST_TYPE (Direction
, Type
, Target
);
426 DevReq
.Request
= (UINT8
) Request
;
427 DevReq
.Value
= Value
;
428 DevReq
.Index
= Index
;
429 DevReq
.Length
= (UINT16
) Length
;
432 Status
= UsbHcControlTransfer (
441 USB_GENERAL_DEVICE_REQUEST_TIMEOUT
,
451 Get the standard descriptors.
453 @param UsbDev The USB device to read descriptor from.
454 @param DescType The type of descriptor to read.
455 @param DescIndex The index of descriptor to read.
456 @param LangId Language ID, only used to get string, otherwise set
458 @param Buf The buffer to hold the descriptor read.
459 @param Length The length of the buffer.
461 @retval EFI_SUCCESS The descriptor is read OK.
462 @retval Others Failed to retrieve the descriptor.
467 IN USB_DEVICE
*UsbDev
,
477 Status
= UsbCtrlRequest (
480 USB_REQ_TYPE_STANDARD
,
482 USB_REQ_GET_DESCRIPTOR
,
483 (UINT16
) ((DescType
<< 8) | DescIndex
),
494 Return the max packet size for endpoint zero. This function
495 is the first function called to get descriptors during bus
498 @param UsbDev The usb device.
500 @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved.
501 @retval EFI_DEVICE_ERROR Failed to retrieve it.
505 UsbGetMaxPacketSize0 (
506 IN USB_DEVICE
*UsbDev
509 EFI_USB_DEVICE_DESCRIPTOR DevDesc
;
515 // Get the first 8 bytes of the device descriptor which contains
516 // max packet size for endpoint 0, which is at least 8.
518 UsbDev
->MaxPacket0
= 8;
520 for (Index
= 0; Index
< 3; Index
++) {
521 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_DEVICE
, 0, 0, &DevDesc
, 8);
523 if (!EFI_ERROR (Status
)) {
524 UsbDev
->MaxPacket0
= DevDesc
.MaxPacketSize0
;
528 gBS
->Stall (USB_RETRY_MAX_PACK_SIZE_STALL
);
531 return EFI_DEVICE_ERROR
;
536 Get the device descriptor for the device.
538 @param UsbDev The Usb device to retrieve descriptor from.
540 @retval EFI_SUCCESS The device descriptor is returned.
541 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
546 IN USB_DEVICE
*UsbDev
549 USB_DEVICE_DESC
*DevDesc
;
552 DevDesc
= AllocateZeroPool (sizeof (USB_DEVICE_DESC
));
554 if (DevDesc
== NULL
) {
555 return EFI_OUT_OF_RESOURCES
;
558 Status
= UsbCtrlGetDesc (
560 USB_DESC_TYPE_DEVICE
,
564 sizeof (EFI_USB_DEVICE_DESCRIPTOR
)
567 if (EFI_ERROR (Status
)) {
568 gBS
->FreePool (DevDesc
);
570 UsbDev
->DevDesc
= DevDesc
;
578 Retrieve the indexed string for the language. It requires two
579 steps to get a string, first to get the string's length. Then
582 @param UsbDev The usb device.
583 @param Index The index the string to retrieve.
584 @param LangId Language ID.
586 @return The created string descriptor or NULL.
589 EFI_USB_STRING_DESCRIPTOR
*
591 IN USB_DEVICE
*UsbDev
,
596 EFI_USB_STRING_DESCRIPTOR Desc
;
601 // First get two bytes which contains the string length.
603 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_STRING
, Index
, LangId
, &Desc
, 2);
605 if (EFI_ERROR (Status
)) {
609 Buf
= AllocateZeroPool (Desc
.Length
);
615 Status
= UsbCtrlGetDesc (
617 USB_DESC_TYPE_STRING
,
624 if (EFI_ERROR (Status
)) {
629 return (EFI_USB_STRING_DESCRIPTOR
*) Buf
;
634 Build the language ID table for string descriptors.
636 @param UsbDev The Usb device.
638 @retval EFI_UNSUPPORTED This device doesn't support string table.
643 IN USB_DEVICE
*UsbDev
646 EFI_USB_STRING_DESCRIPTOR
*Desc
;
653 // The string of language ID zero returns the supported languages
655 Desc
= UsbGetOneString (UsbDev
, 0, 0);
658 return EFI_UNSUPPORTED
;
661 if (Desc
->Length
< 4) {
662 Status
= EFI_UNSUPPORTED
;
666 Status
= EFI_SUCCESS
;
668 Max
= (Desc
->Length
- 2) / 2;
669 Max
= MIN(Max
, USB_MAX_LANG_ID
);
671 Point
= Desc
->String
;
672 for (Index
= 0; Index
< Max
; Index
++) {
673 UsbDev
->LangId
[Index
] = *Point
;
677 UsbDev
->TotalLangId
= (UINT16
)Max
;
680 gBS
->FreePool (Desc
);
686 Retrieve the indexed configure for the device. USB device
687 returns the configuration together with the interfaces for
688 this configuration. Configuration descriptor is also of
691 @param UsbDev The Usb interface.
692 @param Index The index of the configuration.
694 @return The created configuration descriptor.
697 EFI_USB_CONFIG_DESCRIPTOR
*
699 IN USB_DEVICE
*UsbDev
,
703 EFI_USB_CONFIG_DESCRIPTOR Desc
;
708 // First get four bytes which contains the total length
709 // for this configuration.
711 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, &Desc
, 8);
713 if (EFI_ERROR (Status
)) {
714 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get descript length(%d) %r\n",
715 Desc
.TotalLength
, Status
));
720 DEBUG (( EFI_D_INFO
, "UsbGetOneConfig: total length is %d\n", Desc
.TotalLength
));
722 Buf
= AllocateZeroPool (Desc
.TotalLength
);
728 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, Buf
, Desc
.TotalLength
);
730 if (EFI_ERROR (Status
)) {
731 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get full descript %r\n", Status
));
742 Build the whole array of descriptors. This function must
743 be called after UsbGetMaxPacketSize0 returns the max packet
744 size correctly for endpoint 0.
746 @param UsbDev The Usb device.
748 @retval EFI_SUCCESS The descriptor table is build.
749 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor.
754 IN USB_DEVICE
*UsbDev
757 EFI_USB_CONFIG_DESCRIPTOR
*Config
;
758 USB_DEVICE_DESC
*DevDesc
;
759 USB_CONFIG_DESC
*ConfigDesc
;
765 // Get the device descriptor, then allocate the configure
766 // descriptor pointer array to hold configurations.
768 Status
= UsbGetDevDesc (UsbDev
);
770 if (EFI_ERROR (Status
)) {
771 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status
));
775 DevDesc
= UsbDev
->DevDesc
;
776 NumConfig
= DevDesc
->Desc
.NumConfigurations
;
777 DevDesc
->Configs
= AllocateZeroPool (NumConfig
* sizeof (USB_CONFIG_DESC
*));
779 if (DevDesc
->Configs
== NULL
) {
780 return EFI_OUT_OF_RESOURCES
;
783 DEBUG (( EFI_D_INFO
, "UsbBuildDescTable: device has %d configures\n", NumConfig
));
786 // Read each configurations, then parse them
788 for (Index
= 0; Index
< NumConfig
; Index
++) {
789 Config
= UsbGetOneConfig (UsbDev
, Index
);
791 if (Config
== NULL
) {
792 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get configure (index %d)\n", Index
));
795 // If we can get the default descriptor, it is likely that the
796 // device is still operational.
799 return EFI_DEVICE_ERROR
;
805 ConfigDesc
= UsbParseConfigDesc ((UINT8
*) Config
, Config
->TotalLength
);
809 if (ConfigDesc
== NULL
) {
810 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index
));
813 // If we can get the default descriptor, it is likely that the
814 // device is still operational.
817 return EFI_DEVICE_ERROR
;
823 DevDesc
->Configs
[Index
] = ConfigDesc
;
827 // Don't return error even this function failed because
828 // it is possible for the device to not support strings.
830 Status
= UsbBuildLangTable (UsbDev
);
832 if (EFI_ERROR (Status
)) {
833 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: get language ID table %r\n", Status
));
841 Set the device's address.
843 @param UsbDev The device to set address to.
844 @param Address The address to set.
846 @retval EFI_SUCCESS The device is set to the address.
847 @retval Others Failed to set the device address.
852 IN USB_DEVICE
*UsbDev
,
858 Status
= UsbCtrlRequest (
861 USB_REQ_TYPE_STANDARD
,
875 Set the device's configuration. This function changes
876 the device's internal state. UsbSelectConfig changes
877 the Usb bus's internal state.
879 @param UsbDev The USB device to set configure to.
880 @param ConfigIndex The configure index to set.
882 @retval EFI_SUCCESS The device is configured now.
883 @retval Others Failed to set the device configure.
888 IN USB_DEVICE
*UsbDev
,
894 Status
= UsbCtrlRequest (
897 USB_REQ_TYPE_STANDARD
,
911 Usb UsbIo interface to clear the feature. This is should
912 only be used by HUB which is considered a device driver
913 on top of the UsbIo interface.
915 @param UsbIo The UsbIo interface.
916 @param Target The target of the transfer: endpoint/device.
917 @param Feature The feature to clear.
918 @param Index The wIndex parameter.
920 @retval EFI_SUCCESS The device feature is cleared.
921 @retval Others Failed to clear the feature.
926 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
932 EFI_USB_DEVICE_REQUEST DevReq
;
936 DevReq
.RequestType
= USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, Target
);
937 DevReq
.Request
= USB_REQ_CLEAR_FEATURE
;
938 DevReq
.Value
= Feature
;
939 DevReq
.Index
= Index
;
942 Status
= UsbIo
->UsbControlTransfer (
946 USB_CLEAR_FEATURE_REQUEST_TIMEOUT
,