📄 jsthid.cpp
字号:
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
)
{
// RETAILMSG( 1, (TEXT(">ProcessKeyboardReport--joystick\r\n")));
BOOL fRollover = FALSE;
ULONG uCurrUsages;
DWORD dwUsageIdx;
DWORD cbUsageList;
DWORD cKeysSent;
NTSTATUS status;
static bool state=false;
PREFAST_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) {
//RETAILMSG(1, (_T("%s: HID keyboard rollover\r\n"), pszFname));
RETAILMSG(1, (_T("HID keyboard rollover\r\n")));
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
// if(state==false)
// {
// state=true;
// RETAILMSG(1, (_T("No new keys. Hardware autorepeat?--jsthid\r\n")));
// }
// Replace the list of recent downs.
memcpy(pHidKbd->puapMakeUsages, pHidKbd->puapOldMakeUsages, cbUsageList);
}
else
{
// if(state==true){
// state = false;
// RETAILMSG(1, (_T("New keys appear-------------------------------jsthid\r\n")));
// }
// 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;
}
}
}
}
}
// Expands a usage, scan code, and flags to a full scan code and virtual key.
static
void
GenerateKeyInfo(
const USAGE_TO_SCANCODE *pUsageToSc,
PUINT puiVk,
PUINT puiSc,
PDWORD pdwFlags,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent
)
{
RETAILMSG( 1, (TEXT(">GenerateKeyInfo--joystick\r\n")));
PREFAST_DEBUGCHK(pUsageToSc);
PREFAST_DEBUGCHK(puiVk);
PREFAST_DEBUGCHK(puiSc);
PREFAST_DEBUGCHK(pdwFlags);
*puiSc = pUsageToSc->uiSc;
*pdwFlags = 0;
if (hidpKeyEvent == HidP_Keyboard_Break) {
*pdwFlags |= KEYEVENTF_KEYUP;
}
// Prepend extended bits
switch (GET_EB(pUsageToSc->uiFlags)) {
case EB_E0:
*puiSc |= SC_EXTENDED_BITS;
*pdwFlags |= KEYEVENTF_EXTENDEDKEY;
break;
case EB_E114:
*puiSc |= SC_E1_BITS;
break;
case EB_NONE:
break;
default:
// Why are you here?
DEBUGCHK(FALSE);
};
// Convert scan code to virtual key
*puiVk = MapVirtualKey(*puiSc, MAP_SC_TO_VK);
}
// 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
)
{
// RETAILMSG( 1, (TEXT(">SendKeyboardUsages--joystick\r\n")));
PREFAST_DEBUGCHK(puapUsages != NULL);
DEBUGCHK(pKeyStateFlags != NULL);
for (DWORD dwIdx = 0; dwIdx < dwMaxUsages; ++dwIdx) {
// Determine virtual key mapping
PUSAGE_AND_PAGE puapCurr = &puapUsages[dwIdx];
const USAGE_TO_SCANCODE *pUsageToSc = NULL;
USAGE_TO_SCANCODE usageToSc; // For Consumer page
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:
pUsageToSc = FindUsageToSc(puapCurr->Usage);
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) {
const USAGE_TO_SC_ASSOCIATION *pUsageAssn =
&g_rgConsumerToScAssn[dwAssn];
// Later, we assume that this scan code is extended. If
// it is not, we need to dynamically assign the EB_E0 enum.
DEBUGCHK( (pUsageAssn->uiSc & SC_EXTENDED_BITS) == SC_EXTENDED_BITS );
if (pUsageAssn->usage == puapCurr->Usage) {
// Fill in the local USAGE_TO_SCANCODE
usageToSc.uiSc = (UINT8) pUsageAssn->uiSc;
usageToSc.uiFlags = MAKE_FLAGS(EB_E0, PT_STANDARD);
pUsageToSc = &usageToSc;
break;
}
}
break;
}
};
// Was there a conversion? If so, send the event.
if (pUsageToSc != NULL) {
DWORD dwFlags;
UINT uiSc;
UINT uiVk;
PFN_PROCESSING_TYPE pfnProcessingType;
ProcessingType PT;
GenerateKeyInfo(pUsageToSc, &uiVk, &uiSc, &dwFlags, hidpKeyEvent);
DEBUGMSG(ZONE_USAGES, (_T("%s: Usage Page: 0x%04x Usage: 0x%04x -> SC: 0x%06x\r\n"),
pszFname, puapCurr->UsagePage, puapCurr->Usage, uiSc));
// Determine which processing function to call
PT = GET_PT(pUsageToSc->uiFlags);
DEBUGCHK(dim(g_rgpfnProcessingType) == PT_COUNT);
DEBUGCHK(PT < PT_COUNT);
pfnProcessingType = g_rgpfnProcessingType[PT];
PREFAST_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
)
{
RETAILMSG( 1, (TEXT(">KeyboardEvent--joystick\r\n")));
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;
PREFAST_DEBUGCHK(pKeyStateFlags != NULL);
DEBUGCHK(vk != 0);
for (dwIdx = 0; dwIdx < dim(rgVKeyDownToShiftState); ++dwIdx) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -