📄 pdd.c
字号:
L"USB Device is Self-Powered\r\n"));
SETREG32(&pUSBDRegs->SYSCON1, USBD_SYSCON1_SELF_PWR);
}
else
{
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - "
L"USB Device is NOT Self-Powered\r\n"));
CLRREG32(&pUSBDRegs->SYSCON1, USBD_SYSCON1_SELF_PWR);
}
}
else
{
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - "
L"Changing USB Device state to Addressed\r\n"));
OUTREG32(&pUSBDRegs->SYSCON2, USBD_SYSCON2_CLR_CFG);
}
}
// Let MDD process message
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_SETUP_PACKET, (DWORD)data);
}
//------------------------------------------------------------------------------
//
// Function: IssueTxTransfer
//
// This function sends next packet from transaction buffer. It is called from
// interrupt thread and UfnPdd_IssueTransfer.
//
static VOID IssueTxTransfer(USBFN_PDD *pPdd, DWORD endPoint)
{
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
STransfer *pTransfer;
BOOL complete = FALSE;
DWORD stat, space, count, remain;
UCHAR *pBuffer;
DWORD data;
DWORD epNum;
// Get active transfer
pTransfer = pPdd->ep[endPoint].pTransfer;
DEBUGMSG(ZONE_TRANSFER, (L"USBD IssueTxTransfer() - "
L"EP %d pTransfer 0x%08X (%d, %d, %d)\r\n",
endPoint,
pTransfer,
pTransfer != NULL ? pTransfer->cbBuffer : 0,
pTransfer != NULL ? pTransfer->cbTransferred : 0,
pTransfer != NULL ? pTransfer->dwUsbError : -1));
// Select EP
epNum = (USBD_EP_NUM & endPoint) | USBD_EP_NUM_DIRIN;
SelectEp(pPdd, epNum);
// Get EP status
stat = INREG32(&pUSBDRegs->STAT_FLG);
// Depending on EP status
if ((stat & USBD_STAT_STALL) != 0)
{
// We issued stall, remove it...
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_CLR_HALT);
}
else
{
// When transfer is NULL it is handshake ACK
if (pTransfer != NULL)
{
// Is this final interrupt of transfer?
if ((pTransfer->cbTransferred == pTransfer->cbBuffer) && (!pPdd->ep[endPoint].fZeroLengthNeeded))
{
pTransfer->dwUsbError = UFN_NO_ERROR;
complete = TRUE;
}
else
{
__try
{
pBuffer = (UCHAR*)pTransfer->pvBuffer + pTransfer->cbTransferred;
space = pTransfer->cbBuffer - pTransfer->cbTransferred;
if (endPoint != 0)
{
// Non Zero Endpoint: No zero length padding needed.
pPdd->ep[endPoint].fZeroLengthNeeded = FALSE;
}
else
{
// Zero endpoint: Zero length padding needed if last packet is maxPacketSize.
pPdd->ep[endPoint].fZeroLengthNeeded = ((space == pPdd->ep[endPoint].maxPacketSize) && (pPdd->setupCount > pTransfer->cbBuffer));
}
// How many bytes we can send just now?
count = pPdd->ep[endPoint].maxPacketSize;
if (count > space)
{
count = space;
}
// Write data to FIFO
remain = count;
while (remain > 1)
{
data = (pBuffer[1] << 8) | pBuffer[0];
OUTREG16((UINT16*)&pUSBDRegs->DATA, data);
pBuffer += 2;
space -= 2;
remain -= 2;
}
if (remain > 0)
{
OUTREG8((UINT8*)&pUSBDRegs->DATA, *pBuffer);
pBuffer += 1;
space -= 1;
remain -= 1;
}
DEBUGMSG(ZONE_TRANSFER, (L"USBD IssueTxTransfer() - "
L"Transfered %d bytes on ep 0x%02X", count, endPoint));
// Enable FIFO
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_FIFO_EN);
// We transfered some data
pTransfer->cbTransferred = pTransfer->cbBuffer - space;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
pTransfer->dwUsbError = UFN_CLIENT_BUFFER_ERROR;
complete = TRUE;
}
}
}
else
{
DEBUGMSG(ZONE_TRANSFER, (L"USBD IssueTxTransfer() - "
L"pTransfer is NULL; HandShake ACK."));
}
}
// Deselect EP
DeselectEp(pPdd, epNum);
// If transaction is complete we should tell MDD
if (complete)
{
DEBUGMSG(ZONE_TRANSFER, (L"USBD IssueTxTransfer() - "
L"Notifying MDD that transfer is complete."));
pPdd->ep[endPoint].pTransfer = NULL;
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_TRANSFER_COMPLETE, (DWORD)pTransfer);
}
}
//------------------------------------------------------------------------------
//
// Function: IssueRxTransfer
//
// This function receives packet to transaction buffer. It is called from
// interrupt thread.
//
static VOID IssueRxTransfer(USBFN_PDD *pPdd, DWORD endPoint)
{
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
STransfer *pTransfer;
BOOL complete = FALSE;
DWORD space, remain;
UCHAR *pBuffer;
DWORD data;
DWORD stat;
DWORD epNum;
DWORD count;
DWORD maxSize;
// Get active transfer
pTransfer = pPdd->ep[endPoint].pTransfer;
DEBUGMSG(ZONE_TRANSFER, (L"USBD IssueRxTransfer() - "
L"EP %d pTransfer 0x%08X (%d, %d, %d)\r\n",
endPoint,
pTransfer,
pTransfer != NULL ? pTransfer->cbBuffer : 0,
pTransfer != NULL ? pTransfer->cbTransferred : 0,
pTransfer != NULL ? pTransfer->dwUsbError : -1));
// Select EP
epNum = USBD_EP_NUM & endPoint;
SelectEp(pPdd, epNum);
// Get EP status
stat = INREG32(&pUSBDRegs->STAT_FLG);
// Depending on EP status
if ((stat & USBD_STAT_STALL) != 0)
{
// We issued stall, remove it...
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_CLR_HALT);
}
else
{
// When transfer is NULL it is handshake ACK
if (pTransfer != NULL)
{
// Get maxPacketSize
maxSize = pPdd->ep[endPoint].maxPacketSize;
__try
{
pBuffer = (UCHAR*)pTransfer->pvBuffer + pTransfer->cbTransferred;
space = pTransfer->cbBuffer - pTransfer->cbTransferred;
// Get EP status flag
stat = INREG32(&pUSBDRegs->STAT_FLG);
// Get number of bytes in FIFO
if ((stat & USBD_STAT_FIFO_EMPTY) != 0)
{
count = 0;
}
else if ((stat & USBD_STAT_FIFO_FULL) != 0)
{
count = maxSize;
}
else
{
count = INREG32(&pUSBDRegs->RXFSTAT) & USBD_RFXSTAT_COUNT;
}
// Read data
remain = count;
while (remain > 1)
{
data = (WORD)INREG16(&pUSBDRegs->DATA);
if (space > 1)
{
pBuffer[0] = (UCHAR)data;
pBuffer[1] = (UCHAR)(data >> 8);
pBuffer += 2;
space -= 2;
}
remain -= 2;
}
if (remain > 0)
{
data = (WORD)INREG16(&pUSBDRegs->DATA);
if (space > 0)
{
*pBuffer = (UCHAR)data;
pBuffer += 1;
space -= 1;
}
remain -= 1;
}
// We transfered some data
pTransfer->cbTransferred = pTransfer->cbBuffer - space;
DEBUGMSG(ZONE_TRANSFER, (L"USBD IssueRxTransfer() - "
L"Transfered %d bytes on ep 0x%02X", pTransfer->cbTransferred, epNum));
// Is this end of transfer?
if ((pTransfer->cbTransferred == pTransfer->cbBuffer) || (count < maxSize))
{
// Yes, set return code
pTransfer->dwUsbError = UFN_NO_ERROR;
// And complete flag
complete = TRUE;
}
else
{
// No, enable FIFO for next packet
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_FIFO_EN);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
pTransfer->dwUsbError = UFN_CLIENT_BUFFER_ERROR;
complete = TRUE;
}
}
}
// Deselect EP
Deselect(pPdd, epNum);
// If transaction is complete we should tell MDD
if (complete)
{
pPdd->ep[endPoint].pTransfer = NULL;
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_TRANSFER_COMPLETE, (DWORD)pTransfer);
}
}
//------------------------------------------------------------------------------
//
// Function: DevStatEvent
//
// This function handles device state change interrupts.
//
static VOID DevStatEvent(USBFN_PDD *pPdd)
{
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD state, change;
DEBUGMSG(ZONE_FUNCTION, (L"USBD DevStatEvent() - START\r\n"));
// Get Current Device State and compare to Previous Device State
// Store the differences in change.
// Note: (a ^ b) == (a XOR b)
state = INREG32(&pUSBDRegs->DEVSTAT);
change = state ^ pPdd->devState;
DEBUGMSG(ZONE_PDD, (L"USBD DevStatEvent() - "
L"Previous Device State = 0x%04X\r\n", pPdd->devState));
DEBUGMSG(ZONE_PDD, (L"USBD DevStatEvent() - "
L"Current Device State = 0x%04X\r\n", state));
DEBUGMSG(ZONE_PDD, (L"USBD DevStatEvent() - "
L"Device State Change = 0x%04X\r\n", change));
DEBUGMSG(ZONE_PDD, (L"UsbFnPdd!DevStatEvent: "
L"Device State = 0x%04x, change = 0x%04X\r\n", state, change));
#ifdef USE_OLD_CABLE_DETECT_METHOD
// Attach/deattach
if ((change & USBD_DEVSTAT_ATT) != 0)
{
if ((state & USBD_DEVSTAT_ATT) != 0)
{
DEBUGMSG(ZONE_PDD, (L"USBD DevStatEvent() - "
L"Detected Cable Insertion Event!\r\n"));
// TODO: Call bus driver (OTG?) to move HW from deep sleep
// SetSelfPowerState to D0.
pPdd->m_CurSelfPowerState = D0;
UpdateDevicePower(pPdd);
// Let MDD process change
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_SPEED, BS_FULL_SPEED);
}
else
{
DEBUGMSG(ZONE_PDD, (L"USBD DevStatEvent() - "
L"Detected Cable Removal Event!\r\n"));
// We are not configured anymore
OUTREG32(&pUSBDRegs->SYSCON2, USBD_SYSCON2_CLR_CFG);
// TODO: Call bus driver (OTG?) to move HW to deep sleep
// Let MDD process change
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
// Don't process other changes (we are disconnected)
// SetSelfPowerState to D4
pPdd->m_CurSelfPowerState = D4; // Do we need set to D3 as wake up source?
UpdateDevicePower(pPdd);
goto DevStatClean;
}
}
#endif // USE_OLD_CABLE_DETECT_METHOD
// Reset
if (((change & USBD_DEVSTAT_USB_RESET) != 0) || ((change & USBD_DEVSTAT_DEF) != 0))
{
DEBUGMSG(ZONE_PDD, (L"USBD DevStatEvent() - "
L"Detected USB Reset Event!\r\n"));
pPdd->m_NewPowerState = D0;
UpdateDevicePower(pPdd);
if ((state & USBD_DEVSTAT_USB_RESET) == 0)
{
// OTG may not detect attach/detach events correctly on some platforms
// Simulate a attach/detach event to clear any previous state on reset
// Let MDD process change
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_SPEED, BS_FULL_SPEED);
// Tell MDD about reset...
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_RESET);
}
// Enable interrupts
OUTREG32(&pUSBDRegs->IRQ_EN, USBD_IRQ_MASK);
// In the middle of a reset don't process other changes
goto DevStatClean;
}
// Suspend/resume
if ((change & USBD_DEVSTAT_SUS) != 0)
{
if ((state & USBD_DEVSTAT_SUS) != 0)
{
DEBUGMSG(ZONE_PDD, (L"USBD DevStatEvent() - "
L"Detected Device Suspend Event!\r\n"));
// Let MDD process change
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_SUSPEND);
// Read device status
INREG32(&pUSBDRegs->DEVSTAT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -