summaryrefslogtreecommitdiff
path: root/Kernel/Devices/HID
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-03-07 16:34:14 +0100
committerAndreas Kling <kling@serenityos.org>2022-03-07 16:35:23 +0100
commitbaa6ff56497e583d706a2999134f6468f2f89b29 (patch)
tree6007d6fdfd7da60062037b063e44fee47b2179d3 /Kernel/Devices/HID
parentff60e8ffc6e940bcf71cc1a5a697d1b2c25c6caa (diff)
downloadserenity-baa6ff56497e583d706a2999134f6468f2f89b29.zip
Kernel: Wrap HIDManagement keymap data in SpinlockProtected
This serializes access to the current keymap data everywhere in the kernel, allowing to mark sys$setkeymap() as not needing the big lock.
Diffstat (limited to 'Kernel/Devices/HID')
-rw-r--r--Kernel/Devices/HID/HIDManagement.cpp40
-rw-r--r--Kernel/Devices/HID/HIDManagement.h14
2 files changed, 34 insertions, 20 deletions
diff --git a/Kernel/Devices/HID/HIDManagement.cpp b/Kernel/Devices/HID/HIDManagement.cpp
index 1d45324d0e..084f0befc6 100644
--- a/Kernel/Devices/HID/HIDManagement.cpp
+++ b/Kernel/Devices/HID/HIDManagement.cpp
@@ -86,17 +86,23 @@ size_t HIDManagement::generate_minor_device_number_for_keyboard()
return m_keyboard_minor_number++;
}
+UNMAP_AFTER_INIT HIDManagement::KeymapData::KeymapData()
+ : character_map_name(KString::must_create("en-us"sv))
+ , character_map(DEFAULT_CHARACTER_MAP)
+{
+}
+
UNMAP_AFTER_INIT HIDManagement::HIDManagement()
- : m_character_map_name(KString::must_create("en-us"sv))
- , m_character_map(DEFAULT_CHARACTER_MAP)
{
}
void HIDManagement::set_maps(NonnullOwnPtr<KString> character_map_name, Keyboard::CharacterMapData const& character_map_data)
{
- m_character_map_name = move(character_map_name);
- m_character_map = character_map_data;
- dbgln("New Character map '{}' passed in by client.", m_character_map_name);
+ m_keymap_data.with([&](auto& keymap_data) {
+ keymap_data.character_map_name = move(character_map_name);
+ keymap_data.character_map = character_map_data;
+ dbgln("New Character map '{}' passed in by client.", keymap_data.character_map_name);
+ });
}
UNMAP_AFTER_INIT ErrorOr<void> HIDManagement::enumerate()
@@ -150,17 +156,19 @@ u32 HIDManagement::get_char_from_character_map(KeyEvent event) const
auto index = event.scancode & 0xFF; // Index is last byte of scan code.
auto caps_lock_on = event.caps_lock_on;
- u32 code_point;
- if (modifiers & Mod_Alt)
- code_point = m_character_map.alt_map[index];
- else if ((modifiers & Mod_Shift) && (modifiers & Mod_AltGr))
- code_point = m_character_map.shift_altgr_map[index];
- else if (modifiers & Mod_Shift)
- code_point = m_character_map.shift_map[index];
- else if (modifiers & Mod_AltGr)
- code_point = m_character_map.altgr_map[index];
- else
- code_point = m_character_map.map[index];
+ u32 code_point = 0;
+ m_keymap_data.with([&](auto& keymap_data) {
+ if (modifiers & Mod_Alt)
+ code_point = keymap_data.character_map.alt_map[index];
+ else if ((modifiers & Mod_Shift) && (modifiers & Mod_AltGr))
+ code_point = keymap_data.character_map.shift_altgr_map[index];
+ else if (modifiers & Mod_Shift)
+ code_point = keymap_data.character_map.shift_map[index];
+ else if (modifiers & Mod_AltGr)
+ code_point = keymap_data.character_map.altgr_map[index];
+ else
+ code_point = keymap_data.character_map.map[index];
+ });
if (caps_lock_on && (modifiers == 0 || modifiers == Mod_Shift)) {
if (code_point >= 'a' && code_point <= 'z')
diff --git a/Kernel/Devices/HID/HIDManagement.h b/Kernel/Devices/HID/HIDManagement.h
index 5201fb9891..691fe3d476 100644
--- a/Kernel/Devices/HID/HIDManagement.h
+++ b/Kernel/Devices/HID/HIDManagement.h
@@ -16,6 +16,7 @@
#include <Kernel/API/KeyCode.h>
#include <Kernel/API/MousePacket.h>
#include <Kernel/Locking/Spinlock.h>
+#include <Kernel/Locking/SpinlockProtected.h>
#include <Kernel/UnixTypes.h>
#include <LibKeyboard/CharacterMapData.h>
@@ -39,8 +40,14 @@ public:
ErrorOr<void> enumerate();
- StringView keymap_name() const { return m_character_map_name->view(); }
- Keyboard::CharacterMapData const& character_map() const { return m_character_map; }
+ struct KeymapData {
+ KeymapData();
+ NonnullOwnPtr<KString> character_map_name;
+ Keyboard::CharacterMapData character_map;
+ };
+
+ SpinlockProtected<KeymapData>& keymap_data() { return m_keymap_data; }
+
u32 get_char_from_character_map(KeyEvent) const;
void set_client(KeyboardClient* client) { m_client = client; }
@@ -50,10 +57,9 @@ private:
size_t generate_minor_device_number_for_mouse();
size_t generate_minor_device_number_for_keyboard();
+ SpinlockProtected<KeymapData> m_keymap_data;
size_t m_mouse_minor_number { 0 };
size_t m_keyboard_minor_number { 0 };
- NonnullOwnPtr<KString> m_character_map_name;
- Keyboard::CharacterMapData m_character_map;
KeyboardClient* m_client { nullptr };
RefPtr<I8042Controller> m_i8042_controller;
NonnullRefPtrVector<HIDDevice> m_hid_devices;