mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 18:07:34 +00:00
Kernel+Userland: Implement support for PS2 scan code set 2
This scan code set is more advanced than the basic scan code set 1, and is required to be supported for some bare metal hardware that might not properly enable the PS2 first port translation in the i8042 controller. LibWeb can now also generate bindings for keyboard events like the Pause key, as well as other function keys (such as Right Alt, etc). The logic for handling scan code sets is implemented by the PS2 keyboard driver and is abstracted from the main HID KeyboardDevice code which only handles "standard" KeyEvent(s).
This commit is contained in:
parent
60a96b3786
commit
61a385fc01
12 changed files with 982 additions and 440 deletions
|
@ -19,28 +19,693 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
void PS2KeyboardDevice::handle_byte_read_from_serial_input(u8 byte)
|
||||
// clang-format off
|
||||
static constexpr KeyCodeEntry unshifted_scan_code_set1_key_map[0x80] = {
|
||||
{ Key_Invalid, 0xFF }, { Key_Escape, 1 }, { Key_1, 2 }, { Key_2, 3 },
|
||||
{ Key_3, 4 }, { Key_4, 5 }, { Key_5, 6 }, { Key_6, 7 },
|
||||
{ Key_7, 8 }, { Key_8, 9 }, { Key_9, 0x0A }, { Key_0, 0x0B },
|
||||
{ Key_Minus, 0x0C }, { Key_Equal, 0x0D }, { Key_Backspace, 0x0E }, { Key_Tab, 0x0F },
|
||||
{ Key_Q, 0x10 }, { Key_W, 0x11 }, { Key_E, 0x12 }, { Key_R, 0x13 },
|
||||
{ Key_T, 0x14 }, { Key_Y, 0x15 }, { Key_U, 0x16 }, { Key_I, 0x17 },
|
||||
{ Key_O, 0x18 }, { Key_P, 0x19 }, { Key_LeftBracket, 0x1A }, { Key_RightBracket, 0x1B },
|
||||
{ Key_Return, 0x1C }, { Key_Control, 0x1D }, { Key_A, 0x1E }, { Key_S, 0x1F },
|
||||
{ Key_D, 0x20 }, { Key_F, 0x21 }, { Key_G, 0x22 }, { Key_H, 0x23 },
|
||||
{ Key_J, 0x24 }, { Key_K, 0x25 }, { Key_L, 0x26 }, { Key_Semicolon, 0x27 },
|
||||
{ Key_Apostrophe, 0x28 }, { Key_Backtick, 0x29 }, { Key_LeftShift, 0xFF }, { Key_Backslash, 0x2B },
|
||||
{ Key_Z, 0x2C }, { Key_X, 0x2D }, { Key_C, 0x2E }, { Key_V, 0x2F },
|
||||
{ Key_B, 0x30 }, { Key_N, 0x31 }, { Key_M, 0x32 }, { Key_Comma, 0x33 },
|
||||
{ Key_Period, 0x34 }, { Key_Slash, 0x35 }, { Key_RightShift, 0xFF }, { Key_Asterisk, 0x37 },
|
||||
{ Key_Alt, 0xFF }, { Key_Space, 0x39 }, { Key_CapsLock, 0xFF }, { Key_F1, 0xFF },
|
||||
{ Key_F2, 0xFF }, { Key_F3, 0xFF }, { Key_F4, 0xFF }, { Key_F5, 0xFF },
|
||||
{ Key_F6, 0xFF }, { Key_F7, 0xFF }, { Key_F8, 0xFF }, { Key_F9, 0xFF },
|
||||
{ Key_F10, 0xFF }, { Key_NumLock, 0xFF }, { Key_ScrollLock, 0xFF }, { Key_Home, 0xFF },
|
||||
{ Key_Up, 0xFF }, { Key_PageUp, 0xFF }, { Key_Minus, 0x4A }, { Key_Left, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Right, 0xFF }, { Key_Plus, 0xFF }, { Key_End, 0xFF },
|
||||
{ Key_Down, 0xFF }, { Key_PageDown, 0xFF }, { Key_Insert, 0xFF }, { Key_Delete, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Backslash, 0x56 }, { Key_F11, 0xFF },
|
||||
{ Key_F12, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Super, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Menu, 0xFF },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
static constexpr KeyCodeEntry shifted_scan_code_set1_key_map[0x100] = {
|
||||
{ Key_Invalid, 0xFF }, { Key_Escape, 1 }, { Key_Escape, 2 }, { Key_AtSign, 3 },
|
||||
{ Key_Hashtag, 4 }, { Key_Dollar, 5 }, { Key_Percent, 6 }, { Key_Circumflex, 7 },
|
||||
{ Key_Ampersand, 8 }, { Key_Asterisk, 9 }, { Key_LeftParen, 0x0A }, { Key_RightParen, 0x0B },
|
||||
{ Key_Underscore, 0xC }, { Key_Plus, 0xFF }, { Key_Backspace, 0x0E }, { Key_Tab, 0x0F },
|
||||
{ Key_Q, 0x10 }, { Key_W, 0x11 }, { Key_E, 0x12 }, { Key_R, 0x13 },
|
||||
{ Key_T, 0x14 }, { Key_Y, 0x15 }, { Key_U, 0x16 }, { Key_I, 0x17 },
|
||||
{ Key_O, 0x18 }, { Key_P, 0x19 }, { Key_LeftBrace, 0x1A }, { Key_RightBrace, 0x1B },
|
||||
{ Key_Return, 0x1C }, { Key_Control, 0x1D }, { Key_A, 0x1E }, { Key_S, 0x1F },
|
||||
{ Key_D, 0x20 }, { Key_F, 0x21 }, { Key_G, 0x22 }, { Key_H, 0x23 },
|
||||
{ Key_J, 0x24 }, { Key_K, 0x25 }, { Key_L, 0x26 }, { Key_Colon, 0x27 },
|
||||
{ Key_DoubleQuote, 0x28 }, { Key_Tilde, 0x29 }, { Key_LeftShift, 0xFF }, { Key_Pipe, 0x2B },
|
||||
{ Key_Z, 0x2C }, { Key_X, 0x2D }, { Key_C, 0x2E }, { Key_V, 0x2F },
|
||||
{ Key_B, 0x30 }, { Key_N, 0x31 }, { Key_M, 0x32 }, { Key_LessThan, 0x33 },
|
||||
{ Key_GreaterThan, 0x34 }, { Key_QuestionMark, 0x35 }, { Key_RightShift, 0x36 }, { Key_Asterisk, 0x37 },
|
||||
{ Key_Alt, 0x38 }, { Key_Space, 0x39 }, { Key_CapsLock, 0x3A }, { Key_F1, 0x3B },
|
||||
{ Key_F2, 0x3C }, { Key_F3, 0x3D }, { Key_F4, 0x3E }, { Key_F5, 0x3F },
|
||||
{ Key_F6, 0x40 }, { Key_F7, 0x41 }, { Key_F8, 0x42 }, { Key_F9, 0x43 },
|
||||
{ Key_F10, 0x44 }, { Key_NumLock, 0x45 }, { Key_ScrollLock, 0x46 }, { Key_Home, 0x47 },
|
||||
{ Key_Up, 0x48 }, { Key_PageUp, 0x49 }, { Key_Minus, 0x0C }, { Key_Left, 0x4B },
|
||||
{ Key_Invalid, 0xFF }, { Key_Right, 0xFF }, { Key_Plus, 0xFF }, { Key_End, 0xFF },
|
||||
{ Key_Down, 0xFF }, { Key_PageDown, 0xFF }, { Key_Insert, 0xFF }, { Key_Delete, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Pipe, 0x56 }, { Key_F11, 0xFF },
|
||||
{ Key_F12, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Super, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Menu, 0xFF },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
static constexpr KeyCodeEntry unshifted_simple_scan_code_set2_key_map_with_key_num_pad[0x84] = {
|
||||
{ Key_Invalid, 0xFF }, { Key_F9, 0x43 }, { Key_Invalid, 0xFF }, { Key_F5, 0x3F },
|
||||
{ Key_F3, 0x3D }, { Key_F1, 0x3B }, { Key_F2, 0x3C }, { Key_F12, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_F10, 0x44 }, { Key_F8, 0x42 }, { Key_F6, 0x40 },
|
||||
{ Key_F4, 0x3E }, { Key_Tab, 0x0F }, { Key_Backtick, 0x29 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Alt, 0x38 }, { Key_LeftShift, 0x2A }, { Key_Invalid, 0xFF },
|
||||
{ Key_Control, 0x1D }, { Key_Q, 0x10 }, { Key_1, 2 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Z, 0x2C }, { Key_S, 0x1F },
|
||||
{ Key_A, 0x1E }, { Key_W, 0x11 }, { Key_2, 3 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_C, 0x2E }, { Key_X, 0x2D }, { Key_D, 0x20 },
|
||||
{ Key_E, 0x12 }, { Key_4, 5 }, { Key_3, 4 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Space, 0x39 }, { Key_V, 0x2F }, { Key_F, 0x21 },
|
||||
{ Key_T, 0x14 }, { Key_R, 0x13 }, { Key_5, 6 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_N, 0x31 }, { Key_B, 0x30 }, { Key_H, 0x23 },
|
||||
{ Key_G, 0x22 }, { Key_Y, 0x15 }, { Key_6, 7 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_M, 0x32 }, { Key_J, 0x24 },
|
||||
{ Key_U, 0x16 }, { Key_7, 8 }, { Key_8, 9 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Comma, 0x33 }, { Key_K, 0x25 }, { Key_I, 0x17 },
|
||||
{ Key_O, 0x18 }, { Key_0, 0x0B }, { Key_9, 0x0A }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Period, 0x34 }, { Key_Slash, 0x35 }, { Key_L, 0x26 },
|
||||
{ Key_Semicolon, 0x27 }, { Key_P, 0x19 }, { Key_Minus, 0x0C }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Apostrophe, 0x28 }, { Key_Invalid, 0xFF },
|
||||
{ Key_LeftBracket, 0x1A }, { Key_Equal, 0x0D }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_CapsLock, 0x3A }, { Key_RightShift, 0x36 }, { Key_Return, 0x1C }, { Key_RightBracket, 0x1B },
|
||||
{ Key_Invalid, 0xFF }, { Key_Backslash, 0x2B }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Backspace, 0x0E }, { Key_Invalid, 0xFF },
|
||||
// Keypad numbers from here
|
||||
{ Key_Invalid, 0xFF }, { Key_1, 2 }, { Key_Invalid, 0xFF }, { Key_4, 5 },
|
||||
{ Key_7, 8 }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_0, 0x0B }, { Key_Period, 0x34 }, { Key_2, 3 }, { Key_5, 6 },
|
||||
{ Key_6, 7 }, { Key_8, 9 }, { Key_Escape, 1 }, { Key_NumLock, 0x45 },
|
||||
{ Key_F11, 0xFF }, { Key_Plus, 0xFF }, { Key_3, 4 }, { Key_Minus, 0x0C },
|
||||
{ Key_Asterisk, 0x37 }, { Key_9, 0x0A }, { Key_ScrollLock, 0x46 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_F7, 0x41 },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
static constexpr KeyCodeEntry unshifted_simple_scan_code_set2_key_map_with_disabled_key_num_pad[0x84] = {
|
||||
{ Key_Invalid, 0xFF }, { Key_F9, 0x43 }, { Key_Invalid, 0xFF }, { Key_F5, 0x3F },
|
||||
{ Key_F3, 0x3D }, { Key_F1, 0x3B }, { Key_F2, 0x3C }, { Key_F12, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_F10, 0x44 }, { Key_F8, 0x42 }, { Key_F6, 0x40 },
|
||||
{ Key_F4, 0x3E }, { Key_Tab, 0x0F }, { Key_Backtick, 0x29 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Alt, 0x38 }, { Key_LeftShift, 0x2A }, { Key_Invalid, 0xFF },
|
||||
{ Key_Control, 0x1D }, { Key_Q, 0x10 }, { Key_1, 2 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Z, 0x2C }, { Key_S, 0x1F },
|
||||
{ Key_A, 0x1E }, { Key_W, 0x11 }, { Key_2, 3 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_C, 0x2E }, { Key_X, 0x2D }, { Key_D, 0x20 },
|
||||
{ Key_E, 0x12 }, { Key_4, 5 }, { Key_3, 4 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Space, 0x39 }, { Key_V, 0x2F }, { Key_F, 0x21 },
|
||||
{ Key_T, 0x14 }, { Key_R, 0x13 }, { Key_5, 6 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_N, 0x31 }, { Key_B, 0x30 }, { Key_H, 0x23 },
|
||||
{ Key_G, 0x22 }, { Key_Y, 0x15 }, { Key_6, 7 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_M, 0x32 }, { Key_J, 0x24 },
|
||||
{ Key_U, 0x16 }, { Key_7, 8 }, { Key_8, 9 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Comma, 0x33 }, { Key_K, 0x25 }, { Key_I, 0x17 },
|
||||
{ Key_O, 0x18 }, { Key_0, 0x0B }, { Key_9, 0x0A }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Period, 0x34 }, { Key_Slash, 0x35 }, { Key_L, 0x26 },
|
||||
{ Key_Semicolon, 0x27 }, { Key_P, 0x19 }, { Key_Underscore, 0x0C }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Apostrophe, 0x28 }, { Key_Invalid, 0xFF },
|
||||
{ Key_LeftBracket, 0x1A }, { Key_Equal, 0x0D }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_CapsLock, 0x3A }, { Key_RightShift, 0x36 }, { Key_Return, 0x1C }, { Key_RightBracket, 0x1B },
|
||||
{ Key_Invalid, 0xFF }, { Key_Backslash, 0x2B }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Backspace, 0x0E }, { Key_Invalid, 0xFF },
|
||||
// Keypad numbers from here, and disabled or converted to arrows
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Left, 0x4B },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Insert, 0xFF }, { Key_Delete, 0xFF }, { Key_Down, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Right, 0xFF }, { Key_Up, 0x48 }, { Key_Escape, 1 }, { Key_NumLock, 0x45 },
|
||||
{ Key_F11, 0xFF }, { Key_Plus, 0xFF }, { Key_Invalid, 0xFF }, { Key_Minus, 0x0C },
|
||||
{ Key_Asterisk, 0x37 }, { Key_Invalid, 0xFF }, { Key_ScrollLock, 0x46 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_F7, 0x41 },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
static constexpr KeyCodeEntry shifted_simple_scan_code_set2_key_map_with_key_num_pad[0x84] = {
|
||||
{ Key_Invalid, 0xFF }, { Key_F9, 0x43 }, { Key_Invalid, 0xFF }, { Key_F5, 0x3F },
|
||||
{ Key_F3, 0x3D }, { Key_F1, 0x3B }, { Key_F2, 0x3C }, { Key_F12, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_F10, 0x44 }, { Key_F8, 0x42 }, { Key_F6, 0x40 },
|
||||
{ Key_F4, 0x3E }, { Key_Tab, 0x0F }, { Key_Backtick, 0x29 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Alt, 0x38 }, { Key_LeftShift, 0x2A }, { Key_Invalid, 0xFF },
|
||||
{ Key_Control, 0x1D }, { Key_Slash, 0x35 }, { Key_Escape, 2 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Z, 0x2C }, { Key_S, 0x1F },
|
||||
{ Key_A, 0x1E }, { Key_W, 0x11 }, { Key_AtSign, 3 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_C, 0x2E }, { Key_X, 0x2D }, { Key_D, 0x20 },
|
||||
{ Key_E, 0x12 }, { Key_Dollar, 5 }, { Key_Hashtag, 4 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Space, 0x39 }, { Key_V, 0x2F }, { Key_F, 0x21 },
|
||||
{ Key_T, 0x14 }, { Key_R, 0x13 }, { Key_Percent, 6 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_N, 0x31 }, { Key_B, 0x30 }, { Key_H, 0x23 },
|
||||
{ Key_G, 0x22 }, { Key_Y, 0x15 }, { Key_Circumflex, 7 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_M, 0x32 }, { Key_J, 0x24 },
|
||||
{ Key_U, 0x16 }, { Key_Ampersand, 8 }, { Key_Asterisk, 0x37 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_LessThan, 0x33 }, { Key_K, 0x25 }, { Key_I, 0x17 },
|
||||
{ Key_O, 0x18 }, { Key_RightParen, 0x0B }, { Key_LeftParen, 0x0A }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_GreaterThan, 0x34 }, { Key_Slash, 0x35 }, { Key_L, 0x26 },
|
||||
{ Key_Semicolon, 0x27 }, { Key_P, 0x19 }, { Key_Minus, 0x0C }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_DoubleQuote, 0x28 }, { Key_Invalid, 0xFF },
|
||||
{ Key_LeftBrace, 0x1A }, { Key_Plus, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_CapsLock, 0x3A }, { Key_RightShift, 0x36 }, { Key_Return, 0x1C }, { Key_RightBrace, 0x1B },
|
||||
{ Key_Invalid, 0xFF }, { Key_Pipe, 0x2B }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Backspace, 0x0E }, { Key_Invalid, 0xFF },
|
||||
// Keypad numbers from here
|
||||
{ Key_Invalid, 0xFF }, { Key_1, 2 }, { Key_Invalid, 0xFF }, { Key_4, 5 },
|
||||
{ Key_7, 8 }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_0, 0x0B }, { Key_Period, 0x34 }, { Key_2, 3 }, { Key_5, 6 },
|
||||
{ Key_6, 7 }, { Key_8, 9 }, { Key_Escape, 1 }, { Key_NumLock, 0x45 },
|
||||
{ Key_F11, 0xFF }, { Key_Plus, 0xFF }, { Key_3, 4 }, { Key_Minus, 0x0C },
|
||||
{ Key_Asterisk, 0x37 }, { Key_9, 0x0A }, { Key_ScrollLock, 0x46 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_F7, 0x41 },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
static constexpr KeyCodeEntry shifted_simple_scan_code_set2_key_map_with_disabled_key_num_pad[0x84] = {
|
||||
{ Key_Invalid, 0xFF }, { Key_F9, 0x43 }, { Key_Invalid, 0xFF }, { Key_F5, 0x3F },
|
||||
{ Key_F3, 0x3D }, { Key_F1, 0x3B }, { Key_F2, 0x3C }, { Key_F12, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_F10, 0x44 }, { Key_F8, 0x42 }, { Key_F6, 0x40 },
|
||||
{ Key_F4, 0x3E }, { Key_Tab, 0x0F }, { Key_Backtick, 0x29 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Alt, 0x38 }, { Key_LeftShift, 0x2A }, { Key_Invalid, 0xFF },
|
||||
{ Key_Control, 0x1D }, { Key_Slash, 0x35 }, { Key_Escape, 2 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Z, 0x2C }, { Key_S, 0x1F },
|
||||
{ Key_A, 0x1E }, { Key_W, 0x11 }, { Key_AtSign, 3 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_C, 0x2E }, { Key_X, 0x2D }, { Key_D, 0x20 },
|
||||
{ Key_E, 0x12 }, { Key_Dollar, 5 }, { Key_Hashtag, 4 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Space, 0x39 }, { Key_V, 0x2F }, { Key_F, 0x21 },
|
||||
{ Key_T, 0x14 }, { Key_R, 0x13 }, { Key_Percent, 6 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_N, 0x31 }, { Key_B, 0x30 }, { Key_H, 0x23 },
|
||||
{ Key_G, 0x22 }, { Key_Y, 0x15 }, { Key_Circumflex, 7 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_M, 0x32 }, { Key_J, 0x24 },
|
||||
{ Key_U, 0x16 }, { Key_Ampersand, 8 }, { Key_Asterisk, 0x37 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_LessThan, 0xFF}, { Key_K, 0x25 }, { Key_I, 0x17 },
|
||||
{ Key_O, 0x18 }, { Key_RightParen, 0x0B }, { Key_LeftParen, 0x0A }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Period, 0x34 }, { Key_Slash, 0x35 }, { Key_L, 0x26 },
|
||||
{ Key_Semicolon, 0x27 }, { Key_P, 0x19 }, { Key_Underscore, 0x0C }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_DoubleQuote, 0x28 }, { Key_Invalid, 0xFF },
|
||||
{ Key_LeftBrace, 0x1A }, { Key_Plus, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_CapsLock, 0x3A }, { Key_RightShift, 0x36 }, { Key_Return, 0x1C }, { Key_RightBrace, 0x1B },
|
||||
{ Key_Invalid, 0xFF }, { Key_Pipe, 0x2B }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Backspace, 0x0E }, { Key_Invalid, 0xFF },
|
||||
// Keypad numbers from here, and disabled or converted to arrows
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Left, 0x4B },
|
||||
{ Key_7, 8 }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Insert, 0xFF }, { Key_Delete, 0xFF }, { Key_Down, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Right, 0xFF }, { Key_Up, 0x48 }, { Key_Escape, 1 }, { Key_NumLock, 0x45 },
|
||||
{ Key_F11, 0xFF }, { Key_Plus, 0xFF }, { Key_Invalid, 0xFF }, { Key_Minus, 0x0C },
|
||||
{ Key_Asterisk, 0x37 }, { Key_Invalid, 0xFF }, { Key_ScrollLock, 0x46 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_F7, 0x41 },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// Note: First scan code starts at actual 0xE0, 0x10, but we start from 0xE0, 0x0
|
||||
// Note: All keycode are for pressing buttons, not releasing...
|
||||
// clang-format off
|
||||
static constexpr KeyCodeEntry unshifted_scan_code_set2_e0_key_map[0x80] = {
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_BrowserSearch, 0xFF }, { Key_RightAlt, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_RightControl, 0xFF }, { Key_PreviousTrack, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_BrowserFavorites, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_LeftGUI, 0xFF },
|
||||
{ Key_BrowserRefresh, 0xFF }, { Key_VolumeDown, 0xFF }, { Key_Invalid, 0xFF }, { Key_Mute, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_RightGUI, 0xFF },
|
||||
{ Key_BrowserStop, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Calculator, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Apps, 0xFF },
|
||||
{ Key_BrowserForward, 0xFF }, { Key_Invalid, 0xFF }, { Key_VolumeUp, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_PlayPause, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Power, 0xFF },
|
||||
{ Key_BrowserBack, 0xFF }, { Key_Invalid, 0xFF }, { Key_BrowserHome, 0xFF }, { Key_Stop, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Sleep, 0xFF },
|
||||
{ Key_MyComputer, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Email, 0xFF }, { Key_Invalid, 0xFF }, { Key_Slash, 0x35 }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_NextTrack, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_MediaSelect, 0xFF}, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Return, 0x1C }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Wake, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_End, 0xFF }, { Key_Invalid, 0xFF }, { Key_Left, 0xFF },
|
||||
{ Key_Home, 0x47 }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Insert, 0xFF }, { Key_Delete, 0xFF }, { Key_Down, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Right, 0xFF }, { Key_Up, 0xFF }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_Invalid, 0xFF }, { Key_PageDown, 0xFF }, { Key_Invalid, 0xFF },
|
||||
{ Key_Invalid, 0xFF }, { Key_PageUp, 0x49 }, { Key_Invalid, 0xFF }, { Key_Invalid, 0xFF },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RawKeyEvent PS2KeyboardDevice::generate_raw_key_event_input_from_set1(ScanCodeEvent event)
|
||||
{
|
||||
RawKeyEvent key_event {};
|
||||
VERIFY(event.sent_scan_code_set == ScanCodeSet::Set1);
|
||||
bool has_e0_prefix = event.scan_code_bytes[0] == 0xe0;
|
||||
if (has_e0_prefix)
|
||||
VERIFY(event.bytes_count == 2);
|
||||
else
|
||||
VERIFY(event.bytes_count == 1);
|
||||
|
||||
u8 byte = has_e0_prefix ? event.scan_code_bytes[1] : event.scan_code_bytes[0];
|
||||
bool pressed = !(byte & 0x80);
|
||||
u8 ch = byte & 0x7f;
|
||||
|
||||
key_event.is_press_down = pressed;
|
||||
|
||||
m_entropy_source.add_random_event(byte);
|
||||
|
||||
switch (ch) {
|
||||
case 0x38:
|
||||
if (has_e0_prefix)
|
||||
m_keyboard_device->update_modifier(Mod_AltGr, key_event.is_press());
|
||||
else
|
||||
m_keyboard_device->update_modifier(Mod_Alt, key_event.is_press());
|
||||
break;
|
||||
case 0x1d:
|
||||
m_keyboard_device->update_modifier(Mod_Ctrl, key_event.is_press());
|
||||
break;
|
||||
case 0x5b:
|
||||
m_left_super_pressed = key_event.is_press();
|
||||
m_keyboard_device->update_modifier(Mod_Super, m_left_super_pressed || m_right_super_pressed);
|
||||
break;
|
||||
case 0x5c:
|
||||
m_right_super_pressed = key_event.is_press();
|
||||
m_keyboard_device->update_modifier(Mod_Super, m_left_super_pressed || m_right_super_pressed);
|
||||
break;
|
||||
case 0x2a:
|
||||
m_left_shift_pressed = key_event.is_press();
|
||||
m_keyboard_device->update_modifier(Mod_Shift, m_left_shift_pressed || m_right_shift_pressed);
|
||||
break;
|
||||
case 0x36:
|
||||
m_right_shift_pressed = key_event.is_press();
|
||||
m_keyboard_device->update_modifier(Mod_Shift, m_left_shift_pressed || m_right_shift_pressed);
|
||||
break;
|
||||
case 0x1c:
|
||||
case 0x35:
|
||||
if (has_e0_prefix)
|
||||
m_keyboard_device->update_modifier(Mod_Keypad, key_event.is_press());
|
||||
break;
|
||||
case 0x37:
|
||||
case 0x47:
|
||||
case 0x48:
|
||||
case 0x49:
|
||||
case 0x4a:
|
||||
case 0x4b:
|
||||
case 0x4c:
|
||||
case 0x4d:
|
||||
case 0x4e:
|
||||
case 0x4f:
|
||||
case 0x50:
|
||||
case 0x51:
|
||||
case 0x52:
|
||||
case 0x53:
|
||||
if (!has_e0_prefix)
|
||||
m_keyboard_device->update_modifier(Mod_Keypad, key_event.is_press());
|
||||
break;
|
||||
}
|
||||
|
||||
key_event.code_entry = (m_keyboard_device->modifiers() & Mod_Shift) ? shifted_scan_code_set1_key_map[ch] : unshifted_scan_code_set1_key_map[ch];
|
||||
key_event.scancode = has_e0_prefix ? 0xe000 + ch : ch;
|
||||
return key_event;
|
||||
}
|
||||
|
||||
RawKeyEvent PS2KeyboardDevice::generate_raw_key_event_input_from_set2(ScanCodeEvent event)
|
||||
{
|
||||
VERIFY(event.sent_scan_code_set == ScanCodeSet::Set2);
|
||||
|
||||
auto get_key_from_standard_key_map = [this](u8 byte) -> KeyCodeEntry {
|
||||
if (!(m_keyboard_device->modifiers() & Mod_Shift))
|
||||
return (m_keyboard_device->num_lock_on()) ? unshifted_simple_scan_code_set2_key_map_with_key_num_pad[byte] : unshifted_simple_scan_code_set2_key_map_with_disabled_key_num_pad[byte];
|
||||
return (m_keyboard_device->num_lock_on()) ? shifted_simple_scan_code_set2_key_map_with_key_num_pad[byte] : shifted_simple_scan_code_set2_key_map_with_disabled_key_num_pad[byte];
|
||||
};
|
||||
|
||||
RawKeyEvent key_event {};
|
||||
if (event.bytes_count == 1) {
|
||||
auto byte = event.scan_code_bytes[0];
|
||||
key_event.code_entry = get_key_from_standard_key_map(byte);
|
||||
key_event.scancode = byte;
|
||||
key_event.is_press_down = true;
|
||||
m_entropy_source.add_random_event(byte);
|
||||
} else if (event.bytes_count == 2) {
|
||||
auto byte_prefix = event.scan_code_bytes[0];
|
||||
auto byte = event.scan_code_bytes[1];
|
||||
if (byte_prefix == 0xe0) {
|
||||
key_event.code_entry = unshifted_scan_code_set2_e0_key_map[byte];
|
||||
key_event.scancode = 0xe000 + byte;
|
||||
key_event.is_press_down = true;
|
||||
} else if (byte_prefix == 0xf0) {
|
||||
key_event.code_entry = get_key_from_standard_key_map(byte);
|
||||
key_event.scancode = 0xf000 + byte;
|
||||
} else {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
m_entropy_source.add_random_event(byte);
|
||||
} else if (event.bytes_count == 3) {
|
||||
auto first_byte_prefix = event.scan_code_bytes[0];
|
||||
auto second_byte_prefix = event.scan_code_bytes[1];
|
||||
VERIFY(first_byte_prefix == 0xe0);
|
||||
VERIFY(second_byte_prefix == 0xf0);
|
||||
auto byte = event.scan_code_bytes[2];
|
||||
key_event.code_entry = unshifted_scan_code_set2_e0_key_map[byte];
|
||||
key_event.scancode = 0xe0f000 + byte;
|
||||
m_entropy_source.add_random_event(byte);
|
||||
} else if (event.bytes_count == 4) {
|
||||
// 0xE0, 0x12, 0xE0, 0x7C - print screen pressed
|
||||
auto first_byte_prefix = event.scan_code_bytes[0];
|
||||
auto second_byte_prefix = event.scan_code_bytes[1];
|
||||
auto third_byte_prefix = event.scan_code_bytes[2];
|
||||
auto fourth_byte_prefix = event.scan_code_bytes[3];
|
||||
VERIFY(first_byte_prefix == 0xe0);
|
||||
VERIFY(second_byte_prefix == 0x12);
|
||||
VERIFY(third_byte_prefix == 0xe0);
|
||||
VERIFY(fourth_byte_prefix == 0x7c);
|
||||
key_event.code_entry = KeyCodeEntry { Key_PrintScreen, 0xFF };
|
||||
key_event.scancode = 0xe012e07c;
|
||||
key_event.is_press_down = true;
|
||||
} else if (event.bytes_count == 6) {
|
||||
// 0xE0, 0xF0, 0x7C, 0xE0, 0xF0, 0x12 - print screen released
|
||||
auto first_byte_prefix = event.scan_code_bytes[0];
|
||||
auto second_byte_prefix = event.scan_code_bytes[1];
|
||||
auto third_byte_prefix = event.scan_code_bytes[2];
|
||||
auto fourth_byte_prefix = event.scan_code_bytes[3];
|
||||
auto fifth_byte_prefix = event.scan_code_bytes[4];
|
||||
auto sixth_byte_prefix = event.scan_code_bytes[5];
|
||||
VERIFY(first_byte_prefix == 0xe0);
|
||||
VERIFY(second_byte_prefix == 0xf0);
|
||||
VERIFY(third_byte_prefix == 0x7c);
|
||||
VERIFY(fourth_byte_prefix == 0xe0);
|
||||
VERIFY(fifth_byte_prefix == 0xf0);
|
||||
VERIFY(sixth_byte_prefix == 0x12);
|
||||
key_event.code_entry = KeyCodeEntry { Key_PrintScreen, 0xFF };
|
||||
key_event.scancode = 0xe0f07ce0f012;
|
||||
} else if (event.bytes_count == 8) {
|
||||
// 0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0, 0x77 - pause pressed
|
||||
auto first_byte_prefix = event.scan_code_bytes[0];
|
||||
auto second_byte_prefix = event.scan_code_bytes[1];
|
||||
auto third_byte_prefix = event.scan_code_bytes[2];
|
||||
auto fourth_byte_prefix = event.scan_code_bytes[3];
|
||||
auto fifth_byte_prefix = event.scan_code_bytes[4];
|
||||
auto sixth_byte_prefix = event.scan_code_bytes[5];
|
||||
auto seventh_byte_prefix = event.scan_code_bytes[6];
|
||||
auto eight_byte_prefix = event.scan_code_bytes[7];
|
||||
VERIFY(first_byte_prefix == 0xe1);
|
||||
VERIFY(second_byte_prefix == 0x14);
|
||||
VERIFY(third_byte_prefix == 0x77);
|
||||
VERIFY(fourth_byte_prefix == 0xe1);
|
||||
VERIFY(fifth_byte_prefix == 0xf0);
|
||||
VERIFY(sixth_byte_prefix == 0x14);
|
||||
VERIFY(seventh_byte_prefix == 0xf0);
|
||||
VERIFY(eight_byte_prefix == 0x77);
|
||||
key_event.code_entry = KeyCodeEntry { Key_PauseBreak, 0xFF };
|
||||
key_event.scancode = 0xe11477e1f014f077;
|
||||
}
|
||||
|
||||
switch (key_event.code_entry.key_code) {
|
||||
case Key_RightAlt:
|
||||
m_keyboard_device->update_modifier(Mod_AltGr, key_event.is_press());
|
||||
break;
|
||||
case Key_Alt:
|
||||
m_keyboard_device->update_modifier(Mod_Alt, key_event.is_press());
|
||||
break;
|
||||
case Key_Control:
|
||||
m_keyboard_device->update_modifier(Mod_Ctrl, key_event.is_press());
|
||||
break;
|
||||
case Key_Super:
|
||||
m_left_super_pressed = key_event.is_press();
|
||||
m_keyboard_device->update_modifier(Mod_Super, m_left_super_pressed || m_right_super_pressed);
|
||||
break;
|
||||
case Key_LeftShift:
|
||||
m_left_shift_pressed = key_event.is_press();
|
||||
m_keyboard_device->update_modifier(Mod_Shift, m_left_shift_pressed || m_right_shift_pressed);
|
||||
break;
|
||||
case Key_RightShift:
|
||||
m_right_shift_pressed = key_event.is_press();
|
||||
m_keyboard_device->update_modifier(Mod_Shift, m_left_shift_pressed || m_right_shift_pressed);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return key_event;
|
||||
}
|
||||
|
||||
void PS2KeyboardDevice::handle_scan_code_input_event(ScanCodeEvent event)
|
||||
{
|
||||
RawKeyEvent raw_event {};
|
||||
if (event.sent_scan_code_set == ScanCodeSet::Set1) {
|
||||
raw_event = generate_raw_key_event_input_from_set1(event);
|
||||
} else if (event.sent_scan_code_set == ScanCodeSet::Set2) {
|
||||
raw_event = generate_raw_key_event_input_from_set2(event);
|
||||
} else if (event.sent_scan_code_set == ScanCodeSet::Set3) {
|
||||
// FIXME: Implement support for scan code set 3!
|
||||
VERIFY_NOT_REACHED();
|
||||
} else {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
KeyEvent queued_event = {
|
||||
.key = raw_event.code_entry.key_code,
|
||||
.map_entry_index = raw_event.code_entry.map_entry_index,
|
||||
.scancode = raw_event.scancode,
|
||||
.flags = raw_event.is_press() ? (u8)Is_Press : (u8)0,
|
||||
};
|
||||
|
||||
// NOTE: This piece of code is needed for the ScanCodeSet::Set1 to ensure some keys could
|
||||
// function properly.
|
||||
if (event.sent_scan_code_set == ScanCodeSet::Set1) {
|
||||
if ((queued_event.scancode & 0xe000) && queued_event.key == Key_Slash) {
|
||||
// If Key_Slash (scancode = 0x35) mapped to other form "/", we fix num pad key of "/" with this case.
|
||||
queued_event.code_point = '/';
|
||||
} else if ((queued_event.scancode & 0xe000) && queued_event.key != Key_Return) {
|
||||
// Except for `keypad-/` and 'keypad-return', all e0 scan codes are not actually characters. i.e., `keypad-0` and
|
||||
// `Insert` have the same scancode except for the prefix, but insert should not have a code_point.
|
||||
queued_event.code_point = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: This piece of code is needed for the ScanCodeSet::Set1 when NumLock is enabled
|
||||
// because we don't have special mappings when NumLock is enabled for this scan code set.
|
||||
// Scan code set 2 handling code in handle_scan_code_input_event_set2() already handles this fine.
|
||||
if (event.sent_scan_code_set == ScanCodeSet::Set1 && m_keyboard_device->num_lock_on() && !(queued_event.scancode & 0xe000)) {
|
||||
if (queued_event.scancode >= 0x47 && queued_event.scancode <= 0x53) {
|
||||
u8 index = queued_event.scancode - 0x47;
|
||||
constexpr KeyCode numpad_key_map[13] = { Key_7, Key_8, Key_9, Key_Invalid, Key_4, Key_5, Key_6, Key_Invalid, Key_1, Key_2, Key_3, Key_0, Key_Comma };
|
||||
KeyCode newKey = numpad_key_map[index];
|
||||
|
||||
if (newKey != Key_Invalid) {
|
||||
queued_event.key = newKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (raw_event.code_entry.map_entry_index != 0xFF)
|
||||
queued_event.code_point = HIDManagement::the().get_char_from_character_map(queued_event, raw_event.code_entry.map_entry_index);
|
||||
|
||||
m_keyboard_device->handle_input_event(queued_event);
|
||||
}
|
||||
|
||||
void PS2KeyboardDevice::handle_byte_read_for_scan_code_set1(u8 byte)
|
||||
{
|
||||
u8 ch = byte & 0x7f;
|
||||
bool pressed = !(byte & 0x80);
|
||||
dbgln_if(KEYBOARD_DEBUG, "Keyboard::handle_byte_read_for_scan_code_set1: {:#02x} {}", ch, (pressed ? "down" : "up"));
|
||||
if (byte == 0xe0) {
|
||||
m_has_e0_prefix = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ScanCodeEvent event {};
|
||||
event.pressed = pressed;
|
||||
event.e0_prefix = m_has_e0_prefix;
|
||||
event.sent_scan_code_set = ScanCodeSet::Set1;
|
||||
if (m_has_e0_prefix) {
|
||||
event.scan_code_bytes[0] = 0xe0;
|
||||
event.scan_code_bytes[1] = byte;
|
||||
event.bytes_count = 2;
|
||||
} else {
|
||||
event.scan_code_bytes[0] = byte;
|
||||
event.bytes_count = 1;
|
||||
}
|
||||
m_has_e0_prefix = false;
|
||||
|
||||
dbgln_if(KEYBOARD_DEBUG, "Keyboard::handle_byte_read_from_serial_input: {:#02x} {}", ch, (pressed ? "down" : "up"));
|
||||
event.scan_code_value = ch;
|
||||
m_keyboard_device->handle_scan_code_input_event(event);
|
||||
handle_scan_code_input_event(event);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT ErrorOr<NonnullOwnPtr<PS2KeyboardDevice>> PS2KeyboardDevice::try_to_initialize(SerialIOController const& serial_io_controller, SerialIOController::PortIndex port_index, KeyboardDevice const& keyboard_device)
|
||||
void PS2KeyboardDevice::handle_byte_read_for_scan_code_set2(u8 byte)
|
||||
{
|
||||
auto device = TRY(adopt_nonnull_own_or_enomem(new (nothrow) PS2KeyboardDevice(serial_io_controller, port_index, keyboard_device)));
|
||||
dbgln_if(KEYBOARD_DEBUG, "Keyboard::handle_byte_read_for_scan_code_set2: {:#02x}", byte);
|
||||
|
||||
ScanCodeEvent event {};
|
||||
event.sent_scan_code_set = ScanCodeSet::Set2;
|
||||
if (m_received_bytes_count == 0) {
|
||||
if (byte == 0xe0 || byte == 0xf0 || byte == 0xe1) {
|
||||
m_received_bytes[0] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
}
|
||||
event.scan_code_bytes[0] = byte;
|
||||
event.bytes_count = 1;
|
||||
m_received_bytes_count = 0;
|
||||
handle_scan_code_input_event(event);
|
||||
return;
|
||||
} else if (m_received_bytes_count == 1) {
|
||||
if (byte == 0xf0) {
|
||||
VERIFY(m_received_bytes[0] == 0xe0);
|
||||
m_received_bytes[1] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
}
|
||||
if (m_received_bytes[0] == 0xe0 && byte == 0x12) {
|
||||
m_received_bytes[1] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_received_bytes[0] == 0xe1 && byte == 0x14) {
|
||||
m_received_bytes[1] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
event.scan_code_bytes[0] = m_received_bytes[0];
|
||||
event.scan_code_bytes[1] = byte;
|
||||
event.bytes_count = 2;
|
||||
m_received_bytes_count = 0;
|
||||
handle_scan_code_input_event(event);
|
||||
return;
|
||||
} else if (m_received_bytes_count == 2) {
|
||||
if (m_received_bytes[0] == 0xe0 && m_received_bytes[1] == 0x12 && byte == 0xe0) {
|
||||
m_received_bytes[2] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_received_bytes[0] == 0xe0 && m_received_bytes[1] == 0xf0 && byte == 0x7c) {
|
||||
m_received_bytes[2] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_received_bytes[0] == 0xe1) {
|
||||
VERIFY(m_received_bytes[1] == 0x14);
|
||||
m_received_bytes[2] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
event.scan_code_bytes[0] = m_received_bytes[0];
|
||||
event.scan_code_bytes[1] = m_received_bytes[1];
|
||||
event.scan_code_bytes[2] = byte;
|
||||
event.bytes_count = 3;
|
||||
m_received_bytes_count = 0;
|
||||
handle_scan_code_input_event(event);
|
||||
return;
|
||||
} else if (m_received_bytes_count == 3) {
|
||||
if (m_received_bytes[0] == 0xe0
|
||||
&& m_received_bytes[1] == 0x12
|
||||
&& m_received_bytes[2] == 0xe0
|
||||
&& byte == 0x7c) {
|
||||
ScanCodeEvent event {};
|
||||
event.sent_scan_code_set = ScanCodeSet::Set2;
|
||||
event.scan_code_bytes[0] = m_received_bytes[0];
|
||||
event.scan_code_bytes[1] = m_received_bytes[1];
|
||||
event.scan_code_bytes[2] = m_received_bytes[2];
|
||||
event.scan_code_bytes[3] = byte;
|
||||
event.bytes_count = 4;
|
||||
m_received_bytes_count = 0;
|
||||
handle_scan_code_input_event(event);
|
||||
return;
|
||||
}
|
||||
|
||||
m_received_bytes[3] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
} else if (m_received_bytes_count == 4) {
|
||||
m_received_bytes[4] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
} else if (m_received_bytes_count == 5) {
|
||||
if (m_received_bytes[0] == 0xe0
|
||||
&& m_received_bytes[1] == 0xf0
|
||||
&& m_received_bytes[2] == 0x7c
|
||||
&& m_received_bytes[3] == 0xe0
|
||||
&& m_received_bytes[4] == 0xf0
|
||||
&& byte == 0x12) {
|
||||
|
||||
event.scan_code_bytes[0] = m_received_bytes[0];
|
||||
event.scan_code_bytes[1] = m_received_bytes[1];
|
||||
event.scan_code_bytes[2] = m_received_bytes[2];
|
||||
event.scan_code_bytes[3] = m_received_bytes[3];
|
||||
event.scan_code_bytes[4] = m_received_bytes[4];
|
||||
event.scan_code_bytes[5] = byte;
|
||||
event.bytes_count = 6;
|
||||
m_received_bytes_count = 0;
|
||||
handle_scan_code_input_event(event);
|
||||
return;
|
||||
}
|
||||
m_received_bytes[5] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
} else if (m_received_bytes_count == 6) {
|
||||
m_received_bytes[6] = byte;
|
||||
m_received_bytes_count++;
|
||||
return;
|
||||
} else if (m_received_bytes_count == 7) {
|
||||
VERIFY(m_received_bytes[0] == 0xe1);
|
||||
VERIFY(m_received_bytes[1] == 0x14);
|
||||
VERIFY(m_received_bytes[2] == 0x77);
|
||||
VERIFY(m_received_bytes[3] == 0xe1);
|
||||
VERIFY(m_received_bytes[4] == 0xf0);
|
||||
VERIFY(m_received_bytes[5] == 0x14);
|
||||
VERIFY(m_received_bytes[6] == 0xf0);
|
||||
VERIFY(m_received_bytes[7] == 0x77);
|
||||
event.scan_code_bytes[0] = m_received_bytes[0];
|
||||
event.scan_code_bytes[1] = m_received_bytes[1];
|
||||
event.scan_code_bytes[2] = m_received_bytes[2];
|
||||
event.scan_code_bytes[3] = m_received_bytes[3];
|
||||
event.scan_code_bytes[4] = m_received_bytes[4];
|
||||
event.scan_code_bytes[5] = m_received_bytes[5];
|
||||
event.scan_code_bytes[6] = m_received_bytes[6];
|
||||
event.scan_code_bytes[7] = byte;
|
||||
event.bytes_count = 8;
|
||||
m_received_bytes_count = 0;
|
||||
handle_scan_code_input_event(event);
|
||||
return;
|
||||
} else {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void PS2KeyboardDevice::handle_byte_read_from_serial_input(u8 byte)
|
||||
{
|
||||
switch (m_scan_code_set) {
|
||||
case ScanCodeSet::Set1:
|
||||
handle_byte_read_for_scan_code_set1(byte);
|
||||
break;
|
||||
case ScanCodeSet::Set2:
|
||||
handle_byte_read_for_scan_code_set2(byte);
|
||||
break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT ErrorOr<NonnullOwnPtr<PS2KeyboardDevice>> PS2KeyboardDevice::try_to_initialize(SerialIOController const& serial_io_controller, SerialIOController::PortIndex port_index, ScanCodeSet scan_code_set, KeyboardDevice const& keyboard_device)
|
||||
{
|
||||
auto device = TRY(adopt_nonnull_own_or_enomem(new (nothrow) PS2KeyboardDevice(serial_io_controller, port_index, scan_code_set, keyboard_device)));
|
||||
TRY(device->initialize());
|
||||
return device;
|
||||
}
|
||||
|
@ -74,9 +739,10 @@ UNMAP_AFTER_INIT ErrorOr<void> PS2KeyboardDevice::initialize()
|
|||
|
||||
// FIXME: UNMAP_AFTER_INIT might not be correct, because in practice PS/2 devices
|
||||
// are hot pluggable.
|
||||
UNMAP_AFTER_INIT PS2KeyboardDevice::PS2KeyboardDevice(SerialIOController const& serial_io_controller, SerialIOController::PortIndex port_index, KeyboardDevice const& keyboard_device)
|
||||
UNMAP_AFTER_INIT PS2KeyboardDevice::PS2KeyboardDevice(SerialIOController const& serial_io_controller, SerialIOController::PortIndex port_index, ScanCodeSet scan_code_set, KeyboardDevice const& keyboard_device)
|
||||
: SerialIODevice(serial_io_controller, port_index)
|
||||
, m_keyboard_device(keyboard_device)
|
||||
, m_scan_code_set(scan_code_set)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <AK/Types.h>
|
||||
#include <Kernel/API/KeyCode.h>
|
||||
#include <Kernel/Bus/SerialIO/Device.h>
|
||||
#include <Kernel/Devices/HID/Definitions.h>
|
||||
#include <Kernel/Devices/HID/KeyboardDevice.h>
|
||||
#include <Kernel/Security/Random.h>
|
||||
|
||||
|
@ -19,7 +20,7 @@ class PS2KeyboardDevice final : public SerialIODevice {
|
|||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullOwnPtr<PS2KeyboardDevice>> try_to_initialize(SerialIOController const&, SerialIOController::PortIndex port_index, KeyboardDevice const&);
|
||||
static ErrorOr<NonnullOwnPtr<PS2KeyboardDevice>> try_to_initialize(SerialIOController const&, SerialIOController::PortIndex port_index, ScanCodeSet scan_code_set, KeyboardDevice const&);
|
||||
virtual ~PS2KeyboardDevice() override;
|
||||
ErrorOr<void> initialize();
|
||||
|
||||
|
@ -27,11 +28,37 @@ public:
|
|||
virtual void handle_byte_read_from_serial_input(u8 byte) override;
|
||||
|
||||
private:
|
||||
PS2KeyboardDevice(SerialIOController const&, SerialIOController::PortIndex port_index, KeyboardDevice const&);
|
||||
PS2KeyboardDevice(SerialIOController const&, SerialIOController::PortIndex port_index, ScanCodeSet scan_code_set, KeyboardDevice const&);
|
||||
|
||||
RawKeyEvent generate_raw_key_event_input_from_set1(ScanCodeEvent);
|
||||
RawKeyEvent generate_raw_key_event_input_from_set2(ScanCodeEvent);
|
||||
|
||||
void handle_scan_code_input_event(ScanCodeEvent event);
|
||||
|
||||
void handle_byte_read_for_scan_code_set1(u8 byte);
|
||||
void handle_byte_read_for_scan_code_set2(u8 byte);
|
||||
|
||||
// NOTE: This boolean variable is only used with ScanCodeSet::Set1
|
||||
// because it only has one prefix defined in the scan code set.
|
||||
bool m_has_e0_prefix { false };
|
||||
|
||||
// NOTE: This array and its counter are used only when m_scan_code_set
|
||||
// is set to ScanCodeSet::Set2, because that scan code requires us to
|
||||
// manage scan codes with multiple bytes.
|
||||
// According to the scan code set 2 table, a key press (or release)
|
||||
// can generate up to 8 bytes.
|
||||
Array<u8, 8> m_received_bytes;
|
||||
size_t m_received_bytes_count { 0 };
|
||||
|
||||
bool m_left_shift_pressed { false };
|
||||
bool m_right_shift_pressed { false };
|
||||
bool m_left_super_pressed { false };
|
||||
bool m_right_super_pressed { false };
|
||||
|
||||
NonnullRefPtr<KeyboardDevice> const m_keyboard_device;
|
||||
ScanCodeSet const m_scan_code_set { ScanCodeSet::Set1 };
|
||||
|
||||
EntropySource m_entropy_source;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue