Compare commits

..

10 Commits

Author SHA1 Message Date
Bananymous 51214ea1bf Kernel: Add load_keymap syscall and load Finnish keymap in init 2024-01-10 14:46:29 +02:00
Bananymous 8f89519bcf Kernel: Keymaps can now be loaded from files 2024-01-10 14:43:19 +02:00
Bananymous e6d42e5c45 Kernel: Add timeout for device commands on PS/2 devices 2024-01-10 12:51:24 +02:00
Bananymous 961ab9768a Kernel: KeyEvent is now well known keycode
Keycodes are easier to handle as you need only one keyboard layout
for keycodes. Otherwise you would need to implement keyboard layout
for every keyboard driver in every language.
2024-01-10 12:51:24 +02:00
Bananymous e4f48cbc73 Kernel: Move PS/2 command queue to controller instead of device 2024-01-09 20:00:19 +02:00
Bananymous e8f853a197 Kernel: After device updates, reschedule instead of sleeping 2024-01-09 11:21:00 +02:00
Bananymous d760239748 Kernel: Do a big rewrite of PS/2 code
Command sending+response reading is now synchronized. This allows
bochs to properly initialize both mouse and keyboard simultaneously.

Also status register is checked EVERY time read/write to other IO
ports is performed.
2024-01-08 10:50:55 +02:00
Bananymous 2fec718590 Bootloader: cleanup code 2024-01-08 10:50:55 +02:00
Bananymous f0cf54e194 Kernel: Reads from PS/2 keyboard and mouse can be terminated 2024-01-05 12:13:44 +02:00
Bananymous 41ae05dd6e Kernel: Update block_or_eintr API to return ErrorOr<> 2024-01-05 12:13:11 +02:00
32 changed files with 1405 additions and 773 deletions

Binary file not shown.

View File

@ -13,12 +13,10 @@
.global stage1_main
stage1_main:
# setup segments
movw $0, %ax
# setup segments and stack
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
# setup stack
movw %ax, %ss
movl $0x7C00, %esp
@ -53,6 +51,8 @@ stage2_main:
movw $hello_msg, %si
call puts; call print_newline
lgdt gdtr
call enter_unreal_mode
movw $unreal_enter_msg, %si
call puts; call print_newline
@ -86,32 +86,32 @@ stage2_main:
cli
# kernel entry point
movl %eax, %ecx
# setup kernel parameters
movl $0xD3C60CFF, %eax
movl $banan_boot_info, %ebx
# setup protected mode
movl %cr0, %ebx
orb $1, %bl
movl %ebx, %cr0
movl %cr0, %edx
orb $1, %dl
movl %edx, %cr0
# jump to kernel in protected mode
# jump to protected mode
ljmpl $0x18, $protected_mode
.code32
protected_mode:
movw $0x10, %bx
movw %bx, %ds
movw %bx, %es
movw %bx, %fs
movw %bx, %gs
movw %bx, %ss
movl %eax, %ecx
movl $0xD3C60CFF, %eax
movl $banan_boot_info, %ebx
xorl %edx, %edx
xorl %esi, %esi
xorl %edi, %edi
# setup protected mode segments
movw $0x10, %dx
movw %dx, %ds
movw %dx, %es
movw %dx, %fs
movw %dx, %gs
movw %dx, %ss
# jump to kernel entry
jmp *%ecx
@ -120,8 +120,6 @@ enter_unreal_mode:
cli
pushw %ds
lgdt gdtr
movl %cr0, %eax
orb $1, %al
movl %eax, %cr0
@ -152,9 +150,9 @@ start_kernel_load_msg:
gdt:
.quad 0x0000000000000000
.quad 0x00009A000000FFFF
.quad 0x00CF92000000FFFF
.quad 0x00CF9A000000FFFF
.quad 0x008F9A000000FFFF # 16-bit code
.quad 0x00CF92000000FFFF # 32-bit data
.quad 0x00CF9A000000FFFF # 32-bit code
gdtr:
.short . - gdt - 1
.quad gdt

View File

@ -32,6 +32,8 @@ set(KERNEL_SOURCES
kernel/FS/TmpFS/FileSystem.cpp
kernel/FS/TmpFS/Inode.cpp
kernel/FS/VirtualFileSystem.cpp
kernel/Input/KeyboardLayout.cpp
kernel/Input/KeyEvent.cpp
kernel/Input/PS2/Controller.cpp
kernel/Input/PS2/Device.cpp
kernel/Input/PS2/Keyboard.cpp

View File

@ -11,10 +11,6 @@ namespace Kernel
ACPI_NoRootSDT,
ACPI_NoSuchHeader,
ACPI_RootInvalid,
PS2_Timeout,
PS2_SelfTest,
PS2_Reset,
PS2_UnsupportedDevice,
Ext2_Invalid,
Ext2_Corrupted,
Ext2_NoInodes,

View File

@ -5,6 +5,47 @@
namespace Kernel::Input
{
/*
Key Code:
bits 4:0 column (from left)
bits 7:5 row (from top)
*/
#define BANAN_CONSTEVAL_STATIC_ASSERT(cond) do { int dummy = 1 / (cond); } while (false)
consteval uint8_t keycode_function(uint8_t index)
{
BANAN_CONSTEVAL_STATIC_ASSERT(index <= 0b11111);
return index;
}
consteval uint8_t keycode_normal(uint8_t row, uint8_t col)
{
BANAN_CONSTEVAL_STATIC_ASSERT(row <= 0b111 - 1);
BANAN_CONSTEVAL_STATIC_ASSERT(col < 0b11111 - 8);
return ((row + 1) << 5) | col;
}
consteval uint8_t keycode_numpad(uint8_t row, uint8_t col)
{
BANAN_CONSTEVAL_STATIC_ASSERT(row <= 0b111 - 1);
BANAN_CONSTEVAL_STATIC_ASSERT(col <= 8);
return ((row + 1) << 5) | (col + 0b11111 - 8);
}
enum ModifierKeycode
{
CapsLock = keycode_normal(2, 0),
NumLock = keycode_numpad(0, 0),
ScrollLock = keycode_function(20),
LShift = keycode_normal(3, 0),
RShift = keycode_normal(3, 12),
LCtrl = keycode_normal(4, 0),
RCtrl = keycode_normal(4, 5),
LAlt = keycode_normal(4, 2),
RAlt = keycode_normal(4, 4),
};
enum class Key
{
Invalid, None,
@ -14,9 +55,9 @@ namespace Kernel::Input
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,
OpenParenthesis, CloseParenthesis, OpenSquareBracket, CloseSquareBracket, OpenCurlyBracket, CloseCurlyBracket,
Equals, QuestionMark, Plus, BackSlash, Acute, BackTick, TwoDots, Cedilla, Backspace, AtSign, Pound, Dollar, Euro,
Escape, Tab, CapsLock, LeftShift, LeftCtrl, Super, LeftAlt, RightAlt, AltGr = RightAlt, 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,
@ -27,73 +68,44 @@ namespace Kernel::Input
struct KeyEvent
{
enum class Modifier : uint8_t
enum Modifier : uint16_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),
LShift = (1 << 0),
RShift = (1 << 1),
LCtrl = (1 << 2),
RCtrl = (1 << 3),
LAlt = (1 << 4),
RAlt = (1 << 5),
CapsLock = (1 << 6),
NumLock = (1 << 7),
ScrollLock = (1 << 8),
Pressed = (1 << 9),
};
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(); }
bool lshift() const { return modifier & Modifier::LShift; }
bool rshift() const { return modifier & Modifier::RShift; }
bool shift() const { return lshift() || rshift(); }
uint8_t modifier;
Key key;
bool lctrl() const { return modifier & Modifier::LCtrl; }
bool rctrl() const { return modifier & Modifier::RCtrl; }
bool ctrl() const { return lctrl() || rctrl(); }
bool lalt() const { return modifier & Modifier::LAlt; }
bool ralt() const { return modifier & Modifier::RAlt; }
bool alt() const { return lalt() || ralt(); }
bool caps_lock() const { return modifier & Modifier::CapsLock; }
bool num_lock() const { return modifier & Modifier::NumLock; }
bool scroll_lock() const { return modifier & Modifier::ScrollLock; }
bool pressed() const { return modifier & Modifier::Pressed; }
bool released() const { return !pressed(); }
uint16_t modifier;
uint8_t keycode;
};
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];
}
Key key_event_to_key(KeyEvent);
const char* key_to_utf8(Key key, uint16_t modifier);
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/UniqPtr.h>
#include <kernel/Input/KeyEvent.h>
namespace Kernel::Input
{
class KeyboardLayout
{
public:
static BAN::ErrorOr<void> initialize();
static KeyboardLayout& get();
Key get_key_from_event(KeyEvent);
BAN::ErrorOr<void> load_from_file(BAN::StringView path);
private:
KeyboardLayout();
private:
BAN::Array<Key, 0xFF> m_keycode_to_key_normal;
BAN::Array<Key, 0xFF> m_keycode_to_key_shift;
BAN::Array<Key, 0xFF> m_keycode_to_key_altgr;
friend class BAN::UniqPtr<KeyboardLayout>;
};
}

View File

@ -14,8 +14,8 @@ namespace Kernel::Input::PS2
enum Status : uint8_t
{
OUTPUT_FULL = (1 << 0),
INPUT_FULL = (1 << 1),
OUTPUT_STATUS = (1 << 0),
INPUT_STATUS = (1 << 1),
SYSTEM = (1 << 2),
DEVICE_OR_CONTROLLER = (1 << 3),
TIMEOUT_ERROR = (1 << 6),
@ -78,13 +78,6 @@ namespace Kernel::Input::PS2
KEY_ERROR_OR_BUFFER_OVERRUN2 = 0xFF,
};
enum KBScancode : uint8_t
{
SET_SCANCODE_SET1 = 1,
SET_SCANCODE_SET2 = 2,
SET_SCANCODE_SET3 = 3,
};
enum KBLeds : uint8_t
{
SCROLL_LOCK = (1 << 0),

View File

@ -1,8 +1,11 @@
#pragma once
#include <BAN/CircularQueue.h>
#include <BAN/UniqPtr.h>
#include <kernel/Device/Device.h>
#include <kernel/Input/PS2/Config.h>
#include <kernel/InterruptController.h>
#include <kernel/SpinLock.h>
namespace Kernel::Input
{
@ -15,18 +18,50 @@ namespace Kernel::Input
static BAN::ErrorOr<void> initialize();
static PS2Controller& get();
void send_byte(const PS2Device*, uint8_t);
bool append_command_queue(PS2Device*, uint8_t command, uint8_t response_size);
bool append_command_queue(PS2Device*, uint8_t command, uint8_t data, uint8_t response_size);
void update_command_queue();
// Returns true, if byte is used as command, if returns false, byte is meant to device
bool handle_command_byte(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);
BAN::ErrorOr<uint8_t> read_byte();
BAN::ErrorOr<void> send_byte(uint16_t port, uint8_t byte);
BAN::ErrorOr<void> send_command(PS2::Command command);
BAN::ErrorOr<void> send_command(PS2::Command command, uint8_t data);
BAN::ErrorOr<void> device_send_byte(uint8_t device_index, uint8_t byte);
BAN::ErrorOr<void> device_send_byte_and_wait_ack(uint8_t device_index, uint8_t byte);
private:
PS2Device* m_devices[2] { nullptr, nullptr };
struct Command
{
enum class State : uint8_t
{
NotSent,
Sending,
WaitingAck,
WaitingResponse,
};
State state;
uint8_t device_index;
uint8_t out_data[2];
uint8_t out_count;
uint8_t in_count;
uint8_t send_index;
};
private:
BAN::RefPtr<PS2Device> m_devices[2];
RecursiveSpinLock m_lock;
BAN::CircularQueue<Command, 128> m_command_queue;
uint64_t m_command_send_time { 0 };
};
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <kernel/Input/PS2/Controller.h>
#include <kernel/InterruptController.h>
namespace Kernel::Input
{
@ -13,33 +14,23 @@ namespace Kernel::Input
virtual void send_initialize() = 0;
bool append_command_queue(uint8_t command);
bool append_command_queue(uint8_t command, uint8_t data);
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) = 0;
bool append_command_queue(uint8_t command, uint8_t response_size);
bool append_command_queue(uint8_t command, uint8_t data, uint8_t response_size);
virtual void handle_irq() final override;
virtual void handle_byte(uint8_t) = 0;
virtual void handle_device_command_response(uint8_t) = 0;
virtual BAN::StringView name() const final override { return m_name; }
virtual dev_t rdev() const final override { return m_rdev; }
private:
void update();
private:
enum class State
{
Normal,
WaitingAck,
};
virtual void update() final override { m_controller.update_command_queue(); }
private:
const BAN::String m_name;
const dev_t m_rdev;
PS2Controller& m_controller;
State m_state = State::Normal;
BAN::CircularQueue<uint8_t, 10> m_command_queue;
};
}

View File

@ -1,5 +1,7 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/CircularQueue.h>
#include <kernel/Input/KeyEvent.h>
#include <kernel/Input/PS2/Device.h>
#include <kernel/Input/PS2/Keymap.h>
@ -14,15 +16,16 @@ namespace Kernel::Input
enum Command : uint8_t
{
SET_LEDS = 0xED,
SCANCODE = 0xF0
CONFIG_SCANCODE_SET = 0xF0
};
public:
static BAN::ErrorOr<PS2Keyboard*> create(PS2Controller&);
virtual void send_initialize() override;
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override;
virtual void handle_byte(uint8_t) final override;
virtual void handle_device_command_response(uint8_t) final override;
private:
PS2Keyboard(PS2Controller& controller);
@ -30,12 +33,14 @@ namespace Kernel::Input
void update_leds();
private:
uint8_t m_byte_buffer[10];
BAN::Array<uint8_t, 3> m_byte_buffer;
uint8_t m_byte_index { 0 };
uint8_t m_modifiers { 0 };
uint8_t m_scancode_set { 0xFF };
BAN::CircularQueue<KeyEvent, 10> m_event_queue;
uint16_t m_modifiers { 0 };
BAN::CircularQueue<KeyEvent, 50> m_event_queue;
PS2Keymap m_keymap;

View File

@ -1,7 +1,7 @@
#pragma once
#include <BAN/Vector.h>
#include <kernel/Input/KeyEvent.h>
#include <BAN/Array.h>
#include <BAN/Optional.h>
namespace Kernel::Input
{
@ -9,15 +9,18 @@ namespace Kernel::Input
class PS2Keymap
{
public:
PS2Keymap();
void initialize(uint8_t scancode_set);
Key key_for_scancode_and_modifiers(uint32_t, uint8_t);
BAN::Optional<uint8_t> get_keycode(uint8_t scancode, bool extended) const;
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;
void initialize_scancode_set1();
void initialize_scancode_set2();
void initialize_scancode_set3();
private:
BAN::Array<uint8_t, 0xFF> m_scancode_to_keycode_normal;
BAN::Array<uint8_t, 0xFF> m_scancode_to_keycode_extended;
};
}

View File

@ -19,8 +19,9 @@ namespace Kernel::Input
static BAN::ErrorOr<PS2Mouse*> create(PS2Controller&);
virtual void send_initialize() override;
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override {}
virtual void handle_byte(uint8_t) final override;
virtual void handle_device_command_response(uint8_t) final override;
private:
PS2Mouse(PS2Controller& controller);
@ -35,7 +36,7 @@ namespace Kernel::Input
uint8_t m_mouse_id { 0x00 };
uint8_t m_button_mask { 0x00 };
BAN::CircularQueue<MouseEvent, 25> m_event_queue;
BAN::CircularQueue<MouseEvent, 128> m_event_queue;
Semaphore m_semaphore;

View File

@ -146,6 +146,8 @@ namespace Kernel
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
BAN::ErrorOr<long> sys_load_keymap(const char* path);
TTY& tty() { ASSERT(m_controlling_terminal); return *m_controlling_terminal; }
static Process& current() { return Thread::current().process(); }

View File

@ -48,7 +48,7 @@ namespace Kernel
bool add_signal(int signal);
// blocks semaphore and returns either on unblock, eintr or spuriously
[[nodiscard]] bool block_or_eintr(Semaphore&);
BAN::ErrorOr<void> block_or_eintr(Semaphore&);
void set_return_rsp(uintptr_t& rsp) { m_return_rsp = &rsp; }
void set_return_rip(uintptr_t& rip) { m_return_rip = &rip; }

View File

@ -8,10 +8,6 @@ namespace Kernel
"ACPI could not find root SDT header"sv,
"ACPI no such header"sv,
"ACPI root invalid",
"PS/2 device timeout"sv,
"PS/2 controller self test failed"sv,
"PS/2 reset failed"sv,
"PS/2 unsupported device"sv,
"Invalid ext2 filesystem"sv,
"Ext2 filesystem corrupted"sv,
"Ext2 filesystem out of inodes"sv,

View File

@ -6,6 +6,7 @@
#include <kernel/FS/TmpFS/Inode.h>
#include <kernel/LockGuard.h>
#include <kernel/Process.h>
#include <kernel/Scheduler.h>
#include <kernel/Storage/StorageDevice.h>
#include <kernel/Timer/Timer.h>
@ -48,8 +49,7 @@ namespace Kernel
}
);
s_instance->m_device_lock.unlock();
Kernel::SystemTimer::get().sleep(1);
Scheduler::get().reschedule();
}
}, nullptr
);

View File

@ -0,0 +1,57 @@
#include <BAN/Array.h>
#include <kernel/Input/KeyboardLayout.h>
#include <kernel/Input/KeyEvent.h>
namespace Kernel::Input
{
Key key_event_to_key(KeyEvent event)
{
return KeyboardLayout::get().get_key_from_event(event);
}
const char* key_to_utf8(Key key, uint16_t modifier)
{
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));
KeyEvent event { .modifier = modifier, .keycode = 0x00 };
return (event.shift() ^ event.caps_lock()) ? utf8_upper[static_cast<uint8_t>(key)] : utf8_lower[static_cast<uint8_t>(key)];
}
}

View File

@ -0,0 +1,346 @@
#include <BAN/HashMap.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/Input/KeyboardLayout.h>
#include <ctype.h>
namespace Kernel::Input
{
struct StringViewLower
{
BAN::StringView value;
StringViewLower(BAN::StringView sv)
: value(sv)
{ }
bool operator==(const StringViewLower& other) const
{
if (value.size() != other.value.size())
return false;
for (size_t i = 0; i < value.size(); i++)
if (tolower(value[i]) != tolower(other.value[i]))
return false;
return true;
}
};
struct StringViewLowerHash
{
BAN::hash_t operator()(const StringViewLower& value) const
{
constexpr BAN::hash_t FNV_offset_basis = 0x811c9dc5;
constexpr BAN::hash_t FNV_prime = 0x01000193;
BAN::hash_t hash = FNV_offset_basis;
for (size_t i = 0; i < value.value.size(); i++)
{
hash *= FNV_prime;
hash ^= (uint8_t)tolower(value.value[i]);
}
return hash;
}
};
static BAN::UniqPtr<KeyboardLayout> s_instance;
BAN::ErrorOr<void> KeyboardLayout::initialize()
{
ASSERT(!s_instance);
s_instance = TRY(BAN::UniqPtr<KeyboardLayout>::create());
return {};
}
KeyboardLayout& KeyboardLayout::get()
{
ASSERT(s_instance);
return *s_instance;
}
KeyboardLayout::KeyboardLayout()
{
for (auto& key : m_keycode_to_key_normal)
key = Key::None;
for (auto& key : m_keycode_to_key_shift)
key = Key::None;
for (auto& key : m_keycode_to_key_altgr)
key = Key::None;
}
Key KeyboardLayout::get_key_from_event(KeyEvent event)
{
if (event.shift())
return m_keycode_to_key_shift[event.keycode];
if (event.ralt())
return m_keycode_to_key_altgr[event.keycode];
return m_keycode_to_key_normal[event.keycode];
}
static BAN::Optional<uint8_t> parse_keycode(BAN::StringView str)
{
if (str.size() > 3)
return {};
uint16_t keycode = 0;
for (char c : str)
{
if (!isdigit(c))
return {};
keycode = (keycode * 10) + (c - '0');
}
if (keycode >= 0xFF)
return {};
return keycode;
}
static BAN::HashMap<StringViewLower, Key, StringViewLowerHash> s_name_to_key;
static BAN::ErrorOr<void> initialize_name_to_key();
static BAN::Optional<Key> parse_key(BAN::StringView name)
{
if (s_name_to_key.contains(name))
return s_name_to_key[name];
return {};
}
BAN::ErrorOr<void> KeyboardLayout::load_from_file(BAN::StringView path)
{
if (s_name_to_key.empty())
TRY(initialize_name_to_key());
auto inode = TRY(VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, 0)).inode;
BAN::String file_data;
TRY(file_data.resize(inode->size()));
TRY(inode->read(0, { reinterpret_cast<uint8_t*>(file_data.data()), file_data.size() }));
auto new_layout = TRY(BAN::UniqPtr<KeyboardLayout>::create());
auto lines = TRY(file_data.sv().split('\n'));
for (auto line : lines)
{
auto parts = TRY(line.split([](char c) -> bool { return isspace(c); }));
if (parts.empty() || parts.front().front() == '#')
continue;
if (parts.size() == 1)
{
dprintln("Invalid line in keymap '{}'", line);
dprintln(" format: KEYCODE KEY [MODIFIER=KEY]...");
continue;
}
auto keycode = parse_keycode(parts.front());
if (!keycode.has_value())
{
dprintln("Invalid keycode '{}', keycode must number between [0, 0xFF[", parts.front());
continue;
}
auto default_key = parse_key(parts[1]);
if (!default_key.has_value())
{
dprintln("Unrecognized key '{}'", parts[1]);
continue;
}
new_layout->m_keycode_to_key_normal[*keycode] = *default_key;
new_layout->m_keycode_to_key_shift[*keycode] = *default_key;
new_layout->m_keycode_to_key_altgr[*keycode] = *default_key;
for (size_t i = 2; i < parts.size(); i++)
{
auto pair = TRY(parts[i].split('='));
if (pair.size() != 2)
{
dprintln("Invalid modifier format '{}', modifier format: MODIFIRER=KEY", parts[i]);
continue;
}
auto key = parse_key(pair.back());
if (!key.has_value())
{
dprintln("Unrecognized key '{}'", pair.back());
continue;
}
if (pair.front() == "shift"sv)
new_layout->m_keycode_to_key_shift[*keycode] = *key;
else if (pair.front() == "altgr"sv)
new_layout->m_keycode_to_key_altgr[*keycode] = *key;
else
{
dprintln("Unrecognized modifier '{}'", pair.front());
continue;
}
}
}
m_keycode_to_key_normal = new_layout->m_keycode_to_key_normal;
m_keycode_to_key_shift = new_layout->m_keycode_to_key_shift;
m_keycode_to_key_altgr = new_layout->m_keycode_to_key_altgr;
return {};
}
static BAN::ErrorOr<void> initialize_name_to_key()
{
ASSERT(s_name_to_key.empty());
TRY(s_name_to_key.insert("A_Ring"sv, Key::A_Ring));
TRY(s_name_to_key.insert("A_Umlaut"sv, Key::A_Umlaut));
TRY(s_name_to_key.insert("A"sv, Key::A));
TRY(s_name_to_key.insert("Acute"sv, Key::Acute));
TRY(s_name_to_key.insert("AltGr"sv, Key::AltGr));
TRY(s_name_to_key.insert("Ampersand"sv, Key::Ampersand));
TRY(s_name_to_key.insert("ArrowDown"sv, Key::ArrowDown));
TRY(s_name_to_key.insert("ArrowLeft"sv, Key::ArrowLeft));
TRY(s_name_to_key.insert("ArrowRight"sv, Key::ArrowRight));
TRY(s_name_to_key.insert("ArrowUp"sv, Key::ArrowUp));
TRY(s_name_to_key.insert("Asterix"sv, Key::Asterix));
TRY(s_name_to_key.insert("AtSign"sv, Key::AtSign));
TRY(s_name_to_key.insert("B"sv, Key::B));
TRY(s_name_to_key.insert("BackSlash"sv, Key::BackSlash));
TRY(s_name_to_key.insert("Backspace"sv, Key::Backspace));
TRY(s_name_to_key.insert("BackTick"sv, Key::BackTick));
TRY(s_name_to_key.insert("C"sv, Key::C));
TRY(s_name_to_key.insert("Calculator"sv, Key::Calculator));
TRY(s_name_to_key.insert("CapsLock"sv, Key::CapsLock));
TRY(s_name_to_key.insert("Caret"sv, Key::Caret));
TRY(s_name_to_key.insert("Cedilla"sv, Key::Cedilla));
TRY(s_name_to_key.insert("CloseCurlyBracket"sv, Key::CloseCurlyBracket));
TRY(s_name_to_key.insert("CloseParenthesis"sv, Key::CloseParenthesis));
TRY(s_name_to_key.insert("CloseSquareBracket"sv, Key::CloseSquareBracket));
TRY(s_name_to_key.insert("Colon"sv, Key::Colon));
TRY(s_name_to_key.insert("Comma"sv, Key::Comma));
TRY(s_name_to_key.insert("Currency"sv, Key::Currency));
TRY(s_name_to_key.insert("D"sv, Key::D));
TRY(s_name_to_key.insert("Delete"sv, Key::Delete));
TRY(s_name_to_key.insert("Dollar"sv, Key::Dollar));
TRY(s_name_to_key.insert("DoubleQuote"sv, Key::DoubleQuote));
TRY(s_name_to_key.insert("E"sv, Key::E));
TRY(s_name_to_key.insert("End"sv, Key::End));
TRY(s_name_to_key.insert("Enter"sv, Key::Enter));
TRY(s_name_to_key.insert("Equals"sv, Key::Equals));
TRY(s_name_to_key.insert("Escape"sv, Key::Escape));
TRY(s_name_to_key.insert("Euro"sv, Key::Euro));
TRY(s_name_to_key.insert("Exclamation"sv, Key::ExclamationMark));
TRY(s_name_to_key.insert("ExclamationMark"sv, Key::ExclamationMark));
TRY(s_name_to_key.insert("F"sv, Key::F));
TRY(s_name_to_key.insert("F1"sv, Key::F1));
TRY(s_name_to_key.insert("F10"sv, Key::F10));
TRY(s_name_to_key.insert("F11"sv, Key::F11));
TRY(s_name_to_key.insert("F12"sv, Key::F12));
TRY(s_name_to_key.insert("F2"sv, Key::F2));
TRY(s_name_to_key.insert("F3"sv, Key::F3));
TRY(s_name_to_key.insert("F4"sv, Key::F4));
TRY(s_name_to_key.insert("F5"sv, Key::F5));
TRY(s_name_to_key.insert("F6"sv, Key::F6));
TRY(s_name_to_key.insert("F7"sv, Key::F7));
TRY(s_name_to_key.insert("F8"sv, Key::F8));
TRY(s_name_to_key.insert("F9"sv, Key::F9));
TRY(s_name_to_key.insert("G"sv, Key::G));
TRY(s_name_to_key.insert("GreaterThan"sv, Key::GreaterThan));
TRY(s_name_to_key.insert("H"sv, Key::H));
TRY(s_name_to_key.insert("Half"sv, Key::Half));
TRY(s_name_to_key.insert("Hashtag"sv, Key::Hashtag));
TRY(s_name_to_key.insert("Home"sv, Key::Home));
TRY(s_name_to_key.insert("Hyphen"sv, Key::Hyphen));
TRY(s_name_to_key.insert("I"sv, Key::I));
TRY(s_name_to_key.insert("Insert"sv, Key::Insert));
TRY(s_name_to_key.insert("J"sv, Key::J));
TRY(s_name_to_key.insert("K"sv, Key::K));
TRY(s_name_to_key.insert("Key0"sv, Key::_0));
TRY(s_name_to_key.insert("Key1"sv, Key::_1));
TRY(s_name_to_key.insert("Key2"sv, Key::_2));
TRY(s_name_to_key.insert("Key3"sv, Key::_3));
TRY(s_name_to_key.insert("Key4"sv, Key::_4));
TRY(s_name_to_key.insert("Key5"sv, Key::_5));
TRY(s_name_to_key.insert("Key6"sv, Key::_6));
TRY(s_name_to_key.insert("Key7"sv, Key::_7));
TRY(s_name_to_key.insert("Key8"sv, Key::_8));
TRY(s_name_to_key.insert("Key9"sv, Key::_9));
TRY(s_name_to_key.insert("L"sv, Key::L));
TRY(s_name_to_key.insert("LAlt"sv, Key::LeftAlt));
TRY(s_name_to_key.insert("LControl"sv, Key::LeftCtrl));
TRY(s_name_to_key.insert("LeftAlt"sv, Key::LeftAlt));
TRY(s_name_to_key.insert("LeftControl"sv, Key::LeftCtrl));
TRY(s_name_to_key.insert("LeftShift"sv, Key::LeftShift));
TRY(s_name_to_key.insert("LessThan"sv, Key::LessThan));
TRY(s_name_to_key.insert("LShift"sv, Key::LeftShift));
TRY(s_name_to_key.insert("M"sv, Key::M));
TRY(s_name_to_key.insert("MediaNext"sv, Key::MediaNext));
TRY(s_name_to_key.insert("MediaPlayPause"sv, Key::MediaPlayPause));
TRY(s_name_to_key.insert("MediaPrevious"sv, Key::MediaPrevious));
TRY(s_name_to_key.insert("MediaStop"sv, Key::MediaStop));
TRY(s_name_to_key.insert("N"sv, Key::N));
TRY(s_name_to_key.insert("None"sv, Key::None));
TRY(s_name_to_key.insert("NumLock"sv, Key::NumLock));
TRY(s_name_to_key.insert("Numpad0"sv, Key::Numpad0));
TRY(s_name_to_key.insert("Numpad1"sv, Key::Numpad1));
TRY(s_name_to_key.insert("Numpad2"sv, Key::Numpad2));
TRY(s_name_to_key.insert("Numpad3"sv, Key::Numpad3));
TRY(s_name_to_key.insert("Numpad4"sv, Key::Numpad4));
TRY(s_name_to_key.insert("Numpad5"sv, Key::Numpad5));
TRY(s_name_to_key.insert("Numpad6"sv, Key::Numpad6));
TRY(s_name_to_key.insert("Numpad7"sv, Key::Numpad7));
TRY(s_name_to_key.insert("Numpad8"sv, Key::Numpad8));
TRY(s_name_to_key.insert("Numpad9"sv, Key::Numpad9));
TRY(s_name_to_key.insert("NumpadDecimal"sv, Key::NumpadDecimal));
TRY(s_name_to_key.insert("NumpadDivide"sv, Key::NumpadDivide));
TRY(s_name_to_key.insert("NumpadEnter"sv, Key::NumpadEnter));
TRY(s_name_to_key.insert("NumpadMinus"sv, Key::NumpadMinus));
TRY(s_name_to_key.insert("NumpadMultiply"sv, Key::NumpadMultiply));
TRY(s_name_to_key.insert("NumpadPlus"sv, Key::NumpadPlus));
TRY(s_name_to_key.insert("O_Umlaut"sv, Key::O_Umlaut));
TRY(s_name_to_key.insert("O"sv, Key::O));
TRY(s_name_to_key.insert("OpenCurlyBracket"sv, Key::OpenCurlyBracket));
TRY(s_name_to_key.insert("OpenParenthesis"sv, Key::OpenParenthesis));
TRY(s_name_to_key.insert("OpenSquareBracket"sv, Key::OpenSquareBracket));
TRY(s_name_to_key.insert("P"sv, Key::P));
TRY(s_name_to_key.insert("PageDown"sv, Key::PageDown));
TRY(s_name_to_key.insert("PageUp"sv, Key::PageUp));
TRY(s_name_to_key.insert("Percent"sv, Key::Percent));
TRY(s_name_to_key.insert("Period"sv, Key::Period));
TRY(s_name_to_key.insert("Pipe"sv, Key::Pipe));
TRY(s_name_to_key.insert("Plus"sv, Key::Plus));
TRY(s_name_to_key.insert("Pound"sv, Key::Pound));
TRY(s_name_to_key.insert("PrintScreen"sv, Key::PrintScreen));
TRY(s_name_to_key.insert("Q"sv, Key::Q));
TRY(s_name_to_key.insert("Question"sv, Key::QuestionMark));
TRY(s_name_to_key.insert("QuestionMark"sv, Key::QuestionMark));
TRY(s_name_to_key.insert("R"sv, Key::R));
TRY(s_name_to_key.insert("RAlt"sv, Key::RightAlt));
TRY(s_name_to_key.insert("RControl"sv, Key::RightCtrl));
TRY(s_name_to_key.insert("RightAlt"sv, Key::RightAlt));
TRY(s_name_to_key.insert("RightControl"sv, Key::RightCtrl));
TRY(s_name_to_key.insert("RightShift"sv, Key::RightShift));
TRY(s_name_to_key.insert("RShift"sv, Key::RightShift));
TRY(s_name_to_key.insert("S"sv, Key::S));
TRY(s_name_to_key.insert("ScrollLock"sv, Key::ScrollLock));
TRY(s_name_to_key.insert("Section"sv, Key::Section));
TRY(s_name_to_key.insert("Semicolon"sv, Key::Semicolon));
TRY(s_name_to_key.insert("SingleQuote"sv, Key::SingleQuote));
TRY(s_name_to_key.insert("Slash"sv, Key::Slash));
TRY(s_name_to_key.insert("Space"sv, Key::Space));
TRY(s_name_to_key.insert("Super"sv, Key::Super));
TRY(s_name_to_key.insert("T"sv, Key::T));
TRY(s_name_to_key.insert("Tab"sv, Key::Tab));
TRY(s_name_to_key.insert("Tilde"sv, Key::Tilde));
TRY(s_name_to_key.insert("TwoDots"sv, Key::TwoDots));
TRY(s_name_to_key.insert("U"sv, Key::U));
TRY(s_name_to_key.insert("Underscore"sv, Key::Underscore));
TRY(s_name_to_key.insert("V"sv, Key::V));
TRY(s_name_to_key.insert("VolumeDown"sv, Key::VolumeDown));
TRY(s_name_to_key.insert("VolumeMute"sv, Key::VolumeMute));
TRY(s_name_to_key.insert("VolumeUp"sv, Key::VolumeUp));
TRY(s_name_to_key.insert("W"sv, Key::W));
TRY(s_name_to_key.insert("X"sv, Key::X));
TRY(s_name_to_key.insert("Y"sv, Key::Y));
TRY(s_name_to_key.insert("Z"sv, Key::Z));
return {};
}
}

