Import Usb/UsbBusDxe and Usb/UsbMassStorageDxe into MdeModulePkg.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3193 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
991
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
Normal file
991
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
Normal file
@ -0,0 +1,991 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2007, 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:
|
||||
|
||||
UsbDesc.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Manage Usb Descriptor List
|
||||
|
||||
Revision History
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "UsbBus.h"
|
||||
|
||||
|
||||
/**
|
||||
Free the interface setting descriptor
|
||||
|
||||
@param Setting The descriptor to free
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
UsbFreeInterfaceDesc (
|
||||
IN USB_INTERFACE_SETTING *Setting
|
||||
)
|
||||
{
|
||||
USB_ENDPOINT_DESC *Ep;
|
||||
UINTN Index;
|
||||
|
||||
if (Setting->Endpoints != NULL) {
|
||||
//
|
||||
// Each interface setting may have several endpoints, free them first.
|
||||
//
|
||||
for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {
|
||||
Ep = Setting->Endpoints[Index];
|
||||
|
||||
if (Ep != NULL) {
|
||||
gBS->FreePool (Ep);
|
||||
}
|
||||
}
|
||||
|
||||
gBS->FreePool (Setting->Endpoints);
|
||||
}
|
||||
|
||||
gBS->FreePool (Setting);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Free a configuration descriptor with its interface
|
||||
descriptors. It may be initialized partially
|
||||
|
||||
@param Config The configuration descriptor to free
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
UsbFreeConfigDesc (
|
||||
IN USB_CONFIG_DESC *Config
|
||||
)
|
||||
{
|
||||
USB_INTERFACE_DESC *Interface;
|
||||
UINTN Index;
|
||||
UINTN SetIndex;
|
||||
|
||||
if (Config->Interfaces != NULL) {
|
||||
//
|
||||
// A configuration may have several interfaces, free the interface
|
||||
//
|
||||
for (Index = 0; Index < Config->Desc.NumInterfaces; Index++) {
|
||||
Interface = Config->Interfaces[Index];
|
||||
|
||||
if (Interface == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Each interface may have several settings, free the settings
|
||||
//
|
||||
for (SetIndex = 0; SetIndex < Interface->NumOfSetting; SetIndex++) {
|
||||
if (Interface->Settings[SetIndex] != NULL) {
|
||||
UsbFreeInterfaceDesc (Interface->Settings[SetIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
gBS->FreePool (Interface);
|
||||
}
|
||||
|
||||
gBS->FreePool (Config->Interfaces);
|
||||
}
|
||||
|
||||
gBS->FreePool (Config);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Free a device descriptor with its configurations
|
||||
|
||||
@param DevDesc The device descriptor
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
UsbFreeDevDesc (
|
||||
IN USB_DEVICE_DESC *DevDesc
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
if (DevDesc->Configs != NULL) {
|
||||
for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {
|
||||
if (DevDesc->Configs[Index] != NULL) {
|
||||
UsbFreeConfigDesc (DevDesc->Configs[Index]);
|
||||
}
|
||||
}
|
||||
|
||||
gBS->FreePool (DevDesc->Configs);
|
||||
}
|
||||
|
||||
gBS->FreePool (DevDesc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create a descriptor
|
||||
|
||||
@param DescBuf The buffer of raw descriptor
|
||||
@param Len The lenght of the raw descriptor buffer
|
||||
@param Type The type of descriptor to create
|
||||
@param Consumed Number of bytes consumed
|
||||
|
||||
@return Created descriptor or NULL
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID *
|
||||
UsbCreateDesc (
|
||||
IN UINT8 *DescBuf,
|
||||
IN INTN Len,
|
||||
IN UINT8 Type,
|
||||
OUT INTN *Consumed
|
||||
)
|
||||
{
|
||||
USB_DESC_HEAD *Head;
|
||||
INTN DescLen;
|
||||
INTN CtrlLen;
|
||||
INTN Offset;
|
||||
VOID *Desc;
|
||||
|
||||
DescLen = 0;
|
||||
CtrlLen = 0;
|
||||
*Consumed = 0;
|
||||
|
||||
switch (Type) {
|
||||
case USB_DESC_TYPE_DEVICE:
|
||||
DescLen = sizeof (EFI_USB_DEVICE_DESCRIPTOR);
|
||||
CtrlLen = sizeof (USB_DEVICE_DESC);
|
||||
break;
|
||||
|
||||
case USB_DESC_TYPE_CONFIG:
|
||||
DescLen = sizeof (EFI_USB_CONFIG_DESCRIPTOR);
|
||||
CtrlLen = sizeof (USB_CONFIG_DESC);
|
||||
break;
|
||||
|
||||
case USB_DESC_TYPE_INTERFACE:
|
||||
DescLen = sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
|
||||
CtrlLen = sizeof (USB_INTERFACE_SETTING);
|
||||
break;
|
||||
|
||||
case USB_DESC_TYPE_ENDPOINT:
|
||||
DescLen = sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
|
||||
CtrlLen = sizeof (USB_ENDPOINT_DESC);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// All the descriptor has a common LTV (Length, Type, Value)
|
||||
// format. Skip the descriptor that isn't of this Type
|
||||
//
|
||||
Offset = 0;
|
||||
Head = (USB_DESC_HEAD*)DescBuf;
|
||||
|
||||
while ((Offset < Len) && (Head->Type != Type)) {
|
||||
Offset += Head->Len;
|
||||
Head = (USB_DESC_HEAD*)(DescBuf + Offset);
|
||||
}
|
||||
|
||||
if ((Len <= Offset) || (Len < Offset + DescLen) ||
|
||||
(Head->Type != Type) || (Head->Len != DescLen)) {
|
||||
USB_ERROR (("UsbCreateDesc: met mal-format descriptor\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Desc = AllocateZeroPool (CtrlLen);
|
||||
|
||||
if (Desc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CopyMem (Desc, Head, DescLen);
|
||||
*Consumed = Offset + Head->Len;
|
||||
|
||||
return Desc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse an interface desciptor and its endpoints
|
||||
|
||||
@param DescBuf The buffer of raw descriptor
|
||||
@param Len The lenght of the raw descriptor buffer
|
||||
@param Consumed The number of raw descriptor consumed
|
||||
|
||||
@return The create interface setting or NULL if failed
|
||||
|
||||
**/
|
||||
STATIC
|
||||
USB_INTERFACE_SETTING *
|
||||
UsbParseInterfaceDesc (
|
||||
IN UINT8 *DescBuf,
|
||||
IN INTN Len,
|
||||
OUT INTN *Consumed
|
||||
)
|
||||
{
|
||||
USB_INTERFACE_SETTING *Setting;
|
||||
USB_ENDPOINT_DESC *Ep;
|
||||
UINTN Index;
|
||||
UINTN NumEp;
|
||||
INTN Used;
|
||||
INTN Offset;
|
||||
|
||||
*Consumed = 0;
|
||||
Setting = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_INTERFACE, &Used);
|
||||
|
||||
if (Setting == NULL) {
|
||||
USB_ERROR (("UsbParseInterfaceDesc: failed to create interface descriptor\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Offset = Used;
|
||||
|
||||
//
|
||||
// Create an arry to hold the interface's endpoints
|
||||
//
|
||||
NumEp = Setting->Desc.NumEndpoints;
|
||||
|
||||
USB_DEBUG (("UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",
|
||||
Setting->Desc.InterfaceNumber, Setting->Desc.AlternateSetting, NumEp));
|
||||
|
||||
if (NumEp == 0) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Setting->Endpoints = AllocateZeroPool (sizeof (USB_ENDPOINT_DESC *) * NumEp);
|
||||
|
||||
if (Setting->Endpoints == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the endpoints for this interface
|
||||
//
|
||||
for (Index = 0; Index < NumEp; Index++) {
|
||||
Ep = UsbCreateDesc (DescBuf + Offset, Len - Offset, USB_DESC_TYPE_ENDPOINT, &Used);
|
||||
|
||||
if (Ep == NULL) {
|
||||
USB_ERROR (("UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", Index));
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Setting->Endpoints[Index] = Ep;
|
||||
Offset += Used;
|
||||
}
|
||||
|
||||
|
||||
ON_EXIT:
|
||||
*Consumed = Offset;
|
||||
return Setting;
|
||||
|
||||
ON_ERROR:
|
||||
UsbFreeInterfaceDesc (Setting);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the configuration descriptor and its interfaces.
|
||||
|
||||
@param DescBuf The buffer of raw descriptor
|
||||
@param Len The lenght of the raw descriptor buffer
|
||||
|
||||
@return The created configuration descriptor
|
||||
|
||||
**/
|
||||
STATIC
|
||||
USB_CONFIG_DESC *
|
||||
UsbParseConfigDesc (
|
||||
IN UINT8 *DescBuf,
|
||||
IN INTN Len
|
||||
)
|
||||
{
|
||||
USB_CONFIG_DESC *Config;
|
||||
USB_INTERFACE_SETTING *Setting;
|
||||
USB_INTERFACE_DESC *Interface;
|
||||
UINTN Index;
|
||||
UINTN NumIf;
|
||||
INTN Consumed;
|
||||
|
||||
ASSERT (DescBuf != NULL);
|
||||
|
||||
Config = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_CONFIG, &Consumed);
|
||||
|
||||
if (Config == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize an array of setting for the configuration's interfaces.
|
||||
//
|
||||
NumIf = Config->Desc.NumInterfaces;
|
||||
Config->Interfaces = AllocateZeroPool (sizeof (USB_INTERFACE_DESC *) * NumIf);
|
||||
|
||||
if (Config->Interfaces == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
USB_DEBUG (("UsbParseConfigDesc: config %d has %d interfaces\n",
|
||||
Config->Desc.ConfigurationValue, NumIf));
|
||||
|
||||
for (Index = 0; Index < NumIf; Index++) {
|
||||
Interface = AllocateZeroPool (sizeof (USB_INTERFACE_DESC));
|
||||
|
||||
if (Interface == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Config->Interfaces[Index] = Interface;
|
||||
}
|
||||
|
||||
//
|
||||
// If a configuration has several interfaces, these interfaces are
|
||||
// numbered from zero to n. If a interface has several settings,
|
||||
// these settings are also number from zero to m. The interface
|
||||
// setting must be organized as |interface 0, setting 0|interface 0
|
||||
// setting 1|interface 1, setting 0|interface 2, setting 0|. Check
|
||||
// USB2.0 spec, page 267.
|
||||
//
|
||||
DescBuf += Consumed;
|
||||
Len -= Consumed;
|
||||
|
||||
while (Len > 0) {
|
||||
Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);
|
||||
|
||||
if ((Setting == NULL)) {
|
||||
USB_ERROR (("UsbParseConfigDesc: failed to parse interface setting\n"));
|
||||
goto ON_ERROR;
|
||||
|
||||
} else if (Setting->Desc.InterfaceNumber >= NumIf) {
|
||||
USB_ERROR (("UsbParseConfigDesc: mal-formated interface descriptor\n"));
|
||||
|
||||
UsbFreeInterfaceDesc (Setting);
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert the descriptor to the corresponding set.
|
||||
//
|
||||
Interface = Config->Interfaces[Setting->Desc.InterfaceNumber];
|
||||
|
||||
if (Interface->NumOfSetting >= USB_MAX_INTERFACE_SETTING) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Interface->Settings[Interface->NumOfSetting] = Setting;
|
||||
Interface->NumOfSetting++;
|
||||
|
||||
DescBuf += Consumed;
|
||||
Len -= Consumed;
|
||||
}
|
||||
|
||||
return Config;
|
||||
|
||||
ON_ERROR:
|
||||
UsbFreeConfigDesc (Config);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
USB standard control transfer support routine. This
|
||||
function is used by USB device. It is possible that
|
||||
the device's interfaces are still waiting to be
|
||||
enumerated.
|
||||
|
||||
@param UsbDev The usb device
|
||||
@param Direction The direction of data transfer
|
||||
@param Type Standard / class specific / vendor specific
|
||||
@param Target The receiving target
|
||||
@param Request Which request
|
||||
@param Value The wValue parameter of the request
|
||||
@param Index The wIndex parameter of the request
|
||||
@param Buf The buffer to receive data into / transmit from
|
||||
@param Length The length of the buffer
|
||||
|
||||
@retval EFI_SUCCESS The control request is executed
|
||||
@retval EFI_DEVICE_ERROR Failed to execute the control transfer
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UsbCtrlRequest (
|
||||
IN USB_DEVICE *UsbDev,
|
||||
IN EFI_USB_DATA_DIRECTION Direction,
|
||||
IN UINTN Type,
|
||||
IN UINTN Target,
|
||||
IN UINTN Request,
|
||||
IN UINT16 Value,
|
||||
IN UINT16 Index,
|
||||
IN OUT VOID *Buf,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
EFI_USB_DEVICE_REQUEST DevReq;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Result;
|
||||
UINTN Len;
|
||||
|
||||
ASSERT ((UsbDev != NULL) && (UsbDev->Bus != NULL));
|
||||
|
||||
DevReq.RequestType = USB_REQUEST_TYPE (Direction, Type, Target);
|
||||
DevReq.Request = (UINT8) Request;
|
||||
DevReq.Value = Value;
|
||||
DevReq.Index = Index;
|
||||
DevReq.Length = (UINT16) Length;
|
||||
|
||||
Len = Length;
|
||||
Status = UsbHcControlTransfer (
|
||||
UsbDev->Bus,
|
||||
UsbDev->Address,
|
||||
UsbDev->Speed,
|
||||
UsbDev->MaxPacket0,
|
||||
&DevReq,
|
||||
Direction,
|
||||
Buf,
|
||||
&Len,
|
||||
50 * USB_STALL_1_MS,
|
||||
&UsbDev->Translator,
|
||||
&Result
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Get the standard descriptors.
|
||||
|
||||
@param UsbDev The USB device to read descriptor from
|
||||
@param DescType The type of descriptor to read
|
||||
@param DescIndex The index of descriptor to read
|
||||
@param LangId Language ID, only used to get string, otherwise set
|
||||
it to 0
|
||||
@param Buf The buffer to hold the descriptor read
|
||||
@param Length The length of the buffer
|
||||
|
||||
@retval EFI_SUCCESS The descriptor is read OK
|
||||
@retval Others Failed to retrieve the descriptor
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UsbCtrlGetDesc (
|
||||
IN USB_DEVICE *UsbDev,
|
||||
IN UINTN DescType,
|
||||
IN UINTN DescIndex,
|
||||
IN UINT16 LangId,
|
||||
OUT VOID *Buf,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = UsbCtrlRequest (
|
||||
UsbDev,
|
||||
EfiUsbDataIn,
|
||||
USB_REQ_TYPE_STANDARD,
|
||||
USB_TARGET_DEVICE,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
(UINT16) ((DescType << 8) | DescIndex),
|
||||
LangId,
|
||||
Buf,
|
||||
Length
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Return the max packet size for endpoint zero. This function
|
||||
is the first function called to get descriptors during bus
|
||||
enumeration.
|
||||
|
||||
@param UsbDev The usb device
|
||||
|
||||
@retval EFI_SUCCESS The max packet size of endpoint zero is retrieved
|
||||
@retval EFI_DEVICE_ERROR Failed to retrieve it
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UsbGetMaxPacketSize0 (
|
||||
IN USB_DEVICE *UsbDev
|
||||
)
|
||||
{
|
||||
EFI_USB_DEVICE_DESCRIPTOR DevDesc;
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
|
||||
|
||||
//
|
||||
// Get the first 8 bytes of the device descriptor which contains
|
||||
// max packet size for endpoint 0, which is at least 8.
|
||||
//
|
||||
UsbDev->MaxPacket0 = 8;
|
||||
|
||||
for (Index = 0; Index < 3; Index++) {
|
||||
Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_DEVICE, 0, 0, &DevDesc, 8);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
UsbDev->MaxPacket0 = DevDesc.MaxPacketSize0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
gBS->Stall (100 * USB_STALL_1_MS);
|
||||
}
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Get the device descriptor for the device.
|
||||
|
||||
@param UsbDev The Usb device to retrieve descriptor from
|
||||
|
||||
@retval EFI_SUCCESS The device descriptor is returned
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UsbGetDevDesc (
|
||||
IN USB_DEVICE *UsbDev
|
||||
)
|
||||
{
|
||||
USB_DEVICE_DESC *DevDesc;
|
||||
EFI_STATUS Status;
|
||||
|
||||
DevDesc = AllocateZeroPool (sizeof (USB_DEVICE_DESC));
|
||||
|
||||
if (DevDesc == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = UsbCtrlGetDesc (
|
||||
UsbDev,
|
||||
USB_DESC_TYPE_DEVICE,
|
||||
0,
|
||||
0,
|
||||
DevDesc,
|
||||
sizeof (EFI_USB_DEVICE_DESCRIPTOR)
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->FreePool (DevDesc);
|
||||
} else {
|
||||
UsbDev->DevDesc = DevDesc;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Retrieve the indexed string for the language. It requires two
|
||||
steps to get a string, first to get the string's length. Then
|
||||
the string itself.
|
||||
|
||||
@param UsbDev The usb device
|
||||
@param Index The index the string to retrieve
|
||||
@param LangId Language ID
|
||||
|
||||
@return The created string descriptor or NULL
|
||||
|
||||
**/
|
||||
EFI_USB_STRING_DESCRIPTOR *
|
||||
UsbGetOneString (
|
||||
IN USB_DEVICE *UsbDev,
|
||||
IN UINT8 Index,
|
||||
IN UINT16 LangId
|
||||
)
|
||||
{
|
||||
EFI_USB_STRING_DESCRIPTOR Desc;
|
||||
EFI_STATUS Status;
|
||||
UINT8 *Buf;
|
||||
|
||||
//
|
||||
// First get two bytes which contains the string length.
|
||||
//
|
||||
Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Buf = AllocateZeroPool (Desc.Length);
|
||||
|
||||
if (Buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status = UsbCtrlGetDesc (
|
||||
UsbDev,
|
||||
USB_DESC_TYPE_STRING,
|
||||
Index,
|
||||
LangId,
|
||||
Buf,
|
||||
Desc.Length
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->FreePool (Buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (EFI_USB_STRING_DESCRIPTOR *) Buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Build the language ID table for string descriptors
|
||||
|
||||
@param UsbDev The Usb device
|
||||
|
||||
@retval EFI_UNSUPPORTED This device doesn't support string table
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UsbBuildLangTable (
|
||||
IN USB_DEVICE *UsbDev
|
||||
)
|
||||
{
|
||||
EFI_USB_STRING_DESCRIPTOR *Desc;
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
UINTN Max;
|
||||
UINT16 *Point;
|
||||
|
||||
//
|
||||
// The string of language ID zero returns the supported languages
|
||||
//
|
||||
Desc = UsbGetOneString (UsbDev, 0, 0);
|
||||
|
||||
if (Desc == NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (Desc->Length < 4) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
Max = (Desc->Length - 2) / 2;
|
||||
Max = (Max < USB_MAX_LANG_ID ? Max : USB_MAX_LANG_ID);
|
||||
|
||||
Point = Desc->String;
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
UsbDev->LangId[Index] = *Point;
|
||||
Point++;
|
||||
}
|
||||
|
||||
UsbDev->TotalLangId = (UINT16)Max;
|
||||
|
||||
ON_EXIT:
|
||||
gBS->FreePool (Desc);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Retrieve the indexed configure for the device. USB device
|
||||
returns the configuration togetther with the interfaces for
|
||||
this configuration. Configuration descriptor is also of
|
||||
variable length
|
||||
|
||||
@param UsbDev The Usb interface
|
||||
@param Index The index of the configuration
|
||||
|
||||
@return The created configuration descriptor
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_USB_CONFIG_DESCRIPTOR *
|
||||
UsbGetOneConfig (
|
||||
IN USB_DEVICE *UsbDev,
|
||||
IN UINT8 Index
|
||||
)
|
||||
{
|
||||
EFI_USB_CONFIG_DESCRIPTOR Desc;
|
||||
EFI_STATUS Status;
|
||||
VOID *Buf;
|
||||
|
||||
//
|
||||
// First get four bytes which contains the total length
|
||||
// for this configuration.
|
||||
//
|
||||
Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, &Desc, 8);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
USB_ERROR (("UsbGetOneConfig: failed to get descript length(%d) %r\n",
|
||||
Status, Desc.TotalLength));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
USB_DEBUG (("UsbGetOneConfig: total length is %d\n", Desc.TotalLength));
|
||||
|
||||
Buf = AllocateZeroPool (Desc.TotalLength);
|
||||
|
||||
if (Buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, Buf, Desc.TotalLength);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
USB_ERROR (("UsbGetOneConfig: failed to get full descript %r\n", Status));
|
||||
|
||||
gBS->FreePool (Buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Build the whole array of descriptors. This function must
|
||||
be called after UsbGetMaxPacketSize0 returns the max packet
|
||||
size correctly for endpoint 0.
|
||||
|
||||
@param UsbDev The Usb device
|
||||
|
||||
@retval EFI_SUCCESS The descriptor table is build
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UsbBuildDescTable (
|
||||
IN USB_DEVICE *UsbDev
|
||||
)
|
||||
{
|
||||
EFI_USB_CONFIG_DESCRIPTOR *Config;
|
||||
USB_DEVICE_DESC *DevDesc;
|
||||
USB_CONFIG_DESC *ConfigDesc;
|
||||
UINT8 NumConfig;
|
||||
EFI_STATUS Status;
|
||||
UINT8 Index;
|
||||
|
||||
//
|
||||
// Get the device descriptor, then allocate the configure
|
||||
// descriptor pointer array to hold configurations.
|
||||
//
|
||||
Status = UsbGetDevDesc (UsbDev);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
USB_ERROR (("UsbBuildDescTable: failed to get device descriptor - %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
DevDesc = UsbDev->DevDesc;
|
||||
NumConfig = DevDesc->Desc.NumConfigurations;
|
||||
DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));
|
||||
|
||||
if (DevDesc->Configs == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
USB_DEBUG (("UsbBuildDescTable: device has %d configures\n", NumConfig));
|
||||
|
||||
//
|
||||
// Read each configurations, then parse them
|
||||
//
|
||||
for (Index = 0; Index < NumConfig; Index++) {
|
||||
Config = UsbGetOneConfig (UsbDev, Index);
|
||||
|
||||
if (Config == NULL) {
|
||||
USB_ERROR (("UsbBuildDescTable: failed to get configure (index %d)\n", Index));
|
||||
|
||||
//
|
||||
// If we can get the default descriptor, it is likely that the
|
||||
// device is still operational.
|
||||
//
|
||||
if (Index == 0) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ConfigDesc = UsbParseConfigDesc ((UINT8 *) Config, Config->TotalLength);
|
||||
|
||||
gBS->FreePool (Config);
|
||||
|
||||
if (ConfigDesc == NULL) {
|
||||
USB_ERROR (("UsbBuildDescTable: failed to parse configure (index %d)\n", Index));
|
||||
|
||||
//
|
||||
// If we can get the default descriptor, it is likely that the
|
||||
// device is still operational.
|
||||
//
|
||||
if (Index == 0) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
DevDesc->Configs[Index] = ConfigDesc;
|
||||
}
|
||||
|
||||
//
|
||||
// Don't return error even this function failed because
|
||||
// it is possible for the device to not support strings.
|
||||
//
|
||||
Status = UsbBuildLangTable (UsbDev);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
USB_DEBUG (("UsbBuildDescTable: get language ID table %r\n", Status));
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the device's address.
|
||||
|
||||
@param UsbDev The device to set address to
|
||||
@param Address The address to set
|
||||
|
||||
@retval EFI_SUCCESS The device is set to the address
|
||||
@retval Others Failed to set the device address
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UsbSetAddress (
|
||||
IN USB_DEVICE *UsbDev,
|
||||
IN UINT8 Address
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = UsbCtrlRequest (
|
||||
UsbDev,
|
||||
EfiUsbNoData,
|
||||
USB_REQ_TYPE_STANDARD,
|
||||
USB_TARGET_DEVICE,
|
||||
USB_REQ_SET_ADDRESS,
|
||||
Address,
|
||||
0,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the device's configuration. This function changes
|
||||
the device's internal state. UsbSelectConfig changes
|
||||
the Usb bus's internal state.
|
||||
|
||||
@param UsbDev The USB device to set configure to
|
||||
@param ConfigIndex The configure index to set
|
||||
|
||||
@retval EFI_SUCCESS The device is configured now
|
||||
@retval Others Failed to set the device configure
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UsbSetConfig (
|
||||
IN USB_DEVICE *UsbDev,
|
||||
IN UINT8 ConfigIndex
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = UsbCtrlRequest (
|
||||
UsbDev,
|
||||
EfiUsbNoData,
|
||||
USB_REQ_TYPE_STANDARD,
|
||||
USB_TARGET_DEVICE,
|
||||
USB_REQ_SET_CONFIG,
|
||||
ConfigIndex,
|
||||
0,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Usb UsbIo interface to clear the feature. This is should
|
||||
only be used by HUB which is considered a device driver
|
||||
on top of the UsbIo interface.
|
||||
|
||||
@param UsbIo The UsbIo interface
|
||||
@param Target The target of the transfer: endpoint/device
|
||||
@param Feature The feature to clear
|
||||
@param Index The wIndex parameter
|
||||
|
||||
@retval EFI_SUCCESS The device feature is cleared
|
||||
@retval Others Failed to clear the feature
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UsbIoClearFeature (
|
||||
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||||
IN UINTN Target,
|
||||
IN UINT16 Feature,
|
||||
IN UINT16 Index
|
||||
)
|
||||
{
|
||||
EFI_USB_DEVICE_REQUEST DevReq;
|
||||
UINT32 UsbResult;
|
||||
EFI_STATUS Status;
|
||||
|
||||
DevReq.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, Target);
|
||||
DevReq.Request = USB_REQ_CLEAR_FEATURE;
|
||||
DevReq.Value = Feature;
|
||||
DevReq.Index = Index;
|
||||
DevReq.Length = 0;
|
||||
|
||||
Status = UsbIo->UsbControlTransfer (
|
||||
UsbIo,
|
||||
&DevReq,
|
||||
EfiUsbNoData,
|
||||
10 * USB_STALL_1_MS,
|
||||
NULL,
|
||||
0,
|
||||
&UsbResult
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
Reference in New Issue
Block a user