📄 kbdhid.cpp
字号:
0, // Scan Code 0x8D
0, // Scan Code 0x8E
0, // Scan Code 0x8F
};
#define E0ScanCodeTableFirst 0xE010
#define E0ScanCodeTableLast 0xE07F
static UINT8 E0ScanCodeToVKeyTable[] =
{
VK_BROWSER_SEARCH, // Scan Code 0xE010
VK_RMENU, // Scan Code 0xE011
0, // Scan Code 0xE012 which must be 0 or extra WM_KEYDOWN/UP messages will occur
0, // Scan Code 0xE013
VK_RCONTROL, // Scan Code 0xE014
VK_MEDIA_PREV_TRACK, // Scan Code 0xE015
0, // Scan Code 0xE016
0, // Scan Code 0xE017
VK_BROWSER_FAVORITES, // Scan Code 0xE018
0, // Scan Code 0xE019
0, // Scan Code 0xE01A
0, // Scan Code 0xE01B
0, // Scan Code 0xE01C
0, // Scan Code 0xE01D
0, // Scan Code 0xE01E
VK_LWIN, // Scan Code 0xE01F
VK_BROWSER_REFRESH, // Scan Code 0xE020
VK_VOLUME_DOWN, // Scan Code 0xE021
0, // Scan Code 0xE022
VK_VOLUME_MUTE, // Scan Code 0xE023
0, // Scan Code 0xE024
0, // Scan Code 0xE025
0, // Scan Code 0xE026
VK_RWIN, // Scan Code 0xE027
VK_BROWSER_STOP, // Scan Code 0xE028
0, // Scan Code 0xE029
0, // Scan Code 0xE02A
VK_LAUNCH_APP2, // Scan Code 0xE02B
0, // Scan Code 0xE02C
0, // Scan Code 0xE02D
0, // Scan Code 0xE02E
VK_APPS, // Scan Code 0xE02F
VK_BROWSER_FORWARD, // Scan Code 0xE030
0, // Scan Code 0xE031
VK_VOLUME_UP, // Scan Code 0xE032
0, // Scan Code 0xE033
VK_MEDIA_PLAY_PAUSE, // Scan Code 0xE034
0, // Scan Code 0xE035
0, // Scan Code 0xE036
0, // Scan Code 0xE037
VK_BROWSER_BACK, // Scan Code 0xE038
0, // Scan Code 0xE039
VK_BROWSER_HOME, // Scan Code 0xE03A
VK_MEDIA_STOP, // Scan Code 0xE03B
0, // Scan Code 0xE03C
0, // Scan Code 0xE03D
0, // Scan Code 0xE03E
VK_OFF, // Scan Code 0xE03F
VK_LAUNCH_APP1, // Scan Code 0xE040
0, // Scan Code 0xE041
0, // Scan Code 0xE042
0, // Scan Code 0xE043
0, // Scan Code 0xE044
0, // Scan Code 0xE045
0, // Scan Code 0xE046
0, // Scan Code 0xE047
VK_LAUNCH_MAIL, // Scan Code 0xE048
0, // Scan Code 0xE049
VK_DIVIDE, // Scan Code 0xE04A
0, // Scan Code 0xE04B
0, // Scan Code 0xE04C
VK_MEDIA_NEXT_TRACK, // Scan Code 0xE04D
0, // Scan Code 0xE04E
0, // Scan Code 0xE04F
VK_LAUNCH_MEDIA_SELECT, // Scan Code 0xE050
0, // Scan Code 0xE051
0, // Scan Code 0xE052
0, // Scan Code 0xE053
0, // Scan Code 0xE054
0, // Scan Code 0xE055
0, // Scan Code 0xE056
0, // Scan Code 0xE057
0, // Scan Code 0xE058
0, // Scan Code 0xE059
VK_RETURN, // Scan Code 0xE05A
0, // Scan Code 0xE05B
0, // Scan Code 0xE05C
0, // Scan Code 0xE05D
0, // Scan Code 0xE05E
0, // Scan Code 0xE05F
0, // Scan Code 0xE060
0, // Scan Code 0xE061
0, // Scan Code 0xE062
0, // Scan Code 0xE063
0, // Scan Code 0xE064
0, // Scan Code 0xE065
0, // Scan Code 0xE066
0, // Scan Code 0xE067
0, // Scan Code 0xE068
VK_END, // Scan Code 0xE069
0, // Scan Code 0xE06A
VK_LEFT, // Scan Code 0xE06B
VK_HOME, // Scan Code 0xE06C
0, // Scan Code 0xE06D
0, // Scan Code 0xE06E
0, // Scan Code 0xE06F
VK_INSERT, // Scan Code 0xE070
VK_DELETE, // Scan Code 0xE071
VK_DOWN, // Scan Code 0xE072
0, // Scan Code 0xE073
VK_RIGHT, // Scan Code 0xE074
VK_UP, // Scan Code 0xE075
0, // Scan Code 0xE076
0, // Scan Code 0xE077
0, // Scan Code 0xE078
0, // Scan Code 0xE079
VK_NEXT, // Scan Code 0xE07A
0, // Scan Code 0xE07B
VK_SNAPSHOT, // Scan Code 0xE07C
VK_PRIOR, // Scan Code 0xE07D
VK_CANCEL, // Scan Code 0xE07E
0, // Scan Code 0xE07F
};
#ifdef DEBUG
void
ValidateUsageToSc(
const USAGE_TO_SC_INFO *pUsageToScInfo
);
void
ValidateAllUsageToSc(
);
#else
#define ValidateUsageToSc(ptr)
#define ValidateAllUsageToSc()
#endif // DEBUG
DWORD
SendKeyboardUsages(
PHID_KBD pHidKbd,
PUSAGE_AND_PAGE puapUsages,
DWORD dwMaxUsages,
HIDP_KEYBOARD_DIRECTION keyEvent,
KEY_STATE_FLAGS *pKeyStateFlags
);
void
KeyboardEvent(
UINT vk,
UINT sc,
DWORD dwFlags
);
const USAGE_TO_SCANCODE *
FindUsageToSc(
USAGE usage
);
void
ProcessKeyboardReport(
PHID_KBD pHidKbd,
PCHAR pbHidPacket,
DWORD cbHidPacket
);
BOOL
AllocateUsageLists(
PHID_KBD pHidKbd,
size_t cbUsages
);
VOID
FreeHidKbd(
PHID_KBD pHidKbd
);
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);
RETAILMSG(1,(TEXT("Kbdhid::DllEntry %08x.\r\n"), dwReason ));
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, 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -