2. Use ZeroMem to replace gBS->SetMem; 3. Remove marked code; 4. Add IsHub judgement in UsbPortReset function to following EFI1.1 spec; 5. Add brackets for macro definition git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1740 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			826 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			826 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2006, Intel Corporation                                                         
 | |
| All rights reserved. This program and the accompanying materials                          
 | |
| are licensed and made available under the terms and conditions of the BSD License         
 | |
| which accompanies this distribution.  The full text of the license may be found at        
 | |
| http://opensource.org/licenses/bsd-license.php                                            
 | |
|                                                                                           
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | |
| 
 | |
|   Module Name:
 | |
| 
 | |
|     Usb.c
 | |
| 
 | |
|   Abstract:
 | |
| 
 | |
|     Parse usb device configurations.
 | |
| 
 | |
|   Revision History
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include "usbbus.h"
 | |
| 
 | |
| //
 | |
| // Here are some internal helper functions
 | |
| //
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| GetExpectedDescriptor (
 | |
|   IN  UINT8     *Buffer,
 | |
|   IN  UINTN     Length,
 | |
|   IN  UINT8     DescType,
 | |
|   IN  UINT8     DescLength,
 | |
|   OUT UINTN     *ParsedBytes
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ParseThisEndpoint (
 | |
|   IN  ENDPOINT_DESC_LIST_ENTRY     *EndpointEntry,
 | |
|   IN  UINT8                        *Buffer,
 | |
|   IN  UINTN                        BufferLength,
 | |
|   OUT UINTN                        *ParsedBytes
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ParseThisInterface (
 | |
|   IN  INTERFACE_DESC_LIST_ENTRY      *InterfaceEntry,
 | |
|   IN  UINT8                          *Buffer,
 | |
|   IN  UINTN                          *BufferLen,
 | |
|   OUT UINTN                          *ParsedBytes
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ParseThisConfig (
 | |
|   IN CONFIG_DESC_LIST_ENTRY     *ConfigDescEntry,
 | |
|   IN UINT8                      *Buffer,
 | |
|   IN UINTN                      Length
 | |
|   );
 | |
| 
 | |
| //
 | |
| // Implementations
 | |
| //
 | |
| BOOLEAN
 | |
| IsHub (
 | |
|   IN USB_IO_CONTROLLER_DEVICE     *Dev
 | |
|   )
 | |
| /*++
 | |
|   
 | |
|   Routine Description:
 | |
|     Tell if a usb controller is a hub controller.
 | |
|     
 | |
|   Arguments:
 | |
|     Dev - UsbIoController device structure.
 | |
|     
 | |
|   Returns:
 | |
|     TRUE/FALSE
 | |
| --*/
 | |
| {
 | |
|   EFI_USB_INTERFACE_DESCRIPTOR  Interface;
 | |
|   EFI_USB_IO_PROTOCOL           *UsbIo;
 | |
|   EFI_USB_ENDPOINT_DESCRIPTOR   EndpointDescriptor;
 | |
|   UINT8                         Index;
 | |
| 
 | |
|   if (Dev == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   UsbIo = &Dev->UsbIo;
 | |
| 
 | |
|   UsbIo->UsbGetInterfaceDescriptor (
 | |
|           UsbIo,
 | |
|           &Interface
 | |
|           );
 | |
| 
 | |
|   //
 | |
|   // Check classcode
 | |
|   //
 | |
|   if (Interface.InterfaceClass != 0x09) {
 | |
|     return FALSE;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Check protocol
 | |
|   //
 | |
|   if (Interface.InterfaceProtocol != 0x0) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < Interface.NumEndpoints; Index++) {
 | |
|     UsbIo->UsbGetEndpointDescriptor (
 | |
|             UsbIo,
 | |
|             Index,
 | |
|             &EndpointDescriptor
 | |
|             );
 | |
| 
 | |
|     if ((EndpointDescriptor.EndpointAddress & 0x80) == 0) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (EndpointDescriptor.Attributes != 0x03) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     Dev->HubEndpointAddress = EndpointDescriptor.EndpointAddress;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| UsbGetStringtable (
 | |
|   IN USB_IO_DEVICE     *Dev
 | |
|   )
 | |
| /*++
 | |
|   
 | |
|   Routine Description:
 | |
|     Get the string table stored in a usb device.
 | |
|     
 | |
|   Arguments:
 | |
|     Dev     -     UsbIoController device structure.
 | |
|     
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_UNSUPPORTED
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Result;
 | |
|   UINT32                      Status;
 | |
|   EFI_USB_SUPPORTED_LANGUAGES *LanguageTable;
 | |
|   UINT8                       *Buffer;
 | |
|   UINT8                       *ptr;
 | |
|   UINTN                       Index;
 | |
|   UINTN                       LangTableSize;
 | |
|   EFI_USB_IO_PROTOCOL         *UsbIo;
 | |
|   UINT16                      TempBuffer;
 | |
| 
 | |
|   UsbIo = &(Dev->UsbController[0]->UsbIo);
 | |
| 
 | |
|   //
 | |
|   // We get first 2 byte of langID table,
 | |
|   // so we can have the whole table length
 | |
|   //
 | |
|   Result = UsbGetString (
 | |
|             UsbIo,
 | |
|             0,
 | |
|             0,
 | |
|             &TempBuffer,
 | |
|             2,
 | |
|             &Status
 | |
|             );
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   LanguageTable = (EFI_USB_SUPPORTED_LANGUAGES *) &TempBuffer;
 | |
| 
 | |
|   if (LanguageTable->Length == 0) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   //
 | |
|   // If length is 2, then there is no string table
 | |
|   //
 | |
|   if (LanguageTable->Length == 2) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   Buffer = AllocateZeroPool (LanguageTable->Length);
 | |
|   if (Buffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Now we get the whole LangID table
 | |
|   //
 | |
|   Result = UsbGetString (
 | |
|             UsbIo,
 | |
|             0,
 | |
|             0,
 | |
|             Buffer,
 | |
|             LanguageTable->Length,
 | |
|             &Status
 | |
|             );
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     gBS->FreePool (Buffer);
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   LanguageTable = (EFI_USB_SUPPORTED_LANGUAGES *) Buffer;
 | |
| 
 | |
|   //
 | |
|   // ptr point to the LangID table
 | |
|   //
 | |
|   ptr           = Buffer + 2;
 | |
|   LangTableSize = (LanguageTable->Length - 2) / 2;
 | |
| 
 | |
|   for (Index = 0; Index < LangTableSize && Index < USB_MAXLANID; Index++) {
 | |
|     Dev->LangID[Index] = *((UINT16 *) ptr);
 | |
|     ptr += 2;
 | |
|   }
 | |
| 
 | |
|   gBS->FreePool (Buffer);
 | |
|   LanguageTable = NULL;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| EFI_STATUS
 | |
| UsbGetAllConfigurations (
 | |
|   IN USB_IO_DEVICE     *UsbIoDevice
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     This function is to parse all the configuration descriptor.
 | |
|     
 | |
|   Arguments:
 | |
|     UsbIoDevice  -  USB_IO_DEVICE device structure.
 | |
|     
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
|     EFI_OUT_OF_RESOURCES  
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS              Result;
 | |
|   UINT32                  Status;
 | |
|   UINTN                   Index;
 | |
|   UINTN                   TotalLength;
 | |
|   UINT8                   *Buffer;
 | |
|   CONFIG_DESC_LIST_ENTRY  *ConfigDescEntry;
 | |
|   EFI_USB_IO_PROTOCOL     *UsbIo;
 | |
| 
 | |
|   InitializeListHead (&UsbIoDevice->ConfigDescListHead);
 | |
|   UsbIo = &(UsbIoDevice->UsbController[0]->UsbIo);
 | |
| 
 | |
|   for (Index = 0; Index < UsbIoDevice->DeviceDescriptor.NumConfigurations; Index++) {
 | |
|     ConfigDescEntry = NULL;
 | |
| 
 | |
|     ConfigDescEntry = AllocateZeroPool (sizeof (CONFIG_DESC_LIST_ENTRY));
 | |
|     if (ConfigDescEntry == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     //
 | |
|     // 1st only get 1st 4 bytes config descriptor,
 | |
|     // so we can know the whole length
 | |
|     //
 | |
|     Result = UsbGetDescriptor (
 | |
|               UsbIo,
 | |
|               (UINT16) ((USB_DT_CONFIG << 8) | Index),
 | |
|               0,
 | |
|               4,
 | |
|               &ConfigDescEntry->CongfigDescriptor,
 | |
|               &Status
 | |
|               );
 | |
|     if (EFI_ERROR (Result)) {
 | |
|       DEBUG ((gUSBErrorLevel, "First get config descriptor error\n"));
 | |
|       gBS->FreePool (ConfigDescEntry);
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     TotalLength = ConfigDescEntry->CongfigDescriptor.TotalLength;
 | |
| 
 | |
|     Buffer      = AllocateZeroPool (TotalLength);
 | |
|     if (Buffer == NULL) {
 | |
|       gBS->FreePool (ConfigDescEntry);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     //
 | |
|     // Then we get the total descriptors for this configuration
 | |
|     //
 | |
|     Result = UsbGetDescriptor (
 | |
|               UsbIo,
 | |
|               (UINT16) ((USB_DT_CONFIG << 8) | Index),
 | |
|               0,
 | |
|               (UINT16) TotalLength,
 | |
|               Buffer,
 | |
|               &Status
 | |
|               );
 | |
|     if (EFI_ERROR (Result)) {
 | |
|       DEBUG ((gUSBErrorLevel, "Get whole config descriptor error\n"));
 | |
|       gBS->FreePool (ConfigDescEntry);
 | |
|       gBS->FreePool (Buffer);
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     InitializeListHead (&ConfigDescEntry->InterfaceDescListHead);
 | |
| 
 | |
|     //
 | |
|     // Parse this whole configuration
 | |
|     //
 | |
|     Result = ParseThisConfig (ConfigDescEntry, Buffer, TotalLength);
 | |
| 
 | |
|     if (EFI_ERROR (Result)) {
 | |
|       //
 | |
|       // Ignore this configuration, parse next one
 | |
|       //
 | |
|       gBS->FreePool (ConfigDescEntry);
 | |
|       gBS->FreePool (Buffer);
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     InsertTailList (&UsbIoDevice->ConfigDescListHead, &ConfigDescEntry->Link);
 | |
| 
 | |
|     gBS->FreePool (Buffer);
 | |
| 
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| GetExpectedDescriptor (
 | |
|   IN  UINT8     *Buffer,
 | |
|   IN  UINTN     Length,
 | |
|   IN  UINT8     DescType,
 | |
|   IN  UINT8     DescLength,
 | |
|   OUT UINTN     *ParsedBytes
 | |
|   )
 | |
| /*++
 | |
|   
 | |
|   Routine Description:
 | |
|     Get the start position of next wanted descriptor.
 | |
|     
 | |
|   Arguments:
 | |
|     Buffer      - Buffer to parse
 | |
|     Length      - Buffer length 
 | |
|     DescType    - Descriptor type 
 | |
|     DescLength  - Descriptor length
 | |
|     ParsedBytes - Parsed Bytes to return
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT16  DescriptorHeader;
 | |
|   UINT8   Len;
 | |
|   UINT8   *ptr;
 | |
|   UINTN   Parsed;
 | |
| 
 | |
|   Parsed  = 0;
 | |
|   ptr     = Buffer;
 | |
| 
 | |
|   while (TRUE) {
 | |
|     //
 | |
|     // Buffer length should not less than Desc length
 | |
|     //
 | |
|     if (Length < DescLength) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     //
 | |
|     // DescriptorHeader = *((UINT16 *)ptr), compatible with IPF
 | |
|     //
 | |
|     DescriptorHeader  = (UINT16) ((*(ptr + 1) << 8) | *ptr);
 | |
| 
 | |
|     Len               = ptr[0];
 | |
| 
 | |
|     //
 | |
|     // Check to see if it is a start of expected descriptor
 | |
|     //
 | |
|     if (DescriptorHeader == ((DescType << 8) | DescLength)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if ((UINT8) (DescriptorHeader >> 8) == DescType) {
 | |
|       if (Len > DescLength) {
 | |
|         return EFI_DEVICE_ERROR;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // Descriptor length should be at least 2
 | |
|     // and should not exceed the buffer length
 | |
|     //
 | |
|     if (Len < 2) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (Len > Length) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     //
 | |
|     // Skip this mismatch descriptor
 | |
|     //
 | |
|     Length -= Len;
 | |
|     ptr += Len;
 | |
|     Parsed += Len;
 | |
|   }
 | |
| 
 | |
|   *ParsedBytes = Parsed;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ParseThisEndpoint (
 | |
|   IN  ENDPOINT_DESC_LIST_ENTRY     *EndpointEntry,
 | |
|   IN  UINT8                        *Buffer,
 | |
|   IN  UINTN                        BufferLength,
 | |
|   OUT UINTN                        *ParsedBytes
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Get the start position of next wanted endpoint descriptor.
 | |
| 
 | |
|   Arguments:
 | |
|     EndpointEntry - ENDPOINT_DESC_LIST_ENTRY
 | |
|     Buffer        - Buffer to parse 
 | |
|     BufferLength  - Buffer Length
 | |
|     ParsedBytes   - Parsed Bytes to return
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8       *ptr;
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       SkipBytes;
 | |
| 
 | |
|   //
 | |
|   // Skip some data for this interface
 | |
|   //
 | |
|   Status = GetExpectedDescriptor (
 | |
|             Buffer,
 | |
|             BufferLength,
 | |
|             USB_DT_ENDPOINT,
 | |
|             sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),
 | |
|             &SkipBytes
 | |
|             );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ptr           = Buffer + SkipBytes;
 | |
|   *ParsedBytes  = SkipBytes;
 | |
| 
 | |
|   CopyMem (
 | |
|     &EndpointEntry->EndpointDescriptor,
 | |
|     ptr,
 | |
|     sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
 | |
|     );
 | |
| 
 | |
|   *ParsedBytes += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ParseThisInterface (
 | |
|   IN  INTERFACE_DESC_LIST_ENTRY     *InterfaceEntry,
 | |
|   IN  UINT8                         *Buffer,
 | |
|   IN  UINTN                         *BufferLen,
 | |
|   OUT UINTN                         *ParsedBytes
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Get the start position of next wanted interface descriptor.
 | |
| 
 | |
|   Arguments:
 | |
|     InterfaceEntry - INTERFACE_DESC_LIST_ENTRY
 | |
|     Buffer         - Buffer to parse 
 | |
|     BufferLength   - Buffer Length
 | |
|     ParsedBytes    - Parsed Bytes to return
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8                     *ptr;
 | |
|   UINTN                     SkipBytes;
 | |
|   UINTN                     Index;
 | |
|   UINTN                     Length;
 | |
|   UINTN                     Parsed;
 | |
|   ENDPOINT_DESC_LIST_ENTRY  *EndpointEntry;
 | |
|   EFI_STATUS                Status;
 | |
| 
 | |
|   Parsed = 0;
 | |
| 
 | |
|   //
 | |
|   // Skip some data for this interface
 | |
|   //
 | |
|   Status = GetExpectedDescriptor (
 | |
|             Buffer,
 | |
|             *BufferLen,
 | |
|             USB_DT_INTERFACE,
 | |
|             sizeof (EFI_USB_INTERFACE_DESCRIPTOR),
 | |
|             &SkipBytes
 | |
|             );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ptr           = Buffer + SkipBytes;
 | |
|   *ParsedBytes  = SkipBytes;
 | |
| 
 | |
|   //
 | |
|   // Copy the interface descriptor
 | |
|   //
 | |
|   CopyMem (
 | |
|     &InterfaceEntry->InterfaceDescriptor,
 | |
|     ptr,
 | |
|     sizeof (EFI_USB_INTERFACE_DESCRIPTOR)
 | |
|     );
 | |
| 
 | |
|   ptr = Buffer + sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
 | |
|   *ParsedBytes += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
 | |
| 
 | |
|   InitializeListHead (&InterfaceEntry->EndpointDescListHead);
 | |
| 
 | |
|   Length = *BufferLen - SkipBytes - sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
 | |
| 
 | |
|   for (Index = 0; Index < InterfaceEntry->InterfaceDescriptor.NumEndpoints; Index++) {
 | |
|     EndpointEntry = AllocateZeroPool (sizeof (ENDPOINT_DESC_LIST_ENTRY));
 | |
|     if (EndpointEntry == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // Parses all the endpoint descriptors within this interface.
 | |
|     //
 | |
|     Status = ParseThisEndpoint (EndpointEntry, ptr, Length, &Parsed);
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       gBS->FreePool (EndpointEntry);
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     InsertTailList (
 | |
|       &InterfaceEntry->EndpointDescListHead,
 | |
|       &EndpointEntry->Link
 | |
|       );
 | |
| 
 | |
|     Length -= Parsed;
 | |
|     ptr += Parsed;
 | |
|     *ParsedBytes += Parsed;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ParseThisConfig (
 | |
|   IN CONFIG_DESC_LIST_ENTRY     *ConfigDescEntry,
 | |
|   IN UINT8                      *Buffer,
 | |
|   IN UINTN                      Length
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Parse the current configuration descriptior.
 | |
| 
 | |
|   Arguments:
 | |
|     ConfigDescEntry - CONFIG_DESC_LIST_ENTRY
 | |
|     Buffer          - Buffer to parse 
 | |
|     Length          - Buffer Length
 | |
| 
 | |
|   Returns
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8                     *ptr;
 | |
|   UINT8                     NumInterface;
 | |
|   UINTN                     Index;
 | |
|   INTERFACE_DESC_LIST_ENTRY *InterfaceEntry;
 | |
|   UINTN                     SkipBytes;
 | |
|   UINTN                     Parsed;
 | |
|   EFI_STATUS                Status;
 | |
|   UINTN                     LengthLeft;
 | |
| 
 | |
|   Parsed = 0;
 | |
| 
 | |
|   //
 | |
|   //  First skip the current config descriptor;
 | |
|   //
 | |
|   Status = GetExpectedDescriptor (
 | |
|             Buffer,
 | |
|             Length,
 | |
|             USB_DT_CONFIG,
 | |
|             sizeof (EFI_USB_CONFIG_DESCRIPTOR),
 | |
|             &SkipBytes
 | |
|             );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ptr = Buffer + SkipBytes;
 | |
| 
 | |
|   CopyMem (
 | |
|     &ConfigDescEntry->CongfigDescriptor,
 | |
|     ptr,
 | |
|     sizeof (EFI_USB_CONFIG_DESCRIPTOR)
 | |
|     );
 | |
| 
 | |
|   NumInterface = ConfigDescEntry->CongfigDescriptor.NumInterfaces;
 | |
| 
 | |
|   //
 | |
|   // Skip size of Configuration Descriptor
 | |
|   //
 | |
|   ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);
 | |
| 
 | |
|   LengthLeft = Length - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);
 | |
| 
 | |
|   for (Index = 0; Index < NumInterface; Index++) {
 | |
|     //
 | |
|     // Parse all Interface
 | |
|     //
 | |
|     InterfaceEntry = AllocateZeroPool (sizeof (INTERFACE_DESC_LIST_ENTRY));
 | |
|     if (InterfaceEntry == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     Status = ParseThisInterface (InterfaceEntry, ptr, &LengthLeft, &Parsed);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       gBS->FreePool (InterfaceEntry);
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     InsertTailList (
 | |
|       &ConfigDescEntry->InterfaceDescListHead,
 | |
|       &InterfaceEntry->Link
 | |
|       );
 | |
| 
 | |
|     //
 | |
|     // Parsed for next interface
 | |
|     //
 | |
|     LengthLeft -= Parsed;
 | |
|     ptr += Parsed;
 | |
|   }
 | |
|   //
 | |
|   // Parse for additional alt setting;
 | |
|   //
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| UsbSetConfiguration (
 | |
|   IN USB_IO_DEVICE     *UsbIoDev,
 | |
|   IN UINTN             ConfigurationValue
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Set the device to a configuration value.
 | |
|     
 | |
|   Arguments:
 | |
|     UsbIoDev            -   USB_IO_DEVICE to be set configuration
 | |
|     ConfigrationValue   -   The configuration value to be set to that device
 | |
|     
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   LIST_ENTRY              *NextEntry;
 | |
|   CONFIG_DESC_LIST_ENTRY  *ConfigEntry;
 | |
|   UINT32                  Status;
 | |
|   EFI_STATUS              Result;
 | |
|   EFI_USB_IO_PROTOCOL     *UsbIo;
 | |
| 
 | |
|   UsbIo     = &(UsbIoDev->UsbController[0]->UsbIo);
 | |
|   NextEntry = UsbIoDev->ConfigDescListHead.ForwardLink;
 | |
| 
 | |
|   while (NextEntry != &UsbIoDev->ConfigDescListHead) {
 | |
|     //
 | |
|     // Get one entry
 | |
|     //
 | |
|     ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry;
 | |
|     if (ConfigEntry->CongfigDescriptor.ConfigurationValue == ConfigurationValue) {
 | |
|       //
 | |
|       // Find one, set to the active configuration
 | |
|       //
 | |
|       UsbIoDev->ActiveConfig = ConfigEntry;
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     NextEntry = NextEntry->ForwardLink;
 | |
|   }
 | |
|   //
 | |
|   // Next Entry should not be null
 | |
|   //
 | |
|   Result = UsbSetDeviceConfiguration (
 | |
|             UsbIo,
 | |
|             (UINT16) ConfigurationValue,
 | |
|             &Status
 | |
|             );
 | |
| 
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| UsbSetDefaultConfiguration (
 | |
|   IN  USB_IO_DEVICE      *UsbIoDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Set the device to a default configuration value.
 | |
|     
 | |
|   Arguments:
 | |
|     UsbIoDev       -    USB_IO_DEVICE to be set configuration
 | |
|     
 | |
|   Returns
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   CONFIG_DESC_LIST_ENTRY  *ConfigEntry;
 | |
|   UINT16                  ConfigValue;
 | |
|   LIST_ENTRY              *NextEntry;
 | |
| 
 | |
|   if (IsListEmpty (&UsbIoDev->ConfigDescListHead)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   NextEntry   = UsbIoDev->ConfigDescListHead.ForwardLink;
 | |
| 
 | |
|   ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry;
 | |
|   ConfigValue = ConfigEntry->CongfigDescriptor.ConfigurationValue;
 | |
| 
 | |
|   return UsbSetConfiguration (UsbIoDev, ConfigValue);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| UsbDestroyAllConfiguration (
 | |
|   IN  USB_IO_DEVICE      *UsbIoDevice
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Delete all configuration data when device is not used.
 | |
|     
 | |
|   Arguments:
 | |
|     UsbIoDevice  - USB_IO_DEVICE to be set configuration
 | |
|   
 | |
|   Returns:
 | |
|     N/A
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   CONFIG_DESC_LIST_ENTRY    *ConfigEntry;
 | |
|   INTERFACE_DESC_LIST_ENTRY *InterfaceEntry;
 | |
|   ENDPOINT_DESC_LIST_ENTRY  *EndpointEntry;
 | |
|   LIST_ENTRY                *NextEntry;
 | |
| 
 | |
|   //
 | |
|   // Delete all configuration descriptor data
 | |
|   //
 | |
|   ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) UsbIoDevice->ConfigDescListHead.ForwardLink;
 | |
| 
 | |
|   while (ConfigEntry != (CONFIG_DESC_LIST_ENTRY *) &UsbIoDevice->ConfigDescListHead) {
 | |
|     //
 | |
|     // Delete all its interface descriptors
 | |
|     //
 | |
|     InterfaceEntry = (INTERFACE_DESC_LIST_ENTRY *) ConfigEntry->InterfaceDescListHead.ForwardLink;
 | |
| 
 | |
|     while (InterfaceEntry != (INTERFACE_DESC_LIST_ENTRY *) &ConfigEntry->InterfaceDescListHead) {
 | |
|       //
 | |
|       // Delete all its endpoint descriptors
 | |
|       //
 | |
|       EndpointEntry = (ENDPOINT_DESC_LIST_ENTRY *) InterfaceEntry->EndpointDescListHead.ForwardLink;
 | |
|       while (EndpointEntry != (ENDPOINT_DESC_LIST_ENTRY *) &InterfaceEntry->EndpointDescListHead) {
 | |
|         NextEntry = ((LIST_ENTRY *) EndpointEntry)->ForwardLink;
 | |
|         RemoveEntryList ((LIST_ENTRY *) EndpointEntry);
 | |
|         gBS->FreePool (EndpointEntry);
 | |
|         EndpointEntry = (ENDPOINT_DESC_LIST_ENTRY *) NextEntry;
 | |
|       }
 | |
| 
 | |
|       NextEntry = ((LIST_ENTRY *) InterfaceEntry)->ForwardLink;
 | |
|       RemoveEntryList ((LIST_ENTRY *) InterfaceEntry);
 | |
|       gBS->FreePool (InterfaceEntry);
 | |
|       InterfaceEntry = (INTERFACE_DESC_LIST_ENTRY *) NextEntry;
 | |
|     }
 | |
| 
 | |
|     NextEntry = ((LIST_ENTRY *) ConfigEntry)->ForwardLink;
 | |
|     RemoveEntryList ((LIST_ENTRY *) ConfigEntry);
 | |
|     gBS->FreePool (ConfigEntry);
 | |
|     ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry;
 | |
|   }
 | |
| }
 |