1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 14:37:45 +00:00

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.
This commit is contained in:
Andreas Kling 2022-03-07 16:34:14 +01:00
parent ff60e8ffc6
commit baa6ff5649
5 changed files with 52 additions and 36 deletions

View file

@ -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')

View file

@ -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;