📄 pdd.c
字号:
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 clean;
}
// Suspend/resume
if ((change & USBD_DEVSTAT_SUS) != 0) {
if ((state & USBD_DEVSTAT_SUS) != 0) {
// Let MDD process change
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_SUSPEND);
// Read device status
INREG32(&pUSBDRegs->DEVSTAT);
} else {
// Let MDD process change
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_RESUME);
}
}
// Addressed
if ((change & USBD_DEVSTAT_ADD) != 0) {
if ((state & USBD_DEVSTAT_ADD) != 0) {
// Let MDD process change
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_SET_ADDRESS, 1);
} else {
// Let MDD process change
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_CONFIGURED, 0 );
pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_SET_ADDRESS,0 );
}
}
clean:
// Save device state for next interrupt
pPdd->devState = state;
}
//------------------------------------------------------------------------------
//
// Function: InterruptThread
//
// This is interrupt thread. It controls responsed to hardware interrupt. To
// reduce code length it calls interrupt specific functions.
//
DWORD InterruptThread(VOID *pPddContext)
{
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD source, ep;
while (TRUE) {
BOOL fInterrupt = FALSE;
// Get interrupt source
source = INREG32(&pUSBDRegs->IRQ_SRC);
OALMSG(OAL_ETHER&&OAL_FUNC, (
L"UsbFnPdd!InterruptThread: Interrupt source %x\r\n", source
));
// Device state
if ((source & USBD_INT_DS_CHG) != 0 || pPdd->fakeDsChange) {
// Handle device state change
DevStatEvent(pPdd);
// Clear fake DsChange flag
pPdd->fakeDsChange = FALSE;
if (( source & USBD_INT_DS_CHG) != 0 )
OUTREG32(&pUSBDRegs->IRQ_SRC, USBD_INT_DS_CHG);
fInterrupt = TRUE;
}
// EP0 RX interrupt
if ((source & USBD_INT_EP0_RX) != 0) {
// Clear source bit
OUTREG32(&pUSBDRegs->IRQ_SRC, USBD_INT_EP0_RX);
// Issue next Rx transfer
IssueRxTransfer(pPdd, 0);
fInterrupt = TRUE;
}
// EP0 TX interrupt
if ((source & USBD_INT_EP0_TX) != 0) {
// Clear source bit
OUTREG32(&pUSBDRegs->IRQ_SRC, USBD_INT_EP0_TX);
// Issue next Tx transfer
IssueTxTransfer(pPdd, 0);
fInterrupt = TRUE;
}
// EPn RX interrupt
if ((source & USBD_INT_EP_RX) != 0) {
// Get EP number
ep = (INREG32(&pUSBDRegs->EP_STAT) >> 8) & USBD_EP_NUM;
// Clear source bit
OUTREG32(&pUSBDRegs->IRQ_SRC, USBD_INT_EP_RX);
// Handle event
IssueRxTransfer(pPdd, ep);
fInterrupt = TRUE;
}
// EPn TX interrupt
if ((source & USBD_INT_EP_TX) != 0) {
// Get EP number
ep = INREG32(&pUSBDRegs->EP_STAT) & USBD_EP_NUM;
// Clear source bit
OUTREG32(&pUSBDRegs->IRQ_SRC, USBD_INT_EP_TX);
// Handle event
IssueTxTransfer(pPdd, ep);
fInterrupt = TRUE;
}
// Setup Packet
if ((source & USBD_INT_SETUP) != 0) {
// Reading setup FIFO clears interrupt
SetupEvent(pPdd);
fInterrupt = TRUE;
}
if( !fInterrupt )
{
break;
}
}
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
DWORD WINAPI UfnPdd_IssueTransfer(
VOID *pPddContext, DWORD endPoint, STransfer *pTransfer
) {
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD epNum;
// Save transfer for interrupt thread
pPdd->ep[endPoint].pTransfer = pTransfer;
// Sync Length with buffer
if (pTransfer->pvBuffer == NULL) pTransfer->cbBuffer = 0;
// Depending on direction
if (TRANSFER_IS_IN(pTransfer)) {
pPdd->ep[endPoint].zeroLength = (pTransfer->cbBuffer == 0);
IssueTxTransfer(pPdd, endPoint);
} else {
pPdd->ep[endPoint].zeroLength = FALSE;
// Select EP
epNum = USBD_EP_NUM & endPoint;
OUTREG32(&pUSBDRegs->EP_NUM, USBD_EP_NUM_SEL | epNum);
// Enable EP FIFO
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_FIFO_EN);
// Deselect EP
OUTREG32(&pUSBDRegs->EP_NUM, epNum);
}
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
DWORD WINAPI UfnPdd_AbortTransfer(
VOID *pPddContext, DWORD endPoint, STransfer *pTransfer
) {
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD epNum;
// Select EP
epNum = USBD_EP_NUM & endPoint;
if (TRANSFER_IS_IN(pTransfer)) epNum |= USBD_EP_NUM_DIRIN;
OUTREG32(&pUSBDRegs->EP_NUM, USBD_EP_NUM_SEL | epNum);
// Clear EP
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_CLR_EP);
// Deselect EP
OUTREG32(&pUSBDRegs->EP_NUM, epNum);
// Finish transfer
pPdd->ep[endPoint].pTransfer = NULL;
pTransfer->dwUsbError = UFN_CANCELED_ERROR;
pPdd->pfnNotify(
pPdd->pMddContext, UFN_MSG_TRANSFER_COMPLETE, (DWORD)pTransfer
);
// Done
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_StallEndpoint
//
// This function is called by MDD to set end point to stall mode (halted).
//
DWORD WINAPI UfnPdd_StallEndpoint(VOID *pPddContext, DWORD endPoint)
{
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD epNum;
OALMSG(OAL_ETHER&&OAL_FUNC, (
L"UsbFnPdd_StallEndpoint %d\r\n", endPoint
));
if (endPoint == 0) {
// Stall next EP0 transaction
OUTREG32(&pUSBDRegs->SYSCON2, USBD_SYSCON2_STALL_CMD);
} else {
// Select EP
epNum = USBD_EP_NUM & endPoint;
if (!pPdd->ep[endPoint].dirRx) epNum |= USBD_EP_NUM_DIRIN;
OUTREG32(&pUSBDRegs->EP_NUM, USBD_EP_NUM_SEL | epNum);
// Halt EP
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_SET_HALT);
// Deselect EP
OUTREG32(&pUSBDRegs->EP_NUM, epNum);
}
// Done
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_ClearEndpointStall
//
// This function is called by MDD to clear end point stall mode (halted).
//
DWORD WINAPI UfnPdd_ClearEndpointStall(VOID *pPddContext, DWORD endPoint)
{
DWORD rc = ERROR_INVALID_FUNCTION;
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD epNum;
OALMSG(OAL_ETHER&&OAL_FUNC, (
L"UsbFnPdd_ClearEndpoint %d\r\n", endPoint
));
// Endpoint can't be zero
if (endPoint == 0) goto clean;
// Select EP
epNum = USBD_EP_NUM & endPoint;
if (!pPdd->ep[endPoint].dirRx) epNum |= USBD_EP_NUM_DIRIN;
OUTREG32(&pUSBDRegs->EP_NUM, USBD_EP_NUM_SEL | epNum);
// Reset endpoint - clear halt isn't sufficient
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_RESET_EP);
// Deselect EP
OUTREG32(&pUSBDRegs->EP_NUM, epNum);
// Done
rc = ERROR_SUCCESS;
clean:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_IsEndpointHalted
//
DWORD WINAPI UfnPdd_IsEndpointHalted(
VOID *pPddContext, DWORD endPoint, BOOL *pHalted
) {
DWORD rc = ERROR_INVALID_FUNCTION;
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD epNum;
OALMSG(OAL_ETHER&&OAL_FUNC, (
L"UsbFnPdd_IsEndpointHalted %d\r\n", endPoint
));
// Endpoint can't be zero
if (endPoint == 0) goto clean;
// Select EP
epNum = USBD_EP_NUM & endPoint;
if (!pPdd->ep[endPoint].dirRx) epNum |= USBD_EP_NUM_DIRIN;
OUTREG32(&pUSBDRegs->EP_NUM, USBD_EP_NUM_SEL | epNum);
// Is EP halted?
*pHalted = (INREG32(&pUSBDRegs->STAT_FLG) & USBD_STAT_HALTED) != 0;
// Deselect EP
OUTREG32(&pUSBDRegs->EP_NUM, epNum);
// Done
rc = ERROR_SUCCESS;
clean:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_InitiateRemoteWakeup
//
// Send the control status handshake.
//
DWORD WINAPI UfnPdd_SendControlStatusHandshake(
VOID *pPddContext, DWORD endPoint
) {
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD epNum, stat;
// Select EP
epNum = USBD_EP_NUM & endPoint;
if (pPdd->setupDirRx) epNum |= USBD_EP_NUM_DIRIN;
OUTREG32(&pUSBDRegs->EP_NUM, USBD_EP_NUM_SEL | epNum);
// Get actual status
stat = INREG32(&pUSBDRegs->STAT_FLG);
OALMSG(OAL_ETHER&&OAL_FUNC, (
L"UsbFnPdd_SendControlStatusHandhake: %d %s (stat %x)\r\n",
endPoint, pPdd->setupDirRx ? L"IN" : L"OUT", stat
));
// Don't send handshake when EP is stall
if ((stat & USBD_STAT_STALL) == 0) {
// Clear & enable FIFO
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_CLR_EP);
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_FIFO_EN);
}
// Deselect EP
OUTREG32(&pUSBDRegs->EP_NUM, epNum);
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_InitiateRemoteWakeup
//
DWORD WINAPI UfnPdd_InitiateRemoteWakeup(VOID *pPddContext)
{
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
OALMSG(OAL_ETHER&&OAL_FUNC, (L"UsbFnPdd_InitiateRemoteWakeup\r\n"));
SETREG32(&pUSBDRegs->SYSCON2, USBD_SYSCON2_RMT_WKP);
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_PowerDown
//
VOID WINAPI UfnPdd_PowerDown(VOID *pPddContext)
{
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_PowerUp
//
VOID WINAPI UfnPdd_PowerUp(VOID *pPddContext)
{
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_IOControl
//
DWORD WINAPI UfnPdd_IOControl(
VOID *pPddContext, IOCTL_SOURCE source, DWORD code, UCHAR *pInBuffer,
DWORD inSize, UCHAR *pOutBuffer, DWORD outSize, DWORD *pOutSize
) {
DWORD rc = ERROR_INVALID_PARAMETER;
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
UFN_PDD_INFO *pInfo;
switch (code) {
case IOCTL_UFN_GET_PDD_INFO:
if (source != BUS_IOCTL) break;
if (pOutBuffer == NULL || outSize < sizeof(UFN_PDD_INFO)) break;
pInfo = (UFN_PDD_INFO*)pOutBuffer;
pInfo->InterfaceType = Internal;
pInfo->BusNumber = 0;
pInfo->dwAlignment = sizeof(DWORD);
rc = ERROR_SUCCESS;
break;
case IOCTL_BUS_GET_POWER_STATE:
break;
case IOCTL_BUS_SET_POWER_STATE:
break;
}
return rc;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_Deinit
//
DWORD WINAPI UfnPdd_Deinit(VOID *pPddContext)
{
USBFN_PDD *pPdd = pPddContext;
OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
// Unmap USBD controller registers
if (pPdd->pUSBDRegs != NULL) {
pPdd->pUSBDRegs = NULL;
}
// Done
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_DeregisterDevice
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -