3 Manage Usb Descriptor List
5 Copyright (c) 2007 - 2013, 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
);
183 // All the descriptor has a common LTV (Length, Type, Value)
184 // format. Skip the descriptor that isn't of this Type
187 Head
= (USB_DESC_HEAD
*)DescBuf
;
189 while ((Offset
< Len
) && (Head
->Type
!= Type
)) {
191 Head
= (USB_DESC_HEAD
*)(DescBuf
+ Offset
);
194 if ((Len
<= Offset
) || (Len
< Offset
+ DescLen
) ||
195 (Head
->Type
!= Type
) || (Head
->Len
!= DescLen
)) {
196 DEBUG (( EFI_D_ERROR
, "UsbCreateDesc: met mal-format descriptor\n"));
200 Desc
= AllocateZeroPool ((UINTN
) CtrlLen
);
205 CopyMem (Desc
, Head
, (UINTN
) DescLen
);
207 *Consumed
= Offset
+ Head
->Len
;
214 Parse an interface descriptor and its endpoints.
216 @param DescBuf The buffer of raw descriptor.
217 @param Len The length of the raw descriptor buffer.
218 @param Consumed The number of raw descriptor consumed.
220 @return The create interface setting or NULL if failed.
223 USB_INTERFACE_SETTING
*
224 UsbParseInterfaceDesc (
230 USB_INTERFACE_SETTING
*Setting
;
231 USB_ENDPOINT_DESC
*Ep
;
238 Setting
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_INTERFACE
, &Used
);
240 if (Setting
== NULL
) {
241 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));
248 // Create an array to hold the interface's endpoints
250 NumEp
= Setting
->Desc
.NumEndpoints
;
252 DEBUG (( EFI_D_INFO
, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
253 Setting
->Desc
.InterfaceNumber
, Setting
->Desc
.AlternateSetting
, (UINT32
)NumEp
));
259 Setting
->Endpoints
= AllocateZeroPool (sizeof (USB_ENDPOINT_DESC
*) * NumEp
);
261 if (Setting
->Endpoints
== NULL
) {
266 // Create the endpoints for this interface
268 for (Index
= 0; Index
< NumEp
; Index
++) {
269 Ep
= UsbCreateDesc (DescBuf
+ Offset
, Len
- Offset
, USB_DESC_TYPE_ENDPOINT
, &Used
);
272 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32
)Index
));
276 Setting
->Endpoints
[Index
] = Ep
;
286 UsbFreeInterfaceDesc (Setting
);
292 Parse the configuration descriptor and its interfaces.
294 @param DescBuf The buffer of raw descriptor.
295 @param Len The length of the raw descriptor buffer.
297 @return The created configuration descriptor.
306 USB_CONFIG_DESC
*Config
;
307 USB_INTERFACE_SETTING
*Setting
;
308 USB_INTERFACE_DESC
*Interface
;
313 ASSERT (DescBuf
!= NULL
);
315 Config
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_CONFIG
, &Consumed
);
317 if (Config
== NULL
) {
322 // Initialize an array of setting for the configuration's interfaces.
324 NumIf
= Config
->Desc
.NumInterfaces
;
325 Config
->Interfaces
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
*) * NumIf
);
327 if (Config
->Interfaces
== NULL
) {
331 DEBUG (( EFI_D_INFO
, "UsbParseConfigDesc: config %d has %d interfaces\n",
332 Config
->Desc
.ConfigurationValue
, (UINT32
)NumIf
));
334 for (Index
= 0; Index
< NumIf
; Index
++) {
335 Interface
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
));
337 if (Interface
== NULL
) {
341 Config
->Interfaces
[Index
] = Interface
;
345 // If a configuration has several interfaces, these interfaces are
346 // numbered from zero to n. If a interface has several settings,
347 // these settings are also number from zero to m. The interface
348 // setting must be organized as |interface 0, setting 0|interface 0
349 // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
350 // USB2.0 spec, page 267.
356 // Make allowances for devices that return extra data at the
357 // end of their config descriptors
359 while (Len
>= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
)) {
360 Setting
= UsbParseInterfaceDesc (DescBuf
, Len
, &Consumed
);
362 if (Setting
== NULL
) {
363 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));
366 } else if (Setting
->Desc
.InterfaceNumber
>= NumIf
) {
367 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
369 UsbFreeInterfaceDesc (Setting
);
374 // Insert the descriptor to the corresponding set.
376 Interface
= Config
->Interfaces
[Setting
->Desc
.InterfaceNumber
];
378 if (Interface
->NumOfSetting
>= USB_MAX_INTERFACE_SETTING
) {
382 Interface
->Settings
[Interface
->NumOfSetting
] = Setting
;
383 Interface
->NumOfSetting
++;
392 UsbFreeConfigDesc (Config
);
398 USB standard control transfer support routine. This
399 function is used by USB device. It is possible that
400 the device's interfaces are still waiting to be
403 @param UsbDev The usb device.
404 @param Direction The direction of data transfer.
405 @param Type Standard / class specific / vendor specific.
406 @param Target The receiving target.
407 @param Request Which request.
408 @param Value The wValue parameter of the request.
409 @param Index The wIndex parameter of the request.
410 @param Buf The buffer to receive data into / transmit from.
411 @param Length The length of the buffer.
413 @retval EFI_SUCCESS The control request is executed.
414 @retval EFI_DEVICE_ERROR Failed to execute the control transfer.
419 IN USB_DEVICE
*UsbDev
,
420 IN EFI_USB_DATA_DIRECTION Direction
,
430 EFI_USB_DEVICE_REQUEST DevReq
;
435 ASSERT ((UsbDev
!= NULL
) && (UsbDev
->Bus
!= NULL
));
437 DevReq
.RequestType
= USB_REQUEST_TYPE (Direction
, Type
, Target
);
438 DevReq
.Request
= (UINT8
) Request
;
439 DevReq
.Value
= Value
;
440 DevReq
.Index
= Index
;
441 DevReq
.Length
= (UINT16
) Length
;
444 Status
= UsbHcControlTransfer (
453 USB_GENERAL_DEVICE_REQUEST_TIMEOUT
,
463 Get the standard descriptors.
465 @param UsbDev The USB device to read descriptor from.
466 @param DescType The type of descriptor to read.
467 @param DescIndex The index of descriptor to read.
468 @param LangId Language ID, only used to get string, otherwise set
470 @param Buf The buffer to hold the descriptor read.
471 @param Length The length of the buffer.
473 @retval EFI_SUCCESS The descriptor is read OK.
474 @retval Others Failed to retrieve the descriptor.
479 IN USB_DEVICE
*UsbDev
,
489 Status
= UsbCtrlRequest (
492 USB_REQ_TYPE_STANDARD
,
494 USB_REQ_GET_DESCRIPTOR
,
495 (UINT16
) ((DescType
<< 8) | DescIndex
),
506 Return the max packet size for endpoint zero. This function
507 is the first function called to get descriptors during bus
510 @param UsbDev The usb device.
512 @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved.
513 @retval EFI_DEVICE_ERROR Failed to retrieve it.
517 UsbGetMaxPacketSize0 (
518 IN USB_DEVICE
*UsbDev
521 EFI_USB_DEVICE_DESCRIPTOR DevDesc
;
527 // Get the first 8 bytes of the device descriptor which contains
528 // max packet size for endpoint 0, which is at least 8.
530 for (Index
= 0; Index
< 3; Index
++) {
531 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_DEVICE
, 0, 0, &DevDesc
, 8);
533 if (!EFI_ERROR (Status
)) {
534 if ((DevDesc
.BcdUSB
== 0x0300) && (DevDesc
.MaxPacketSize0
== 9)) {
535 UsbDev
->MaxPacket0
= 1 << 9;
538 UsbDev
->MaxPacket0
= DevDesc
.MaxPacketSize0
;
542 gBS
->Stall (USB_RETRY_MAX_PACK_SIZE_STALL
);
545 return EFI_DEVICE_ERROR
;
550 Get the device descriptor for the device.
552 @param UsbDev The Usb device to retrieve descriptor from.
554 @retval EFI_SUCCESS The device descriptor is returned.
555 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
560 IN USB_DEVICE
*UsbDev
563 USB_DEVICE_DESC
*DevDesc
;
566 DevDesc
= AllocateZeroPool (sizeof (USB_DEVICE_DESC
));
568 if (DevDesc
== NULL
) {
569 return EFI_OUT_OF_RESOURCES
;
572 Status
= UsbCtrlGetDesc (
574 USB_DESC_TYPE_DEVICE
,
578 sizeof (EFI_USB_DEVICE_DESCRIPTOR
)
581 if (EFI_ERROR (Status
)) {
582 gBS
->FreePool (DevDesc
);
584 UsbDev
->DevDesc
= DevDesc
;
592 Retrieve the indexed string for the language. It requires two
593 steps to get a string, first to get the string's length. Then
596 @param UsbDev The usb device.
597 @param Index The index the string to retrieve.
598 @param LangId Language ID.
600 @return The created string descriptor or NULL.
603 EFI_USB_STRING_DESCRIPTOR
*
605 IN USB_DEVICE
*UsbDev
,
610 EFI_USB_STRING_DESCRIPTOR Desc
;
615 // First get two bytes which contains the string length.
617 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_STRING
, Index
, LangId
, &Desc
, 2);
619 if (EFI_ERROR (Status
)) {
623 Buf
= AllocateZeroPool (Desc
.Length
);
629 Status
= UsbCtrlGetDesc (
631 USB_DESC_TYPE_STRING
,
638 if (EFI_ERROR (Status
)) {
643 return (EFI_USB_STRING_DESCRIPTOR
*) Buf
;
648 Build the language ID table for string descriptors.
650 @param UsbDev The Usb device.
652 @retval EFI_UNSUPPORTED This device doesn't support string table.
657 IN USB_DEVICE
*UsbDev
660 EFI_USB_STRING_DESCRIPTOR
*Desc
;
667 // The string of language ID zero returns the supported languages
669 Desc
= UsbGetOneString (UsbDev
, 0, 0);
672 return EFI_UNSUPPORTED
;
675 if (Desc
->Length
< 4) {
676 Status
= EFI_UNSUPPORTED
;
680 Status
= EFI_SUCCESS
;
682 Max
= (Desc
->Length
- 2) / 2;
683 Max
= MIN(Max
, USB_MAX_LANG_ID
);
685 Point
= Desc
->String
;
686 for (Index
= 0; Index
< Max
; Index
++) {
687 UsbDev
->LangId
[Index
] = *Point
;
691 UsbDev
->TotalLangId
= (UINT16
)Max
;
694 gBS
->FreePool (Desc
);
700 Retrieve the indexed configure for the device. USB device
701 returns the configuration together with the interfaces for
702 this configuration. Configuration descriptor is also of
705 @param UsbDev The Usb interface.
706 @param Index The index of the configuration.
708 @return The created configuration descriptor.
711 EFI_USB_CONFIG_DESCRIPTOR
*
713 IN USB_DEVICE
*UsbDev
,
717 EFI_USB_CONFIG_DESCRIPTOR Desc
;
722 // First get four bytes which contains the total length
723 // for this configuration.
725 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, &Desc
, 8);
727 if (EFI_ERROR (Status
)) {
728 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get descript length(%d) %r\n",
729 Desc
.TotalLength
, Status
));
734 DEBUG (( EFI_D_INFO
, "UsbGetOneConfig: total length is %d\n", Desc
.TotalLength
));
736 Buf
= AllocateZeroPool (Desc
.TotalLength
);
742 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, Buf
, Desc
.TotalLength
);
744 if (EFI_ERROR (Status
)) {
745 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get full descript %r\n", Status
));
756 Build the whole array of descriptors. This function must
757 be called after UsbGetMaxPacketSize0 returns the max packet
758 size correctly for endpoint 0.
760 @param UsbDev The Usb device.
762 @retval EFI_SUCCESS The descriptor table is build.
763 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor.
768 IN USB_DEVICE
*UsbDev
771 EFI_USB_CONFIG_DESCRIPTOR
*Config
;
772 USB_DEVICE_DESC
*DevDesc
;
773 USB_CONFIG_DESC
*ConfigDesc
;
779 // Get the device descriptor, then allocate the configure
780 // descriptor pointer array to hold configurations.
782 Status
= UsbGetDevDesc (UsbDev
);
784 if (EFI_ERROR (Status
)) {
785 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status
));
789 DevDesc
= UsbDev
->DevDesc
;
790 NumConfig
= DevDesc
->Desc
.NumConfigurations
;
791 if (NumConfig
== 0) {
792 return EFI_DEVICE_ERROR
;
795 DevDesc
->Configs
= AllocateZeroPool (NumConfig
* sizeof (USB_CONFIG_DESC
*));
796 if (DevDesc
->Configs
== NULL
) {
797 return EFI_OUT_OF_RESOURCES
;
800 DEBUG (( EFI_D_INFO
, "UsbBuildDescTable: device has %d configures\n", NumConfig
));
803 // Read each configurations, then parse them
805 for (Index
= 0; Index
< NumConfig
; Index
++) {
806 Config
= UsbGetOneConfig (UsbDev
, Index
);
808 if (Config
== NULL
) {
809 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get configure (index %d)\n", Index
));
812 // If we can get the default descriptor, it is likely that the
813 // device is still operational.
816 return EFI_DEVICE_ERROR
;
822 ConfigDesc
= UsbParseConfigDesc ((UINT8
*) Config
, Config
->TotalLength
);
826 if (ConfigDesc
== NULL
) {
827 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index
));
830 // If we can get the default descriptor, it is likely that the
831 // device is still operational.
834 return EFI_DEVICE_ERROR
;
840 DevDesc
->Configs
[Index
] = ConfigDesc
;
844 // Don't return error even this function failed because
845 // it is possible for the device to not support strings.
847 Status
= UsbBuildLangTable (UsbDev
);
849 if (EFI_ERROR (Status
)) {
850 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: get language ID table %r\n", Status
));
858 Set the device's address.
860 @param UsbDev The device to set address to.
861 @param Address The address to set.
863 @retval EFI_SUCCESS The device is set to the address.
864 @retval Others Failed to set the device address.
869 IN USB_DEVICE
*UsbDev
,
875 Status
= UsbCtrlRequest (
878 USB_REQ_TYPE_STANDARD
,
892 Set the device's configuration. This function changes
893 the device's internal state. UsbSelectConfig changes
894 the Usb bus's internal state.
896 @param UsbDev The USB device to set configure to.
897 @param ConfigIndex The configure index to set.
899 @retval EFI_SUCCESS The device is configured now.
900 @retval Others Failed to set the device configure.
905 IN USB_DEVICE
*UsbDev
,
911 Status
= UsbCtrlRequest (
914 USB_REQ_TYPE_STANDARD
,
928 Usb UsbIo interface to clear the feature. This is should
929 only be used by HUB which is considered a device driver
930 on top of the UsbIo interface.
932 @param UsbIo The UsbIo interface.
933 @param Target The target of the transfer: endpoint/device.
934 @param Feature The feature to clear.
935 @param Index The wIndex parameter.
937 @retval EFI_SUCCESS The device feature is cleared.
938 @retval Others Failed to clear the feature.
943 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
949 EFI_USB_DEVICE_REQUEST DevReq
;
953 DevReq
.RequestType
= USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, Target
);
954 DevReq
.Request
= USB_REQ_CLEAR_FEATURE
;
955 DevReq
.Value
= Feature
;
956 DevReq
.Index
= Index
;
959 Status
= UsbIo
->UsbControlTransfer (
963 USB_CLEAR_FEATURE_REQUEST_TIMEOUT
,