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

📄 cpipe.cpp

📁 Xcale270Bsp包,wince平台
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                m_pDummyTd.td->bfDiscard = 1;
                for (int i = 1; i < m_transfer.numTDsInList; ++i) {
                    m_transfer.vaTDList.td[i].bfDiscard = 1;
                }
                // We need to complete the transfer ourselves
                m_pED->paTdQueueHead = m_pED->paTdQueueTail = GetTDPhysAddr( m_pDummyTd.td );
                m_pED->bfSkip = 0;
                pTransfer = &m_transfer;
            }
        } else {
            // Transfer is not the current one so just nuke it from the list of pending transfers
            for (pTransfer = &m_transfer;
                 pTransfer != NULL && pTransfer->lpvCancelId != lpvCancelId;
                 pTransfer = pTransfer->lpNextTransfer)
                if (pTransfer->lpNextTransfer == m_pLastTransfer)
                    // if anything gets removed, it'll be the last one in the list;
                    // otherwise, we'll need to reset this later.
                    m_pLastTransfer = pTransfer;
            if (pTransfer == NULL && m_pLastTransfer->lpNextTransfer != NULL)
                // oops - didn't find one, so reset my state
                m_pLastTransfer = m_pLastTransfer->lpNextTransfer;
        }
    }
    
    if ( pTransfer != NULL ) {
        DEBUGCHK( pTransfer->lpvCancelId == lpvCancelId );
        DEBUGCHK( AreTransferParametersValid(pTransfer) );

        DWORD dwOldPermissions =  SetProcPermissions(m_transfer.dwCurrentPermissions);
        __try { // accessing caller's memory  
            *pTransfer->lpdwError = USB_CANCELED_ERROR;
            *pTransfer->lpfComplete = TRUE;
            *pTransfer->lpdwBytesTransferred = 0;
        } __except( EXCEPTION_EXECUTE_HANDLER ) {
        }
        SetProcPermissions(dwOldPermissions);

        // cache the callback info because *pTransfer will be transmogrified
        LPTRANSFER_NOTIFY_ROUTINE lpfnCompletion = pTransfer->lpfnCallback;
        LPVOID                    lpvParam = pTransfer->lpvCallbackParameter;

        STransfer *pNext = pTransfer->lpNextTransfer;
        if (pNext == m_pLastTransfer)
            m_pLastTransfer = pTransfer;
        FreeTransferMemory(pTransfer);
        if (pNext) {
            *pTransfer = *pNext; // yes, yes, it's a copy.
            delete pNext;
        } else {
            if (m_pLastTransfer == pTransfer) {
                // this is the only transfer in the queue
                DEBUGCHK( pTransfer == &m_transfer );
                m_fTransferInProgress = FALSE;
                m_pLastTransfer = NULL;
            } else {
                DEBUGCHK( m_pLastTransfer->lpNextTransfer == pTransfer );
                m_pLastTransfer->lpNextTransfer = NULL;
            }
        }
        // from this point on, pTransfer is no longer what it was.

        if (pTransfer == &m_transfer && m_pLastTransfer != NULL)
                ScheduleTransfer();
    
        // ok, transfer has been aborted. Perform callback if needed.
        if ( lpfnCompletion ) {
            __try { // calling the transfer complete callback
                ( *lpfnCompletion )( lpvParam );
            } __except( EXCEPTION_EXECUTE_HANDLER ) {
                  DEBUGMSG( ZONE_ERROR, (TEXT("CQueuedPipe::AbortTransfer - exception executing completion callback function\n")) );
            }
        }
        if ( lpCancelAddress ) {
            __try { // calling the Cancel function
                ( *lpCancelAddress )( lpvNotifyParameter );
            } __except( EXCEPTION_EXECUTE_HANDLER ) {
                  DEBUGMSG( ZONE_ERROR, (TEXT("CQueuedPipe::AbortTransfer - exception executing cancellation callback function\n")) );
            }
        }
        status = requestOK;
    }

    LeaveCriticalSection( &m_csPipeLock );
    DEBUGMSG( ZONE_TRANSFER, (TEXT("-CQueuedPipe(%s)::AbortTransfer - lpvCancelId = 0x%x, returning HCD_REQUEST_STATUS %d\n"), GetPipeType(), lpvCancelId, status) );
    return status;
}

// ******************************************************************               
// Scope: private
void  CQueuedPipe::AbortQueue( void ) 
//
// Purpose: Abort the current transfer (i.e., queue of TDs).
//
// Parameters: pQH - pointer to Queue Head for transfer to abort
//
// Returns: Nothing
//
// Notes: not used for OHCI
// ******************************************************************
{
    DEBUGCHK(0);
}

