📄 kbdist.cpp
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1998 Microsoft Corporation
@doc EXTERNAL DRIVERS
@module keybdist.cpp |
This file implements the interrupt service thread part of the platform
independent code of the keyboard driver. This is provided as a sample to
platform driver writers and is expected to be able to be used without
major modification on most hardware platforms.
*/
#include <windows.h>
#include <nkintr.h>
//#include <oalintr.h>
#include <keybddr.h>
#include <keybdpdd.h>
#ifdef DEBUG
DBGPARAM dpCurSettings = { TEXT("Keybd"), {
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined") },
0x00000000 };
#endif
// Auto repeat #defines and state variables.
#define AR_WAIT_FOR_ANY 0
#define AR_INITIAL_DELAY 1
#define AR_AUTOREPEATING 2
#define AR_AUTO_PARTIAL 3 // Auto repeat was interrupted by real PDD event.
#define AUTO_REPEAT_INITIAL_DELAY_MIN 250
#define AUTO_REPEAT_INITIAL_DELAY_MAX 1000
#define AUTO_REPEAT_INITIAL_DELAY_DEFAULT 500
#define AUTO_REPEAT_KEYS_PER_SEC_MIN 2
#define AUTO_REPEAT_KEYS_PER_SEC_MAX 30
#define AUTO_REPEAT_KEYS_PER_SEC_DEFAULT 20
static int v_AutoRepeatState = AR_WAIT_FOR_ANY;
static DWORD v_AutoRepeatInitialDelay = AUTO_REPEAT_INITIAL_DELAY_DEFAULT;
static DWORD v_AutoRepeatKeysPerSec = AUTO_REPEAT_KEYS_PER_SEC_DEFAULT;
static UINT32 v_AutoRepeatVKey;
static UINT32 v_AutoRepeatScanCode;
static KEY_STATE_FLAGS v_AutoRepeatKeyStateFlags;
// Routine to call back in to user when there is a keyboard event.
static PFN_KEYBD_EVENT_CALLBACK_EX v_pfnKeybdEventCallbackEx;
extern DWORD dwSysIntrPs2Ch1;
extern DWORD dwSysIntrKeyboard;
extern "C"
// @doc EXTERNAL DRIVERS
/* @func
Gives information about the keyboard and driver.
@rdesc If the function succeeds the return value is TRUE, otherwise, it is
FALSE. Extended error information is available via the GetLastError
function.
@xref
<tab><c KBDI_VKEY_TO_UNICODE_INFO_ID><nl>
<tab><c KBDI_AUTOREPEAT_INFO_ID><nl>
<tab><c KBDI_AUTOREPEAT_SELECTIONS_INFO_ID>
@comm This function must be re-entrant since it is exposed by the input
system via the <f KeybdGetDeviceInfo> function and may be called by
multiple threads.
*/
BOOL KeybdDriverGetInfo(
INT iKeybdId, // @parm Id of the keyboard to get the information from.
INT iIndex, // @parm Id of info to retrieve.
LPVOID lpOutput // @parm Output buffer.
)
{
if ( lpOutput == NULL )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
switch ( iIndex )
{
case KBDI_VKEY_TO_UNICODE_INFO_ID:
VKeyToUnicodeInfo((struct KBDI_VKEY_TO_UNICODE_INFO*)lpOutput);
break;
case KBDI_AUTOREPEAT_INFO_ID:
{
struct KBDI_AUTOREPEAT_INFO *pInfo =
(struct KBDI_AUTOREPEAT_INFO*)lpOutput;
pInfo -> CurrentInitialDelay = v_AutoRepeatInitialDelay;
pInfo -> CurrentRepeatRate = v_AutoRepeatKeysPerSec;
pInfo -> cInitialDelaysSelectable = -1;
pInfo -> cRepeatRatesSelectable = -1;
}
break;
case KBDI_AUTOREPEAT_SELECTIONS_INFO_ID:
{
INT32 *pInfo = (INT32*)lpOutput;
*(pInfo) = AUTO_REPEAT_INITIAL_DELAY_MIN; // Min initial delay
*(pInfo+1) = AUTO_REPEAT_INITIAL_DELAY_MAX; // Max initial delay
*(pInfo+2) = AUTO_REPEAT_KEYS_PER_SEC_MIN; // Min repeat rate
*(pInfo+3) = AUTO_REPEAT_KEYS_PER_SEC_MAX; // Max repeat rate
}
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_GET_INFO v_pfnGetInfoTest = KeybdDriverGetInfo;
#endif
extern "C"
// @doc EXTERNAL DRIVERS
/* @func
Sets information about the keyboard device.
@rdesc If the function succeeds the return value is TRUE, otherwise, it is
FALSE. Extended error information is available via the GetLastError
function.
@xref
<tab><f KeybdDriverGetIno><nl>
<tab><c KBDI_AUTOREPEAT_INFO_ID><nl>
--*/
BOOL KeybdDriverSetMode(
INT iKeybdId, // @parm Id of the keyboard to set the information.
INT iIndex, // @parm Id of info to set.
LPVOID lpInput // @parm Input buffer.
)
{
if ( lpInput == NULL )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
switch ( iIndex )
{
case KBDI_AUTOREPEAT_INFO_ID:
{
struct KBDI_AUTOREPEAT_INFO *pInfo =
(struct KBDI_AUTOREPEAT_INFO*)lpInput;
if ( pInfo -> CurrentInitialDelay > AUTO_REPEAT_INITIAL_DELAY_MAX )
{
// RETAILMSG(1,
// (TEXT("Initial delay too large, using %d\r\n"),
// AUTO_REPEAT_INITIAL_DELAY_MAX));
v_AutoRepeatInitialDelay = AUTO_REPEAT_INITIAL_DELAY_MAX;
}
else if ( pInfo -> CurrentInitialDelay < AUTO_REPEAT_INITIAL_DELAY_MIN )
{
// RETAILMSG(1,
// (TEXT("Initial delay too small, using %d\r\n"),
// AUTO_REPEAT_INITIAL_DELAY_MIN));
v_AutoRepeatInitialDelay = AUTO_REPEAT_INITIAL_DELAY_MIN;
}
else
{
v_AutoRepeatInitialDelay = pInfo -> CurrentInitialDelay;
}
if ( pInfo -> CurrentRepeatRate > AUTO_REPEAT_KEYS_PER_SEC_MAX )
{
// RETAILMSG(1,
// (TEXT("Initial repeat rate too large, using %d\r\n"),
// AUTO_REPEAT_KEYS_PER_SEC_MAX));
v_AutoRepeatKeysPerSec = AUTO_REPEAT_KEYS_PER_SEC_MAX;
}
else if ( ( pInfo -> CurrentRepeatRate < AUTO_REPEAT_KEYS_PER_SEC_MIN ) &&
( pInfo -> CurrentRepeatRate != 0 ) )
{
// RETAILMSG(1,
// (TEXT("Initial repeat rate too small, using %d\r\n"),
// AUTO_REPEAT_KEYS_PER_SEC_MIN));
v_AutoRepeatKeysPerSec = AUTO_REPEAT_KEYS_PER_SEC_MIN;
}
else
{
v_AutoRepeatKeysPerSec = pInfo -> CurrentRepeatRate;
}
}
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_SET_MODE v_pfnSetModeTest = KeybdDriverSetMode;
#endif
/*++
KeybdDriverThread:
Keyboard driver interrupt service thread.
Return Value:
Never returns.
--*/
BOOL
KeybdIstLoop(
HANDLE hevInterrupt
)
{
UINT32 VKeyBuf[16]; // hardcoded w/ PDD.
UINT32 ScanCodeBuf[16]; // hardcoded w/ PDD.
KEY_STATE_FLAGS KeyStateFlagsBuf[16]; // hardcoded w/ PDD.
UINT32 RemapVKeyBuf[16];
UINT32 RemapScanCodeBuf[16];
KEY_STATE_FLAGS RemapKeyStateFlagsBuf[16];
int cKeyEvents;
int iKeyEventIdx;
int cRemapEvents;
int iRemapIdx;
DWORD AutoRepeatKeysPerSec;
long AutoRepeatTimeout;
BOOL fSendAutoRepeatKey;
DWORD MRKeyTimeForPolling = 0; // Get rid of compiler uninitialized variable warning.
// RETAILMSG(1, (TEXT("KeybdIstLoop\r\n")));
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
AutoRepeatTimeout = INFINITE;
wait_for_keybd_interrupt:
fSendAutoRepeatKey = FALSE;
// Grab a copy once w/o critical section.
AutoRepeatKeysPerSec = v_AutoRepeatKeysPerSec;
// 0 keys per second => auto repeat disabled.
if ( AutoRepeatKeysPerSec == 0 )
v_AutoRepeatState = AR_WAIT_FOR_ANY;
if ( v_AutoRepeatState == AR_WAIT_FOR_ANY )
{
//RETAILMSG(1,(TEXT("AR_WAIT_FOR_ANY\r\n")));
AutoRepeatTimeout = INFINITE;
}
else if ( v_AutoRepeatState == AR_INITIAL_DELAY )
{
//RETAILMSG(1,(TEXT("AR_INITIAL_DELAY\r\n")));
AutoRepeatTimeout = v_AutoRepeatInitialDelay;
}
else if ( v_AutoRepeatState == AR_AUTO_PARTIAL )
{
//RETAILMSG(1,(TEXT("AR_AUTO_PARTIAL\r\n")));
long lTemp = AutoRepeatTimeout - (GetTickCount() - MRKeyTimeForPolling);
AutoRepeatTimeout = (lTemp > 0) ? lTemp : 0;
}
else
{
//RETAILMSG(1,(TEXT("ELSE\r\n")));
AutoRepeatTimeout = 1000/AutoRepeatKeysPerSec;
}
MRKeyTimeForPolling = GetTickCount();
if ( WaitForSingleObject(hevInterrupt, AutoRepeatTimeout) == WAIT_TIMEOUT )
{
/* On power off, the v_AutoRepeatState is set to AR_WAIT_FOR_ANY, but we
cannot reset the WaitForSingleObject timeout value. This means that when
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -