From b30af0edcae2032f8a3f89414d8f06a1aac4cfb2 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 7 Sep 2023 15:06:27 +0300 Subject: [PATCH] Kernel: TTY now reads input byte by byte This allows correct behaviour for character streams / keyboard handling. Serial input can now send working ^C :D --- kernel/include/kernel/Terminal/TTY.h | 2 +- kernel/kernel/Terminal/Serial.cpp | 8 +- kernel/kernel/Terminal/TTY.cpp | 127 ++++++++++----------------- 3 files changed, 55 insertions(+), 82 deletions(-) diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index f67186c2..43040297 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -29,7 +29,7 @@ namespace Kernel static void initialize_devices(); void on_key_event(Input::KeyEvent); - void handle_input(const uint8_t* ch); + void handle_input_byte(uint8_t); virtual bool is_tty() const override { return true; } diff --git a/kernel/kernel/Terminal/Serial.cpp b/kernel/kernel/Terminal/Serial.cpp index 0274247f..46490c4f 100644 --- a/kernel/kernel/Terminal/Serial.cpp +++ b/kernel/kernel/Terminal/Serial.cpp @@ -244,12 +244,13 @@ namespace Kernel if (m_serial.port() != COM1_PORT && m_serial.port() != COM2_PORT) return; + static uint8_t buffer[128]; + auto update_com = [&](auto& device, auto& input_queue) { if (input_queue.empty()) return; - uint8_t buffer[128]; uint8_t* ptr = buffer; while (!input_queue.empty()) { @@ -262,7 +263,10 @@ namespace Kernel ptr++; } *ptr = '\0'; - device->handle_input(buffer); + + ptr = buffer; + while (*ptr) + device->handle_input_byte(*ptr++); }; CriticalScope _; diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index 5f996931..bd5839cd 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -54,20 +54,7 @@ namespace Kernel { Input::KeyEvent event; ASSERT(MUST(Process::current().sys_read(fd, &event, sizeof(event))) == sizeof(event)); - - TTY& current_tty = *TTY::current(); - if (current_tty.m_foreground_pgrp && - event.pressed() && - event.ctrl() && - !event.shift() - && event.key == Input::Key::C - ) - { - if (auto ret = Process::sys_kill(-current_tty.m_foreground_pgrp, SIGINT); ret.is_error()) - dwarnln("TTY: {}", ret.error()); - } - else - current_tty.on_key_event(event); + TTY::current()->on_key_event(event); } }, nullptr ); @@ -146,91 +133,73 @@ namespace Kernel } } - handle_input((const uint8_t*)ansi_c_str); + if (ansi_c_str) + { + auto* ptr = (const uint8_t*)ansi_c_str; + while (*ptr) + handle_input_byte(*ptr++); + } } - void TTY::handle_input(const uint8_t* ansi) + void TTY::handle_input_byte(uint8_t ch) { - LockGuard _(m_lock); - - bool eof = ansi && ( - ansi[0] == '\x04' || // ^D - ansi[0] == '\n' // \n - ); - - if (ansi && m_termios.canonical) - { - // EOF from ^D - if (ansi[0] == '\x04') - goto flush; - else if (ansi[0] == '\b') - { - ansi = nullptr; - do_backspace(); - } - } - - if (ansi == nullptr) + if (ch == 0) return; - for (size_t i = 0; ansi[i]; i++) + LockGuard _(m_lock); + + // ^C + if (ch == '\x03') { - if (m_output.bytes >= m_output.buffer.size()) - { - dprintln("TTY buffer full"); - break; - } - m_output.buffer[m_output.bytes++] = ansi[i]; + if (auto ret = Process::sys_kill(-m_foreground_pgrp, SIGINT); ret.is_error()) + dwarnln("TTY: {}", ret.error()); + return; } + // ^D + canonical + if (ch == '\x04' && m_termios.canonical) + { + m_output.flush = true; + m_output.semaphore.unblock(); + return; + } + + // backspace + canonical + if (ch == '\b' && m_termios.canonical) + { + do_backspace(); + return; + } + + m_output.buffer[m_output.bytes++] = ch; + if (m_termios.echo) { - for (size_t i = 0; ansi[i]; i++) + if ((ch <= 31 || ch == 127) && ch != '\n') { - if (ansi[i] <= 26 && ansi[i] != 10) - { - putchar('^'); - putchar('A' + ansi[i] - 1); - } - else if (ansi[i] == 27) - { - putchar('^'); + putchar('^'); + if (ch <= 26 && ch != 10) + putchar('A' + ch - 1); + else if (ch == 27) putchar('['); - } - else if (ansi[i] == 28) - { - putchar('^'); + else if (ch == 28) putchar('\\'); - } - else if (ansi[i] == 29) - { - putchar('^'); + else if (ch == 29) putchar(']'); - } - else if (ansi[i] == 30) - { - putchar('^'); - putchar('^'); - } - else if (ansi[i] == 31) - { + else if (ch == 30) putchar('^'); + else if (ch == 31) putchar('_'); - } - else if (ansi[i] == 127) - { - putchar('^'); + else if (ch == 127) putchar('?'); - } - else - { - putchar(ansi[i]); - } + } + else + { + putchar(ch); } } -flush: - if (eof || !m_termios.canonical) + if (ch == '\n' || !m_termios.canonical) { m_output.flush = true; m_output.semaphore.unblock();