3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Manage Usb Descriptor List
29 Free the interface setting descriptor
31 @param Setting The descriptor to free
38 UsbFreeInterfaceDesc (
39 IN USB_INTERFACE_SETTING
*Setting
42 USB_ENDPOINT_DESC
*Ep
;
45 if (Setting
->Endpoints
!= NULL
) {
47 // Each interface setting may have several endpoints, free them first.
49 for (Index
= 0; Index
< Setting
->Desc
.NumEndpoints
; Index
++) {
50 Ep
= Setting
->Endpoints
[Index
];
57 gBS
->FreePool (Setting
->Endpoints
);
60 gBS
->FreePool (Setting
);
66 Free a configuration descriptor with its interface
67 descriptors. It may be initialized partially
69 @param Config The configuration descriptor to free
77 IN USB_CONFIG_DESC
*Config
80 USB_INTERFACE_DESC
*Interface
;
84 if (Config
->Interfaces
!= NULL
) {
86 // A configuration may have several interfaces, free the interface
88 for (Index
= 0; Index
< Config
->Desc
.NumInterfaces
; Index
++) {
89 Interface
= Config
->Interfaces
[Index
];
91 if (Interface
== NULL
) {
96 // Each interface may have several settings, free the settings
98 for (SetIndex
= 0; SetIndex
< Interface
->NumOfSetting
; SetIndex
++) {
99 if (Interface
->Settings
[SetIndex
] != NULL
) {
100 UsbFreeInterfaceDesc (Interface
->Settings
[SetIndex
]);
104 gBS
->FreePool (Interface
);
107 gBS
->FreePool (Config
->Interfaces
);
110 gBS
->FreePool (Config
);
117 Free a device descriptor with its configurations
119 @param DevDesc The device descriptor
126 IN USB_DEVICE_DESC
*DevDesc
131 if (DevDesc
->Configs
!= NULL
) {
132 for (Index
= 0; Index
< DevDesc
->Desc
.NumConfigurations
; Index
++) {
133 if (DevDesc
->Configs
[Index
] != NULL
) {
134 UsbFreeConfigDesc (DevDesc
->Configs
[Index
]);
138 gBS
->FreePool (DevDesc
->Configs
);
141 gBS
->FreePool (DevDesc
);
148 @param DescBuf The buffer of raw descriptor
149 @param Len The lenght of the raw descriptor buffer
150 @param Type The type of descriptor to create
151 @param Consumed Number of bytes consumed
153 @return Created descriptor or NULL
176 case USB_DESC_TYPE_DEVICE
:
177 DescLen
= sizeof (EFI_USB_DEVICE_DESCRIPTOR
);
178 CtrlLen
= sizeof (USB_DEVICE_DESC
);
181 case USB_DESC_TYPE_CONFIG
:
182 DescLen
= sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
183 CtrlLen
= sizeof (USB_CONFIG_DESC
);
186 case USB_DESC_TYPE_INTERFACE
:
187 DescLen
= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
188 CtrlLen
= sizeof (USB_INTERFACE_SETTING
);
191 case USB_DESC_TYPE_ENDPOINT
:
192 DescLen
= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
193 CtrlLen
= sizeof (USB_ENDPOINT_DESC
);
198 // All the descriptor has a common LTV (Length, Type, Value)
199 // format. Skip the descriptor that isn't of this Type
202 Head
= (USB_DESC_HEAD
*)DescBuf
;
204 while ((Offset
< Len
) && (Head
->Type
!= Type
)) {
206 Head
= (USB_DESC_HEAD
*)(DescBuf
+ Offset
);
209 if ((Len
<= Offset
) || (Len
< Offset
+ DescLen
) ||
210 (Head
->Type
!= Type
) || (Head
->Len
!= DescLen
)) {
211 DEBUG (( EFI_D_ERROR
, "UsbCreateDesc: met mal-format descriptor\n"));
215 Desc
= AllocateZeroPool (CtrlLen
);
221 CopyMem (Desc
, Head
, DescLen
);
222 *Consumed
= Offset
+ Head
->Len
;
229 Parse an interface desciptor and its endpoints
231 @param DescBuf The buffer of raw descriptor
232 @param Len The lenght of the raw descriptor buffer
233 @param Consumed The number of raw descriptor consumed
235 @return The create interface setting or NULL if failed
239 USB_INTERFACE_SETTING
*
240 UsbParseInterfaceDesc (
246 USB_INTERFACE_SETTING
*Setting
;
247 USB_ENDPOINT_DESC
*Ep
;
254 Setting
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_INTERFACE
, &Used
);
256 if (Setting
== NULL
) {
257 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));
264 // Create an arry to hold the interface's endpoints
266 NumEp
= Setting
->Desc
.NumEndpoints
;
268 DEBUG (( EFI_D_INFO
, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
269 Setting
->Desc
.InterfaceNumber
, Setting
->Desc
.AlternateSetting
, NumEp
));
275 Setting
->Endpoints
= AllocateZeroPool (sizeof (USB_ENDPOINT_DESC
*) * NumEp
);
277 if (Setting
->Endpoints
== NULL
) {
282 // Create the endpoints for this interface
284 for (Index
= 0; Index
< NumEp
; Index
++) {
285 Ep
= UsbCreateDesc (DescBuf
+ Offset
, Len
- Offset
, USB_DESC_TYPE_ENDPOINT
, &Used
);
288 DEBUG (( EFI_D_ERROR
, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", Index
));
292 Setting
->Endpoints
[Index
] = Ep
;
302 UsbFreeInterfaceDesc (Setting
);
308 Parse the configuration descriptor and its interfaces.
310 @param DescBuf The buffer of raw descriptor
311 @param Len The lenght of the raw descriptor buffer
313 @return The created configuration descriptor
323 USB_CONFIG_DESC
*Config
;
324 USB_INTERFACE_SETTING
*Setting
;
325 USB_INTERFACE_DESC
*Interface
;
330 ASSERT (DescBuf
!= NULL
);
332 Config
= UsbCreateDesc (DescBuf
, Len
, USB_DESC_TYPE_CONFIG
, &Consumed
);
334 if (Config
== NULL
) {
339 // Initialize an array of setting for the configuration's interfaces.
341 NumIf
= Config
->Desc
.NumInterfaces
;
342 Config
->Interfaces
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
*) * NumIf
);
344 if (Config
->Interfaces
== NULL
) {
348 DEBUG (( EFI_D_INFO
, "UsbParseConfigDesc: config %d has %d interfaces\n",
349 Config
->Desc
.ConfigurationValue
, NumIf
));
351 for (Index
= 0; Index
< NumIf
; Index
++) {
352 Interface
= AllocateZeroPool (sizeof (USB_INTERFACE_DESC
));
354 if (Interface
== NULL
) {
358 Config
->Interfaces
[Index
] = Interface
;
362 // If a configuration has several interfaces, these interfaces are
363 // numbered from zero to n. If a interface has several settings,
364 // these settings are also number from zero to m. The interface
365 // setting must be organized as |interface 0, setting 0|interface 0
366 // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
367 // USB2.0 spec, page 267.
373 Setting
= UsbParseInterfaceDesc (DescBuf
, Len
, &Consumed
);
375 if ((Setting
== NULL
)) {
376 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: failed to parse interface setting\n"));
379 } else if (Setting
->Desc
.InterfaceNumber
>= NumIf
) {
380 DEBUG (( EFI_D_ERROR
, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
382 UsbFreeInterfaceDesc (Setting
);
387 // Insert the descriptor to the corresponding set.
389 Interface
= Config
->Interfaces
[Setting
->Desc
.InterfaceNumber
];
391 if (Interface
->NumOfSetting
>= USB_MAX_INTERFACE_SETTING
) {
395 Interface
->Settings
[Interface
->NumOfSetting
] = Setting
;
396 Interface
->NumOfSetting
++;
405 UsbFreeConfigDesc (Config
);
412 USB standard control transfer support routine. This
413 function is used by USB device. It is possible that
414 the device's interfaces are still waiting to be
417 @param UsbDev The usb device
418 @param Direction The direction of data transfer
419 @param Type Standard / class specific / vendor specific
420 @param Target The receiving target
421 @param Request Which request
422 @param Value The wValue parameter of the request
423 @param Index The wIndex parameter of the request
424 @param Buf The buffer to receive data into / transmit from
425 @param Length The length of the buffer
427 @retval EFI_SUCCESS The control request is executed
428 @retval EFI_DEVICE_ERROR Failed to execute the control transfer
433 IN USB_DEVICE
*UsbDev
,
434 IN EFI_USB_DATA_DIRECTION Direction
,
444 EFI_USB_DEVICE_REQUEST DevReq
;
449 ASSERT ((UsbDev
!= NULL
) && (UsbDev
->Bus
!= NULL
));
451 DevReq
.RequestType
= USB_REQUEST_TYPE (Direction
, Type
, Target
);
452 DevReq
.Request
= (UINT8
) Request
;
453 DevReq
.Value
= Value
;
454 DevReq
.Index
= Index
;
455 DevReq
.Length
= (UINT16
) Length
;
458 Status
= UsbHcControlTransfer (
478 Get the standard descriptors.
480 @param UsbDev The USB device to read descriptor from
481 @param DescType The type of descriptor to read
482 @param DescIndex The index of descriptor to read
483 @param LangId Language ID, only used to get string, otherwise set
485 @param Buf The buffer to hold the descriptor read
486 @param Length The length of the buffer
488 @retval EFI_SUCCESS The descriptor is read OK
489 @retval Others Failed to retrieve the descriptor
495 IN USB_DEVICE
*UsbDev
,
505 Status
= UsbCtrlRequest (
508 USB_REQ_TYPE_STANDARD
,
510 USB_REQ_GET_DESCRIPTOR
,
511 (UINT16
) ((DescType
<< 8) | DescIndex
),
523 Return the max packet size for endpoint zero. This function
524 is the first function called to get descriptors during bus
527 @param UsbDev The usb device
529 @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved
530 @retval EFI_DEVICE_ERROR Failed to retrieve it
534 UsbGetMaxPacketSize0 (
535 IN USB_DEVICE
*UsbDev
538 EFI_USB_DEVICE_DESCRIPTOR DevDesc
;
544 // Get the first 8 bytes of the device descriptor which contains
545 // max packet size for endpoint 0, which is at least 8.
547 UsbDev
->MaxPacket0
= 8;
549 for (Index
= 0; Index
< 3; Index
++) {
550 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_DEVICE
, 0, 0, &DevDesc
, 8);
552 if (!EFI_ERROR (Status
)) {
553 UsbDev
->MaxPacket0
= DevDesc
.MaxPacketSize0
;
557 gBS
->Stall (100 * USB_STALL_1_MS
);
560 return EFI_DEVICE_ERROR
;
566 Get the device descriptor for the device.
568 @param UsbDev The Usb device to retrieve descriptor from
570 @retval EFI_SUCCESS The device descriptor is returned
571 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory
577 IN USB_DEVICE
*UsbDev
580 USB_DEVICE_DESC
*DevDesc
;
583 DevDesc
= AllocateZeroPool (sizeof (USB_DEVICE_DESC
));
585 if (DevDesc
== NULL
) {
586 return EFI_OUT_OF_RESOURCES
;
589 Status
= UsbCtrlGetDesc (
591 USB_DESC_TYPE_DEVICE
,
595 sizeof (EFI_USB_DEVICE_DESCRIPTOR
)
598 if (EFI_ERROR (Status
)) {
599 gBS
->FreePool (DevDesc
);
601 UsbDev
->DevDesc
= DevDesc
;
610 Retrieve the indexed string for the language. It requires two
611 steps to get a string, first to get the string's length. Then
614 @param UsbDev The usb device
615 @param Index The index the string to retrieve
616 @param LangId Language ID
618 @return The created string descriptor or NULL
621 EFI_USB_STRING_DESCRIPTOR
*
623 IN USB_DEVICE
*UsbDev
,
628 EFI_USB_STRING_DESCRIPTOR Desc
;
633 // First get two bytes which contains the string length.
635 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_STRING
, Index
, LangId
, &Desc
, 2);
637 if (EFI_ERROR (Status
)) {
641 Buf
= AllocateZeroPool (Desc
.Length
);
647 Status
= UsbCtrlGetDesc (
649 USB_DESC_TYPE_STRING
,
656 if (EFI_ERROR (Status
)) {
661 return (EFI_USB_STRING_DESCRIPTOR
*) Buf
;
667 Build the language ID table for string descriptors
669 @param UsbDev The Usb device
671 @retval EFI_UNSUPPORTED This device doesn't support string table
677 IN USB_DEVICE
*UsbDev
680 EFI_USB_STRING_DESCRIPTOR
*Desc
;
687 // The string of language ID zero returns the supported languages
689 Desc
= UsbGetOneString (UsbDev
, 0, 0);
692 return EFI_UNSUPPORTED
;
695 if (Desc
->Length
< 4) {
696 Status
= EFI_UNSUPPORTED
;
700 Status
= EFI_SUCCESS
;
702 Max
= (Desc
->Length
- 2) / 2;
703 Max
= (Max
< USB_MAX_LANG_ID
? Max
: USB_MAX_LANG_ID
);
705 Point
= Desc
->String
;
706 for (Index
= 0; Index
< Max
; Index
++) {
707 UsbDev
->LangId
[Index
] = *Point
;
711 UsbDev
->TotalLangId
= (UINT16
)Max
;
714 gBS
->FreePool (Desc
);
721 Retrieve the indexed configure for the device. USB device
722 returns the configuration togetther with the interfaces for
723 this configuration. Configuration descriptor is also of
726 @param UsbDev The Usb interface
727 @param Index The index of the configuration
729 @return The created configuration descriptor
733 EFI_USB_CONFIG_DESCRIPTOR
*
735 IN USB_DEVICE
*UsbDev
,
739 EFI_USB_CONFIG_DESCRIPTOR Desc
;
744 // First get four bytes which contains the total length
745 // for this configuration.
747 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, &Desc
, 8);
749 if (EFI_ERROR (Status
)) {
750 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get descript length(%d) %r\n",
751 Status
, Desc
.TotalLength
));
756 DEBUG (( EFI_D_INFO
, "UsbGetOneConfig: total length is %d\n", Desc
.TotalLength
));
758 Buf
= AllocateZeroPool (Desc
.TotalLength
);
764 Status
= UsbCtrlGetDesc (UsbDev
, USB_DESC_TYPE_CONFIG
, Index
, 0, Buf
, Desc
.TotalLength
);
766 if (EFI_ERROR (Status
)) {
767 DEBUG (( EFI_D_ERROR
, "UsbGetOneConfig: failed to get full descript %r\n", Status
));
779 Build the whole array of descriptors. This function must
780 be called after UsbGetMaxPacketSize0 returns the max packet
781 size correctly for endpoint 0.
783 @param UsbDev The Usb device
785 @retval EFI_SUCCESS The descriptor table is build
786 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor
791 IN USB_DEVICE
*UsbDev
794 EFI_USB_CONFIG_DESCRIPTOR
*Config
;
795 USB_DEVICE_DESC
*DevDesc
;
796 USB_CONFIG_DESC
*ConfigDesc
;
802 // Get the device descriptor, then allocate the configure
803 // descriptor pointer array to hold configurations.
805 Status
= UsbGetDevDesc (UsbDev
);
807 if (EFI_ERROR (Status
)) {
808 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status
));
812 DevDesc
= UsbDev
->DevDesc
;
813 NumConfig
= DevDesc
->Desc
.NumConfigurations
;
814 DevDesc
->Configs
= AllocateZeroPool (NumConfig
* sizeof (USB_CONFIG_DESC
*));
816 if (DevDesc
->Configs
== NULL
) {
817 return EFI_OUT_OF_RESOURCES
;
820 DEBUG (( EFI_D_INFO
, "UsbBuildDescTable: device has %d configures\n", NumConfig
));
823 // Read each configurations, then parse them
825 for (Index
= 0; Index
< NumConfig
; Index
++) {
826 Config
= UsbGetOneConfig (UsbDev
, Index
);
828 if (Config
== NULL
) {
829 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to get configure (index %d)\n", Index
));
832 // If we can get the default descriptor, it is likely that the
833 // device is still operational.
836 return EFI_DEVICE_ERROR
;
842 ConfigDesc
= UsbParseConfigDesc ((UINT8
*) Config
, Config
->TotalLength
);
844 gBS
->FreePool (Config
);
846 if (ConfigDesc
== NULL
) {
847 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index
));
850 // If we can get the default descriptor, it is likely that the
851 // device is still operational.
854 return EFI_DEVICE_ERROR
;
860 DevDesc
->Configs
[Index
] = ConfigDesc
;
864 // Don't return error even this function failed because
865 // it is possible for the device to not support strings.
867 Status
= UsbBuildLangTable (UsbDev
);
869 if (EFI_ERROR (Status
)) {
870 DEBUG (( EFI_D_ERROR
, "UsbBuildDescTable: get language ID table %r\n", Status
));
878 Set the device's address.
880 @param UsbDev The device to set address to
881 @param Address The address to set
883 @retval EFI_SUCCESS The device is set to the address
884 @retval Others Failed to set the device address
889 IN USB_DEVICE
*UsbDev
,
895 Status
= UsbCtrlRequest (
898 USB_REQ_TYPE_STANDARD
,
912 Set the device's configuration. This function changes
913 the device's internal state. UsbSelectConfig changes
914 the Usb bus's internal state.
916 @param UsbDev The USB device to set configure to
917 @param ConfigIndex The configure index to set
919 @retval EFI_SUCCESS The device is configured now
920 @retval Others Failed to set the device configure
925 IN USB_DEVICE
*UsbDev
,
931 Status
= UsbCtrlRequest (
934 USB_REQ_TYPE_STANDARD
,
949 Usb UsbIo interface to clear the feature. This is should
950 only be used by HUB which is considered a device driver
951 on top of the UsbIo interface.
953 @param UsbIo The UsbIo interface
954 @param Target The target of the transfer: endpoint/device
955 @param Feature The feature to clear
956 @param Index The wIndex parameter
958 @retval EFI_SUCCESS The device feature is cleared
959 @retval Others Failed to clear the feature
964 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
970 EFI_USB_DEVICE_REQUEST DevReq
;
974 DevReq
.RequestType
= USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
, Target
);
975 DevReq
.Request
= USB_REQ_CLEAR_FEATURE
;
976 DevReq
.Value
= Feature
;
977 DevReq
.Index
= Index
;
980 Status
= UsbIo
->UsbControlTransfer (