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

📄 hidmdd.cpp

📁 嵌入式操作系统WINCE5.0下的USB驱动程序
💻 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.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  

    hidmdd.cpp

Abstract:  
    MDD for Human Interface Device (HID) Class Driver.

Functions:

Notes: 

--*/


#include "hidmdd.h"
#include <pm.h>
#include <devload.h>


// Globals that keep track of the reference count for the unnamed stream
// driver.
static CRITICAL_SECTION g_csHidRefCount;
static DWORD            g_dwHidRefCount;
static HANDLE           g_hMainHidDriver;


#ifdef DEBUG

// Print the report.
static
void
OutputReport(
    PBYTE pData,
    DWORD cbData,
    DWORD dwReportID,
    USAGE UsagePage,
    USAGE Usage
    )
{
    TCHAR szBuf[512];
    TCHAR *szCurr = szBuf;
    
    if (dim(szBuf) > cbData * 3) 
    {
        for (DWORD dwByte = 0; dwByte < cbData; ++dwByte) {
            _stprintf(szCurr, _T("%02X "), pData[dwByte]);
            szCurr += 3;
        }
    }
    else {
        DEBUGCHK(FALSE); // Why does the buffer need to be bigger? 512 is plenty!
        szBuf[0] = 0;
    }
    
    DEBUGMSG(ZONE_HID_DATA, (_T("HID Report ID %u (TLC %X-%X): %s\r\n"), dwReportID, 
        UsagePage, Usage, szBuf));
}


// Prints the available device strings.
static
void
DumpDeviceStrings(
    PCHID_CONTEXT pHidContext
    )
{
    SETFNAME(_T("DumpDeviceStrings"));

    struct DESC_TYPE_PAIR {
        LPCTSTR pszDesc;
        HID_STRING_TYPE stringType;
    };

    static const DESC_TYPE_PAIR rgList[] = {
        { _T("Manufacturer"), HID_STRING_ID_IMANUFACTURER },
        { _T("Product"), HID_STRING_ID_IPRODUCT},
        { _T("Serial Number"), HID_STRING_ID_ISERIALNUMBER},
    };            
    
    TCHAR szBuf[256];
    DWORD cchBuf;
    DWORD dwIdx;
    DWORD dwErr;

    for (dwIdx = 0; dwIdx < dim(rgList); ++dwIdx) {
        dwErr = HidPdd_GetString(pHidContext->hPddDevice, 
            rgList[dwIdx].stringType, 0, szBuf, dim(szBuf), &cchBuf);
        
        if (dwErr == ERROR_SUCCESS) {
            DEBUGMSG(ZONE_INIT, (_T("%s: %s: %s\r\n"), pszFname, 
                rgList[dwIdx].pszDesc, szBuf));
        }       
    }
}

#else

#define OutputReport(ptr, dw1, dw2, usage1, usage2)
#define DumpDeviceStrings(ptr)

#endif // DEBUG



// Generic routine to return the subkey of the form 
// pdwVals[0]_pdwVals[1]_...pdwVals[cdwVals-1].
static
HKEY 
OpenSpecificClientRegKey(
    HKEY hKeyRoot,
    const DWORD *pdwVals,
    DWORD cdwVals
    )
{
    HKEY hKeyRet = NULL;
    TCHAR szBuf[40];
    TCHAR *pszCur = szBuf;
    const TCHAR *pszKey;
    DWORD dwIdx;
    int ichWritten;

    DEBUGCHK(cdwVals * 11 + 1 < dim(szBuf));

    if (cdwVals == 0) {
        // Try default
        pszKey = DEFAULT_SZ;
    }
    else 
    {
        // Build key string
        for (dwIdx = 0; dwIdx < cdwVals; ++dwIdx) {
            ichWritten = _stprintf(pszCur, _T("%u_"), pdwVals[dwIdx]);
            pszCur += ichWritten;
        }

        *(pszCur - 1) = 0; // Remove the last _
        pszKey = szBuf;
    }

    RegOpenKey(hKeyRoot, pszKey, &hKeyRet);

    return hKeyRet;    
}


