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

📄 trans.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    CQTD * pPrevTD=m_pCQTDList;
    if ( m_pCQTDList==NULL  && m_sTransfer.dwBufferSize == 0 ) { // No Control but Zero Length
        ASSERT((m_sTransfer.dwFlags & USB_IN_TRANSFER)==0);// No meaning for IN Zero length packet.
        CQTD * pCurTD = new( m_pCPhysMem) CQTD(this, ((CQueuedPipe * const)m_pCPipe)->GetQHead());
        if (pCurTD) {            
            PhysBufferArray bufferArray;
            bufferArray.dwNumOfBlock=0;
            bufferArray.dwBlockSize=0;
            bufferArray.dwStartOffset=0;
            bufferArray.dwArrayBlockAddr[0]=0;
            bufferArray.dwArrayBlockAddr[1]=0;// Terminate
            pCurTD->IssueTransfer( (m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0? TD_IN_PID: TD_OUT_PID,
                bDataToggle1, 0 ,&bufferArray,TRUE);
            if (pPrevTD) {
                pPrevTD->QueueNextTD(pCurTD);
                pPrevTD=pCurTD;
            }
            else { // THis is First. So update m_pQTDList
                pPrevTD= m_pCQTDList = pCurTD;
            }
        }
        else {
            if ( pStatusTD) {
                pStatusTD->~CQTD();
                m_pCPhysMem->FreeMemory((PBYTE)pStatusTD,m_pCPhysMem->VaToPa((PBYTE)pStatusTD), CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK );
            }
            return FALSE;                
        }
    }
    else
    if (m_sTransfer.lpvBuffer &&  m_sTransfer.paBuffer && m_sTransfer.dwBufferSize) {
        DWORD dwCurPos=0;
        while ( dwCurPos< m_sTransfer.dwBufferSize) {
            CQTD * pCurTD = new( m_pCPhysMem) CQTD(this, ((CQueuedPipe * const)m_pCPipe)->GetQHead());
            ASSERT(pCurTD!=NULL);
            if (pCurTD==NULL) {
                // delete  pStatusTD;
                if ( pStatusTD) {
                    pStatusTD->~CQTD();
                    m_pCPhysMem->FreeMemory((PBYTE)pStatusTD,m_pCPhysMem->VaToPa((PBYTE)pStatusTD), CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK );
                }
                return FALSE;                
            }                
            DWORD dwCurPhysAddr=  m_sTransfer.paBuffer + dwCurPos;
            // We only can queue maximun 4 page for one TD and  Align with Packet Size.
            // Note: Even though we can limit to 16K, but if start offset != 0, it would require 5 buffer pointers, instead of 4.
            DWORD dwPacketSize= (m_pCPipe->GetEndptDescriptor()).wMaxPacketSize & 0x7ff;
            ASSERT(dwPacketSize!=0);
            DWORD dwCurLength = ((EHCI_PAGE_SIZE * MAX_QTD_PAGE_SIZE)/dwPacketSize)*dwPacketSize;            
            dwCurLength = min( m_sTransfer.dwBufferSize- dwCurPos,dwCurLength);
            PhysBufferArray bufferArray;
            bufferArray.dwStartOffset= dwCurPhysAddr & EHCI_PAGE_OFFSET_MASK;
            bufferArray.dwNumOfBlock=  (bufferArray.dwStartOffset + dwCurLength + EHCI_PAGE_SIZE -1 ) /EHCI_PAGE_SIZE;          
            ASSERT(bufferArray.dwNumOfBlock<=(MAX_QTD_PAGE_SIZE+1) && bufferArray.dwNumOfBlock!=0);            
            bufferArray.dwBlockSize = min (bufferArray.dwStartOffset + m_sTransfer.dwBufferSize- dwCurPos,EHCI_PAGE_SIZE);
            
            for (DWORD dwIndex=0;dwIndex<bufferArray.dwNumOfBlock+1 && dwIndex<5;dwIndex++) {
                bufferArray.dwArrayBlockAddr[dwIndex] = (dwCurPhysAddr & EHCI_PAGE_ADDR_MASK);
                dwCurPhysAddr += EHCI_PAGE_SIZE;
            }
            DWORD dwReturnLength = pCurTD->IssueTransfer( (m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0?TD_IN_PID:TD_OUT_PID,
                bDataToggle1, dwCurLength,&bufferArray,TRUE);
            ASSERT(dwReturnLength == dwCurLength);

            // Setup for Short Packet
            if ( pStatusTD) {
                pCurTD->SetAltNextQTDPointer(pStatusTD->GetPhysAddr());
            }
            
            DWORD dwNumOfPacket = (dwReturnLength + dwPacketSize-1)/dwPacketSize;
            
            dwCurPos += dwReturnLength;
            if (pPrevTD) {
                pPrevTD->QueueNextTD(pCurTD);
                pPrevTD=pCurTD;
            }
            else { // THis is First. So update m_pQTDList
                pPrevTD= m_pCQTDList = pCurTD;
            }
            if ((dwNumOfPacket & 1)!=0) // if it is odd packet number. Toggle the data toggle.
                bDataToggle1 = !bDataToggle1;
        }
    }
    // We have to append Status TD here.
    if (pStatusTD) { // This is setup packet.
        if (pPrevTD) {
            pPrevTD->QueueNextTD(pStatusTD);
            pPrevTD=pStatusTD;
        }
        else { // Something Wrong.
            ASSERT(FALSE);
            //delete pCurTD;
            pStatusTD->~CQTD();
            m_pCPhysMem->FreeMemory((PBYTE)pStatusTD,m_pCPhysMem->VaToPa((PBYTE)pStatusTD), CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK  );
            return FALSE;
        }
    };
    return TRUE;    
}

//***********************************************************************************************
BOOL CQTransfer::DoneTransfer()
//
// Purpose: Check if transfer is done and success, acknowledge back into MDD
//
// Parameters: None
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CQTransfer::DoneTransfer (this=0x%x,id=0x%x)\r\n"),this,m_dwTransferID));
    BOOL bIsTransDone = IsTransferDone();
    ASSERT(bIsTransDone == TRUE);
    if (bIsTransDone && !m_fDoneTransferCalled) {
        DWORD dwUsbError = USB_NO_ERROR;
        DWORD dwDataNotTransferred = 0;
        m_fDoneTransferCalled = TRUE;
        
        CQTD * pCurTD = m_pCQTDList;
        BOOL bReturn=TRUE;
        while ( pCurTD!=NULL) {
            pCurTD->CheckStructure();
            if (  pCurTD->qTD_Token.qTD_TContext.PID != 2) // Do not count Setup TD
                dwDataNotTransferred +=  pCurTD ->qTD_Token.qTD_TContext.BytesToTransfer ;
            if (pCurTD->qTD_Token.qTD_TContext.Halted==1) { // This Transfer Has been halted due to error.
                // This is error. We do not have error code for EHCI so generically we set STALL error.
                if (pCurTD->qTD_Token.qTD_TContext.BabbleDetected) {// Babble.
                    dwUsbError = USB_DATA_OVERRUN_ERROR ;
                }
                else if (pCurTD->qTD_Token.qTD_TContext.DataBufferError) {
                    dwUsbError = ((m_sTransfer.dwFlags &USB_IN_TRANSFER)!=0? USB_BUFFER_OVERRUN_ERROR : USB_BUFFER_UNDERRUN_ERROR);
                }
                else  if (dwUsbError == USB_NO_ERROR)
                    dwUsbError = USB_STALL_ERROR;
            }
            else
            if (pCurTD->qTD_Token.qTD_TContext.Active ==1) {
                if (dwUsbError == USB_NO_ERROR) 
                    dwUsbError = USB_NOT_COMPLETE_ERROR;
                break;
            }
            pCurTD = pCurTD->GetNextTD();
        }
        ASSERT(dwDataNotTransferred <= m_sTransfer.dwBufferSize);
        if (dwDataNotTransferred >= m_sTransfer.dwBufferSize)
            dwDataNotTransferred = m_sTransfer.dwBufferSize;
        m_DataTransferred = m_sTransfer.dwBufferSize -  dwDataNotTransferred ;

        // We have to update the buffer when this is IN Transfer.
        if ((m_sTransfer.dwFlags & USB_IN_TRANSFER)!=NULL && m_pAllocatedForClient!=NULL && m_sTransfer.dwBufferSize!=0) {
            __try { // copying client buffer for OUT transfer
                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;
            }
        }
        if (m_fCanceled && dwUsbError == USB_NO_ERROR) {
            dwUsbError = USB_CANCELED_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() ) );
        }

        return (dwUsbError==USB_NO_ERROR);
    }
    else
        return TRUE;
}

