diff --git a/Kernel/API/KeyCode.h b/Kernel/API/KeyCode.h index eab009d07d..c7f191f515 100644 --- a/Kernel/API/KeyCode.h +++ b/Kernel/API/KeyCode.h @@ -8,113 +8,140 @@ #include -#define ENUMERATE_KEY_CODES \ - __ENUMERATE_KEY_CODE(Invalid, "Invalid") \ - __ENUMERATE_KEY_CODE(Escape, "Escape") \ - __ENUMERATE_KEY_CODE(Tab, "Tab") \ - __ENUMERATE_KEY_CODE(Backspace, "Backspace") \ - __ENUMERATE_KEY_CODE(Return, "Return") \ - __ENUMERATE_KEY_CODE(Insert, "Insert") \ - __ENUMERATE_KEY_CODE(Delete, "Delete") \ - __ENUMERATE_KEY_CODE(PrintScreen, "PrintScreen") \ - __ENUMERATE_KEY_CODE(SysRq, "SysRq") \ - __ENUMERATE_KEY_CODE(Home, "Home") \ - __ENUMERATE_KEY_CODE(End, "End") \ - __ENUMERATE_KEY_CODE(Left, "Left") \ - __ENUMERATE_KEY_CODE(Up, "Up") \ - __ENUMERATE_KEY_CODE(Right, "Right") \ - __ENUMERATE_KEY_CODE(Down, "Down") \ - __ENUMERATE_KEY_CODE(PageUp, "PageUp") \ - __ENUMERATE_KEY_CODE(PageDown, "PageDown") \ - __ENUMERATE_KEY_CODE(LeftShift, "LeftShift") \ - __ENUMERATE_KEY_CODE(RightShift, "RightShift") \ - __ENUMERATE_KEY_CODE(Control, "Ctrl") \ - __ENUMERATE_KEY_CODE(Alt, "Alt") \ - __ENUMERATE_KEY_CODE(CapsLock, "CapsLock") \ - __ENUMERATE_KEY_CODE(NumLock, "NumLock") \ - __ENUMERATE_KEY_CODE(ScrollLock, "ScrollLock") \ - __ENUMERATE_KEY_CODE(F1, "F1") \ - __ENUMERATE_KEY_CODE(F2, "F2") \ - __ENUMERATE_KEY_CODE(F3, "F3") \ - __ENUMERATE_KEY_CODE(F4, "F4") \ - __ENUMERATE_KEY_CODE(F5, "F5") \ - __ENUMERATE_KEY_CODE(F6, "F6") \ - __ENUMERATE_KEY_CODE(F7, "F7") \ - __ENUMERATE_KEY_CODE(F8, "F8") \ - __ENUMERATE_KEY_CODE(F9, "F9") \ - __ENUMERATE_KEY_CODE(F10, "F10") \ - __ENUMERATE_KEY_CODE(F11, "F11") \ - __ENUMERATE_KEY_CODE(F12, "F12") \ - __ENUMERATE_KEY_CODE(Space, "Space") \ - __ENUMERATE_KEY_CODE(ExclamationPoint, "!") \ - __ENUMERATE_KEY_CODE(DoubleQuote, "\"") \ - __ENUMERATE_KEY_CODE(Hashtag, "#") \ - __ENUMERATE_KEY_CODE(Dollar, "$") \ - __ENUMERATE_KEY_CODE(Percent, "%") \ - __ENUMERATE_KEY_CODE(Ampersand, "&") \ - __ENUMERATE_KEY_CODE(Apostrophe, "'") \ - __ENUMERATE_KEY_CODE(LeftParen, "(") \ - __ENUMERATE_KEY_CODE(RightParen, ")") \ - __ENUMERATE_KEY_CODE(Asterisk, "*") \ - __ENUMERATE_KEY_CODE(Plus, "+") \ - __ENUMERATE_KEY_CODE(Comma, ",") \ - __ENUMERATE_KEY_CODE(Minus, "-") \ - __ENUMERATE_KEY_CODE(Period, ".") \ - __ENUMERATE_KEY_CODE(Slash, "/") \ - __ENUMERATE_KEY_CODE(0, "0") \ - __ENUMERATE_KEY_CODE(1, "1") \ - __ENUMERATE_KEY_CODE(2, "2") \ - __ENUMERATE_KEY_CODE(3, "3") \ - __ENUMERATE_KEY_CODE(4, "4") \ - __ENUMERATE_KEY_CODE(5, "5") \ - __ENUMERATE_KEY_CODE(6, "6") \ - __ENUMERATE_KEY_CODE(7, "7") \ - __ENUMERATE_KEY_CODE(8, "8") \ - __ENUMERATE_KEY_CODE(9, "9") \ - __ENUMERATE_KEY_CODE(Colon, ":") \ - __ENUMERATE_KEY_CODE(Semicolon, ";") \ - __ENUMERATE_KEY_CODE(LessThan, "<") \ - __ENUMERATE_KEY_CODE(Equal, "=") \ - __ENUMERATE_KEY_CODE(GreaterThan, ">") \ - __ENUMERATE_KEY_CODE(QuestionMark, "?") \ - __ENUMERATE_KEY_CODE(AtSign, "@") \ - __ENUMERATE_KEY_CODE(A, "A") \ - __ENUMERATE_KEY_CODE(B, "B") \ - __ENUMERATE_KEY_CODE(C, "C") \ - __ENUMERATE_KEY_CODE(D, "D") \ - __ENUMERATE_KEY_CODE(E, "E") \ - __ENUMERATE_KEY_CODE(F, "F") \ - __ENUMERATE_KEY_CODE(G, "G") \ - __ENUMERATE_KEY_CODE(H, "H") \ - __ENUMERATE_KEY_CODE(I, "I") \ - __ENUMERATE_KEY_CODE(J, "J") \ - __ENUMERATE_KEY_CODE(K, "K") \ - __ENUMERATE_KEY_CODE(L, "L") \ - __ENUMERATE_KEY_CODE(M, "M") \ - __ENUMERATE_KEY_CODE(N, "N") \ - __ENUMERATE_KEY_CODE(O, "O") \ - __ENUMERATE_KEY_CODE(P, "P") \ - __ENUMERATE_KEY_CODE(Q, "Q") \ - __ENUMERATE_KEY_CODE(R, "R") \ - __ENUMERATE_KEY_CODE(S, "S") \ - __ENUMERATE_KEY_CODE(T, "T") \ - __ENUMERATE_KEY_CODE(U, "U") \ - __ENUMERATE_KEY_CODE(V, "V") \ - __ENUMERATE_KEY_CODE(W, "W") \ - __ENUMERATE_KEY_CODE(X, "X") \ - __ENUMERATE_KEY_CODE(Y, "Y") \ - __ENUMERATE_KEY_CODE(Z, "Z") \ - __ENUMERATE_KEY_CODE(LeftBracket, "[") \ - __ENUMERATE_KEY_CODE(RightBracket, "]") \ - __ENUMERATE_KEY_CODE(Backslash, "\\") \ - __ENUMERATE_KEY_CODE(Circumflex, "^") \ - __ENUMERATE_KEY_CODE(Underscore, "_") \ - __ENUMERATE_KEY_CODE(LeftBrace, "{") \ - __ENUMERATE_KEY_CODE(RightBrace, "}") \ - __ENUMERATE_KEY_CODE(Pipe, "|") \ - __ENUMERATE_KEY_CODE(Tilde, "~") \ - __ENUMERATE_KEY_CODE(Backtick, "`") \ - __ENUMERATE_KEY_CODE(Super, "Super") \ +#define ENUMERATE_KEY_CODES \ + __ENUMERATE_KEY_CODE(Invalid, "Invalid") \ + __ENUMERATE_KEY_CODE(Escape, "Escape") \ + __ENUMERATE_KEY_CODE(Tab, "Tab") \ + __ENUMERATE_KEY_CODE(Backspace, "Backspace") \ + __ENUMERATE_KEY_CODE(Return, "Return") \ + __ENUMERATE_KEY_CODE(Insert, "Insert") \ + __ENUMERATE_KEY_CODE(Delete, "Delete") \ + __ENUMERATE_KEY_CODE(PrintScreen, "PrintScreen") \ + __ENUMERATE_KEY_CODE(PauseBreak, "PauseBreak") \ + __ENUMERATE_KEY_CODE(SysRq, "SysRq") \ + __ENUMERATE_KEY_CODE(Home, "Home") \ + __ENUMERATE_KEY_CODE(End, "End") \ + __ENUMERATE_KEY_CODE(Left, "Left") \ + __ENUMERATE_KEY_CODE(Up, "Up") \ + __ENUMERATE_KEY_CODE(Right, "Right") \ + __ENUMERATE_KEY_CODE(Down, "Down") \ + __ENUMERATE_KEY_CODE(PageUp, "PageUp") \ + __ENUMERATE_KEY_CODE(PageDown, "PageDown") \ + __ENUMERATE_KEY_CODE(LeftShift, "LeftShift") \ + __ENUMERATE_KEY_CODE(RightShift, "RightShift") \ + __ENUMERATE_KEY_CODE(Control, "Ctrl") \ + __ENUMERATE_KEY_CODE(RightControl, "RightCtrl") \ + __ENUMERATE_KEY_CODE(Alt, "Alt") \ + __ENUMERATE_KEY_CODE(RightAlt, "Alt") \ + __ENUMERATE_KEY_CODE(CapsLock, "CapsLock") \ + __ENUMERATE_KEY_CODE(NumLock, "NumLock") \ + __ENUMERATE_KEY_CODE(ScrollLock, "ScrollLock") \ + __ENUMERATE_KEY_CODE(F1, "F1") \ + __ENUMERATE_KEY_CODE(F2, "F2") \ + __ENUMERATE_KEY_CODE(F3, "F3") \ + __ENUMERATE_KEY_CODE(F4, "F4") \ + __ENUMERATE_KEY_CODE(F5, "F5") \ + __ENUMERATE_KEY_CODE(F6, "F6") \ + __ENUMERATE_KEY_CODE(F7, "F7") \ + __ENUMERATE_KEY_CODE(F8, "F8") \ + __ENUMERATE_KEY_CODE(F9, "F9") \ + __ENUMERATE_KEY_CODE(F10, "F10") \ + __ENUMERATE_KEY_CODE(F11, "F11") \ + __ENUMERATE_KEY_CODE(F12, "F12") \ + __ENUMERATE_KEY_CODE(Space, "Space") \ + __ENUMERATE_KEY_CODE(ExclamationPoint, "!") \ + __ENUMERATE_KEY_CODE(DoubleQuote, "\"") \ + __ENUMERATE_KEY_CODE(Hashtag, "#") \ + __ENUMERATE_KEY_CODE(Dollar, "$") \ + __ENUMERATE_KEY_CODE(Percent, "%") \ + __ENUMERATE_KEY_CODE(Ampersand, "&") \ + __ENUMERATE_KEY_CODE(Apostrophe, "'") \ + __ENUMERATE_KEY_CODE(LeftParen, "(") \ + __ENUMERATE_KEY_CODE(RightParen, ")") \ + __ENUMERATE_KEY_CODE(Asterisk, "*") \ + __ENUMERATE_KEY_CODE(Plus, "+") \ + __ENUMERATE_KEY_CODE(Comma, ",") \ + __ENUMERATE_KEY_CODE(Minus, "-") \ + __ENUMERATE_KEY_CODE(Period, ".") \ + __ENUMERATE_KEY_CODE(Slash, "/") \ + __ENUMERATE_KEY_CODE(0, "0") \ + __ENUMERATE_KEY_CODE(1, "1") \ + __ENUMERATE_KEY_CODE(2, "2") \ + __ENUMERATE_KEY_CODE(3, "3") \ + __ENUMERATE_KEY_CODE(4, "4") \ + __ENUMERATE_KEY_CODE(5, "5") \ + __ENUMERATE_KEY_CODE(6, "6") \ + __ENUMERATE_KEY_CODE(7, "7") \ + __ENUMERATE_KEY_CODE(8, "8") \ + __ENUMERATE_KEY_CODE(9, "9") \ + __ENUMERATE_KEY_CODE(Colon, ":") \ + __ENUMERATE_KEY_CODE(Semicolon, ";") \ + __ENUMERATE_KEY_CODE(LessThan, "<") \ + __ENUMERATE_KEY_CODE(Equal, "=") \ + __ENUMERATE_KEY_CODE(GreaterThan, ">") \ + __ENUMERATE_KEY_CODE(QuestionMark, "?") \ + __ENUMERATE_KEY_CODE(AtSign, "@") \ + __ENUMERATE_KEY_CODE(A, "A") \ + __ENUMERATE_KEY_CODE(B, "B") \ + __ENUMERATE_KEY_CODE(C, "C") \ + __ENUMERATE_KEY_CODE(D, "D") \ + __ENUMERATE_KEY_CODE(E, "E") \ + __ENUMERATE_KEY_CODE(F, "F") \ + __ENUMERATE_KEY_CODE(G, "G") \ + __ENUMERATE_KEY_CODE(H, "H") \ + __ENUMERATE_KEY_CODE(I, "I") \ + __ENUMERATE_KEY_CODE(J, "J") \ + __ENUMERATE_KEY_CODE(K, "K") \ + __ENUMERATE_KEY_CODE(L, "L") \ + __ENUMERATE_KEY_CODE(M, "M") \ + __ENUMERATE_KEY_CODE(N, "N") \ + __ENUMERATE_KEY_CODE(O, "O") \ + __ENUMERATE_KEY_CODE(P, "P") \ + __ENUMERATE_KEY_CODE(Q, "Q") \ + __ENUMERATE_KEY_CODE(R, "R") \ + __ENUMERATE_KEY_CODE(S, "S") \ + __ENUMERATE_KEY_CODE(T, "T") \ + __ENUMERATE_KEY_CODE(U, "U") \ + __ENUMERATE_KEY_CODE(V, "V") \ + __ENUMERATE_KEY_CODE(W, "W") \ + __ENUMERATE_KEY_CODE(X, "X") \ + __ENUMERATE_KEY_CODE(Y, "Y") \ + __ENUMERATE_KEY_CODE(Z, "Z") \ + __ENUMERATE_KEY_CODE(LeftBracket, "[") \ + __ENUMERATE_KEY_CODE(RightBracket, "]") \ + __ENUMERATE_KEY_CODE(Backslash, "\\") \ + __ENUMERATE_KEY_CODE(Circumflex, "^") \ + __ENUMERATE_KEY_CODE(Underscore, "_") \ + __ENUMERATE_KEY_CODE(LeftBrace, "{") \ + __ENUMERATE_KEY_CODE(RightBrace, "}") \ + __ENUMERATE_KEY_CODE(Pipe, "|") \ + __ENUMERATE_KEY_CODE(Tilde, "~") \ + __ENUMERATE_KEY_CODE(Backtick, "`") \ + __ENUMERATE_KEY_CODE(Super, "Super") \ + __ENUMERATE_KEY_CODE(BrowserSearch, "BrowserSearch") \ + __ENUMERATE_KEY_CODE(BrowserFavorites, "BrowserFavorites") \ + __ENUMERATE_KEY_CODE(BrowserHome, "BrowserHome") \ + __ENUMERATE_KEY_CODE(PreviousTrack, "PreviousTrack") \ + __ENUMERATE_KEY_CODE(BrowserBack, "BrowserBack") \ + __ENUMERATE_KEY_CODE(BrowserForward, "BrowserForward") \ + __ENUMERATE_KEY_CODE(BrowserRefresh, "BrowserRefresh") \ + __ENUMERATE_KEY_CODE(BrowserStop, "BrowserStop") \ + __ENUMERATE_KEY_CODE(VolumeDown, "VolumeDown") \ + __ENUMERATE_KEY_CODE(VolumeUp, "VolumeUp") \ + __ENUMERATE_KEY_CODE(Wake, "Wake") \ + __ENUMERATE_KEY_CODE(Sleep, "Sleep") \ + __ENUMERATE_KEY_CODE(NextTrack, "NextTrack") \ + __ENUMERATE_KEY_CODE(MediaSelect, "MediaSelect") \ + __ENUMERATE_KEY_CODE(Email, "Email") \ + __ENUMERATE_KEY_CODE(MyComputer, "MyComputer") \ + __ENUMERATE_KEY_CODE(Power, "Power") \ + __ENUMERATE_KEY_CODE(Stop, "Stop") \ + __ENUMERATE_KEY_CODE(LeftGUI, "LeftGUI") \ + __ENUMERATE_KEY_CODE(Mute, "Mute") \ + __ENUMERATE_KEY_CODE(RightGUI, "RightGUI") \ + __ENUMERATE_KEY_CODE(Calculator, "Calculator") \ + __ENUMERATE_KEY_CODE(Apps, "Apps") \ + __ENUMERATE_KEY_CODE(PlayPause, "PlayPause") \ __ENUMERATE_KEY_CODE(Menu, "Menu") enum KeyCode : u8 { @@ -143,11 +170,10 @@ enum KeyModifier { struct KeyEvent { KeyCode key { Key_Invalid }; u8 map_entry_index { 0 }; - u32 scancode { 0 }; + u64 scancode { 0 }; u32 code_point { 0 }; u8 flags { 0 }; bool caps_lock_on { false }; - bool e0_prefix { false }; bool alt() const { return flags & Mod_Alt; } bool ctrl() const { return flags & Mod_Ctrl; } bool shift() const { return flags & Mod_Shift; } diff --git a/Kernel/Arch/x86_64/ISABus/I8042Controller.cpp b/Kernel/Arch/x86_64/ISABus/I8042Controller.cpp index 0fd6cce927..1155d783ac 100644 --- a/Kernel/Arch/x86_64/ISABus/I8042Controller.cpp +++ b/Kernel/Arch/x86_64/ISABus/I8042Controller.cpp @@ -120,7 +120,7 @@ UNMAP_AFTER_INIT bool I8042Controller::check_existence_via_probing(Badge I8042Controller::detect_devices() +UNMAP_AFTER_INIT ErrorOr I8042Controller::detect_devices(EnableKeyboardFirstPortTranslation enable_first_port_translation) { u8 configuration; { @@ -135,7 +135,13 @@ UNMAP_AFTER_INIT ErrorOr I8042Controller::detect_devices() configuration = TRY(do_wait_then_read_any_input(I8042Port::Buffer)); configuration &= ~I8042ConfigurationFlag::FirstPS2PortInterrupt; configuration &= ~I8042ConfigurationFlag::SecondPS2PortInterrupt; - configuration |= I8042ConfigurationFlag::FirstPS2PortTranslation; + + // FIXME: Don't enable translation for the first i8042 port if nothing is connected + // or even worse - a mouse device, because we will get garbage data. + if (enable_first_port_translation == EnableKeyboardFirstPortTranslation::Yes) + configuration |= I8042ConfigurationFlag::FirstPS2PortTranslation; + else + configuration &= ~I8042ConfigurationFlag::FirstPS2PortTranslation; TRY(do_wait_then_write(I8042Port::Command, I8042Command::WriteConfiguration)); TRY(do_wait_then_write(I8042Port::Buffer, configuration)); @@ -197,7 +203,9 @@ UNMAP_AFTER_INIT ErrorOr I8042Controller::detect_devices() // FIXME: Actually figure out the connected PS2 device type m_first_ps2_port.device_type = PS2DeviceType::StandardKeyboard; auto keyboard_device = TRY(KeyboardDevice::try_to_initialize()); - auto error_or_device = PS2KeyboardDevice::try_to_initialize(*this, I8042PortIndex::FirstPort, *keyboard_device); + // FIXME: Determine if the user wants to operate in scan code set 3. + auto keyboard_device_scan_code_set = enable_first_port_translation == EnableKeyboardFirstPortTranslation::Yes ? ScanCodeSet::Set1 : ScanCodeSet::Set2; + auto error_or_device = PS2KeyboardDevice::try_to_initialize(*this, I8042PortIndex::FirstPort, keyboard_device_scan_code_set, *keyboard_device); if (error_or_device.is_error()) { dbgln("I8042: Keyboard device failed to initialize, disable"); m_first_port_available = false; diff --git a/Kernel/Arch/x86_64/ISABus/I8042Controller.h b/Kernel/Arch/x86_64/ISABus/I8042Controller.h index 833c6e978f..69be77416b 100644 --- a/Kernel/Arch/x86_64/ISABus/I8042Controller.h +++ b/Kernel/Arch/x86_64/ISABus/I8042Controller.h @@ -94,7 +94,12 @@ class I8042Controller final : public SerialIOController { public: static ErrorOr> create(); - ErrorOr detect_devices(); + enum class EnableKeyboardFirstPortTranslation { + Yes, + No + }; + ErrorOr detect_devices(EnableKeyboardFirstPortTranslation); + virtual ErrorOr send_command(PortIndex, DeviceCommand command) override; virtual ErrorOr send_command(PortIndex, DeviceCommand command, u8 data) override; diff --git a/Kernel/Devices/HID/Definitions.h b/Kernel/Devices/HID/Definitions.h new file mode 100644 index 0000000000..cc00914d6a --- /dev/null +++ b/Kernel/Devices/HID/Definitions.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +enum class ScanCodeSet { + Set1 = 1, + Set2 = 2, + Set3 = 3, +}; + +struct KeyCodeEntry { + KeyCode key_code; + u8 map_entry_index; +}; + +struct RawKeyEvent { + KeyCodeEntry code_entry; + u64 scancode { 0 }; + bool is_press_down { false }; + bool is_press() const { return is_press_down; } +}; + +} diff --git a/Kernel/Devices/HID/KeyboardDevice.cpp b/Kernel/Devices/HID/KeyboardDevice.cpp index 8fb25f0a40..67c355074e 100644 --- a/Kernel/Devices/HID/KeyboardDevice.cpp +++ b/Kernel/Devices/HID/KeyboardDevice.cpp @@ -20,309 +20,46 @@ namespace Kernel { -static constexpr KeyCode unshifted_key_map[0x80] = { - Key_Invalid, - Key_Escape, - Key_1, - Key_2, - Key_3, - Key_4, - Key_5, - Key_6, - Key_7, - Key_8, - Key_9, - Key_0, - Key_Minus, - Key_Equal, - Key_Backspace, - Key_Tab, // 15 - Key_Q, - Key_W, - Key_E, - Key_R, - Key_T, - Key_Y, - Key_U, - Key_I, - Key_O, - Key_P, - Key_LeftBracket, - Key_RightBracket, - Key_Return, // 28 - Key_Control, // 29 - Key_A, - Key_S, - Key_D, - Key_F, - Key_G, - Key_H, - Key_J, - Key_K, - Key_L, - Key_Semicolon, - Key_Apostrophe, - Key_Backtick, - Key_LeftShift, // 42 - Key_Backslash, - Key_Z, - Key_X, - Key_C, - Key_V, - Key_B, - Key_N, - Key_M, - Key_Comma, - Key_Period, - Key_Slash, - Key_RightShift, // 54 - Key_Asterisk, - Key_Alt, // 56 - Key_Space, // 57 - Key_CapsLock, // 58 - Key_F1, - Key_F2, - Key_F3, - Key_F4, - Key_F5, - Key_F6, - Key_F7, - Key_F8, - Key_F9, - Key_F10, - Key_NumLock, - Key_Invalid, // 70 - Key_Home, - Key_Up, - Key_PageUp, - Key_Minus, - Key_Left, - Key_Invalid, - Key_Right, // 77 - Key_Plus, - Key_End, - Key_Down, // 80 - Key_PageDown, - Key_Insert, - Key_Delete, // 83 - Key_Invalid, - Key_Invalid, - Key_Backslash, - Key_F11, - Key_F12, - Key_Invalid, - Key_Invalid, - Key_Super, - Key_Invalid, - Key_Menu, -}; - -static constexpr KeyCode shifted_key_map[0x100] = { - Key_Invalid, - Key_Escape, - Key_ExclamationPoint, - Key_AtSign, - Key_Hashtag, - Key_Dollar, - Key_Percent, - Key_Circumflex, - Key_Ampersand, - Key_Asterisk, - Key_LeftParen, - Key_RightParen, - Key_Underscore, - Key_Plus, - Key_Backspace, - Key_Tab, - Key_Q, - Key_W, - Key_E, - Key_R, - Key_T, - Key_Y, - Key_U, - Key_I, - Key_O, - Key_P, - Key_LeftBrace, - Key_RightBrace, - Key_Return, - Key_Control, - Key_A, - Key_S, - Key_D, - Key_F, - Key_G, - Key_H, - Key_J, - Key_K, - Key_L, - Key_Colon, - Key_DoubleQuote, - Key_Tilde, - Key_LeftShift, // 42 - Key_Pipe, - Key_Z, - Key_X, - Key_C, - Key_V, - Key_B, - Key_N, - Key_M, - Key_LessThan, - Key_GreaterThan, - Key_QuestionMark, - Key_RightShift, // 54 - Key_Asterisk, - Key_Alt, - Key_Space, // 57 - Key_CapsLock, // 58 - Key_F1, - Key_F2, - Key_F3, - Key_F4, - Key_F5, - Key_F6, - Key_F7, - Key_F8, - Key_F9, - Key_F10, - Key_NumLock, - Key_Invalid, // 70 - Key_Home, - Key_Up, - Key_PageUp, - Key_Minus, - Key_Left, - Key_Invalid, - Key_Right, // 77 - Key_Plus, - Key_End, - Key_Down, // 80 - Key_PageDown, - Key_Insert, - Key_Delete, // 83 - Key_Invalid, - Key_Invalid, - Key_Pipe, - Key_F11, - Key_F12, - Key_Invalid, - Key_Invalid, - Key_Super, - Key_Invalid, - Key_Menu, -}; - -void KeyboardDevice::handle_scan_code_input_event(ScanCodeEvent event) +void KeyboardDevice::handle_input_event(KeyEvent queued_event) { - m_entropy_source.add_random_event(event.scan_code_value); - switch (event.scan_code_value) { - case 0x38: - if (event.e0_prefix) - update_modifier(Mod_AltGr, event.pressed); - else - update_modifier(Mod_Alt, event.pressed); - break; - case 0x1d: - update_modifier(Mod_Ctrl, event.pressed); - break; - case 0x5b: - m_left_super_pressed = event.pressed; - update_modifier(Mod_Super, m_left_super_pressed || m_right_super_pressed); - break; - case 0x5c: - m_right_super_pressed = event.pressed; - update_modifier(Mod_Super, m_left_super_pressed || m_right_super_pressed); - break; - case 0x2a: - m_left_shift_pressed = event.pressed; - update_modifier(Mod_Shift, m_left_shift_pressed || m_right_shift_pressed); - break; - case 0x36: - m_right_shift_pressed = event.pressed; - update_modifier(Mod_Shift, m_left_shift_pressed || m_right_shift_pressed); - break; - case 0x1c: - case 0x35: - if (event.e0_prefix) - update_modifier(Mod_Keypad, event.pressed); - 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 (!event.e0_prefix) - update_modifier(Mod_Keypad, event.pressed); - break; - } + if (queued_event.key == Key_NumLock && queued_event.is_press()) + m_num_lock_on = !m_num_lock_on; - KeyCode key = (m_modifiers & Mod_Shift) ? shifted_key_map[event.scan_code_value] : unshifted_key_map[event.scan_code_value]; + queued_event.flags |= m_modifiers; - if ((m_modifiers == (Mod_Alt | Mod_Shift) || m_modifiers == (Mod_Ctrl | Mod_Alt | Mod_Shift)) && key == Key_F12) { + if (queued_event.is_press() && (m_modifiers == (Mod_Alt | Mod_Shift) || m_modifiers == (Mod_Ctrl | Mod_Alt | Mod_Shift)) && queued_event.key == Key_F12) { // Alt+Shift+F12 pressed, dump some kernel state to the debug console. ConsoleManagement::the().switch_to_debug(); Scheduler::dump_scheduler_state(m_modifiers == (Mod_Ctrl | Mod_Alt | Mod_Shift)); } - if ((m_modifiers & Mod_Alt) != 0 && key >= Key_1 && key < Key_1 + ConsoleManagement::s_max_virtual_consoles) { - // FIXME: Do something sanely here if we can't allocate a work queue? - MUST(g_io_work->try_queue([key]() { - ConsoleManagement::the().switch_to(key - Key_1); - })); - } - - if (key == Key_NumLock && event.pressed) - m_num_lock_on = !m_num_lock_on; - - if (m_num_lock_on && !event.e0_prefix) { - if (event.scan_code_value >= 0x47 && event.scan_code_value <= 0x53) { - u8 index = event.scan_code_value - 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) { - key = newKey; - } + { + auto key = queued_event.key; + if (queued_event.is_press() && (m_modifiers & Mod_Alt) != 0 && key >= Key_1 && key < Key_1 + ConsoleManagement::s_max_virtual_consoles) { + // FIXME: Do something sanely here if we can't allocate a work queue? + MUST(g_io_work->try_queue([key]() { + ConsoleManagement::the().switch_to(key - Key_1); + })); } } - Event queued_event; - queued_event.key = key; - queued_event.map_entry_index = event.scan_code_value & 0xFF; - queued_event.scancode = event.e0_prefix ? 0xe000 + event.scan_code_value : event.scan_code_value; - queued_event.flags = m_modifiers; - queued_event.e0_prefix = event.e0_prefix; - queued_event.caps_lock_on = m_caps_lock_on; - queued_event.code_point = HIDManagement::the().get_char_from_character_map(queued_event, m_num_lock_on); - // If using a non-QWERTY layout, queued_event.key needs to be updated to be the same as event.code_point KeyCode mapped_key = code_point_to_key_code(queued_event.code_point); - if (mapped_key != KeyCode::Key_Invalid) { + if (mapped_key != KeyCode::Key_Invalid) queued_event.key = mapped_key; - key = mapped_key; - } - if (!g_caps_lock_remapped_to_ctrl && key == Key_CapsLock && event.pressed) + if (!g_caps_lock_remapped_to_ctrl && queued_event.key == Key_CapsLock && queued_event.is_press()) m_caps_lock_on = !m_caps_lock_on; - if (g_caps_lock_remapped_to_ctrl && key == Key_CapsLock) { - m_caps_lock_to_ctrl_pressed = event.pressed; + queued_event.caps_lock_on = m_caps_lock_on; + + if (g_caps_lock_remapped_to_ctrl && queued_event.key == Key_CapsLock) { + m_caps_lock_to_ctrl_pressed = queued_event.is_press(); update_modifier(Mod_Ctrl, m_caps_lock_to_ctrl_pressed); } - if (event.pressed) - queued_event.flags |= Is_Press; + if (queued_event.map_entry_index != 0xFF) + queued_event.code_point = HIDManagement::the().get_char_from_character_map(queued_event, queued_event.map_entry_index); { SpinlockLocker locker(HIDManagement::the().m_client_lock); diff --git a/Kernel/Devices/HID/KeyboardDevice.h b/Kernel/Devices/HID/KeyboardDevice.h index 9c7d7042c3..10b70de12a 100644 --- a/Kernel/Devices/HID/KeyboardDevice.h +++ b/Kernel/Devices/HID/KeyboardDevice.h @@ -34,8 +34,6 @@ public: virtual ErrorOr write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override { return EINVAL; } virtual bool can_write(OpenFileDescription const&, u64) const override { return true; } - void handle_scan_code_input_event(ScanCodeEvent); - // ^File virtual ErrorOr ioctl(OpenFileDescription&, unsigned request, Userspace arg) override; @@ -47,6 +45,11 @@ public: m_modifiers &= ~modifier; } + u8 modifiers() const { return m_modifiers; } + + void handle_input_event(KeyEvent); + bool num_lock_on() const { return m_num_lock_on; } + protected: KeyboardDevice(); mutable Spinlock m_queue_lock {}; @@ -58,10 +61,6 @@ protected: bool m_caps_lock_to_ctrl_pressed { false }; bool m_caps_lock_on { false }; bool m_num_lock_on { false }; - bool m_left_shift_pressed { false }; - bool m_right_shift_pressed { false }; - bool m_left_super_pressed { false }; - bool m_right_super_pressed { false }; void key_state_changed(u8 raw, bool pressed); }; diff --git a/Kernel/Devices/HID/Management.cpp b/Kernel/Devices/HID/Management.cpp index 6badd34b8c..912302abdc 100644 --- a/Kernel/Devices/HID/Management.cpp +++ b/Kernel/Devices/HID/Management.cpp @@ -167,7 +167,7 @@ UNMAP_AFTER_INIT ErrorOr HIDManagement::enumerate() // Note: If we happen to not have i8042 just return "gracefully" for now. if (!has_i8042_controller) return {}; - if (auto result_or_error = i8042_controller->detect_devices(); result_or_error.is_error()) + if (auto result_or_error = i8042_controller->detect_devices(I8042Controller::EnableKeyboardFirstPortTranslation::No); result_or_error.is_error()) return {}; m_hid_serial_io_controllers.with([&](auto& list) { list.append(i8042_controller); @@ -188,10 +188,10 @@ HIDManagement& HIDManagement::the() return *s_the; } -u32 HIDManagement::get_char_from_character_map(KeyEvent event, bool num_lock_on) const +u32 HIDManagement::get_char_from_character_map(KeyEvent event, u8 index) const { + VERIFY(index < CHAR_MAP_SIZE); auto modifiers = event.modifiers(); - auto index = event.scancode & 0xFF; // Index is last byte of scan code. auto caps_lock_on = event.caps_lock_on; u32 code_point = 0; @@ -215,19 +215,6 @@ u32 HIDManagement::get_char_from_character_map(KeyEvent event, bool num_lock_on) code_point |= 0x20; } - if (event.e0_prefix && event.key == Key_Slash) { - // If Key_Slash (scancode = 0x35) mapped to other form "/", we fix num pad key of "/" with this case. - code_point = '/'; - } else if (event.e0_prefix && 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. - code_point = 0; - } else if (!num_lock_on && !event.e0_prefix && event.scancode >= 0x47 && event.scancode <= 0x53 && event.key != Key_Minus && event.key != Key_Plus) { - // When Num Lock is off, some numpad keys have the same function as some of the extended keys like Home, End, PgDown, arrows etc. - // These keys should have the code_point set to 0. - code_point = 0; - } - return code_point; } diff --git a/Kernel/Devices/HID/Management.h b/Kernel/Devices/HID/Management.h index 5dc07b416a..31f5c6dcc8 100644 --- a/Kernel/Devices/HID/Management.h +++ b/Kernel/Devices/HID/Management.h @@ -48,7 +48,7 @@ public: SpinlockProtected& keymap_data() { return m_keymap_data; } - u32 get_char_from_character_map(KeyEvent, bool) const; + u32 get_char_from_character_map(KeyEvent, u8) const; void set_client(KeyboardClient* client); void set_maps(NonnullOwnPtr character_map_name, Keyboard::CharacterMapData const& character_map); diff --git a/Kernel/Devices/HID/PS2/KeyboardDevice.cpp b/Kernel/Devices/HID/PS2/KeyboardDevice.cpp index 59d5e7fb6a..1a570e7d68 100644 --- a/Kernel/Devices/HID/PS2/KeyboardDevice.cpp +++ b/Kernel/Devices/HID/PS2/KeyboardDevice.cpp @@ -19,28 +19,699 @@ 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; +} + +Optional 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]; + if (first_byte_prefix != 0xe0 + || second_byte_prefix != 0xf0) { + return Optional {}; + } + + 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]; + if (first_byte_prefix != 0xe0 + || second_byte_prefix != 0x12 + || third_byte_prefix != 0xe0 + || fourth_byte_prefix != 0x7c) { + return Optional {}; + } + + 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]; + if (first_byte_prefix != 0xe0 + || second_byte_prefix != 0xf0 + || third_byte_prefix != 0x7c + || fourth_byte_prefix != 0xe0 + || fifth_byte_prefix != 0xf0 + || sixth_byte_prefix != 0x12) { + return Optional {}; + } + + 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]; + if (first_byte_prefix != 0xe1 + || second_byte_prefix != 0x14 + || third_byte_prefix != 0x77 + || fourth_byte_prefix != 0xe1 + || fifth_byte_prefix != 0xf0 + || sixth_byte_prefix != 0x14 + || seventh_byte_prefix != 0xf0 + || eight_byte_prefix != 0x77) { + return Optional {}; + } + + 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) { + auto possible_raw_event = generate_raw_key_event_input_from_set2(event); + if (!possible_raw_event.has_value()) { + dmesgln("PS2KeyboardDevice BUG: Invalid scan code (set 2) event, length: {}, bytes: {}", event.bytes_count, event.scan_code_bytes.span().trim(event.bytes_count)); + return; + } + raw_event = possible_raw_event.release_value(); + } 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; + } + } + } + + 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> 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) { + 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> 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 +745,10 @@ UNMAP_AFTER_INIT ErrorOr 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) { } diff --git a/Kernel/Devices/HID/PS2/KeyboardDevice.h b/Kernel/Devices/HID/PS2/KeyboardDevice.h index 66387b4792..2ab126a129 100644 --- a/Kernel/Devices/HID/PS2/KeyboardDevice.h +++ b/Kernel/Devices/HID/PS2/KeyboardDevice.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -19,7 +20,7 @@ class PS2KeyboardDevice final : public SerialIODevice { friend class DeviceManagement; public: - static ErrorOr> try_to_initialize(SerialIOController const&, SerialIOController::PortIndex port_index, KeyboardDevice const&); + static ErrorOr> try_to_initialize(SerialIOController const&, SerialIOController::PortIndex port_index, ScanCodeSet scan_code_set, KeyboardDevice const&); virtual ~PS2KeyboardDevice() override; ErrorOr 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); + Optional 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 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 const m_keyboard_device; + ScanCodeSet const m_scan_code_set { ScanCodeSet::Set1 }; + + EntropySource m_entropy_source; }; } diff --git a/Kernel/Devices/HID/ScanCodeEvent.h b/Kernel/Devices/HID/ScanCodeEvent.h index d89e8fc5fb..3a1d8a44c9 100644 --- a/Kernel/Devices/HID/ScanCodeEvent.h +++ b/Kernel/Devices/HID/ScanCodeEvent.h @@ -7,13 +7,14 @@ #pragma once #include +#include namespace Kernel { struct ScanCodeEvent { - u32 scan_code_value { 0 }; - bool pressed { false }; - bool e0_prefix { false }; + Array scan_code_bytes; + ScanCodeSet sent_scan_code_set { ScanCodeSet::Set1 }; + u8 bytes_count { 0 }; }; } diff --git a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp index cab4243ab0..13b7712fb7 100644 --- a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp @@ -143,8 +143,9 @@ static ErrorOr> get_event_named_key(KeyCode platform_key) // 3.2. Modifier Keys, https://www.w3.org/TR/uievents-key/#keys-modifier case KeyCode::Key_Alt: - return "Alt"_string; - // FIXME: AltGraph + return "AltLeft"_string; + case KeyCode::Key_RightAlt: + return "AltRight"_string; case KeyCode::Key_CapsLock: return "CapsLock"_string; case KeyCode::Key_Control: @@ -457,7 +458,9 @@ static ErrorOr get_event_code(KeyCode platform_key, unsigned modifiers) // 3.1.2. Functional Keys, https://www.w3.org/TR/uievents-code/#key-alphanumeric-functional case KeyCode::Key_Alt: - return "Alt"_string; // FIXME: Detect left vs. right key. + return "AltLeft"_string; + case KeyCode::Key_RightAlt: + return "AltRight"_string; case KeyCode::Key_Backspace: return "Backspace"_string; case KeyCode::Key_CapsLock: @@ -465,7 +468,9 @@ static ErrorOr get_event_code(KeyCode platform_key, unsigned modifiers) case KeyCode::Key_Menu: return "ContextMenu"_string; case KeyCode::Key_Control: - return "Control"_string; // FIXME: Detect left vs. right key. + return "ControlLeft"_string; + case KeyCode::Key_RightControl: + return "ControlRight"_string; case KeyCode::Key_Return: return "Enter"_string; case KeyCode::Key_Super: @@ -540,7 +545,60 @@ static ErrorOr get_event_code(KeyCode platform_key, unsigned modifiers) return "PrintScreen"_string; case KeyCode::Key_ScrollLock: return "ScrollLock"_string; - // FIXME: Pause + case KeyCode::Key_PauseBreak: + return "Pause"_string; + + // 3.6. Media Section, https://www.w3.org/TR/uievents-code/#media-keys + case KeyCode::Key_BrowserSearch: + return "BrowserSearch"_string; + case KeyCode::Key_BrowserFavorites: + return "BrowserFavorites"_string; + case KeyCode::Key_BrowserHome: + return "BrowserHome"_string; + case KeyCode::Key_PreviousTrack: + return "PreviousTrack"_string; + case KeyCode::Key_BrowserBack: + return "BrowserBack"_string; + case KeyCode::Key_BrowserForward: + return "BrowserForward"_string; + case KeyCode::Key_BrowserRefresh: + return "BrowserRefresh"_string; + case KeyCode::Key_BrowserStop: + return "BrowserStop"_string; + case KeyCode::Key_VolumeDown: + return "AudioVolumeDown"_string; + case KeyCode::Key_VolumeUp: + return "AudioVolumeUp"_string; + case KeyCode::Key_Wake: + return "WakeUp"_string; + case KeyCode::Key_Sleep: + return "Sleep"_string; + case KeyCode::Key_NextTrack: + return "NextTrack"_string; + case KeyCode::Key_MediaSelect: + return "MediaSelect"_string; + case KeyCode::Key_Email: + return "LaunchMail"_string; + + case KeyCode::Key_Power: + return "Power"_string; + case KeyCode::Key_Stop: + return "MediaStop"_string; + case KeyCode::Key_PlayPause: + return "MediaPlayPause"_string; + case KeyCode::Key_Mute: + return "AudioVolumeMute"_string; + case KeyCode::Key_Calculator: + return "LaunchApp2"_string; + case KeyCode::Key_MyComputer: + return "LaunchApp1"_string; + + // FIXME: Are these correct? + case KeyCode::Key_LeftGUI: + return "LaunchApp2"_string; + case KeyCode::Key_RightGUI: + case KeyCode::Key_Apps: + return "LaunchApp1"_string; // 3.7. Legacy, Non-Standard and Special Keys, https://www.w3.org/TR/uievents-code/#key-legacy case KeyCode::Key_Invalid: