mirror of https://github.com/acidanthera/audk.git
1177 lines
32 KiB
C
1177 lines
32 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:
|
||
|
|
||
|
UsbIo.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
USB I/O Abstraction Driver
|
||
|
|
||
|
Revision History
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "usbbus.h"
|
||
|
|
||
|
//
|
||
|
// USB I/O Support Function Prototypes
|
||
|
//
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbControlTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN EFI_USB_DEVICE_REQUEST *Request,
|
||
|
IN EFI_USB_DATA_DIRECTION Direction,
|
||
|
IN UINT32 Timeout,
|
||
|
IN OUT VOID *Data, OPTIONAL
|
||
|
IN UINTN DataLength, OPTIONAL
|
||
|
OUT UINT32 *Status
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbBulkTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN OUT VOID *Data,
|
||
|
IN OUT UINTN *DataLength,
|
||
|
IN UINTN Timeout,
|
||
|
OUT UINT32 *Status
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbAsyncInterruptTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL * This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN BOOLEAN IsNewTransfer,
|
||
|
IN UINTN PollingInterval, OPTIONAL
|
||
|
IN UINTN DataLength, OPTIONAL
|
||
|
IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack, OPTIONAL
|
||
|
IN VOID *Context OPTIONAL
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbSyncInterruptTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN OUT VOID *Data,
|
||
|
IN OUT UINTN *DataLength,
|
||
|
IN UINTN Timeout,
|
||
|
OUT UINT32 *Status
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbIsochronousTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN OUT VOID *Data,
|
||
|
IN UINTN DataLength,
|
||
|
OUT UINT32 *Status
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbAsyncIsochronousTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL * This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN OUT VOID *Data,
|
||
|
IN UINTN DataLength,
|
||
|
IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
|
||
|
IN VOID *Context OPTIONAL
|
||
|
);
|
||
|
|
||
|
extern
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbPortReset (
|
||
|
IN EFI_USB_IO_PROTOCOL *This
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetDeviceDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
OUT EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetActiveConfigDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
OUT EFI_USB_CONFIG_DESCRIPTOR *ConfigurationDescriptor
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetInterfaceDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetEndpointDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 EndpointIndex,
|
||
|
OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetStringDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT16 LangID,
|
||
|
IN UINT8 StringIndex,
|
||
|
OUT CHAR16 **String
|
||
|
);
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetSupportedLanguages (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
OUT UINT16 **LangIDTable,
|
||
|
OUT UINT16 *TableSize
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// USB I/O Interface structure
|
||
|
//
|
||
|
STATIC EFI_USB_IO_PROTOCOL UsbIoInterface = {
|
||
|
UsbControlTransfer,
|
||
|
UsbBulkTransfer,
|
||
|
UsbAsyncInterruptTransfer,
|
||
|
UsbSyncInterruptTransfer,
|
||
|
UsbIsochronousTransfer,
|
||
|
UsbAsyncIsochronousTransfer,
|
||
|
UsbGetDeviceDescriptor,
|
||
|
UsbGetActiveConfigDescriptor,
|
||
|
UsbGetInterfaceDescriptor,
|
||
|
UsbGetEndpointDescriptor,
|
||
|
UsbGetStringDescriptor,
|
||
|
UsbGetSupportedLanguages,
|
||
|
UsbPortReset
|
||
|
};
|
||
|
|
||
|
VOID
|
||
|
InitializeUsbIoInstance (
|
||
|
IN USB_IO_CONTROLLER_DEVICE *UsbIoController
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// Copy EFI_USB_IO protocol instance
|
||
|
//
|
||
|
CopyMem (
|
||
|
&UsbIoController->UsbIo,
|
||
|
&UsbIoInterface,
|
||
|
sizeof (EFI_USB_IO_PROTOCOL)
|
||
|
);
|
||
|
}
|
||
|
//
|
||
|
// Implementation
|
||
|
//
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbControlTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN EFI_USB_DEVICE_REQUEST *Request,
|
||
|
IN EFI_USB_DATA_DIRECTION Direction,
|
||
|
IN UINT32 Timeout,
|
||
|
IN OUT VOID *Data, OPTIONAL
|
||
|
IN UINTN DataLength, OPTIONAL
|
||
|
OUT UINT32 *Status
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
This function is used to manage a USB device with a control transfer pipe.
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates calling context.
|
||
|
Request - A pointer to the USB device request that will be sent to
|
||
|
the USB device.
|
||
|
Direction - Indicates the data direction.
|
||
|
Data - A pointer to the buffer of data that will be transmitted
|
||
|
to USB device or received from USB device.
|
||
|
Timeout - Indicates the transfer should be completed within this time
|
||
|
frame.
|
||
|
DataLength - The size, in bytes, of the data buffer specified by Data.
|
||
|
Status - A pointer to the result of the USB transfer.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_INVALID_PARAMETER
|
||
|
EFI_OUT_OF_RESOURCES
|
||
|
EFI_TIMEOUT
|
||
|
EFI_DEVICE_ERROR
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
USB_IO_CONTROLLER_DEVICE *UsbIoController;
|
||
|
EFI_USB_HC_PROTOCOL *UsbHCInterface;
|
||
|
EFI_STATUS RetStatus;
|
||
|
USB_IO_DEVICE *UsbIoDevice;
|
||
|
UINT8 MaxPacketLength;
|
||
|
UINT32 TransferResult;
|
||
|
BOOLEAN Disconnected;
|
||
|
//
|
||
|
// Parameters Checking
|
||
|
//
|
||
|
if (Status == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// leave the HostController's ControlTransfer
|
||
|
// to perform other parameters checking
|
||
|
//
|
||
|
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
|
||
|
UsbIoDevice = UsbIoController->UsbDevice;
|
||
|
UsbHCInterface = UsbIoDevice->BusController->UsbHCInterface;
|
||
|
MaxPacketLength = UsbIoDevice->DeviceDescriptor.MaxPacketSize0;
|
||
|
|
||
|
|
||
|
if (Request->Request == USB_DEV_CLEAR_FEATURE &&
|
||
|
Request->RequestType == 0x02 &&
|
||
|
Request->Value == EfiUsbEndpointHalt) {
|
||
|
//
|
||
|
//Reduce the remove delay time for system response
|
||
|
//
|
||
|
IsDeviceDisconnected (UsbIoController, &Disconnected);
|
||
|
if (!EFI_ERROR (Status) && Disconnected == TRUE) {
|
||
|
DEBUG ((gUSBErrorLevel, "Device is disconnected when trying reset\n"));
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// using HostController's ControlTransfer to complete the request
|
||
|
//
|
||
|
RetStatus = UsbHCInterface->ControlTransfer (
|
||
|
UsbHCInterface,
|
||
|
UsbIoDevice->DeviceAddress,
|
||
|
UsbIoDevice->IsSlowDevice,
|
||
|
MaxPacketLength,
|
||
|
Request,
|
||
|
Direction,
|
||
|
Data,
|
||
|
&DataLength,
|
||
|
(UINTN) Timeout,
|
||
|
&TransferResult
|
||
|
);
|
||
|
*Status = TransferResult;
|
||
|
|
||
|
if (Request->Request == USB_DEV_CLEAR_FEATURE &&
|
||
|
Request->RequestType == 0x02 &&
|
||
|
Request->Value == EfiUsbEndpointHalt) {
|
||
|
//
|
||
|
// This is a UsbClearEndpointHalt request
|
||
|
// Need to clear data toggle
|
||
|
// Request.Index == EndpointAddress
|
||
|
//
|
||
|
if (!EFI_ERROR (RetStatus) && TransferResult == EFI_USB_NOERROR) {
|
||
|
SetDataToggleBit (
|
||
|
This,
|
||
|
(UINT8) Request->Index,
|
||
|
0
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
return RetStatus;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbBulkTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN OUT VOID *Data,
|
||
|
IN OUT UINTN *DataLength,
|
||
|
IN UINTN Timeout,
|
||
|
OUT UINT32 *Status
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
This function is used to manage a USB device with the bulk transfer pipe.
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates calling context.
|
||
|
DeviceEndpoint - The destination USB device endpoint to which the device
|
||
|
request is being sent.
|
||
|
Data - A pointer to the buffer of data that will be transmitted
|
||
|
to USB device or received from USB device.
|
||
|
DataLength - On input, the size, in bytes, of the data buffer
|
||
|
specified by Data. On output, the number of bytes that
|
||
|
were actually transferred.
|
||
|
Timeout - Indicates the transfer should be completed within this
|
||
|
time frame.
|
||
|
Status - This parameter indicates the USB transfer status.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_INVALID_PARAMETER
|
||
|
EFI_OUT_OF_RESOURCES
|
||
|
EFI_TIMEOUT
|
||
|
EFI_DEVICE_ERROR
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
USB_IO_DEVICE *UsbIoDev;
|
||
|
UINT8 MaxPacketLength;
|
||
|
UINT8 DataToggle;
|
||
|
UINT8 OldToggle;
|
||
|
EFI_STATUS RetStatus;
|
||
|
EFI_USB_HC_PROTOCOL *UsbHCInterface;
|
||
|
USB_IO_CONTROLLER_DEVICE *UsbIoController;
|
||
|
ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry;
|
||
|
UINT32 TransferResult;
|
||
|
|
||
|
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
|
||
|
UsbIoDev = UsbIoController->UsbDevice;
|
||
|
UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
|
||
|
|
||
|
//
|
||
|
// Parameters Checking
|
||
|
//
|
||
|
if ((DeviceEndpoint & 0x7F) == 0) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if ((DeviceEndpoint & 0x7F) > 15) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if (Status == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
EndPointListEntry = FindEndPointListEntry (
|
||
|
This,
|
||
|
DeviceEndpoint
|
||
|
);
|
||
|
|
||
|
if (EndPointListEntry == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if ((EndPointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x02) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// leave the HostController's BulkTransfer
|
||
|
// to perform other parameters checking
|
||
|
//
|
||
|
GetDeviceEndPointMaxPacketLength (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
&MaxPacketLength
|
||
|
);
|
||
|
|
||
|
GetDataToggleBit (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
&DataToggle
|
||
|
);
|
||
|
|
||
|
OldToggle = DataToggle;
|
||
|
|
||
|
//
|
||
|
// using HostController's BulkTransfer to complete the request
|
||
|
//
|
||
|
RetStatus = UsbHCInterface->BulkTransfer (
|
||
|
UsbHCInterface,
|
||
|
UsbIoDev->DeviceAddress,
|
||
|
DeviceEndpoint,
|
||
|
MaxPacketLength,
|
||
|
Data,
|
||
|
DataLength,
|
||
|
&DataToggle,
|
||
|
Timeout,
|
||
|
&TransferResult
|
||
|
);
|
||
|
|
||
|
if (OldToggle != DataToggle) {
|
||
|
//
|
||
|
// Write the toggle back
|
||
|
//
|
||
|
SetDataToggleBit (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
DataToggle
|
||
|
);
|
||
|
}
|
||
|
|
||
|
*Status = TransferResult;
|
||
|
|
||
|
return RetStatus;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbSyncInterruptTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN OUT VOID *Data,
|
||
|
IN OUT UINTN *DataLength,
|
||
|
IN UINTN Timeout,
|
||
|
OUT UINT32 *Status
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Usb Sync Interrupt Transfer
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates calling context.
|
||
|
DeviceEndpoint - The destination USB device endpoint to which the device
|
||
|
request is being sent.
|
||
|
Data - A pointer to the buffer of data that will be transmitted
|
||
|
to USB device or received from USB device.
|
||
|
DataLength - On input, the size, in bytes, of the data buffer
|
||
|
specified by Data. On output, the number of bytes that
|
||
|
were actually transferred.
|
||
|
Timeout - Indicates the transfer should be completed within this
|
||
|
time frame.
|
||
|
Status - This parameter indicates the USB transfer status.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_INVALID_PARAMETER
|
||
|
EFI_OUT_OF_RESOURCES
|
||
|
EFI_TIMEOUT
|
||
|
EFI_DEVICE_ERROR
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
USB_IO_DEVICE *UsbIoDev;
|
||
|
UINT8 MaxPacketLength;
|
||
|
UINT8 DataToggle;
|
||
|
UINT8 OldToggle;
|
||
|
EFI_STATUS RetStatus;
|
||
|
EFI_USB_HC_PROTOCOL *UsbHCInterface;
|
||
|
USB_IO_CONTROLLER_DEVICE *UsbIoController;
|
||
|
ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry;
|
||
|
|
||
|
//
|
||
|
// Parameters Checking
|
||
|
//
|
||
|
if ((DeviceEndpoint & 0x7F) == 0) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if ((DeviceEndpoint & 0x7F) > 15) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if (Status == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
EndPointListEntry = FindEndPointListEntry (
|
||
|
This,
|
||
|
DeviceEndpoint
|
||
|
);
|
||
|
|
||
|
if (EndPointListEntry == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if ((EndPointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x03) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// leave the HostController's SyncInterruptTransfer
|
||
|
// to perform other parameters checking
|
||
|
//
|
||
|
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
|
||
|
UsbIoDev = UsbIoController->UsbDevice;
|
||
|
UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
|
||
|
|
||
|
GetDeviceEndPointMaxPacketLength (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
&MaxPacketLength
|
||
|
);
|
||
|
|
||
|
GetDataToggleBit (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
&DataToggle
|
||
|
);
|
||
|
|
||
|
OldToggle = DataToggle;
|
||
|
//
|
||
|
// using HostController's SyncInterruptTransfer to complete the request
|
||
|
//
|
||
|
RetStatus = UsbHCInterface->SyncInterruptTransfer (
|
||
|
UsbHCInterface,
|
||
|
UsbIoDev->DeviceAddress,
|
||
|
DeviceEndpoint,
|
||
|
UsbIoDev->IsSlowDevice,
|
||
|
MaxPacketLength,
|
||
|
Data,
|
||
|
DataLength,
|
||
|
&DataToggle,
|
||
|
Timeout,
|
||
|
Status
|
||
|
);
|
||
|
|
||
|
if (OldToggle != DataToggle) {
|
||
|
//
|
||
|
// Write the toggle back
|
||
|
//
|
||
|
SetDataToggleBit (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
DataToggle
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return RetStatus;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbAsyncInterruptTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN BOOLEAN IsNewTransfer,
|
||
|
IN UINTN PollingInterval, OPTIONAL
|
||
|
IN UINTN DataLength, OPTIONAL
|
||
|
IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack, OPTIONAL
|
||
|
IN VOID *Context OPTIONAL
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Usb Async Interrput Transfer
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates calling context.
|
||
|
DeviceEndpoint - The destination USB device endpoint to which the
|
||
|
device request is being sent.
|
||
|
IsNewTransfer - If TRUE, a new transfer will be submitted to USB
|
||
|
controller. If FALSE, the interrupt transfer is
|
||
|
deleted from the device's interrupt transfer queue.
|
||
|
PollingInterval - Indicates the periodic rate, in milliseconds, that
|
||
|
the transfer is to be executed.
|
||
|
DataLength - Specifies the length, in bytes, of the data to be
|
||
|
received from the USB device.
|
||
|
InterruptCallback - The Callback function. This function is called if
|
||
|
the asynchronous interrupt transfer is completed.
|
||
|
Context - Passed to InterruptCallback
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_INVALID_PARAMETER
|
||
|
EFI_OUT_OF_RESOURCES
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
USB_IO_DEVICE *UsbIoDev;
|
||
|
UINT8 MaxPacketLength;
|
||
|
UINT8 DataToggle;
|
||
|
EFI_USB_HC_PROTOCOL *UsbHCInterface;
|
||
|
EFI_STATUS RetStatus;
|
||
|
USB_IO_CONTROLLER_DEVICE *UsbIoController;
|
||
|
ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
|
||
|
|
||
|
//
|
||
|
// Check endpoint
|
||
|
//
|
||
|
if ((DeviceEndpoint & 0x7F) == 0) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if ((DeviceEndpoint & 0x7F) > 15) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
EndpointListEntry = FindEndPointListEntry (
|
||
|
This,
|
||
|
DeviceEndpoint
|
||
|
);
|
||
|
|
||
|
if (EndpointListEntry == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if ((EndpointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x03) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
|
||
|
UsbIoDev = UsbIoController->UsbDevice;
|
||
|
UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
|
||
|
|
||
|
if (!IsNewTransfer) {
|
||
|
//
|
||
|
// Delete this transfer
|
||
|
//
|
||
|
UsbHCInterface->AsyncInterruptTransfer (
|
||
|
UsbHCInterface,
|
||
|
UsbIoDev->DeviceAddress,
|
||
|
DeviceEndpoint,
|
||
|
UsbIoDev->IsSlowDevice,
|
||
|
0,
|
||
|
FALSE,
|
||
|
&DataToggle,
|
||
|
PollingInterval,
|
||
|
DataLength,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// We need to store the toggle value
|
||
|
//
|
||
|
SetDataToggleBit (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
DataToggle
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
GetDeviceEndPointMaxPacketLength (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
&MaxPacketLength
|
||
|
);
|
||
|
|
||
|
GetDataToggleBit (
|
||
|
This,
|
||
|
DeviceEndpoint,
|
||
|
&DataToggle
|
||
|
);
|
||
|
|
||
|
RetStatus = UsbHCInterface->AsyncInterruptTransfer (
|
||
|
UsbHCInterface,
|
||
|
UsbIoDev->DeviceAddress,
|
||
|
DeviceEndpoint,
|
||
|
UsbIoDev->IsSlowDevice,
|
||
|
MaxPacketLength,
|
||
|
TRUE,
|
||
|
&DataToggle,
|
||
|
PollingInterval,
|
||
|
DataLength,
|
||
|
InterruptCallBack,
|
||
|
Context
|
||
|
);
|
||
|
|
||
|
return RetStatus;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbIsochronousTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN OUT VOID *Data,
|
||
|
IN UINTN DataLength,
|
||
|
OUT UINT32 *Status
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Usb Isochronous Transfer
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates calling context.
|
||
|
DeviceEndpoint - The destination USB device endpoint to which the
|
||
|
device request is being sent.
|
||
|
Data - A pointer to the buffer of data that will be
|
||
|
transmitted to USB device or received from USB device.
|
||
|
DataLength - The size, in bytes, of the data buffer specified by
|
||
|
Data.
|
||
|
Status - This parameter indicates the USB transfer status.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_INVALID_PARAMETER
|
||
|
EFI_OUT_OF_RESOURCES
|
||
|
EFI_TIMEOUT
|
||
|
EFI_DEVICE_ERROR
|
||
|
EFI_UNSUPPORTED
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// Currently we don't support this transfer
|
||
|
//
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbAsyncIsochronousTransfer (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 DeviceEndpoint,
|
||
|
IN OUT VOID *Data,
|
||
|
IN UINTN DataLength,
|
||
|
IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
|
||
|
IN VOID *Context OPTIONAL
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Usb Async Isochronous Transfer
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
This - EFI_USB_IO_PROTOCOL
|
||
|
DeviceEndpoint - DeviceEndpoint number
|
||
|
Data - Data to transfer
|
||
|
DataLength - DataLength
|
||
|
IsochronousCallBack - Isochronous CallBack function
|
||
|
Context - Passed to IsochronousCallBack function
|
||
|
Returns:
|
||
|
|
||
|
EFI_UNSUPPORTED - Unsupported now
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// Currently we don't support this transfer
|
||
|
//
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
//
|
||
|
// Here is new definitions
|
||
|
//
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetDeviceDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
OUT EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Retrieves the USB Device Descriptor.
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates the calling context.
|
||
|
DeviceDescriptor - A pointer to the caller allocated USB Device
|
||
|
Descriptor.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_INVALID_PARAMETER
|
||
|
EFI_NOT_FOUND
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
USB_IO_CONTROLLER_DEVICE *UsbIoController;
|
||
|
USB_IO_DEVICE *UsbIoDev;
|
||
|
|
||
|
//
|
||
|
// This function just wrapps UsbGetDeviceDescriptor.
|
||
|
//
|
||
|
|
||
|
if (DeviceDescriptor == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
|
||
|
UsbIoDev = UsbIoController->UsbDevice;
|
||
|
|
||
|
if (!UsbIoDev->IsConfigured) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
CopyMem (
|
||
|
DeviceDescriptor,
|
||
|
&UsbIoDev->DeviceDescriptor,
|
||
|
sizeof (EFI_USB_DEVICE_DESCRIPTOR)
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetActiveConfigDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
OUT EFI_USB_CONFIG_DESCRIPTOR *ConfigurationDescriptor
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Retrieves the current USB configuration Descriptor.
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates the calling context.
|
||
|
ConfigurationDescriptor - A pointer to the caller allocated USB active
|
||
|
Configuration Descriptor.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_INVALID_PARAMETER
|
||
|
EFI_NOT_FOUND
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
USB_IO_DEVICE *UsbIoDev;
|
||
|
USB_IO_CONTROLLER_DEVICE *UsbIoController;
|
||
|
|
||
|
//
|
||
|
// This function just wrapps UsbGetActiveConfigDescriptor.
|
||
|
//
|
||
|
if (ConfigurationDescriptor == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
|
||
|
UsbIoDev = UsbIoController->UsbDevice;
|
||
|
|
||
|
if (!UsbIoDev->IsConfigured) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
CopyMem (
|
||
|
ConfigurationDescriptor,
|
||
|
&(UsbIoDev->ActiveConfig->CongfigDescriptor),
|
||
|
sizeof (EFI_USB_CONFIG_DESCRIPTOR)
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetInterfaceDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Retrieves the interface Descriptor for that controller.
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates the calling context.
|
||
|
InterfaceDescriptor - A pointer to the caller allocated USB interface
|
||
|
Descriptor.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_INVALID_PARAMETER
|
||
|
EFI_NOT_FOUND
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
|
||
|
|
||
|
if (InterfaceDescriptor == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
InterfaceListEntry = FindInterfaceListEntry (This);
|
||
|
|
||
|
if (InterfaceListEntry == NULL) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
CopyMem (
|
||
|
InterfaceDescriptor,
|
||
|
&(InterfaceListEntry->InterfaceDescriptor),
|
||
|
sizeof (EFI_USB_INTERFACE_DESCRIPTOR)
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetEndpointDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT8 EndpointIndex,
|
||
|
OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Retrieves the endpoint Descriptor for a given endpoint.
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates the calling context.
|
||
|
EndpointIndex - Indicates which endpoint descriptor to retrieve.
|
||
|
The valid range is 0..15.
|
||
|
EndpointDescriptor - A pointer to the caller allocated USB Endpoint
|
||
|
Descriptor of a USB controller.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS - The endpoint descriptor was retrieved successfully.
|
||
|
EFI_INVALID_PARAMETER - EndpointIndex is not valid.
|
||
|
- EndpointDescriptor is NULL.
|
||
|
EFI_NOT_FOUND - The endpoint descriptor cannot be found.
|
||
|
The device may not be correctly configured.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
|
||
|
LIST_ENTRY *EndpointListHead;
|
||
|
ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
|
||
|
|
||
|
if (EndpointDescriptor == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if (EndpointIndex > 15) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
InterfaceListEntry = FindInterfaceListEntry (This);
|
||
|
|
||
|
if (InterfaceListEntry == NULL) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
EndpointListHead = (LIST_ENTRY *) (&InterfaceListEntry->EndpointDescListHead);
|
||
|
EndpointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointListHead->ForwardLink);
|
||
|
|
||
|
if (EndpointIndex >= InterfaceListEntry->InterfaceDescriptor.NumEndpoints) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
//
|
||
|
// Loop all endpoint descriptor to get match one.
|
||
|
//
|
||
|
while (EndpointIndex != 0) {
|
||
|
EndpointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointListEntry->Link.ForwardLink);
|
||
|
EndpointIndex--;
|
||
|
}
|
||
|
|
||
|
CopyMem (
|
||
|
EndpointDescriptor,
|
||
|
&EndpointListEntry->EndpointDescriptor,
|
||
|
sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetSupportedLanguages (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
OUT UINT16 **LangIDTable,
|
||
|
OUT UINT16 *TableSize
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Get all the languages that the USB device supports
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates the calling context.
|
||
|
LangIDTable - Language ID for the string the caller wants to get.
|
||
|
TableSize - The size, in bytes, of the table LangIDTable.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_NOT_FOUND
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
USB_IO_DEVICE *UsbIoDev;
|
||
|
USB_IO_CONTROLLER_DEVICE *UsbIoController;
|
||
|
UINTN Index;
|
||
|
BOOLEAN Found;
|
||
|
|
||
|
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
|
||
|
UsbIoDev = UsbIoController->UsbDevice;
|
||
|
|
||
|
Found = FALSE;
|
||
|
Index = 0;
|
||
|
//
|
||
|
// Loop language table
|
||
|
//
|
||
|
while (UsbIoDev->LangID[Index]) {
|
||
|
Found = TRUE;
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
if (!Found) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
*LangIDTable = UsbIoDev->LangID;
|
||
|
*TableSize = (UINT16) Index;
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
UsbGetStringDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *This,
|
||
|
IN UINT16 LangID,
|
||
|
IN UINT8 StringIndex,
|
||
|
OUT CHAR16 **String
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Get a given string descriptor
|
||
|
|
||
|
Arguments:
|
||
|
This - Indicates the calling context.
|
||
|
LangID - The Language ID for the string being retrieved.
|
||
|
StringIndex - The ID of the string being retrieved.
|
||
|
String - A pointer to a buffer allocated by this function
|
||
|
with AllocatePool() to store the string. If this
|
||
|
function returns EFI_SUCCESS, it stores the string
|
||
|
the caller wants to get. The caller should release
|
||
|
the string buffer with FreePool() after the string
|
||
|
is not used any more.
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_NOT_FOUND
|
||
|
EFI_OUT_OF_RESOURCES
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
UINT32 Status;
|
||
|
EFI_STATUS Result;
|
||
|
EFI_USB_STRING_DESCRIPTOR *StrDescriptor;
|
||
|
UINT8 *Buffer;
|
||
|
CHAR16 *UsbString;
|
||
|
UINT16 TempBuffer;
|
||
|
USB_IO_DEVICE *UsbIoDev;
|
||
|
UINT8 Index;
|
||
|
BOOLEAN Found;
|
||
|
USB_IO_CONTROLLER_DEVICE *UsbIoController;
|
||
|
|
||
|
if (StringIndex == 0) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
//
|
||
|
// Search LanguageID, check if it is supported by this device
|
||
|
//
|
||
|
if (LangID == 0) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
|
||
|
UsbIoDev = UsbIoController->UsbDevice;
|
||
|
|
||
|
Found = FALSE;
|
||
|
Index = 0;
|
||
|
while (UsbIoDev->LangID[Index]) {
|
||
|
if (UsbIoDev->LangID[Index] == LangID) {
|
||
|
Found = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
if (!Found) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
//
|
||
|
// Get String Length
|
||
|
//
|
||
|
Result = UsbGetString (
|
||
|
This,
|
||
|
LangID,
|
||
|
StringIndex,
|
||
|
&TempBuffer,
|
||
|
2,
|
||
|
&Status
|
||
|
);
|
||
|
if (EFI_ERROR (Result)) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
StrDescriptor = (EFI_USB_STRING_DESCRIPTOR *) &TempBuffer;
|
||
|
|
||
|
if (StrDescriptor->Length == 0) {
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
Buffer = AllocateZeroPool (StrDescriptor->Length);
|
||
|
if (Buffer == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
Result = UsbGetString (
|
||
|
This,
|
||
|
LangID,
|
||
|
StringIndex,
|
||
|
Buffer,
|
||
|
StrDescriptor->Length,
|
||
|
&Status
|
||
|
);
|
||
|
|
||
|
if (EFI_ERROR (Result)) {
|
||
|
gBS->FreePool (Buffer);
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
StrDescriptor = (EFI_USB_STRING_DESCRIPTOR *) Buffer;
|
||
|
|
||
|
//
|
||
|
// UsbString is a UNICODE string
|
||
|
//
|
||
|
UsbString = AllocateZeroPool (StrDescriptor->Length);
|
||
|
if (UsbString == NULL) {
|
||
|
gBS->FreePool (Buffer);
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
CopyMem (
|
||
|
(VOID *) UsbString,
|
||
|
Buffer + 2,
|
||
|
StrDescriptor->Length - 2
|
||
|
);
|
||
|
|
||
|
*String = UsbString;
|
||
|
|
||
|
gBS->FreePool (Buffer);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|