git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 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;
 | 
						|
  }
 | 
						|
}
 |