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

📄 pipe.cpp

📁 It permits simultaneous use of multiple USB Serial protocols.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//

#include "pipe.h"
#include "ufnmdd.h"

static
inline
VOID
FreeTransfer(
    CFreeTransferList              *pFreeTransferList,
    PCUfnMddTransfer               pTransfer
    )
{
    SETFNAME();
    PREFAST_DEBUGCHK(pFreeTransferList);
    DEBUGCHK(pTransfer);
    
    DEBUGMSG(ZONE_TRANSFER, (_T("%s Freeing transfer 0x%08x\r\n"), 
        pszFname, pTransfer));

    pFreeTransferList->FreeTransfer(pTransfer);
}


CPipe::CPipe(
    DWORD dwPhysicalEndpoint, 
    PUFN_PDD_INTERFACE_INFO pPddInfo, 
    CFreeTransferList *pFreeTransferList
    ) : m_TransferQueue()
{
    DEBUGCHK(pPddInfo);
    DEBUGCHK(pFreeTransferList);
    
    InitializeCriticalSection(&m_cs);
    m_dwPhysicalEndpoint = dwPhysicalEndpoint;
    m_pPddInfo = pPddInfo;
    m_pFreeTransferList = pFreeTransferList;
    m_fOpen = FALSE;
    m_dwSig = UFN_PIPE_SIG;
    m_dwCompletionCount = 0 ;
    
    Reset();

#ifdef DEBUG
    m_dwThreadId = 0;
    m_dwLockCount = 0;
#endif
}


CPipe::~CPipe()
{
    DEBUGCHK(!IsOpen());
    DEBUGCHK(m_dwLockCount == 0);
    DeleteCriticalSection(&m_cs);
}


VOID 
CPipe::Reserve(
    UFN_BUS_SPEED Speed,
    BOOL fReserve, 
    DWORD dwInterfaceNumber,
    DWORD dwEndpointIndex, 
    PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc
    ) 
{
    Lock();

    PUSB_ENDPOINT_DESCRIPTOR *ppOurEndpointDesc;
    if (Speed == BS_FULL_SPEED) {
        ppOurEndpointDesc = &m_pFullSpeedEndpointDesc;
    }
    else {
        ppOurEndpointDesc = &m_pHighSpeedEndpointDesc;
    }
    
    if (fReserve) {
        m_dwReservedSpeedMask |= Speed;

        if (GetPhysicalEndpoint() != 0) {
            *ppOurEndpointDesc = pEndpointDesc;
            m_dwEndpointIndex = dwEndpointIndex;
            m_dwInterfaceNumber = dwInterfaceNumber;
        }
    }
    else {
        m_dwReservedSpeedMask &= ~Speed;
        *ppOurEndpointDesc = NULL;
        m_dwEndpointIndex = -1;
        m_dwInterfaceNumber = -1;
    }

    Unlock();
}


DWORD 
CPipe::Open(UFN_BUS_SPEED Speed, PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc)
{
    SETFNAME();
    DWORD dwRet;
    
    Lock();

    DEBUGCHK(m_TransferQueue.IsEmpty());
    DEBUGCHK(m_DoneTransferQueue.IsEmpty());
    DEBUGCHK(Speed & m_dwReservedSpeedMask);

    if (IsOpen()) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Pipe (0x%08x) is already opened\r\n"), pszFname, this));
        dwRet = ERROR_INVALID_PARAMETER;
    }
    else {
        PUSB_ENDPOINT_DESCRIPTOR pOurEndpointDesc;
        if (Speed == BS_FULL_SPEED) {
            pOurEndpointDesc = m_pFullSpeedEndpointDesc;
        }
        else {
            pOurEndpointDesc = m_pHighSpeedEndpointDesc;
        }

        if (pOurEndpointDesc == NULL) {
            DEBUGCHK(GetPhysicalEndpoint() == 0);
            DEBUGCHK(pEndpointDesc);
            pOurEndpointDesc = pEndpointDesc;
        }
        else {
            DEBUGCHK(GetPhysicalEndpoint() != 0);
            DEBUGCHK(pEndpointDesc == NULL);
        }
        
        dwRet = m_pPddInfo->pfnInitEndpoint(m_pPddInfo->pvPddContext, 
            m_dwPhysicalEndpoint, Speed, pOurEndpointDesc, NULL, 0, 0, 0);

        if (dwRet == ERROR_SUCCESS) {
            DEBUGMSG(ZONE_INIT || ZONE_PIPE, (_T("%s Opened pipe (0x%08x): physical address %u, bus address 0x%02x\r\n"),
                pszFname, this, m_dwPhysicalEndpoint, GetEndpointAddress()));
            m_fOpen = TRUE;
        }
        else {
            DEBUGMSG(ZONE_ERROR, (_T("%s Failed to open pipe (0x%08x): physical address %u, bus address 0x%02x\r\n"),
                pszFname, this, m_dwPhysicalEndpoint, GetEndpointAddress()));
        }
    }

    Unlock();

    return dwRet;
}


