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

📄 pxa25xpdd.cpp

📁 pxa25x library for windows ce
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            // There is no error status for this. Will Assume it success.
            if (pTransfer) {
                if (pTransfer->cbTransferred >= pTransfer->cbBuffer || (ulUdccs &USB_UDCCS_RSP )!= 0 ) { // Complete.
                    *(peps->lpulUDCCSx) = ulUdccs ;
                    CompleteTransfer(pContext, peps, UFN_NO_ERROR);
                    continue;
                }
            }
            else { // No transfer. Keep Naking. do not interrupt us anymore
                ulUdccs &= ~USB_UDCCS_RPC;
            }
            
        }
        if((ulUdccs  & (USB_UDCCS_SST|USB_UDCCS_FST))== (USB_UDCCS_SST|USB_UDCCS_FST))  {
            USB_DEVICE_REQUEST udr;
            udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
            udr.bRequest =USB_REQUEST_CLEAR_FEATURE;
            udr.wValue = USB_FEATURE_ENDPOINT_STALL;
            udr.wIndex = (BYTE) peps->dwEndPointNumber ;
            udr.wLength =0;
            DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s Got SST EP%u \r\n"), pszFname, peps->dwEndPointNumber ));
            ulUdccs &= ~(USB_UDCCS_SST | USB_UDCCS_FST);
            *(peps->lpulUDCCSx) = ulUdccs;
            bContinue = TRUE;
            pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_PREPROCESSED_SETUP_PACKET,(DWORD) &udr);
            continue;
        }
        *(peps->lpulUDCCSx) = ulUdccs ;

    }
    if (peps->pTransfer == NULL )
        DisableEndpointInterrupt(pContext, peps->dwEndPointNumber );
    FUNCTION_LEAVE_MSG();
}


// Write data to an endpoint.
static VOID
HandleTx(
         PCTRLR_PDD_CONTEXT       pContext,
         PEP_STATUS peps
         )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    DEBUGCHK(pContext);
    PREFAST_DEBUGCHK(peps);
    BOOL fCompleted = FALSE;

    // This routine can be entered from both ISTMain and MDD/Client threads so
    // need critical section.
    BOOL  bContinue = TRUE;
    while (bContinue) {
        ULONG ulUdccs = *(peps->lpulUDCCSx);
        bContinue = FALSE;
        PSTransfer pTransfer = peps->pTransfer;
        DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s ulUdccs = %u \r\n"), pszFname, ulUdccs));
        ulUdccs &= ~USB_UDCCS_TSP ;
        if ( ulUdccs &  USB_UDCCS_TPC ) {  // The status is valid here.
            if (pTransfer && !peps->fZeroPacketNeeded && pTransfer->cbTransferred >= pTransfer->cbBuffer)  {
                *(peps->lpulUDCCSx) = ulUdccs ;
                CompleteTransfer(pContext,peps, UFN_NO_ERROR);
                continue;                
            }
        }
        if (pTransfer && ( ulUdccs & USB_UDCCS_TFS )!= 0 &&
                (pTransfer->cbTransferred < pTransfer->cbBuffer || peps->fZeroPacketNeeded  )) {

            DEBUGCHK(peps->fInitialized);

            ValidateTransferDirection(pContext, peps, pTransfer);
            DWORD dwSize = (pTransfer->cbTransferred< pTransfer->cbBuffer? pTransfer->cbBuffer-pTransfer->cbTransferred: 0);
            dwSize = min(dwSize, peps->dwPacketSizeSupported );
            DWORD dwReturnSize = 0;
            DWORD dwError = UFN_NO_ERROR ; 
            
            DWORD dwCurrentPermissions = GetCurrentPermissions();
            SetProcPermissions(pTransfer->dwCallerPermissions);
            __try {
                dwReturnSize = XmitData(peps,(PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred,dwSize);
            }
            __except(EXCEPTION_EXECUTE_HANDLER) {
                dwReturnSize = 0;
                dwError =UFN_CLIENT_BUFFER_ERROR;
            }
            SetProcPermissions(dwCurrentPermissions);
            
            pTransfer->cbTransferred += dwReturnSize;
            if (dwReturnSize < peps->dwPacketSizeSupported) {
                ulUdccs |= USB_UDCCS_TSP ;
            }
            peps->fZeroPacketNeeded = FALSE;
            DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s Transfer dwReturnSize = 0x%x ulUdccs = 0x%x, fZeroPacket =%d \r\n"), pszFname, dwReturnSize ,ulUdccs));
            
        }
        if((ulUdccs  & (USB_UDCCS_SST|USB_UDCCS_FST))== (USB_UDCCS_SST|USB_UDCCS_FST))  {
            USB_DEVICE_REQUEST udr;
            udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
            udr.bRequest =USB_REQUEST_CLEAR_FEATURE;
            udr.wValue = USB_FEATURE_ENDPOINT_STALL;
            udr.wIndex = (BYTE) peps->dwEndPointNumber ;
            udr.wLength =0;
            DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s Got SST EP%u \r\n"), pszFname, peps->dwEndPointNumber ));
            ulUdccs &=  ~USB_UDCCS_FST;
            *(peps->lpulUDCCSx) = ulUdccs;
            pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_PREPROCESSED_SETUP_PACKET,(DWORD) &udr);
            continue;
        }

        *(peps->lpulUDCCSx) = ulUdccs ;
    }
    if (peps->pTransfer == NULL )
        DisableEndpointInterrupt(pContext, peps->dwEndPointNumber );
    FUNCTION_LEAVE_MSG();
}


