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

📄 trans.cpp

📁 嵌入式操作系统WINCE5.0下的USB驱动程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                memcpy( m_sTransfer.lpvBuffer, m_pAllocatedForClient, m_sTransfer.dwBufferSize );
            } __except( EXCEPTION_EXECUTE_HANDLER ) {
                  // bad lpvBuffer.
                if (dwUsbError == USB_NO_ERROR)
                    dwUsbError = USB_CLIENT_BUFFER_ERROR;
            }
        }
        __try { // setting transfer status and executing callback function
            if (m_sTransfer.lpfComplete !=NULL)
                *m_sTransfer.lpfComplete = TRUE;
            if (m_sTransfer.lpdwError!=NULL)
                *m_sTransfer.lpdwError = dwUsbError;
            if (m_sTransfer.lpdwBytesTransferred)
                *m_sTransfer.lpdwBytesTransferred =  m_DataTransferred;
            if ( m_sTransfer.lpStartAddress ) {
                ( *m_sTransfer.lpStartAddress )(m_sTransfer.lpvNotifyParameter );
                m_sTransfer.lpStartAddress = NULL ; // Make sure only do once.
            }
        } __except( EXCEPTION_EXECUTE_HANDLER ) {
              DEBUGMSG( ZONE_ERROR, (TEXT("CQueuedPipe(%s)::CheckForDoneTransfers - exception setting transfer status to complete\n"), m_pCPipe->GetPipeType() ) );
        }
        SetProcPermissions(dwOldPermissions);
        return (dwUsbError==USB_NO_ERROR);
    }
    else
        return TRUE;
}
BOOL CQTransfer::AbortTransfer()
{
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CQTransfer::AbortTransfer (this=0x%x,id=0x%x)\r\n"),this,m_dwTransferID));
    CQTD * pCurTD = m_pCQTDList;
    while ( pCurTD!=NULL) {
        pCurTD->DeActiveTD();
        pCurTD = pCurTD->GetNextTD();
    }
    Sleep(2);// Make sure the shcdule has advanced. and current Transfer has completeded.
    return TRUE;
}
BOOL CQTransfer::IsTransferDone()
{
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CQTransfer::IsTransferDone (this=0x%x,id=0x%x)\r\n"),this,m_dwTransferID));
    if (m_pCQTDList==NULL) { // Has been created. Somthing wrong.
        return TRUE;
    }
    CQTD * pCurTD = m_pCQTDList;
    BOOL bReturn=TRUE;
    while ( pCurTD!=NULL) {
        ASSERT(pCurTD->m_pTrans == this);
        if (pCurTD->qTD_Token.qTD_TContext.Halted==1) { // This Transfer Has been halted due to error.
            break;
        }
        if (pCurTD->qTD_Token.qTD_TContext.Active == 1) { 
            bReturn = FALSE;
            break;
        }
        if (pCurTD ->GetLinkValid() == FALSE) { // No like connected. This Transfer is  aborted.
            break;
        }
        pCurTD = pCurTD ->GetNextTD();
    }
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CQTransfer::IsTransferDone (this=0x%x) return %d \r\n"),this,bReturn));
    return bReturn;
}
CIsochTransfer::CIsochTransfer(IN CIsochronousPipe * const pCPipe,IN CEhcd * const pCEhcd,STransfer sTransfer) 
    : CTransfer(pCPipe,pCEhcd->GetPhysMem(),sTransfer)
    ,m_pCEhcd(pCEhcd)
{
    m_dwFrameIndexStart = m_sTransfer.dwStartingFrame;
    m_dwNumOfTD =0;
    m_dwSchedTDIndex=0;

    m_dwDequeuedTDIndex=0;
    
    m_dwArmedTDIndex =0;
    m_dwArmedBufferIndex=0;
    m_dwFirstError =  USB_NO_ERROR;
    m_dwLastFrameIndex = 0;

};

CITransfer::CITransfer(IN CIsochronousPipe * const pCPipe, IN CEhcd * const pCEhcd,STransfer sTransfer)
    :CIsochTransfer (pCPipe, pCEhcd,sTransfer)
{
    m_pCITDList =0;
}
CITransfer::~CITransfer()
{
    ASSERT(m_dwSchedTDIndex==m_dwNumOfTD || m_dwLastFrameIndex<m_dwNumOfTD);
    ASSERT(m_dwDequeuedTDIndex ==  m_dwNumOfTD||m_dwLastFrameIndex<m_dwNumOfTD );
    if (m_pCITDList && m_dwNumOfTD) {
        AbortTransfer();
        for (DWORD dwIndex=0;dwIndex<m_dwNumOfTD;dwIndex++)
            if (*(m_pCITDList + dwIndex)) {
                ASSERT((*(m_pCITDList + dwIndex) )->GetLinkValid() != TRUE); // Invalid Next Link
                //Free *(m_pCITDList + dwIndex);
                GetPipe()->FreeCITD(*(m_pCITDList + dwIndex));
                *(m_pCITDList + dwIndex) = NULL;
            }
        delete m_pCITDList;
    }
}
BOOL CITransfer::ArmTD()
{
    BOOL bAnyArmed = FALSE;
    if (m_pCITDList && m_dwArmedTDIndex<m_dwNumOfTD ) { // Something TD wait for Arm.
        DWORD dwCurDataPhysAddr = m_sTransfer.paBuffer + m_dwArmedBufferIndex;
        DWORD dwFrameIndex = m_dwArmedTDIndex * MAX_TRNAS_PER_ITD ;
        while (dwFrameIndex< m_sTransfer.dwFrames && m_dwArmedTDIndex < m_dwNumOfTD) {
            *(m_pCITDList + m_dwArmedTDIndex) = GetPipe()->AllocateCITD( this);
            if (*(m_pCITDList + m_dwArmedTDIndex) == NULL) 
                break;
            DWORD dwTransLenArray[MAX_TRNAS_PER_ITD];
            DWORD dwFrameAddrArray[MAX_TRNAS_PER_ITD];
            for (DWORD dwTransIndex=0; dwTransIndex <  MAX_TRNAS_PER_ITD && dwFrameIndex < m_sTransfer.dwFrames ; dwTransIndex ++) {
                dwTransLenArray[dwTransIndex]=  *(m_sTransfer.aLengths + dwFrameIndex);
                dwFrameAddrArray[dwTransIndex] = dwCurDataPhysAddr;
                dwCurDataPhysAddr +=dwTransLenArray[dwTransIndex];
                m_dwArmedBufferIndex += dwTransLenArray[dwTransIndex];
                dwFrameIndex ++;
            }
            if (dwTransIndex !=0) {
                (*(m_pCITDList + m_dwArmedTDIndex))->IssueTransfer( 
                    dwTransIndex,dwTransLenArray, dwFrameAddrArray,
                    dwFrameIndex>= m_sTransfer.dwFrames ,
                    (m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0);
                (*(m_pCITDList+ m_dwArmedTDIndex ))->SetIOC(TRUE); // Interrupt On every TD.
            }
            else {
                ASSERT(FALSE);
                break;
            }
            m_dwArmedTDIndex ++;
            bAnyArmed=TRUE;
        }
    }
    return bAnyArmed;
}
BOOL CITransfer::AddTransfer () 
{
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer::AddTransfer (this=0x%x,id=0x%x)\r\n"),this,m_dwTransferID));
    if (m_dwNumOfTD!=0 || m_pCITDList != NULL) {
        ASSERT(FALSE);
        return FALSE;
    }
    m_dwNumOfTD = (m_sTransfer.dwFrames + MAX_TRNAS_PER_ITD-1)/MAX_TRNAS_PER_ITD;
    m_dwSchedTDIndex=0;
    m_dwArmedBufferIndex=0;
    m_dwArmedTDIndex = 0 ;
    m_dwFirstError =  USB_NO_ERROR;
    if (m_sTransfer.lpvBuffer &&  m_sTransfer.paBuffer && m_sTransfer.dwBufferSize) {
        // Allocate space for CITD List
        m_pCITDList =(CITD **) new PVOID[m_dwNumOfTD];
        if (m_pCITDList!=NULL) {
            memset(m_pCITDList,0,sizeof(CITD *)*m_dwNumOfTD);
            ArmTD();
            return TRUE;
        }
    }
    ASSERT(FALSE);
    return FALSE;
}
BOOL CITransfer::ScheduleTD(DWORD dwCurFrameIndex,DWORD /*dwCurMicroFrameIndex*/)
{
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer::ScheduleTD (this=0x%x,id=0x%x,curFrameIndex=0x%x)\r\n"),this,m_dwTransferID, dwCurFrameIndex));
    BOOL bReturn = FALSE;
    ArmTD();
    if (m_dwSchedTDIndex < m_dwNumOfTD && m_pCITDList !=0 && m_pCEhcd ) {
        if ((long)(dwCurFrameIndex - m_dwFrameIndexStart) > (long)m_dwSchedTDIndex) {
            m_dwSchedTDIndex = dwCurFrameIndex - m_dwFrameIndexStart;
        }
        m_dwSchedTDIndex = min( m_dwSchedTDIndex , m_dwNumOfTD);
        
        DWORD EndShedTDIndex = dwCurFrameIndex + (m_pCEhcd->GetPeriodicMgr()).GetFrameSize()-1;
        DWORD dwNumTDCanSched;
        if ( (long)(EndShedTDIndex - m_dwFrameIndexStart ) >= 0)
            dwNumTDCanSched =EndShedTDIndex - m_dwFrameIndexStart ;
        else  // Too Early.
            dwNumTDCanSched = 0;
        dwNumTDCanSched= min(m_dwNumOfTD ,dwNumTDCanSched);
        dwNumTDCanSched = min (m_dwArmedTDIndex, dwNumTDCanSched);
        if (m_dwSchedTDIndex < dwNumTDCanSched) { // Do scudule those index.            
            for (DWORD dwIndex = m_dwSchedTDIndex ; dwIndex<dwNumTDCanSched; dwIndex++) {
                m_pCEhcd->PeriodQueueITD(*(m_pCITDList+dwIndex),m_dwFrameIndexStart + dwIndex );
                (*(m_pCITDList+dwIndex))->CheckStructure ();
                ASSERT((*(m_pCITDList+dwIndex))->m_pTrans == this);
            }
            m_dwSchedTDIndex = dwNumTDCanSched;
            bReturn = TRUE;
        }
    }
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer::ScheduleTD (this=0x%x) return %d\r\n"),this,bReturn));
    return bReturn;
}
BOOL CITransfer::IsTransferDone(DWORD dwCurFrameIndex,DWORD /*dwCurMicroFrameIndex*/)
{
    // Dequeue those TD has Transfered.
    m_dwLastFrameIndex = dwCurFrameIndex - m_dwFrameIndexStart;
    if ((long)(dwCurFrameIndex - m_dwFrameIndexStart)>= 1 ) {
        DWORD dwTransfered = min(dwCurFrameIndex - m_dwFrameIndexStart , m_dwSchedTDIndex);
        for (DWORD dwIndex=m_dwDequeuedTDIndex;dwIndex<dwTransfered && dwIndex<m_dwNumOfTD ; dwIndex++) {
            if ( *(m_pCITDList+dwIndex) != NULL ) {
                ASSERT((*(m_pCITDList+dwIndex))->m_pTrans == this);
                BOOL bResult =m_pCEhcd->PeriodDeQueueTD((*(m_pCITDList+dwIndex))->GetPhysAddr(),dwIndex + m_dwFrameIndexStart);
                ASSERT(bResult == TRUE);
                (*(m_pCITDList + dwIndex) )->SetLinkValid(FALSE);
                (*(m_pCITDList+ dwIndex))->CheckStructure ();
                DWORD dwFrameIndex = dwIndex * MAX_TRNAS_PER_ITD;
                
                for (DWORD dwTrans=0; dwTrans<MAX_TRNAS_PER_ITD && dwFrameIndex< m_sTransfer.dwFrames; dwTrans++) {
                    DWORD dwTDError= USB_NO_ERROR;
                    if ((*(m_pCITDList + dwIndex))->iTD_StatusControl[dwTrans].iTD_SCContext.Active!=0) 
                        dwTDError = USB_NOT_COMPLETE_ERROR;
                    else
                    if ((*(m_pCITDList + dwIndex))->iTD_StatusControl[dwTrans].iTD_SCContext.XactErr!=0) 
                        dwTDError = USB_ISOCH_ERROR;
                    else
                    if ((*(m_pCITDList + dwIndex))->iTD_StatusControl[dwTrans].iTD_SCContext.BabbleDetected!=0) 
                        dwTDError = USB_STALL_ERROR;
                    else
                    if ((*(m_pCITDList + dwIndex))->iTD_StatusControl[dwTrans].iTD_SCContext.DataBufferError!=0) 
                        dwTDError = ((m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0?USB_DATA_OVERRUN_ERROR:USB_DATA_UNDERRUN_ERROR);
                        
                    if (m_dwFirstError == USB_NO_ERROR   ) { // only update first time
                        m_dwFirstError = dwTDError;
                    }
                    
                    DWORD dwTransLength =(*(m_pCITDList + dwIndex))->iTD_StatusControl[dwTrans].iTD_SCContext.TransactionLength;
                    if (dwFrameIndex< m_sTransfer.dwFrames) {
                        DWORD dwOldPermissions =  SetProcPermissions(m_dwCurrentPermissions);
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
                        __try { // setting isoch OUT status parameters
                            m_sTransfer.adwIsochErrors[ dwFrameIndex ] = dwTDError;
                            // Document said length is only update for Isoch IN 3.3.2
                            m_sTransfer.adwIsochLengths[ dwFrameIndex ] = ((m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0?
                                    dwTransLength :  *(m_sTransfer.aLengths + dwFrameIndex ));
                            m_DataTransferred += m_sTransfer.adwIsochLengths[ dwFrameIndex ];
                        } __except( EXCEPTION_EXECUTE_HANDLER ) {
                        }
#pragma prefast(pop)
                        SetProcPermissions(dwOldPermissions);
                    }
                    dwFrameIndex ++;

                }
                GetPipe()->FreeCITD(*(m_pCITDList + dwIndex));
                *(m_pCITDList + dwIndex) = NULL;
            }
        }
        m_dwDequeuedTDIndex = dwIndex;
    }
    BOOL bReturn = ((long)(dwCurFrameIndex-m_dwFrameIndexStart)>= (long)m_dwNumOfTD);
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer:::IsTransferDone (this=0x%x,curFrameIndex=0x%x) return %d \r\n"),this, dwCurFrameIndex,bReturn));
    return bReturn;
}
BOOL CITransfer::AbortTransfer()
{
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer::AbortTransfer (this=0x%x,id=0x%x) \r\n"),this,m_dwTransferID));
    for (DWORD dwIndex=m_dwDequeuedTDIndex;dwIndex < m_dwNumOfTD && dwIndex< m_dwSchedTDIndex; dwIndex++) {
        if ( *(m_pCITDList+dwIndex) != NULL) {
            BOOL bResult=m_pCEhcd->PeriodDeQueueTD((*(m_pCITDList+dwIndex))->GetPhysAddr(),dwIndex + m_dwFrameIndexStart);
            ASSERT(bResult == TRUE);
            (*(m_pCITDList + dwIndex) )->SetLinkValid(FALSE);
            
            DWORD dwFrameIndex = dwIndex * MAX_TRNAS_PER_ITD;            
            for (DWORD dwTrans=0; dwTrans<MAX_TRNAS_PER_ITD && dwFrameIndex< m_sTransfer.dwFrames; dwTrans++) {
                if (dwFrameIndex< m_sTransfer.dwFrames) {
                    DWORD dwOldPermissions =  SetProcPermissions(m_dwCurrentPermissions);
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
                    __try { // setting isoch OUT status parameters
                        m_sTransfer.adwIsochErrors[ dwFrameIndex ] = USB_NOT_COMPLETE_ERROR;;
                        m_sTransfer.adwIsochLengths[ dwFrameIndex ] = 0;
                    } __except( EXCEPTION_EXECUTE_HANDLER ) {
                    }
#pragma prefast(pop)
                    SetProcPermissions(dwOldPermissions);
                }
                dwFrameIndex ++;
            }
            if (m_dwFirstError == USB_NO_ERROR   ) { // only update first time
                m_dwFirstError = USB_NOT_COMPLETE_ERROR;
            }
        }
    }
    m_dwDequeuedTDIndex = m_dwSchedTDIndex = m_dwNumOfTD;
    Sleep(2); // Make Sure EHCI nolong reference to those TD;
    return DoneTransfer(m_dwFrameIndexStart+m_dwNumOfTD, 0);
};
BOOL CITransfer::DoneTransfer(DWORD dwCurFrameIndex,DWORD dwCurMicroFrameIndex)

⌨️ 快捷键说明

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