DWORD 
CPipe::Close() {
    SETFNAME();
    DWORD dwRet = ERROR_SUCCESS;
    
    Lock();

    if (IsOpen() == FALSE) {
        DEBUGMSG(ZONE_PIPE, (_T("%s Pipe (0x%08x): physical address %u is not open\r\n"), 
            pszFname, this, GetPhysicalEndpoint()));
        dwRet = ERROR_INVALID_HANDLE;
    }
    else {
        // We will say we are closed even if there was a failure
        m_fOpen = FALSE; 
        
        AbortAllTransfers();
    
        dwRet = m_pPddInfo->pfnDeinitEndpoint(m_pPddInfo->pvPddContext, m_dwPhysicalEndpoint);

        if (dwRet == ERROR_SUCCESS) {
            DEBUGMSG(ZONE_INIT || ZONE_PIPE, (_T("%s Closed pipe (0x%08x): physical address %u, bus address 0x%02x\r\n"),
                pszFname, this, m_dwPhysicalEndpoint, GetEndpointAddress()));
        }
        else {
            DEBUGMSG(ZONE_ERROR, (_T("%s Failed to close pipe (0x%08x): physical address %u, bus address 0x%02x\r\n"),
                pszFname, this, m_dwPhysicalEndpoint, GetEndpointAddress()));
        }

    }

    Unlock();
    
    return (dwRet == ERROR_SUCCESS);
}


VOID 
CPipe::AbortAllTransfers(
    )
{
    SETFNAME();
    Lock();
        
    while (m_TransferQueue.IsEmpty() == FALSE) {
        PCUfnMddTransfer pTransfer = m_TransferQueue.Back();
        pTransfer->Validate();
    
        DEBUGCHK(!pTransfer->IsComplete());
        DWORD dwErr = AbortTransfer(pTransfer);
        DEBUGCHK(dwErr == ERROR_SUCCESS);
    }

    Unlock();
}


DWORD 
CPipe::IssueTransfer(
    LPTRANSFER_NOTIFY_ROUTINE   lpNotifyRoutine,
    PVOID                       pvNotifyContext,
    DWORD                       dwFlags,
    DWORD                       cbBuffer, 
    PVOID                       pvBuffer,
    DWORD                       dwBufferPhysicalAddress,
    PCUfnMddTransfer           *ppTransfer,
    PVOID                       pvPddTransferInfo
    )
{
    SETFNAME();

    Lock();
    FUNCTION_ENTER_MSG();

    DEBUGCHK( (lpNotifyRoutine && pvNotifyContext) || 
              ( (lpNotifyRoutine == NULL) && (pvNotifyContext == NULL) ) );
    DEBUGCHK( (cbBuffer == 0) || (pvBuffer) );
    DEBUGCHK(ppTransfer);

    DWORD dwRet;
    BOOL fTransferOnQueue = FALSE;
    BOOL fStartTransfer = FALSE;
    PCUfnMddTransfer pTransfer = NULL;
    
    if (IsOpen() == FALSE) {
        DEBUGMSG(ZONE_WARNING, (_T("%s Pipe (0x%08x): physical address %u is not open\r\n"), 
            pszFname, this, GetPhysicalEndpoint()));
        dwRet = ERROR_INVALID_HANDLE;
        goto EXIT;
    }
    
    pTransfer = m_pFreeTransferList->AllocTransfer();
    if (pTransfer == NULL) {
        dwRet = GetLastError();
        DEBUGMSG(ZONE_ERROR, (_T("%s Failed to allocate new transfer. Error: %d\r\n"),
            pszFname, dwRet));
        goto EXIT;
    }

    pTransfer->Init(dwFlags, pvBuffer, dwBufferPhysicalAddress, cbBuffer,
        pvPddTransferInfo, lpNotifyRoutine, pvNotifyContext, this);
    pTransfer->AddRef();

    if (m_TransferQueue.IsEmpty()) {
        fStartTransfer = TRUE;
    }
    dwRet = m_TransferQueue.PushBack(pTransfer);
    
    if (dwRet != ERROR_SUCCESS) {
        goto EXIT;
    }

    pTransfer->AddRef();
    fTransferOnQueue = TRUE;

    __try {
        *ppTransfer = pTransfer;
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        RETAILMSG(1, (_T("%s Exception!\r\n"), pszFname));
        dwRet = ERROR_INVALID_PARAMETER;
    }

    if (dwRet != ERROR_SUCCESS) {
        goto EXIT;
    }

    DEBUGMSG(ZONE_TRANSFER, (_T("%s Issuing %s transfer (0x%08x) on ep %u (0x%02x) for %u bytes\r\n"),
        pszFname, 
        (pTransfer->GetDwFlags() & USB_REQUEST_DEVICE_TO_HOST) ? _T("IN") : _T("OUT"),
        pTransfer, GetPhysicalEndpoint(), GetEndpointAddress(), 
        pTransfer->GetCbBuffer()));

    if (fStartTransfer) {
        DEBUGCHK(pTransfer == m_TransferQueue.Front());
        pTransfer->EnteringPdd();
        dwRet = m_pPddInfo->pfnIssueTransfer(m_pPddInfo->pvPddContext, 
            GetPhysicalEndpoint(), pTransfer->GetPddTransfer());
        if (dwRet != ERROR_SUCCESS) {
            RETAILMSG(1, (_T("%s Could not start transfer 0x%08x\r\n"), 
                pszFname, pTransfer));
            pTransfer->LeavingPdd();
        }
    }

EXIT:
    if (pTransfer) {
        if (dwRet != ERROR_SUCCESS) {
            __try {
                *ppTransfer = NULL;
            }
            __except(EXCEPTION_EXECUTE_HANDLER) {
                DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
            }

            if (fTransferOnQueue) {
                // We must remove this transfer from the list.
                // Note that we've been holding the endpoint lock
                // this whole time so no one has taken the transfer off
                // the queue yet.
                DEBUGCHK(m_TransferQueue.Back() == pTransfer);
                m_TransferQueue.PopBack();
                pTransfer->Release();
            }
        }
        
        if (dwRet != ERROR_SUCCESS) {
            // Free the transfer
            pTransfer->Release();

⌨️ 快捷键说明

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