From 0c6a00bc6be81eca060d1fa9e0b134903e9b56e6 Mon Sep 17 00:00:00 2001 From: Matheus Date: Fri, 15 Aug 2025 22:52:23 -0300 Subject: [PATCH] tty: add termios_callback --- kernel-src/include/kernel/tty.h | 4 +++- kernel-src/io/console.c | 4 +++- kernel-src/io/pty.c | 2 +- kernel-src/io/tty.c | 29 +++++++++++++++++++++++------ 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/kernel-src/include/kernel/tty.h b/kernel-src/include/kernel/tty.h index e5449747..324199a2 100644 --- a/kernel-src/include/kernel/tty.h +++ b/kernel-src/include/kernel/tty.h @@ -12,6 +12,7 @@ typedef size_t (*ttydevicewritefn_t)(void *internal, char *str, size_t size); typedef void (*ttyinactivefn_t)(void *internal); +typedef void (*tty_termios_callback_t)(void *internal, termios_t *termios); typedef struct { pollheader_t pollheader; @@ -25,6 +26,7 @@ typedef struct { int devicepos; ttydevicewritefn_t writetodevice; ttyinactivefn_t inactivedevice; + tty_termios_callback_t termios_callback; int minor; winsize_t winsize; vnode_t *mastervnode; @@ -33,7 +35,7 @@ typedef struct { } tty_t; void tty_init(); -tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inactivefn, void *internal); +tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inactivefn, tty_termios_callback_t termios_callback, void *internal); void tty_process(tty_t *tty, char c); void tty_unregister(tty_t *tty); int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result, cred_t *cred); diff --git a/kernel-src/io/console.c b/kernel-src/io/console.c index a06ba384..35b55f42 100644 --- a/kernel-src/io/console.c +++ b/kernel-src/io/console.c @@ -115,7 +115,7 @@ void console_init() { __assert(thread); sched_queue(thread); - tty = tty_create("console", console_ttywrite, NULL, NULL); + tty = tty_create("console", console_ttywrite, NULL, NULL, NULL); __assert(tty); size_t x, y, fbx, fby; @@ -124,6 +124,8 @@ void console_init() { tty->winsize.ws_row = y; tty->winsize.ws_xpixel = fbx; tty->winsize.ws_ypixel = fby; + + logging_sethook(console_putc); } INIT_ROUTINE_DEFINE(console, INIT_ROUTINE_FLAGS_NONE, console_init, scheduler, keyboard); diff --git a/kernel-src/io/pty.c b/kernel-src/io/pty.c index 003b2b93..1bec027e 100644 --- a/kernel-src/io/pty.c +++ b/kernel-src/io/pty.c @@ -266,7 +266,7 @@ static int open(int oldminor, vnode_t **vnode, int flags) { // create a pairing slave device snprintf(tmpname, 20, "pts/%d", newminor); - pty->tty = tty_create(tmpname, writetopty, inactivepty, pty); + pty->tty = tty_create(tmpname, writetopty, inactivepty, NULL, pty); if (pty->tty == NULL) { VOP_RELEASE(pty->mastervnode); return ENOMEM; diff --git a/kernel-src/io/tty.c b/kernel-src/io/tty.c index 07b459a2..cdb853da 100644 --- a/kernel-src/io/tty.c +++ b/kernel-src/io/tty.c @@ -43,6 +43,14 @@ static int setforeground(tty_t *tty, proc_t *proc) { return ENOTTY; } +// TODO: make this interrupt safe +// this would mean: +// - preventing the leaders from reaching refcnt = 1 during the getforeground() call until it is done +// - list mutex -> list spinlock +// +// however, for it to truly be interrupt safe, the tty->writetodevice callback would also need to be interrupt safe, +// which means that any drivers expecting to call this from an interrupt context would REQUIRE to have the callback to also be interrupt safe +// the main console is an example of a driver which would not be able to do so. void tty_process(tty_t *tty, char c) { if (c == '\r' && (tty->termios.c_iflag & IGNCR)) return; @@ -337,8 +345,14 @@ int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result, cred_t *cre } case TCGETS: return USERCOPY_POSSIBLY_TO_USER(arg, &tty->termios, sizeof(termios_t)); - case TCSETS: - return USERCOPY_POSSIBLY_FROM_USER(&tty->termios, arg, sizeof(termios_t)); + case TCSETS: { + int e = USERCOPY_POSSIBLY_FROM_USER(&tty->termios, arg, sizeof(termios_t)); + + if (e == 0 && tty->termios_callback) + tty->termios_callback(tty->deviceinternal, &tty->termios); + + return e; + } case TIOCSCTTY: { // set as controlling tty return jobctl_setctty(current_thread()->proc, tty, (uintptr_t)arg == 1); @@ -464,7 +478,7 @@ static devops_t devops = { .inactive = inactive }; -tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inactivefn, void *internal) { +tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inactivefn, tty_termios_callback_t termios_callback, void *internal) { tty_t *tty = alloc(sizeof(tty_t)); if (tty == NULL) return NULL; @@ -501,9 +515,7 @@ tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inacti tty->termios.c_iflag = ICRNL; tty->termios.c_oflag = ONLCR; tty->termios.c_lflag = ECHO | ICANON | ISIG | ECHOCTL; - tty->termios.c_cflag = 0; - tty->termios.ibaud = 38400; - tty->termios.obaud = 38400; + tty->termios.c_cflag = CS8 | B38400; tty->termios.c_cc[VMIN] = 1; tty->termios.c_cc[VINTR] = 0x03; tty->termios.c_cc[VQUIT] = 0x1c; @@ -518,6 +530,7 @@ tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inacti tty->inactivedevice = inactivefn; tty->minor = minor; tty->deviceinternal = internal; + tty->termios_callback = termios_callback; vnode_t *newnode; __assert(devfs_getnode(NULL, DEV_MAJOR_TTY, minor, &newnode) == 0); @@ -526,6 +539,10 @@ tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inacti VOP_RELEASE(newnode); + // set up basic state for the tty + if (termios_callback) + termios_callback(internal, &tty->termios); + return tty; error: if (tty->name)