📄 kbdhid.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
//
#include "kbdhid.h"
//#undef RETAILMSG
//#define RETAILMSG(x,y) NKDbgPrintfW y
#ifdef DEBUG
// Debug Zones
#define DBG_ERROR 0x0001
#define DBG_WARNING 0x0002
#define DBG_INIT 0x0004
#define DBG_FUNCTION 0x0008
#define DBG_USAGES 0x0010
DBGPARAM dpCurSettings = {
TEXT("KbdHid"), {
TEXT("Errors"), TEXT("Warnings"), TEXT("Init"), TEXT("Function"),
TEXT("Usages"), TEXT(""), TEXT(""), TEXT(""),
TEXT(""), TEXT(""), TEXT(""), TEXT(""),
TEXT(""), TEXT(""), TEXT(""), TEXT("") },
DBG_ERROR | DBG_WARNING };
#endif // DEBUG
// MapVirtualKey(x, 3) converts scan codes to virtual keys
#define MAP_SC_TO_VK 3
#define SC_PRTSCRN 0xE07C
#define SC_PAUSE 0xE11477
// Zero usage and page for convenience
static const USAGE_AND_PAGE g_uapZero = { 0, 0 };
// Variables used by the Japanese key remapper. Global, so simultaneous
// use of two Japanese HID keyboards might cause certain Japanese remappings
// to produce the incorrect virtual key.
static UINT8 v_vkAlphaNumSent;
static UINT8 v_vkFullHalfSent;
static UINT8 v_vkHiraKataSent;
// AutoRepeat variables. Global since all HID keyboards share the same
// timings. Not protected since the Layout Manager serializes change
// requests (IOCTLs).
DWORD g_dwAutoRepeatInitialDelay = KBD_AUTO_REPEAT_INITIAL_DELAY_DEFAULT;
DWORD g_dwAutoRepeatKeysPerSec = KBD_AUTO_REPEAT_KEYS_PER_SEC_DEFAULT;
// Defines for checking the state of modifier keys
#define ANY_ALT_DOWN() (*pKeyStateFlags & (KeyShiftLeftAltFlag | KeyShiftRightAltFlag))
#define ANY_CTRL_DOWN() (*pKeyStateFlags & (KeyShiftLeftCtrlFlag | KeyShiftRightCtrlFlag))
#define ANY_SHIFT_DOWN() (*pKeyStateFlags & (KeyShiftLeftShiftFlag | KeyShiftRightShiftFlag))
#define IS_NUMLOCK_ENABLED() ((*pKeyStateFlags & KeyShiftNumLockFlag) != 0)
#define IS_CAPSLOCK_ENABLED() ((*pKeyStateFlags & KeyShiftCapitalFlag) != 0)
#define IS_SCROLLLOCK_ENABLED() ((*pKeyStateFlags & KeyShiftScrollLockFlag) != 0)
// Two bits represent extended bytes to prepend to the scan codes.
enum ExtendedBytes {
EB_NONE = 0,
EB_E0,
EB_E114,
EB_COUNT,
};
// Six bits represent the type of processing that needs to be performed.
enum ProcessingType {
PT_STANDARD = 0,
PT_MODIFIER,
PT_NUMPAD,
PT_SPECIAL,
PT_JPN,
PT_NO_BREAK,
PT_COUNT,
};
// Describes a Scan Code that is associated with a Usage
struct USAGE_TO_SCANCODE {
UINT8 uiFlags; // Top six bits = ProcessingType. Bottom two = ExtendedBytes
UINT8 uiSc;
};
// Describes an association from a Usage to an AT Scan Code
struct USAGE_TO_SC_ASSOCIATION {
USAGE usage;
UINT16 uiSc;
};
// Helper macros to get the right bits out of and into the uiFlags field.
#define SET_EB(x) ((x) & 0x3)
#define GET_EB(flags) ( (ExtendedBytes) ((flags) & 0x3) )
#define SET_PT(x) ((x) << 2)
#define GET_PT(flags) ( (ProcessingType) ((UINT8) ((flags) >> 2)) )
#define MAKE_FLAGS(eb, pt) (SET_EB(eb) | SET_PT(pt))
// The general Usage to AT Scan Code mapping.
#define FIRST_USAGE 0
#define LAST_USAGE (FIRST_USAGE + dim(g_rgUsageToSc) - 1)
static const USAGE_TO_SCANCODE g_rgUsageToSc[] = {
{ 0, 0x00 }, // 00 - No Event
{ 0, 0x00 }, // 01 - Overrun
{ 0, 0x00 }, // 02 - POST Fail
{ 0, 0x00 }, // 03 - ErrorUndefined
{ 0, 0x1C }, // 04 - a A
{ 0, 0x32 }, // 05 - b B
{ 0, 0x21 }, // 06 - c C
{ 0, 0x23 }, // 07 - d D
{ 0, 0x24 }, // 08 - e E
{ 0, 0x2B }, // 09 - f F
{ 0, 0x34 }, // 0a - g G
{ 0, 0x33 }, // 0b - h H
{ 0, 0x43 }, // 0c - i I
{ 0, 0x3B }, // 0d - j J
{ 0, 0x42 }, // 0e - k K
{ 0, 0x4B }, // 0f - l L
{ 0, 0x3A }, // 10 - m M
{ 0, 0x31 }, // 11 - n N
{ 0, 0x44 }, // 12 - o O
{ 0, 0x4D }, // 13 - p P
{ 0, 0x15 }, // 14 - q Q
{ 0, 0x2D }, // 15 - r R
{ 0, 0x1B }, // 16 - s S
{ 0, 0x2C }, // 17 - t T
{ 0, 0x3C }, // 18 - u U
{ 0, 0x2A }, // 19 - v V
{ 0, 0x1D }, // 1a - w W
{ 0, 0x22 }, // 1b - x X
{ 0, 0x35 }, // 1c - y Y
{ 0, 0x1A }, // 1d - z Z
{ 0, 0x16 }, // 1e - 1 !
{ 0, 0x1E }, // 1f - 2 @
{ 0, 0x26 }, // 20 - 3 #
{ 0, 0x25 }, // 21 - 4 $
{ 0, 0x2E }, // 22 - 5 %
{ 0, 0x36 }, // 23 - 6 ^
{ 0, 0x3D }, // 24 - 7 &
{ 0, 0x3E }, // 25 - 8 *
{ 0, 0x46 }, // 26 - 9 (
{ 0, 0x45 }, // 27 - 0 )
{ 0, 0x5A }, // 28 - Return
{ 0, 0x76 }, // 29 - Escape
{ 0, 0x66 }, // 2a - Backspace
{ 0, 0x0D }, // 2b - Tab
{ 0, 0x29 }, // 2c - Space
{ 0, 0x4E }, // 2d - - _
{ 0, 0x55 }, // 2e - = +
{ 0, 0x54 }, // 2f - [ {
{ 0, 0x5B }, // 30 - ] }
{ 0, 0x5D }, // 31 - \ |
{ 0, 0x5D }, // 32 - Europe 1 (Note 2)
{ 0, 0x4C }, // 33 - ; :
{ 0, 0x52 }, // 34 - "' """
{ MAKE_FLAGS(0, PT_JPN), 0x0E }, // 35 - ` ~
{ 0, 0x41 }, // 36 - ", <"
{ 0, 0x49 }, // 37 - . >
{ 0, 0x4A }, // 38 - / ?
{ MAKE_FLAGS(0, PT_JPN), 0x58 }, // 39 - Caps Lock
{ 0, 0x05 }, // 3a - F1
{ 0, 0x06 }, // 3b - F2
{ 0, 0x04 }, // 3c - F3
{ 0, 0x0C }, // 3d - F4
{ 0, 0x03 }, // 3e - F5
{ 0, 0x0B }, // 3f - F6
{ 0, 0x83 }, // 40 - F7
{ 0, 0x0A }, // 41 - F8
{ 0, 0x01 }, // 42 - F9
{ 0, 0x09 }, // 43 - F10
{ 0, 0x78 }, // 44 - F11
{ 0, 0x07 }, // 45 - F12
{ MAKE_FLAGS(EB_E0, PT_SPECIAL), 0x7C }, // 46 - Print Screen (Note 1)
{ 0, 0x7E }, // 47 - Scroll Lock
{ MAKE_FLAGS(EB_E114, PT_SPECIAL), 0x77 }, // 48 - Pause
{ MAKE_FLAGS(EB_E0, 0), 0x70 }, // 49 - Insert (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x6C }, // 4a - Home (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x7D }, // 4b - Page Up (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x71 }, // 4c - Delete (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x69 }, // 4d - End (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x7A }, // 4e - Page Down (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x74 }, // 4f - Right Arrow (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x6B }, // 50 - Left Arrow (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x72 }, // 51 - Down Arrow (Note 1)
{ MAKE_FLAGS(EB_E0, 0), 0x75 }, // 52 - Up Arrow (Note 1)
{ 0, 0x77 }, // 53 - Num Lock
{ MAKE_FLAGS(EB_E0, 0), 0x4A }, // 54 - Keypad / (Note 1)
{ 0, 0x7C }, // 55 - Keypad *
{ 0, 0x7B }, // 56 - Keypad -
{ 0, 0x79 }, // 57 - Keypad +
{ MAKE_FLAGS(EB_E0, 0), 0x5A }, // 58 - Keypad Enter
{ MAKE_FLAGS(0, PT_NUMPAD), 0x69 }, // 59 - Keypad 1 End
{ MAKE_FLAGS(0, PT_NUMPAD), 0x72 }, // 5a - Keypad 2 Down
{ MAKE_FLAGS(0, PT_NUMPAD), 0x7A }, // 5b - Keypad 3 PageDn
{ MAKE_FLAGS(0, PT_NUMPAD), 0x6B }, // 5c - Keypad 4 Left
{ MAKE_FLAGS(0, PT_NUMPAD), 0x73 }, // 5d - Keypad 5
{ MAKE_FLAGS(0, PT_NUMPAD), 0x74 }, // 5e - Keypad 6 Right
{ MAKE_FLAGS(0, PT_NUMPAD), 0x6C }, // 5f - Keypad 7 Home
{ MAKE_FLAGS(0, PT_NUMPAD), 0x75 }, // 60 - Keypad 8 Up
{ MAKE_FLAGS(0, PT_NUMPAD), 0x7D }, // 61 - Keypad 9 PageUp
{ MAKE_FLAGS(0, PT_NUMPAD), 0x70 }, // 62 - Keypad 0 Insert
{ MAKE_FLAGS(0, PT_NUMPAD), 0x71 }, // 63 - Keypad . Delete
{ 0, 0x61 }, // 64 - Europe 2 (Note 2)
{ MAKE_FLAGS(EB_E0, 0), 0x2F }, // 65 - App
{ 0, 0x00 }, // 66 - Keyboard Power
{ 0, 0x0F }, // 67 - Keypad =
{ 0, 0x2F }, // 68 - F13
{ 0, 0x37 }, // 69 - F14
{ 0, 0x3F }, // 6a - F15
};
// Mapping from international Usages to AT Scan Codes
#define FIRST_GLOBAL_USAGE 0x85
#define LAST_GLOBAL_USAGE (FIRST_GLOBAL_USAGE + dim(g_rgGlobalUsageToSc) - 1)
static const USAGE_TO_SCANCODE g_rgGlobalUsageToSc[] =
{
{ 0, 0x51 }, // 85 - Keybad , (Brazillian)
{ 0, 0x00 }, // 86 - Keypad =
{ MAKE_FLAGS(0, PT_JPN), 0x51 }, // 87 - Ro
{ MAKE_FLAGS(0, PT_JPN), 0x13 }, // 88 - Katakana/Hiragana
{ MAKE_FLAGS(0, PT_JPN), 0x6A }, // 89 - Yen
{ MAKE_FLAGS(0, PT_JPN), 0x64 }, // 8a - Henkan
{ MAKE_FLAGS(0, PT_JPN), 0x67 }, // 8b - Muhenkan
{ 0, 0x00 }, // 8c - Int'l 6
{ 0, 0x00 }, // 8d - Int'l 7
{ 0, 0x00 }, // 8e - Int'l 8
{ 0, 0x00 }, // 8f - Int'l 9
{ MAKE_FLAGS(0, PT_NO_BREAK), 0xF2 }, // 90 - Hanguel/English
{ MAKE_FLAGS(0, PT_NO_BREAK), 0xF1 }, // 91 - Hanja
{ 0, 0x63 }, // 92 - LANG Katakana
{ 0, 0x62 }, // 93 - LANG Hiragana
{ 0, 0x5F }, // 94 - LANG Zenkaku/Hankaku
};
// Mapping from modifier Usages to AT Scan Codes
#define FIRST_MODIFIER_USAGE 0xE0
#define LAST_MODIFIER_USAGE (FIRST_MODIFIER_USAGE + dim(g_rgModifierUsageToSc) - 1)
static const USAGE_TO_SCANCODE g_rgModifierUsageToSc[] = {
{ MAKE_FLAGS(0, PT_MODIFIER), 0x14 }, // E0 - Left Control
{ MAKE_FLAGS(0, PT_MODIFIER), 0x12 }, // E1 - Left Shift
{ MAKE_FLAGS(0, PT_MODIFIER), 0x11 }, // E2 - Left Alt
{ MAKE_FLAGS(EB_E0, PT_MODIFIER), 0x1F }, // E3 - Left GUI
{ MAKE_FLAGS(EB_E0, PT_MODIFIER), 0x14 }, // E4 - Right Control
{ MAKE_FLAGS(0, PT_MODIFIER), 0x59 }, // E5 - Right Shift
{ MAKE_FLAGS(EB_E0, PT_MODIFIER), 0x11 }, // E6 - Right Alt
{ MAKE_FLAGS(EB_E0, PT_MODIFIER), 0x27 }, // E7 - Right GUI
};
// Describes a table listing a direct mapping from Usages to Scan Codes
struct USAGE_TO_SC_INFO {
const USAGE_TO_SCANCODE *pUsageToSc;
USHORT uFirstUsage;
USHORT uLastUsage;
};
// Our list of direct Usage to Virtual Key mapping tables
static const USAGE_TO_SC_INFO g_rgUsageToScInfo[] = {
{ g_rgModifierUsageToSc, FIRST_MODIFIER_USAGE, LAST_MODIFIER_USAGE },
{ g_rgUsageToSc, FIRST_USAGE, LAST_USAGE },
{ g_rgGlobalUsageToSc, FIRST_GLOBAL_USAGE, LAST_GLOBAL_USAGE },
};
// Consumer page (0xC) usage to virtual key.
// Note that most Consumer usages will be sent in
// Consumer Control (0xC 0x1) top level collections
// and will be handled in the consumer control client.
static const USAGE_TO_SC_ASSOCIATION g_rgConsumerToScAssn[] = {
{ 0x018A, 0xE048 }, // 018A - Mail
{ 0x0221, 0xE010 }, // 0221 - WWW Search
{ 0x0223, 0xE03A }, // 0223 - WWW Home
{ 0x0224, 0xE038 }, // 0224 - WWW Back
{ 0x0225, 0xE030 }, // 0225 - WWW Forward
{ 0x0226, 0xE028 }, // 0226 - WWW Stop
{ 0x0227, 0xE020 }, // 0227 - WWW Refresh
{ 0x022A, 0xE018 }, // 022A - WWW Favorites
};
// Declare all the processing functions.
typedef void (*PFN_PROCESSING_TYPE) (
UINT uiVk,
UINT uiSc,
DWORD dwFlags,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
KEY_STATE_FLAGS *pKeyStateFlags
);
#define DECLARE_PROCESSING_TYPE_FN(fn) void Process ## fn ## ( \
UINT uiVk, UINT uiSc, DWORD dwFlags, HIDP_KEYBOARD_DIRECTION hidpKeyEvent, \
KEY_STATE_FLAGS *pKeyStateFlags)
DECLARE_PROCESSING_TYPE_FN(Standard);
DECLARE_PROCESSING_TYPE_FN(Modifier);
DECLARE_PROCESSING_TYPE_FN(NumPad);
DECLARE_PROCESSING_TYPE_FN(Special);
DECLARE_PROCESSING_TYPE_FN(Jpn);
DECLARE_PROCESSING_TYPE_FN(NoBreak);
// Array of processing functions. Indexed by a ProcessingType.
static const PFN_PROCESSING_TYPE g_rgpfnProcessingType[] = {
&ProcessStandard,
&ProcessModifier,
&ProcessNumPad,
&ProcessSpecial,
&ProcessJpn,
&ProcessNoBreak,
};
#define ScanCodeTableFirst 0x00
#define ScanCodeTableLast 0x8f
static UINT8 ScanCodeToVKeyTable[] =
{
0, // Scan Code 0x0
VK_F9, // Scan Code 0x1
0, // Scan Code 0x2
VK_F5, // Scan Code 0x3
VK_F3, // Scan Code 0x4
VK_F1, // Scan Code 0x5
VK_F2, // Scan Code 0x6
VK_F12, // Scan Code 0x7
0, // Scan Code 0x8
VK_F10, // Scan Code 0x9
VK_F8, // Scan Code 0xA
VK_F6, // Scan Code 0xB
VK_F4, // Scan Code 0xC
VK_TAB, // Scan Code 0xD
VK_BACKQUOTE, // Scan Code 0xE
0, // Scan Code 0xF
0, // Scan Code 0x10
VK_LMENU, // Scan Code 0x11
VK_LSHIFT, // Scan Code 0x12
0, // Scan Code 0x13
VK_LCONTROL, // Scan Code 0x14
'Q', // Scan Code 0x15
'1', // Scan Code 0x16
0, // Scan Code 0x17
0, // Scan Code 0x18
0, // Scan Code 0x19
'Z', // Scan Code 0x1A
'S', // Scan Code 0x1B
'A', // Scan Code 0x1C
'W', // Scan Code 0x1D
'2', // Scan Code 0x1E
0, // Scan Code 0x1F
0, // Scan Code 0x20
'C', // Scan Code 0x21
'X', // Scan Code 0x22
'D', // Scan Code 0x23
'E', // Scan Code 0x24
'4', // Scan Code 0x25
'3', // Scan Code 0x26
0, // Scan Code 0x27
0, // Scan Code 0x28
VK_SPACE, // Scan Code 0x29
'V', // Scan Code 0x2A
'F', // Scan Code 0x2B
'T', // Scan Code 0x2C
'R', // Scan Code 0x2D
'5', // Scan Code 0x2E
0, // Scan Code 0x2F
0, // Scan Code 0x30
'N', // Scan Code 0x31
'B', // Scan Code 0x32
'H', // Scan Code 0x33
'G', // Scan Code 0x34
'Y', // Scan Code 0x35
'6', // Scan Code 0x36
0, // Scan Code 0x37
0, // Scan Code 0x38
0, // Scan Code 0x39
'M', // Scan Code 0x3A
'J', // Scan Code 0x3B
'U', // Scan Code 0x3C
'7', // Scan Code 0x3D
'8', // Scan Code 0x3E
0, // Scan Code 0x3F
0, // Scan Code 0x40
VK_COMMA, // Scan Code 0x41
'K', // Scan Code 0x42
'I', // Scan Code 0x43
'O', // Scan Code 0x44
'0', // Scan Code 0x45
'9', // Scan Code 0x46
0, // Scan Code 0x47
0, // Scan Code 0x48
VK_PERIOD, // Scan Code 0x49
VK_SLASH, // Scan Code 0x4A
'L', // Scan Code 0x4B
VK_SEMICOLON, // Scan Code 0x4C
'P', // Scan Code 0x4D
VK_HYPHEN, // Scan Code 0x4E
0, // Scan Code 0x4F
0, // Scan Code 0x50
0, // Scan Code 0x51
VK_APOSTROPHE, // Scan Code 0x52
0, // Scan Code 0x53
VK_LBRACKET, // Scan Code 0x54
VK_EQUAL, // Scan Code 0x55
0, // Scan Code 0x56
0, // Scan Code 0x57
VK_CAPITAL, // Scan Code 0x58
VK_RSHIFT, // Scan Code 0x59
VK_RETURN, // Scan Code 0x5A
VK_RBRACKET, // Scan Code 0x5B
0, // Scan Code 0x5C
VK_BACKSLASH, // Scan Code 0x5D
0, // Scan Code 0x5E
0, // Scan Code 0x5F
0, // Scan Code 0x60
0, // Scan Code 0x61
0, // Scan Code 0x62
0, // Scan Code 0x63
0, // Scan Code 0x64
0, // Scan Code 0x65
VK_BACK, // Scan Code 0x66
0, // Scan Code 0x67
0, // Scan Code 0x68
VK_NUMPAD1, // Scan Code 0x69
0, // Scan Code 0x6A
VK_NUMPAD4, // Scan Code 0x6B
VK_NUMPAD7, // Scan Code 0x6C
0, // Scan Code 0x6D
0, // Scan Code 0x6E
0, // Scan Code 0x6F
VK_NUMPAD0, // Scan Code 0x70
VK_DECIMAL, // Scan Code 0x71
VK_NUMPAD2, // Scan Code 0x72
VK_NUMPAD5, // Scan Code 0x73
VK_NUMPAD6, // Scan Code 0x74
VK_NUMPAD8, // Scan Code 0x75
VK_ESCAPE, // Scan Code 0x76
VK_NUMLOCK, // Scan Code 0x77
VK_F11, // Scan Code 0x78
VK_ADD, // Scan Code 0x79
VK_NUMPAD3, // Scan Code 0x7A
VK_SUBTRACT, // Scan Code 0x7B
VK_MULTIPLY, // Scan Code 0x7C
VK_NUMPAD9, // Scan Code 0x7D
VK_SCROLL, // Scan Code 0x7E
0, // Scan Code 0x7F
0, // Scan Code 0x80
0, // Scan Code 0x81
0, // Scan Code 0x82
VK_F7, // Scan Code 0x83
VK_SNAPSHOT, // Scan Code 0x84
0, // Scan Code 0x85
0, // Scan Code 0x86
0, // Scan Code 0x87
0, // Scan Code 0x88
0, // Scan Code 0x89
0, // Scan Code 0x8A
0, // Scan Code 0x8B
0, // Scan Code 0x8C
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -