📄 usbdriver.c
字号:
* direction - direction for the transfer (EP_IN or EP_OUT)
*
* Globals Used:
* gActiveEndpointStates
*
* Description:
* Sets the DMA address/length for an endpoint, and arms it, alongwith providing
* the appropriate config. information for the endpoint.
*
* Returns:
* Nothing
*
*------------------------------------------------------------*/
void ArmEndpoint (UCHAR endpointNumber, UCHAR direction)
{
USHORT cfgReg;
//USHORT len = gActiveEndpointStates[endpointNumber].dmaBufferSize;
cfgReg = (USHORT)((USBD_EPCFG_ARM) | (direction << 1) | (gActiveEndpointStates[endpointNumber].endpointType << 2));
SET_USBD_MAX(cfgReg, GetMaxPacketSizeCode (gActiveEndpointStates[endpointNumber].maxPacketSize));
(*(PVUS)((UINT)USBD_EPCFG0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = cfgReg;
//Dprintf ("CFG Reg = %08x", cfgReg);
(*(PVUS)((UINT)USBD_EPADR0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) =
(USHORT)((ULONG)gActiveEndpointStates[endpointNumber].dmaBuffer & USBD_OFFSET_SGMSK);
//Dprintf ("ADR Reg = %08x", (USHORT)((ULONG)gActiveEndpointStates[endpointNumber].dmaBuffer & USBD_OFFSET_SGMSK));
(*(PVUS)((UINT)USBD_EPLEN0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) =
(USHORT)gActiveEndpointStates[endpointNumber].dmaBufferSize;
//Dprintf ("LEN Reg: %08x", (USHORT)gActiveEndpointStates[endpointNumber].dmaBufferSize);
asm("ssync;");
}
/*------------------------------------------------------------
* DisarmEndpoint
*
* Parameters:
* endpointNumber - endpoint to arm.
* direction - direction for the transfer (EP_IN or EP_OUT)
*
* Globals Used:
* gActiveEndpointStates
*
* Description:
* Disarms the given endpoint. In the process, it also toggles the
* direction bit - as recommended by Errata (Item 27):
* Blackfin ADSP-21535 Anomaly list
* for Revision(s) ADSP-21535-0.2, ADSP-21535-1.0, ADSP-21535-1.1
* Created Tue Sep 10 15:37:16 2002 (IM)
*
* Returns:
* Nothing
*
*------------------------------------------------------------*/
void DisarmEndpoint (UCHAR endpointNumber, UCHAR direction)
{
USHORT cfgReg;
//Need to toggle the direction bit.
cfgReg = (USHORT)((((direction) ? 0 : 1) << 1) | (gActiveEndpointStates[endpointNumber].endpointType << 2));
SET_USBD_MAX(cfgReg, GetMaxPacketSizeCode (gActiveEndpointStates[endpointNumber].maxPacketSize));
(*(PVUS)((UINT)USBD_EPCFG0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = cfgReg;
asm("ssync;");
//Dprintf ("CFG Reg = %08x", cfgReg);
cfgReg = (USHORT)((direction << 1) | (gActiveEndpointStates[endpointNumber].endpointType << 2));
SET_USBD_MAX(cfgReg, GetMaxPacketSizeCode (gActiveEndpointStates[endpointNumber].maxPacketSize));
(*(PVUS)((UINT)USBD_EPCFG0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = cfgReg;
//Dprintf ("CFG Reg = %08x", cfgReg);
(*(PVUS)((UINT)USBD_EPLEN0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = 0;
asm("ssync;");
}
/*------------------------------------------------------------
* USBDriver_ISR
*
* Parameters:
* r0x, r1x, r2x
*
* Globals Used:
*
*
* Description:
* The ISR to handle USBD interrupts.
*
* Returns:
* Nothing
*
*
*------------------------------------------------------------*/
//EX_REENTRANT_HANDLER (USBDriver_ISR)
void USBDriver_ISR ( int _r0x, int _r1x, int _r2x )
{
int i, currentEndpoint;
USHORT usbd_gintr;
USHORT usbd_status;
static USHORT usbd_epintr[MAX_PHY_EP];
bool shouldStall, shouldRecycle;
// clear the interrupt last!
usbd_gintr = (USHORT)USBD_GINTR_REG;
usbd_epintr[0]= (USHORT)USBD_INTR0_REG;
USBD_INTR0_REG = usbd_epintr[0];
usbd_epintr[1]= (USHORT)USBD_INTR1_REG;
USBD_INTR1_REG = usbd_epintr[1];
usbd_epintr[2]= (USHORT)USBD_INTR2_REG;
USBD_INTR2_REG = usbd_epintr[2];
usbd_epintr[3]= (USHORT)USBD_INTR3_REG;
USBD_INTR3_REG = usbd_epintr[3];
usbd_epintr[4]= (USHORT)USBD_INTR4_REG;
USBD_INTR4_REG = usbd_epintr[4];
usbd_epintr[5]= (USHORT)USBD_INTR5_REG;
USBD_INTR5_REG = usbd_epintr[5];
usbd_epintr[6]= (USHORT)USBD_INTR6_REG;
USBD_INTR6_REG = usbd_epintr[6];
usbd_epintr[7]= (USHORT)USBD_INTR7_REG;
USBD_INTR7_REG = usbd_epintr[7];
usbd_status = (USHORT)USBD_STAT_REG;
asm("ssync;");
//Dprintf1 ("usbd_gintr = %08x", usbd_gintr);
//Dprintf1 ("epint0 = %08x", usbd_epintr[0]);
if (usbd_gintr & USBD_GINTR_CFG)
{
if (gpOnConfigurationChange)
{
//Dprintf1 ("usbd_status = %08x", usbd_status);
//Call the client to do whatever it needs to do on config change
(*gpOnConfigurationChange)(GET_USBD_CONFIG(usbd_status),
GET_USBD_INTERFACE(usbd_status),
GET_USBD_ALTSETTING(usbd_status));
}
}
if (usbd_gintr & USBD_GINTR_SUSP)
{
//We should reset the states of all our endpoints
for (currentEndpoint = (MAX_PHY_EP-1); currentEndpoint >= EP0 ; currentEndpoint--)
{
gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_IDLE;
}
//and free the DMA buffers
InitDMA ();
//let the client know about this!
if (gpOnSuspend)
(gpOnSuspend)();
}
if (usbd_gintr & USBD_GINTR_RESUME)
{
//Prepare control EP for receiving a setup packet!
GetControlEndpointReady (EP0);
//let the client know about this!
if (gpOnResume)
(gpOnResume)();
}
if (usbd_gintr & USBD_GINTR_RST)
{
//We should reset the states of all our endpoints
for (currentEndpoint = (MAX_PHY_EP-1); currentEndpoint >= EP0 ; currentEndpoint--)
{
gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_IDLE;
}
//and free the DMA buffers
InitDMA ();
//Prepare control EP for receiving a setup packet!
GetControlEndpointReady (EP0);
if (gpOnReset)
(gpOnReset)();
}
if ((usbd_gintr & USBD_GINTR_SOF) && (gpOnSOF))
(gpOnSOF)();
for (currentEndpoint = EP0; currentEndpoint < MAX_PHY_EP; currentEndpoint++)
{
if ((gActiveEndpointStates[currentEndpoint].currentState == EP_STATE_WAITING_FOR_SETUP) &&
((usbd_epintr[currentEndpoint] & USBD_INTR_SETUP)))
{
//Save a copy of the setup request
CopyDMABufferToSETUPStruct (&gActiveEndpointStates[currentEndpoint].setupData,
gActiveEndpointStates[currentEndpoint].dmaBuffer);
//Dprintf ("Received Setup Request");
//Don't need this buffer any more
FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
//If there's no data-phase to this
if (gActiveEndpointStates[currentEndpoint].setupData.wLength == 0)
{
//Dprintf ("Entering Status Phase");
HandleNoDataControlRequest (currentEndpoint);
}
else
{
//We come here when wLength is non-zero
//If direction of accompanying data is OUT, we need to have a DMA buffer
//to recive it, and ARM our endpoint accordingly
if (USB_CONTROL_REQUEST_GET_DIRECTION (gActiveEndpointStates[currentEndpoint].setupData.bmRequestType)
== USB_CONTROL_REQUEST_TYPE_OUT)
{
//Dprintf ("Entering Data Out Phase");
HandleDataOutControlRequest (currentEndpoint);
}
else
{
//Dprintf ("Entering Data In Phase");
HandleDataInControlRequest (currentEndpoint);
}
}
}
else if (usbd_epintr[currentEndpoint] & USBD_INTR_TC)
{
switch (gActiveEndpointStates[currentEndpoint].currentState)
{
case EP_STATE_WAITING_FOR_IN_TC:
//Free the DMA buffer
FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_IDLE;
//Let the client know that a xfer has completed
if (gpOnInTC)
(gpOnInTC)(currentEndpoint);
break;
case EP_STATE_WAITING_FOR_OUT_TC:
gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_IDLE;
shouldRecycle = false;
//Let the client know that a xfer has completed
if (gpOnOutTC)
{
shouldRecycle = (gpOnOutTC)(currentEndpoint, gActiveEndpointStates[currentEndpoint].dmaBuffer,
gActiveEndpointStates[currentEndpoint].dmaBufferSize -
(*(PVUS)((UINT)USBD_EPLEN0 + (USBD_EPCFG1 - USBD_EPCFG0) * currentEndpoint)),
usbd_epintr[currentEndpoint] & USBD_INTR_PC);
}
if (shouldRecycle)
{
gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_WAITING_FOR_OUT_TC;
ArmEndpoint (currentEndpoint, EP_OUT);
}
else
{
DisarmEndpoint (currentEndpoint, EP_OUT);
//Free the DMA buffer
gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
}
break;
case EP_STATE_STATUS_PHASE:
//Dprintf ("Completed Status Phase");
//Nothing more to do, let's get the endpoint ready for more requests
GetControlEndpointReady (currentEndpoint);
break;
case EP_STATE_DATA_OUT_PHASE:
//We've recevied all the data, let's provide this to client
//Dprintf ("Entering Status Phase from Data Out");
shouldStall = true;
if (gpOnSetupReq)
{
shouldStall = (!(gpOnSetupReq) (currentEndpoint, &gActiveEndpointStates[currentEndpoint].setupData,
gActiveEndpointStates[currentEndpoint].dmaBuffer, &gActiveEndpointStates[currentEndpoint].dmaBufferSize));
}
//Free the DMA buffer
FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
if (shouldStall)
{
StallEndpoint (currentEndpoint);
GetControlEndpointReady (currentEndpoint);
}
else
{
gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_STATUS_PHASE;
ArmEndpoint (currentEndpoint, EP_IN);
}
break;
case EP_STATE_DATA_IN_PHASE:
//The host has read the data we provided, let's enter the status phase
//Free the DMA buffer
//Let's not be too sure! Check to make sure this is indeed the case!
if (gActiveEndpointStates[currentEndpoint].maxPacketSize >=
(*(PVUS)((UINT)USBD_EPLEN0 + (USBD_EPCFG1 - USBD_EPCFG0) * currentEndpoint)))
{
//Dprintf ("Entering Status Phase from Data In");
FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_STATUS_PHASE;
ArmEndpoint (currentEndpoint, EP_OUT);
}
break;
default:
//ToDo: For non-control endpoints, we need to do our client notification
//Etc. here
break;
} //(gActiveEndpointStates[currentEndpoint].currentState)
} //if (usbd_epintr[currentEndpoint] & USBD_INTR_TC)
if (usbd_epintr[currentEndpoint] & USBD_INTR_MERR)
{
if (gpOnMERR)
(gpOnMERR)(currentEndpoint);
}// (usbd_epintr[currentEndpoint] & USBD_INTR_MERR)
} //(currentEndpoint = EP0; currentEndpoint < MAX_PHY_EP; currentEndpoint++)
//ToDo: Add code to do whatever is necessary to handle other interrupts
USBD_GINTR_REG = (USHORT)usbd_gintr;
asm("ssync;");
}
/*------------------------------------------------------------
* HandleNoDataControlRequest
*
* Parameters:
* currentEndpoint - endpoint on which to handle the request.
*
* Globals Used:
* gpOnSetupReq, gActiveEndpointStates
*
* Description:
* This routine is called to handle a Control Request(SETUP) with
* no data. If the client has setup a callback, this routine calls
* the client, with the setup data. And based on the client's reply
* it either transitions the transfer to status phase, or stalls the
* endpoint.
*
* Returns:
* Nothing.
*
*------------------------------------------------------------*/
void HandleNoDataControlRequest (UCHAR currentEndpoint)
{
//Call the client to let them know!
if (gpOnSetupReq)
{
if ((gpOnSetupReq) (currentEndpoint, &gActiveEndpointStates[currentEndpoint].setupData,
nil, nil))
{
//Success, meaning we are ready to get into the status phase,
//Which simply involves receiving a zero length DATA OUT packet.
gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_STATUS_PHASE;
ArmEndpoint (currentEndpoint, EP_OUT);
}
else
{
//stall!
StallEndpoint (currentEndpoint);
GetControlEndpointReady (currentEndpoint);
}
}
else
{
//stall!
StallEndpoint (currentEndpoint);
GetControlEndpointReady (currentEndpoint);
}
}
/*------------------------------------------------------------
* HandleDataOutControlRequest
*
* Parameters:
* currentEndpoint - endpoint on which to handle the request.
*
* Globals Used:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -