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.
28 UsbFreeInterfaceDesc (
29 IN USB_INTERFACE_SETTING
*Setting
32 USB_ENDPOINT_DESC
*Ep
;
35 if (Setting
->Endpoints
!= NULL
) {
37 // Each interface setting may have several endpoints, free them first.
39 for (Index
= 0; Index
< Setting
->Desc
.NumEndpoints
; Index
++) {
40 Ep
= Setting
->Endpoints
[Index
];
47 gBS
->FreePool (Setting
->Endpoints
);
50 gBS
->FreePool (Setting
);
55 Free a configuration descriptor with its interface
56 descriptors. It may be initialized partially.
58 @param Config The configuration descriptor to free.
65 IN USB_CONFIG_DESC
*Config
68 USB_INTERFACE_DESC
*Interface
;
72 if (Config
->Interfaces
!= NULL
) {
74 // A configuration may have several interfaces, free the interface
76 for (Index
= 0; Index
< Config
->Desc
.NumInterfaces
; Index
++) {
77 Interface
= Config
->Interfaces
[Index
];
79 if (Interface
== NULL
) {
84 // Each interface may have several settings, free the settings
86 for (SetIndex
= 0; SetIndex
< Interface
->NumOfSetting
; SetIndex
++) {
87 if (Interface
->Settings
[SetIndex
] != NULL
) {
88 UsbFreeInterfaceDesc (Interface
->Settings
[SetIndex
]);
92 gBS
->FreePool (Interface
);
95 gBS
->FreePool (Config
->Interfaces
);
98 gBS
->FreePool (Config
);
104 Free a device descriptor with its configurations.
106 @param DevDesc The device descriptor.
113 IN USB_DEVICE_DESC
*DevDesc
118 if (DevDesc
->Configs
!= NULL
) {
119 for (Index
= 0; Index
< DevDesc
->Desc
.NumConfigurations
; Index
++) {
120 if (DevDesc
->Configs
[Index
] != NULL
) {
121 UsbFreeConfigDesc (DevDesc
->Configs
[Index
]);
125 gBS
->FreePool (DevDesc
->Configs
);
128 gBS
->FreePool (DevDesc
);
135 @param DescBuf The buffer of raw descriptor.
136 @param Len The lenght of the raw descriptor buffer.
137 @param Type The type of descriptor to create.
138 @param Consumed Number of bytes consumed.
140 @return Created descriptor or NULL.
162 case USB_DESC_TYPE_DEVICE
:
163 DescLen
= sizeof (EFI_USB_DEVICE_DESCRIPTOR
);
164 CtrlLen
= sizeof (USB_DEVICE_DESC
);
167 case USB_DESC_TYPE_CONFIG
:
168 DescLen
= sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
169 CtrlLen
= sizeof (USB_CONFIG_DESC
);
172 case USB_DESC_TYPE_INTERFACE
:
173 DescLen
= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
174 CtrlLen
= sizeof (USB_INTERFACE_SETTING
);
177 case USB_DESC_TYPE_ENDPOINT
:
178 DescLen
= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
179 CtrlLen
= sizeof (USB_ENDPOINT_DESC
);
184 // All the descriptor has a common LTV (Length, Type, Value)
185 // format. Skip the descriptor that isn't of this Type
188 Head
= (USB_DESC_HEAD
*)DescBuf
;
190 while ((Offset
< Len
) && (Head
->Type
!= Type
)) {
192 Head
= (USB_DESC_HEAD
*)(DescBuf
+ Offset
);
195 if ((Len
<= Offset
) || (Len
< Offset
+ DescLen
) ||
196 (Head
->Type
!= Type
) || (Head
->Len
!= DescLen
)) {
197 DEBUG (( EFI_D_ERROR
, "UsbCreateDesc: met mal-format descriptor\n"));
201 Desc
= AllocateZeroPool (CtrlLen
);
207 CopyMem (Desc
, Head
, DescLen
);
208 *Consumed
= Offset
+ Head
->Len
;
215 Parse an interface desciptor and its endpoints.
217 @param DescBuf The buffer of raw descriptor.
218 @param Len The lenght of the raw descriptor buffer.
219 @param Consumed The number of raw descriptor consumed.
221 @return The create interface setting or NULL if failed.
224 USB_INTERFACE_SETTING
*
225 UsbParseInterfaceDesc (
231 USB_INTERFACE_SETTING
*Setting
;
232 USB_ENDPOINT_DESC
*Ep
;
239 Setting
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_INTERFACE
, &Used
);
241 if (Setting
== NULL
) {
242 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));
249 // Create an arry to hold the interface's endpoints
251 NumEp
= Setting
->Desc
.NumEndpoints
;
253 DEBUG (( EFI_D_INFO
, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
254 Setting
->Desc
.InterfaceNumber
, Setting
->Desc
.AlternateSetting
, (UINT32
)NumEp
));
260 Setting
->Endpoints
= AllocateZeroPool (sizeof (USB_ENDPOINT_DESC
*) * NumEp
);
262 if (Setting
->Endpoints
== NULL
) {
267 // Create the endpoints for this interface
269 for (Index
= 0; Index
< NumEp
; Index
++) {
270 Ep
= UsbCreateDesc (DescBuf
+ Offset
, Len
- Offset
, USB_DESC_TYPE_ENDPOINT
, &Used
);
273 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32
)Index
));
277 Setting
->Endpoints
[Index
] = Ep
;
287 UsbFreeInterfaceDesc (Setting
);
293 Parse the configuration descriptor and its interfaces.
295 @param DescBuf The buffer of raw descriptor.
296 @param Len The lenght of the raw descriptor buffer.
298 @return The created configuration descriptor.
307 USB_CONFIG_DESC
*Config
;
308 USB_INTERFACE_SETTING
*Setting
;
309 USB_INTERFACE_DESC
*Interface
;
314 ASSERT (DescBuf
!= NULL
);
316 Config
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_CONFIG
, &Consumed
);
318 if (Config
== NULL
) {
323 // Initialize an array of setting for the configuration's interfaces.
325 NumIf
= Config
->Desc
.NumInterfaces
;
326 Config
->Interfaces
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
*) * NumIf
);
328 if (Config
->Interfaces
== NULL
) {
332 DEBUG (( EFI_D_INFO
, "UsbParseConfigDesc: config %d has %d interfaces\n",
333 Config
->Desc
.ConfigurationValue
, (UINT32
)NumIf
));
335 for (Index
= 0; Index
< NumIf
; Index
++) {
336 Interface
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
));
338 if (Interface
== NULL
) {
342 Config
->Interfaces
[Index
] = Interface
;
346 // If a configuration has several interfaces, these interfaces are
347 // numbered from zero to n. If a interface has several settings,
348 // these settings are also number from zero to m. The interface
349 // setting must be organized as |interface 0, setting 0|interface 0
350 // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
351 // USB2.0 spec, page 267.
357 Setting
= UsbParseInterfaceDesc (DescBuf
, Len
, &Consumed
);
359 if ((Setting
== NULL
)) {
360 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: failed to parse interface setting\n"));
363 } else if (Setting
->Desc
.InterfaceNumber
>= NumIf
) {
364 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
366 UsbFreeInterfaceDesc (Setting
);
371 // Insert the descriptor to the corresponding set.
373 Interface
= Config
->Interfaces
[Setting
->Desc
.InterfaceNumber
];
375 if (Interface
->NumOfSetting
>= USB_MAX_INTERFACE_SETTING
) {
379 Interface
->Settings
[Interface
->NumOfSetting
] = Setting
;
380 Interface
->NumOfSetting
++;
389 UsbFreeConfigDesc (Config
);
395 USB standard control transfer support routine. This
396 function is used by USB device. It is possible that
397 the device's interfaces are still waiting to be
400 @param UsbDev The usb device.
401 @param Direction The direction of data transfer.
402 @param Type Standard / class specific / vendor specific.
403 @param Target The receiving target.
404 @param Request Which request.
405 @param Value The wValue parameter of the request.
406 @param Index The wIndex parameter of the request.
407 @param Buf The buffer to receive data into / transmit from.
408 @param Length The length of the buffer.
410 @retval EFI_SUCCESS The control request is executed.
411 @retval EFI_DEVICE_ERROR Failed to execute the control transfer.
416 IN USB_DEVICE
*UsbDev
,
417 IN EFI_USB_DATA_DIRECTION Direction
,
427 EFI_USB_DEVICE_REQUEST DevReq
;
432 ASSERT ((UsbDev
!= NULL
) && (UsbDev
->Bus
!= NULL
));
434 DevReq
.RequestType
= USB_REQUEST_TYPE (Direction
, Type
, Target
);
435 DevReq
.Request
= (UINT8
) Request
;
436 DevReq
.Value
= Value
;
437 DevReq
.Index
= Index
;
438 DevReq
.Length
= (UINT16
) Length
;
441 Status
= UsbHcControlTransfer (
450 USB_GENERAL_DEVICE_REQUEST_TIMEOUT
,
460 Get the standard descriptors.
462 @param UsbDev The USB device to read descriptor from.
463 @param DescType The type of descriptor to read.
464 @param DescIndex The index of descriptor to read.
465 @param LangId Language ID, only used to get string, otherwise set
467 @param Buf The buffer to hold the descriptor read.
468 @param Length The length of the buffer.
470 @retval EFI_SUCCESS The descriptor is read OK.
471 @retval Others Failed to retrieve the descriptor.
476 IN USB_DEVICE
*UsbDev
,
486 Status
= UsbCtrlRequest (
489 USB_REQ_TYPE_STANDARD
,
491 USB_REQ_GET_DESCRIPTOR
,
492 (UINT16
) ((DescType
<< 8) | DescIndex
),
503 Return the max packet size for endpoint zero. This function
504 is the first function called to get descriptors during bus
507 @param UsbDev The usb device.
509 @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved.
510 @retval EFI_DEVICE_ERROR Failed to retrieve it.
514 UsbGetMaxPacketSize0 (
515 IN USB_DEVICE
*UsbDev
518 EFI_USB_DEVICE_DESCRIPTOR DevDesc
;
524 // Get the first 8 bytes of the device descriptor which contains
525 // max packet size for endpoint 0, which is at least 8.
527 UsbDev
->MaxPacket0
= 8;
529 for (Index
= 0; Index
< 3; Index
++) {
530 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_DEVICE
, 0, 0, &DevDesc
, 8);
532 if (!EFI_ERROR (Status
)) {
533 UsbDev
->MaxPacket0
= DevDesc
.MaxPacketSize0
;
537 gBS
->Stall (USB_RETRY_MAX_PACK_SIZE_STALL
);
540 return EFI_DEVICE_ERROR
;
545 Get the device descriptor for the device.
547 @param UsbDev The Usb device to retrieve descriptor from.
549 @retval EFI_SUCCESS The device descriptor is returned.
550 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
555 IN USB_DEVICE
*UsbDev
558 USB_DEVICE_DESC
*DevDesc
;
561 DevDesc
= AllocateZeroPool (sizeof (USB_DEVICE_DESC
));
563 if (DevDesc
== NULL
) {
564 return EFI_OUT_OF_RESOURCES
;
567 Status
= UsbCtrlGetDesc (
569 USB_DESC_TYPE_DEVICE
,
573 sizeof (EFI_USB_DEVICE_DESCRIPTOR
)
576 if (EFI_ERROR (Status
)) {
577 gBS
->FreePool (DevDesc
);
579 UsbDev
->DevDesc
= DevDesc
;
587 Retrieve the indexed string for the language. It requires two
588 steps to get a string, first to get the string's length. Then
591 @param UsbDev The usb device.
592 @param Index The index the string to retrieve.
593 @param LangId Language ID.
595 @return The created string descriptor or NULL.
598 EFI_USB_STRING_DESCRIPTOR
*
600 IN USB_DEVICE
*UsbDev
,
605 EFI_USB_STRING_DESCRIPTOR Desc
;
610 // First get two bytes which contains the string length.
612 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_STRING
, Index
, LangId
, &Desc
, 2);
614 if (EFI_ERROR (Status
)) {
618 Buf
= AllocateZeroPool (Desc
.Length
);
624 Status
= UsbCtrlGetDesc (
626 USB_DESC_TYPE_STRING
,
633 if (EFI_ERROR (Status
)) {
638 return (EFI_USB_STRING_DESCRIPTOR
*) Buf
;
643 Build the language ID table for string descriptors.
645 @param UsbDev The Usb device.
647 @retval EFI_UNSUPPORTED This device doesn't support string table.
652 IN USB_DEVICE
*UsbDev
655 EFI_USB_STRING_DESCRIPTOR
*Desc
;
662 // The string of language ID zero returns the supported languages
664 Desc
= UsbGetOneString (UsbDev
, 0, 0);
667 return EFI_UNSUPPORTED
;
670 if (Desc
->Length
< 4) {
671 Status
= EFI_UNSUPPORTED
;
675 Status
= EFI_SUCCESS
;
677 Max
= (Desc
->Length
- 2) / 2;
678 Max
= (Max
< USB_MAX_LANG_ID
? Max
: USB_MAX_LANG_ID
);
680 Point
= Desc
->String
;
681 for (Index
= 0; Index
< Max
; Index
++) {
682 UsbDev
->LangId
[Index
] = *Point
;
686 UsbDev
->TotalLangId
= (UINT16
)Max
;
689 gBS
->FreePool (Desc
);
695 Retrieve the indexed configure for the device. USB device
696 returns the configuration togetther with the interfaces for
697 this configuration. Configuration descriptor is also of
700 @param UsbDev The Usb interface.
701 @param Index The index of the configuration.
703 @return The created configuration descriptor.
706 EFI_USB_CONFIG_DESCRIPTOR
*
708 IN USB_DEVICE
*UsbDev
,
712 EFI_USB_CONFIG_DESCRIPTOR Desc
;
717 // First get four bytes which contains the total length
718 // for this configuration.
720 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, &Desc
, 8);
722 if (EFI_ERROR (Status
)) {
723 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get descript length(%d) %r\n",
724 Desc
.TotalLength
, Status
));
729 DEBUG (( EFI_D_INFO
, "UsbGetOneConfig: total length is %d\n", Desc
.TotalLength
));
731 Buf
= AllocateZeroPool (Desc
.TotalLength
);
737 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, Buf
, Desc
.TotalLength
);
739 if (EFI_ERROR (Status
)) {
740 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get full descript %r\n", Status
));
751 Build the whole array of descriptors. This function must
752 be called after UsbGetMaxPacketSize0 returns the max packet
753 size correctly for endpoint 0.
755 @param UsbDev The Usb device.
757 @retval EFI_SUCCESS The descriptor table is build.
758 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor.
763 IN USB_DEVICE
*UsbDev
766 EFI_USB_CONFIG_DESCRIPTOR
*Config
;
767 USB_DEVICE_DESC
*DevDesc
;
768 USB_CONFIG_DESC
*ConfigDesc
;
774 // Get the device descriptor, then allocate the configure
775 // descriptor pointer array to hold configurations.
777 Status
= UsbGetDevDesc (UsbDev
);
779 if (EFI_ERROR (Status
)) {
780 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status
));
784 DevDesc
= UsbDev
->DevDesc
;
785 NumConfig
= DevDesc
->Desc
.NumConfigurations
;
786 DevDesc
->Configs
= AllocateZeroPool (NumConfig
* sizeof (USB_CONFIG_DESC
*));
788 if (DevDesc
->Configs
== NULL
) {
789 return EFI_OUT_OF_RESOURCES
;
792 DEBUG (( EFI_D_INFO
, "UsbBuildDescTable: device has %d configures\n", NumConfig
));
795 // Read each configurations, then parse them
797 for (Index
= 0; Index
< NumConfig
; Index
++) {
798 Config
= UsbGetOneConfig (UsbDev
, Index
);
800 if (Config
== NULL
) {
801 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get configure (index %d)\n", Index
));
804 // If we can get the default descriptor, it is likely that the
805 // device is still operational.
808 return EFI_DEVICE_ERROR
;
814 ConfigDesc
= UsbParseConfigDesc ((UINT8
*) Config
, Config
->TotalLength
);
816 gBS
->FreePool (Config
);
818 if (ConfigDesc
== NULL
) {
819 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index
));
822 // If we can get the default descriptor, it is likely that the
823 // device is still operational.
826 return EFI_DEVICE_ERROR
;
832 DevDesc
->Configs
[Index
] = ConfigDesc
;
836 // Don't return error even this function failed because
837 // it is possible for the device to not support strings.
839 Status
= UsbBuildLangTable (UsbDev
);
841 if (EFI_ERROR (Status
)) {
842 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: get language ID table %r\n", Status
));
850 Set the device's address.
852 @param UsbDev The device to set address to.
853 @param Address The address to set.
855 @retval EFI_SUCCESS The device is set to the address.
856 @retval Others Failed to set the device address.
861 IN USB_DEVICE
*UsbDev
,
867 Status
= UsbCtrlRequest (
870 USB_REQ_TYPE_STANDARD
,
884 Set the device's configuration. This function changes
885 the device's internal state. UsbSelectConfig changes
886 the Usb bus's internal state.
888 @param UsbDev The USB device to set configure to.
889 @param ConfigIndex The configure index to set.
891 @retval EFI_SUCCESS The device is configured now.
892 @retval Others Failed to set the device configure.
897 IN USB_DEVICE
*UsbDev
,
903 Status
= UsbCtrlRequest (
906 USB_REQ_TYPE_STANDARD
,
920 Usb UsbIo interface to clear the feature. This is should
921 only be used by HUB which is considered a device driver
922 on top of the UsbIo interface.
924 @param UsbIo The UsbIo interface.
925 @param Target The target of the transfer: endpoint/device.
926 @param Feature The feature to clear.
927 @param Index The wIndex parameter.
929 @retval EFI_SUCCESS The device feature is cleared.
930 @retval Others Failed to clear the feature.
935 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
941 EFI_USB_DEVICE_REQUEST DevReq
;
945 DevReq
.RequestType
= USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, Target
);
946 DevReq
.Request
= USB_REQ_CLEAR_FEATURE
;
947 DevReq
.Value
= Feature
;
948 DevReq
.Index
= Index
;
951 Status
= UsbIo
->UsbControlTransfer (
955 USB_CLEAR_FEATURE_REQUEST_TIMEOUT
,