From a7c28e983c4e0b2f20c8e92faae6f781f81c634e Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 11 Jun 2023 16:47:33 +0100 Subject: [PATCH] kernel: tty: implement tty input using line disciplines --- include/socks/ringbuffer.h | 4 + include/socks/tty.h | 29 +++- init/main.c | 143 +--------------- kernel/tty/device.c | 83 ++++++++- kernel/tty/ldisc.c | 339 +++++++++++++++++++++++++++++++++++++ kernel/tty/tty.c | 34 ++++ 6 files changed, 484 insertions(+), 148 deletions(-) create mode 100644 kernel/tty/ldisc.c diff --git a/include/socks/ringbuffer.h b/include/socks/ringbuffer.h index 1be91c4..fd2c64e 100644 --- a/include/socks/ringbuffer.h +++ b/include/socks/ringbuffer.h @@ -25,6 +25,10 @@ extern size_t ringbuffer_avail(struct ringbuffer *buf); extern size_t ringbuffer_read(struct ringbuffer *buf, size_t size, void *buffer, socks_flags_t flags); extern size_t ringbuffer_write(struct ringbuffer *buf, size_t size, const void *buffer, socks_flags_t flags); +/* TODO */ +//extern size_t ringbuffer_peek(struct ringbuffer *buf, size_t at, size_t size, void *buffer); +//extern size_t ringbuffer_skip(struct ringbuffer *buf, size_t count); + extern int ringbuffer_write_would_block(struct ringbuffer *buf); #endif diff --git a/include/socks/tty.h b/include/socks/tty.h index 4a40ebd..de8a084 100644 --- a/include/socks/tty.h +++ b/include/socks/tty.h @@ -10,6 +10,9 @@ #define TTY_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_CHAR ? (dev)->chr.c_tty : NULL) #define TTY_DRIVER(drv) ((struct tty_driver *)((char *)drv - offsetof(struct tty_driver, tty_base))) +#define TTY_EVENT_QUEUE_SIZE 4 +#define TTY_INPUT_QUEUE_SIZE 256 + struct kext; /* The TTY system. @@ -56,6 +59,13 @@ enum tty_scroll_dir { TTY_SCROLL_UP, }; +enum tty_modifier_key { + TTY_KEY_OTHER = 0x00u, + TTY_KEY_CTRL = 0x01u, + TTY_KEY_ALT = 0x02u, + TTY_KEY_SHIFT = 0x04u, +}; + /* character attribute. this could be as simple as VGA's 16-colour palette plus an extra bit for bright, or a full 24-bit RGB value with bold and underline support, depending on what the driver supports. */ @@ -81,19 +91,35 @@ struct tty_driver { struct tty_driver_ops *tty_ops; }; +struct tty_ldisc { + char name[OBJECT_NAME_MAX]; + void(*process_events)(struct device *); +}; + struct tty_device { unsigned int tty_xcells, tty_ycells; unsigned int tty_xcur, tty_ycur; unsigned int tty_iflag, tty_oflag, tty_lflag; tty_attrib_t tty_curattrib; + + enum tty_modifier_key tty_modstate; + + struct tty_ldisc *tty_ldisc; + + /* raw input events sent to the TTY */ + struct ringbuffer tty_events; + /* input characters processed from tty_events, returned by tty_read() */ + struct ringbuffer tty_input; }; extern kern_status_t tty_bootstrap(void); +extern struct tty_ldisc *tty_default_line_discipline(void); extern struct device *tty_device_create(void); extern kern_status_t tty_device_register(struct device *dev, struct tty_driver *owner, struct device *parent); -extern void tty_set_printk_output(struct device *tty); +extern void tty_set_foreground(struct device *tty); +extern kern_status_t tty_connect_foreground_input_device(struct device *input); extern struct tty_driver *tty_driver_create(struct kext *self, const char *name); extern kern_status_t tty_driver_destroy(struct tty_driver *drv); @@ -106,6 +132,7 @@ static inline struct driver *tty_driver_base(struct tty_driver *drv) extern kern_status_t tty_read(struct device *tty, void *buf, size_t max, size_t *nr_read, socks_flags_t flags); extern kern_status_t tty_write(struct device *tty, const void *buf, size_t len, size_t *nr_written, socks_flags_t flags); +extern kern_status_t tty_report_event(struct device *tty, const struct input_event *ev); #ifdef __cplusplus } diff --git a/init/main.c b/init/main.c index da5eecd..7f12dc9 100644 --- a/init/main.c +++ b/init/main.c @@ -21,120 +21,6 @@ extern unsigned long get_rflags(void); extern char __pstart[], __pend[]; -static char keycode_chars[] = { - [KEY_UNKNOWN] = ' ', - [KEY_A] = 'a', - [KEY_B] = 'b', - [KEY_C] = 'c', - [KEY_D] = 'd', - [KEY_E] = 'e', - [KEY_F] = 'f', - [KEY_G] = 'g', - [KEY_H] = 'h', - [KEY_I] = 'i', - [KEY_J] = 'j', - [KEY_K] = 'k', - [KEY_L] = 'l', - [KEY_M] = 'm', - [KEY_N] = 'n', - [KEY_O] = 'o', - [KEY_P] = 'p', - [KEY_Q] = 'q', - [KEY_R] = 'r', - [KEY_S] = 's', - [KEY_T] = 't', - [KEY_U] = 'u', - [KEY_V] = 'v', - [KEY_W] = 'w', - [KEY_X] = 'x', - [KEY_Y] = 'y', - [KEY_Z] = 'z', - [KEY_KEY_1] = '1', - [KEY_KEY_2] = '2', - [KEY_KEY_3] = '3', - [KEY_KEY_4] = '4', - [KEY_KEY_5] = '5', - [KEY_KEY_6] = '6', - [KEY_KEY_7] = '7', - [KEY_KEY_8] = '8', - [KEY_KEY_9] = '9', - [KEY_KEY_0] = '0', - [KEY_ENTER] = '\n', - [KEY_ESCAPE] = 0, - [KEY_BACKSPACE] = '\b', - [KEY_TAB] = ' ', - [KEY_SPACE] = ' ', - [KEY_MINUS] = '-', - [KEY_EQUALS] = '=', - [KEY_LEFT_BRACE] = '[', - [KEY_RIGHT_BRACE] = ']', - [KEY_BACKSLASH] = '\\', - [KEY_NON_US_HASH] = 0, - [KEY_SEMICOLON] = ';', - [KEY_APOSTROPHE] = '\'', - [KEY_GRAVE_ACCENT] = 0, - [KEY_COMMA] = ',', - [KEY_DOT] = '.', - [KEY_SLASH] = '/', - [KEY_CAPS_LOCK] = 0, - [KEY_F1] = 0, - [KEY_F2] = 0, - [KEY_F3] = 0, - [KEY_F4] = 0, - [KEY_F5] = 0, - [KEY_F6] = 0, - [KEY_F7] = 0, - [KEY_F8] = 0, - [KEY_F9] = 0, - [KEY_F10] = 0, - [KEY_F11] = 0, - [KEY_F12] = 0, - [KEY_PRINT_SCREEN] = 0, - [KEY_SCROLL_LOCK] = 0, - [KEY_PAUSE] = 0, - [KEY_INSERT] = 0, - [KEY_HOME] = 0, - [KEY_PAGE_UP] = 0, - [KEY_DELETE] = 0, - [KEY_END] = 0, - [KEY_PAGE_DOWN] = 0, - [KEY_RIGHT] = 0, - [KEY_LEFT] = 0, - [KEY_DOWN] = 0, - [KEY_UP] = 0, - [KEY_NUM_LOCK] = 0, - [KEY_KEYPAD_SLASH] = '/', - [KEY_KEYPAD_ASTERISK] = '*', - [KEY_KEYPAD_MINUS] = '-', - [KEY_KEYPAD_PLUS] = '+', - [KEY_KEYPAD_ENTER] = '\n', - [KEY_KEYPAD_1] = '1', - [KEY_KEYPAD_2] = '2', - [KEY_KEYPAD_3] = '3', - [KEY_KEYPAD_4] = '4', - [KEY_KEYPAD_5] = '5', - [KEY_KEYPAD_6] = '6', - [KEY_KEYPAD_7] = '7', - [KEY_KEYPAD_8] = '8', - [KEY_KEYPAD_9] = '9', - [KEY_KEYPAD_0] = '0', - [KEY_KEYPAD_DOT] = '.', - [KEY_NON_US_BACKSLASH] = 0, - [KEY_KEYPAD_EQUALS] = '=', - [KEY_MENU] = 0, - [KEY_LEFT_CTRL] = 0, - [KEY_LEFT_SHIFT] = 0, - [KEY_LEFT_ALT] = 0, - [KEY_LEFT_META] = 0, - [KEY_RIGHT_CTRL] = 0, - [KEY_RIGHT_SHIFT] = 0, - [KEY_RIGHT_ALT] = 0, - [KEY_RIGHT_META] = 0, - [KEY_MEDIA_MUTE] = 0, - [KEY_MEDIA_VOLUME_INCREMENT] = 0, - [KEY_MEDIA_VOLUME_DECREMENT] = 0, -}; - void print_kernel_banner(void) { printk("Socks kernel version " BUILD_ID); @@ -210,7 +96,7 @@ void kernel_init(uintptr_t arg) struct object *tty0; status = object_get("/dev/tty/tty0", &tty0); if (status == KERN_OK) { - tty_set_printk_output(cast_to_device(tty0)); + tty_set_foreground(cast_to_device(tty0)); } create_kernel_thread(background_thread); @@ -220,31 +106,8 @@ void kernel_init(uintptr_t arg) run_all_tests(); status = object_get("/dev/input/input0", &kbd); - if (status != KERN_OK) { - printk("no keyboard available"); - hang(); - } - - while (1) { - struct input_event ev; - size_t r; - status = object_read(kbd, &ev, sizeof ev, &r, 0); - - if (status != KERN_OK || r != sizeof ev) { - printk("keyboard read error: %s", kern_status_string(status)); - break; - } - - if (ev.ev_type != INPUT_TYPE_KEY || ev.ev_key.state != INPUT_KEYSTATE_DOWN) { - continue; - } - - char c = keycode_chars[ev.ev_key.key]; - if (c == 0) { - continue; - } - - putchar(c); + if (status == KERN_OK) { + tty_connect_foreground_input_device(cast_to_device(kbd)); } hang(); diff --git a/kernel/tty/device.c b/kernel/tty/device.c index 9aaf374..c6e273c 100644 --- a/kernel/tty/device.c +++ b/kernel/tty/device.c @@ -1,6 +1,7 @@ #include #include #include +#include #include static struct char_device_ops tty_ops = { @@ -8,12 +9,32 @@ static struct char_device_ops tty_ops = { .write = tty_write, }; -static struct device *tty_printk_output = NULL; +static spin_lock_t foreground_lock; +static struct device *foreground = NULL; +static struct device *foreground_input = NULL; + +static void tty_input_hook_callback(struct device *dev, struct input_event *ev, enum input_event_hook_flags *flags, void *arg) +{ + struct device *fg_tty = foreground; + + if (!fg_tty) { + return; + } + + tty_report_event(fg_tty, ev); + *flags = 0; +} + +static struct input_event_hook foreground_input_hook = { + .hook_callback = tty_input_hook_callback, +}; static void tty_console_write(struct console *con, const char *s, unsigned int len) { - size_t nr_written; - tty_write(tty_printk_output, s, len, &nr_written, 0); + if (foreground) { + size_t nr_written; + tty_write(foreground, s, len, &nr_written, 0); + } } static struct console tty_console = { @@ -30,10 +51,27 @@ struct device *tty_device_create(void) struct tty_device *tty_dev = kmalloc(sizeof *tty_dev, VM_NORMAL); if (!tty_dev) { - /* TODO destroy cdev */ + object_deref(char_device_object(cdev)); return NULL; } + kern_status_t status = ringbuffer_init(&tty_dev->tty_events, TTY_EVENT_QUEUE_SIZE * sizeof(struct input_event)); + if (status != KERN_OK) { + kfree(tty_dev); + object_deref(char_device_object(cdev)); + return NULL; + } + + status = ringbuffer_init(&tty_dev->tty_input, TTY_INPUT_QUEUE_SIZE * sizeof(char)); + if (status != KERN_OK) { + ringbuffer_deinit(&tty_dev->tty_events); + kfree(tty_dev); + object_deref(char_device_object(cdev)); + return NULL; + } + + tty_dev->tty_ldisc = tty_default_line_discipline(); + cdev->c_ops = &tty_ops; cdev->c_tty = tty_dev; @@ -62,16 +100,47 @@ kern_status_t tty_device_register(struct device *dev, struct tty_driver *owner, return object_namespace_create_link(global_namespace(), link_path, &dev->dev_base); } -void tty_set_printk_output(struct device *tty) +void tty_set_foreground(struct device *tty) { bool console_init = false; - if (tty_printk_output) { + if (foreground) { console_init = true; } - tty_printk_output = tty; + foreground = tty; if (!console_init) { console_register(&tty_console); } } + +kern_status_t tty_connect_foreground_input_device(struct device *input) +{ + struct input_device *inputdev = INPUT_DEVICE(input); + if (!inputdev) { + return KERN_INVALID_ARGUMENT; + } + + unsigned long flags; + spin_lock_irqsave(&foreground_lock, &flags); + + if (foreground_input) { + struct device *prev = foreground_input; + foreground_input = NULL; + + device_lock(prev); + input_device_remove_hook(prev, &foreground_input_hook); + device_unlock(prev); + object_deref(&prev->dev_base); + } + + object_ref(&input->dev_base); + foreground_input = input; + device_lock(input); + input_device_add_hook(input, &foreground_input_hook); + device_unlock(input); + + spin_unlock_irqrestore(&foreground_lock, flags); + + return KERN_OK; +} diff --git a/kernel/tty/ldisc.c b/kernel/tty/ldisc.c new file mode 100644 index 0000000..56b586d --- /dev/null +++ b/kernel/tty/ldisc.c @@ -0,0 +1,339 @@ +#include +#include +#include + +static void process_events(struct device *tty); + +static char keycode_chars[] = { + [KEY_UNKNOWN] = ' ', + [KEY_A] = 'a', + [KEY_B] = 'b', + [KEY_C] = 'c', + [KEY_D] = 'd', + [KEY_E] = 'e', + [KEY_F] = 'f', + [KEY_G] = 'g', + [KEY_H] = 'h', + [KEY_I] = 'i', + [KEY_J] = 'j', + [KEY_K] = 'k', + [KEY_L] = 'l', + [KEY_M] = 'm', + [KEY_N] = 'n', + [KEY_O] = 'o', + [KEY_P] = 'p', + [KEY_Q] = 'q', + [KEY_R] = 'r', + [KEY_S] = 's', + [KEY_T] = 't', + [KEY_U] = 'u', + [KEY_V] = 'v', + [KEY_W] = 'w', + [KEY_X] = 'x', + [KEY_Y] = 'y', + [KEY_Z] = 'z', + [KEY_KEY_1] = '1', + [KEY_KEY_2] = '2', + [KEY_KEY_3] = '3', + [KEY_KEY_4] = '4', + [KEY_KEY_5] = '5', + [KEY_KEY_6] = '6', + [KEY_KEY_7] = '7', + [KEY_KEY_8] = '8', + [KEY_KEY_9] = '9', + [KEY_KEY_0] = '0', + [KEY_ENTER] = '\n', + [KEY_ESCAPE] = 0, + [KEY_BACKSPACE] = '\b', + [KEY_TAB] = ' ', + [KEY_SPACE] = ' ', + [KEY_MINUS] = '-', + [KEY_EQUALS] = '=', + [KEY_LEFT_BRACE] = '[', + [KEY_RIGHT_BRACE] = ']', + [KEY_BACKSLASH] = '\\', + [KEY_NON_US_HASH] = 0, + [KEY_SEMICOLON] = ';', + [KEY_APOSTROPHE] = '\'', + [KEY_GRAVE_ACCENT] = 0, + [KEY_COMMA] = ',', + [KEY_DOT] = '.', + [KEY_SLASH] = '/', + [KEY_CAPS_LOCK] = 0, + [KEY_F1] = 0, + [KEY_F2] = 0, + [KEY_F3] = 0, + [KEY_F4] = 0, + [KEY_F5] = 0, + [KEY_F6] = 0, + [KEY_F7] = 0, + [KEY_F8] = 0, + [KEY_F9] = 0, + [KEY_F10] = 0, + [KEY_F11] = 0, + [KEY_F12] = 0, + [KEY_PRINT_SCREEN] = 0, + [KEY_SCROLL_LOCK] = 0, + [KEY_PAUSE] = 0, + [KEY_INSERT] = 0, + [KEY_HOME] = 0, + [KEY_PAGE_UP] = 0, + [KEY_DELETE] = 0, + [KEY_END] = 0, + [KEY_PAGE_DOWN] = 0, + [KEY_RIGHT] = 0, + [KEY_LEFT] = 0, + [KEY_DOWN] = 0, + [KEY_UP] = 0, + [KEY_NUM_LOCK] = 0, + [KEY_KEYPAD_SLASH] = '/', + [KEY_KEYPAD_ASTERISK] = '*', + [KEY_KEYPAD_MINUS] = '-', + [KEY_KEYPAD_PLUS] = '+', + [KEY_KEYPAD_ENTER] = '\n', + [KEY_KEYPAD_1] = '1', + [KEY_KEYPAD_2] = '2', + [KEY_KEYPAD_3] = '3', + [KEY_KEYPAD_4] = '4', + [KEY_KEYPAD_5] = '5', + [KEY_KEYPAD_6] = '6', + [KEY_KEYPAD_7] = '7', + [KEY_KEYPAD_8] = '8', + [KEY_KEYPAD_9] = '9', + [KEY_KEYPAD_0] = '0', + [KEY_KEYPAD_DOT] = '.', + [KEY_NON_US_BACKSLASH] = 0, + [KEY_KEYPAD_EQUALS] = '=', + [KEY_MENU] = 0, + [KEY_LEFT_CTRL] = 0, + [KEY_LEFT_SHIFT] = 0, + [KEY_LEFT_ALT] = 0, + [KEY_LEFT_META] = 0, + [KEY_RIGHT_CTRL] = 0, + [KEY_RIGHT_SHIFT] = 0, + [KEY_RIGHT_ALT] = 0, + [KEY_RIGHT_META] = 0, + [KEY_MEDIA_MUTE] = 0, + [KEY_MEDIA_VOLUME_INCREMENT] = 0, + [KEY_MEDIA_VOLUME_DECREMENT] = 0, +}; + +static char keycode_chars_shift[] = { + [KEY_UNKNOWN] = ' ', + [KEY_A] = 'A', + [KEY_B] = 'B', + [KEY_C] = 'C', + [KEY_D] = 'D', + [KEY_E] = 'E', + [KEY_F] = 'F', + [KEY_G] = 'G', + [KEY_H] = 'H', + [KEY_I] = 'I', + [KEY_J] = 'J', + [KEY_K] = 'K', + [KEY_L] = 'L', + [KEY_M] = 'M', + [KEY_N] = 'N', + [KEY_O] = 'O', + [KEY_P] = 'P', + [KEY_Q] = 'Q', + [KEY_R] = 'R', + [KEY_S] = 'S', + [KEY_T] = 'T', + [KEY_U] = 'U', + [KEY_V] = 'V', + [KEY_W] = 'W', + [KEY_X] = 'X', + [KEY_Y] = 'Y', + [KEY_Z] = 'Z', + [KEY_KEY_1] = '!', + [KEY_KEY_2] = '"', + [KEY_KEY_3] = 0, + [KEY_KEY_4] = '$', + [KEY_KEY_5] = '%', + [KEY_KEY_6] = '^', + [KEY_KEY_7] = '&', + [KEY_KEY_8] = '*', + [KEY_KEY_9] = '(', + [KEY_KEY_0] = ')', + [KEY_ENTER] = '\n', + [KEY_ESCAPE] = 0, + [KEY_BACKSPACE] = '\b', + [KEY_TAB] = ' ', + [KEY_SPACE] = ' ', + [KEY_MINUS] = '_', + [KEY_EQUALS] = '+', + [KEY_LEFT_BRACE] = '{', + [KEY_RIGHT_BRACE] = '}', + [KEY_BACKSLASH] = '|', + [KEY_NON_US_HASH] = 0, + [KEY_SEMICOLON] = ':', + [KEY_APOSTROPHE] = '@', + [KEY_GRAVE_ACCENT] = 0, + [KEY_COMMA] = '<', + [KEY_DOT] = '>', + [KEY_SLASH] = '?', + [KEY_CAPS_LOCK] = 0, + [KEY_F1] = 0, + [KEY_F2] = 0, + [KEY_F3] = 0, + [KEY_F4] = 0, + [KEY_F5] = 0, + [KEY_F6] = 0, + [KEY_F7] = 0, + [KEY_F8] = 0, + [KEY_F9] = 0, + [KEY_F10] = 0, + [KEY_F11] = 0, + [KEY_F12] = 0, + [KEY_PRINT_SCREEN] = 0, + [KEY_SCROLL_LOCK] = 0, + [KEY_PAUSE] = 0, + [KEY_INSERT] = 0, + [KEY_HOME] = 0, + [KEY_PAGE_UP] = 0, + [KEY_DELETE] = 0, + [KEY_END] = 0, + [KEY_PAGE_DOWN] = 0, + [KEY_RIGHT] = 0, + [KEY_LEFT] = 0, + [KEY_DOWN] = 0, + [KEY_UP] = 0, + [KEY_NUM_LOCK] = 0, + [KEY_KEYPAD_SLASH] = '/', + [KEY_KEYPAD_ASTERISK] = '*', + [KEY_KEYPAD_MINUS] = '-', + [KEY_KEYPAD_PLUS] = '+', + [KEY_KEYPAD_ENTER] = '\n', + [KEY_KEYPAD_1] = '1', + [KEY_KEYPAD_2] = '2', + [KEY_KEYPAD_3] = '3', + [KEY_KEYPAD_4] = '4', + [KEY_KEYPAD_5] = '5', + [KEY_KEYPAD_6] = '6', + [KEY_KEYPAD_7] = '7', + [KEY_KEYPAD_8] = '8', + [KEY_KEYPAD_9] = '9', + [KEY_KEYPAD_0] = '0', + [KEY_KEYPAD_DOT] = '.', + [KEY_NON_US_BACKSLASH] = 0, + [KEY_KEYPAD_EQUALS] = '=', + [KEY_MENU] = 0, + [KEY_LEFT_CTRL] = 0, + [KEY_LEFT_SHIFT] = 0, + [KEY_LEFT_ALT] = 0, + [KEY_LEFT_META] = 0, + [KEY_RIGHT_CTRL] = 0, + [KEY_RIGHT_SHIFT] = 0, + [KEY_RIGHT_ALT] = 0, + [KEY_RIGHT_META] = 0, + [KEY_MEDIA_MUTE] = 0, + [KEY_MEDIA_VOLUME_INCREMENT] = 0, + [KEY_MEDIA_VOLUME_DECREMENT] = 0, +}; + +static struct tty_ldisc default_ldisc = { + .name = "n_tty", + .process_events = process_events, +}; + +static enum tty_modifier_key get_modifier_key(struct input_event *ev) +{ + switch (ev->ev_key.key) { + case KEY_LEFT_CTRL: + case KEY_RIGHT_CTRL: + return TTY_KEY_CTRL; + case KEY_LEFT_ALT: + case KEY_RIGHT_ALT: + return TTY_KEY_ALT; + case KEY_LEFT_SHIFT: + case KEY_RIGHT_SHIFT: + return TTY_KEY_SHIFT; + default: + return TTY_KEY_OTHER; + } +} + +static void handle_modifier_keys(struct device *tty, enum tty_modifier_key modkey, struct input_event *ev) +{ + struct tty_device *ttydev = TTY_DEVICE(tty); + + if (ev->ev_key.state == INPUT_KEYSTATE_DOWN) { + ttydev->tty_modstate |= modkey; + } else { + ttydev->tty_modstate &= ~modkey; + } +} + +static void convert_ev_to_chars(struct device *tty, struct input_event *ev) +{ + if (ev->ev_key.state == INPUT_KEYSTATE_UP) { + return; + } + + struct tty_device *ttydev = TTY_DEVICE(tty); + + char echo[2]; + int echo_len = 0; + + char c = keycode_chars[ev->ev_key.key]; + if (c == 0) { + return; + } + + if (ttydev->tty_modstate & TTY_KEY_CTRL) { + if (!isalpha(c)) { + return; + } + + echo[0] = '^'; + echo[1] = toupper(c); + echo_len = 2; + + c = tolower(c); + c -= 97; + c++; + } else if (ttydev->tty_modstate & TTY_KEY_SHIFT) { + c = keycode_chars_shift[ev->ev_key.key]; + echo[0] = c; + echo_len = 1; + } else { + echo[0] = c; + echo_len = 1; + } + + if (c == 0) { + return; + } + + ringbuffer_write(&ttydev->tty_input, sizeof c, &c, S_NOBLOCK); + size_t nr_written; + tty_write(tty, echo, echo_len, &nr_written, S_NOBLOCK); +} + +void process_events(struct device *tty) +{ + struct tty_device *ttydev = TTY_DEVICE(tty); + struct ringbuffer *events = &ttydev->tty_events; + + struct input_event ev; + + size_t w = ringbuffer_read(events, sizeof ev, &ev, S_NOBLOCK); + + if (w != sizeof ev || ev.ev_type != INPUT_TYPE_KEY) { + return; + } + + enum tty_modifier_key modkeys = get_modifier_key(&ev); + + if (modkeys != TTY_KEY_OTHER) { + handle_modifier_keys(tty, modkeys, &ev); + } else { + convert_ev_to_chars(tty, &ev); + } +} + +struct tty_ldisc *tty_default_line_discipline(void) +{ + return &default_ldisc; +} diff --git a/kernel/tty/tty.c b/kernel/tty/tty.c index ed0f952..e14381b 100644 --- a/kernel/tty/tty.c +++ b/kernel/tty/tty.c @@ -1,4 +1,5 @@ #include +#include #include static void newline(struct device *tty) @@ -90,3 +91,36 @@ kern_status_t tty_write(struct device *tty, const void *buf, size_t len, size_t *nr_written = r; return KERN_OK; } + +static void process_events(struct device *tty) +{ + struct tty_device *ttydev = TTY_DEVICE(tty); + + if (!ttydev->tty_ldisc || !ttydev->tty_ldisc->process_events) { + struct input_event ev; + while (ringbuffer_unread(&ttydev->tty_events)) { + ringbuffer_read(&ttydev->tty_events, sizeof ev, &ev, S_NOBLOCK); + } + + return; + } + + ttydev->tty_ldisc->process_events(tty); +} + +kern_status_t tty_report_event(struct device *tty, const struct input_event *ev) +{ + struct tty_device *ttydev = TTY_DEVICE(tty); + size_t w = ringbuffer_write(&ttydev->tty_events, sizeof *ev, ev, S_NOBLOCK); + + if (w != sizeof *ev) { + return KERN_WOULD_BLOCK; + } + + if (ringbuffer_unread(&ttydev->tty_events) > 0) { + process_events(tty); + + } + + return KERN_OK; +}