📄 jsthid.cpp
字号:
//extern "C"
BOOL
DllEntry(
HANDLE hDllHandle,
DWORD dwReason,
LPVOID lpReserved
)
{
RETAILMSG( 1, (TEXT(">DllEntry--joystick\r\n")));
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
)
{
// RETAILMSG( 1, (TEXT(">KeyboardThreadProc--joystick\r\n")));
PHID_KBD pHidKbd = (PHID_KBD) lpParameter;
PREFAST_DEBUGCHK(pHidKbd != NULL);
DEBUGCHK(pHidKbd->hevClosing != NULL); // Needed to signal exit
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
const DWORD cbMaxHidPacket = pHidKbd->hidpCaps.InputReportByteLength;
pHidKbd->pbInputBuffer = NULL;
pHidKbd->pbInputBuffer = (PCHAR) LocalAlloc(LMEM_FIXED, cbMaxHidPacket);
if (pHidKbd->pbInputBuffer == NULL) {
RETAILMSG( 1, (TEXT("LocalAlloc error:%d--joystick\r\n"), 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;
}
DWORD dwTimeout;
// 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;
}
DWORD cbHidPacket;
// Get an interrupt report from the device.
DWORD dwErr = pHidKbd->pHidFuncs->lpGetInterruptReport(
pHidKbd->hDevice,
pHidKbd->pbInputBuffer,
cbMaxHidPacket,
&cbHidPacket,
pHidKbd->hevClosing,
dwTimeout);
if (dwErr == ERROR_TIMEOUT) {
// Perform autorepeat
DEBUGCHK(pHidKbd->ARState != AR_WAIT_FOR_ANY);
DWORD cKeysSent = SendKeyboardUsages(pHidKbd->puapMakeUsages,
pHidKbd->dwMaxUsages, HidP_Keyboard_Make, &pHidKbd->KeyStateFlags);
DEBUGCHK(cKeysSent != 0);
pHidKbd->ARState = AR_AUTOREPEATING;
RETAILMSG(1, (_T("InterruptReport ERROR_TIMEOUT--jsthid\r\n")));
}
else if (dwErr != ERROR_SUCCESS) {
if ( (dwErr != ERROR_DEVICE_REMOVED) && (dwErr != ERROR_CANCELLED) ) {
//DEBUGMSG(ZONE_ERROR,
// (_T("%s: GetInterruptReport returned unexpected error %u\r\n"),
// pszFname, dwErr));
RETAILMSG(1,
(_T("GetInterruptReport returned unexpected error %u\r\n"),
dwErr));
}
// Exit thread
break;
}
else {
DEBUGCHK(cbHidPacket <= cbMaxHidPacket);
ProcessKeyboardReport(pHidKbd, pHidKbd->pbInputBuffer, cbHidPacket);
}
}
EXIT:
if (pHidKbd->pbInputBuffer != NULL)
LocalFree(pHidKbd->pbInputBuffer);
RETAILMSG(1, (_T("Exiting thread\r\n")));
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
)
{
RETAILMSG( 1, (TEXT(">HIDDeviceAttach--joystick\r\n")));
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) {
RETAILMSG(1, (_T("LocalAlloc error:%d\r\n"), 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()));
RETAILMSG(1, (_T("LocalAlloc error--joystick:%d\r\n"), GetLastError()));
goto EXIT;
}
pHidKbd->hevClosing = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pHidKbd->hevClosing == NULL) {
//DEBUGMSG(ZONE_ERROR, (_T("%s: Error creating event: %d\r\n"),
RETAILMSG(1, (_T("Error creating event--joystick: %d\r\n"),
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 ")
RETAILMSG(1, (_T("This collection does not have any ")
_T("understood usages and will be ignored--joystick\r\n")));
goto EXIT;
}
cbUsages = pHidKbd->dwMaxUsages * sizeof(USAGE_AND_PAGE);
if (AllocateUsageLists(pHidKbd, cbUsages) == FALSE) {
RETAILMSG(1, (_T("AllocateUsageLists failed--joystick\r\n")));
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) {
RETAILMSG(1, (_T("Failed creating keyboard thread--joystick\r\n")));
goto EXIT;
}
#ifdef DEBUG
pHidKbd->fhThreadInited = TRUE;
#endif
// Create the KBD device
pHidKbd->hOSDevice = ActivateDevice(pszClientKey, (DWORD) pHidKbd);
if (pHidKbd->hOSDevice == NULL) {
RETAILMSG(1, (_T("Error on ActivateDevice(%s)\r\n"), 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.
RETAILMSG(1, (_T("Initialization failed--joystick\r\n")));
FreeHidKbd(pHidKbd);
}
else
RETAILMSG(1, (_T("Initialization succeed--joystick\r\n")));
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
)
{
RETAILMSG( 1, (TEXT(">HIDDeviceNotifications--joystick\r\n")));
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));
RETAILMSG( 1, (TEXT("Received invalid structure pointer--joystick\r\n")));
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);
// Wait for KBD_Deinit to complete so we can free our context.
WaitForSingleObject(pHidKbd->hevClosing, INFINITE);
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
)
{
RETAILMSG( 1, (TEXT(">FlashLEDs--joystick\r\n")));
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
)
{
RETAILMSG( 1, (TEXT(">AllocateUsageLists--joystick\r\n")));
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()));
RETAILMSG( 1, (TEXT("LocalAlloc error:%d--joystick\r\n"),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
)
{
PREFAST_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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -