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

📄 kbdhid.cpp

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


// Free the memory used by pHidKbd
void
FreeHidKbd(
    PHID_KBD pHidKbd
    )
{
    DEBUGCHK(pHidKbd != NULL);

    // Close thread if it has been created.
    if (pHidKbd->hThread != NULL) {
        DEBUGCHK(pHidKbd->hevClosing != NULL);
        SetEvent(pHidKbd->hevClosing);
        WaitForSingleObject(pHidKbd->hThread, INFINITE);
        CloseHandle(pHidKbd->hThread);
    }

    if (pHidKbd->hevClosing != NULL) CloseHandle(pHidKbd->hevClosing);
    if (pHidKbd->puapPrevUsages != NULL) LocalFree(pHidKbd->puapPrevUsages);
    if (pHidKbd->pbOutputBuffer != NULL) LocalFree(pHidKbd->pbOutputBuffer);
    LocalFree(pHidKbd);    
}


// Determine what usages have been set/unset and send the key events off to
// the system.
//
// On entry, pHidKbd->puapPrevUsages contains the previous usage list and
// pHidKbd->puapMakeUsages contains the most recent set of usages that
// went down (usually a single usage).
static
void
ProcessKeyboardReport(
    PHID_KBD pHidKbd,
    PCHAR pbHidPacket,
    DWORD cbHidPacket
    )
{
    SETFNAME(_T("ProcessKeyboardReport"));

    BOOL fRollover = FALSE;
    ULONG uCurrUsages;
    DWORD dwUsageIdx;
    DWORD cbUsageList;
    DWORD cKeysSent;
    NTSTATUS status;
    
    DEBUGCHK(pHidKbd != NULL);
    DEBUGCHK(pbHidPacket != NULL);

    uCurrUsages = pHidKbd->dwMaxUsages;
    cbUsageList = uCurrUsages * sizeof(USAGE_AND_PAGE);

    status = HidP_GetUsagesEx(
        HidP_Input,
        0,
        pHidKbd->puapCurrUsages,
        &uCurrUsages, // IN OUT parameter
        pHidKbd->phidpPreparsedData,
        pbHidPacket,
        cbHidPacket
        );
    DEBUGCHK(NT_SUCCESS(status));
    DEBUGCHK(uCurrUsages <= pHidKbd->dwMaxUsages);

    // Check usages returned for keyboard rollover.
    for (dwUsageIdx = 0; dwUsageIdx < uCurrUsages; ++dwUsageIdx) 
    {
        PUSAGE_AND_PAGE puapCurr = &pHidKbd->puapCurrUsages[dwUsageIdx];

        if (puapCurr->UsagePage == HID_USAGE_PAGE_KEYBOARD) 
        {
            if (puapCurr->Usage == HID_USAGE_KEYBOARD_ROLLOVER) {
                DEBUGMSG(ZONE_WARNING, (_T("%s: HID keyboard rollover\r\n"), pszFname));
                fRollover = TRUE;
            }

            // At this point either we got the rollover usage or there will
            // not be one. Break either way.
            break;
        }
    }

    if (fRollover == FALSE) 
    {
        // Save our most recent down list.
        memcpy(pHidKbd->puapOldMakeUsages, pHidKbd->puapMakeUsages, cbUsageList);

        // Determine what keys went down and up.
        status = HidP_UsageAndPageListDifference(
            pHidKbd->puapPrevUsages,
            pHidKbd->puapCurrUsages,
            pHidKbd->puapBreakUsages,
            pHidKbd->puapMakeUsages,
            pHidKbd->dwMaxUsages
            );
        DEBUGCHK(NT_SUCCESS(status));

        if (HidP_IsSameUsageAndPage(pHidKbd->puapMakeUsages[0], g_uapZero) &&
            HidP_IsSameUsageAndPage(pHidKbd->puapBreakUsages[0], g_uapZero))
        {
            // No new keys
            DEBUGMSG(ZONE_USAGES, (_T("%s: No new keys. Hardware autorepeat?\r\n"), pszFname));

            // Replace the list of recent downs.
            memcpy(pHidKbd->puapMakeUsages, pHidKbd->puapOldMakeUsages, cbUsageList);
        }
        else
        {
            // Move the current usages to the previous usage list.
            memcpy(pHidKbd->puapPrevUsages, pHidKbd->puapCurrUsages, cbUsageList);

            // Convert the key ups into scan codes and send them
            cKeysSent = SendKeyboardUsages(pHidKbd->puapBreakUsages, pHidKbd->dwMaxUsages,
                HidP_Keyboard_Break, &pHidKbd->KeyStateFlags);

            // If there were ups, then turn off repeat.
            if (cKeysSent > 0) {
                pHidKbd->ARState = AR_WAIT_FOR_ANY;
            }

            if (HidP_IsSameUsageAndPage(pHidKbd->puapCurrUsages[0], g_uapZero) == FALSE &&
                HidP_IsSameUsageAndPage(pHidKbd->puapMakeUsages[0], g_uapZero) == TRUE)
            {
                // There are not any new downs, but there may be some old ones
                // that are repeating in hardware. We'll update our make usages
                // to include any keys that have not come up.
                status = HidP_UsageAndPageListDifference(
                    pHidKbd->puapBreakUsages,
                    pHidKbd->puapOldMakeUsages,
                    pHidKbd->puapCurrUsages, // We can scrap the current usages now
                    pHidKbd->puapMakeUsages,
                    pHidKbd->dwMaxUsages
                    );
                DEBUGCHK(NT_SUCCESS(status));
            }
            else {
                // Convert the key downs to scan codes and send them
                cKeysSent = SendKeyboardUsages(pHidKbd->puapMakeUsages, pHidKbd->dwMaxUsages,
                    HidP_Keyboard_Make, &pHidKbd->KeyStateFlags);

                // If there were downs, then set for repeat.
                if (cKeysSent > 0) {
                    pHidKbd->ARState = AR_INITIAL_DELAY;
                }
            }
        }
    }
}


