From 8ff9c030bff876821f3365913fafab77a1559626 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 30 May 2025 22:10:39 +0300 Subject: [PATCH] Kernel: Add better termios support I'm not sure if this is correct but at least it's better than before :) --- BAN/include/BAN/Debug.h | 6 +-- kernel/include/kernel/Terminal/TTY.h | 2 +- kernel/kernel/Terminal/PseudoTerminal.cpp | 10 ++++- kernel/kernel/Terminal/Serial.cpp | 12 ++++-- kernel/kernel/Terminal/TTY.cpp | 51 ++++++++++++++++------- kernel/kernel/Terminal/VirtualTTY.cpp | 10 ++++- 6 files changed, 67 insertions(+), 24 deletions(-) diff --git a/BAN/include/BAN/Debug.h b/BAN/include/BAN/Debug.h index c0fd529a43..2c9e656c3f 100644 --- a/BAN/include/BAN/Debug.h +++ b/BAN/include/BAN/Debug.h @@ -14,7 +14,7 @@ #define dprintln(...) \ do { \ BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \ - BAN::Formatter::print(__debug_putchar,"\r\n"); \ + BAN::Formatter::print(__debug_putchar,"\n"); \ fflush(stddbg); \ } while (false) @@ -22,7 +22,7 @@ do { \ BAN::Formatter::print(__debug_putchar, "\e[33m"); \ BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \ - BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \ + BAN::Formatter::print(__debug_putchar, "\e[m\n"); \ fflush(stddbg); \ } while(false) @@ -30,7 +30,7 @@ do { \ BAN::Formatter::print(__debug_putchar, "\e[31m"); \ BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \ - BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \ + BAN::Formatter::print(__debug_putchar, "\e[m\n"); \ fflush(stddbg); \ } while(false) diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index f1078ab99e..77ba288cb2 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -57,7 +57,7 @@ namespace Kernel virtual bool has_hungup_impl() const override { return false; } protected: - TTY(mode_t mode, uid_t uid, gid_t gid); + TTY(termios termios, mode_t mode, uid_t uid, gid_t gid); virtual bool putchar_impl(uint8_t ch) = 0; virtual void update_cursor() {} diff --git a/kernel/kernel/Terminal/PseudoTerminal.cpp b/kernel/kernel/Terminal/PseudoTerminal.cpp index 0e4e463296..79f71c1744 100644 --- a/kernel/kernel/Terminal/PseudoTerminal.cpp +++ b/kernel/kernel/Terminal/PseudoTerminal.cpp @@ -158,7 +158,15 @@ namespace Kernel } PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid) - : TTY(mode, uid, gid) + : TTY({ + .c_iflag = 0, + .c_oflag = 0, + .c_cflag = CS8, + .c_lflag = ECHO | ICANON, + .c_cc = {}, + .c_ospeed = B38400, + .c_ispeed = B38400, + }, mode, uid, gid) , m_name(BAN::move(name)) , m_number(number) {} diff --git a/kernel/kernel/Terminal/Serial.cpp b/kernel/kernel/Terminal/Serial.cpp index bcc68831eb..b6bec3d9c2 100644 --- a/kernel/kernel/Terminal/Serial.cpp +++ b/kernel/kernel/Terminal/Serial.cpp @@ -170,7 +170,15 @@ namespace Kernel } SerialTTY::SerialTTY(Serial serial) - : TTY(0600, 0, 0) + : TTY({ + .c_iflag = ICRNL, + .c_oflag = OPOST | ONLCR, + .c_cflag = CS8, + .c_lflag = ECHO | ICANON, + .c_cc = {}, + .c_ospeed = B38400, + .c_ispeed = B38400, + }, 0600, 0, 0) , m_name(MUST(BAN::String::formatted("ttyS{}", s_next_tty_number++))) , m_serial(serial) {} @@ -235,8 +243,6 @@ namespace Kernel while (!m_input.empty()) { *ptr = m_input.front(); - if (*ptr == '\r') - *ptr = '\n'; m_input.pop(); ptr++; } diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index 230376b187..33f7c94871 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -66,18 +66,11 @@ namespace Kernel return makedev(DeviceNumber::TTY, s_minor++); } - TTY::TTY(mode_t mode, uid_t uid, gid_t gid) + TTY::TTY(termios termios, mode_t mode, uid_t uid, gid_t gid) : CharacterDevice(mode, uid, gid) + , m_termios(termios) , m_rdev(next_tty_rdev()) - { - // FIXME: add correct baud and flags - m_termios.c_iflag = 0; - m_termios.c_oflag = 0; - m_termios.c_cflag = CS8; - m_termios.c_lflag = ECHO | ICANON; - m_termios.c_ospeed = B38400; - m_termios.c_ispeed = B38400; - } + { } BAN::RefPtr TTY::current() { @@ -228,6 +221,17 @@ namespace Kernel LockGuard _(m_mutex); + if ((m_termios.c_iflag & ISTRIP)) + ch &= 0x7F; + if ((m_termios.c_iflag & IGNCR) && ch == '\r') + return; + uint8_t conv = ch; + if ((m_termios.c_iflag & ICRNL) && ch == '\r') + conv = '\n'; + if ((m_termios.c_iflag & INLCR) && ch == '\n') + conv = '\r'; + ch = conv; + // ^C if (ch == '\x03') { @@ -252,6 +256,10 @@ namespace Kernel return; } + // FIXME: don't ignore these bytes + if (m_output.bytes >= m_output.buffer.size()) + return; + m_output.buffer[m_output.bytes++] = ch; if (m_termios.c_lflag & ECHO) @@ -280,7 +288,7 @@ namespace Kernel } } - if (ch == '\n' || !(m_termios.c_lflag & ICANON)) + if (ch == '\n' || !(m_termios.c_lflag & ICANON) || m_output.bytes == m_output.buffer.size()) { m_output.flush = true; epoll_notify(EPOLLIN); @@ -334,9 +342,16 @@ namespace Kernel bool TTY::putchar(uint8_t ch) { SpinLockGuard _(m_write_lock); - if (m_tty_ctrl.draw_graphics) - return putchar_impl(ch); - return true; + if (!m_tty_ctrl.draw_graphics) + return true; + if (m_termios.c_oflag & OPOST) + { + if ((m_termios.c_oflag & ONLCR) && ch == '\n') + return putchar_impl('\r') && putchar_impl('\n'); + if ((m_termios.c_oflag & OCRNL) && ch == '\r') + return putchar_impl('\n'); + } + return putchar_impl(ch); } BAN::ErrorOr TTY::read_impl(off_t, BAN::ByteSpan buffer) @@ -353,7 +368,13 @@ namespace Kernel return 0; } - size_t to_copy = BAN::Math::min(buffer.size(), m_output.bytes); + const size_t max_to_copy = BAN::Math::min(buffer.size(), m_output.bytes); + size_t to_copy = max_to_copy; + if (m_termios.c_lflag & ICANON) + for (to_copy = 1; to_copy < max_to_copy; to_copy++) + if (m_output.buffer[to_copy - 1] == '\n') + break; + memcpy(buffer.data(), m_output.buffer.data(), to_copy); memmove(m_output.buffer.data(), m_output.buffer.data() + to_copy, m_output.bytes - to_copy); diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index 29b3aeb3ca..8bf3a572a1 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -36,7 +36,15 @@ namespace Kernel } VirtualTTY::VirtualTTY(BAN::RefPtr driver) - : TTY(0600, 0, 0) + : TTY({ + .c_iflag = 0, + .c_oflag = 0, + .c_cflag = CS8, + .c_lflag = ECHO | ICANON, + .c_cc = {}, + .c_ospeed = B38400, + .c_ispeed = B38400, + }, 0600, 0, 0) , m_name(MUST(BAN::String::formatted("tty{}", s_next_tty_number++))) , m_terminal_driver(driver) , m_palette(driver->palette())