/*++ Copyright (c) 2012 Minoca Corp. All Rights Reserved Module Name: scancode.c Abstract: This module impelements support for converting between scancodes used in keyboards to OS key abstractions. Author: Evan Green 21-Dec-2012 Environment: Kernel --*/ // // ------------------------------------------------------------------- Includes // #include #include "i8042.h" // // ---------------------------------------------------------------- Definitions // #define MAX_SCAN_CODE_1 0x7F #define SCAN_CODE_1_KEY_UP 0x80 #define SCAN_CODE_1_EXTENDED_KEY_COUNT 41 #define SCAN_CODE_1_EXTENDED_2_KEY_COUNT 1 // // ------------------------------------------------------ Data Type Definitions // typedef struct _EXTENDED_KEY_DESCRIPTION { UCHAR ScanCode; KEYBOARD_KEY Key; } EXTENDED_KEY_DESCRIPTION, *PEXTENDED_KEY_DESCRIPTION; typedef struct _EXTENDED_2_KEY_DESCRIPTION { UCHAR ScanCode1; UCHAR ScanCode2; KEYBOARD_KEY Key; } EXTENDED_2_KEY_DESCRIPTION, *PEXTENDED_2_KEY_DESCRIPTION; // // ----------------------------------------------- Internal Function Prototypes // // // -------------------------------------------------------------------- Globals // KEYBOARD_KEY I8042ScanCodeSet1KeyTable[MAX_SCAN_CODE_1] = { KeyboardKeyInvalid, /* 00 */ KeyboardKeyEscape, KeyboardKey1, KeyboardKey2, KeyboardKey3, KeyboardKey4, KeyboardKey5, KeyboardKey6, KeyboardKey7, KeyboardKey8, KeyboardKey9, KeyboardKey0, KeyboardKeyDash, KeyboardKeyEquals, KeyboardKeyBackspace, KeyboardKeyTab, KeyboardKeyQ, /* 10 */ KeyboardKeyW, KeyboardKeyE, KeyboardKeyR, KeyboardKeyT, KeyboardKeyY, KeyboardKeyU, KeyboardKeyI, KeyboardKeyO, KeyboardKeyP, KeyboardKeyLeftBracket, KeyboardKeyRightBracket, KeyboardKeyEnter, KeyboardKeyLeftControl, KeyboardKeyA, KeyboardKeyS, KeyboardKeyD, /* 20 */ KeyboardKeyF, KeyboardKeyG, KeyboardKeyH, KeyboardKeyJ, KeyboardKeyK, KeyboardKeyL, KeyboardKeySemicolon, KeyboardKeyApostrophe, KeyboardKeyTilde, KeyboardKeyLeftShift, KeyboardKeyBackslash, KeyboardKeyZ, KeyboardKeyX, KeyboardKeyC, KeyboardKeyV, KeyboardKeyB, /* 30 */ KeyboardKeyN, KeyboardKeyM, KeyboardKeyComma, KeyboardKeyPeriod, KeyboardKeySlash, KeyboardKeyRightShift, KeyboardKeyKeypadAsterisk, KeyboardKeyLeftAlt, KeyboardKeySpace, KeyboardKeyCapsLock, KeyboardKeyF1, KeyboardKeyF2, KeyboardKeyF3, KeyboardKeyF4, KeyboardKeyF5, KeyboardKeyF6, /* 40 */ KeyboardKeyF7, KeyboardKeyF8, KeyboardKeyF9, KeyboardKeyF10, KeyboardKeyNumLock, KeyboardKeyScrollLock, KeyboardKeyKeypad7, KeyboardKeyKeypad8, KeyboardKeyKeypad9, KeyboardKeyKeypadMinus, KeyboardKeyKeypad4, KeyboardKeyKeypad5, KeyboardKeyKeypad6, KeyboardKeyKeypadPlus, KeyboardKeyKeypad1, KeyboardKeyKeypad2, /* 50 */ KeyboardKeyKeypad3, KeyboardKeyKeypad0, KeyboardKeyKeypadPeriod, KeyboardKeySysRq, KeyboardKeyInvalid, KeyboardKeyInternational1, KeyboardKeyF11, KeyboardKeyF12, KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyF13, KeyboardKeyF14, KeyboardKeyF15, KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyInvalid, /* 60 */ KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyF16, KeyboardKeyF17, KeyboardKeyF18, KeyboardKeyF19, KeyboardKeyF20, KeyboardKeyF21, KeyboardKeyF22, KeyboardKeyF23, KeyboardKeyF24, KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyKatakana, /* 70 */ KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyInternational3, KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyInvalid, KeyboardKeyFurigana, KeyboardKeyInvalid, KeyboardKeyKanji, KeyboardKeyInvalid, KeyboardKeyHirijana, KeyboardKeyInvalid, KeyboardKeyInternational4, KeyboardKeyInternational5, }; EXTENDED_KEY_DESCRIPTION I8042ScanCodeSet1ExtendedKeyTable[SCAN_CODE_1_EXTENDED_KEY_COUNT] = { {0x07, KeyboardKeyRedo}, {0x08, KeyboardKeyUndo}, {0x0A, KeyboardKeyPaste}, {0x10, KeyboardKeySkipBack}, {0x17, KeyboardKeyCut}, {0x18, KeyboardKeyCopy}, {0x19, KeyboardKeySkipForward}, {0x1C, KeyboardKeyKeypadEnter}, {0x1D, KeyboardKeyRightControl}, {0x1E, KeyboardKeyMail}, {0x20, KeyboardKeyMute}, {0x22, KeyboardKeyPlay}, {0x24, KeyboardKeyStop}, {0x2C, KeyboardKeyEject}, {0x2E, KeyboardKeyVolumeDown}, {0x30, KeyboardKeyVolumeUp}, {0x32, KeyboardKeyWeb}, {0x35, KeyboardKeyKeypadSlash}, {0x37, KeyboardKeyPrintScreen}, {0x38, KeyboardKeyRightAlt}, {0x3B, KeyboardKeyHelp}, {0x3C, KeyboardKeyMusic}, {0x46, KeyboardKeyBreak}, {0x47, KeyboardKeyHome}, {0x48, KeyboardKeyUp}, {0x49, KeyboardKeyPageUp}, {0x4B, KeyboardKeyLeft}, {0x4D, KeyboardKeyRight}, {0x4F, KeyboardKeyEnd}, {0x50, KeyboardKeyDown}, {0x51, KeyboardKeyPageDown}, {0x52, KeyboardKeyInsert}, {0x53, KeyboardKeyDelete}, {0x5B, KeyboardKeyLeftWindows}, {0x5C, KeyboardKeyRightWindows}, {0x5D, KeyboardKeyMenu}, {0x5E, KeyboardKeyPower}, {0x5F, KeyboardKeySleep}, {0x63, KeyboardKeyWake}, {0x64, KeyboardKeyPictures}, {0x6D, KeyboardKeyVideo}, }; EXTENDED_2_KEY_DESCRIPTION I8042ScanCodeSet1Extended2KeyTable[SCAN_CODE_1_EXTENDED_2_KEY_COUNT] = { {0x1D, 0x45, KeyboardKeyBreak}, }; // // ------------------------------------------------------------------ Functions // KEYBOARD_KEY I8042ConvertScanCodeToKey ( UCHAR ScanCode1, UCHAR ScanCode2, UCHAR ScanCode3, PBOOL KeyUp ) /*++ Routine Description: This routine converts a scan code sequence into a key. Arguments: ScanCode1 - Supplies the first scan code. ScanCode2 - Supplies an optional second scan code. ScanCode3 - Supplies an optional third scan code. KeyUp - Supplies a pointer where a boolean will be returned indicating whether the key is being released (TRUE) or pressed (FALSE). Return Value: Returns the keyboard key code associated with this scan code sequence. --*/ { ULONG ExtendedIndex; KEYBOARD_KEY Key; *KeyUp = FALSE; if (ScanCode1 == SCAN_CODE_1_EXTENDED_2_CODE) { if ((ScanCode2 & SCAN_CODE_1_KEY_UP) != 0) { *KeyUp = TRUE; ScanCode2 &= ~SCAN_CODE_1_KEY_UP; ASSERT((ScanCode3 & SCAN_CODE_1_KEY_UP) != 0); ScanCode3 &= ~ SCAN_CODE_1_KEY_UP; } for (ExtendedIndex = 0; ExtendedIndex < SCAN_CODE_1_EXTENDED_2_KEY_COUNT; ExtendedIndex += 1) { if ((I8042ScanCodeSet1Extended2KeyTable[ExtendedIndex].ScanCode1 == ScanCode2) && (I8042ScanCodeSet1Extended2KeyTable[ExtendedIndex].ScanCode2 == ScanCode3)) { break; } } if (ExtendedIndex == SCAN_CODE_1_EXTENDED_2_KEY_COUNT) { Key = KeyboardKeyInvalid; } else { Key = I8042ScanCodeSet1Extended2KeyTable[ExtendedIndex].Key; } } else if (ScanCode1 == SCAN_CODE_1_EXTENDED_CODE) { if ((ScanCode2 & SCAN_CODE_1_KEY_UP) != 0) { *KeyUp = TRUE; ScanCode2 &= ~SCAN_CODE_1_KEY_UP; } for (ExtendedIndex = 0; ExtendedIndex < SCAN_CODE_1_EXTENDED_KEY_COUNT; ExtendedIndex += 1) { if (I8042ScanCodeSet1ExtendedKeyTable[ExtendedIndex].ScanCode == ScanCode2) { break; } } if (ExtendedIndex == SCAN_CODE_1_EXTENDED_KEY_COUNT) { Key = KeyboardKeyInvalid; } else { Key = I8042ScanCodeSet1ExtendedKeyTable[ExtendedIndex].Key; } } else { if ((ScanCode1 & SCAN_CODE_1_KEY_UP) != 0) { *KeyUp = TRUE; ScanCode1 &= ~SCAN_CODE_1_KEY_UP; } Key = I8042ScanCodeSet1KeyTable[ScanCode1]; } return Key; } // // --------------------------------------------------------- Internal Functions //