diff --git a/kernel/include/kernel/Input/InputDevice.h b/kernel/include/kernel/Input/InputDevice.h index 6404a69e..a93fa03b 100644 --- a/kernel/include/kernel/Input/InputDevice.h +++ b/kernel/include/kernel/Input/InputDevice.h @@ -61,6 +61,7 @@ namespace Kernel { public: static BAN::ErrorOr> create(mode_t mode, uid_t uid, gid_t gid); + static BAN::ErrorOr initialize_tty_thread(); void notify(); diff --git a/kernel/kernel/Input/InputDevice.cpp b/kernel/kernel/Input/InputDevice.cpp index 76b9f868..bafa632f 100644 --- a/kernel/kernel/Input/InputDevice.cpp +++ b/kernel/kernel/Input/InputDevice.cpp @@ -1,7 +1,10 @@ +#include + #include #include #include #include +#include #include #include @@ -24,6 +27,10 @@ namespace Kernel static SpinLock s_joystick_lock; static BAN::Vector> s_joysticks; + static SpinLock s_tty_keyboard_event_lock; + static ThreadBlocker s_tty_keyboard_event_blocker; + static BAN::CircularQueue s_tty_keyboard_events; + static const char* get_name_format(InputDevice::Type type) { switch (type) @@ -201,6 +208,15 @@ namespace Kernel break; } } + + if (TTY::current()->should_receive_input()) + { + SpinLockGuard _(s_tty_keyboard_event_lock); + if (!s_tty_keyboard_events.full()) + s_tty_keyboard_events.push(key_event); + s_tty_keyboard_event_blocker.unblock(); + return; + } } if (m_event_count == m_max_event_count) @@ -261,6 +277,41 @@ namespace Kernel } + static void tty_keyboard_thread(void*) + { + static BAN::Atomic initialized = false; + [[maybe_unused]] bool old_initialized = initialized.exchange(true); + ASSERT(old_initialized == false); + + for (;;) + { + LibInput::RawKeyEvent event; + + { + SpinLockGuard guard(s_tty_keyboard_event_lock); + + if (s_tty_keyboard_events.empty()) + { + SpinLockGuardAsMutex smutex(guard); + s_tty_keyboard_event_blocker.block_indefinite(&smutex); + continue; + } + + event = s_tty_keyboard_events.front(); + s_tty_keyboard_events.pop(); + } + + TTY::current()->on_key_event(event); + } + } + + BAN::ErrorOr KeyboardDevice::initialize_tty_thread() + { + auto* thread = TRY(Thread::create_kernel(tty_keyboard_thread, nullptr)); + ASSERT(thread); + TRY(Processor::scheduler().add_thread(thread)); + return {}; + } BAN::ErrorOr> KeyboardDevice::create(mode_t mode, uid_t uid, gid_t gid) { diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index 0f534c66..44c3ce14 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -117,40 +118,9 @@ namespace Kernel return {}; } - void TTY::keyboard_task(void*) - { - BAN::RefPtr keyboard_inode; - if (auto ret = DevFileSystem::get().root_inode()->find_inode("keyboard"_sv); !ret.is_error()) - keyboard_inode = ret.release_value(); - else - { - dprintln("could not open keyboard device: {}", ret.error()); - return; - } - - while (true) - { - while (TTY::current()->m_tty_ctrl.receive_input) - { - if (!keyboard_inode->can_read()) - { - SystemTimer::get().sleep_ms(1); - continue; - } - - LibInput::RawKeyEvent event; - [[maybe_unused]] const size_t read = MUST(keyboard_inode->read(0, BAN::ByteSpan::from(event))); - ASSERT(read == sizeof(event)); - - TTY::current()->on_key_event(LibInput::KeyboardLayout::get().key_event_from_raw(event)); - } - } - } - void TTY::initialize_devices() { - auto* thread = MUST(Thread::create_kernel(&TTY::keyboard_task, nullptr)); - MUST(Processor::scheduler().add_thread(thread)); + MUST(KeyboardDevice::initialize_tty_thread()); DevFileSystem::get().add_inode("tty", MUST(DevTTY::create(0666, 0, 0))); } @@ -268,7 +238,7 @@ namespace Kernel if (ch == _POSIX_VDISABLE) return; - LockGuard _0(m_mutex); + LockGuard _(m_mutex); const auto termios = get_termios();