// Contains most of the logic to find and open the proper HID client key.
// The algorithm searches for the most specific vendor key of the form
// idVendor_idProduct_bcdDevice. Then its subkeys are searched for the most
// specific interface key of the form bInterface_bCollection. Then its
// subkeys are searched for the most specific top level collection key 
// of the form UsagePage_Usage.
//
// The order of vendor precedence is described below.
//
// idVendor_idProduct_bcdDevice
// idVendor_idProduct
// idVendor
// Default
//
// The order of interface precedence is described below.
//
// bInterface_bCollection
// bInterface
// Default
//
// The order of TLC precedence is 
//
// UsagePage_Usage
// UsagePage
// Default
//
// So the order of checking would be
// 1. idVendor_idProduct_bcdDevice\bInterface_bCollection\UsagePage_Usage
// 2. idVendor_idProduct_bcdDevice\bInterface_bCollection\UsagePage
// 3. idVendor_idProduct_bcdDevice\bInterface_bCollection\Default
// 4. idVendor_idProduct_bcdDevice\bInterface\UsagePage_Usage
// ...
// 7. idVendor_idProduct_bcdDevice\Default\UsagePage_Usage
// ...
// 10. idVendor_idProduct\bInterface_bCollection\UsagePage_Usage
// ...
// 42. Default\bInterface_bCollection\Default
// 43. Default\bInterface\UsagePage_Usage
// 44. Default\bInterface\UsagePage
// 45. Default\bInterface\Default
// 46. Default\Default\UsagePage_Usage
// 47. Default\Default\UsagePage
// 48. Default\Default\Default
//
static
HKEY
OpenClientRegKey(
    HKEY hKeyRoot,
    const DWORD *pdwVendorVals, 
    DWORD cdwVendorVals,
    const DWORD *pdwInterfaceVals,
    DWORD cdwInterfaceVals,
    const DWORD *pdwTLCVals,
    DWORD cdwTLCVals,
    PHID_DRIVER_SETTINGS pDriverSettingsUsed
    )
{
    SETFNAME(_T("OpenClientRegKey"));

    HKEY hKeyRet = NULL;
    HKEY hKeyVendor;
    HKEY hKeyInterface;
    INT cCurrVendor = -1;
    INT cCurrInterface = -1;
    INT cCurrTLC = -1;
    INT iIdx;

    DEBUGCHK(pdwVendorVals != NULL);
    DEBUGCHK(pdwInterfaceVals != NULL);
    DEBUGCHK(pdwTLCVals != NULL);

    for (cCurrVendor = (INT) cdwVendorVals; cCurrVendor >= 0; --cCurrVendor)
    {
        hKeyVendor = OpenSpecificClientRegKey(hKeyRoot, pdwVendorVals, cCurrVendor);
        if (hKeyVendor != NULL)
        {
            for (cCurrInterface = (INT) cdwInterfaceVals; 
                 cCurrInterface >= 0; 
                 --cCurrInterface)
            {
                hKeyInterface = OpenSpecificClientRegKey(hKeyVendor, pdwInterfaceVals, cCurrInterface);
                if (hKeyInterface != NULL)
                {
                    for (cCurrTLC = (INT) cdwTLCVals; cCurrTLC >= 0; --cCurrTLC)
                    {
                        hKeyRet = OpenSpecificClientRegKey(hKeyInterface, pdwTLCVals, cCurrTLC);
                        if (hKeyRet != NULL) {
                            // We found our key
                            break;
                        }
                    }
                    
                    RegCloseKey(hKeyInterface);

                    if (hKeyRet != NULL) {
                        // We found our key
                        break;
                    }
                } 
            }

            RegCloseKey(hKeyVendor);

            if (hKeyRet != NULL) {
                // We found our key.
                break;
            }
        }
    }

    if (hKeyRet != NULL) {
        // We found a match. Fill in the driver settings used.
        PDWORD rgpdwDriverSettings[] = {
            &pDriverSettingsUsed->dwVendorId,
            &pDriverSettingsUsed->dwProductId,
            &pDriverSettingsUsed->dwReleaseNumber,
            &pDriverSettingsUsed->dwInterfaceNumber,
            &pDriverSettingsUsed->dwCollection,
            &pDriverSettingsUsed->dwUsagePage,
            &pDriverSettingsUsed->dwUsage,
        };

        // Fill in the matching vendor info
        for (iIdx = 0; iIdx < cCurrVendor; ++iIdx) {
            *rgpdwDriverSettings[iIdx] = pdwVendorVals[iIdx];
        }

        // Fill in the matching interface info
        for (iIdx = 0; iIdx < cCurrInterface; ++iIdx) {
            *rgpdwDriverSettings[iIdx + cdwVendorVals] = pdwInterfaceVals[iIdx];
        }

        // Fill in the matching TLC info
        for (iIdx = 0; iIdx < cCurrTLC; ++iIdx) {
            *rgpdwDriverSettings[iIdx + cdwVendorVals + cdwInterfaceVals] 
                = pdwTLCVals[iIdx];
        }
    }

    return hKeyRet;
}


