#include "fs/devices/ConsoleDevice.h" #include "arch/Keyboard.h" #include "memory/MemoryManager.h" #include "video/TextConsole.h" #include #include #include #include static Buffer g_console_input; static bool g_eof { false }; static bool g_echo { true }; Result> ConsoleDevice::create() { return (SharedPtr)TRY(make_shared()); } Result ConsoleDevice::read(u8* buf, usize, usize length) const { if (length > g_console_input.size()) length = g_console_input.size(); memcpy(buf, g_console_input.data(), length); memmove(g_console_input.data(), g_console_input.data() + length, g_console_input.size() - length); g_console_input.try_resize(g_console_input.size() - length).release_value(); if (!length && g_eof) g_eof = false; return length; } Result ConsoleDevice::write(const u8* buf, usize, usize length) { TextConsole::write((const char*)buf, length); return length; } bool ConsoleDevice::blocking() const { return g_eof ? false : g_console_input.size() == 0; } static Vector g_temp_input; void ConsoleDevice::did_press_key(char key) { if (key == '\b') { if (g_temp_input.try_pop().has_value()) { if (g_echo) TextConsole::putwchar(L'\b'); } return; } // Ctrl+D if (key == 'd' && (Keyboard::modifiers() & Keyboard::LeftControl)) { if (g_temp_input.size() == 0) g_eof = true; return; } g_temp_input.try_append((u8)key).value(); if (key == '\n') { g_console_input.append_data(g_temp_input.data(), g_temp_input.size()).value(); g_temp_input.clear(); } if (!g_echo) return; TextConsole::putchar(key); } Result ConsoleDevice::ioctl(int request, void* arg) { switch (request) { case TCGETS: { struct termios tc { .c_lflag = 0 }; if (g_echo) tc.c_lflag |= ECHO; return MemoryManager::copy_to_user_typed((struct termios*)arg, &tc) ? 0 : err(EFAULT); } case TCSETS: { struct termios tc; if (!MemoryManager::copy_from_user_typed((const struct termios*)arg, &tc)) return err(EFAULT); if (tc.c_lflag & ECHO) g_echo = true; else g_echo = false; return 0; } default: return err(EINVAL); } }