summaryrefslogtreecommitdiff
path: root/Kernel/Devices/HID/KeyboardDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Devices/HID/KeyboardDevice.cpp')
-rw-r--r--Kernel/Devices/HID/KeyboardDevice.cpp100
1 files changed, 75 insertions, 25 deletions
diff --git a/Kernel/Devices/HID/KeyboardDevice.cpp b/Kernel/Devices/HID/KeyboardDevice.cpp
index e71dc7143a..7daf6335b3 100644
--- a/Kernel/Devices/HID/KeyboardDevice.cpp
+++ b/Kernel/Devices/HID/KeyboardDevice.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
+ * Copyright (c) 2021-2023, Liav A. <liavalb@hotmail.co.il>
* Copyright (c) 2021, Edwin Hoksberg <mail@edwinhoksberg.nl>
*
* SPDX-License-Identifier: BSD-2-Clause
@@ -9,9 +9,14 @@
#include <AK/Assertions.h>
#include <AK/Types.h>
#include <Kernel/API/Ioctl.h>
+#include <Kernel/API/KeyCode.h>
+#include <Kernel/Devices/DeviceManagement.h>
#include <Kernel/Devices/HID/KeyboardDevice.h>
+#include <Kernel/Scheduler.h>
#include <Kernel/Sections.h>
+#include <Kernel/TTY/ConsoleManagement.h>
#include <Kernel/TTY/VirtualConsole.h>
+#include <Kernel/WorkQueue.h>
namespace Kernel {
@@ -209,16 +214,58 @@ static constexpr KeyCode shifted_key_map[0x100] = {
Key_Menu,
};
-void KeyboardDevice::key_state_changed(u8 scan_code, bool pressed)
+void KeyboardDevice::handle_scan_code_input_event(ScanCodeEvent event)
{
- KeyCode key = (m_modifiers & Mod_Shift) ? shifted_key_map[scan_code] : unshifted_key_map[scan_code];
+ 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;
+ }
+
+ KeyCode key = (m_modifiers & Mod_Shift) ? shifted_key_map[event.scan_code_value] : unshifted_key_map[event.scan_code_value];
+
+ if ((m_modifiers == (Mod_Alt | Mod_Shift) || m_modifiers == (Mod_Ctrl | Mod_Alt | Mod_Shift)) && 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 (key == Key_NumLock && pressed)
+ if ((m_modifiers & Mod_Alt) != 0 && key >= Key_1 && key <= Key_1 + ConsoleManagement::s_max_virtual_consoles + 1) {
+ // 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 && !m_has_e0_prefix) {
- if (scan_code >= 0x47 && scan_code <= 0x53) {
- u8 index = scan_code - 0x47;
+ 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];
@@ -228,48 +275,51 @@ void KeyboardDevice::key_state_changed(u8 scan_code, bool pressed)
}
}
- Event event;
- event.key = key;
- event.scancode = m_has_e0_prefix ? 0xe000 + scan_code : scan_code;
- event.flags = m_modifiers;
- event.e0_prefix = m_has_e0_prefix;
- event.caps_lock_on = m_caps_lock_on;
- event.code_point = HIDManagement::the().get_char_from_character_map(event);
+ Event queued_event;
+ queued_event.key = key;
+ 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);
- // If using a non-QWERTY layout, event.key needs to be updated to be the same as event.code_point
- KeyCode mapped_key = code_point_to_key_code(event.code_point);
+ // 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) {
- event.key = mapped_key;
+ queued_event.key = mapped_key;
key = mapped_key;
}
- if (!g_caps_lock_remapped_to_ctrl && key == Key_CapsLock && pressed)
+ if (!g_caps_lock_remapped_to_ctrl && key == Key_CapsLock && event.pressed)
m_caps_lock_on = !m_caps_lock_on;
if (g_caps_lock_remapped_to_ctrl && key == Key_CapsLock) {
- m_caps_lock_to_ctrl_pressed = pressed;
+ m_caps_lock_to_ctrl_pressed = event.pressed;
update_modifier(Mod_Ctrl, m_caps_lock_to_ctrl_pressed);
}
- if (pressed)
- event.flags |= Is_Press;
+ if (event.pressed)
+ queued_event.flags |= Is_Press;
{
SpinlockLocker locker(HIDManagement::the().m_client_lock);
if (HIDManagement::the().m_client)
- HIDManagement::the().m_client->on_key_pressed(event);
+ HIDManagement::the().m_client->on_key_pressed(queued_event);
}
{
SpinlockLocker lock(m_queue_lock);
- m_queue.enqueue(event);
+ m_queue.enqueue(queued_event);
}
- m_has_e0_prefix = false;
-
evaluate_block_conditions();
}
+ErrorOr<NonnullRefPtr<KeyboardDevice>> KeyboardDevice::try_to_initialize()
+{
+ return *TRY(DeviceManagement::try_create_device<KeyboardDevice>());
+}
+
// FIXME: UNMAP_AFTER_INIT is fine for now, but for hot-pluggable devices
// like USB keyboards, we need to remove this
UNMAP_AFTER_INIT KeyboardDevice::KeyboardDevice()