// Converts the usages to virtual keys and sends them off.
// Returns the number of usages converted.
static
DWORD
SendKeyboardUsages(
    PUSAGE_AND_PAGE puapUsages,
    DWORD dwMaxUsages,
    HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
    KEY_STATE_FLAGS *pKeyStateFlags
    )
{    
    SETFNAME(_T("SendKeyboardUsages"));
    
    DWORD dwIdx;
    
    DEBUGCHK(puapUsages != NULL);
    DEBUGCHK(pKeyStateFlags != NULL);

    for (dwIdx = 0; dwIdx < dwMaxUsages; ++dwIdx) {
        // Determine virtual key mapping
        PUSAGE_AND_PAGE puapCurr = &puapUsages[dwIdx];
	    PFN_PROCESSING_TYPE pfnProcessingType;
        ProcessingType PT;
        UINT8 uiFlags;
        DWORD dwFlags = 0;
        UINT uiSc = 0;
        UINT uiVk;

        if (puapCurr->Usage == 0) {
            // No more usages
            break;
        }

        // Convert the usage to a scan code with flags.
        switch (puapCurr->UsagePage) 
        {
        case HID_USAGE_PAGE_KEYBOARD:
            {
                const USAGE_TO_SCANCODE *pUsageToSc = FindUsageToSc(puapCurr->Usage);

                if ( (pUsageToSc != NULL) && (pUsageToSc->uiSc != 0) ) {
                    uiFlags = pUsageToSc->uiFlags;
                    uiSc = pUsageToSc->uiSc;
                }
                break;
            }
    			
        case HID_USAGE_PAGE_CONSUMER:
            {
                // Note that most consumer keys will be handled in the 0xC 0x1 
                // HID client.
                DWORD dwAssn;
                
                for (dwAssn = 0; dwAssn < dim(g_rgConsumerToScAssn); ++dwAssn) {
                    if (g_rgConsumerToScAssn[dwAssn].usage == puapCurr->Usage) {
                        uiSc = g_rgConsumerToScAssn[dwAssn].uiSc;
                        uiFlags = MAKE_FLAGS(EB_NONE, PT_STANDARD);
                        break;
                    }
                }
                
                break;
            }
        };

        // Was there a conversion? If so, send the event.
        if (uiSc != 0) 
        {
            DEBUGMSG(ZONE_USAGES, (_T("%s: Usage Page: 0x%04x Usage: 0x%04x -> SC: 0x%06x\r\n"),
                pszFname, puapCurr->UsagePage, puapCurr->Usage, uiSc));

            if (hidpKeyEvent == HidP_Keyboard_Break) {
                dwFlags |= KEYEVENTF_KEYUP;
            }

            // Prepend extended bits
            switch (GET_EB(uiFlags)) {
                case EB_E0:
                    uiSc |= 0xE000;
                    dwFlags |= KEYEVENTF_EXTENDEDKEY;
                    break;

                case EB_E114:
                    uiSc |= 0xE11400;
                    break;
            };

            // Convert scan code to virtual key
            DEBUGCHK(IsAPIReady(SH_WMGR) == TRUE); // Exception if FALSE
            uiVk = MapVirtualKey(uiSc, MAP_SC_TO_VK);

            // Determine which processing function to call
            PT = GET_PT(uiFlags);
            DEBUGCHK(dim(g_rgpfnProcessingType) == PT_COUNT);
            DEBUGCHK(PT < PT_COUNT);
            pfnProcessingType = g_rgpfnProcessingType[PT];
            DEBUGCHK(pfnProcessingType != NULL);

            // Call the processing function to send off the event
            (*pfnProcessingType)(uiVk, uiSc, dwFlags, hidpKeyEvent, pKeyStateFlags);
        }
		else {
            DEBUGMSG(ZONE_WARNING, (_T("%s: No scan code for Usage Page: 0x%04x Usage: 0x%04x\r\n"),
                pszFname, puapCurr->UsagePage, puapCurr->Usage));
		}
    }

    return dwIdx;
}


// Send the keyboard event to GWES.
static
void
KeyboardEvent(
    UINT vk,
    UINT sc,
    DWORD dwFlags
    )
{
    SETFNAME(_T("KeyboardEvent"));

    UINT8 uiVk = (UINT8) vk;
    UINT8 uiSc = (UINT8) sc;

    DEBUGCHK((uiVk != 0) || (uiSc != 0));

    DEBUGMSG(ZONE_USAGES, (_T("%s: Keybd event: vk: 0x%02x sc: 0x%02x flags: 0x%08x\r\n"),
        pszFname, uiVk, uiSc, dwFlags));
    keybd_event(uiVk, uiSc, dwFlags, 0);
}


// Search for usage in the g_rgUsageToScInfo tables.
static
const USAGE_TO_SCANCODE *
FindUsageToSc(
    USAGE usage
    )
{
    const USAGE_TO_SC_INFO *pUsageToScInfo;
    const USAGE_TO_SCANCODE *pUsageToSc = NULL;
    DWORD cUsageToScInfo = dim(g_rgUsageToScInfo);
    DWORD dwNormalizedUsage;
    DWORD dwIdx;

    ValidateAllUsageToSc();

    for (dwIdx = 0; dwIdx < cUsageToScInfo; ++dwIdx) 
    {
        pUsageToScInfo = &g_rgUsageToScInfo[dwIdx];

        ValidateUsageToSc(pUsageToScInfo);

        if ( (usage >= pUsageToScInfo->uFirstUsage) &&
             (usage <= pUsageToScInfo->uLastUsage) ) 
        {
            dwNormalizedUsage = usage - pUsageToScInfo->uFirstUsage;
            DEBUGCHK(dwNormalizedUsage <= pUsageToScInfo->uLastUsage);
            pUsageToSc = &pUsageToScInfo->pUsageToSc[dwNormalizedUsage];
            break;
        }
    }

    return pUsageToSc;
}


// Standard key processing.
static
void
ProcessStandard(
    UINT uiVk,
    UINT uiSc,
    DWORD dwFlags,
    HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
    KEY_STATE_FLAGS *pKeyStateFlags
    )
{
    KeyboardEvent(uiVk, uiSc, dwFlags);
}


// Updates the given key state with the given virtual key modifier.
// Only processes L/R Ctrl, Shift and Alt. The toggled key state is
// set through IOCTL calls from the Layout Manager.
static
void
UpdateKeyState(
    KEY_STATE_FLAGS *pKeyStateFlags,
    UINT8 vk,
    HIDP_KEYBOARD_DIRECTION hidpKeyEvent
    )
{
	struct VKeyToShiftState {
		UINT8           vk; // Virtual key
		KEY_STATE_FLAGS ksf;   // Corresponding shift state flag
	}; 
    
    static const VKeyToShiftState rgVKeyDownToShiftState[] = {
        { VK_LSHIFT,    KeyShiftLeftShiftFlag },
        { VK_RSHIFT,    KeyShiftRightShiftFlag },
        { VK_LCONTROL,  KeyShiftLeftCtrlFlag },
        { VK_RCONTROL,  KeyShiftRightCtrlFlag },
        { VK_LMENU,     KeyShiftLeftAltFlag },
        { VK_RMENU,     KeyShiftRightAltFlag },
    };

    DWORD dwIdx;
    const VKeyToShiftState *pvkshiftCurr;

    DEBUGCHK(pKeyStateFlags != NULL);
    DEBUGCHK(vk != 0);

    for (dwIdx = 0; dwIdx < dim(rgVKeyDownToShiftState); ++dwIdx) {
        pvkshiftCurr = &rgVKeyDownToShiftState[dwIdx];
        if (pvkshiftCurr->vk == vk) {
            if (hidpKeyEvent == HidP_Keyboard_Make) {
                *pKeyStateFlags |= pvkshiftCurr->ksf;
            }
            else {
                *pKeyStateFlags &= ~pvkshiftCurr->ksf;

⌨️ 快捷键说明

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