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

📄 kbdhid.cpp

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

BOOL
FlashLEDs(
    PHID_KBD pHidKbd
    );



// Dll entry function.
extern "C" 
BOOL
DllEntry(
    HANDLE hDllHandle,
    DWORD dwReason, 
    LPVOID lpReserved
    )
{
    SETFNAME(_T("KBDHID 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 or the close event has been signaled.
static
DWORD
WINAPI
KeyboardThreadProc(
    LPVOID lpParameter
    )
{
    SETFNAME(_T("KeyboardThreadProc"));

    PHID_KBD pHidKbd = (PHID_KBD) lpParameter;
    BOOL  fGWEReady = FALSE;
    PCHAR pbHidPacket;
    DWORD cbHidPacket;
    DWORD cbBuffer;
    DWORD dwErr;
    DWORD cKeysSent;
    DWORD dwTimeout;
    
    DEBUGCHK(pHidKbd != NULL);
    DEBUGCHK(pHidKbd->hevClosing != NULL); // Needed to signal exit

    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
    
    cbBuffer = pHidKbd->hidpCaps.InputReportByteLength;
    
    pbHidPacket = (PCHAR) LocalAlloc(LMEM_FIXED, cbBuffer);
    if (pbHidPacket == NULL) {
        DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
        goto EXIT;
    }

    while (TRUE) 
    {  
        ValidateHidKbd(pHidKbd);

        DEBUGCHK(g_dwAutoRepeatInitialDelay >= KBD_AUTO_REPEAT_INITIAL_DELAY_MIN);
        DEBUGCHK(g_dwAutoRepeatInitialDelay <= KBD_AUTO_REPEAT_INITIAL_DELAY_MAX);
        DEBUGCHK(!g_dwAutoRepeatKeysPerSec || 
                 g_dwAutoRepeatKeysPerSec   >= KBD_AUTO_REPEAT_KEYS_PER_SEC_MIN);
        DEBUGCHK(g_dwAutoRepeatKeysPerSec   <= KBD_AUTO_REPEAT_KEYS_PER_SEC_MAX);

        // 0 keys per second => auto repeat disabled.
        if (g_dwAutoRepeatKeysPerSec == 0) {
            pHidKbd->ARState = AR_WAIT_FOR_ANY;
        }

        // Set our timeout according to the current autorepeat state.
        if (pHidKbd->ARState == AR_WAIT_FOR_ANY) {
            dwTimeout = INFINITE;
        }
        else if (pHidKbd->ARState == AR_INITIAL_DELAY) {
            dwTimeout = g_dwAutoRepeatInitialDelay;
        }
        else {
            DEBUGCHK(pHidKbd->ARState == AR_AUTOREPEATING);
            DEBUGCHK(g_dwAutoRepeatKeysPerSec != 0); // Special case above
            dwTimeout = 1000 / g_dwAutoRepeatKeysPerSec;
        }

        // Get an interrupt report from the device.
        dwErr = pHidKbd->pHidFuncs->lpGetInterruptReport(
            pHidKbd->hDevice,
            pbHidPacket,
            cbBuffer,
            &cbHidPacket,
            pHidKbd->hevClosing,
            dwTimeout);

        // Make sure gwes is ready to accept keystrokes.
        // Since USB is part of device.exe it can attempt to send keystrokes
        // before gwes is present (if something is leaning on keyboard at poweron).
        if (fGWEReady == FALSE) {
            fGWEReady = IsAPIReady(SH_WMGR);
        }

        if ( (dwErr == ERROR_DEVICE_REMOVED) || (dwErr == ERROR_CANCELLED) ) {
            // Exit thread 
            break;
        }
        else if (fGWEReady == FALSE) {
            // We cannot do anything with these keystrokes.
            DEBUGMSG(ZONE_ERROR, (_T("%s: Discarding keyboard event, no GWES yet\n"),
                pszFname));
            continue;
        }
        else if (dwErr == ERROR_TIMEOUT) {
            // Perform autorepeat
            DEBUGCHK(pHidKbd->ARState != AR_WAIT_FOR_ANY);
            cKeysSent = SendKeyboardUsages(pHidKbd->puapMakeUsages, pHidKbd->dwMaxUsages,
                HidP_Keyboard_Make, &pHidKbd->KeyStateFlags);
            DEBUGCHK(cKeysSent != 0);
            pHidKbd->ARState = AR_AUTOREPEATING;
        }
        else {
            DEBUGCHK(dwErr == ERROR_SUCCESS);
            ProcessKeyboardReport(pHidKbd, 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_KBD pHidKbd;
    const TCHAR * const pszClientKey = CLIENT_REGKEY_SZ;

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

    // Allocate this keyboard's data structure and fill it.
    pHidKbd = (PHID_KBD) LocalAlloc(LPTR, sizeof(HID_KBD));
    if (pHidKbd == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
        goto EXIT;
    }

    pHidKbd->dwSig = HID_KBD_SIG;
    pHidKbd->hDevice = hDevice;
    pHidKbd->pHidFuncs = pHidFuncs;
    pHidKbd->phidpPreparsedData = phidpPreparsedData;
    HidP_GetCaps(pHidKbd->phidpPreparsedData, &pHidKbd->hidpCaps);
    pHidKbd->KeyStateFlags = 0;
    pHidKbd->ARState = AR_WAIT_FOR_ANY;

	// Allocate enough space for output reports.
    pHidKbd->cbOutputBuffer = pHidKbd->hidpCaps.OutputReportByteLength;
    pHidKbd->pbOutputBuffer = (PCHAR) LocalAlloc(0, pHidKbd->cbOutputBuffer);
    if (pHidKbd->pbOutputBuffer == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
        goto EXIT;
    }
    
    pHidKbd->hevClosing = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (pHidKbd->hevClosing == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Error creating event: %d\r\n"),
            pszFname, GetLastError()));
        goto EXIT;
    }
    
    // Get the total number of usages that can be returned in an input packet.
    pHidKbd->dwMaxUsages = HidP_MaxUsageListLength(HidP_Input, 0, phidpPreparsedData);
    if (pHidKbd->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 = pHidKbd->dwMaxUsages * sizeof(USAGE_AND_PAGE);

    if (AllocateUsageLists(pHidKbd, cbUsages) == FALSE) {
        goto EXIT;
    }

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

    // Create the KBD device
    pHidKbd->hOSDevice = ActivateDevice(pszClientKey, (DWORD) pHidKbd);
    if (pHidKbd->hOSDevice == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Error on ActivateDevice(%s)\r\n"), 
            pszFname, pszClientKey));
        goto EXIT;
    }
#ifdef DEBUG
    pHidKbd->fhOSDeviceInited = TRUE;
#endif

    *ppvNotifyParameter = pHidKbd;
    ValidateHidKbd(pHidKbd);
    fRet = TRUE;

EXIT:
    if ((fRet == FALSE) && (pHidKbd != NULL)) {
        // Initialization failed. Clean up any resources that did allocate.
        FreeHidKbd(pHidKbd);
    }
    return fRet;
}
#ifdef DEBUG
// Match function with typedef.
static LPHID_CLIENT_ATTACH g_pfnDeviceAttach = HIDDeviceAttach;
#endif


// Entry point for the HID driver to give us notifications.
extern "C" 
BOOL 
WINAPI
HIDDeviceNotifications(
    DWORD  dwMsg,
    WPARAM wParam, // Message parameter
    PVOID  pvNotifyParameter
    )
{
    SETFNAME(_T("HIDDeviceNotifications"));

    BOOL fRet = FALSE;
    PHID_KBD pHidKbd = (PHID_KBD) pvNotifyParameter;

    UNREFERENCED_PARAMETER(wParam);

    if (VALID_HID_KBD(pHidKbd) == FALSE) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Received invalid structure pointer\r\n"), pszFname));
        goto EXIT;
    }

    ValidateHidKbd(pHidKbd);
    
    switch(dwMsg) {
        case HID_CLOSE_DEVICE:
            // Free all of our resources.
            WaitForSingleObject(pHidKbd->hThread, INFINITE);
            CloseHandle(pHidKbd->hThread);
            pHidKbd->hThread = NULL;
            
            // Key up all keys that are still down.
            SendKeyboardUsages(pHidKbd->puapPrevUsages, pHidKbd->dwMaxUsages,
                HidP_Keyboard_Break, &pHidKbd->KeyStateFlags);

            DeactivateDevice(pHidKbd->hOSDevice);
            FreeHidKbd(pHidKbd);
            fRet = TRUE;
            break;

        default:
            DEBUGMSG(ZONE_ERROR, (_T("%s: Unhandled message %u\r\n"), pszFname));
            break;
    };

EXIT:
    return fRet;
}
#ifdef DEBUG
// Match function with typedef.
static LPHID_CLIENT_NOTIFICATIONS g_pfnDeviceNotifications = HIDDeviceNotifications;
#endif


// Flashes the keyboard's LEDs.
static
BOOL
FlashLEDs(
    PHID_KBD pHidKbd
    )
{
    SETFNAME(_T("FlashLEDs"));

    DEBUGCHK(pHidKbd != NULL);

    // Turn on all LEDs.
    SetLEDs(pHidKbd, ~0);

    // Turn off all LEDs.
    SetLEDs(pHidKbd, 0);

    return TRUE;
}


// Allocate the usage lists for this keyboard. The lists are allocated in 
// a single block and then divided up.
static
BOOL
AllocateUsageLists(
    PHID_KBD pHidKbd,
    size_t cbUsages
    )
{
    SETFNAME(_T("AllocateUsageLists"));

    BOOL fRet = FALSE;
    size_t cbTotal;
    PBYTE pbStart;
    DWORD dwIdx;
    PUSAGE_AND_PAGE *rgppUsageAndPage[] = {
        &pHidKbd->puapPrevUsages,
        &pHidKbd->puapCurrUsages,
        &pHidKbd->puapBreakUsages,
        &pHidKbd->puapMakeUsages,
        &pHidKbd->puapOldMakeUsages
    };
    
    DEBUGCHK(pHidKbd != NULL);
	DEBUGCHK(cbUsages > 0);

    // Allocate a block of memory for all the usage lists
	cbTotal = cbUsages * dim(rgppUsageAndPage);
    pbStart = (PBYTE) LocalAlloc(LPTR, cbTotal);
    
    if (pbStart == NULL) {
       DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
       goto EXIT;
    }

    // Divide the block.
    for (dwIdx = 0; dwIdx < dim(rgppUsageAndPage); ++dwIdx) {
        *rgppUsageAndPage[dwIdx] = (PUSAGE_AND_PAGE) (pbStart + (cbUsages * dwIdx));
    }

    fRet = TRUE;

⌨️ 快捷键说明

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