View File

@ -10,65 +10,212 @@
#include <kernel/IO.h>
#include <kernel/Timer/Timer.h>
#define DEBUG_PS2 1
namespace Kernel::Input
{
static constexpr uint64_t s_device_timeout_ms = 100;
static void controller_send_command(PS2::Command command)
{
IO::outb(PS2::IOPort::COMMAND, command);
}
static void controller_send_command(PS2::Command command, uint8_t data)
{
IO::outb(PS2::IOPort::COMMAND, command);
while (IO::inb(PS2::IOPort::STATUS) & PS2::Status::INPUT_FULL)
continue;
IO::outb(PS2::IOPort::DATA, data);
}
static uint8_t wait_and_read()
{
while (!(IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_FULL))
continue;
return IO::inb(PS2::IOPort::DATA);
}
static BAN::ErrorOr<void> device_send_byte(uint8_t device, uint8_t byte)
{
if (device == 1)
IO::outb(PS2::IOPort::COMMAND, PS2::Command::WRITE_TO_SECOND_PORT);
uint64_t timeout = SystemTimer::get().ms_since_boot() + s_device_timeout_ms;
while (SystemTimer::get().ms_since_boot() < timeout)
{
if (!(IO::inb(PS2::IOPort::STATUS) & PS2::Status::INPUT_FULL))
{
IO::outb(PS2::IOPort::DATA, byte);
return {};
}
}
return BAN::Error::from_error_code(ErrorCode::PS2_Timeout);
}
static BAN::ErrorOr<uint8_t> device_read_byte()
{
uint64_t timeout = SystemTimer::get().ms_since_boot() + s_device_timeout_ms;
while (SystemTimer::get().ms_since_boot() < timeout)
if (IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_FULL)
return IO::inb(PS2::IOPort::DATA);
return BAN::Error::from_error_code(ErrorCode::PS2_Timeout);
}
static BAN::ErrorOr<void> device_wait_ack()
{
while (TRY(device_read_byte()) != PS2::Response::ACK)
continue;;
return {};
}
static constexpr uint64_t s_ps2_timeout_ms = 100;
static PS2Controller* s_instance = nullptr;
BAN::ErrorOr<void> PS2Controller::send_byte(uint16_t port, uint8_t byte)
{
ASSERT(interrupts_enabled());
LockGuard _(m_lock);
uint64_t timeout = SystemTimer::get().ms_since_boot() + s_ps2_timeout_ms;
while (SystemTimer::get().ms_since_boot() < timeout)
{
if (IO::inb(PS2::IOPort::STATUS) & PS2::Status::INPUT_STATUS)
continue;
IO::outb(port, byte);
return {};
}
return BAN::Error::from_errno(ETIMEDOUT);
}
BAN::ErrorOr<uint8_t> PS2Controller::read_byte()
{
ASSERT(interrupts_enabled());
LockGuard _(m_lock);
uint64_t timeout = SystemTimer::get().ms_since_boot() + s_ps2_timeout_ms;
while (SystemTimer::get().ms_since_boot() < timeout)
{
if (!(IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_STATUS))
continue;
return IO::inb(PS2::IOPort::DATA);
}
return BAN::Error::from_errno(ETIMEDOUT);
}
BAN::ErrorOr<void> PS2Controller::send_command(PS2::Command command)
{
LockGuard _(m_lock);
TRY(send_byte(PS2::IOPort::COMMAND, command));
return {};
}
BAN::ErrorOr<void> PS2Controller::send_command(PS2::Command command, uint8_t data)
{
LockGuard _(m_lock);
TRY(send_byte(PS2::IOPort::COMMAND, command));
TRY(send_byte(PS2::IOPort::DATA, data));
return {};
}
BAN::ErrorOr<void> PS2Controller::device_send_byte(uint8_t device_index, uint8_t byte)
{
LockGuard _(m_lock);
if (device_index == 1)
TRY(send_byte(PS2::IOPort::COMMAND, PS2::Command::WRITE_TO_SECOND_PORT));
TRY(send_byte(PS2::IOPort::DATA, byte));
return {};
}
BAN::ErrorOr<void> PS2Controller::device_send_byte_and_wait_ack(uint8_t device_index, uint8_t byte)
{
LockGuard _(m_lock);
for (;;)
{
TRY(device_send_byte(device_index, byte));
uint8_t response = TRY(read_byte());
if (response == PS2::Response::RESEND)
continue;
if (response == PS2::Response::ACK)
break;
dwarnln_if(DEBUG_PS2, "PS/2 device on port {} did not respond with expected ACK, got {2H}", device_index, byte);
return BAN::Error::from_errno(EBADMSG);
}
return {};
}
bool PS2Controller::append_command_queue(PS2Device* device, uint8_t command, uint8_t response_size)
{
// NOTE: command queue push/pop must be done without interrupts
CriticalScope _;
ASSERT(device && (device == m_devices[0].ptr() || device == m_devices[1].ptr()));
if (m_command_queue.size() + 1 >= m_command_queue.capacity())
{
dprintln("PS/2 command queue full");
return false;
}
m_command_queue.push(Command {
.state = Command::State::NotSent,
.device_index = (device == m_devices[0].ptr()) ? uint8_t(0) : uint8_t(1),
.out_data = { command, 0x00 },
.out_count = 1,
.in_count = response_size,
.send_index = 0
});
return true;
}
bool PS2Controller::append_command_queue(PS2Device* device, uint8_t command, uint8_t data, uint8_t response_size)
{
// NOTE: command queue push/pop must be done without interrupts
CriticalScope _;
ASSERT(device && (device == m_devices[0].ptr() || device == m_devices[1].ptr()));
if (m_command_queue.size() + 1 >= m_command_queue.capacity())
{
dprintln("PS/2 command queue full");
return false;
}
m_command_queue.push(Command {
.state = Command::State::NotSent,
.device_index = (device == m_devices[0].ptr()) ? uint8_t(0) : uint8_t(1),
.out_data = { command, data },
.out_count = 2,
.in_count = response_size,
.send_index = 0
});
return true;
}
void PS2Controller::update_command_queue()
{
ASSERT(interrupts_enabled());
if (m_command_queue.empty())
return;
auto& command = m_command_queue.front();
if (command.state == Command::State::WaitingResponse || command.state == Command::State::WaitingAck)
{
if (SystemTimer::get().ms_since_boot() >= m_command_send_time + s_ps2_timeout_ms)
{
dwarnln_if(DEBUG_PS2, "Command timedout");
m_devices[command.device_index]->command_timedout(command.out_data, command.out_count);
m_command_queue.pop();
}
return;
}
ASSERT(command.send_index < command.out_count);
command.state = Command::State::WaitingAck;
m_command_send_time = SystemTimer::get().ms_since_boot();
if (auto ret = device_send_byte(command.device_index, command.out_data[command.send_index]); ret.is_error())
{
command.state = Command::State::Sending;
dwarnln_if(DEBUG_PS2, "PS/2 send command byte: {}", ret.error());
}
}
bool PS2Controller::handle_command_byte(PS2Device* device, uint8_t byte)
{
// NOTE: command queue push/pop must be done without interrupts
ASSERT(!interrupts_enabled());
if (m_command_queue.empty())
return false;
auto& command = m_command_queue.front();
ASSERT(device && (device == m_devices[0].ptr() || device == m_devices[1].ptr()));
if (command.device_index != (device == m_devices[0].ptr()) ? 0 : 1)
return false;
switch (command.state)
{
case Command::State::NotSent:
{
return false;
}
case Command::State::Sending:
{
dwarnln_if(DEBUG_PS2, "PS/2 device sent byte while middle of command send");
return false;
}
case Command::State::WaitingResponse:
{
if (--command.in_count <= 0)
m_command_queue.pop();
return false;
}
case Command::State::WaitingAck:
{
switch (byte)
{
case PS2::Response::ACK:
{
if (++command.send_index < command.out_count)
command.state = Command::State::Sending;
else if (command.in_count > 0)
command.state = Command::State::WaitingResponse;
else
m_command_queue.pop();
return true;
}
case PS2::Response::RESEND:
command.state = Command::State::Sending;
return true;
default:
dwarnln_if(DEBUG_PS2, "PS/2 expected ACK got {2H}", byte);
command.state = Command::State::Sending;
return true;
}
break;
}
}
ASSERT_NOT_REACHED();
}
BAN::ErrorOr<void> PS2Controller::initialize()
{
ASSERT(s_instance == nullptr);
@ -89,88 +236,96 @@ namespace Kernel::Input
BAN::ErrorOr<void> PS2Controller::initialize_impl()
{
// Step 1: Initialise USB Controllers
// FIXME
// FIXME: Initialise USB Controllers
// Step 2: Determine if the PS/2 Controller Exists
// FIXME
// Determine if the PS/2 Controller Exists
auto* fadt = static_cast<const ACPI::FADT*>(ACPI::get().get_header("FACP"sv, 0));
if (fadt && fadt->revision > 1 && !(fadt->iapc_boot_arch & (1 << 1)))
{
dwarnln_if(DEBUG_PS2, "No PS/2 available");
return {};
}
// Step 3: Disable Devices
controller_send_command(PS2::Command::DISABLE_FIRST_PORT);
controller_send_command(PS2::Command::DISABLE_SECOND_PORT);
// Disable Devices
TRY(send_command(PS2::Command::DISABLE_FIRST_PORT));
TRY(send_command(PS2::Command::DISABLE_SECOND_PORT));
// Step 4: Flush The Output Buffer
IO::inb(PS2::IOPort::DATA);
// Flush The Output Buffer
while (!read_byte().is_error())
continue;
// Step 5: Set the Controller Configuration Byte
controller_send_command(PS2::Command::READ_CONFIG);
uint8_t config = wait_and_read();
// Set the Controller Configuration Byte
TRY(send_command(PS2::Command::READ_CONFIG));
uint8_t config = TRY(read_byte());
config &= ~PS2::Config::INTERRUPT_FIRST_PORT;
config &= ~PS2::Config::INTERRUPT_SECOND_PORT;
config &= ~PS2::Config::TRANSLATION_FIRST_PORT;
controller_send_command(PS2::Command::WRITE_CONFIG, config);
TRY(send_command(PS2::Command::WRITE_CONFIG, config));
// Step 6: Perform Controller Self Test
controller_send_command(PS2::Command::TEST_CONTROLLER);
if (wait_and_read() != PS2::Response::TEST_CONTROLLER_PASS)
return BAN::Error::from_error_code(ErrorCode::PS2_SelfTest);
// Perform Controller Self Test
TRY(send_command(PS2::Command::TEST_CONTROLLER));
if (TRY(read_byte()) != PS2::Response::TEST_CONTROLLER_PASS)
{
dwarnln_if(DEBUG_PS2, "PS/2 Controller test failed");
return BAN::Error::from_errno(ENODEV);
}
// NOTE: self test might reset the device so we set the config byte again
controller_send_command(PS2::Command::WRITE_CONFIG, config);
TRY(send_command(PS2::Command::WRITE_CONFIG, config));
// Step 7: Determine If There Are 2 Channels
// Determine If There Are 2 Channels
bool valid_ports[2] { true, false };
if (config & PS2::Config::CLOCK_SECOND_PORT)
{
controller_send_command(PS2::Command::ENABLE_SECOND_PORT);
controller_send_command(PS2::Command::READ_CONFIG);
if (!(wait_and_read() & PS2::Config::CLOCK_SECOND_PORT))
TRY(send_command(PS2::Command::ENABLE_SECOND_PORT));
TRY(send_command(PS2::Command::READ_CONFIG));
if (!(TRY(read_byte()) & PS2::Config::CLOCK_SECOND_PORT))
{
valid_ports[1] = true;
controller_send_command(PS2::Command::DISABLE_SECOND_PORT);
TRY(send_command(PS2::Command::DISABLE_SECOND_PORT));
}
}
// Step 8: Perform Interface Tests
controller_send_command(PS2::Command::TEST_FIRST_PORT);
if (wait_and_read() != PS2::Response::TEST_FIRST_PORT_PASS)
// Perform Interface Tests
TRY(send_command(PS2::Command::TEST_FIRST_PORT));
if (TRY(read_byte()) != PS2::Response::TEST_FIRST_PORT_PASS)
{
dwarnln_if(DEBUG_PS2, "PS/2 first port test failed");
valid_ports[0] = false;
}
if (valid_ports[1])
{
controller_send_command(PS2::Command::TEST_SECOND_PORT);
if (wait_and_read() != PS2::Response::TEST_SECOND_PORT_PASS)
TRY(send_command(PS2::Command::TEST_SECOND_PORT));
if (TRY(read_byte()) != PS2::Response::TEST_SECOND_PORT_PASS)
{
dwarnln_if(DEBUG_PS2, "PS/2 second port test failed");
valid_ports[1] = false;
}
}
if (!valid_ports[0] && !valid_ports[1])
return {};
// Step 9: Enable Devices (and disable scanning)
// Initialize devices
for (uint8_t device = 0; device < 2; device++)
{
if (!valid_ports[device])
continue;
controller_send_command(device == 0 ? PS2::Command::ENABLE_FIRST_PORT : PS2::Command::ENABLE_SECOND_PORT);
if (set_scanning(device, false).is_error())
valid_ports[device] = false;
if (auto ret = send_command(device == 0 ? PS2::Command::ENABLE_FIRST_PORT : PS2::Command::ENABLE_SECOND_PORT); ret.is_error())
{
dwarnln_if(DEBUG_PS2, "PS/2 device enable failed: {}", ret.error());
continue;
}
// Step 10: Reset Devices
for (uint8_t device = 0; device < 2; device++)
{
if (!valid_ports[device])
continue;
if (reset_device(device).is_error())
valid_ports[device] = false;
if (set_scanning(device, false).is_error())
valid_ports[device] = false;
}
// Step 11: Initialize Device Drivers
for (uint8_t device = 0; device < 2; device++)
{
if (!valid_ports[device])
continue;
if (auto res = initialize_device(device); res.is_error())
dprintln("{}", res.error());
{
dwarnln_if(DEBUG_PS2, "PS/2 device initialization failed: {}", res.error());
(void)send_command(device == 0 ? PS2::Command::DISABLE_FIRST_PORT : PS2::Command::DISABLE_SECOND_PORT);
continue;
}
}
if (!m_devices[0] && !m_devices[1])
return {};
// Enable irqs on valid devices
if (m_devices[0])
{
m_devices[0]->set_irq(PS2::IRQ::DEVICE0);
@ -184,11 +339,12 @@ namespace Kernel::Input
config |= PS2::Config::INTERRUPT_SECOND_PORT;
}
controller_send_command(PS2::Command::WRITE_CONFIG, config);
TRY(send_command(PS2::Command::WRITE_CONFIG, config));
// Send device initialization sequence after interrupts are enabled
for (uint8_t device = 0; device < 2; device++)
{
if (m_devices[device] == nullptr)
if (!m_devices[device])
continue;
m_devices[device]->send_initialize();
DevFileSystem::get().add_device(m_devices[device]);
@ -199,14 +355,30 @@ namespace Kernel::Input
BAN::ErrorOr<void> PS2Controller::initialize_device(uint8_t device)
{
TRY(device_send_byte(device, PS2::DeviceCommand::IDENTIFY));
TRY(device_wait_ack());
// Reset device
TRY(device_send_byte_and_wait_ack(device, PS2::DeviceCommand::RESET));
if (TRY(read_byte()) != PS2::Response::SELF_TEST_PASS)
{
dwarnln_if(DEBUG_PS2, "PS/2 device self test failed");
return BAN::Error::from_errno(ENODEV);
}
while (!read_byte().is_error())
continue;
// Disable scanning and flush buffer
TRY(device_send_byte_and_wait_ack(device, PS2::DeviceCommand::DISABLE_SCANNING));
while (!read_byte().is_error())
continue;
// Identify device
TRY(device_send_byte_and_wait_ack(device, PS2::DeviceCommand::IDENTIFY));
// Read up to 2 identification bytes
uint8_t bytes[2] {};
uint8_t index = 0;
for (uint8_t i = 0; i < 2; i++)
{
auto res = device_read_byte();
auto res = read_byte();
if (res.is_error())
break;
bytes[index++] = res.value();
@ -214,38 +386,22 @@ namespace Kernel::Input
// Standard PS/2 Mouse
if (index == 1 && (bytes[0] == 0x00))
{
dprintln_if(DEBUG_PS2, "PS/2 found mouse");
m_devices[device] = TRY(PS2Mouse::create(*this));
return {};
}
// MF2 Keyboard
else if (index == 2 && (bytes[0] == 0xAB && bytes[1] == 0x83))
if (index == 2 && (bytes[0] == 0xAB && (bytes[1] == 0x83 || bytes[1] == 0x41)))
{
dprintln_if(DEBUG_PS2, "PS/2 found keyboard");
m_devices[device] = TRY(PS2Keyboard::create(*this));
if (m_devices[device])
return {};
return BAN::Error::from_error_code(ErrorCode::PS2_UnsupportedDevice);
}
void PS2Controller::send_byte(const PS2Device* device, uint8_t byte)
{
ASSERT(device != nullptr && (device == m_devices[0] || device == m_devices[1]));
uint8_t device_index = (device == m_devices[0]) ? 0 : 1;
MUST(device_send_byte(device_index, byte));
}
BAN::ErrorOr<void> PS2Controller::reset_device(uint8_t device)
{
TRY(device_send_byte(device, PS2::DeviceCommand::RESET));
TRY(device_wait_ack());
if (TRY(device_read_byte()) != PS2::Response::SELF_TEST_PASS)
return BAN::Error::from_error_code(ErrorCode::PS2_Reset);
return {};
}
BAN::ErrorOr<void> PS2Controller::set_scanning(uint8_t device, bool enabled)
{
TRY(device_send_byte(device, enabled ? PS2::DeviceCommand::ENABLE_SCANNING : PS2::DeviceCommand::DISABLE_SCANNING));
TRY(device_wait_ack());
return {};
dprintln_if(DEBUG_PS2, "PS/2 unsupported device {2H} {2H} ({} bytes) on port {}", bytes[0], bytes[1], index, device);
return BAN::Error::from_errno(ENOTSUP);
}
}

View File

@ -15,74 +15,21 @@ namespace Kernel::Input
, m_controller(controller)
{ }
bool PS2Device::append_command_queue(uint8_t command)
bool PS2Device::append_command_queue(uint8_t command, uint8_t response_size)
{
if (m_command_queue.size() + 1 >= m_command_queue.capacity())
{
dprintln("PS/2 command queue full");
return false;
}
m_command_queue.push(command);
update();
return true;
return m_controller.append_command_queue(this, command, response_size);
}
bool PS2Device::append_command_queue(uint8_t command, uint8_t data)
bool PS2Device::append_command_queue(uint8_t command, uint8_t data, uint8_t response_size)
{
if (m_command_queue.size() + 2 >= m_command_queue.capacity())
{
dprintln("PS/2 command queue full");
return false;
}
m_command_queue.push(command);
m_command_queue.push(data);
update();
return true;
return m_controller.append_command_queue(this, command, data, response_size);
}
void PS2Device::handle_irq()
{
uint8_t byte = IO::inb(PS2::IOPort::DATA);
// NOTE: This implementation does not allow using commands
// that respond with more bytes than ACK
switch (m_state)
{
case State::WaitingAck:
{
switch (byte)
{
case PS2::Response::ACK:
m_command_queue.pop();
m_state = State::Normal;
break;
case PS2::Response::RESEND:
m_state = State::Normal;
break;
default:
handle_device_command_response(byte);
break;
}
break;
}
case State::Normal:
{
if (!m_controller.handle_command_byte(this, byte))
handle_byte(byte);
break;
}
}
update();
}
void PS2Device::update()
{
if (m_state == State::WaitingAck)
return;
if (m_command_queue.empty())
return;
m_state = State::WaitingAck;
m_controller.send_byte(this, m_command_queue.front());
}
}

View File

@ -3,6 +3,7 @@
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Input/PS2/Config.h>
#include <kernel/Input/PS2/Keyboard.h>
#include <kernel/Thread.h>
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
@ -24,90 +25,121 @@ namespace Kernel::Input
void PS2Keyboard::send_initialize()
{
append_command_queue(Command::SET_LEDS, 0x00);
append_command_queue(Command::SCANCODE, PS2::KBScancode::SET_SCANCODE_SET2);
append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING);
constexpr uint8_t wanted_scancode_set = 3;
append_command_queue(Command::SET_LEDS, 0x00, 0);
append_command_queue(Command::CONFIG_SCANCODE_SET, wanted_scancode_set, 0);
append_command_queue(Command::CONFIG_SCANCODE_SET, 0, 1);
}
void PS2Keyboard::handle_device_command_response(uint8_t byte)
void PS2Keyboard::command_timedout(uint8_t* command_data, uint8_t command_size)
{
switch (byte)
if (command_size == 0)
return;
if (command_data[0] == Command::CONFIG_SCANCODE_SET && m_scancode_set >= 0xFE)
{
case PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN1:
case PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN2:
dwarnln("Key detection error or internal buffer overrun");
break;
default:
dwarnln("Unhandeled byte {2H}", byte);
break;
dwarnln("Could not detect scancode set, assuming 1");
m_scancode_set = 1;
m_keymap.initialize(m_scancode_set);
append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING, 0);
}
}
void PS2Keyboard::handle_byte(uint8_t byte)
{
if (byte == PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN1 || byte == PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN2)
{
dwarnln("Key detection error or internal buffer overrun");
return;
}
if (m_scancode_set == 0xFF)
{
append_command_queue(Command::CONFIG_SCANCODE_SET, 0, 1);
m_scancode_set = 0xFE;
return;
}
if (m_scancode_set == 0xFE)
{
if (1 <= byte && byte <= 3)
{
m_scancode_set = byte;
dprintln("Using scancode set {}", m_scancode_set);
}
else
{
dwarnln("Could not detect scancode set, assuming 1");
m_scancode_set = 1;
}
m_keymap.initialize(m_scancode_set);
append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING, 0);
return;
}
if (m_byte_index >= 3)
{
dwarnln("PS/2 corrupted key packet");
m_byte_index = 0;
return;
}
m_byte_buffer[m_byte_index++] = byte;
if (byte == 0xE0 || byte == 0xF0)
if (byte == 0xE0)
return;
if ((m_scancode_set == 2 || m_scancode_set == 3) && byte == 0xF0)
return;
uint32_t scancode = 0;
bool extended = false;
bool released = false;
for (uint8_t i = 0; i < m_byte_index; i++)
uint8_t index = 0;
// in all scancode sets, extended scancode is indicated by byte 0xE0
if (index < m_byte_index && m_byte_buffer[index] == 0xE0)
{
if (m_byte_buffer[i] == 0xE0)
extended = true;
else if (m_byte_buffer[i] == 0xF0)
index++;
}
// in scancode set 1, released key is indicated by bit 7 set
if (m_scancode_set == 1 && (m_byte_buffer[index] & 0x80))
{
released = true;
else
scancode = (scancode << 8) | m_byte_buffer[i];
m_byte_buffer[index] &= 0x7F;
}
// in scancode set 2 and 3, released key is indicated by byte 0xF0
if ((m_scancode_set == 2 || m_scancode_set == 3) && m_byte_buffer[index] == 0xF0)
{
released = true;
index++;
}
if (extended)
scancode |= 0x80000000;
bool corrupted = (index + 1 != m_byte_index);
m_byte_index = 0;
Key key = m_keymap.key_for_scancode_and_modifiers(scancode, m_modifiers);
if (key == Key::None)
return;
if (key == Input::Key::Invalid)
if (corrupted)
{
dprintln("unknown key for scancode {2H} {}", scancode & 0x7FFFFFFF, extended ? 'E' : ' ');
dwarnln("PS/2 corrupted key packet");
return;
}
uint8_t modifier_mask = 0;
uint8_t toggle_mask = 0;
switch (key)
auto keycode = m_keymap.get_keycode(m_byte_buffer[index], extended);
if (!keycode.has_value())
return;
uint16_t modifier_mask = 0;
uint16_t toggle_mask = 0;
switch (keycode.value())
{
case Input::Key::LeftShift:
case Input::Key::RightShift:
modifier_mask = (uint8_t)Input::KeyEvent::Modifier::Shift;
break;
case Input::Key::LeftCtrl:
case Input::Key::RightCtrl:
modifier_mask = (uint8_t)Input::KeyEvent::Modifier::Ctrl;
break;
case Input::Key::Alt:
modifier_mask = (uint8_t)Input::KeyEvent::Modifier::Alt;
break;
case Input::Key::AltGr:
modifier_mask = (uint8_t)Input::KeyEvent::Modifier::AltGr;
break;;
case Input::Key::ScrollLock:
toggle_mask = (uint8_t)Input::KeyEvent::Modifier::ScrollLock;
break;
case Input::Key::NumLock:
toggle_mask = (uint8_t)Input::KeyEvent::Modifier::NumLock;
break;
case Input::Key::CapsLock:
toggle_mask = (uint8_t)Input::KeyEvent::Modifier::CapsLock;
break;
default:
break;
case ModifierKeycode::LShift: modifier_mask = KeyEvent::Modifier::LShift; break;
case ModifierKeycode::RShift: modifier_mask = KeyEvent::Modifier::RShift; break;
case ModifierKeycode::LCtrl: modifier_mask = KeyEvent::Modifier::LCtrl; break;
case ModifierKeycode::RCtrl: modifier_mask = KeyEvent::Modifier::RCtrl; break;
case ModifierKeycode::LAlt: modifier_mask = KeyEvent::Modifier::LAlt; break;
case ModifierKeycode::RAlt: modifier_mask = KeyEvent::Modifier::RAlt; break;
case ModifierKeycode::ScrollLock: toggle_mask = KeyEvent::Modifier::ScrollLock; break;
case ModifierKeycode::NumLock: toggle_mask = KeyEvent::Modifier::NumLock; break;
case ModifierKeycode::CapsLock: toggle_mask = KeyEvent::Modifier::CapsLock; break;
}
if (modifier_mask)
@ -118,15 +150,15 @@ namespace Kernel::Input
m_modifiers |= modifier_mask;
}
if (toggle_mask && !released)
if (toggle_mask)
{
m_modifiers ^= toggle_mask;
update_leds();
}
Input::KeyEvent event;
event.modifier = m_modifiers | (released ? (uint8_t)Input::KeyEvent::Modifier::Released : 0);
event.key = key;
KeyEvent event;
event.modifier = m_modifiers | (released ? 0 : KeyEvent::Modifier::Pressed);
event.keycode = keycode.value();
if (m_event_queue.full())
{
@ -141,13 +173,13 @@ namespace Kernel::Input
void PS2Keyboard::update_leds()
{
uint8_t new_leds = 0;
if (m_modifiers & (uint8_t)Input::KeyEvent::Modifier::ScrollLock)
if (m_modifiers & +Input::KeyEvent::Modifier::ScrollLock)
new_leds |= PS2::KBLeds::SCROLL_LOCK;
if (m_modifiers & (uint8_t)Input::KeyEvent::Modifier::NumLock)
if (m_modifiers & +Input::KeyEvent::Modifier::NumLock)
new_leds |= PS2::KBLeds::NUM_LOCK;
if (m_modifiers & (uint8_t)Input::KeyEvent::Modifier::CapsLock)
if (m_modifiers & +Input::KeyEvent::Modifier::CapsLock)
new_leds |= PS2::KBLeds::CAPS_LOCK;
append_command_queue(Command::SET_LEDS, new_leds);
append_command_queue(Command::SET_LEDS, new_leds, 0);
}
BAN::ErrorOr<size_t> PS2Keyboard::read_impl(off_t, BAN::ByteSpan buffer)
@ -158,7 +190,7 @@ namespace Kernel::Input
while (true)
{
if (m_event_queue.empty())
m_semaphore.block();
TRY(Thread::current().block_or_eintr(m_semaphore));
CriticalScope _;
if (m_event_queue.empty())

View File

@ -1,360 +1,361 @@
#include <kernel/Input/KeyEvent.h>
#include <kernel/Input/PS2/Keymap.h>
namespace Kernel::Input
{
PS2Keymap::PS2Keymap()
void PS2Keymap::initialize(uint8_t scancode_set)
{
MUST(m_normal_keymap.resize(0xFF, Key::Invalid));
m_normal_keymap[0x01] = Key::F9;
m_normal_keymap[0x03] = Key::F5;
m_normal_keymap[0x04] = Key::F3;
m_normal_keymap[0x05] = Key::F1;
m_normal_keymap[0x06] = Key::F2;
m_normal_keymap[0x07] = Key::F11;
m_normal_keymap[0x09] = Key::F10;
m_normal_keymap[0x0A] = Key::F8;
m_normal_keymap[0x0B] = Key::F6;
m_normal_keymap[0x0C] = Key::F4;
m_normal_keymap[0x0D] = Key::Tab;
m_normal_keymap[0x0E] = Key::Section;
m_normal_keymap[0x11] = Key::Alt;
m_normal_keymap[0x12] = Key::LeftShift;
m_normal_keymap[0x14] = Key::LeftCtrl;
m_normal_keymap[0x15] = Key::Q;
m_normal_keymap[0x16] = Key::_1;
m_normal_keymap[0x1A] = Key::Z;
m_normal_keymap[0x1B] = Key::S;
m_normal_keymap[0x1C] = Key::A;
m_normal_keymap[0x1D] = Key::W;
m_normal_keymap[0x1E] = Key::_2;
m_normal_keymap[0x21] = Key::C;
m_normal_keymap[0x22] = Key::X;
m_normal_keymap[0x23] = Key::D;
m_normal_keymap[0x24] = Key::E;
m_normal_keymap[0x25] = Key::_4;
m_normal_keymap[0x26] = Key::_3;
m_normal_keymap[0x29] = Key::Space;
m_normal_keymap[0x2A] = Key::V;
m_normal_keymap[0x2B] = Key::F;
m_normal_keymap[0x2C] = Key::T;
m_normal_keymap[0x2D] = Key::R;
m_normal_keymap[0x2E] = Key::_5;
m_normal_keymap[0x31] = Key::N;
m_normal_keymap[0x32] = Key::B;
m_normal_keymap[0x33] = Key::H;
m_normal_keymap[0x34] = Key::G;
m_normal_keymap[0x35] = Key::Y;
m_normal_keymap[0x36] = Key::_6;
m_normal_keymap[0x3A] = Key::M;
m_normal_keymap[0x3B] = Key::J;
m_normal_keymap[0x3C] = Key::U;
m_normal_keymap[0x3D] = Key::_7;
m_normal_keymap[0x3E] = Key::_8;
m_normal_keymap[0x41] = Key::Comma;
m_normal_keymap[0x42] = Key::K;
m_normal_keymap[0x43] = Key::I;
m_normal_keymap[0x44] = Key::O;
m_normal_keymap[0x45] = Key::_0;
m_normal_keymap[0x46] = Key::_9;
m_normal_keymap[0x49] = Key::Period;
m_normal_keymap[0x4A] = Key::Hyphen;
m_normal_keymap[0x4B] = Key::L;
m_normal_keymap[0x4C] = Key::O_Umlaut;
m_normal_keymap[0x4D] = Key::P;
m_normal_keymap[0x4E] = Key::Plus;
m_normal_keymap[0x52] = Key::A_Umlaut;
m_normal_keymap[0x54] = Key::A_Ring;
m_normal_keymap[0x55] = Key::Acute;
m_normal_keymap[0x58] = Key::CapsLock;
m_normal_keymap[0x59] = Key::RightShift;
m_normal_keymap[0x59] = Key::RightShift;
m_normal_keymap[0x5A] = Key::Enter;
m_normal_keymap[0x5B] = Key::TwoDots;
m_normal_keymap[0x5D] = Key::SingleQuote;
m_normal_keymap[0x61] = Key::LessThan;
m_normal_keymap[0x66] = Key::Backspace;
m_normal_keymap[0x69] = Key::Numpad1;
m_normal_keymap[0x6B] = Key::Numpad4;
m_normal_keymap[0x6C] = Key::Numpad7;
m_normal_keymap[0x70] = Key::Numpad0;
m_normal_keymap[0x71] = Key::NumpadDecimal;
m_normal_keymap[0x72] = Key::Numpad2;
m_normal_keymap[0x73] = Key::Numpad5;
m_normal_keymap[0x74] = Key::Numpad6;
m_normal_keymap[0x75] = Key::Numpad8;
m_normal_keymap[0x76] = Key::Escape;
m_normal_keymap[0x77] = Key::NumLock;
m_normal_keymap[0x78] = Key::F11;
m_normal_keymap[0x79] = Key::NumpadPlus;
m_normal_keymap[0x7A] = Key::Numpad3;
m_normal_keymap[0x7B] = Key::NumpadMinus;
m_normal_keymap[0x7C] = Key::NumpadMultiply;
m_normal_keymap[0x7D] = Key::Numpad9;
m_normal_keymap[0x83] = Key::F7;
MUST(m_shift_keymap.resize(0xFF, Key::Invalid));
m_shift_keymap[0x01] = Key::F9;
m_shift_keymap[0x03] = Key::F5;
m_shift_keymap[0x04] = Key::F3;
m_shift_keymap[0x05] = Key::F1;
m_shift_keymap[0x06] = Key::F2;
m_shift_keymap[0x07] = Key::F11;
m_shift_keymap[0x09] = Key::F10;
m_shift_keymap[0x0A] = Key::F8;
m_shift_keymap[0x0B] = Key::F6;
m_shift_keymap[0x0C] = Key::F4;
m_shift_keymap[0x0D] = Key::Tab;
m_shift_keymap[0x0E] = Key::Half;
m_shift_keymap[0x11] = Key::Alt;
m_shift_keymap[0x12] = Key::LeftShift;
m_shift_keymap[0x14] = Key::LeftCtrl;
m_shift_keymap[0x15] = Key::Q;
m_shift_keymap[0x16] = Key::ExclamationMark;
m_shift_keymap[0x1A] = Key::Z;
m_shift_keymap[0x1B] = Key::S;
m_shift_keymap[0x1C] = Key::A;
m_shift_keymap[0x1D] = Key::W;
m_shift_keymap[0x1E] = Key::DoubleQuote;
m_shift_keymap[0x21] = Key::C;
m_shift_keymap[0x22] = Key::X;
m_shift_keymap[0x23] = Key::D;
m_shift_keymap[0x24] = Key::E;
m_shift_keymap[0x25] = Key::Currency;
m_shift_keymap[0x26] = Key::Hashtag;
m_shift_keymap[0x29] = Key::Space;
m_shift_keymap[0x2A] = Key::V;
m_shift_keymap[0x2B] = Key::F;
m_shift_keymap[0x2C] = Key::T;
m_shift_keymap[0x2D] = Key::R;
m_shift_keymap[0x2E] = Key::Percent;
m_shift_keymap[0x31] = Key::N;
m_shift_keymap[0x32] = Key::B;
m_shift_keymap[0x33] = Key::H;
m_shift_keymap[0x34] = Key::G;
m_shift_keymap[0x35] = Key::Y;
m_shift_keymap[0x36] = Key::Ampersand;
m_shift_keymap[0x3A] = Key::M;
m_shift_keymap[0x3B] = Key::J;
m_shift_keymap[0x3C] = Key::U;
m_shift_keymap[0x3D] = Key::Slash;
m_shift_keymap[0x3E] = Key::OpenBracet;
m_shift_keymap[0x41] = Key::Semicolon;
m_shift_keymap[0x42] = Key::K;
m_shift_keymap[0x43] = Key::I;
m_shift_keymap[0x44] = Key::O;
m_shift_keymap[0x45] = Key::Equals;
m_shift_keymap[0x46] = Key::CloseBracet;
m_shift_keymap[0x49] = Key::Colon;
m_shift_keymap[0x4A] = Key::Underscore;
m_shift_keymap[0x4B] = Key::L;
m_shift_keymap[0x4C] = Key::O_Umlaut;
m_shift_keymap[0x4D] = Key::P;
m_shift_keymap[0x4E] = Key::QuestionMark;
m_shift_keymap[0x52] = Key::A_Umlaut;
m_shift_keymap[0x54] = Key::A_Ring;
m_shift_keymap[0x55] = Key::BackTick;
m_shift_keymap[0x58] = Key::CapsLock;
m_shift_keymap[0x59] = Key::RightShift;
m_shift_keymap[0x59] = Key::RightShift;
m_shift_keymap[0x5A] = Key::Enter;
m_shift_keymap[0x5B] = Key::Caret;
m_shift_keymap[0x5D] = Key::Asterix;
m_shift_keymap[0x61] = Key::GreaterThan;
m_shift_keymap[0x66] = Key::Backspace;
m_shift_keymap[0x69] = Key::Numpad1;
m_shift_keymap[0x6B] = Key::Numpad4;
m_shift_keymap[0x6C] = Key::Numpad7;
m_shift_keymap[0x70] = Key::Numpad0;
m_shift_keymap[0x71] = Key::NumpadDecimal;
m_shift_keymap[0x72] = Key::Numpad2;
m_shift_keymap[0x73] = Key::Numpad5;
m_shift_keymap[0x74] = Key::Numpad6;
m_shift_keymap[0x75] = Key::Numpad8;
m_shift_keymap[0x76] = Key::Escape;
m_shift_keymap[0x77] = Key::NumLock;
m_shift_keymap[0x78] = Key::F11;
m_shift_keymap[0x79] = Key::NumpadPlus;
m_shift_keymap[0x7A] = Key::Numpad3;
m_shift_keymap[0x7B] = Key::NumpadMinus;
m_shift_keymap[0x7C] = Key::NumpadMultiply;
m_shift_keymap[0x7D] = Key::Numpad9;
m_shift_keymap[0x83] = Key::F7;
MUST(m_altgr_keymap.resize(0xFF, Key::Invalid));
m_altgr_keymap[0x01] = Key::F9;
m_altgr_keymap[0x03] = Key::F5;
m_altgr_keymap[0x04] = Key::F3;
m_altgr_keymap[0x05] = Key::F1;
m_altgr_keymap[0x06] = Key::F2;
m_altgr_keymap[0x07] = Key::F11;
m_altgr_keymap[0x09] = Key::F10;
m_altgr_keymap[0x0A] = Key::F8;
m_altgr_keymap[0x0B] = Key::F6;
m_altgr_keymap[0x0C] = Key::F4;
m_altgr_keymap[0x0D] = Key::Tab;
m_altgr_keymap[0x0E] = Key::None;
m_altgr_keymap[0x11] = Key::Alt;
m_altgr_keymap[0x12] = Key::LeftShift;
m_altgr_keymap[0x14] = Key::LeftCtrl;
m_altgr_keymap[0x15] = Key::Q;
m_altgr_keymap[0x16] = Key::None;
m_altgr_keymap[0x1A] = Key::Z;
m_altgr_keymap[0x1B] = Key::S;
m_altgr_keymap[0x1C] = Key::A;
m_altgr_keymap[0x1D] = Key::W;
m_altgr_keymap[0x1E] = Key::AtSign;
m_altgr_keymap[0x21] = Key::C;
m_altgr_keymap[0x22] = Key::X;
m_altgr_keymap[0x23] = Key::D;
m_altgr_keymap[0x24] = Key::Euro;
m_altgr_keymap[0x25] = Key::Dollar;
m_altgr_keymap[0x26] = Key::Pound;
m_altgr_keymap[0x29] = Key::Space;
m_altgr_keymap[0x2A] = Key::V;
m_altgr_keymap[0x2B] = Key::F;
m_altgr_keymap[0x2C] = Key::T;
m_altgr_keymap[0x2D] = Key::R;
m_altgr_keymap[0x2E] = Key::None;
m_altgr_keymap[0x31] = Key::N;
m_altgr_keymap[0x32] = Key::B;
m_altgr_keymap[0x33] = Key::H;
m_altgr_keymap[0x34] = Key::G;
m_altgr_keymap[0x35] = Key::Y;
m_altgr_keymap[0x36] = Key::None;
m_altgr_keymap[0x3A] = Key::M;
m_altgr_keymap[0x3B] = Key::J;
m_altgr_keymap[0x3C] = Key::U;
m_altgr_keymap[0x3D] = Key::OpenCurlyBrace;
m_altgr_keymap[0x3E] = Key::OpenBrace;
m_altgr_keymap[0x41] = Key::None;
m_altgr_keymap[0x42] = Key::K;
m_altgr_keymap[0x43] = Key::I;
m_altgr_keymap[0x44] = Key::O;
m_altgr_keymap[0x45] = Key::CloseCurlyBrace;
m_altgr_keymap[0x46] = Key::CloseBrace;
m_altgr_keymap[0x49] = Key::None;
m_altgr_keymap[0x4A] = Key::None;
m_altgr_keymap[0x4B] = Key::L;
m_altgr_keymap[0x4C] = Key::O_Umlaut;
m_altgr_keymap[0x4D] = Key::P;
m_altgr_keymap[0x4E] = Key::BackSlash;
m_altgr_keymap[0x52] = Key::A_Umlaut;
m_altgr_keymap[0x54] = Key::A_Ring;
m_altgr_keymap[0x55] = Key::None;
m_altgr_keymap[0x58] = Key::CapsLock;
m_altgr_keymap[0x59] = Key::RightShift;
m_altgr_keymap[0x59] = Key::RightShift;
m_altgr_keymap[0x5A] = Key::Enter;
m_altgr_keymap[0x5B] = Key::Tilde;
m_altgr_keymap[0x5D] = Key::None;
m_altgr_keymap[0x61] = Key::Pipe;
m_altgr_keymap[0x66] = Key::Backspace;
m_altgr_keymap[0x69] = Key::Numpad1;
m_altgr_keymap[0x6B] = Key::Numpad4;
m_altgr_keymap[0x6C] = Key::Numpad7;
m_altgr_keymap[0x70] = Key::Numpad0;
m_altgr_keymap[0x71] = Key::NumpadDecimal;
m_altgr_keymap[0x72] = Key::Numpad2;
m_altgr_keymap[0x73] = Key::Numpad5;
m_altgr_keymap[0x74] = Key::Numpad6;
m_altgr_keymap[0x75] = Key::Numpad8;
m_altgr_keymap[0x76] = Key::Escape;
m_altgr_keymap[0x77] = Key::NumLock;
m_altgr_keymap[0x78] = Key::F11;
m_altgr_keymap[0x79] = Key::NumpadPlus;
m_altgr_keymap[0x7A] = Key::Numpad3;
m_altgr_keymap[0x7B] = Key::NumpadMinus;
m_altgr_keymap[0x7C] = Key::NumpadMultiply;
m_altgr_keymap[0x7D] = Key::Numpad9;
m_altgr_keymap[0x83] = Key::F7;
MUST(m_extended_keymap.resize(0xFF, Key::Invalid));
m_extended_keymap[0x11] = Key::AltGr;
m_extended_keymap[0x14] = Key::RightCtrl;
m_extended_keymap[0x15] = Key::MediaPrevious;
m_extended_keymap[0x1F] = Key::Super;
m_extended_keymap[0x21] = Key::VolumeUp;
m_extended_keymap[0x23] = Key::VolumeMute;
m_extended_keymap[0x2B] = Key::Calculator;
m_extended_keymap[0x32] = Key::VolumeDown;
m_extended_keymap[0x34] = Key::MediaPlayPause;
m_extended_keymap[0x3B] = Key::MediaStop;
m_extended_keymap[0x4A] = Key::NumpadDivide;
m_extended_keymap[0x4D] = Key::MediaNext;
m_extended_keymap[0x5A] = Key::NumpadEnter;
m_extended_keymap[0x69] = Key::End;
m_extended_keymap[0x6B] = Key::ArrowLeft;
m_extended_keymap[0x6C] = Key::Home;
m_extended_keymap[0x70] = Key::Insert;
m_extended_keymap[0x71] = Key::Delete;
m_extended_keymap[0x72] = Key::ArrowDown;
m_extended_keymap[0x74] = Key::ArrowRight;
m_extended_keymap[0x75] = Key::ArrowUp;
m_extended_keymap[0x7A] = Key::PageUp;
m_extended_keymap[0x7D] = Key::PageDown;
memset(m_scancode_to_keycode_normal.data(), 0xFF, m_scancode_to_keycode_normal.size());
memset(m_scancode_to_keycode_extended.data(), 0xFF, m_scancode_to_keycode_extended.size());
if (scancode_set == 1)
return initialize_scancode_set1();
if (scancode_set == 2)
return initialize_scancode_set2();
if (scancode_set == 3)
return initialize_scancode_set3();
ASSERT_NOT_REACHED();
}
Key PS2Keymap::key_for_scancode_and_modifiers(uint32_t scancode, uint8_t modifiers)
BAN::Optional<uint8_t> PS2Keymap::get_keycode(uint8_t scancode, bool extended) const
{
bool extended = scancode & 0x80000000;
scancode &= 0x7FFFFFFF;
KeyEvent dummy;
dummy.modifier = modifiers;
auto& keymap = extended ? m_extended_keymap :
dummy.shift() ? m_shift_keymap :
dummy.altgr() ? m_altgr_keymap :
m_normal_keymap;
if (scancode >= keymap.size())
return Key::Invalid;
Key key = keymap[scancode];
if (!dummy.num_lock() || dummy.shift() || dummy.ctrl() || dummy.alt())
uint8_t keycode = extended ? m_scancode_to_keycode_extended[scancode] : m_scancode_to_keycode_normal[scancode];
if (keycode == 0xFF)
{
switch (key)
dprintln("unknown {2H} {}", scancode, extended ? 'E' : ' ');
return {};
}
return keycode;
}
void PS2Keymap::initialize_scancode_set1()
{
case Key::Numpad0:
key = Key::Insert;
break;
case Key::Numpad1:
key = Key::End;
break;
case Key::Numpad2:
key = Key::ArrowDown;
break;
case Key::Numpad3:
key = Key::PageDown;
break;
case Key::Numpad4:
key = Key::ArrowLeft;
break;
case Key::Numpad5:
key = Key::None;
break;
case Key::Numpad6:
key = Key::ArrowRight;
break;
case Key::Numpad7:
key = Key::Home;
break;
case Key::Numpad8:
key = Key::ArrowUp;
break;
case Key::Numpad9:
key = Key::PageUp;
break;
case Key::NumpadDecimal:
key = Key::Delete;
break;
default:
break;
}
m_scancode_to_keycode_normal[0x29] = keycode_normal(0, 0);
m_scancode_to_keycode_normal[0x02] = keycode_normal(0, 1);
m_scancode_to_keycode_normal[0x03] = keycode_normal(0, 2);
m_scancode_to_keycode_normal[0x04] = keycode_normal(0, 3);
m_scancode_to_keycode_normal[0x05] = keycode_normal(0, 4);
m_scancode_to_keycode_normal[0x06] = keycode_normal(0, 5);
m_scancode_to_keycode_normal[0x07] = keycode_normal(0, 6);
m_scancode_to_keycode_normal[0x08] = keycode_normal(0, 7);
m_scancode_to_keycode_normal[0x09] = keycode_normal(0, 8);
m_scancode_to_keycode_normal[0x0A] = keycode_normal(0, 9);
m_scancode_to_keycode_normal[0x0B] = keycode_normal(0, 10);
m_scancode_to_keycode_normal[0x0C] = keycode_normal(0, 11);
m_scancode_to_keycode_normal[0x0D] = keycode_normal(0, 12);
m_scancode_to_keycode_normal[0x0E] = keycode_normal(0, 13);
m_scancode_to_keycode_normal[0x0F] = keycode_normal(1, 0);
m_scancode_to_keycode_normal[0x10] = keycode_normal(1, 1);
m_scancode_to_keycode_normal[0x11] = keycode_normal(1, 2);
m_scancode_to_keycode_normal[0x12] = keycode_normal(1, 3);
m_scancode_to_keycode_normal[0x13] = keycode_normal(1, 4);
m_scancode_to_keycode_normal[0x14] = keycode_normal(1, 5);
m_scancode_to_keycode_normal[0x15] = keycode_normal(1, 6);
m_scancode_to_keycode_normal[0x16] = keycode_normal(1, 7);
m_scancode_to_keycode_normal[0x17] = keycode_normal(1, 8);
m_scancode_to_keycode_normal[0x18] = keycode_normal(1, 9);
m_scancode_to_keycode_normal[0x19] = keycode_normal(1, 10);
m_scancode_to_keycode_normal[0x1A] = keycode_normal(1, 11);
m_scancode_to_keycode_normal[0x1B] = keycode_normal(1, 12);
m_scancode_to_keycode_normal[0x3A] = keycode_normal(2, 0);
m_scancode_to_keycode_normal[0x1E] = keycode_normal(2, 1);
m_scancode_to_keycode_normal[0x1F] = keycode_normal(2, 2);
m_scancode_to_keycode_normal[0x20] = keycode_normal(2, 3);
m_scancode_to_keycode_normal[0x21] = keycode_normal(2, 4);
m_scancode_to_keycode_normal[0x22] = keycode_normal(2, 5);
m_scancode_to_keycode_normal[0x23] = keycode_normal(2, 6);
m_scancode_to_keycode_normal[0x24] = keycode_normal(2, 7);
m_scancode_to_keycode_normal[0x25] = keycode_normal(2, 8);
m_scancode_to_keycode_normal[0x26] = keycode_normal(2, 9);
m_scancode_to_keycode_normal[0x27] = keycode_normal(2, 10);
m_scancode_to_keycode_normal[0x28] = keycode_normal(2, 11);
m_scancode_to_keycode_normal[0x2B] = keycode_normal(2, 12);
m_scancode_to_keycode_normal[0x1C] = keycode_normal(2, 13);
m_scancode_to_keycode_normal[0x2A] = keycode_normal(3, 0);
m_scancode_to_keycode_normal[0x56] = keycode_normal(3, 1);
m_scancode_to_keycode_normal[0x2C] = keycode_normal(3, 2);
m_scancode_to_keycode_normal[0x2D] = keycode_normal(3, 3);
m_scancode_to_keycode_normal[0x2E] = keycode_normal(3, 4);
m_scancode_to_keycode_normal[0x2F] = keycode_normal(3, 5);
m_scancode_to_keycode_normal[0x30] = keycode_normal(3, 6);
m_scancode_to_keycode_normal[0x31] = keycode_normal(3, 7);
m_scancode_to_keycode_normal[0x32] = keycode_normal(3, 8);
m_scancode_to_keycode_normal[0x33] = keycode_normal(3, 9);
m_scancode_to_keycode_normal[0x34] = keycode_normal(3, 10);
m_scancode_to_keycode_normal[0x35] = keycode_normal(3, 11);
m_scancode_to_keycode_normal[0x36] = keycode_normal(3, 12);
m_scancode_to_keycode_normal[0x1D] = keycode_normal(4, 0);
m_scancode_to_keycode_extended[0x5B] = keycode_normal(4, 1);
m_scancode_to_keycode_normal[0x38] = keycode_normal(4, 2);
m_scancode_to_keycode_normal[0x39] = keycode_normal(4, 3);
m_scancode_to_keycode_extended[0x38] = keycode_normal(4, 4);
m_scancode_to_keycode_extended[0x1D] = keycode_normal(4, 5);
m_scancode_to_keycode_normal[0x45] = keycode_numpad(0, 0);
m_scancode_to_keycode_extended[0x35] = keycode_numpad(0, 1);
m_scancode_to_keycode_normal[0x37] = keycode_numpad(0, 2);
m_scancode_to_keycode_normal[0x4A] = keycode_numpad(0, 3);
m_scancode_to_keycode_normal[0x47] = keycode_numpad(1, 0);
m_scancode_to_keycode_normal[0x48] = keycode_numpad(1, 1);
m_scancode_to_keycode_normal[0x49] = keycode_numpad(1, 2);
m_scancode_to_keycode_normal[0x4E] = keycode_numpad(1, 3);
m_scancode_to_keycode_normal[0x4B] = keycode_numpad(2, 0);
m_scancode_to_keycode_normal[0x4C] = keycode_numpad(2, 1);
m_scancode_to_keycode_normal[0x4D] = keycode_numpad(2, 2);
m_scancode_to_keycode_normal[0x4F] = keycode_numpad(3, 0);
m_scancode_to_keycode_normal[0x50] = keycode_numpad(3, 1);
m_scancode_to_keycode_normal[0x51] = keycode_numpad(3, 2);
m_scancode_to_keycode_extended[0x1C] = keycode_numpad(3, 3);
m_scancode_to_keycode_normal[0x52] = keycode_numpad(4, 0);
m_scancode_to_keycode_normal[0x53] = keycode_numpad(4, 1);
m_scancode_to_keycode_normal[0x01] = keycode_function( 0);
m_scancode_to_keycode_normal[0x3B] = keycode_function( 1);
m_scancode_to_keycode_normal[0x3C] = keycode_function( 2);
m_scancode_to_keycode_normal[0x3D] = keycode_function( 3);
m_scancode_to_keycode_normal[0x3E] = keycode_function( 4);
m_scancode_to_keycode_normal[0x3F] = keycode_function( 5);
m_scancode_to_keycode_normal[0x40] = keycode_function( 6);
m_scancode_to_keycode_normal[0x41] = keycode_function( 7);
m_scancode_to_keycode_normal[0x42] = keycode_function( 8);
m_scancode_to_keycode_normal[0x43] = keycode_function( 9);
m_scancode_to_keycode_normal[0x44] = keycode_function(10);
m_scancode_to_keycode_normal[0x57] = keycode_function(11);
m_scancode_to_keycode_normal[0x58] = keycode_function(12);
m_scancode_to_keycode_extended[0x52] = keycode_function(13);
//m_scancode_to_keycode_normal[0x] = keycode_function(14);
m_scancode_to_keycode_extended[0x53] = keycode_function(15);
m_scancode_to_keycode_extended[0x47] = keycode_function(16);
m_scancode_to_keycode_extended[0x4F] = keycode_function(17);
m_scancode_to_keycode_extended[0x49] = keycode_function(18);
m_scancode_to_keycode_extended[0x51] = keycode_function(19);
m_scancode_to_keycode_normal[0x46] = keycode_function(20);
// Arrow keys
m_scancode_to_keycode_extended[0x48] = keycode_normal(5, 0);
m_scancode_to_keycode_extended[0x4B] = keycode_normal(5, 1);
m_scancode_to_keycode_extended[0x50] = keycode_normal(5, 2);
m_scancode_to_keycode_extended[0x4D] = keycode_normal(5, 3);
}
return key;
void PS2Keymap::initialize_scancode_set2()
{
m_scancode_to_keycode_normal[0x0E] = keycode_normal(0, 0);
m_scancode_to_keycode_normal[0x16] = keycode_normal(0, 1);
m_scancode_to_keycode_normal[0x1E] = keycode_normal(0, 2);
m_scancode_to_keycode_normal[0x26] = keycode_normal(0, 3);
m_scancode_to_keycode_normal[0x25] = keycode_normal(0, 4);
m_scancode_to_keycode_normal[0x2E] = keycode_normal(0, 5);
m_scancode_to_keycode_normal[0x36] = keycode_normal(0, 6);
m_scancode_to_keycode_normal[0x3D] = keycode_normal(0, 7);
m_scancode_to_keycode_normal[0x3E] = keycode_normal(0, 8);
m_scancode_to_keycode_normal[0x46] = keycode_normal(0, 9);
m_scancode_to_keycode_normal[0x45] = keycode_normal(0, 10);
m_scancode_to_keycode_normal[0x4E] = keycode_normal(0, 11);
m_scancode_to_keycode_normal[0x55] = keycode_normal(0, 12);
m_scancode_to_keycode_normal[0x66] = keycode_normal(0, 13);
m_scancode_to_keycode_normal[0x0D] = keycode_normal(1, 0);
m_scancode_to_keycode_normal[0x15] = keycode_normal(1, 1);
m_scancode_to_keycode_normal[0x1D] = keycode_normal(1, 2);
m_scancode_to_keycode_normal[0x24] = keycode_normal(1, 3);
m_scancode_to_keycode_normal[0x2D] = keycode_normal(1, 4);
m_scancode_to_keycode_normal[0x2C] = keycode_normal(1, 5);
m_scancode_to_keycode_normal[0x35] = keycode_normal(1, 6);
m_scancode_to_keycode_normal[0x3C] = keycode_normal(1, 7);
m_scancode_to_keycode_normal[0x43] = keycode_normal(1, 8);
m_scancode_to_keycode_normal[0x44] = keycode_normal(1, 9);
m_scancode_to_keycode_normal[0x4D] = keycode_normal(1, 10);
m_scancode_to_keycode_normal[0x54] = keycode_normal(1, 11);
m_scancode_to_keycode_normal[0x5B] = keycode_normal(1, 12);
m_scancode_to_keycode_normal[0x58] = keycode_normal(2, 0);
m_scancode_to_keycode_normal[0x1C] = keycode_normal(2, 1);
m_scancode_to_keycode_normal[0x1B] = keycode_normal(2, 2);
m_scancode_to_keycode_normal[0x23] = keycode_normal(2, 3);
m_scancode_to_keycode_normal[0x2B] = keycode_normal(2, 4);
m_scancode_to_keycode_normal[0x34] = keycode_normal(2, 5);
m_scancode_to_keycode_normal[0x33] = keycode_normal(2, 6);
m_scancode_to_keycode_normal[0x3B] = keycode_normal(2, 7);
m_scancode_to_keycode_normal[0x42] = keycode_normal(2, 8);
m_scancode_to_keycode_normal[0x4B] = keycode_normal(2, 9);
m_scancode_to_keycode_normal[0x4C] = keycode_normal(2, 10);
m_scancode_to_keycode_normal[0x52] = keycode_normal(2, 11);
m_scancode_to_keycode_normal[0x5D] = keycode_normal(2, 12);
m_scancode_to_keycode_normal[0x5A] = keycode_normal(2, 13);
m_scancode_to_keycode_normal[0x12] = keycode_normal(3, 0);
m_scancode_to_keycode_normal[0x61] = keycode_normal(3, 1);
m_scancode_to_keycode_normal[0x1A] = keycode_normal(3, 2);
m_scancode_to_keycode_normal[0x22] = keycode_normal(3, 3);
m_scancode_to_keycode_normal[0x21] = keycode_normal(3, 4);
m_scancode_to_keycode_normal[0x2A] = keycode_normal(3, 5);
m_scancode_to_keycode_normal[0x32] = keycode_normal(3, 6);
m_scancode_to_keycode_normal[0x31] = keycode_normal(3, 7);
m_scancode_to_keycode_normal[0x3A] = keycode_normal(3, 8);
m_scancode_to_keycode_normal[0x41] = keycode_normal(3, 9);
m_scancode_to_keycode_normal[0x49] = keycode_normal(3, 10);
m_scancode_to_keycode_normal[0x4A] = keycode_normal(3, 11);
m_scancode_to_keycode_normal[0x59] = keycode_normal(3, 12);
m_scancode_to_keycode_normal[0x14] = keycode_normal(4, 1);
m_scancode_to_keycode_extended[0x1F] = keycode_normal(4, 2);
m_scancode_to_keycode_normal[0x11] = keycode_normal(4, 3);
m_scancode_to_keycode_normal[0x29] = keycode_normal(4, 4);
m_scancode_to_keycode_extended[0x11] = keycode_normal(4, 5);
m_scancode_to_keycode_extended[0x14] = keycode_normal(4, 6);
m_scancode_to_keycode_normal[0x77] = keycode_numpad(0, 0);
m_scancode_to_keycode_extended[0x4A] = keycode_numpad(0, 1);
m_scancode_to_keycode_normal[0x7C] = keycode_numpad(0, 2);
m_scancode_to_keycode_normal[0x7B] = keycode_numpad(0, 3);
m_scancode_to_keycode_normal[0x6C] = keycode_numpad(1, 0);
m_scancode_to_keycode_normal[0x75] = keycode_numpad(1, 1);
m_scancode_to_keycode_normal[0x7D] = keycode_numpad(1, 2);
m_scancode_to_keycode_normal[0x79] = keycode_numpad(1, 3);
m_scancode_to_keycode_normal[0x6B] = keycode_numpad(2, 0);
m_scancode_to_keycode_normal[0x73] = keycode_numpad(2, 1);
m_scancode_to_keycode_normal[0x74] = keycode_numpad(2, 2);
m_scancode_to_keycode_normal[0x69] = keycode_numpad(3, 0);
m_scancode_to_keycode_normal[0x72] = keycode_numpad(3, 1);
m_scancode_to_keycode_normal[0x7A] = keycode_numpad(3, 2);
m_scancode_to_keycode_extended[0x5A] = keycode_numpad(3, 3);
m_scancode_to_keycode_normal[0x70] = keycode_numpad(4, 0);
m_scancode_to_keycode_normal[0x71] = keycode_numpad(4, 1);
m_scancode_to_keycode_normal[0x76] = keycode_function( 0);
m_scancode_to_keycode_normal[0x05] = keycode_function( 1);
m_scancode_to_keycode_normal[0x06] = keycode_function( 2);
m_scancode_to_keycode_normal[0x04] = keycode_function( 3);
m_scancode_to_keycode_normal[0x0C] = keycode_function( 4);
m_scancode_to_keycode_normal[0x03] = keycode_function( 5);
m_scancode_to_keycode_normal[0x0B] = keycode_function( 6);
m_scancode_to_keycode_normal[0x83] = keycode_function( 7);
m_scancode_to_keycode_normal[0x0A] = keycode_function( 8);
m_scancode_to_keycode_normal[0x01] = keycode_function( 9);
m_scancode_to_keycode_normal[0x09] = keycode_function(10);
m_scancode_to_keycode_normal[0x78] = keycode_function(11);
m_scancode_to_keycode_normal[0x07] = keycode_function(12);
m_scancode_to_keycode_extended[0x70] = keycode_function(13);
//m_scancode_to_keycode_normal[0x] = keycode_function(14);
m_scancode_to_keycode_extended[0x71] = keycode_function(15);
m_scancode_to_keycode_extended[0x6C] = keycode_function(16);
m_scancode_to_keycode_extended[0x69] = keycode_function(17);
m_scancode_to_keycode_extended[0x7D] = keycode_function(18);
m_scancode_to_keycode_extended[0x7A] = keycode_function(19);
m_scancode_to_keycode_normal[0x7E] = keycode_function(20);
// Arrow keys
m_scancode_to_keycode_extended[0x75] = keycode_normal(5, 0);
m_scancode_to_keycode_extended[0x6B] = keycode_normal(5, 1);
m_scancode_to_keycode_extended[0x72] = keycode_normal(5, 2);
m_scancode_to_keycode_extended[0x74] = keycode_normal(5, 3);
}
void PS2Keymap::initialize_scancode_set3()
{
m_scancode_to_keycode_normal[0x0E] = keycode_normal(0, 0);
m_scancode_to_keycode_normal[0x16] = keycode_normal(0, 1);
m_scancode_to_keycode_normal[0x1E] = keycode_normal(0, 2);
m_scancode_to_keycode_normal[0x26] = keycode_normal(0, 3);
m_scancode_to_keycode_normal[0x25] = keycode_normal(0, 4);
m_scancode_to_keycode_normal[0x2E] = keycode_normal(0, 5);
m_scancode_to_keycode_normal[0x36] = keycode_normal(0, 6);
m_scancode_to_keycode_normal[0x3D] = keycode_normal(0, 7);
m_scancode_to_keycode_normal[0x3E] = keycode_normal(0, 8);
m_scancode_to_keycode_normal[0x46] = keycode_normal(0, 9);
m_scancode_to_keycode_normal[0x45] = keycode_normal(0, 10);
m_scancode_to_keycode_normal[0x4E] = keycode_normal(0, 11);
m_scancode_to_keycode_normal[0x55] = keycode_normal(0, 12);
m_scancode_to_keycode_normal[0x66] = keycode_normal(0, 13);
m_scancode_to_keycode_normal[0x0D] = keycode_normal(1, 0);
m_scancode_to_keycode_normal[0x15] = keycode_normal(1, 1);
m_scancode_to_keycode_normal[0x1D] = keycode_normal(1, 2);
m_scancode_to_keycode_normal[0x24] = keycode_normal(1, 3);
m_scancode_to_keycode_normal[0x2D] = keycode_normal(1, 4);
m_scancode_to_keycode_normal[0x2C] = keycode_normal(1, 5);
m_scancode_to_keycode_normal[0x35] = keycode_normal(1, 6);
m_scancode_to_keycode_normal[0x3C] = keycode_normal(1, 7);
m_scancode_to_keycode_normal[0x43] = keycode_normal(1, 8);
m_scancode_to_keycode_normal[0x44] = keycode_normal(1, 9);
m_scancode_to_keycode_normal[0x4D] = keycode_normal(1, 10);
m_scancode_to_keycode_normal[0x54] = keycode_normal(1, 11);
m_scancode_to_keycode_normal[0x5B] = keycode_normal(1, 12);
m_scancode_to_keycode_normal[0x14] = keycode_normal(2, 0);
m_scancode_to_keycode_normal[0x1C] = keycode_normal(2, 1);
m_scancode_to_keycode_normal[0x1B] = keycode_normal(2, 2);
m_scancode_to_keycode_normal[0x23] = keycode_normal(2, 3);
m_scancode_to_keycode_normal[0x2B] = keycode_normal(2, 4);
m_scancode_to_keycode_normal[0x34] = keycode_normal(2, 5);
m_scancode_to_keycode_normal[0x33] = keycode_normal(2, 6);
m_scancode_to_keycode_normal[0x3B] = keycode_normal(2, 7);
m_scancode_to_keycode_normal[0x42] = keycode_normal(2, 8);
m_scancode_to_keycode_normal[0x4B] = keycode_normal(2, 9);
m_scancode_to_keycode_normal[0x4C] = keycode_normal(2, 10);
m_scancode_to_keycode_normal[0x52] = keycode_normal(2, 11);
m_scancode_to_keycode_normal[0x5C] = keycode_normal(2, 12);
m_scancode_to_keycode_normal[0x5A] = keycode_normal(2, 13);
m_scancode_to_keycode_normal[0x12] = keycode_normal(3, 0);
m_scancode_to_keycode_normal[0x13] = keycode_normal(3, 1);
m_scancode_to_keycode_normal[0x1A] = keycode_normal(3, 2);
m_scancode_to_keycode_normal[0x22] = keycode_normal(3, 3);
m_scancode_to_keycode_normal[0x21] = keycode_normal(3, 4);
m_scancode_to_keycode_normal[0x2A] = keycode_normal(3, 5);
m_scancode_to_keycode_normal[0x32] = keycode_normal(3, 6);
m_scancode_to_keycode_normal[0x31] = keycode_normal(3, 7);
m_scancode_to_keycode_normal[0x3A] = keycode_normal(3, 8);
m_scancode_to_keycode_normal[0x41] = keycode_normal(3, 9);
m_scancode_to_keycode_normal[0x49] = keycode_normal(3, 10);
m_scancode_to_keycode_normal[0x4A] = keycode_normal(3, 11);
m_scancode_to_keycode_normal[0x59] = keycode_normal(3, 12);
m_scancode_to_keycode_normal[0x11] = keycode_normal(4, 0);
m_scancode_to_keycode_normal[0x8B] = keycode_normal(4, 1);
m_scancode_to_keycode_normal[0x19] = keycode_normal(4, 2);
m_scancode_to_keycode_normal[0x29] = keycode_normal(4, 3);
m_scancode_to_keycode_normal[0x39] = keycode_normal(4, 4);
m_scancode_to_keycode_normal[0x58] = keycode_normal(4, 5);
m_scancode_to_keycode_normal[0x76] = keycode_numpad(0, 0);
//m_scancode_to_keycode_normal[0x] = keycode_numpad(0, 1);
m_scancode_to_keycode_normal[0x7E] = keycode_numpad(0, 2);
//m_scancode_to_keycode_normal[0x] = keycode_numpad(0, 3);
m_scancode_to_keycode_normal[0x6C] = keycode_numpad(1, 1);
m_scancode_to_keycode_normal[0x75] = keycode_numpad(1, 2);
m_scancode_to_keycode_normal[0x7D] = keycode_numpad(1, 3);
m_scancode_to_keycode_normal[0x7C] = keycode_numpad(1, 4);
m_scancode_to_keycode_normal[0x6B] = keycode_numpad(2, 1);
m_scancode_to_keycode_normal[0x73] = keycode_numpad(2, 2);
m_scancode_to_keycode_normal[0x74] = keycode_numpad(2, 3);
m_scancode_to_keycode_normal[0x69] = keycode_numpad(3, 1);
m_scancode_to_keycode_normal[0x72] = keycode_numpad(3, 2);
m_scancode_to_keycode_normal[0x7A] = keycode_numpad(3, 3);
m_scancode_to_keycode_normal[0x79] = keycode_numpad(3, 4);
m_scancode_to_keycode_normal[0x70] = keycode_numpad(4, 1);
m_scancode_to_keycode_normal[0x71] = keycode_numpad(4, 2);
m_scancode_to_keycode_normal[0x08] = keycode_function(0);
m_scancode_to_keycode_normal[0x07] = keycode_function(1);
m_scancode_to_keycode_normal[0x0F] = keycode_function(2);
m_scancode_to_keycode_normal[0x17] = keycode_function(3);
m_scancode_to_keycode_normal[0x1F] = keycode_function(4);
m_scancode_to_keycode_normal[0x27] = keycode_function(5);
m_scancode_to_keycode_normal[0x2F] = keycode_function(6);
m_scancode_to_keycode_normal[0x37] = keycode_function(7);
m_scancode_to_keycode_normal[0x3F] = keycode_function(8);
m_scancode_to_keycode_normal[0x47] = keycode_function(9);
m_scancode_to_keycode_normal[0x4F] = keycode_function(10);
m_scancode_to_keycode_normal[0x56] = keycode_function(11);
m_scancode_to_keycode_normal[0x5E] = keycode_function(12);
m_scancode_to_keycode_normal[0x67] = keycode_function(13);
m_scancode_to_keycode_normal[0x57] = keycode_function(14);
m_scancode_to_keycode_normal[0x64] = keycode_function(15);
m_scancode_to_keycode_normal[0x6E] = keycode_function(16);
m_scancode_to_keycode_normal[0x65] = keycode_function(17);
m_scancode_to_keycode_normal[0x6F] = keycode_function(18);
m_scancode_to_keycode_normal[0x6D] = keycode_function(19);
m_scancode_to_keycode_normal[0x5F] = keycode_function(20);
// Arrow keys
m_scancode_to_keycode_normal[0x63] = keycode_normal(5, 0);
m_scancode_to_keycode_normal[0x61] = keycode_normal(5, 1);
m_scancode_to_keycode_normal[0x60] = keycode_normal(5, 2);
m_scancode_to_keycode_normal[0x6A] = keycode_normal(5, 3);
}
}

View File

@ -3,6 +3,7 @@
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Input/PS2/Config.h>
#include <kernel/Input/PS2/Mouse.h>
#include <kernel/Thread.h>
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
@ -25,10 +26,10 @@ namespace Kernel::Input
void PS2Mouse::send_initialize()
{
// Query extensions
append_command_queue(Command::SET_SAMPLE_RATE, 200);
append_command_queue(Command::SET_SAMPLE_RATE, 100);
append_command_queue(Command::SET_SAMPLE_RATE, 80);
append_command_queue(PS2::DeviceCommand::IDENTIFY);
append_command_queue(Command::SET_SAMPLE_RATE, 200, 0);
append_command_queue(Command::SET_SAMPLE_RATE, 100, 0);
append_command_queue(Command::SET_SAMPLE_RATE, 80, 0);
append_command_queue(PS2::DeviceCommand::IDENTIFY, 1);
}
void PS2Mouse::initialize_extensions(uint8_t byte)
@ -47,10 +48,10 @@ namespace Kernel::Input
else
{
m_mouse_id = 0x03;
append_command_queue(Command::SET_SAMPLE_RATE, 200);
append_command_queue(Command::SET_SAMPLE_RATE, 200);
append_command_queue(Command::SET_SAMPLE_RATE, 80);
append_command_queue(PS2::DeviceCommand::IDENTIFY);
append_command_queue(Command::SET_SAMPLE_RATE, 200, 0);
append_command_queue(Command::SET_SAMPLE_RATE, 200, 0);
append_command_queue(Command::SET_SAMPLE_RATE, 80, 0);
append_command_queue(PS2::DeviceCommand::IDENTIFY, 1);
}
break;
case 0x04:
@ -64,18 +65,8 @@ namespace Kernel::Input
if (m_enabled)
{
append_command_queue(Command::SET_SAMPLE_RATE, 100);
append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING);
}
}
void PS2Mouse::handle_device_command_response(uint8_t byte)
{
switch (byte)
{
default:
dwarnln("Unhandeled byte {2H}", byte);
break;
append_command_queue(Command::SET_SAMPLE_RATE, 100, 0);
append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING, 0);
}
}
@ -188,7 +179,7 @@ namespace Kernel::Input
while (true)
{
if (m_event_queue.empty())
m_semaphore.block();
TRY(Thread::current().block_or_eintr(m_semaphore));
CriticalScope _;
if (m_event_queue.empty())

View File

@ -5,6 +5,7 @@
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/IDT.h>
#include <kernel/Input/KeyboardLayout.h>
#include <kernel/InterruptController.h>
#include <kernel/LockGuard.h>
#include <kernel/Memory/FileBackedRegion.h>
@ -1253,6 +1254,17 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_load_keymap(const char* path)
{
LockGuard _(m_lock);
TRY(validate_string_access(path));
auto absolute_path = TRY(absolute_path_of(path));
TRY(Input::KeyboardLayout::get().load_from_file(absolute_path));
return 0;
}
BAN::ErrorOr<long> Process::sys_signal(int signal, void (*handler)(int))
{
if (signal < _SIGMIN || signal > _SIGMAX)

View File

@ -210,6 +210,9 @@ namespace Kernel
case SYS_CHOWN:
ret = Process::current().sys_chown((const char*)arg1, (uid_t)arg2, (gid_t)arg3);
break;
case SYS_LOAD_KEYMAP:
ret = Process::current().sys_load_keymap((const char*)arg1);
break;
default:
dwarnln("Unknown syscall {}", syscall);
break;

View File

@ -127,12 +127,13 @@ namespace Kernel
if (event.released())
return;
const char* ansi_c_str = Input::key_event_to_utf8(event);
Input::Key key = Input::key_event_to_key(event);
const char* ansi_c_str = Input::key_to_utf8(key, event.modifier);
if (event.ctrl())
{
ansi_c_str = nullptr;
switch (event.key)
switch (key)
{
case Input::Key::A: ansi_c_str = "\x01"; break;
case Input::Key::B: ansi_c_str = "\x02"; break;
@ -165,7 +166,7 @@ namespace Kernel
}
else
{
switch (event.key)
switch (key)
{
case Input::Key::Enter:
case Input::Key::NumpadEnter:
@ -322,11 +323,11 @@ namespace Kernel
uint32_t depth = m_lock.lock_depth();
for (uint32_t i = 0; i < depth; i++)
m_lock.unlock();
bool eintr = Thread::current().block_or_eintr(m_output.semaphore);
auto eintr = Thread::current().block_or_eintr(m_output.semaphore);
for (uint32_t i = 0; i < depth; i++)
m_lock.lock();
if (eintr)
return BAN::Error::from_errno(EINTR);
if (eintr.is_error())
return eintr.release_error();
}
if (m_output.bytes == 0)

View File

@ -343,12 +343,14 @@ namespace Kernel
return false;
}
bool Thread::block_or_eintr(Semaphore& semaphore)
BAN::ErrorOr<void> Thread::block_or_eintr(Semaphore& semaphore)
{
if (is_interrupted_by_signal())
return true;
return BAN::Error::from_errno(EINTR);
semaphore.block();
return is_interrupted_by_signal();
if (is_interrupted_by_signal())
return BAN::Error::from_errno(EINTR);
return {};
}
void Thread::validate_stack() const

View File

@ -8,6 +8,7 @@
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/GDT.h>
#include <kernel/IDT.h>
#include <kernel/Input/KeyboardLayout.h>
#include <kernel/Input/PS2/Controller.h>
#include <kernel/InterruptController.h>
#include <kernel/kprint.h>
@ -176,12 +177,19 @@ static void init2(void*)
DevFileSystem::get().initialize_device_updater();
#if 0
dprintln("sleeping for 5 seconds");
SystemTimer::get().sleep(5000);
#endif
PCI::PCIManager::initialize();
dprintln("PCI initialized");
VirtualFileSystem::initialize(cmdline.root);
dprintln("VFS initialized");
// Initialize empty keymap
MUST(Input::KeyboardLayout::initialize());
if (auto res = PS2Controller::initialize(); res.is_error())
dprintln("{}", res.error());

View File

@ -34,6 +34,8 @@ return value: 0 on success, -1 on failure and errno set to the error
int tty_ctrl(int fildes, int command, int flags);
int poweroff(int command);
int load_keymap(const char* path);
__END_DECLS
#endif

View File

@ -62,6 +62,7 @@ __BEGIN_DECLS
#define SYS_MSYNC 61
#define SYS_PREAD 62
#define SYS_CHOWN 63
#define SYS_LOAD_KEYMAP 64
__END_DECLS

View File

@ -11,3 +11,8 @@ int poweroff(int command)
{
return syscall(SYS_POWEROFF, command);
}
int load_keymap(const char* path)
{
return syscall(SYS_LOAD_KEYMAP, path);
}

View File

@ -8,6 +8,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/banan-os.h>
#include <termios.h>
void initialize_stdio()
@ -25,6 +26,9 @@ int main()
if (signal(SIGINT, [](int) {}) == SIG_ERR)
perror("signal");
if (load_keymap("/usr/share/keymaps/fi.keymap") == -1)
perror("load_keymap");
bool first = true;
termios termios;