3 Copyright (c) 2006, 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 Parse usb device configurations.
27 // Here are some internal helper functions
31 GetExpectedDescriptor (
36 OUT UINTN
*ParsedBytes
42 IN ENDPOINT_DESC_LIST_ENTRY
*EndpointEntry
,
44 IN UINTN BufferLength
,
45 OUT UINTN
*ParsedBytes
51 IN INTERFACE_DESC_LIST_ENTRY
*InterfaceEntry
,
54 OUT UINTN
*ParsedBytes
60 IN CONFIG_DESC_LIST_ENTRY
*ConfigDescEntry
,
70 IN USB_IO_CONTROLLER_DEVICE
*Dev
75 Tell if a usb controller is a hub controller.
78 Dev - UsbIoController device structure.
84 EFI_USB_INTERFACE_DESCRIPTOR Interface
;
85 EFI_USB_IO_PROTOCOL
*UsbIo
;
86 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
95 UsbIo
->UsbGetInterfaceDescriptor (
103 if (Interface
.InterfaceClass
!= 0x09) {
110 if (Interface
.InterfaceProtocol
!= 0x0) {
114 for (Index
= 0; Index
< Interface
.NumEndpoints
; Index
++) {
115 UsbIo
->UsbGetEndpointDescriptor (
121 if ((EndpointDescriptor
.EndpointAddress
& 0x80) == 0) {
125 if (EndpointDescriptor
.Attributes
!= 0x03) {
129 Dev
->HubEndpointAddress
= EndpointDescriptor
.EndpointAddress
;
138 IN USB_IO_DEVICE
*Dev
143 Get the string table stored in a usb device.
146 Dev - UsbIoController device structure.
157 EFI_USB_SUPPORTED_LANGUAGES
*LanguageTable
;
162 EFI_USB_IO_PROTOCOL
*UsbIo
;
165 UsbIo
= &(Dev
->UsbController
[0]->UsbIo
);
168 // We get first 2 byte of langID table,
169 // so we can have the whole table length
171 Result
= UsbGetString (
179 if (EFI_ERROR (Result
)) {
180 return EFI_UNSUPPORTED
;
183 LanguageTable
= (EFI_USB_SUPPORTED_LANGUAGES
*) &TempBuffer
;
185 if (LanguageTable
->Length
== 0) {
186 return EFI_UNSUPPORTED
;
189 // If length is 2, then there is no string table
191 if (LanguageTable
->Length
== 2) {
192 return EFI_UNSUPPORTED
;
195 Buffer
= AllocateZeroPool (LanguageTable
->Length
);
196 if (Buffer
== NULL
) {
197 return EFI_OUT_OF_RESOURCES
;
201 // Now we get the whole LangID table
203 Result
= UsbGetString (
208 LanguageTable
->Length
,
211 if (EFI_ERROR (Result
)) {
212 gBS
->FreePool (Buffer
);
213 return EFI_UNSUPPORTED
;
216 LanguageTable
= (EFI_USB_SUPPORTED_LANGUAGES
*) Buffer
;
219 // ptr point to the LangID table
222 LangTableSize
= (LanguageTable
->Length
- 2) / 2;
224 for (Index
= 0; Index
< LangTableSize
&& Index
< USB_MAXLANID
; Index
++) {
225 Dev
->LangID
[Index
] = *((UINT16
*) ptr
);
229 gBS
->FreePool (Buffer
);
230 LanguageTable
= NULL
;
237 UsbGetAllConfigurations (
238 IN USB_IO_DEVICE
*UsbIoDevice
243 This function is to parse all the configuration descriptor.
246 UsbIoDevice - USB_IO_DEVICE device structure.
260 CONFIG_DESC_LIST_ENTRY
*ConfigDescEntry
;
261 EFI_USB_IO_PROTOCOL
*UsbIo
;
263 InitializeListHead (&UsbIoDevice
->ConfigDescListHead
);
264 UsbIo
= &(UsbIoDevice
->UsbController
[0]->UsbIo
);
266 for (Index
= 0; Index
< UsbIoDevice
->DeviceDescriptor
.NumConfigurations
; Index
++) {
267 ConfigDescEntry
= NULL
;
269 ConfigDescEntry
= AllocateZeroPool (sizeof (CONFIG_DESC_LIST_ENTRY
));
270 if (ConfigDescEntry
== NULL
) {
271 return EFI_OUT_OF_RESOURCES
;
274 // 1st only get 1st 4 bytes config descriptor,
275 // so we can know the whole length
277 Result
= UsbGetDescriptor (
279 (UINT16
) ((USB_DT_CONFIG
<< 8) | Index
),
282 &ConfigDescEntry
->CongfigDescriptor
,
285 if (EFI_ERROR (Result
)) {
286 DEBUG ((gUSBErrorLevel
, "First get config descriptor error\n"));
287 gBS
->FreePool (ConfigDescEntry
);
288 return EFI_DEVICE_ERROR
;
291 TotalLength
= ConfigDescEntry
->CongfigDescriptor
.TotalLength
;
293 Buffer
= AllocateZeroPool (TotalLength
);
294 if (Buffer
== NULL
) {
295 gBS
->FreePool (ConfigDescEntry
);
296 return EFI_OUT_OF_RESOURCES
;
299 // Then we get the total descriptors for this configuration
301 Result
= UsbGetDescriptor (
303 (UINT16
) ((USB_DT_CONFIG
<< 8) | Index
),
305 (UINT16
) TotalLength
,
309 if (EFI_ERROR (Result
)) {
310 DEBUG ((gUSBErrorLevel
, "Get whole config descriptor error\n"));
311 gBS
->FreePool (ConfigDescEntry
);
312 gBS
->FreePool (Buffer
);
313 return EFI_DEVICE_ERROR
;
316 InitializeListHead (&ConfigDescEntry
->InterfaceDescListHead
);
319 // Parse this whole configuration
321 Result
= ParseThisConfig (ConfigDescEntry
, Buffer
, TotalLength
);
323 if (EFI_ERROR (Result
)) {
325 // Ignore this configuration, parse next one
327 gBS
->FreePool (ConfigDescEntry
);
328 gBS
->FreePool (Buffer
);
332 InsertTailList (&UsbIoDevice
->ConfigDescListHead
, &ConfigDescEntry
->Link
);
334 gBS
->FreePool (Buffer
);
343 GetExpectedDescriptor (
348 OUT UINTN
*ParsedBytes
353 Get the start position of next wanted descriptor.
356 Buffer - Buffer to parse
357 Length - Buffer length
358 DescType - Descriptor type
359 DescLength - Descriptor length
360 ParsedBytes - Parsed Bytes to return
367 UINT16 DescriptorHeader
;
377 // Buffer length should not less than Desc length
379 if (Length
< DescLength
) {
380 return EFI_DEVICE_ERROR
;
383 // DescriptorHeader = *((UINT16 *)ptr), compatible with IPF
385 DescriptorHeader
= (UINT16
) ((*(ptr
+ 1) << 8) | *ptr
);
390 // Check to see if it is a start of expected descriptor
392 if (DescriptorHeader
== ((DescType
<< 8) | DescLength
)) {
396 if ((UINT8
) (DescriptorHeader
>> 8) == DescType
) {
397 if (Len
> DescLength
) {
398 return EFI_DEVICE_ERROR
;
402 // Descriptor length should be at least 2
403 // and should not exceed the buffer length
406 return EFI_DEVICE_ERROR
;
410 return EFI_DEVICE_ERROR
;
413 // Skip this mismatch descriptor
420 *ParsedBytes
= Parsed
;
429 IN ENDPOINT_DESC_LIST_ENTRY
*EndpointEntry
,
431 IN UINTN BufferLength
,
432 OUT UINTN
*ParsedBytes
437 Get the start position of next wanted endpoint descriptor.
440 EndpointEntry - ENDPOINT_DESC_LIST_ENTRY
441 Buffer - Buffer to parse
442 BufferLength - Buffer Length
443 ParsedBytes - Parsed Bytes to return
455 // Skip some data for this interface
457 Status
= GetExpectedDescriptor (
461 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
),
465 if (EFI_ERROR (Status
)) {
469 ptr
= Buffer
+ SkipBytes
;
470 *ParsedBytes
= SkipBytes
;
473 &EndpointEntry
->EndpointDescriptor
,
475 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
478 *ParsedBytes
+= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
);
486 IN INTERFACE_DESC_LIST_ENTRY
*InterfaceEntry
,
489 OUT UINTN
*ParsedBytes
494 Get the start position of next wanted interface descriptor.
497 InterfaceEntry - INTERFACE_DESC_LIST_ENTRY
498 Buffer - Buffer to parse
499 BufferLength - Buffer Length
500 ParsedBytes - Parsed Bytes to return
513 ENDPOINT_DESC_LIST_ENTRY
*EndpointEntry
;
519 // Skip some data for this interface
521 Status
= GetExpectedDescriptor (
525 sizeof (EFI_USB_INTERFACE_DESCRIPTOR
),
529 if (EFI_ERROR (Status
)) {
533 ptr
= Buffer
+ SkipBytes
;
534 *ParsedBytes
= SkipBytes
;
537 // Copy the interface descriptor
540 &InterfaceEntry
->InterfaceDescriptor
,
542 sizeof (EFI_USB_INTERFACE_DESCRIPTOR
)
545 ptr
= Buffer
+ sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
546 *ParsedBytes
+= sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
548 InitializeListHead (&InterfaceEntry
->EndpointDescListHead
);
550 Length
= *BufferLen
- SkipBytes
- sizeof (EFI_USB_INTERFACE_DESCRIPTOR
);
552 for (Index
= 0; Index
< InterfaceEntry
->InterfaceDescriptor
.NumEndpoints
; Index
++) {
553 EndpointEntry
= AllocateZeroPool (sizeof (ENDPOINT_DESC_LIST_ENTRY
));
554 if (EndpointEntry
== NULL
) {
555 return EFI_OUT_OF_RESOURCES
;
559 // Parses all the endpoint descriptors within this interface.
561 Status
= ParseThisEndpoint (EndpointEntry
, ptr
, Length
, &Parsed
);
563 if (EFI_ERROR (Status
)) {
564 gBS
->FreePool (EndpointEntry
);
569 &InterfaceEntry
->EndpointDescListHead
,
575 *ParsedBytes
+= Parsed
;
584 IN CONFIG_DESC_LIST_ENTRY
*ConfigDescEntry
,
591 Parse the current configuration descriptior.
594 ConfigDescEntry - CONFIG_DESC_LIST_ENTRY
595 Buffer - Buffer to parse
596 Length - Buffer Length
607 INTERFACE_DESC_LIST_ENTRY
*InterfaceEntry
;
616 // First skip the current config descriptor;
618 Status
= GetExpectedDescriptor (
622 sizeof (EFI_USB_CONFIG_DESCRIPTOR
),
626 if (EFI_ERROR (Status
)) {
630 ptr
= Buffer
+ SkipBytes
;
633 &ConfigDescEntry
->CongfigDescriptor
,
635 sizeof (EFI_USB_CONFIG_DESCRIPTOR
)
638 NumInterface
= ConfigDescEntry
->CongfigDescriptor
.NumInterfaces
;
641 // Skip size of Configuration Descriptor
643 ptr
+= sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
645 LengthLeft
= Length
- SkipBytes
- sizeof (EFI_USB_CONFIG_DESCRIPTOR
);
647 for (Index
= 0; Index
< NumInterface
; Index
++) {
649 // Parse all Interface
651 InterfaceEntry
= AllocateZeroPool (sizeof (INTERFACE_DESC_LIST_ENTRY
));
652 if (InterfaceEntry
== NULL
) {
653 return EFI_OUT_OF_RESOURCES
;
656 Status
= ParseThisInterface (InterfaceEntry
, ptr
, &LengthLeft
, &Parsed
);
657 if (EFI_ERROR (Status
)) {
658 gBS
->FreePool (InterfaceEntry
);
663 &ConfigDescEntry
->InterfaceDescListHead
,
664 &InterfaceEntry
->Link
668 // Parsed for next interface
670 LengthLeft
-= Parsed
;
674 // Parse for additional alt setting;
680 UsbSetConfiguration (
681 IN USB_IO_DEVICE
*UsbIoDev
,
682 IN UINTN ConfigurationValue
687 Set the device to a configuration value.
690 UsbIoDev - USB_IO_DEVICE to be set configuration
691 ConfigrationValue - The configuration value to be set to that device
699 LIST_ENTRY
*NextEntry
;
700 CONFIG_DESC_LIST_ENTRY
*ConfigEntry
;
703 EFI_USB_IO_PROTOCOL
*UsbIo
;
705 UsbIo
= &(UsbIoDev
->UsbController
[0]->UsbIo
);
706 NextEntry
= UsbIoDev
->ConfigDescListHead
.ForwardLink
;
708 while (NextEntry
!= &UsbIoDev
->ConfigDescListHead
) {
712 ConfigEntry
= (CONFIG_DESC_LIST_ENTRY
*) NextEntry
;
713 if (ConfigEntry
->CongfigDescriptor
.ConfigurationValue
== ConfigurationValue
) {
715 // Find one, set to the active configuration
717 UsbIoDev
->ActiveConfig
= ConfigEntry
;
721 NextEntry
= NextEntry
->ForwardLink
;
724 // Next Entry should not be null
726 Result
= UsbSetDeviceConfiguration (
728 (UINT16
) ConfigurationValue
,
736 UsbSetDefaultConfiguration (
737 IN USB_IO_DEVICE
*UsbIoDev
742 Set the device to a default configuration value.
745 UsbIoDev - USB_IO_DEVICE to be set configuration
753 CONFIG_DESC_LIST_ENTRY
*ConfigEntry
;
755 LIST_ENTRY
*NextEntry
;
757 if (IsListEmpty (&UsbIoDev
->ConfigDescListHead
)) {
758 return EFI_DEVICE_ERROR
;
761 NextEntry
= UsbIoDev
->ConfigDescListHead
.ForwardLink
;
763 ConfigEntry
= (CONFIG_DESC_LIST_ENTRY
*) NextEntry
;
764 ConfigValue
= ConfigEntry
->CongfigDescriptor
.ConfigurationValue
;
766 return UsbSetConfiguration (UsbIoDev
, ConfigValue
);
770 UsbDestroyAllConfiguration (
771 IN USB_IO_DEVICE
*UsbIoDevice
776 Delete all configuration data when device is not used.
779 UsbIoDevice - USB_IO_DEVICE to be set configuration
786 CONFIG_DESC_LIST_ENTRY
*ConfigEntry
;
787 INTERFACE_DESC_LIST_ENTRY
*InterfaceEntry
;
788 ENDPOINT_DESC_LIST_ENTRY
*EndpointEntry
;
789 LIST_ENTRY
*NextEntry
;
792 // Delete all configuration descriptor data
794 ConfigEntry
= (CONFIG_DESC_LIST_ENTRY
*) UsbIoDevice
->ConfigDescListHead
.ForwardLink
;
796 while (ConfigEntry
!= (CONFIG_DESC_LIST_ENTRY
*) &UsbIoDevice
->ConfigDescListHead
) {
798 // Delete all its interface descriptors
800 InterfaceEntry
= (INTERFACE_DESC_LIST_ENTRY
*) ConfigEntry
->InterfaceDescListHead
.ForwardLink
;
802 while (InterfaceEntry
!= (INTERFACE_DESC_LIST_ENTRY
*) &ConfigEntry
->InterfaceDescListHead
) {
804 // Delete all its endpoint descriptors
806 EndpointEntry
= (ENDPOINT_DESC_LIST_ENTRY
*) InterfaceEntry
->EndpointDescListHead
.ForwardLink
;
807 while (EndpointEntry
!= (ENDPOINT_DESC_LIST_ENTRY
*) &InterfaceEntry
->EndpointDescListHead
) {
808 NextEntry
= ((LIST_ENTRY
*) EndpointEntry
)->ForwardLink
;
809 RemoveEntryList ((LIST_ENTRY
*) EndpointEntry
);
810 gBS
->FreePool (EndpointEntry
);
811 EndpointEntry
= (ENDPOINT_DESC_LIST_ENTRY
*) NextEntry
;
814 NextEntry
= ((LIST_ENTRY
*) InterfaceEntry
)->ForwardLink
;
815 RemoveEntryList ((LIST_ENTRY
*) InterfaceEntry
);
816 gBS
->FreePool (InterfaceEntry
);
817 InterfaceEntry
= (INTERFACE_DESC_LIST_ENTRY
*) NextEntry
;
820 NextEntry
= ((LIST_ENTRY
*) ConfigEntry
)->ForwardLink
;
821 RemoveEntryList ((LIST_ENTRY
*) ConfigEntry
);
822 gBS
->FreePool (ConfigEntry
);
823 ConfigEntry
= (CONFIG_DESC_LIST_ENTRY
*) NextEntry
;