diff options
author | Ian Moffett <ian@osmora.org> | 2024-05-18 01:00:19 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-05-18 01:01:07 -0400 |
commit | 68bc6fb38fe2f308746d74de1973c7aa84fed440 (patch) | |
tree | 61928ffcc55703133c90c5ede4d17b96898c9333 /sys/kern | |
parent | a38eb07f6cee8618d2ad59396a46e6bfee05b1b3 (diff) |
kernel: tty: Handle ICANON
Add basic handling for canonical mode
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_tty.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/sys/kern/kern_tty.c b/sys/kern/kern_tty.c index 641e7ba..7be7042 100644 --- a/sys/kern/kern_tty.c +++ b/sys/kern/kern_tty.c @@ -31,6 +31,7 @@ #include <sys/cdefs.h> #include <sys/errno.h> #include <sys/syslog.h> +#include <sys/ascii.h> #include <fs/devfs.h> #include <string.h> @@ -62,18 +63,27 @@ static ssize_t __tty_flush(struct tty *tty) { struct tty_ring *ring = &tty->ring; + const struct termios *termios; size_t count = 0; char tmp; + termios = &tty->termios; + /* Do we have any data left? */ if (ring->deq_index >= ring->enq_index) return -EAGAIN; - /* Flush the ring */ - while (ring->deq_index < ring->enq_index) { - tmp = ring->data[ring->deq_index++]; - vcons_putch(tty->scr, tmp); - ++count; + /* + * Flush the ring to the console if we are in + * canonical mode. Otherwise, just throw away + * the bytes. + */ + if (__TEST(termios->c_lflag, ICANON)) { + while (ring->deq_index < ring->enq_index) { + tmp = ring->data[ring->deq_index++]; + vcons_putch(tty->scr, tmp); + ++count; + } } ring->enq_index = 0; @@ -132,11 +142,37 @@ int tty_putc(struct tty *tty, int c) { struct tty_ring *ring; + const struct termios *termios; + bool canon; ring = &tty->ring; + termios = &tty->termios; + canon = __TEST(termios->c_lflag, ICANON); + spinlock_acquire(&tty->rlock); ring->data[ring->enq_index++] = c; + /* + * If we aren't in canonical mode, just write directly to + * the console. + * + * XXX: Won't need to worry about extra bytes being printed + * as __tty_flush() won't flush them to the console + * when we aren't in canonical mode. + */ + if (!canon) { + vcons_putch(tty->scr, c); + } + + /* + * If we are in canonical mode and we have a linefeed ('\n') + * character, we should flush the ring. + */ + if (canon && c == ASCII_LF) { + __tty_flush(tty); + } + + /* Flush if the buffer is full */ if (ring->enq_index >= TTY_RING_SIZE) { __tty_flush(tty); } |