⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


  Module Name:

    Usb.c

  Abstract:

    Parse usb device configurations.

  Revision History

--*/

#include "Efi.h"
#include "EfiDriverLib.h"

//
// Driver Consumed Protocol Prototypes
//
#include EFI_PROTOCOL_DEFINITION(UsbIo)

#include "usb.h"
#include EFI_PROTOCOL_DEFINITION(UsbHostController)
#include "usbbus.h"
#include "usblib.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.
    
  Parameters:
    Dev     -     UsbIoController device structure.
    
  Return Value:
    TRUE/FALSE
    
--*/
{
  EFI_USB_INTERFACE_DESCRIPTOR    Interface;
  EFI_USB_IO_PROTOCOL             *UsbIo;
  EFI_USB_ENDPOINT_DESCRIPTOR     EndpointDescriptor;
  UINT8                           i;
  
  if (Dev == NULL) {
    return FALSE;
  }

  UsbIo = &Dev->UsbIo;

  UsbIo->UsbGetInterfaceDescriptor(
           UsbIo,
           &Interface
         );

  //
  // Check classcode
  //
  if(Interface.InterfaceClass != 0x09) {
    return FALSE;
  }

  //
  // Check sub-class code
  //
  if(Interface.InterfaceSubClass != 0) {
    return FALSE;
  }

  //
  // Check protocol
  //
  if(Interface.InterfaceProtocol != 0x0) {
    return FALSE;
  }

  for (i = 0; i < Interface.NumEndpoints; i++) {
    UsbIo->UsbGetEndpointDescriptor(
             UsbIo,
             i,
             &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.
    
  Parameters:
    Dev     -     UsbIoController device structure.
    
  Return Value:
    EFI_SUCCESS
    EFI_UNSUPPORTED
    EFI_OUT_OF_RESOURCES
    
--*/
{
  EFI_STATUS                  Result;
  UINT32                      Status;
  EFI_USB_SUPPORTED_LANGUAGES *LanguageTable;
  UINT8                       *Buffer, *ptr;
  UINTN                       i, 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;
  }

  Result = gBS->AllocatePool (
                  EfiBootServicesData,
                  LanguageTable->Length,
                  &Buffer
                );

  if (EFI_ERROR (Result)) {
    return EFI_OUT_OF_RESOURCES;
  }
  
  EfiZeroMem(Buffer, LanguageTable->Length);

  //
  // 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(i = 0; i < LangTableSize && i< USB_MAXLANID; i++) {
    Dev->LangID[i] = *((UINT16*)ptr);
    ptr += 2;
  }

  gBS->FreePool(Buffer);
  LanguageTable = NULL;

  return EFI_SUCCESS;
}


EFI_STATUS
UsbGetAllConfigurations (
  IN  USB_IO_DEVICE *UsbDev
  )
/*++

  Routine Description:
    This function is to parse all the configuration descriptor.
    
  Parameters:
    Dev     -     USB_IO_DEVICE device structure.
    
  Return Values:
    EFI_SUCCESS
    EFI_DEVICE_ERROR
    EFI_OUT_OF_RESOURCES  

--*/
{
  EFI_STATUS               Result;
  UINT32                   Status;
  UINTN                    i;
  UINTN                    TotalLength;
  UINT8                    *Buffer;
  CONFIG_DESC_LIST_ENTRY   *ConfigDescEntry;
  EFI_USB_IO_PROTOCOL      *UsbIo;

  UsbIo = &(UsbDev->UsbController[0]->UsbIo);

  for(i = 0; i < UsbDev->DeviceDescriptor.NumConfigurations; i++) {
    ConfigDescEntry = NULL;

    Result = gBS->AllocatePool(
                    EfiBootServicesData,
                    sizeof(CONFIG_DESC_LIST_ENTRY),
                    &ConfigDescEntry
                  );

    if (EFI_ERROR (Result)) {
      return EFI_OUT_OF_RESOURCES;
    }

    EfiZeroMem(ConfigDescEntry, sizeof(CONFIG_DESC_LIST_ENTRY));

    //
    // 1st only get 1st 4 bytes config descriptor,
    // so we can know the whole length
    //
    Result = UsbGetDescriptor(
                    UsbIo,
                    0x0200,
                    (UINT8)i,
                    4,
                    &ConfigDescEntry->CongfigDescriptor,
                    &Status
             );
    if (EFI_ERROR (Result)) {
      DEBUG ((EFI_D_ERROR, "Get 1st config descriptor error\n"));
      gBS->FreePool(ConfigDescEntry);
      return EFI_DEVICE_ERROR;
    }

    TotalLength = (ConfigDescEntry->CongfigDescriptor).TotalLength;

    Buffer = NULL;
    Result = gBS->AllocatePool(
                    EfiBootServicesData,
                    TotalLength,
                    &Buffer
                  );

    if (EFI_ERROR (Result)) {
      gBS->FreePool(ConfigDescEntry);
      return EFI_OUT_OF_RESOURCES;
    }

    EfiZeroMem(Buffer, TotalLength);

    //
    // Then we get the total descriptors for this configuration
    //
    Result = UsbGetDescriptor(
                UsbIo,
                0x0200,
                (UINT16)i,
                (UINT16)TotalLength,
                Buffer,
                &Status
             );
    if (EFI_ERROR (Result)) {
      DEBUG((EFI_D_ERROR, "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(&UsbDev->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.
    
  Parameters:
  
  Return Value:
    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;
      }
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -