⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdd.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 C
📖 第 1 页 / 共 3 页
字号:
            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 + -