kernel: Add a keyboard device for graphical session
This commit is contained in:
parent
9c1e275f34
commit
4794d0dfef
@ -61,6 +61,7 @@ set(SOURCES
|
||||
src/fs/devices/FramebufferDevice.cpp
|
||||
src/fs/devices/UARTDevice.cpp
|
||||
src/fs/devices/MouseDevice.cpp
|
||||
src/fs/devices/KeyboardDevice.cpp
|
||||
src/fs/InitRD.cpp
|
||||
src/binfmt/ELF.cpp
|
||||
src/binfmt/BinaryFormat.cpp
|
||||
|
131
kernel/src/api/Keyboard.h
Normal file
131
kernel/src/api/Keyboard.h
Normal file
@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
#include <luna/Types.h>
|
||||
|
||||
namespace moon
|
||||
{
|
||||
enum KeyCode : u8
|
||||
{
|
||||
// Function keys
|
||||
K_F1,
|
||||
K_F2,
|
||||
K_F3,
|
||||
K_F4,
|
||||
K_F5,
|
||||
K_F6,
|
||||
K_F7,
|
||||
K_F8,
|
||||
K_F9,
|
||||
K_F10,
|
||||
K_F11,
|
||||
K_F12,
|
||||
// System keys
|
||||
K_Esc,
|
||||
K_PrtScr,
|
||||
K_Pause,
|
||||
K_Super,
|
||||
K_Menu,
|
||||
// Modifier keys
|
||||
K_LeftShift,
|
||||
K_RightShift,
|
||||
K_LeftAlt,
|
||||
K_RightAlt, // or AltGr on some keyboards
|
||||
K_LeftControl,
|
||||
K_RightControl,
|
||||
// Navigation keys
|
||||
K_Tab,
|
||||
K_Home,
|
||||
K_End,
|
||||
K_PageUp,
|
||||
K_PageDown,
|
||||
K_RightArrow,
|
||||
K_LeftArrow,
|
||||
K_UpArrow,
|
||||
K_DownArrow,
|
||||
// Editing keys
|
||||
K_Backspace,
|
||||
K_Enter,
|
||||
K_Insert,
|
||||
K_Delete,
|
||||
K_KeypadEnter,
|
||||
// Lock keys
|
||||
K_ScrollLock,
|
||||
K_CapsLock,
|
||||
K_NumLock,
|
||||
// Keypad keys
|
||||
K_Keypad0,
|
||||
K_Keypad1,
|
||||
K_Keypad2,
|
||||
K_Keypad3,
|
||||
K_Keypad4,
|
||||
K_Keypad5,
|
||||
K_Keypad6,
|
||||
K_Keypad7,
|
||||
K_Keypad8,
|
||||
K_Keypad9,
|
||||
K_KeypadDot,
|
||||
K_KeypadPlus,
|
||||
K_KeypadMinus,
|
||||
K_KeypadMul,
|
||||
K_KeypadDiv,
|
||||
// Character keys (depending on keyboard layout), examples in US QWERTY
|
||||
K_CH00, // `
|
||||
K_CH01, // 1
|
||||
K_CH02, // 2
|
||||
K_CH03, // 3
|
||||
K_CH04, // 4
|
||||
K_CH05, // 5
|
||||
K_CH06, // 6
|
||||
K_CH07, // 7
|
||||
K_CH08, // 8
|
||||
K_CH09, // 9
|
||||
K_CH10, // 0
|
||||
K_CH11, // -
|
||||
K_CH12, // =
|
||||
K_CH13, // Q
|
||||
K_CH14, // W
|
||||
K_CH15, // E
|
||||
K_CH16, // R
|
||||
K_CH17, // T
|
||||
K_CH18, // Y
|
||||
K_CH19, // U
|
||||
K_CH20, // I
|
||||
K_CH21, // O
|
||||
K_CH22, // P
|
||||
K_CH23, // [
|
||||
K_CH24, // ]
|
||||
K_CH25, // A
|
||||
K_CH26, // S
|
||||
K_CH27, // D
|
||||
K_CH28, // F
|
||||
K_CH29, // G
|
||||
K_CH30, // H
|
||||
K_CH31, // J
|
||||
K_CH32, // K
|
||||
K_CH33, // L
|
||||
K_CH34, // ;
|
||||
K_CH35, // '
|
||||
K_CH36, // #
|
||||
K_CH37, // Backslash
|
||||
K_CH38, // Z
|
||||
K_CH39, // X
|
||||
K_CH40, // C
|
||||
K_CH41, // V
|
||||
K_CH42, // B
|
||||
K_CH43, // N
|
||||
K_CH44, // M
|
||||
K_CH45, // ,
|
||||
K_CH46, // .
|
||||
K_CH47, // /
|
||||
K_CH48, // Space
|
||||
// Unknown key
|
||||
K_Unknown,
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] KeyboardPacket
|
||||
{
|
||||
u8 key;
|
||||
bool released;
|
||||
};
|
||||
|
||||
static_assert(sizeof(KeyboardPacket) == 2);
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
#include "api/Keyboard.h"
|
||||
#include <luna/Option.h>
|
||||
|
||||
namespace Keyboard
|
||||
{
|
||||
struct KeyboardState
|
||||
struct TTYKeyboardState
|
||||
{
|
||||
bool ignore_next { false };
|
||||
bool left_shift { false };
|
||||
@ -12,5 +13,12 @@ namespace Keyboard
|
||||
bool capslock { false };
|
||||
};
|
||||
|
||||
Option<char> decode_scancode_tty(u8 scancode, KeyboardState& state);
|
||||
struct KeyboardState
|
||||
{
|
||||
bool ignore_next { false };
|
||||
};
|
||||
|
||||
Option<char> decode_scancode_tty(u8 scancode, TTYKeyboardState& state);
|
||||
|
||||
Option<moon::KeyboardPacket> decode_scancode(u8 scancode, KeyboardState& state);
|
||||
}
|
||||
|
@ -113,7 +113,71 @@ constexpr char shifted_key_table[] = {
|
||||
'.', // keypad .
|
||||
};
|
||||
|
||||
static bool is_shifted(const Keyboard::KeyboardState& state)
|
||||
using namespace moon;
|
||||
|
||||
constexpr KeyCode keycode_table[] = {
|
||||
K_Unknown, K_Esc,
|
||||
K_CH01, // 1
|
||||
K_CH02, // 2
|
||||
K_CH03, // 3
|
||||
K_CH04, // 4
|
||||
K_CH05, // 5
|
||||
K_CH06, // 6
|
||||
K_CH07, // 7
|
||||
K_CH08, // 8
|
||||
K_CH09, // 9
|
||||
K_CH10, // 0
|
||||
K_CH11, // -
|
||||
K_CH12, // =
|
||||
K_Backspace, K_Tab,
|
||||
K_CH13, // Q
|
||||
K_CH14, // W
|
||||
K_CH15, // E
|
||||
K_CH16, // R
|
||||
K_CH17, // T
|
||||
K_CH18, // Y
|
||||
K_CH19, // U
|
||||
K_CH20, // I
|
||||
K_CH21, // O
|
||||
K_CH22, // P
|
||||
K_CH23, // [
|
||||
K_CH24, // ]
|
||||
K_Enter, K_LeftControl,
|
||||
K_CH25, // A
|
||||
K_CH26, // S
|
||||
K_CH27, // D
|
||||
K_CH28, // F
|
||||
K_CH29, // G
|
||||
K_CH30, // H
|
||||
K_CH31, // J
|
||||
K_CH32, // K
|
||||
K_CH33, // L
|
||||
K_CH34, // ;
|
||||
K_CH35, // '
|
||||
K_CH00, // `
|
||||
K_LeftShift,
|
||||
K_CH36, // #
|
||||
K_CH38, // Z
|
||||
K_CH39, // X
|
||||
K_CH40, // C
|
||||
K_CH41, // V
|
||||
K_CH42, // B
|
||||
K_CH43, // N
|
||||
K_CH44, // M
|
||||
K_CH45, // ,
|
||||
K_CH46, // .
|
||||
K_CH47, // /
|
||||
K_RightShift, K_KeypadMul, K_LeftAlt,
|
||||
K_CH48, // Space
|
||||
K_CapsLock, K_F1, K_F2, K_F3, K_F4, K_F5, K_F6,
|
||||
K_F7, K_F8, K_F9, K_F10, K_NumLock, K_ScrollLock, K_Keypad7,
|
||||
K_Keypad8, K_Keypad9, K_KeypadMinus, K_Keypad4, K_Keypad5, K_Keypad6, K_KeypadPlus,
|
||||
K_Keypad1, K_Keypad2, K_Keypad3, K_Keypad0, K_KeypadDot, K_Unknown, K_Unknown,
|
||||
K_CH37, // Backslash
|
||||
K_F11, K_F12,
|
||||
};
|
||||
|
||||
static bool is_shifted(const Keyboard::TTYKeyboardState& state)
|
||||
{
|
||||
if (state.capslock) return !(state.left_shift || state.right_shift);
|
||||
return state.left_shift || state.right_shift;
|
||||
@ -121,7 +185,7 @@ static bool is_shifted(const Keyboard::KeyboardState& state)
|
||||
|
||||
namespace Keyboard
|
||||
{
|
||||
Option<char> decode_scancode_tty(u8 scancode, KeyboardState& state)
|
||||
Option<char> decode_scancode_tty(u8 scancode, TTYKeyboardState& state)
|
||||
{
|
||||
if (state.ignore_next)
|
||||
{
|
||||
@ -184,4 +248,24 @@ namespace Keyboard
|
||||
if (is_shifted(state)) return shifted_key_table[scancode];
|
||||
return key_table[scancode];
|
||||
}
|
||||
|
||||
Option<KeyboardPacket> decode_scancode(u8 scancode, KeyboardState& state)
|
||||
{
|
||||
if (state.ignore_next)
|
||||
{
|
||||
state.ignore_next = false;
|
||||
return {};
|
||||
}
|
||||
|
||||
// FIXME: Support extended scancodes.
|
||||
if (scancode == EXTENDED_KEY_CODE)
|
||||
{
|
||||
state.ignore_next = true;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool released = is_key_released(scancode);
|
||||
|
||||
return KeyboardPacket { keycode_table[scancode], released };
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "fs/devices/ConsoleDevice.h"
|
||||
#include "Log.h"
|
||||
#include "fs/devices/DeviceRegistry.h"
|
||||
#include "fs/devices/KeyboardDevice.h"
|
||||
#include "memory/MemoryManager.h"
|
||||
#include "thread/Scheduler.h"
|
||||
#include "video/TextConsole.h"
|
||||
@ -61,7 +62,7 @@ Result<usize> ConsoleDevice::write(const u8* buf, usize, usize length)
|
||||
{
|
||||
if (m_settings.c_lflag & TOSTOP) TRY(handle_background_process_group(true, SIGTTOU));
|
||||
|
||||
if (s_is_in_graphical_mode) return length;
|
||||
// if (s_is_in_graphical_mode) return length;
|
||||
|
||||
TextConsole::write((const char*)buf, length);
|
||||
return length;
|
||||
@ -74,7 +75,14 @@ bool ConsoleDevice::will_block_if_read() const
|
||||
|
||||
void ConsoleDevice::did_press_or_release_key(u8 scancode)
|
||||
{
|
||||
if (!s_is_in_graphical_mode)
|
||||
for (const auto& device : m_console_devices) { device->process_key_event(scancode); }
|
||||
else
|
||||
{
|
||||
static Keyboard::KeyboardState state = {};
|
||||
auto packet = Keyboard::decode_scancode(scancode, state);
|
||||
if (packet.has_value()) KeyboardDevice::add_keyboard_event(packet.release_value());
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleDevice::process_key_event(u8 scancode)
|
||||
|
@ -37,7 +37,7 @@ class ConsoleDevice : public Device
|
||||
mutable Buffer m_input_buffer;
|
||||
Option<pid_t> m_foreground_process_group {};
|
||||
Vector<u8> m_line_buffer;
|
||||
mutable Keyboard::KeyboardState m_kb_state;
|
||||
mutable Keyboard::TTYKeyboardState m_kb_state;
|
||||
|
||||
static Vector<SharedPtr<ConsoleDevice>> m_console_devices;
|
||||
static bool s_is_in_graphical_mode;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "fs/devices/ConsoleDevice.h"
|
||||
#include "fs/devices/FramebufferDevice.h"
|
||||
#include "fs/devices/FullDevice.h"
|
||||
#include "fs/devices/KeyboardDevice.h"
|
||||
#include "fs/devices/MouseDevice.h"
|
||||
#include "fs/devices/NullDevice.h"
|
||||
#include "fs/devices/UARTDevice.h"
|
||||
@ -72,6 +73,7 @@ namespace DeviceRegistry
|
||||
FramebufferDevice::create();
|
||||
UARTDevice::create();
|
||||
MouseDevice::create();
|
||||
KeyboardDevice::create();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
34
kernel/src/fs/devices/KeyboardDevice.cpp
Normal file
34
kernel/src/fs/devices/KeyboardDevice.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "fs/devices/KeyboardDevice.h"
|
||||
|
||||
SharedPtr<KeyboardDevice> KeyboardDevice::s_keyboard_device = {};
|
||||
|
||||
Result<void> KeyboardDevice::create()
|
||||
{
|
||||
auto device = TRY(make_shared<KeyboardDevice>());
|
||||
s_keyboard_device = device;
|
||||
return DeviceRegistry::register_special_device(DeviceRegistry::Input, 1, device, 0600);
|
||||
}
|
||||
|
||||
Result<usize> KeyboardDevice::read(u8* buf, usize, usize length) const
|
||||
{
|
||||
length = m_packet_buffer.dequeue_data(buf, length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
Result<usize> KeyboardDevice::write(const u8* buf, usize, usize length)
|
||||
{
|
||||
TRY(m_packet_buffer.append_data(buf, length));
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void KeyboardDevice::add_keyboard_event(const moon::KeyboardPacket& packet)
|
||||
{
|
||||
if (s_keyboard_device) s_keyboard_device->write((const u8*)&packet, 0, sizeof(packet));
|
||||
}
|
||||
|
||||
bool KeyboardDevice::will_block_if_read() const
|
||||
{
|
||||
return !m_packet_buffer.size();
|
||||
}
|
31
kernel/src/fs/devices/KeyboardDevice.h
Normal file
31
kernel/src/fs/devices/KeyboardDevice.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "api/Keyboard.h"
|
||||
#include "fs/devices/DeviceRegistry.h"
|
||||
#include <luna/Buffer.h>
|
||||
|
||||
class KeyboardDevice : public Device
|
||||
{
|
||||
public:
|
||||
// Initializer for DeviceRegistry.
|
||||
static Result<void> create();
|
||||
|
||||
Result<usize> read(u8*, usize, usize) const override;
|
||||
|
||||
Result<usize> write(const u8*, usize, usize) override;
|
||||
|
||||
static void add_keyboard_event(const moon::KeyboardPacket& packet);
|
||||
|
||||
bool will_block_if_read() const override;
|
||||
|
||||
StringView device_path() const override
|
||||
{
|
||||
return "kbd";
|
||||
}
|
||||
|
||||
virtual ~KeyboardDevice() = default;
|
||||
|
||||
private:
|
||||
mutable Buffer m_packet_buffer;
|
||||
|
||||
static SharedPtr<KeyboardDevice> s_keyboard_device;
|
||||
};
|
Loading…
Reference in New Issue
Block a user