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

📄 ufnbus.cpp

📁 It permits simultaneous use of multiple USB Serial protocols.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// 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 "ufnbus.h"
#include "ufnmdd.h"
#include "ufnclient.h"
#include <devload.h>


CUfnBusDevice::CUfnBusDevice(
    LPCTSTR pszBusName,
    LPCTSTR pszRegPath,
    LPCTSTR pszDeviceBusName,
    LPCTSTR pszChildName,
    DWORD dwController,
    HANDLE hParent
    ) : 
        DeviceFolder(pszBusName, pszRegPath, Internal, 0, dwController, 
            0, hParent, 0, pszDeviceBusName)
{
    m_fValid = TRUE;
    
    HRESULT hr = StringCchCopy(m_szUfnName, dim(m_szUfnName), pszChildName);
    if (FAILED(hr)) {
        m_fValid = FALSE;
    }

    DEBUGCHK(m_fValid);
}

static
BOOL
GetUfnDescription(
    HKEY hkClient,
    LPTSTR pszDescription,
    DWORD  cchDescription
    )
{
    SETFNAME();

    DEBUGCHK(hkClient);
    PREFAST_DEBUGCHK(pszDescription);

    DWORD dwType;
    DWORD cbValue = sizeof(TCHAR) * cchDescription;
    DWORD dwError = RegQueryValueEx(hkClient, PSZ_REG_FRIENDLY_NAME, 
        NULL, &dwType, (PBYTE) pszDescription, &cbValue);
    pszDescription[cchDescription - 1] = 0; // Null-terminate

    if ( (dwError != ERROR_SUCCESS) || (dwType != REG_SZ) ) {
        // No description. Still return success, though.
        pszDescription[0] = 0;
        DEBUGMSG(ZONE_WARNING, (_T("%s No friendly name given for client\r\n"),
            pszFname));
    }

    return TRUE;
}
    
#define MAX_ENDPOINTS 0x1000 // arbitrary max endpoint count

static
DWORD
AllocEndpoints(
    PUFN_MDD_CONTEXT pContext
    )
{
    SETFNAME();
    DWORD dwRet = ERROR_SUCCESS;
    
    // Set up our pipe table
    DEBUGCHK(pContext->pPipes == NULL);
    DEBUGCHK(pContext->pFreeTransferList);

    // First guard against integer overflow
    if (pContext->PddInfo.dwEndpointCount > MAX_ENDPOINTS) {
        dwRet = ERROR_INVALID_PARAMETER;
        DEBUGMSG(ZONE_ERROR, (_T("%s Too many endpoints: %u\r\n"), pszFname, 
            pContext->PddInfo.dwEndpointCount));
    }
    else {    
        pContext->pPipes = (PCPipe) LocalAlloc(LPTR, 
            sizeof(CPipe) * pContext->PddInfo.dwEndpointCount);
        if (pContext->pPipes == NULL) {
            dwRet = GetLastError();
            DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d\r\n"), pszFname, 
                dwRet));
        }
        else {
            for (DWORD dwPipe = 0; dwPipe < pContext->PddInfo.dwEndpointCount; ++dwPipe) {
                PVOID pv = &pContext->pPipes[dwPipe];
                new (pv) CPipe(dwPipe, &pContext->PddInfo, pContext->pFreeTransferList);
            }
        }
    }

    return dwRet;
}


static
VOID
FreePipes(
    PUFN_MDD_CONTEXT pContext
    )
{
    PREFAST_DEBUGCHK(pContext->pPipes);
    
    for (DWORD dwPipe = 0; dwPipe < pContext->PddInfo.dwEndpointCount; ++dwPipe) {
        PCPipe pPipe = &pContext->pPipes[dwPipe];
        pPipe->~CPipe();
    }

    LocalFree(pContext->pPipes);
    pContext->pPipes = NULL;
}


CUfnBus::CUfnBus(
    LPCTSTR pszActivePath,
    UFN_MDD_CONTEXT *pContext
    ) :
        DefaultBusDriver(pszActivePath) 
{
    DEBUGCHK(pszActivePath);
    DEBUGCHK(pContext);
    
    m_pContext = pContext;
    m_dwControllerNumber = 0xFFFFFFFF;
    m_fIsChildPowerManaged = FALSE;
}


BOOL 
CUfnBus::Init(
    )
{
    SETFNAME();
    
    BOOL fRet = DefaultBusDriver::Init();
    
    if (fRet) {
        DEVMGR_DEVICE_INFORMATION ddi;
        ddi.dwSize = sizeof(ddi);
        if (!GetDeviceInformationByDeviceHandle(GetDeviceHandle(), &ddi)) {
            DEBUGMSG(ZONE_ERROR, (_T("%s Could not get device information. Error = %d\r\n"),
                pszFname, GetLastError()));
            fRet = FALSE;        
        }
        else {
            m_dwControllerNumber = (ddi.szLegacyName[3] - L'0');    
            HRESULT hr = StringCchPrintf(m_szClientBusName, dim(m_szClientBusName),
                TEXT("%s_%d_0"), UFN_BUS_PREFIX, m_dwControllerNumber);
            DEBUGCHK(SUCCEEDED(hr));
            fRet = TRUE;
        }
    }

    return fRet;
}


CUfnBus::~CUfnBus(
    )
{
    if (IsClientActive()) {
        DeactivateChild(m_szClientBusName);
    }
}
    

