📄 usbdriver.c
字号:
/*----------------------------------------------------------------------------------
*
* COPYRIGHT (c) 2001 by Singing Electrons, Inc. All rights reserved.
*
*
* Module Name : C:\se\adi\hidclass\Source\usbdriver.c
*
* Description : The USB Driver - contains implementation of the low level USB interface.
*
*
* Revision History : At bottom of the file.
*
*---------------------------------------------------------------------------------*/
/** include files **/
#include <sys/exception.h>
#include <sys/excause.h>
#include <defBF535.h>
#include "dtype.h"
#include "register.h"
#include "usb.h"
#include "usbdriver.h"
#include "dmablocks.h"
#include "dprintf.h"
/** local definitions **/
/* default settings */
typedef struct tagEPSTATE{
UCHAR currentState;
USB_SETUP_DATA setupData;
void *dmaBuffer;
UINT dmaBufferSize;
UCHAR endpointType;
UINT maxPacketSize;
UINT defaultMaxTransferSize;
} EPSTATE, *PEPSTATE;
//for currentState
enum {
EP_STATE_IDLE = 0,
EP_STATE_WAITING_FOR_SETUP,
EP_STATE_DATA_IN_PHASE,
EP_STATE_DATA_OUT_PHASE,
EP_STATE_STATUS_PHASE,
EP_STATE_WAITING_FOR_IN_TC,
EP_STATE_WAITING_FOR_OUT_TC,
};
/** external functions **/
/** external data **/
/** internal functions **/
/** public data **/
/** private data **/
static int gNumEPBufsSetup = 0;
static EP_BUF gEndpointBuffers[MAX_EP_BUF];
static EPSTATE gActiveEndpointStates[MAX_PHY_EP];
static PSETUPPROC gpOnSetupReq;
static PGETDEVICEDESCRIPTORPROC gpOnGetDeviceDescriptor;
static PGETCONFIGDESCRIPTORPROC gpOnGetConfigDescriptor;
static PGETSTRINGDESCRIPTORPROC gpOnGetStringDescriptor;
static PINTCPROC gpOnInTC;
static POUTTCPROC gpOnOutTC;
static PMERRPROC gpOnMERR;
static PSUSPENDPROC gpOnSuspend;
static PRESUMEPROC gpOnResume;
static PRESETPROC gpOnReset;
static PCONFIGPROC gpOnConfigurationChange;
static PSOFPROC gpOnSOF;
static USHORT gep_int_mask; //Nothing special
UCHAR *gpControlEPDMABufferOUT;
UCHAR *gpControlEPDMABufferIN;
/** public functions **/
void *AllocDMABlock (int numBytesToAllocate);
void FreeDMABlock (void *blockToDealloc);
void InitDMA (void);
/** private functions **/
#pragma interrupt_reentrant
EX_INTERRUPT_HANDLER (USBDriver_ISR);
bool GetControlEndpointReady (UCHAR endpointNumber);
void HandleNoDataControlRequest (UCHAR currentEndpoint);
void HandleDataOutControlRequest (UCHAR currentEndpoint);
void HandleDataInControlRequest (UCHAR currentEndpoint);
bool DispatchDataInControlRequest (UCHAR endpointNumber);
/*------------------------------------------------------------
* USBDriver_PreInit
*
* Parameters:
*
* Globals Used:
* gNumEPBufsSetup
*
* Description:
* This routine initializes the global state variables used
* by the driver, and the USBD hardware. It does not
* initialize the EPBUFs
*
* Returns:
*
*
*------------------------------------------------------------*/
bool USBDriver_PreInit (void)
{
UINT chipVer;
gNumEPBufsSetup = 0;
memset (&gEndpointBuffers, 0, sizeof (gEndpointBuffers));
memset (&gActiveEndpointStates, 0, sizeof (gActiveEndpointStates));
InitDMA ();
//Let's setup the control endpoint, as it should be the same
//for all devices
USBDriver_SetupEndpoint (EP0, EP_CONFIG0, EP_IFACE0, EP_ALT0, 0, EP_CTL,
CONTROL_PIPE_PACKET_SIZE);
gpOnSetupReq = nil;
gpOnGetDeviceDescriptor = nil;
gpOnGetConfigDescriptor = nil;
gpOnGetStringDescriptor = nil;
gpOnInTC = nil;
gpOnOutTC = nil;
gpOnMERR = nil;
gpOnSuspend = nil;
gpOnResume = nil;
gpOnReset = nil;
gpOnConfigurationChange = nil;
// setup endpint interrpt mask
gep_int_mask = (USBD_GINTR_EP1INT|USBD_GINTR_EP2INT|USBD_GINTR_EP3INT|
USBD_GINTR_EP4INT|USBD_GINTR_EP5INT|USBD_GINTR_EP6INT|
USBD_GINTR_EP7INT);
// install the handler
//register_handler(ik_ivg7, USBDriver_ISR);
register_handler(ik_ivg8, USBDriver_ISR);
chipVer = 0xf0000000 & chipId_REG;
if(chipVer)
{
// rev. 1.0 or higher
SIC_IMASK_REG |= SIC_MASK2;
}
else
{
// rev. 0.x
SIC_IMASK_REG &= SIC_UNMASK2;
}
asm("ssync;");
//IMASK_REG |= 0x0080; // unmask IVG 7 at core
IMASK_REG |= 0x0100; // unmask IVG 8 at core
asm("ssync;");
return (true);
}
/*------------------------------------------------------------
* USBDriver_SetupEndpoint
*
* Parameters:
* endpointNumber - the endpoint number to be used (EP0..EP7)
* config - which configuration this setting is to be used for.
* interface - which interface this setting is to be used for.
* altSetting - which alt. setting this setting is to be used for.
* direction - could be EP_IN or EP_OUT
* ep_type - could be EP_CTL, EP_ISO, EP_BULK, or EP_INTERRUPT
* maxPacketSize - maximum packet length - could be 8, 16, 32,
* 64 for Bulk, Int, and Control EPs, or any value from
* 0 to 1023 for Iso. endpoints
*
* Globals Used:
* gNumEPBufsSetup
*
* Description:
* This routine loads the next EP_BUF array member with the
* supplied parameters
*
* Returns:
* true on success, false on failure
*
*
*------------------------------------------------------------*/
bool USBDriver_SetupEndpoint (UINT endpointNumber, UCHAR altSetting,
UCHAR interface, UCHAR configuration, UCHAR direction,
UCHAR ep_type, UINT maxPacketSize)
{
//Make sure we can hold them all!
if (gNumEPBufsSetup >= MAX_EP_BUF)
return (false);
gEndpointBuffers[gNumEPBufsSetup].s_ep_buf.ep_bufadrptr = endpointNumber;
gEndpointBuffers[gNumEPBufsSetup].s_ep_buf.ep_maxpktsize = maxPacketSize;
gEndpointBuffers[gNumEPBufsSetup].s_ep_buf.ep_dir = direction;
gEndpointBuffers[gNumEPBufsSetup].s_ep_buf.ep_type = ep_type;
gEndpointBuffers[gNumEPBufsSetup].s_ep_buf.ep_altsetting = altSetting;
gEndpointBuffers[gNumEPBufsSetup].s_ep_buf.ep_interface = interface;
gEndpointBuffers[gNumEPBufsSetup].s_ep_buf.ep_config = configuration;
gEndpointBuffers[gNumEPBufsSetup].s_ep_buf.epnum = endpointNumber;
gNumEPBufsSetup++;
return (true);
}
/*------------------------------------------------------------
* USBDriver_CompleteInit
*
* Parameters:
*
* Globals Used:
*
* Description:
* This routine finishes up the initialization, by installing the
* callback addresses and loading up the EP bufs, enabling USB, etc..
*
* Returns:
*
*
*------------------------------------------------------------*/
bool USBDriver_CompleteInit (PSETUPPROC pSetupProc, PGETDEVICEDESCRIPTORPROC pDevDescProc,
PGETCONFIGDESCRIPTORPROC pCfgDescProc, PGETSTRINGDESCRIPTORPROC pStringDescProc,
PINTCPROC pInTCProc, POUTTCPROC pOutTCProc, PMERRPROC pMerrProc, PSUSPENDPROC pSuspendProc, PRESUMEPROC pResumeProc,
PRESETPROC pResetProc, PCONFIGPROC pConfigProc, PSOFPROC pSOFProc, UINT controlEPMaxTransferSize)
{
int epBufNumber, epByte, timeout;
gpOnSetupReq = pSetupProc;
gpOnGetDeviceDescriptor = pDevDescProc;
gpOnGetConfigDescriptor = pCfgDescProc;
gpOnGetStringDescriptor = pStringDescProc;
gpOnInTC = pInTCProc;
gpOnOutTC = pOutTCProc;
gpOnMERR = pMerrProc;
gpOnSuspend = pSuspendProc;
gpOnResume = pResumeProc;
gpOnReset = pResetProc;
gpOnConfigurationChange = pConfigProc;
gpOnSOF = pSOFProc;
// initialize all 64 EP through the USBD_EPBUF
for (epBufNumber = 0; epBufNumber < MAX_EP_BUF; epBufNumber++)
{
for (epByte = EP_BUF_SZ; epByte > 0; epByte--)
{
UCHAR byteToDownload = gEndpointBuffers[epBufNumber].a_ep_buf[epByte-1];
USBD_EPBUF_REG = (USHORT) byteToDownload;
timeout = NUM_EPBUF_RDY_CHK;
while (timeout)
{
if((USBD_EPBUF_REG) & USBD_EPBUF_RDY)
break;
timeout--;
}
if (!timeout)
break;
asm("ssync;");
}
}
//See if we're all done!
if(((USBD_EPBUF_REG) & USBD_EPBUF_CFG))
{
asm("ssync;");
return (false);
}
asm("ssync;");
//=========================================================================
// setup the USBD_GINTR, USBD_INTRx and DMA USBD_DMACFG
// interrupt mask !
//=========================================================================
// clear all pending interrupts
USBD_GINTR_REG = (USHORT)0xFFFF;
// unmask all the EPs interrupt as well
USBD_GMASK_REG &= (USHORT)~(USBD_GMASK_EP0MSK|USBD_GMASK_EP1MSK|USBD_GMASK_EP2MSK|
USBD_GMASK_EP3MSK|USBD_GMASK_EP4MSK|USBD_GMASK_EP5MSK|
USBD_GMASK_EP6MSK|USBD_GMASK_EP7MSK|USBD_GMASK_CFGM |USBD_GMASK_RSTM|
USBD_GMASK_SUSPM|USBD_GMASK_RESUMEM | USBD_GMASK_SOFM);
// clear interrupt for all the EPs
USBD_INTR0_REG |= (USHORT)(USBD_INTR_TC|USBD_INTR_PC|USBD_INTR_BCSTAT|
USBD_INTR_SETUP|USBD_INTR_MSETUP|USBD_INTR_MERR);
USBD_INTR1_REG |= (USHORT)(USBD_INTR_TC|USBD_INTR_PC|USBD_INTR_BCSTAT);
USBD_INTR2_REG |= (USHORT)(USBD_INTR_TC|USBD_INTR_PC|USBD_INTR_BCSTAT);
USBD_INTR3_REG |= (USHORT)(USBD_INTR_TC|USBD_INTR_PC|USBD_INTR_BCSTAT);
USBD_INTR4_REG |= (USHORT)(USBD_INTR_TC|USBD_INTR_PC|USBD_INTR_BCSTAT);
USBD_INTR5_REG |= (USHORT)(USBD_INTR_TC|USBD_INTR_PC|USBD_INTR_BCSTAT);
USBD_INTR6_REG |= (USHORT)(USBD_INTR_TC|USBD_INTR_PC|USBD_INTR_BCSTAT);
USBD_INTR7_REG |= (USHORT)(USBD_INTR_TC|USBD_INTR_PC|USBD_INTR_BCSTAT);
// Unmask the USBD interrupts
USBD_MASK0_REG &= (USHORT)~(USBD_MASK_TC|USBD_MASK_PC|USBD_MASK_SETUP|
USBD_MASK_MSETUP|USBD_MASK_MERR|USBD_MASK_BCSTAT);
// Let's try something different: enable only BCSTAT
// SL :)
#if 1
USBD_MASK1_REG &= (USHORT)~(USBD_MASK_TC|USBD_MASK_PC|USBD_INTR_BCSTAT|USBD_MASK_MERR);
USBD_MASK2_REG &= (USHORT)~(USBD_MASK_TC|USBD_MASK_PC|USBD_INTR_BCSTAT);
USBD_MASK3_REG &= (USHORT)~(USBD_MASK_TC|USBD_MASK_PC|USBD_INTR_BCSTAT);
USBD_MASK4_REG &= (USHORT)~(USBD_MASK_TC|USBD_MASK_PC|USBD_INTR_BCSTAT);
USBD_MASK5_REG &= (USHORT)~(USBD_MASK_TC|USBD_MASK_PC|USBD_INTR_BCSTAT);
USBD_MASK6_REG &= (USHORT)~(USBD_MASK_TC|USBD_MASK_PC|USBD_INTR_BCSTAT);
USBD_MASK7_REG &= (USHORT)~(USBD_MASK_TC|USBD_MASK_PC|USBD_INTR_BCSTAT);
#else
USBD_MASK1_REG &= (USHORT)~(USBD_INTR_BCSTAT);
USBD_MASK2_REG &= (USHORT)~(USBD_INTR_BCSTAT);
USBD_MASK3_REG &= (USHORT)~(USBD_INTR_BCSTAT);
USBD_MASK4_REG &= (USHORT)~(USBD_INTR_BCSTAT);
USBD_MASK5_REG &= (USHORT)~(USBD_INTR_BCSTAT);
USBD_MASK6_REG &= (USHORT)~(USBD_INTR_BCSTAT);
USBD_MASK7_REG &= (USHORT)~(USBD_INTR_BCSTAT);
#endif
// clear the DMA FIFO first. before we use it !
USBD_DMACFG_REG |= (USHORT)USBD_DMACFG_DMABC;
USBD_DMACFG_REG = (USHORT)USBD_DMACFG_DMAEN;
//=========================================================================
// program the DMA master interface with the USB module's base address
// USBD_DMABL, USBD_DMABH
//=========================================================================
// BUG ! BUG ! BUG !
// need to do the lower 16 bit first to avoid a compiler bug !
USBD_DMABL_REG = (USHORT)((ULONG)gDMABuffer&USBD_DMABL_SGMSK);
USBD_DMABH_REG = (USHORT)((ULONG)gDMABuffer >> 16);
ActivateEndpoint (EP0, USBD_TYP_CTL, CONTROL_PIPE_PACKET_SIZE, controlEPMaxTransferSize);
if (!GetControlEndpointReady (EP0))
return (false);
// Enable the USBD now
USBD_CTRL_REG |= (USHORT)USBD_CTRL_ENA;
asm("ssync;");
//we're now ready to receive interrupts!
return(true);
}
/*------------------------------------------------------------
* ActivateEndpoint
*
* Parameters:
* endpointNumber - endpoint to set the information for.
* endpointType - type of endpoint - EP_CTL, EP_BULK, EP_INT, or EP_ISO
* maxPacketSize - the maximum packet size for this endpoint.
* defaultMaxTransferSize - the max. trasfer size to use by default.
*
* Globals Used:
* gActiveEndpointStates
*
* Description:
* This routine initializes the active endpoint state for the specified endpoint
* with the type, max packet size and default max. transfer size for the endpoint.
* This information is used in other circumstances. This routine should be called
* once for each endpoint after a new config. has come in effect.
*
* Returns:
* Nothing
*
*------------------------------------------------------------*/
void ActivateEndpoint (UCHAR endpointNumber, UCHAR endpointType, UCHAR maxPacketSize, UINT defaultMaxTransferSize)
{
gActiveEndpointStates[endpointNumber].endpointType = endpointType;
gActiveEndpointStates[endpointNumber].maxPacketSize = maxPacketSize;
gActiveEndpointStates[endpointNumber].defaultMaxTransferSize = defaultMaxTransferSize;
}
/*------------------------------------------------------------
* ArmEndpoint
*
* Parameters:
* endpointNumber - endpoint to arm.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -