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

📄 kbdhid.cpp

📁 Xcale270Bsp包,wince平台
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    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, 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;

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);

	RETAILMSG(1,(TEXT("ProcessKeyboardReport: pbHidPacket: %08x, cbHidPacket: %d, %02x %02x %02x %02x %02x %02x %02x %02x.\r\n"),
		pbHidPacket, cbHidPacket, pbHidPacket[0], pbHidPacket[1], pbHidPacket[2], pbHidPacket[3], pbHidPacket[4], pbHidPacket[5], pbHidPacket[6], pbHidPacket[7] ));

    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, 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, 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(
    PHID_KBD pHidKbd,
    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 )
				{
					RETAILMSG(1,(TEXT("SendKbdUsg: U: %08x, Sc: %08x, Fl: %08x.\r\n"), puapCurr->Usage, pUsageToSc->uiSc, pUsageToSc->uiFlags ));
				}
				else
				{
					RETAILMSG(1,(TEXT("SendKbdsg: U: %08x has no scancode mapping.\r\n")));
				}

                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

			// used to use MapVirtualKey. This way, the VK's are looked up directly
			if( uiSc <= ScanCodeTableLast )
			{
				uiVk = ScanCodeToVKeyTable[uiSc];
				RETAILMSG(1,(TEXT("SendKbdUsg: Map: %d, Sc: %08x, Vk: %08x.\r\n"), 0, uiSc, uiVk ));
			}
			else
			if( ( uiSc <= E0ScanCodeTableLast ) && ( uiSc >= E0ScanCodeTableFirst ) )
			{
				uiVk = E0ScanCodeToVKeyTable[uiSc - E0ScanCodeTableFirst];
				RETAILMSG(1,(TEXT("SendKbdUsg: Map: %d, Sc: %08x, Vk: %08x.\r\n"), 0, uiSc, uiVk ));
			}
			else
			{
				RETAILMSG(1,(TEXT("SendKbdUsg: no VKeyTable entry for %08x.\r\n"), uiSc ));
			}


			// look for a numlock on key make events
			if( hidpKeyEvent == HidP_Keyboard_Make )
			{
				if( uiVk == VK_NUMLOCK )
				{
					// need to toggle the numlock state
					if (IS_NUMLOCK_ENABLED() == FALSE)
					{
						*pKeyStateFlags |= KeyShiftNumLockFlag;
						RETAILMSG(1,(TEXT("SendKbdUsb: Setting numlock flag. Result: %08x.\r\n"), *pKeyStateFlags ));
					}
					else
					{
						*pKeyStateFlags &= ~KeyShiftNumLockFlag;
						RETAILMSG(1,(TEXT("SendKbdUsb: Clearing numlock flag. Result: %08x.\r\n"), *pKeyStateFlags ));
					}

					SetLEDs( pHidKbd, *pKeyStateFlags );
				}
			}

			// look for a caps lock on key make events
			if( hidpKeyEvent == HidP_Keyboard_Make )
			{
				if( uiVk == VK_CAPITAL )
				{
					// need to toggle the numlock state
					if (IS_CAPSLOCK_ENABLED() == FALSE)
					{
						*pKeyStateFlags |= KeyShiftCapitalFlag;
						RETAILMSG(1,(TEXT("SendKbdUsb: Setting capslock flag. Result: %08x.\r\n"), *pKeyStateFlags ));
					}
					else
					{
						*pKeyStateFlags &= ~KeyShiftCapitalFlag;
						RETAILMSG(1,(TEXT("SendKbdUsb: Clearing capslock flag. Result: %08x.\r\n"), *pKeyStateFlags ));
					}

					SetLEDs( pHidKbd, *pKeyStateFlags );
				}
			}


			// look for a scroll lock on key make events
			if( hidpKeyEvent == HidP_Keyboard_Make )
			{
				if( uiVk == VK_SCROLL )
				{
					// need to toggle the numlock state
					if (IS_SCROLLLOCK_ENABLED() == FALSE)
					{
						*pKeyStateFlags |= KeyShiftScrollLockFlag;
						RETAILMSG(1,(TEXT("SendKbdUsb: Setting scrolllock flag. Result: %08x.\r\n"), *pKeyStateFlags ));
					}
					else
					{
						*pKeyStateFlags &= ~KeyShiftScrollLockFlag;
						RETAILMSG(1,(TEXT("SendKbdUsb: Clearing scrolllock flag. Result: %08x.\r\n"), *pKeyStateFlags ));
					}

					SetLEDs( pHidKbd, *pKeyStateFlags );
				}
			}


            // Determine which processing function to call
            PT = GET_PT(uiFlags);
			RETAILMSG(1,(TEXT("SendKbdUsg: key category is %d.\r\n"), PT ));


            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;

⌨️ 快捷键说明

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