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

📄 cpipe.cpp

📁 Latest USB 802.3, HID printer and mass storage divers from Microsoft for Platform Builder 4.2.
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    if (MaxLength == (DWORD)-1) {
        // zero-length transfer
        pTD->paCurBuffer = 0;
        pTD->paBufferEnd = 0;
    } else {
        DEBUGCHK( MaxLength <= 0x2000 /*8K*/ );
        pTD->paCurBuffer = paBuffer;
        pTD->paBufferEnd = paBuffer+MaxLength;
    }
}

// ******************************************************************               
// Scope: public
CQueuedPipe::CQueuedPipe( IN const LPCUSB_ENDPOINT_DESCRIPTOR lpEndpointDescriptor,
                          IN const BOOL fIsLowSpeed,
                          IN const UCHAR bDeviceAddress,
                          IN CUhcd * const pCUhcd)
//
// Purpose: Constructor for CQueuedPipe
//
// Parameters: See CPipe::CPipe
//
// Returns: Nothing
//
// Notes: Do not modify static variables here!!
// ******************************************************************
: CPipe( lpEndpointDescriptor, fIsLowSpeed, bDeviceAddress,pCUhcd )   // constructor for base class
, m_fIsReclamationPipe( FALSE ) // this gets set to TRUE later as need arises
//, m_dataToggle( 1 ) // data toggle for this pipe
{
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CQueuedPipe::CQueuedPipe\n")) );
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CQueuedPipe::CQueuedPipe\n")) );
}

// ******************************************************************               
// Scope: public virtual
CQueuedPipe::~CQueuedPipe( )
//
// Purpose: Destructor for CQueuedPipe
//
// Parameters: None
//
// Returns: Nothing
//
// Notes: Do not modify static variables here!!
// ******************************************************************
{
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CQueuedPipe::~CQueuedPipe\n")) );
    // queue should be freed via ClosePipe before calling destructor
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CQueuedPipe::~CQueuedPipe\n")) );
}

// ******************************************************************               
// Scope: public (Implements CPipe::ClosePipe = 0)
HCD_REQUEST_STATUS CQueuedPipe::ClosePipe( void )
//
// Purpose: Abort any transfers associated with this pipe, and
//          remove its data structures from the schedule
//
// Parameters: None
//
// Returns: requestOK
//
// Notes: 
// ******************************************************************
{
    HCD_REQUEST_STATUS status = requestOK;
    
    DEBUGMSG( ZONE_PIPE, (TEXT("+CQueuedPipe(%s)::ClosePipe\n"), GetPipeType() ) );

    // Don't enter CS before calling AbortTransfer, since
    // that function will need to leave the pipe CS
    // at a certain point to avoid deadlock, and
    // won't be able to do so if the CS is nested.

    while (m_fTransferInProgress)
        AbortTransfer( NULL, // callback function
                       NULL, // callback param
                       m_transfer.lpvCancelId );

    EnterCriticalSection( &m_csPipeLock );

    // transfer was either never issued, finished before we got to
    // this function, or aborted above.
    DEBUGCHK( !m_fTransferInProgress );

    m_pED->bfSkip = 1;
    m_pCUhcd->CHW::WaitOneFrame();

    ULONG *pNextPhys = GetListHead(FALSE);
    ULONG thisPhys = GetQHPhysAddr(m_pED);

    while (*pNextPhys != 0 && *pNextPhys != thisPhys) {
        P_ED pnext = (P_ED) m_pCUhcd->CHCCAera::m_pCPhysMem->PaToVa(*pNextPhys);
        pNextPhys = &pnext->paNextEd;
    }
    if (*pNextPhys == 0) {
        DEBUGMSG(ZONE_WARNING, (TEXT("!CQueuedPipe(%s)::ClosePipe %08x doesn't exist!\n"), GetPipeType(), m_pED));
        status = requestFailed;
    } else {
        DEBUGCHK( *pNextPhys == thisPhys );
        *pNextPhys = m_pED->paNextEd;
        DEBUGCHK( (m_pED->paTdQueueHead & ~3) == m_pED->paTdQueueTail );
        DEBUGCHK( (m_pED->paTdQueueHead & ~3) == m_pCUhcd->CHCCAera::m_pCPhysMem->VaToPa((PUCHAR)m_pDummyTd.td) );

        m_pCUhcd->CHCCAera::m_pCPhysMem->FreeMemory((PUCHAR)m_pDummyTd.td, m_pCUhcd->CHCCAera::m_pCPhysMem->VaToPa((PUCHAR)m_pDummyTd.td),
                                GetMemoryAllocationFlags());
        m_pDummyTd.td = 0;

        m_pCUhcd->CHCCAera::m_pCPhysMem->FreeMemory((PUCHAR)m_pED, m_pCUhcd->CHCCAera::m_pCPhysMem->VaToPa((PUCHAR)m_pED),
                                GetMemoryAllocationFlags());
        m_pED = 0;
    }

    (void) GetListHead(TRUE);
    LeaveCriticalSection( &m_csPipeLock );

    DEBUGMSG( ZONE_PIPE, (TEXT("-CQueuedPipe(%s)::ClosePipe\n"), GetPipeType() ) );
    return status;
}