DWORD
CUfnBus::CreateChild(
    LPCTSTR pszChildName,
    CUfnBusDevice **ppDevice
    )
{
    SETFNAME();

    TCHAR szFullRegPath[MAX_PATH];
    DWORD dwRet;

    HRESULT hr = StringCchPrintf(szFullRegPath, dim(szFullRegPath), _T("%s\\%s"),
        PSZ_REG_CLIENT_DRIVER_PATH, pszChildName);
    if (FAILED(hr)) {
        dwRet = HRESULT_CODE(hr);
        RETAILMSG(1, (_T("%s Reg path too long for buffer. \"%s\\%s\"\r\n"),
            pszFname, PSZ_REG_CLIENT_DRIVER_PATH, pszChildName));
        goto EXIT;
    }
        
    DEBUGMSG(ZONE_INIT, (_T("%s Using client driver key \"%s\"\r\n"), pszFname,
        szFullRegPath));

    CUfnBusDevice *pDevice = new CUfnBusDevice(UFN_BUS_PREFIX, szFullRegPath, 
        m_szClientBusName, pszChildName, m_dwControllerNumber, GetDeviceHandle());
    if (!pDevice || !pDevice->Init()) {
        if (pDevice) {
            delete pDevice;
        }
        dwRet = ERROR_GEN_FAILURE;
        goto EXIT;
    }

    dwRet = ERROR_SUCCESS;
    *ppDevice = pDevice;

EXIT:
    return dwRet;
}


DWORD
CUfnBus::OpenFunctionKey(HKEY *phkFunctions)
{
    SETFNAME();
    
    DEBUGCHK(phkFunctions);
    
    // Determine which client driver to load
    DWORD dwRet = RegOpenKey(HKEY_LOCAL_MACHINE, PSZ_REG_CLIENT_DRIVER_PATH, phkFunctions);
    if (dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Failed to open function client key \"%s\". Error = %d\r\n"),
            pszFname, PSZ_REG_CLIENT_DRIVER_PATH, dwRet));
    }

    return dwRet;
}


BOOL
CUfnBus::PostInit(
    )
{
    SETFNAME();
    
    BOOL fErr;
    CUfnBusDevice *pDevice = NULL;

    TCHAR szClientName[UFN_CLIENT_NAME_MAX_CHARS];
    DWORD dwRet;
    BOOL fInserted = FALSE;

    DEBUGCHK(GetDeviceList() == NULL);

    dwRet = GetDefaultClientName(szClientName, dim(szClientName));
    if (dwRet != ERROR_SUCCESS) {
        goto EXIT;
    }

    dwRet = CreateChild(szClientName, &pDevice);
    if (dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s CreateChild failed.\r\n"), pszFname));
        dwRet = ERROR_GEN_FAILURE;
        goto EXIT;
    }

    fErr = InsertChild(pDevice);
    if (!fErr) {
        DEBUGMSG(ZONE_ERROR, (_T("%s InsertChild failed.\r\n"), pszFname));
        dwRet = ERROR_GEN_FAILURE;
        goto EXIT;
    }

    fInserted = TRUE;

    fErr = ActivateChild(m_szClientBusName);
    if (!fErr) {
        DEBUGMSG(ZONE_ERROR, (_T("%s ActivateChild failed.\r\n"), pszFname));
        dwRet = ERROR_GEN_FAILURE;
        goto EXIT;
    }

EXIT:
    BOOL fRet = TRUE;
    
    if (dwRet != ERROR_SUCCESS) {
        if (pDevice) {
            if (fInserted) {
                RemoveChildByFolder(pDevice);
                // This will take reference count to 0 and delete it.
            }
            else {
                delete pDevice;
            }
        }
        
        SetLastError(dwRet);
        fRet = FALSE;
    }

    return fRet;
}

BOOL CUfnBus::ActivateChild(LPCTSTR pszChildBusName) 
{
    SETFNAME();
    DWORD dwRet;

    DEBUGCHK(m_fIsChildPowerManaged == FALSE);
    
    // Allocate our free transfer list
    DEBUGCHK(m_pContext->pFreeTransferList == NULL);
    m_pContext->pFreeTransferList = new CFreeTransferList();
    if (m_pContext->pFreeTransferList == NULL) {
        dwRet = GetLastError();
        DEBUGMSG(ZONE_ERROR, (_T("%s Failed to create free transfer list. Error %u\r\n"),
            pszFname, dwRet));
        goto EXIT;
    }

#ifdef DEBUG
    // Verify that a compact can occur on a free list where
    // nothing has been allocated yet.
    //
    // Perform an initial compact to simulate the compact that will
    // occur after a quick attach and detach when no transfers have
    // been allocated yet.
    m_pContext->pFreeTransferList->Compact();
#endif

    dwRet = AllocEndpoints(m_pContext);
    if (dwRet != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Failed to create pipes. Error %u\r\n"),
            pszFname, dwRet));
        goto EXIT;
    }

    // Load the client driver
    DEBUGCHK(m_pContext->fClientIsBeingAddedOrRemoved == FALSE);
    m_pContext->fClientIsBeingAddedOrRemoved = TRUE;
    m_hInitThread = GetCurrentThread();

    // ActivateChild will eventually call the PDD's Start routine. The Start
    // routine will create the IST which could immediately send notifications
    // to the MDD. Reset the event so that notifications will be stalled.
    ResetEvent(m_pContext->hevReadyForNotifications);
    BOOL fErr = DefaultBusDriver::ActivateChild(pszChildBusName);

    m_hInitThread = NULL;
    m_pContext->fClientIsBeingAddedOrRemoved = FALSE;

    // Allow the stalled notification to continue now that the client is 
    // fully loaded.
    SetEvent(m_pContext->hevReadyForNotifications);

    if (fErr == FALSE) {
        DEBUGMSG(ZONE_ERROR, (_T("%s ActivateChild failed.\r\n"), pszFname));
        dwRet = ERROR_GEN_FAILURE;
        goto EXIT;

⌨️ 快捷键说明

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