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:
Bananymous
2023-03-29 03:05:16 +03:00
parent e5c3486826
commit fa8e921ee8
16 changed files with 1339 additions and 775 deletions

View File

@@ -21,6 +21,65 @@ namespace Kernel
uint32_t creator_revision;
} __attribute__((packed));
struct FADT : public SDTHeader
{
uint32_t firmware_ctrl;
uint32_t dsdt;
uint8_t __reserved;
uint8_t preferred_pm_profile;
uint16_t sci_int;
uint32_t smi_cmd;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_cnt;
uint32_t pm1a_evt_blk;
uint32_t pm1b_evt_blk;
uint32_t pm1a_cnt_blk;
uint32_t pm1b_cnt_blk;
uint32_t pm2_cnt_blk;
uint32_t pm_tmr_blk;
uint32_t gpe0_blk;
uint32_t gpe1_blk;
uint8_t pm1_evt_len;
uint8_t pm1_cnt_len;
uint8_t pm2_cnt_len;
uint8_t pm_tmr_len;
uint8_t gpe0_blk_len;
uint8_t gpe1_blk_len;
uint8_t gpe1_base;
uint8_t cst_cnt;
uint16_t p_lvl2_lat;
uint16_t p_lvl3_lat;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alrm;
uint8_t mon_alrm;
uint8_t century;
uint16_t iapc_boot_arch;
uint8_t __reserved2;
uint32_t flags;
uint8_t reset_reg[12];
uint8_t reset_value;
uint16_t arm_boot_arch;
uint8_t fadt_minor_version;
uint64_t x_firmware_version;
uint64_t x_dsdt;
uint8_t x_pm1a_evt_blk[12];
uint8_t x_pm1b_evt_blk[12];
uint8_t x_pm1a_cnt_blk[12];
uint8_t x_pm1b_cnt_blk[12];
uint8_t x_pm2_cnt_blk[12];
uint8_t x_pm_tmr_blk[12];
uint8_t x_gpe0_blk[12];
uint8_t x_gpe1_blk[12];
uint8_t sleep_control_reg[12];
uint8_t sleep_status_reg[12];
uint64_t hypervison_vendor_identity;
} __attribute__((packed));
public:
static BAN::ErrorOr<void> initialize();
static ACPI& get();

View File

@@ -0,0 +1,59 @@
#pragma once
#include <BAN/Vector.h>
#include <kernel/SpinLock.h>
namespace Kernel
{
class Device
{
public:
enum class Type
{
BlockDevice,
CharacterDevice,
DeviceController
};
virtual ~Device() {}
virtual Type type() const = 0;
virtual void update() {}
};
class BlockDevice : public Device
{
public:
virtual Type type() const override { return Type::BlockDevice; }
};
class CharacterDevice : public Device
{
public:
virtual Type type() const override { return Type::CharacterDevice; }
virtual BAN::ErrorOr<void> read(BAN::Span<uint8_t>);
};
class DeviceManager
{
BAN_NON_COPYABLE(DeviceManager);
BAN_NON_MOVABLE(DeviceManager);
public:
static DeviceManager& get();
void update();
void add_device(Device*);
BAN::Vector<Device*> devices() { return m_devices; }
private:
DeviceManager() = default;
private:
SpinLock m_lock;
BAN::Vector<Device*> m_devices;
};
}

View File

@@ -1,67 +0,0 @@
#pragma once
#include <BAN/Function.h>
#include <stdint.h>
namespace Input
{
enum class Key : uint8_t
{
INVALID, None,
_0, _1, _2, _3, _4, _5, _6, _7, _8, _9,
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_Dot, A_Dots, O_Dots,
Comma, Colon, Period, Semicolon, Hyphen, Underscore, SingleQuote, Asterix, Caret, Tilde,
ExclamationMark, QuestionMark, DoubleQuote, Hashtag, Percent, Ampersand, Slash, BackSlash, Plus, Equals,
OpenParen, CloseParen, OpenBracket, CloseBracket, OpenBrace, CloseBrace,
Dollar, Pound, Euro, Currency, Enter, Space, Tab, Backspace, LessThan, MoreThan, Tick, BackTick, Section, Half, At, Pipe,
End, Home, Insert, Delete, Super, PageUp, PageDown, PrintScreen, Left, Right, Up, Down,
LeftShift, RightShift, CapsLock, LeftCtrl, RightCtrl, LeftAlt, RightAlt, NumLock, ScrollLock, Escape,
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
NumpadSep, NumpadPlus, NumpadMult, NumpadDiv, NumpadMinus, NumpadEnter,
Mute, VolumeDown, VolumeUp, Calculator, PlayPause, Stop, PreviousTrack, NextTrack,
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
Count
};
struct KeyEvent
{
Key key;
uint8_t modifiers;
bool pressed;
};
enum class MouseButton
{
Left, Right, Middle,
};
struct MouseButtonEvent
{
MouseButton button;
};
struct MouseMoveEvent
{
int16_t dx;
int16_t dy;
};
bool initialize();
void update();
bool is_key_down(Key);
void register_key_event_callback(const BAN::Function<void(KeyEvent)>&);
void register_mouse_button_event_callback(const BAN::Function<void(MouseButtonEvent)>&);
void register_mouse_move_event_callback(const BAN::Function<void(MouseMoveEvent)>&);
const char* key_event_to_utf8(KeyEvent);
}

View 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];
}
}

View 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 };
};
}

View 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 };
};
}

View 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;
};
}

View File

@@ -2,7 +2,7 @@
#include <BAN/String.h>
#include <BAN/Vector.h>
#include <kernel/Input.h>
#include <kernel/Input/KeyEvent.h>
#include <kernel/TTY.h>
namespace Kernel