conshid.cpp

来自「嵌入式操作系统WINCE5.0下的USB驱动程序」· C++ 代码 · 共 589 行 · 第 1/2 页

CPP
589
字号
//
// 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 "conshid.h"
#include <windev.h>


#ifdef DEBUG

// Debug Zones
#define DBG_ERROR              0x0001
#define DBG_WARNING            0x0002
#define DBG_INIT               0x0004
#define DBG_FUNCTION           0x0008

#define DBG_USAGES             0x0010

DBGPARAM dpCurSettings = {
        TEXT("ConsHid"), {
        TEXT("Errors"), TEXT("Warnings"), TEXT("Init"), TEXT("Function"),
        TEXT("Usages"), TEXT(""), TEXT(""), TEXT(""),
        TEXT(""), TEXT(""), TEXT(""), TEXT(""),
        TEXT(""), TEXT(""), TEXT(""), TEXT("") },
        DBG_ERROR | DBG_WARNING };
        

static
void
ValidateHidConsumer(
    PHID_CONSUMER pHidConsumer
    );

#else

#define ValidateHidConsumer(ptr)

#endif // DEBUG


// MapVirtualKey(x, 3) converts scan codes to virtual keys
#define MAP_SC_TO_VK 3


// Describes an association from a Usage to an AT Scan Code
struct USAGE_TO_SC_ASSOCIATION {
    USAGE  usage;
    UINT16 uiSc;
};


// Usage to Virtual Key table
static const USAGE_TO_SC_ASSOCIATION g_rgUsageToScAssn[] = {
    { HID_CONSUMER_SCAN_NEXT_TRACK,             0xE04D },
    { HID_CONSUMER_SCAN_PREVIOUS_TRACK,         0xE015 },
	{ HID_CONSUMER_STOP,                        0xE03B },
	{ HID_CONSUMER_PLAY_PAUSE,                  0xE034 },

    { HID_CONSUMER_VOLUME_MUTE,                 0xE023 },
    { HID_CONSUMER_VOLUME_INCREMENT,            0xE032 },
    { HID_CONSUMER_VOLUME_DECREMENT,            0xE021 },

    { HID_CONSUMER_LAUNCH_CONFIGURATION,        0xE050 },
    { HID_CONSUMER_LAUNCH_EMAIL,                0xE048 },
    { HID_CONSUMER_LAUNCH_CALCULATOR,           0xE02B },
    { HID_CONSUMER_LAUNCH_BROWSER,              0xE040 },

    { HID_CONSUMER_APP_SEARCH,                  0xE010 },
    { HID_CONSUMER_APP_HOME,                    0xE03A },
    { HID_CONSUMER_APP_BACK,                    0xE038 },
    { HID_CONSUMER_APP_FORWARD,                 0xE030 },
    { HID_CONSUMER_APP_STOP,                    0xE028 },
    { HID_CONSUMER_APP_REFRESH,                 0xE020 },
    { HID_CONSUMER_APP_BOOKMARKS,               0xE018 },
};


DWORD
SendKeyboardUsages(
    PUSAGE pUsages,
    DWORD dwMaxUsages,
    HIDP_KEYBOARD_DIRECTION keyEvent 
    );

void 
KeyboardEvent(
    UINT vk,
    UINT sc,
    DWORD dwFlags
    );

void
ProcessConsumerReport(
    PHID_CONSUMER pHidConsumer,
    PCHAR pbHidPacket,
    DWORD cbHidPacket
    );

BOOL
AllocateUsageLists(
    PHID_CONSUMER pHidConsumer,
    size_t cbUsages
    );

VOID
FreeHidConsumer(
    PHID_CONSUMER pHidConsumer
    );



// Dll entry function.
extern "C" 
BOOL
DllEntry(
    HANDLE hDllHandle,
    DWORD dwReason, 
    LPVOID lpReserved
    )
{
    SETFNAME(_T("CONSHID DllEntry"));
    
    UNREFERENCED_PARAMETER(lpReserved);
    
    switch (dwReason) {
        case DLL_PROCESS_ATTACH:
            DEBUGREGISTER((HINSTANCE)hDllHandle);

            DEBUGMSG(ZONE_INIT, (_T("%s: Attach\r\n"), pszFname));
            DisableThreadLibraryCalls((HMODULE) hDllHandle);
            break;
            
        case DLL_PROCESS_DETACH:
            DEBUGMSG(ZONE_INIT, (_T("%s: Detach\r\n"), pszFname));
            break;
            
        default:
            break;
    }
    
    return TRUE ;
}


