Kernel: Rework the whole input system
We now use Device abstraction that will allow us to provide devices to userspace through /dev. Currently Shell reads from first and only device (it being PS/2 Keyboard).
This commit is contained in:
99
kernel/include/kernel/Input/KeyEvent.h
Normal file
99
kernel/include/kernel/Input/KeyEvent.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel::Input
|
||||
{
|
||||
|
||||
enum class Key
|
||||
{
|
||||
Invalid, None,
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
A_Ring, A_Umlaut, O_Umlaut,
|
||||
_0, _1, _2, _3, _4, _5, _6, _7, _8, _9,
|
||||
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||
Insert, PrintScreen, Delete, Home, End, PageUp, PageDown, Enter, Space,
|
||||
ExclamationMark, DoubleQuote, Hashtag, Currency, Percent, Ampersand, Slash, Section, Half,
|
||||
OpenBracet, CloseBracet, OpenBrace, CloseBrace, OpenCurlyBrace, CloseCurlyBrace,
|
||||
Equals, QuestionMark, Plus, BackSlash, Acute, BackTick, TwoDots, Backspace, AtSign, Pound, Dollar, Euro,
|
||||
Escape, Tab, CapsLock, LeftShift, LeftCtrl, Super, Alt, AltGr, RightCtrl, RightShift,
|
||||
SingleQuote, Asterix, Caret, Tilde, ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
|
||||
Comma, Semicolon, Period, Colon, Hyphen, Underscore, NumLock, ScrollLock, LessThan, GreaterThan, Pipe,
|
||||
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
|
||||
NumpadPlus, NumpadMinus, NumpadMultiply, NumpadDivide, NumpadEnter, NumpadDecimal,
|
||||
VolumeMute, VolumeUp, VolumeDown, Calculator, MediaPlayPause, MediaStop, MediaPrevious, MediaNext,
|
||||
Count,
|
||||
};
|
||||
|
||||
struct KeyEvent
|
||||
{
|
||||
enum class Modifier : uint8_t
|
||||
{
|
||||
Shift = (1 << 0),
|
||||
Ctrl = (1 << 1),
|
||||
Alt = (1 << 2),
|
||||
AltGr = (1 << 3),
|
||||
CapsLock = (1 << 4),
|
||||
NumLock = (1 << 5),
|
||||
ScrollLock = (1 << 6),
|
||||
Released = (1 << 7),
|
||||
};
|
||||
|
||||
bool shift() const { return modifier & (uint8_t)Modifier::Shift; }
|
||||
bool ctrl() const { return modifier & (uint8_t)Modifier::Ctrl; }
|
||||
bool alt() const { return modifier & (uint8_t)Modifier::Alt; }
|
||||
bool altgr() const { return modifier & (uint8_t)Modifier::AltGr; }
|
||||
bool caps_lock() const { return modifier & (uint8_t)Modifier::CapsLock; }
|
||||
bool num_lock() const { return modifier & (uint8_t)Modifier::NumLock; }
|
||||
bool scroll_lock() const { return modifier & (uint8_t)Modifier::ScrollLock; }
|
||||
bool released() const { return modifier & (uint8_t)Modifier::Released; }
|
||||
bool pressed() const { return !released(); }
|
||||
|
||||
uint8_t modifier;
|
||||
Key key;
|
||||
};
|
||||
|
||||
inline const char* key_event_to_utf8(KeyEvent event)
|
||||
{
|
||||
static constexpr const char* utf8_lower[] = {
|
||||
nullptr, nullptr,
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||
"å", "ä", "ö",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
|
||||
"!", "\"", "#", "¤", "%", "&", "/", "§", "½",
|
||||
"(", ")", "[", "]", "{", "}",
|
||||
"=", "?", "+", "\\", "´", "`", "¨", nullptr, "@", "£", "$", "€",
|
||||
nullptr, "\t", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
"'", "*", "^", "~", nullptr, nullptr, nullptr, nullptr,
|
||||
",", ";", ".", ":", "-", "_", nullptr, nullptr, "<", ">", "|",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"+", "-", "*", "/", nullptr, ",",
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
};
|
||||
static_assert((size_t)Key::Count == sizeof(utf8_lower) / sizeof(*utf8_lower));
|
||||
|
||||
static constexpr const char* utf8_upper[] = {
|
||||
nullptr, nullptr,
|
||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
||||
"Å", "Ä", "Ö",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, " ",
|
||||
"!", "\"", "#", "¤", "%", "&", "/", "§", "½",
|
||||
"(", ")", "[", "]", "{", "}",
|
||||
"=", "?", "+", "\\", "´", "`", "¨", nullptr, "@", "£", "$", "€",
|
||||
nullptr, "\t", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
"'", "*", "^", "~", nullptr, nullptr, nullptr, nullptr,
|
||||
",", ";", ".", ":", "-", "_", nullptr, nullptr, "<", ">", "|",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"+", "-", "*", "/", nullptr, ",",
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
};
|
||||
static_assert((size_t)Key::Count == sizeof(utf8_upper) / sizeof(*utf8_lower));
|
||||
|
||||
return (event.shift() ^ event.caps_lock()) ? utf8_upper[(uint8_t)event.key] : utf8_lower[(uint8_t)event.key];
|
||||
}
|
||||
|
||||
}
|
||||
38
kernel/include/kernel/Input/PS2Controller.h
Normal file
38
kernel/include/kernel/Input/PS2Controller.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Device.h>
|
||||
|
||||
namespace Kernel::Input
|
||||
{
|
||||
|
||||
class PS2Device : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
virtual ~PS2Device() {}
|
||||
virtual void on_byte(uint8_t) = 0;
|
||||
};
|
||||
|
||||
class PS2Controller
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<void> initialize();
|
||||
static PS2Controller& get();
|
||||
|
||||
void send_byte(const PS2Device*, uint8_t);
|
||||
|
||||
private:
|
||||
PS2Controller() = default;
|
||||
BAN::ErrorOr<void> initialize_impl();
|
||||
BAN::ErrorOr<void> initialize_device(uint8_t);
|
||||
|
||||
BAN::ErrorOr<void> reset_device(uint8_t);
|
||||
BAN::ErrorOr<void> set_scanning(uint8_t, bool);
|
||||
|
||||
static void device0_irq();
|
||||
static void device1_irq();
|
||||
|
||||
private:
|
||||
PS2Device* m_devices[2] { nullptr, nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
64
kernel/include/kernel/Input/PS2Keyboard.h
Normal file
64
kernel/include/kernel/Input/PS2Keyboard.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/CircularQueue.h>
|
||||
#include <kernel/Input/KeyEvent.h>
|
||||
#include <kernel/Input/PS2Controller.h>
|
||||
#include <kernel/Input/PS2Keymap.h>
|
||||
|
||||
namespace Kernel::Input
|
||||
{
|
||||
|
||||
class PS2Keyboard final : public PS2Device
|
||||
{
|
||||
private:
|
||||
enum Command : uint8_t
|
||||
{
|
||||
SET_LEDS = 0xED,
|
||||
SCANCODE = 0xF0,
|
||||
ENABLE_SCANNING = 0xF4,
|
||||
DISABLE_SCANNING = 0xF5,
|
||||
};
|
||||
|
||||
enum class State
|
||||
{
|
||||
Normal,
|
||||
WaitingAck,
|
||||
};
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<PS2Keyboard*> create(PS2Controller&);
|
||||
|
||||
virtual void on_byte(uint8_t) override;
|
||||
virtual void update() override;
|
||||
|
||||
virtual BAN::ErrorOr<void> read(BAN::Span<uint8_t>) override;
|
||||
|
||||
private:
|
||||
PS2Keyboard(PS2Controller& controller)
|
||||
: m_controller(controller)
|
||||
{}
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
void append_command_queue(uint8_t);
|
||||
void append_command_queue(uint8_t, uint8_t);
|
||||
|
||||
void buffer_has_key();
|
||||
|
||||
void update_leds();
|
||||
|
||||
private:
|
||||
PS2Controller& m_controller;
|
||||
uint8_t m_byte_buffer[10];
|
||||
uint8_t m_byte_index { 0 };
|
||||
|
||||
uint8_t m_modifiers { 0 };
|
||||
|
||||
BAN::CircularQueue<KeyEvent, 10> m_event_queue;
|
||||
BAN::CircularQueue<uint8_t, 10> m_command_queue;
|
||||
|
||||
PS2Keymap m_keymap;
|
||||
|
||||
State m_state { State::Normal };
|
||||
};
|
||||
|
||||
}
|
||||
23
kernel/include/kernel/Input/PS2Keymap.h
Normal file
23
kernel/include/kernel/Input/PS2Keymap.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/Input/KeyEvent.h>
|
||||
|
||||
namespace Kernel::Input
|
||||
{
|
||||
|
||||
class PS2Keymap
|
||||
{
|
||||
public:
|
||||
PS2Keymap();
|
||||
|
||||
Key key_for_scancode_and_modifiers(uint32_t, uint8_t);
|
||||
|
||||
private:
|
||||
BAN::Vector<Key> m_normal_keymap;
|
||||
BAN::Vector<Key> m_shift_keymap;
|
||||
BAN::Vector<Key> m_altgr_keymap;
|
||||
BAN::Vector<Key> m_extended_keymap;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user