// ******************************************************************               
// Scope: public (implements CPipe::AbortTransfer = 0)
HCD_REQUEST_STATUS CQueuedPipe::AbortTransfer( 
                                IN const LPTRANSFER_NOTIFY_ROUTINE lpCancelAddress,
                                IN const LPVOID lpvNotifyParameter,
                                IN LPCVOID lpvCancelId )
//
// Purpose: Abort any transfer on this pipe if its cancel ID matches
//          that which is passed in.
//
// Parameters: lpCancelAddress - routine to callback after aborting transfer
//
//             lpvNotifyParameter - parameter for lpCancelAddress callback
//
//             lpvCancelId - identifier for transfer to abort
//
// Returns: requestOK if transfer aborted
//          requestFailed if lpvCancelId doesn't match currently executing
//                 transfer, or if there is no transfer in progress
//
// Notes:
// ******************************************************************
{
    DEBUGMSG( ZONE_TRANSFER, (TEXT("+CQueuedPipe(%s)::AbortTransfer - lpvCancelId = 0x%x\n"), GetPipeType(), lpvCancelId) );

    HCD_REQUEST_STATUS status = requestFailed;
    STransfer         *pTransfer = 0;

    EnterCriticalSection( &m_csPipeLock );

    if (m_fTransferInProgress) {
        if (m_transfer.lpvCancelId == lpvCancelId) {
            // Now we need to ensure that the hardware is no longer accessing
            // the TDs which made up this transfer. Accomplish this by skipping
            // the ED, relinquishing the critsec, and waiting for the next frame.
            // At the start of the next frame, the WDH interrupt should fire and
            // that will cause the CFDT thread (which has higher priority than
            // whoever is calling AbortTransfer) to run. CFDT will flush leftover
            // TDs (and potentially complete the transfer pre-abortion).
            m_pED->bfSkip = 1;
            // Wait for all TDs being held by hardware are released.
            P_TD pTD;
            for(DWORD dwIndex=0;dwIndex<1000;dwIndex++) {
                LeaveCriticalSection( &m_csPipeLock );
                m_pCUhcd->CHW::WaitOneFrame();
                EnterCriticalSection( &m_csPipeLock );
                pTD = m_pDummyTd.td;
                if (m_fTransferInProgress && m_transfer.lpvCancelId == lpvCancelId) { // Still in the this transfer.
                    if ( m_transfer.numTDsComplete>0 && m_transfer.numTDsComplete < m_transfer.numTDsInList)
                        pTD =  &(m_transfer.vaTDList.td[m_transfer.numTDsComplete]);
                    if ( GetTDPhysAddr(pTD) == (m_pED->paTdQueueHead & ~3)) // No more outstanding TD
                        break;
                }
                else
                    break;
            }
            if (!m_fTransferInProgress || m_transfer.lpvCancelId != lpvCancelId) {
                // Too late; the transfer already completed.
                m_pED->bfSkip = 0;
                pTransfer = NULL;
            } else {
                ASSERT(GetTDPhysAddr(pTD) == (m_pED->paTdQueueHead & ~3));
                // Set the discard bit on any TDs not yet processed in the done queue
                // Since the CFDT thread has higher priority than this thread, the fact
                // that we are executing here means it's OK to tweak the bits.
                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:
// *****************************************************************

⌨️ 快捷键说明

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