//**********************************************************************************
BOOL CQTransfer::AbortTransfer()
//
// Purpose: Abort the current transfer
//
// Parameters: None
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
    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();
    }
    m_fCanceled = TRUE;
    Sleep(2);// Make sure the shcdule has advanced. and current Transfer has completeded.
    return TRUE;
}

//*********************************************************************
BOOL CQTransfer::IsTransferDone()
//
// Purpose: This is to read the current transfer descriptor and see if there is 
//          any error or if the transfer is still active.
//
// Parameters: None
//
// Returns: TRUE - completed, FALSE - not completed
//
// Notes:
// ******************************************************************
{
    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.XactErr == 1) 
            RETAILMSG(1, (TEXT("TD Token: XactErr\r\n")));

        if (pCurTD->qTD_Token.qTD_TContext.DataBufferError == 1)
        {
            if ((m_sTransfer.dwFlags & USB_IN_TRANSFER) != 0x00)
                RETAILMSG(1, (TEXT("TD Token: DataBufferError in IN\r\n")));
            else
                RETAILMSG(1, (TEXT("TD Token: DataBufferError in OUT\r\n")));
        }

        if (pCurTD->qTD_Token.qTD_TContext.Halted==1) { // This Transfer Has been halted due to error.
            RETAILMSG(1, (TEXT("CQTransfer: Halted\r\n")));
            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)
//
// Purpose: Constructor of CIsochTransfer 
//
// Parameters: 
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
    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)
//
// Purpose: Constructor of High Speed Isochronous Transfer
//
// Parameters: 
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
    m_pCITDList =0;
}

//*******************************************************************
CITransfer::~CITransfer()
//
// Purpose: Destructor of High Speed Isochronous Transfer
//
// Parameters: 
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
    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;
    }
}

⌨️ 快捷键说明

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