// ******************************************************************               
// Scope: protected (Implements CPipe::CheckForDoneTransfers = 0)
BOOL CQueuedPipe::CheckForDoneTransfers( void )
//
// Purpose: Check if the transfer on this pipe is finished, and 
//          take the appropriate actions - i.e. remove the transfer
//          data structures and call any notify routines
//
// Parameters: None
//
// Returns: TRUE if transfer is done, else FALSE
//
// Notes:
// ******************************************************************
{
    DEBUGMSG( ZONE_TRANSFER, (TEXT("+CQueuedPipe(%s)::CheckForDoneTransfers\n"), GetPipeType() ) );

    EnterCriticalSection( &m_csPipeLock );

    DEBUGMSG( ZONE_TRANSFER && !m_fTransferInProgress, (TEXT("CQueuedPipe(%s)::CheckForDoneTransfers - queue was already finished on entry\n"), GetPipeType() ) );

    DEBUGCHK( m_fTransferInProgress );

    if ( m_fTransferInProgress ) {
        // this is the normal case where we want to check if the queue is done
        // and take appropriate action

        // Shortcut exit if the transfer is still in progress
        if (m_transfer.numTDsComplete < m_transfer.numTDsInList && !m_pED->bfHalted) {
            LeaveCriticalSection( &m_csPipeLock );
            return FALSE;
        }
        
        DEBUGCHK( AreTransferParametersValid() );

        DWORD dwUsbError = USB_NO_ERROR;
        DWORD dwDataTransferred = m_transfer.dwBufferSize;

        if (m_pED->bfHalted) {
            // Generally, the endpt is halted only on error, but we could get
            // here also as the result of an allowable short packet on a TD
            // other than the last one. This can only happen with transfers
            // large enough to require >1 TD. If that's the case then fast-forward
            // the ED and clear the halted bit. Then we can process the completion normally.
            //
            // WARNING: Because the ED is updated by the HC independently of the done queue,
            // it is possible to wind up here before the errored TD has made it onto the
            // the done queue. If that happens, just return and wait for the next frame,
            // by which time the errored TD should have become fully retired.
            //
            // DANGER: We don't distinguish pipe types here so this code won't
            // properly deal with control transfers (because of the status stage).
            // That means that large control IN transfers cannot be short!
            //
            P_TD pTD = m_pDummyTd.td;  // this is first due to mechanics of transfer insertion
            {
                DWORD iTD = 1;
                while (pTD->bfConditionCode == USB_NO_ERROR) {
                    pTD = pTD->pNextTd;
                    DEBUGCHK( pTD != NULL && pTD->bfConditionCode != USB_NOT_ACCESSED_ERROR ); // there must be an errored TD somewhere
                    ++iTD;
                }
                if (iTD > m_transfer.numTDsComplete) {
                    LeaveCriticalSection( &m_csPipeLock );
                    return FALSE;
                }
            }
            
            DEBUGCHK( pTD->bfConditionCode != USB_NO_ERROR );
            if (pTD->paCurBuffer != 0 && pTD->bfPID != TD_SETUP_PID)
                dwDataTransferred = pTD->paCurBuffer - m_transfer.paActualBuffer;
            else
                dwDataTransferred = 0;
            if (pTD->bfConditionCode == USB_DATA_UNDERRUN_ERROR && (m_transfer.dwFlags & USB_SHORT_TRANSFER_OK)) {
                // OK, this one's just short.
                DEBUGCHK( dwDataTransferred < m_transfer.dwBufferSize ); // NOT "<="
                m_pED->paTdQueueHead = m_pED->paTdQueueTail; // indicates emptiness
                m_pED->bfHalted = 0; // let the HC process the ED again
            } else {
                // This is really an error.
                dwUsbError = pTD->bfConditionCode;
                DEBUGMSG( ZONE_WARNING, (TEXT("CQueuedPipe(%s)::CheckForDoneTransfers - failure on TD 0x%x, address = %d, endpoint = %d, status field = 0x%x\n"), GetPipeType(), pTD, m_bBusAddress, m_bEndpointAddress, dwUsbError ) );
                if (m_pED->bfEndpointNumber != 0)
                    m_fIsHalted = TRUE;
            }
#ifdef DEBUG
            // Verify that the rest of the TDs (if any) are still pristine
            for (pTD = pTD->pNextTd; pTD != NULL; pTD = pTD->pNextTd)
                DEBUGCHK( pTD->bfConditionCode == USB_NOT_ACCESSED_ERROR );
#endif // DEBUG
        } else if (m_transfer.dwFlags & USB_SHORT_TRANSFER_OK) {
            // A short transfer can still complete without halting the EP if it was
            // expected and if the last TD in the transfer is the short one.
            // We could assert here that this was an IN transfer.
            int iLast = m_transfer.numTDsComplete - 1;
            DEBUGCHK( iLast >= 0 );
            P_TD pTD = iLast ? &m_transfer.vaTDList.td[iLast] : m_pDummyTd.td;
            if (pTD->paCurBuffer)
                dwDataTransferred = pTD->paCurBuffer - m_transfer.paActualBuffer;
        }

        // Regardless of success or failure, copy the transferred data.
        // IN transfer where client did not specify a buffer
        // for us to DMA into. Thus, we created our own internal
        // buffer, and now need to copy the data.
        if ( (m_transfer.dwFlags & USB_IN_TRANSFER) &&
             m_transfer.paClientBuffer == 0 ) {
            DEBUGCHK( m_transfer.lpvClientBuffer != NULL &&
                      m_transfer.paActualBuffer != 0 &&
                      m_transfer.vaActualBuffer != NULL );

            DWORD dwOldPermissions = SetProcPermissions(m_transfer.dwCurrentPermissions);
            __try {
                memcpy( PUCHAR( m_transfer.lpvClientBuffer ), m_transfer.vaActualBuffer, dwDataTransferred );
				RETAILMSG(RETAIL_ZONE_PIPE,(TEXT("CQPipe::CFDT: va: %08x pa: %08x ln: %2d to %08x: "), m_transfer.vaActualBuffer, m_transfer.paActualBuffer, dwDataTransferred, m_transfer.lpvClientBuffer ));
#if 0
				{
					int	len = dwDataTransferred;
					int	i;

					if( len > 16 ) len = 16;
					if( len < 0 ) len = 0;


					for( i = 0; i < len; i++ ){
						RETAILMSG(RETAIL_ZONE_PIPE,(TEXT("%02x "), m_transfer.vaActualBuffer[i] ));
					}
					RETAILMSG(RETAIL_ZONE_PIPE,(TEXT("\r\n")));
				}
#endif
            } __except( EXCEPTION_EXECUTE_HANDLER ) {
                dwDataTransferred = 0;
                if (dwUsbError == USB_NO_ERROR)
                    dwUsbError = USB_CLIENT_BUFFER_ERROR;
            }
            SetProcPermissions(dwOldPermissions);
        }

        m_fTransferInProgress = FALSE;
        
        DEBUGMSG(ZONE_TRANSFER, (TEXT("CQueuedPipe::CheckForDoneTransfers: completing xfr %08x at %08x\n"), m_transfer.vaTDList.td[0].pTransfer, &m_transfer));

        // the TDs/Buffers associated with the transfer
        // can now be freed and the ED reset
        FreeTransferMemory();
        m_pED->bfSkip = 1;
		RETAILMSG(RETAIL_ZONE_PIPE,(TEXT("CQPipe::CFDT: Waiting one frame.\r\n")));
        CHW::WaitOneFrame();  //JEFFRO: need to find a way around this
		RETAILMSG(RETAIL_ZONE_PIPE,(TEXT("CQPipe::CFDT: Waiting done.\r\n")));
        DWORD toggleCarry = m_pED->bfToggleCarry; // this field is actually part of QueueHead
        m_pED->paTdQueueHead = m_pED->paTdQueueTail = GetTDPhysAddr( m_pDummyTd.td );
        m_pED->bfToggleCarry = toggleCarry;
        m_pED->bfHalted = m_fIsHalted ? 1 : 0;
        m_pED->bfSkip = 0;

        DWORD dwOldPermissions =  SetProcPermissions(m_transfer.dwCurrentPermissions);
        __try { // setting transfer status and executing callback function
            *m_transfer.lpfComplete = TRUE;
            *m_transfer.lpdwError = dwUsbError;
            *m_transfer.lpdwBytesTransferred = dwDataTransferred;
            if ( m_transfer.lpfnCallback ) {
				RETAILMSG(RETAIL_ZONE_PIPE,(TEXT("CQPipe::CFDT: Calling %08x with %08x.\r\n"), m_transfer.lpfnCallback, m_transfer.lpvCallbackParameter));
                ( *m_transfer.lpfnCallback )( m_transfer.lpvCallbackParameter );
				RETAILMSG(RETAIL_ZONE_PIPE,(TEXT("CQPipe::CFDT: Calling done.\r\n")));
            }
			else
			{
				RETAILMSG(RETAIL_ZONE_PIPE,(TEXT("CQPipe::CFDT: No completion routine on transfer to call.\r\n")));
			}

        } __except( EXCEPTION_EXECUTE_HANDLER ) {
            DEBUGMSG( ZONE_ERROR, (TEXT("CQueuedPipe(%s)::CheckForDoneTransfers - exception setting transfer status to complete\n"), GetPipeType() ) );
        }
        SetProcPermissions(dwOldPermissions);

        // this transfer is now officially done; are more pending?
        STransfer *pNext = m_transfer.lpNextTransfer;
        if (pNext) {
            DEBUGCHK(m_pLastTransfer != NULL);
            if (pNext == m_pLastTransfer)
                m_pLastTransfer = &m_transfer;
            m_transfer = *pNext;    // copy for historical reasons; will fix someday.
            delete pNext;

            // and note that a transfer is still in progress (albeit a new one)
            m_fTransferInProgress = TRUE;
            ScheduleTransfer();
        } else {
            // this queue is now done - clean up and remove the transfer
            DEBUGMSG( ZONE_TRANSFER, (TEXT("CQueuedPipe(%s)::CheckForDoneTransfers - queue was processed and is now finished\n"), GetPipeType() ) );
            DEBUGCHK(m_pLastTransfer == &m_transfer);
            m_fTransferInProgress = FALSE;
            m_pLastTransfer = NULL;
#ifdef DEBUG
            

⌨️ 快捷键说明

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