// Process an endpoint interrupt.  Call interrupt-specific handler.
static
VOID
HandleEndpointEvent(
                    PCTRLR_PDD_CONTEXT pContext,
                    DWORD            dwEndpoint
                    )
{  
    BOOL fNotifyMddClearFeature = FALSE;


    SETFNAME();

    DEBUGCHK(dwEndpoint != 0);

    ValidateContext(pContext);
    DEBUGCHK(pContext->fRunning);

    PEP_STATUS peps = GetEpStatus(pContext, dwEndpoint);
    LOCK_ENDPOINT(peps);

    FUNCTION_ENTER_MSG();

    volatile ULONG *lpulIrqStat = peps->lpulUDCCSx;
    PREFAST_DEBUGCHK(lpulIrqStat != NULL);

    DWORD dwPendingEvents = 0;
    peps->fInIST = TRUE;
    // setup active && out packet ready -> setup token event
    if (peps->dwDirectionSupported == USB_IN_TRANSFER){
        HandleTx(pContext, peps);
        DEBUGMSG(ZONE_FUNCTION, (_T("%s End EPIn Status =  %x \r\n"), pszFname, *lpulIrqStat));
    }
    else if (peps->dwDirectionSupported == USB_OUT_TRANSFER){
        //
        // receive packet complete && receive fifo not empty -> out token + data rx event
        //
        HandleRx(pContext, peps);
        DEBUGMSG(ZONE_FUNCTION, (_T("%s End EPOut Status =  %x \r\n"), 
            pszFname, *lpulIrqStat));
    }
    peps->fInIST = FALSE;

    FUNCTION_LEAVE_MSG();
    UNLOCK_ENDPOINT(peps);
}


static void SetRequestInfo(EP0_REQUEST *pRequest, EP0_DIR eDir)
{
    pRequest->eDir = eDir;
    pRequest->dwExpectedSize = 0;
    pRequest->fCompleted = FALSE;
    if (eDir == EP0Setup ) {
        pRequest->fBackupNext = FALSE;
    }
}


static BOOL GetSetupPkt(PUSB_DEVICE_REQUEST pUdr, BOOL fForce)
{
    SETFNAME();
    
    DWORD dwRead = 0;
    UCHAR *pucBuffer = (UCHAR *) pUdr;

    while( (dwRead < sizeof(USB_DEVICE_REQUEST)) && 
           (fForce || g_pUDCBase->udccs0 & USB_UDCCS0_RNE) ) {
        *pucBuffer++ = (UCHAR) g_pUDCBase->uddr0;
        dwRead++;
    }

    if (dwRead != sizeof(USB_DEVICE_REQUEST)) {
        DEBUGMSG(ZONE_WARNING, (_T("%s Only %d bytes read for SetupPacket\r\n"), 
            pszFname, dwRead));
        return FALSE;
    }
    
    return TRUE;
}

#define UDCCS0_MWRITEREG( x, y )        ((x) = ((x) & (~UDCCS0_MASK)) | (y))
#define UISR_IR0_CLR(pUISR0)            (pUISR0 = USB_UISR0_IR0)