// Get interrupt reports from the device. Thread exits when the device has
// been removed.
static
DWORD
WINAPI
ConsumerThreadProc(
    LPVOID lpParameter
    )
{
    SETFNAME(_T("ConsumerThreadProc"));

    PHID_CONSUMER pHidConsumer = (PHID_CONSUMER) lpParameter;
    
    PREFAST_DEBUGCHK(pHidConsumer != NULL);

    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

    const DWORD cbMaxHidPacket = pHidConsumer->hidpCaps.InputReportByteLength;
    PCHAR pbHidPacket = (PCHAR) LocalAlloc(LMEM_FIXED, cbMaxHidPacket);
    if (pbHidPacket == NULL) {
        DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error: %d\r\n"), pszFname, 
            GetLastError()));
        goto EXIT;
    }

    while (TRUE) {
        DWORD cbHidPacket;
        
        ValidateHidConsumer(pHidConsumer);
        
        // Get an interrupt report from the device.
        DWORD dwErr = pHidConsumer->pHidFuncs->lpGetInterruptReport(
            pHidConsumer->hDevice,
            pbHidPacket,
            cbMaxHidPacket,
            &cbHidPacket,
            NULL,
            INFINITE);

        if (dwErr != ERROR_SUCCESS) {
            if ( (dwErr != ERROR_DEVICE_REMOVED) && (dwErr != ERROR_CANCELLED) ) {
                DEBUGMSG(ZONE_ERROR, 
                    (_T("%s: GetInterruptReport returned unexpected error %u\r\n"),
                    pszFname, dwErr));
            }

            // Exit thread
            break;
        }
        else {
            DEBUGCHK(cbHidPacket <= cbMaxHidPacket);
            ProcessConsumerReport(pHidConsumer, pbHidPacket, cbHidPacket);
        }
    }

EXIT:
    if (pbHidPacket != NULL) LocalFree(pbHidPacket);
    DEBUGMSG(ZONE_FUNCTION, (_T("%s: Exiting thread\r\n"), pszFname));
    
    return 0;
}


// Entry point for the HID driver. Initializes the structures for this 
// keyboard and starts the thread that will receive interrupt reports.
extern "C"
BOOL
HIDDeviceAttach(
    HID_HANDLE                 hDevice, 
    PCHID_FUNCS                pHidFuncs,
    const HID_DRIVER_SETTINGS *pDriverSettings,
    PHIDP_PREPARSED_DATA       phidpPreparsedData,
    PVOID                     *ppvNotifyParameter,
    DWORD                      dwUnused
    )
{
    SETFNAME(_T("HIDDeviceAttach"));

    BOOL fRet = FALSE;
    size_t cbUsages;
    PHID_CONSUMER pHidConsumer;

    DEBUGCHK(hDevice != NULL);
    DEBUGCHK(pHidFuncs != NULL);
    DEBUGCHK(phidpPreparsedData != NULL);
    DEBUGCHK(ppvNotifyParameter != NULL);

    // Allocate this device's data structure and fill it.
    pHidConsumer = (PHID_CONSUMER) LocalAlloc(LPTR, sizeof(HID_CONSUMER));
    if (pHidConsumer == NULL) {
        DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
        goto EXIT;
    }

    pHidConsumer->dwSig = HID_CONSUMER_SIG;
    pHidConsumer->hDevice = hDevice;
    pHidConsumer->pHidFuncs = pHidFuncs;
    pHidConsumer->phidpPreparsedData = phidpPreparsedData;
    HidP_GetCaps(pHidConsumer->phidpPreparsedData, &pHidConsumer->hidpCaps);
    
    // Get the total number of usages that can be returned in an input packet.
    pHidConsumer->dwMaxUsages = HidP_MaxUsageListLength(HidP_Input, 
        HID_USAGE_PAGE_CONSUMER, phidpPreparsedData);
    if (pHidConsumer->dwMaxUsages == 0) {
        DEBUGMSG(ZONE_WARNING, (_T("%s: This collection does not have any ")
            _T("understood usages and will be ignored\r\n"), pszFname));
        goto EXIT;
    }
    
    cbUsages = pHidConsumer->dwMaxUsages * sizeof(*pHidConsumer->puPrevUsages);

    if (AllocateUsageLists(pHidConsumer, cbUsages) == FALSE) {
        goto EXIT;
    }
	
    // Create the thread that will receive reports from this device
    pHidConsumer->hThread = CreateThread(NULL, 0, ConsumerThreadProc, pHidConsumer, 0, NULL);
    if (pHidConsumer->hThread == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Failed creating keyboard thread\r\n"), 
            pszFname));
        goto EXIT;
    }
#ifdef DEBUG
    pHidConsumer->fhThreadInited = TRUE;
#endif


    *ppvNotifyParameter = pHidConsumer;
    ValidateHidConsumer(pHidConsumer);
    fRet = TRUE;

EXIT:
    if ((fRet == FALSE) && (pHidConsumer != NULL)) {
        FreeHidConsumer(pHidConsumer);
    }
    return fRet;
}
#ifdef DEBUG
// Match function with typedef.
static LPHID_CLIENT_ATTACH g_pfnDeviceAttach = HIDDeviceAttach;
#endif

⌨️ 快捷键说明

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