#include #include #include static void newline(struct device *tty) { struct tty_device *ttydev = TTY_DEVICE(tty); struct tty_driver *tty_driver = TTY_DRIVER(tty->dev_owner); struct tty_driver_ops *ops = tty_driver->tty_ops; ttydev->tty_xcur = 0; ttydev->tty_ycur++; if (ttydev->tty_ycur >= ttydev->tty_ycells) { ttydev->tty_xcur = 0; ttydev->tty_ycur = ttydev->tty_ycells - 1; if (ops->tty_scroll) { ops->tty_scroll(tty, TTY_SCROLL_DOWN, 1); } } ops->tty_move_cursor(tty, ttydev->tty_xcur, ttydev->tty_ycur); } static void __putchar(struct device *tty, int c) { struct tty_device *ttydev = TTY_DEVICE(tty); struct tty_driver *tty_driver = TTY_DRIVER(tty->dev_owner); struct tty_driver_ops *ops = tty_driver->tty_ops; ops->tty_putc(tty, c, ttydev->tty_xcur, ttydev->tty_ycur, ttydev->tty_curattrib); ttydev->tty_xcur++; if (ttydev->tty_xcur >= ttydev->tty_xcells) { ttydev->tty_xcur = 0; ttydev->tty_ycur++; } if (ttydev->tty_ycur >= ttydev->tty_ycells) { ttydev->tty_xcur = 0; ttydev->tty_ycur = ttydev->tty_ycells - 1; if (ops->tty_scroll) { ops->tty_scroll(tty, TTY_SCROLL_DOWN, 1); } } ops->tty_move_cursor(tty, ttydev->tty_xcur, ttydev->tty_ycur); } static void putchar(struct device *tty, int c) { struct tty_driver *tty_driver = TTY_DRIVER(tty->dev_owner); struct tty_driver_ops *ops = tty_driver->tty_ops; if (!ops->tty_putc) { return; } if (tty_driver->tty_type == TTY_DRIVER_SIMPLE) { ops->tty_putc(tty, c, -1, -1, 0); return; } switch (c) { case '\n': newline(tty); break; default: __putchar(tty, c); break; } } kern_status_t tty_read(struct device *tty, void *buf, size_t max, size_t *nr_read, socks_flags_t flags) { printk("tty_read"); return KERN_OK; } kern_status_t tty_write(struct device *tty, const void *buf, size_t len, size_t *nr_written, socks_flags_t flags) { size_t r = 0; const char *s = buf; for (size_t i = 0; i < len; i++) { putchar(tty, s[i]); r++; } *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; }