alder_lake_bios/Intel/AlderLake/AlderLakePlatSamplePkg/Features/Usb/UsbDeviceDxe/UsbDeviceMode.c

1497 lines
42 KiB
C

/** @file
Implementation of USB device mode APIs.
@copyright
INTEL CONFIDENTIAL
Copyright 2015 - 2020 Intel Corporation.
The source code contained or described herein and all documents related to the
source code ("Material") are owned by Intel Corporation or its suppliers or
licensors. Title to the Material remains with Intel Corporation or its suppliers
and licensors. The Material may contain trade secrets and proprietary and
confidential information of Intel Corporation and its suppliers and licensors,
and is protected by worldwide copyright and trade secret laws and treaty
provisions. No part of the Material may be used, copied, reproduced, modified,
published, uploaded, posted, transmitted, distributed, or disclosed in any way
without Intel's prior express written permission.
No license under any patent, copyright, trade secret or other intellectual
property right is granted to or conferred upon you by disclosure or delivery
of the Materials, either expressly, by implication, inducement, estoppel or
otherwise. Any license under such intellectual property rights must be
express and approved by Intel in writing.
Unless otherwise agreed by Intel in writing, you may not remove or alter
this notice or any other notice embedded in Materials by Intel or
Intel's suppliers or licensors in any way.
This file contains a 'Sample Driver' and is licensed as such under the terms
of your license agreement with Intel or your vendor. This file may be modified
by the user, subject to the additional terms of the license agreement.
@par Specification Reference:
**/
#include <Base.h>
#include <Library/BaseLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/IoLib.h>
#include "XdciUtility.h"
#include "UsbDeviceMode.h"
#include "UsbDeviceDxe.h"
#include <Library/PchPciBdfLib.h>
//
// Module global USBD driver object. This is the main private driver object
// that contains all data needed for this driver to operate.
//
USB_DEVICE_DRIVER_OBJ mDrvObj;
//
// Module global data IO transaction request object
//
USB_DEVICE_IO_REQ mCtrlIoReq = {
//
// IO information containing the buffer and data size
//
{
NULL,
0,
},
//
// Note: This object is used for Control Ep transfers only
// therefore the endpoint info must always be NULL
//
{
NULL,
NULL,
}
};
/**
This function can be called to poll for certain value within a time given.
@param[in] MmioAddress The Mmio Address.
@param[in] BitMask Bits to be masked.
@param[in] BitValue Value to be polled.
#param[in] DelayTime Delay time in terms of 100 micro seconds.
@retval EFI_SUCCESS Successfully polled the value.
@retval EFI_TIMEOUT Timeout while polling the value.
**/
EFI_STATUS
EFIAPI
PchMmioPoll (
IN UINTN MmioAddress,
IN UINT32 BitMask,
IN UINT32 BitValue,
IN UINT16 DelayTime
)
{
UINT32 LoopTime;
UINT8 PollSuccess;
LoopTime = 0;
PollSuccess = 0;
DEBUG ((DEBUG_INFO, "PchMmioPoll32, BitMask: %x, BitValue: %x\n", BitMask, BitValue));
for (LoopTime = 0; LoopTime < DelayTime; LoopTime++) {
if ((MmioRead32 (MmioAddress) & BitMask) == (BitValue & BitMask)) {
PollSuccess = 1;
break;
} else {
gBS->Stall (100);
}
}
if (PollSuccess) {
return EFI_SUCCESS;
} else {
return EFI_TIMEOUT;
}
}
//
// global flag to signal device event processing loop to run/stop
//
BOOLEAN mXdciRun = FALSE;
STATIC VOID
XhciSwitchSwid(
BOOLEAN enable
)
{
UINT64 XhciPciMmBase;
UINTN XhciMmioBase;
UINT32 DualRoleCfg0;
UINT32 BitValue;
UINT32 BitMask;
EFI_STATUS Status;
XhciPciMmBase = PchXhciPciCfgBase ();
XhciMmioBase = PciSegmentRead32 (XhciPciMmBase + R_XHCI_CFG_BAR0) & ~(UINT32)B_XHCI_CFG_ALIGN_MASK;
XhciMmioBase |= LShiftU64 (PciSegmentRead32 (XhciPciMmBase + R_XHCI_CFG_BAR0 + 4), 32);
DEBUG ((DEBUG_INFO, "XhciPciMmBase=%x, XhciMmioBase=%x\n", XhciPciMmBase, XhciMmioBase));
DualRoleCfg0 = MmioRead32 ((UINTN)(XhciMmioBase + R_XHCI_MEM_DUAL_ROLE_CFG0));
if (enable) {
DualRoleCfg0 = DualRoleCfg0 | (1 << 24) | (1 << 21) | (1 << 20);
DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Set SW ID : 0x%x \n", DualRoleCfg0));
}
else {
DualRoleCfg0 = DualRoleCfg0 & ~(1 << 24) & ~(1 << 21) & ~(1 << 20);
DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Clear SW ID : 0x%x \n", DualRoleCfg0));
}
MmioWrite32 ((UINTN)(XhciMmioBase + R_XHCI_MEM_DUAL_ROLE_CFG0), DualRoleCfg0);
BitMask = (UINT32) (0x20000000);
BitValue = (UINT32) (1 << 29);
Status = PchMmioPoll (
(UINTN) (XhciMmioBase + R_XHCI_MEM_DUAL_ROLE_CFG1),
BitMask,
~BitValue,
1000
);
if (Status == EFI_TIMEOUT) {
DEBUG ((DEBUG_ERROR, "Timeout while polling on xHCI BAR + 0x80DC [29] for 0b, %x\n", MmioRead32((UINT32)(XhciMmioBase + R_XHCI_MEM_DUAL_ROLE_CFG1))));
}
}
VOID
EFIAPI
UsbdMonitorEvents (
IN EFI_EVENT Event,
IN VOID *Context
)
{
USB_XDCI_DEV_CONTEXT *XdciDevContext;
UINT32 EventCount;
UINT32 PreEventCount;
UINT32 LoopCount;
XdciDevContext = (USB_XDCI_DEV_CONTEXT *) Context;
EventCount = usb_reg_read (XdciDevContext->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG (0));
if (EventCount == 0) {
return;
}
LoopCount = 0;
PreEventCount = EventCount;
while (EventCount != 0) {
if (usb_device_isr_routine_timer_based (mDrvObj.XdciDrvObj) != EFI_SUCCESS) {
DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"));
}
EventCount = usb_reg_read (XdciDevContext->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG (0));
if (PreEventCount == EventCount) {
LoopCount++;
if (LoopCount >= 5) {
DEBUG ((DEBUG_INFO, "USB is working on a long event...\n"));
break;
}
} else {
LoopCount = 0;
}
}
return;
}
/**
Initializes the XDCI core
@param MmioBar Address of MMIO BAR
@param XdciHndl Double pointer to for XDCI layer to set as an
opaque handle to the driver to be used in subsequent
interactions with the XDCI layer.
@return EFI_SUCCESS if successfully initialized XDCI, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdInit (
IN UINTN MmioBar,
IN VOID **XdciHndl
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
USB_DEV_CONFIG_PARAMS ConfigParams;
XhciSwitchSwid(TRUE);
DEBUG ((DEBUG_INFO, "UsbdInit start\n"));
ConfigParams.ControllerId = USB_ID_DWC_XDCI;
ConfigParams.BaseAddress = MmioBar;
ConfigParams.Role = USB_ROLE_DEVICE;
ConfigParams.Speed = USB_SPEED_SUPER;
Status = usb_device_init (&ConfigParams, XdciHndl);
DEBUG ((DEBUG_INFO, "UsbdInit status is %x\n", Status));
DEBUG ((DEBUG_INFO, "ConfigParams.BaseAddress 0x%x\n", ConfigParams.BaseAddress));
return Status;
}
/**
Copies relevant endpoint data from standard USB endpoint descriptors
to the usb_ep_info structure used by the XDCI
@param EpDest destination structure
@param EpSrc source structure
@return VOID
**/
VOID
UsbdSetEpInfo (
IN USB_EP_INFO *EpDest,
IN USB_DEVICE_ENDPOINT_INFO *EpSrc
)
{
EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc = NULL;
EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpCompDesc = NULL;
/* start by clearing all data in the destination */
SetMem (EpDest, sizeof(USB_EP_INFO), 0);
EpDesc = EpSrc->EndpointDesc;
EpCompDesc = EpSrc->EndpointCompDesc;
if (EpDesc != NULL) {
EpDest->ep_num = EpDesc->EndpointAddress & 0x0F; /* Bits 0-3 are ep num */
EpDest->ep_dir = ((EpDesc->EndpointAddress & USB_ENDPOINT_DIR_IN) > 0) ? UsbEpDirIn : UsbEpDirOut;
EpDest->ep_type = EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK;
EpDest->max_pkt_size = EpDesc->MaxPacketSize;
EpDest->interval = EpDesc->Interval;
}
if (EpCompDesc != NULL) {
EpDest->max_streams = EpCompDesc->Attributes & USB_EP_BULK_BM_ATTR_MASK;
EpDest->burst_size = EpCompDesc->MaxBurst;
EpDest->mult = EpCompDesc->BytesPerInterval;
}
return;
}
/**
Initializes the given endpoint
@param XdciHndl Pointer (handle) to the XDCI driver object
@param DevEpInfo Pointer to endpoint info structure
for the endpoint to initialize
@return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdInitEp (
IN VOID *XdciHndl,
IN USB_DEVICE_ENDPOINT_INFO *DevEpInfo
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
USB_EP_INFO EpInfo;
UsbdSetEpInfo (&EpInfo, DevEpInfo);
Status = usb_device_init_ep (XdciHndl, &EpInfo);
return Status;
}
/**
Callback handler used when transfer operations complete. Calls
upper layer routine to handle the operation.
@param XdciHndl Pointer (handle) to the XDCI driver object
@param XferReq Pointer to the transfer request structure
@return VOID
**/
VOID
EFIAPI
UsbdXferDoneHndlr (
IN VOID *XdciHndl,
IN USB_XFER_REQUEST *XferReq
)
{
EFI_USB_DEVICE_XFER_INFO XferInfo;
DEBUG ((DEBUG_INFO, "UsbdXferDoneHndlr\n"));
XferInfo.EndpointNum = (UINT8)XferReq->ep_info.ep_num;
XferInfo.EndpointDir = XferReq->ep_info.ep_dir;
XferInfo.EndpointType = XferReq->ep_info.ep_type;
XferInfo.Buffer = XferReq->xfer_buffer;
XferInfo.Length = XferReq->actual_xfer_len;
//
// If this is a non-control transfer complete, notify the class driver
//
if (XferInfo.EndpointNum > 0) {
if (mDrvObj.UsbdDevObj->DataCallback != NULL) {
mDrvObj.UsbdDevObj->DataCallback (&XferInfo);
}
}
return;
}
/**
Queue a request to transmit data
@param XdciHndl Pointer (handle) to the XDCI driver object
@param IoReq Pointer to IO structure containing details of the
transfer request
@return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdEpTxData (
IN VOID *XdciHndl,
IN USB_DEVICE_IO_REQ *IoReq
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
USB_XFER_REQUEST TxReq;
/* set endpoint data */
UsbdSetEpInfo (&(TxReq.ep_info), &(IoReq->EndpointInfo)); /* set endpoint data */
/* if this is a control endpoint, set the number and direction */
if (IoReq->EndpointInfo.EndpointDesc == NULL) {
TxReq.ep_info.ep_num = 0;
TxReq.ep_info.ep_dir = UsbEpDirIn;
}
/* setup the trasfer request */
TxReq.xfer_buffer = IoReq->IoInfo.Buffer;
TxReq.xfer_len = IoReq->IoInfo.Length;
TxReq.xfer_done = UsbdXferDoneHndlr;
DEBUG ((DEBUG_INFO, "TX REQUEST: epNum: 0x%x, epDir: 0x%x, epType: 0x%x, MaxPktSize: 0x%x\n",\
TxReq.ep_info.ep_num, TxReq.ep_info.ep_dir, TxReq.ep_info.ep_type, TxReq.ep_info.max_pkt_size));
Status = usb_device_ep_tx_data (XdciHndl, &TxReq);
return Status;
}
/**
Queue a request to receive data
@param XdciHndl Pointer (handle) to the XDCI driver object
@param IoReq Pointer to IO structure containing details of the
receive request
@return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdEpRxData (
IN VOID *XdciHndl,
IN USB_DEVICE_IO_REQ *IoReq
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
USB_XFER_REQUEST RxReq;
UINT32 ReqPacket;
DEBUG ((DEBUG_INFO, "RX REQUEST in: IoReq->IoInfo.Length: 0x%x\n", IoReq->IoInfo.Length));
DEBUG ((DEBUG_INFO, "RX REQUEST in: MaxPacketSize: 0x%x\n", IoReq->EndpointInfo.EndpointDesc->MaxPacketSize));
if (IoReq->EndpointInfo.EndpointDesc->MaxPacketSize == 0) {
return EFI_DEVICE_ERROR;
}
/* set endpoint data */
UsbdSetEpInfo (&(RxReq.ep_info), &(IoReq->EndpointInfo));
/* setup the trasfer request */
RxReq.xfer_buffer = IoReq->IoInfo.Buffer;
//
// Transfer length should be multiple of USB packet size.
//
ReqPacket = IoReq->IoInfo.Length / IoReq->EndpointInfo.EndpointDesc->MaxPacketSize;
ReqPacket = ((IoReq->IoInfo.Length % IoReq->EndpointInfo.EndpointDesc->MaxPacketSize) == 0)? ReqPacket : ReqPacket + 1;
RxReq.xfer_len = ReqPacket * IoReq->EndpointInfo.EndpointDesc->MaxPacketSize;
RxReq.xfer_done = UsbdXferDoneHndlr;
DEBUG ((DEBUG_INFO, "RX REQUEST: epNum: 0x%x, epDir: 0x%x, epType: 0x%x\n",\
RxReq.ep_info.ep_num, RxReq.ep_info.ep_dir, RxReq.ep_info.ep_type));
DEBUG ((DEBUG_INFO, "RX REQUEST send: xfer_len: 0x%x\n", RxReq.xfer_len));
Status = usb_device_ep_rx_data (XdciHndl, &RxReq);
return Status;
}
/**
Callback used to handle Reset events from the XDCI
@param Param Pointer to a generic callback parameter structure
@return XDCI usb status
**/
EFI_STATUS
EFIAPI
UsbdResetEvtHndlr (
IN USB_DEVICE_CALLBACK_PARAM *Param
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_INFO, "UsbdResetEvtHndlr\n"));
/* reset device address to 0 */
Status = usb_device_set_address (mDrvObj.XdciDrvObj, 0x0);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "UsbdResetHdlr() - Failed to set address in XDCI\n"));
}
return Status;
}
/**
Callback used to handle Connection done events from the XDCI
@param Param Pointer to a generic callback parameter structure
@return XDCI usb status
**/
EFI_STATUS
EFIAPI
UsbdConnDoneEvtHndlr (
IN USB_DEVICE_CALLBACK_PARAM *Param
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_INFO, "UsbdConnDoneEvtHndlr\n"));
/* reset device address to 0 */
Status = usb_device_set_address (mDrvObj.XdciDrvObj, 0x0);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDCI\n"));
}
/* set the device state to attached/connected */
mDrvObj.State = UsbDevStateAttached;
return Status;
}
/**
Callback used to handle Control Endpoint Setup events from the XDCI
@param Param Pointer to a generic callback parameter structure
@return XDCI usb status
**/
EFI_STATUS
EFIAPI
UsbdSetupEvtHndlr (
IN USB_DEVICE_CALLBACK_PARAM *Param
)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_USB_DEVICE_REQUEST Req;
DEBUG ((DEBUG_INFO, "UsbdSetupEvtHndlr\n"));
/* Fill out request object from the incomming buffer */
CopyMem (&Req, Param->buffer, sizeof(EFI_USB_DEVICE_REQUEST));
Status = UsbdSetupHdlr (&Req);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "UsbdSetupEvtHndlr: ERROR status %r\n", Status));
}
return Status;
}
/**
* Callback used to handle XferNotReady events from the XDCI
*
* @param Param Pointer to a generic callback parameter structure
*
* @return XDCI usb status
*/
EFI_STATUS
EFIAPI
UsbdNrdyEvtHndlr (
IN USB_DEVICE_CALLBACK_PARAM *Param
)
{
DEBUG ((DEBUG_INFO, "UsbdNrdyEvtHndlr\n"));
return EFI_SUCCESS;
}
/**
Registers callbacks for event handlers with the XDCI layer.
The functions will be called as the registered events are triggered.
@param XdciHndl to XDCI core driver
@return EFI_SUCCESS if successful, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdRegisterCallbacks (
IN VOID *XdciHndl
)
{
if (usb_device_register_callback (XdciHndl, USB_DEVICE_RESET_EVENT, UsbdResetEvtHndlr) != EFI_SUCCESS) {
goto UdciRegCallbackError;
}
if (usb_device_register_callback (XdciHndl, USB_DEVICE_CONNECTION_DONE, UsbdConnDoneEvtHndlr) != EFI_SUCCESS) {
goto UdciRegCallbackError;
}
if (usb_device_register_callback (XdciHndl, USB_DEVICE_SETUP_PKT_RECEIVED, UsbdSetupEvtHndlr) != EFI_SUCCESS) {
goto UdciRegCallbackError;
}
if (usb_device_register_callback (XdciHndl, USB_DEVICE_XFER_NRDY, UsbdNrdyEvtHndlr) != EFI_SUCCESS) {
goto UdciRegCallbackError;
}
return EFI_SUCCESS;
UdciRegCallbackError:
return EFI_DEVICE_ERROR;
}
/**
Returns the configuration descriptor for this device. The data
buffer returned will also contain all downstream interface and
endpoint buffers.
@param Buffer Pointer to destination buffer to copy descriptor data to
@param DescIndex the index of the descriptor to return
@param ReqLen the length in bytes of the request buffer
@param DataLen Pointer whos value is to be filled with the byte count of
data copied to the output buffer
@return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdGetConfigDesc (
IN VOID *Buffer,
IN UINT8 DescIndex,
IN UINT32 ReqLen,
IN UINT32 *DataLen
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
UINT8 NumConfigs = 0;
UINT32 ConfigLen = 0;
USB_DEVICE_CONFIG_OBJ *ConfigObj = NULL;
VOID *Descriptor = 0;
UINT32 Length = 0;
DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc()\n"));
/*
* For a CONFIGURATION request we send back all descriptors branching out
* from this descriptor including the INTERFACE and ENDPOINT descriptors
*/
/* Verify the requested configuration exists - check valid index */
NumConfigs = mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations;
if (DescIndex < NumConfigs) {
/* get the configuration object using the index offset */
ConfigObj = (mDrvObj.UsbdDevObj->ConfigObjs + DescIndex);
/* get the complete configuration buffer block including Interface and Endpoint data */
Descriptor = ConfigObj->ConfigAll;
/* The config descriptor TotalLength has the full value for all desc buffers */
ConfigLen = ConfigObj->ConfigDesc->TotalLength;
/* copy the data to the output buffer */
Length = MIN (ReqLen, ConfigLen);
CopyMem (Buffer, Descriptor, Length);
*DataLen = Length;
Status = EFI_SUCCESS;
} else {
DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc() - Invalid Config index: %i\n", DescIndex));
}
if (Status == EFI_SUCCESS) {
if (ConfigObj != NULL) {
PrintConfigDescriptor (ConfigObj->ConfigDesc);
}
}
return Status;
}
/**
Sets the active configuration to the selected configuration index if it exists
@param CfgValue the configuration value to set
@return EFI_SUCCESS if the configuration was set, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdSetConfig (
UINT8 CfgValue
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
UINT8 numConfigs = 0;
USB_DEVICE_CONFIG_OBJ *pConfigObj = NULL;
USB_DEVICE_INTERFACE_OBJ *pIfObj = NULL;
USB_DEVICE_ENDPOINT_OBJ *pEpObj = NULL;
UINT8 cfgItr = 0;
UINT8 ifItr = 0;
UINT8 epItr = 0;
USB_DEVICE_ENDPOINT_INFO epInfo;
USB_EP_INFO UsbEpInfo;
DEBUG ((DEBUG_INFO, "UsbdSetConfig()\n"));
/* Verify the requested configuration exists - check valid index */
numConfigs = mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations;
if (CfgValue != 0) {
/* Search for a matching configuration */
for (cfgItr = 0; cfgItr < numConfigs; cfgItr++) {
pConfigObj = (mDrvObj.UsbdDevObj->ConfigObjs + cfgItr);
if (pConfigObj->ConfigDesc->ConfigurationValue == CfgValue) {
/* Set the active configuration object */
mDrvObj.ActiveConfigObj = pConfigObj;
/* Find all interface objects for this configuration */
for (ifItr = 0; ifItr < pConfigObj->ConfigDesc->NumInterfaces; ifItr++) {
pIfObj = (pConfigObj->InterfaceObjs + ifItr);
/* Configure the Endpoints in the XDCI */
for (epItr = 0; epItr < pIfObj->InterfaceDesc->NumEndpoints; epItr++) {
pEpObj = (pIfObj->EndpointObjs + epItr);
epInfo.EndpointDesc = pEpObj->EndpointDesc;
epInfo.EndpointCompDesc = pEpObj->EndpointCompDesc;
if (UsbdInitEp (mDrvObj.XdciDrvObj, &epInfo) == EFI_SUCCESS) {
UsbdSetEpInfo(&UsbEpInfo, &epInfo);
if (usb_device_ep_enable (mDrvObj.XdciDrvObj, &UsbEpInfo) == EFI_SUCCESS) {
Status = EFI_SUCCESS;
} else {
DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to enable endpoint\n"));
}
} else {
DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to initialize endpoint\n"));
}
}
}
/* Let the class driver know it is configured */
if (Status == EFI_SUCCESS) {
if (mDrvObj.UsbdDevObj->ConfigCallback != NULL) {
mDrvObj.UsbdDevObj->ConfigCallback (CfgValue);
}
}
mDrvObj.State = UsbDevStateConfigured; /* we are now configured */
break; /* break from config search loop */
}
}
}
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Invalid requested configuration value: %i\n", CfgValue));
}
return Status;
}
/**
Returns the currently active configuration value
@param Buffer Pointer to destination buffer to copy configuration value to
@param ReqLen the length in bytes of the request buffer
@param DataLen Pointer whos value is to be filled with the byte count of
data copied to the output buffer
@return EFI_SUCCESS if config value is successfully copied, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdGetConfig (
VOID *Buffer,
UINT32 ReqLen,
UINT32 *DataLen
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_INFO, "UsbdGetConfig()\n"));
if (ReqLen >= 1) { /* length of data expected must be 1 */
if (mDrvObj.ActiveConfigObj != NULL) { /* assure we have a config active */
*DataLen = 1; /* one byte for ConfigurationValue */
*(UINT8*)Buffer = mDrvObj.ActiveConfigObj->ConfigDesc->ConfigurationValue;
Status = EFI_SUCCESS;
} else {
DEBUG ((DEBUG_INFO, "UsbdGetConfig() - No active configuration available\n"));
}
} else {
DEBUG ((DEBUG_INFO, "UsbdGetConfig() - Invalid data length\n"));
}
return Status;
}
/**
Returns the requested string descriptor if it exists
@param Buffer Pointer to destination buffer to copy descriptor data to
@param DescIndex the index of the descriptor to return
@param LangId the target language ID
@param ReqLen the length in bytes of the request buffer
@param DataLen Pointer whos value is to be filled with the byte count of
data copied to the output buffer
@return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdGetStringDesc (
VOID *Buffer,
UINT8 DescIndex,
UINT16 LangId,
UINT32 ReqLen,
UINT32 *DataLen
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
UINT32 Length = 0;
USB_STRING_DESCRIPTOR *StringDesc;
UINT8 Index = 0;
UINT8 StrLangEntries = 0;
BOOLEAN StrLangFound = FALSE;
DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Index: 0x%x, LangId: 0x%x, ReqLen: 0x%x\n", DescIndex, LangId, ReqLen));
/* index zero of the string table contains the supported language codes */
if (DescIndex == 0) {
StringDesc = (mDrvObj.UsbdDevObj->StringTable);
Length = MIN (ReqLen, StringDesc->Length);
CopyMem (Buffer, StringDesc, Length);
*DataLen = Length;
Status = EFI_SUCCESS;
} else {
/*
* Verify the requested language ID is supported. String descriptor Zero
* (First entry in the string table) is expected to contain the language list.
* The requested language ID is specified in the Index member of the request.
*/
StringDesc = mDrvObj.UsbdDevObj->StringTable; /* get language string descriptor */
StrLangEntries = ((StringDesc->Length - 2) >> 1);
DEBUG ((DEBUG_INFO, "StrLangEntries=%x\n", StrLangEntries));
DEBUG ((DEBUG_INFO, "Looking LangID: \n"));
for (Index = 0; Index < StrLangEntries; Index++) {
DEBUG ((DEBUG_INFO, "LangID [%x]= %x\n", Index, StringDesc->LangID [Index]));
if (StringDesc->LangID [Index] == LangId) {
DEBUG ((DEBUG_INFO, "Found it\n"));
StrLangFound = TRUE;
}
}
/* If we found a matching language, attempt to get the string index requested */
if (StrLangFound == TRUE) {
DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: StrLangFound=Found, DescIndex=%x, StrTblEntries=%x\n", DescIndex, mDrvObj.UsbdDevObj->StrTblEntries));
if (DescIndex < mDrvObj.UsbdDevObj->StrTblEntries) {
/* get the string descriptor for the requested index */
StringDesc = (mDrvObj.UsbdDevObj->StringTable + DescIndex);
Length = MIN (ReqLen, StringDesc->Length);
DEBUG ((DEBUG_INFO, "ReqLen=%x, StringLength=%x, Length=%x\n", ReqLen, StringDesc->Length, Length));
CopyMem (Buffer, StringDesc, Length);
*DataLen = Length;
Status = EFI_SUCCESS;
} else {
DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Invalid String index in USB_REQ_GET_DESCRIPTOR request\n"));
}
} else {
DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Unsupported String Language ID for USB_REQ_GET_DESCRIPTOR request\n"));
}
}
if (Status == EFI_SUCCESS) {
PrintStringDescriptor (StringDesc);
}
return Status;
}
#ifdef SUPPORT_SUPER_SPEED
/**
Returns the configuration descriptor for this device. The data
buffer returned will also contain all downstream interface and
endpoint buffers.
@param Buffer Pointer to destination buffer to copy descriptor data to
@param ReqLen the length in bytes of the request buffer
@param DataLen Pointer whos value is to be filled with the byte count of
data copied to the output buffer
@return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdGetBOSDesc (
IN VOID *Buffer,
IN UINT32 ReqLen,
IN UINT32 *DataLen
)
{
EFI_USB_BOS_DESCRIPTOR *BosDesc = 0;
UINT32 Length = 0;
DEBUG ((DEBUG_INFO, "UsbdGetBOSDesc()\n"));
BosDesc = mDrvObj.UsbdDevObj->BosDesc;
Length = MIN (ReqLen, mDrvObj.UsbdDevObj->BosDesc->TotalLength);
CopyMem(Buffer, BosDesc, Length);
*DataLen = Length;
PrintBOSDescriptor (BosDesc);
return EFI_SUCCESS;
}
#endif
/**
Returns the current status for Device/Interface/Endpoint
@param Buffer Pointer to destination buffer to copy descriptor data to
@param ReqType The type of status to get
@param ReqLen the length in bytes of the request buffer
@param DataLen Pointer whos value is to be filled with the byte count of
data copied to the output buffer
@return EFI_SUCCESS if status successfully copied, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdGetStatus (
VOID *Buffer,
UINT8 ReqType,
UINT32 ReqLen,
UINT32 *DataLen
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_INFO, "UsbdGetStatus()\n"));
if (ReqLen >= 2) { /* length of data must be at least 2 bytes */
switch (ReqType & USB_TARGET_MASK) {
case USB_TARGET_DEVICE:
*DataLen = 2; /* two byte for status */
*(UINT16*)Buffer = USB_STATUS_SELFPOWERED;
Status = EFI_SUCCESS;
break;
case USB_TARGET_INTERFACE:
/* No implementation needed at this time */
break;
case USB_TARGET_ENDPOINT:
/* No implementation needed at this time */
/* Should specify if endpoint is halted. Implement as necessary. */
break;
case USB_TARGET_OTHER:
/* No implementation needed at this time */
break;
default:
break;
}
} else {
DEBUG ((DEBUG_INFO, "UsbdGetStatus() - Invalid data length\n"));
}
return Status;
}
/**
Sets the address of the device
@param address the address value to set
@return EFI_SUCCESS if address was set, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdSetAddress (
UINT8 Address
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_INFO, "UsbdSetAddress: setting address: 0x%x\n", Address));
if (Address <= 0x7F) { /* address must not be > 127 */
mDrvObj.Address = Address;
/* Configure Address in the XDCI */
Status = usb_device_set_address (mDrvObj.XdciDrvObj, mDrvObj.Address);
if (!EFI_ERROR (Status)) {
mDrvObj.State = UsbDevStateAddress;
} else {
DEBUG ((DEBUG_INFO, "UsbdSetAddress: Failed to set address in XDCI\n"));
}
} else {
DEBUG ((DEBUG_INFO, "UsbdSetAddress: Invalid address: 0x%x\n", Address));
}
return Status;
}
/**
Handles Setup device requests. Standard requests are immediately
handled here, and any Class/Vendor specific requests are forwarded
to the class driver
@param CtrlRequest Pointer to a device request
@return EFI_SUCCESS if request successfully handled, FALSE otherwise
**/
EFI_STATUS
UsbdSetupHdlr (
IN EFI_USB_DEVICE_REQUEST *CtrlRequest
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
UINT8 DescIndex = 0;
USB_DEVICE_DESCRIPTOR *DevDesc = 0;
USB_EP_INFO EpInfo;
/* Initialize the IO object */
mCtrlIoReq.IoInfo.Length = 0;
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr start\n"));
PrintDeviceRequest (CtrlRequest);
/* Handle Standard Device Requests */
if ((CtrlRequest->RequestType & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) {
switch (CtrlRequest->Request) {
case USB_REQ_GET_DESCRIPTOR:
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Host requests get descriptor\n"));
if (CtrlRequest->RequestType == USB_RT_TX_DIR_D_TO_H) {
DescIndex = (CtrlRequest->Value & 0xff); /* low byte is the index requested */
switch (CtrlRequest->Value >> 8) { /* high byte contains request type */
case USB_DESC_TYPE_DEVICE:
DEBUG ((DEBUG_INFO, "Descriptor tyep: Device\n"));
DevDesc = mDrvObj.UsbdDevObj->DeviceDesc;
/* copy the data to the output buffer */
mCtrlIoReq.IoInfo.Length = MIN (CtrlRequest->Length, DevDesc->Length);
CopyMem (mCtrlIoReq.IoInfo.Buffer, DevDesc, mCtrlIoReq.IoInfo.Length);
PrintDeviceDescriptor (DevDesc);
break;
case USB_DESC_TYPE_CONFIG:
DEBUG ((DEBUG_INFO, "Descriptor tyep: Configuration\n"));
Status = UsbdGetConfigDesc (
mCtrlIoReq.IoInfo.Buffer,
DescIndex,
CtrlRequest->Length,
&(mCtrlIoReq.IoInfo.Length)
);
break;
case USB_DESC_TYPE_STRING:
DEBUG ((DEBUG_INFO, "Descriptor tyep: String\n"));
Status = UsbdGetStringDesc (
mCtrlIoReq.IoInfo.Buffer,
DescIndex,
CtrlRequest->Index,
CtrlRequest->Length,
&(mCtrlIoReq.IoInfo.Length)
);
break;
#ifdef SUPPORT_SUPER_SPEED
case USB_DESC_TYPE_BOS:
DEBUG ((DEBUG_INFO, "Descriptor tyep: BOS\n"));
Status = UsbdGetBOSDesc (
mCtrlIoReq.IoInfo.Buffer,
CtrlRequest->Length,
&(mCtrlIoReq.IoInfo.Length)
);
break;
case USB_DESC_TYPE_SS_ENDPOINT_COMPANION:
DEBUG ((DEBUG_INFO, "Descriptor tyep: Endpoint Companion\n"));
break;
#endif
default:
DEBUG ((DEBUG_INFO, "Descriptor tyep: Unsupported, USB_REQ_GET_DESCRIPTOR request: 0x%x\n", (CtrlRequest->Value >> 8)));
break;
}
} else {
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr() - Invalid direction for USB_REQ_GET_DESCRIPTOR request\n"));
}
break;
case USB_REQ_GET_CONFIG:
DEBUG ((DEBUG_INFO, "USB_REQ_GET_CONFIG\n"));
if (CtrlRequest->RequestType == USB_RT_TX_DIR_D_TO_H) {
Status = UsbdGetConfig (mCtrlIoReq.IoInfo.Buffer, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length));
} else {
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_GET_CONFIG request\n"));
}
break;
case USB_REQ_SET_CONFIG:
DEBUG ((DEBUG_INFO, "USB_REQ_SET_CONFIG\n"));
if (CtrlRequest->RequestType == USB_RT_TX_DIR_H_TO_D) {
Status = UsbdSetConfig ((UINT8)CtrlRequest->Value);
} else {
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_SET_CONFIG request\n"));
}
break;
case USB_REQ_SET_ADDRESS:
DEBUG ((DEBUG_INFO, "USB_REQ_SET_ADDRESS\n"));
if (CtrlRequest->RequestType == USB_RT_TX_DIR_H_TO_D) {
Status = UsbdSetAddress ((UINT8)CtrlRequest->Value);
} else {
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_SET_ADDRESS request\n"));
}
break;
case USB_REQ_GET_STATUS:
DEBUG ((DEBUG_INFO, "USB_REQ_GET_STATUS\n"));
if (CtrlRequest->RequestType & USB_RT_TX_DIR_D_TO_H) {
Status = UsbdGetStatus (mCtrlIoReq.IoInfo.Buffer, CtrlRequest->RequestType, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length));
} else {
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_GET_STATUS request\n"));
}
break;
case USB_REQ_CLEAR_FEATURE:
DEBUG ((DEBUG_INFO, "USB_REQ_CLEAR_FEATURE\n"));
if (CtrlRequest->Value == USB_FEATURE_ENDPOINT_HALT) {
if ((CtrlRequest->Index & USB_RT_TX_DIR_MASK) == USB_RT_TX_DIR_H_TO_D) {
EpInfo.ep_dir = UsbEpDirOut;
EpInfo.ep_num = CtrlRequest->Index;
} else {
EpInfo.ep_dir = UsbEpDirIn;
EpInfo.ep_num = CtrlRequest->Index & (~USB_RT_TX_DIR_MASK);
}
usb_device_ep_clear_stall (mDrvObj.XdciDrvObj, &EpInfo);
}
break;
case USB_REQ_SET_FEATURE:
case USB_REQ_SET_DESCRIPTOR:
case USB_REQ_GET_INTERFACE:
case USB_REQ_SET_INTERFACE:
case USB_REQ_SYNCH_FRAME:
default:
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Unsupported Standard Request: 0x%x\n", CtrlRequest->Request));
break;
}
} else { /* This is not a Standard request, it specifies Class/Vendor handling */
/* Forward request to class driver */
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Class/Vendor Request\n"));
if (mDrvObj.UsbdDevObj->SetupCallback != NULL) {
mDrvObj.UsbdDevObj->SetupCallback (CtrlRequest, &(mCtrlIoReq.IoInfo));
}
}
DEBUG ((DEBUG_INFO, "mCtrlIoReq.IoInfo.Length = 0x%x\n", mCtrlIoReq.IoInfo.Length));
/* Transfer data according to request if necessary */
if (mCtrlIoReq.IoInfo.Length> 0) {
Status = UsbdEpTxData (mDrvObj.XdciDrvObj, &mCtrlIoReq);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Failed to TX data\n"));
}
} else {
/* If we are not responding with data, send control status */
Status = usb_device_ep0_tx_status (mDrvObj.XdciDrvObj);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Failed to Tx Ep0 Status\n"));
}
}
return Status;
}
/**
Handles Connection done events. Sets the device address to zero.
@return EFI_SUCCESS if able to set the address, EFI_DEVICE_ERROR otherwise
**/
EFI_STATUS
UsbdConnDoneHdlr (
VOID
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr()\n"));
/* reset device address to 0 */
Status = usb_device_set_address (mDrvObj.XdciDrvObj, 0x0);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDCI\n"));
}
/* set the device state to attached/connected */
mDrvObj.State = UsbDevStateAttached;
return Status;
}
/**
Handles transmit/receive completion events. Directly handles
control endpoint events and forwards class/vendor specific events
to the class drivers.
@param XferInfo Pointer to xfer structure
@return
**/
VOID
UsbdXferDoneHdlr (
IN EFI_USB_DEVICE_XFER_INFO *XferInfo
)
{
//
// If this is a non-control transfer complete, notify the class driver
//
if (XferInfo->EndpointNum > 0) {
if (mDrvObj.UsbdDevObj->DataCallback != NULL) {
mDrvObj.UsbdDevObj->DataCallback (XferInfo);
}
}
return;
}
/**
Binds a USB class driver with this USB device driver core.
After calling this routine, the driver is ready to begin
USB processing.
@param UsbdDevObj Pointer to a usbd device object which contains
all relevant information for the class driver device
@return TRUE if binding was successful, FALSE otherwise
**/
EFI_STATUS
EFIAPI
UsbDeviceBind (
IN EFI_USB_DEVICE_MODE_PROTOCOL *This,
IN USB_DEVICE_OBJ *UsbdDevObj
)
{
EFI_STATUS Status = EFI_SUCCESS;
/* allocate Tx buffer */
mCtrlIoReq.IoInfo.Buffer = AllocateZeroPool (USB_EPO_MAX_PKT_SIZE_ALL);
if (mCtrlIoReq.IoInfo.Buffer != NULL) {
mDrvObj.UsbdDevObj = UsbdDevObj;
mDrvObj.ActiveConfigObj = NULL;
mDrvObj.Address = 0;
mDrvObj.State = UsbDevStateInit;
} else {
DEBUG ((DEBUG_INFO, "UsbDeviceBind() - Failed to allocate IO Buffer\n"));
Status = EFI_DEVICE_ERROR;
}
return Status;
}
/**
Unbinds the USB class driver from this USB device driver core.
@return TRUE if successful, FALSE otherwise
**/
EFI_STATUS
EFIAPI
UsbDeviceUnbind (
IN EFI_USB_DEVICE_MODE_PROTOCOL *This
)
{
mDrvObj.UsbdDevObj = NULL;
mDrvObj.ActiveConfigObj = NULL;
mDrvObj.Address = 0;
mDrvObj.State = UsbDevStateOff;
mDrvObj.XdciInitialized = FALSE;
/* release allocated buffer data */
if (mCtrlIoReq.IoInfo.Buffer) {
FreePool (mCtrlIoReq.IoInfo.Buffer);
}
return EFI_SUCCESS;
}
/**
Performs continual USB device event processing until a cancel
event occurs
@param TimeoutMs Connection timeout in ms. If 0, waits forever.
@return TRUE if run executed normally, FALSE if error ocurred
**/
EFI_STATUS
EFIAPI
UsbDeviceRun (
IN EFI_USB_DEVICE_MODE_PROTOCOL *This,
IN UINT32 TimeoutMs
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
USB_XDCI_DEV_CONTEXT *XdciDevContext;
XdciDevContext = USBUSBD_CONTEXT_FROM_PROTOCOL (This);
/* can only run if XDCI is initialized */
if ((mDrvObj.XdciInitialized == TRUE)) {
if ((mDrvObj.State == UsbDevStateConfigured) && (XdciDevContext->XdciPollTimer == NULL)) {
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
UsbdMonitorEvents,
XdciDevContext,
&XdciDevContext->XdciPollTimer
);
if (!EFI_ERROR (Status)) {
Status = gBS->SetTimer (XdciDevContext->XdciPollTimer, TimerPeriodic, EFI_TIMER_PERIOD_MILLISECONDS (20));
DEBUG ((EFI_D_ERROR, "UsbDeviceRun Create Event\n"));
}
}
mXdciRun = TRUE; /* set the run flag to active */
Status = EFI_SUCCESS;
/* start the Event processing loop */
/* DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Starting event processing...\n")); */
while (TRUE) {
if (XdciDevContext->XdciPollTimer == NULL) {
if (usb_device_isr_routine (mDrvObj.XdciDrvObj) != EFI_SUCCESS) {
DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"));
}
}
/* Check if a run cancel request exists, if so exit processing loop */
if (mXdciRun == FALSE) {
if (XdciDevContext->XdciPollTimer != NULL) {
DEBUG ((EFI_D_ERROR, "UsbDeviceRun close Event\n"));
gBS->SetTimer (XdciDevContext->XdciPollTimer, TimerCancel, 0);
gBS->CloseEvent (XdciDevContext->XdciPollTimer);
XdciDevContext->XdciPollTimer = NULL;
}
Status = EFI_SUCCESS;
DEBUG ((DEBUG_INFO, "UsbDeviceRun() - processing was cancelled\n"));
break;
}
/* check for timeout */
if (TimeoutMs == 0)
return EFI_TIMEOUT;
gBS->Stall (50);
TimeoutMs--;
}
}
return Status;
}
/**
Sets a flag to stop the running device processing loop
@return TRUE always
**/
EFI_STATUS
EFIAPI
UsbDeviceStop (
IN EFI_USB_DEVICE_MODE_PROTOCOL *This
)
{
mXdciRun = FALSE; /* set run flag to FALSE to stop processing */
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
UsbDeviceInitXdci (
IN EFI_USB_DEVICE_MODE_PROTOCOL *This
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
USB_XDCI_DEV_CONTEXT *XdciDevContext;
XdciDevContext = USBUSBD_CONTEXT_FROM_PROTOCOL (This);
PlatformSpecificInit ();
if (mDrvObj.XdciInitialized == FALSE) {
if (XdciDevContext->XdciMmioBarAddr != 0) {
/* Initialize device controller driver */
DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Initializing Controller...\n"));
/* Initialize the device controller interface */
if (UsbdInit (XdciDevContext->XdciMmioBarAddr, &mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
/* Setup callbacks */
if (UsbdRegisterCallbacks (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
mDrvObj.XdciInitialized = TRUE;
Status = EFI_SUCCESS;
DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Controller initialization complete\n"));
} else {
DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to register UDCI callbacks\n"));
}
} else {
DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to initialize UDCI\n"));
}
} else {
DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI MMIO BAR not set\n"));
}
} else {
DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI already initialized\n"));
Status = EFI_ALREADY_STARTED;
}
return Status;
}
EFI_STATUS
EFIAPI
UsbDeviceConnect(
IN EFI_USB_DEVICE_MODE_PROTOCOL *This
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_INFO, "UsbDeviceConnect \n"));
if (usb_device_connect (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
Status = EFI_SUCCESS;
}
return Status;
}
EFI_STATUS
EFIAPI
UsbDeviceDisConnect (
IN EFI_USB_DEVICE_MODE_PROTOCOL *This
)
{
EFI_STATUS Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_INFO, "UsbDeviceDisConnect \n"));
if (usb_device_disconnect (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
mDrvObj.State = UsbDevStateInit;
Status = EFI_SUCCESS;
}
return Status;
}
EFI_STATUS
EFIAPI
UsbDeviceEpTxData(
IN EFI_USB_DEVICE_MODE_PROTOCOL *This,
IN USB_DEVICE_IO_REQ *IoRequest
)
{
EFI_STATUS Status;
Status = UsbdEpTxData (mDrvObj.XdciDrvObj, IoRequest);
return Status;
}
EFI_STATUS
EFIAPI
UsbDeviceEpRxData(
IN EFI_USB_DEVICE_MODE_PROTOCOL *This,
IN USB_DEVICE_IO_REQ *IoRequest
)
{
EFI_STATUS Status;
Status = UsbdEpRxData (mDrvObj.XdciDrvObj, IoRequest);
return Status;
}
//
// The Runtime UsbDeviceMode Protocol instance produced by this driver
//
EFI_USB_DEVICE_MODE_PROTOCOL mUsbDeviceModeProtocol = {
UsbDeviceInitXdci,
UsbDeviceConnect,
UsbDeviceDisConnect,
UsbDeviceEpTxData,
UsbDeviceEpRxData,
UsbDeviceBind,
UsbDeviceUnbind,
UsbDeviceRun,
UsbDeviceStop
};