// Get the registry key for the HID client that will best service the device
// descripted in pDriverSettings.
// Returns the registry key and the actual driver settings that matched the key.
static
HKEY
FindClientRegKey(
    const HID_DRIVER_SETTINGS *pDriverSettings,
    PHID_DRIVER_SETTINGS pDriverSettingsUsed
    )
{
    SETFNAME(_T("FindClientRegKey"));

    const DWORD rgdwVendorVals[] = { 
        pDriverSettings->dwVendorId, 
        pDriverSettings->dwProductId, 
        pDriverSettings->dwReleaseNumber 
        };
    const DWORD rgdwInterfaceVals[] = { 
        pDriverSettings->dwInterfaceNumber,
        pDriverSettings->dwCollection
        };
    const DWORD rgdwTLCVals[] = { 
        pDriverSettings->dwUsagePage, 
        pDriverSettings->dwUsage 
        };

    HKEY hKeyRoot = NULL;
    HKEY hKeyRet = NULL;
    LONG iErr;

    DEBUGCHK(pDriverSettings != NULL);
    DEBUGCHK(pDriverSettingsUsed != NULL);
    
    memset(pDriverSettingsUsed, (BYTE) HID_NO_INFO, sizeof(HID_DRIVER_SETTINGS));

    iErr = RegOpenKey(HKEY_LOCAL_MACHINE, LOAD_CLIENTS_PATH_SZ, &hKeyRoot);
    if (iErr != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Failed opening HID client key [HKLM\\%s]\r\n"),
            pszFname, LOAD_CLIENTS_PATH_SZ));
        goto EXIT;
    }

    // Now find the most specific match.
    hKeyRet = OpenClientRegKey(hKeyRoot, 
        rgdwVendorVals, dim(rgdwVendorVals),
        rgdwInterfaceVals, dim(rgdwInterfaceVals),
        rgdwTLCVals, dim(rgdwTLCVals), 
        pDriverSettingsUsed);
    
    if (hKeyRet == NULL) {
        DEBUGMSG(ZONE_COMMENT, (_T("%s: Could not find a suitable HID client driver\r\n"),
            pszFname));
        goto EXIT;
    }

EXIT:
    if (hKeyRoot != NULL) RegCloseKey(hKeyRoot);

    return hKeyRet;
}


// Check this collection's registry key to see if remote wakeup needs
// to be enabled for this device.
static
void
SetRemoteWakeup(
    PHID_CONTEXT pHidContext,
    HKEY hKeyClient
    )
{
    SETFNAME(_T("SetRemoteWakeup"));
    
    DWORD dwRemoteWakeup;
    DWORD cbdwRemoteWakeup;
    BOOL fEnable;
    DWORD dwType;
    INT iErr;
    DWORD dwErr;

    DEBUGCHK(pHidContext != NULL);
    PREFAST_DEBUGCHK(hKeyClient != NULL);
    
    // Check to see if we should enable remote wakeup for this device.
    // If any TLC client wishes to be a remote wakeup source, the device
    // will be set as a remote wakeup source.
    cbdwRemoteWakeup = sizeof(dwRemoteWakeup);
    iErr = RegQueryValueEx(hKeyClient, REMOTE_WAKEUP_VALUE_SZ, NULL, &dwType, 
        (PBYTE) &dwRemoteWakeup, &cbdwRemoteWakeup);
    if ( (iErr == ERROR_SUCCESS) && (dwType == REG_DWORD) && 
         (cbdwRemoteWakeup == sizeof(dwRemoteWakeup)) && (dwRemoteWakeup != 0) ) {
        // Enable remote wakeup
        fEnable = TRUE;
        dwErr = HidPdd_IssueCommand(pHidContext->hPddDevice, 
            HID_PDD_REMOTE_WAKEUP, fEnable);
        
        if (dwErr != ERROR_SUCCESS) {
            DEBUGMSG(ZONE_WARNING, 
                (_T("%s: Unable to set device as remote wakeup source\r\n"),
                pszFname));
        }
    }
}


// Check this collection's registry key to see if the idle rate needs 
// to be adjusted.
static
void
SetIdleRate(
    PHID_CONTEXT pHidContext,
    HKEY hKeyClient,
    DWORD dwCollection
    )
{
    SETFNAME(_T("SetIdleRate"));
    
    DWORD dwDuration;
    DWORD cbdwDuration;
    DWORD dwType;
    INT iErr;
    DWORD dwIdx;
    DWORD dwErr;

    DEBUGCHK(pHidContext != NULL);
    PREFAST_DEBUGCHK(hKeyClient != NULL);
    
    // Check to see if we should set an idle rate for the device.
    cbdwDuration = sizeof(dwDuration);
    iErr = RegQueryValueEx(hKeyClient, IDLE_RATE_VALUE_SZ, NULL, &dwType, 
        (PBYTE) &dwDuration, &cbdwDuration);
    if ( (iErr == ERROR_SUCCESS) && (dwType == REG_DWORD) && 
         (cbdwDuration == sizeof(dwDuration)) ) {         

⌨️ 快捷键说明

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