#if defined(CHECK_UISR_IR0_CLR)
#define PRECHECK_IR0(p)   do {     if (((p) & 1) == 0) DEBUGMSG(ZONE_WARNING, (_T("%s %d IR0 not set\r\n"), pszFname, __LINE__)); } while (0)
#define CHECK_IR0(p)   do {     if ((p) & 1) DEBUGMSG(ZONE_WARNING, (_T("%s %d IR0 still set\r\n", pszFname, __LINE__)); } while (0)
#define UISR_IR0_CLR_CHK(p)  do { PRECHECK_IR0((p)); UISR_IR0_CLR((p)); CHECK_IR0((p)); } while (0)
#else
#define UISR_IR0_CLR_CHK(p)     UISR_IR0_CLR((p))
#endif
static VOID ServiceSetup(PCTRLR_PDD_CONTEXT pContext , PEP_STATUS peps)
{
    SETFNAME();
    FUNCTION_ENTER_MSG();    
    DEBUGCHK(pContext);
    
    BOOL    bContinue = TRUE;
    while (bContinue) {
        bContinue = FALSE;
        USB_DEVICE_REQUEST udr;
        DWORD dwUdrMsg = 0;

        ULONG ulStatusReg = *(peps->lpulUDCCSx);
        DEBUGMSG(ZONE_TRANSFER, (_T("%s EP0 Status Reg =  %x \r\n"), pszFname, ulStatusReg));

        PEP0_REQUEST pRequest = &pContext->ep0Request;
        PSTransfer pTransfer = peps->pTransfer;

        // Check for stall sent
        if ((ulStatusReg & USB_UDCCS0_SST)!=0) { // Stall on endpoint zero, It is auto clear, So we do not need to do anything here.
            ulStatusReg &= ~(USB_UDCCS0_FST);
            SetRequestInfo(pRequest, EP0Setup);
        }
        // Continue processing the other.
        if (ulStatusReg & USB_UDCCS0_OPR) {
            // check for missing status interrupt
            if ((ulStatusReg & USB_UDCCS0_SA)!=0 ) {
                if (pContext->fSpeedReported == FALSE) {
                    pContext->fSpeedReported = TRUE;
                    // After Every Reset Notify MDD of Speed setting.
                    // This device can only support FULL Speed.
                    pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_SPEED, BS_FULL_SPEED);
                    
                    // The HW Filters the Set Address ... Fake it here
                    pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SET_ADDRESS, 0xFF);
                    // Setup Configuration.
                    udr.bmRequestType = USB_REQUEST_FOR_DEVICE;
                    udr.bRequest = USB_REQUEST_SET_CONFIGURATION;
                    udr.wValue = pContext->wConfigurationValue ;
                    udr.wIndex = 0;
                    udr.wLength =0;
                    pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET,(DWORD) &udr);
                }
                if (!GetSetupPkt(&udr,TRUE)) { // No matter what, Read Packet First.
                    // fail to properly get setup packet from FIFO
                    // force a STALL condition
                    ulStatusReg |=USB_UDCCS0_FST;
                    DEBUGMSG(ZONE_WARNING, (_T("%s **** ERROR: Get setup packet failed\r\n"), pszFname));
                    ASSERT(FALSE);
                }
                
                if (pTransfer) {
                    CompleteTransfer(pContext, peps, UFN_NO_ERROR);
                }
                if (pContext->fEndpoint0AckNeeded) { // Wait for Ack from Application. Do not clean anything.
                    DisableEndpointInterrupt(pContext, 0 );
                    pRequest->fBackupNext = TRUE;
                    pRequest->udr = udr;
                    *(peps->lpulUDCCSx)= ulStatusReg ;
                }
                else {
                    SetRequestInfo(pRequest, EP0Setup);
                    pRequest->fCompleted = FALSE;
                    pRequest->dwExpectedSize = udr.wLength;
                    // Set data direction
                    if (udr.wLength != 0) {
                        if (udr.bmRequestType & USB_REQUEST_DEVICE_TO_HOST) {
                            pRequest->eDir = EP0In;
                        }
                        else {
                            pRequest->eDir = EP0Out;
                        }
                    }
                    else {
                        pRequest->eDir = EP0Out;
                    }
                    pRequest->fBackupNext = FALSE ;
                    pContext->fEndpoint0AckNeeded = TRUE;
                    *(peps->lpulUDCCSx)= ulStatusReg ;
                    pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
                }
                continue;
            }
            else { // Out Data.
                if ((ulStatusReg & USB_UDCCS0_RNE)== 0 ) { // This is ack from Host.
                    if (pRequest->eDir == EP0In) {
                        if (pTransfer) {
                            *(peps->lpulUDCCSx)= ulStatusReg ;
                            CompleteTransfer(pContext, peps, UFN_NO_ERROR);
                            continue;
                        }
                    }
                    else {
                        DEBUGMSG(ZONE_ERROR,(_T("%s **** ERROR: Get Zero Packet on EP0 Out Transfer,UDCCS0@INT = 0x%x,UDCCS0@Now = 0x%x, Try it again\r\n"), pszFname,ulStatusReg,*(peps->lpulUDCCSx)));
                        bContinue = TRUE;
                        continue;
                    }
                }
                else { // Data Available.
                    if (pTransfer ) {
                        if ( pRequest->eDir == EP0Out) {
                            DWORD dwCurrentPermissions = GetCurrentPermissions();
                            DWORD dwSize = (pTransfer->cbTransferred< pTransfer->cbBuffer? pTransfer->cbBuffer-pTransfer->cbTransferred: 0);
                            dwSize = min(dwSize, peps->dwPacketSizeSupported );
                            DWORD dwReturnSize = 0;
                            DWORD dwError = UFN_NO_ERROR ; 
                            SetProcPermissions(pTransfer->dwCallerPermissions);
                            __try {
                                dwReturnSize = ReceiveData(peps,(PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred , dwSize);
                            }
                            __except(EXCEPTION_EXECUTE_HANDLER) {
                                dwReturnSize = 0;
                                dwError =UFN_CLIENT_BUFFER_ERROR ;
                            }
                            SetProcPermissions(dwCurrentPermissions);
                            pTransfer->cbTransferred += dwReturnSize;
                            if (pTransfer->cbTransferred >= pTransfer->cbBuffer || dwReturnSize < dwSize) { // Complete or shourt packet.
                                *(peps->lpulUDCCSx)= ulStatusReg ;
                                CompleteTransfer(pContext, peps, dwError);
                                continue;
                            }
                        }
                        else
                            ulStatusReg |=USB_UDCCS0_FST;
                    }
                    else { 
                        DEBUGMSG(ZONE_ERROR, (_T("%s EP0 Out Packet without Transfer, Packet Dropped!!! \r\n"), pszFname));
                    }
                }
            }
        }
        else
        if ((ulStatusReg & USB_UDCCS0_IPR) == 0) { // Received One Packet.
            if (pRequest->eDir == EP0In) {
                if (pTransfer) {
                    DWORD dwCurrentPermissions = GetCurrentPermissions();
                    DWORD dwSize = (pTransfer->cbTransferred< pTransfer->cbBuffer? pTransfer->cbBuffer-pTransfer->cbTransferred: 0);
                    dwSize = min(dwSize, peps->dwPacketSizeSupported );
                    DWORD dwReturnSize = 0;
                    DWORD dwError = UFN_NO_ERROR ; 
                    SetProcPermissions(pTransfer->dwCallerPermissions);
                    __try {
                        dwReturnSize = XmitData(peps, (PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred,dwSize);
                    }
                    __except(EXCEPTION_EXECUTE_HANDLER) {
                        dwReturnSize = 0;
                        dwError =UFN_CLIENT_BUFFER_ERROR ;
                    }
                    SetProcPermissions(dwCurrentPermissions);
                    pTransfer->cbTransferred += dwReturnSize;
                    if (dwReturnSize < peps->dwPacketSizeSupported) {
                        ulStatusReg |= USB_UDCCS0_IPR;
                        peps->fZeroPacketNeeded = FALSE; // Short packet already.
                    }
                    else 
                        peps->fZeroPacketNeeded = TRUE; 
                    if (pTransfer->cbTransferred >= pTransfer->cbBuffer && !peps->fZeroPacketNeeded) { // We are complete.
                        *(peps->lpulUDCCSx) = ulStatusReg ;
                        CompleteTransfer(pContext, peps, UFN_NO_ERROR);
                        continue;
                    }
                    
                }
            }
        }
        else
            ulStatusReg &= ~USB_UDCCS0_IPR;
        *(peps->lpulUDCCSx) = ulStatusReg ;
    }

    FUNCTION_LEAVE_MSG();
}

static
VOID
ServiceEP0(
           PCTRLR_PDD_CONTEXT pContext
           )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    DEBUGCHK(pContext);
    PEP_STATUS peps = GetEpStatus(pContext, 0);
    LOCK_ENDPOINT(peps);
    
    peps->fInIST = TRUE;
    ServiceSetup(pContext, peps);
    peps->fInIST = FALSE;
    
    UNLOCK_ENDPOINT(peps);
    FUNCTION_LEAVE_MSG();
}
// Process an interrupt.
static
VOID
HandleUSBEvent(
               PCTRLR_PDD_CONTEXT pContext
               )
{
    DWORD interruptsToClear = 0;
    DWORD ulI;

    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    // GetDevice Interrupt Flag.
    BOOL bContinue = TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -