From abe4af093e72e4822f6578adc9c3b230c5285781 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 11 Jun 2023 09:23:57 +0100 Subject: [PATCH] tty: implement read/write support --- arch/x86_64/init.c | 2 +- dev/char.c | 29 ++++++++++++++++++++++ dev/core.c | 22 +++++++++++------ dev/input.c | 1 + include/socks/device.h | 10 +++++--- include/socks/tty.h | 9 ++++++- kernel/tty/device.c | 7 ++++++ kernel/tty/driver.c | 2 +- kernel/tty/tty.c | 56 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 kernel/tty/tty.c diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index aaf6c26..b771a0f 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -154,7 +154,7 @@ int ml_init(uintptr_t arg) acpi_init(); #endif - tty_init(); + tty_bootstrap(); ml_int_enable(); diff --git a/dev/char.c b/dev/char.c index 0a1ab66..6e4e83b 100644 --- a/dev/char.c +++ b/dev/char.c @@ -17,3 +17,32 @@ struct char_device *char_device_from_generic(struct device *dev) dev->dev_type = DEV_TYPE_CHAR; return CHAR_DEVICE(dev); } + +static kern_status_t char_device_read(struct device *dev, void *buf, size_t size, size_t *bytes_read, socks_flags_t flags) +{ + kern_status_t status = KERN_UNSUPPORTED; + struct char_device *cdev = CHAR_DEVICE(dev); + + if (cdev->c_ops && cdev->c_ops->read) { + status = cdev->c_ops->read(dev, buf, size, bytes_read, flags); + } + + return status; +} + +static kern_status_t char_device_write(struct device *dev, const void *buf, size_t size, size_t *bytes_read, socks_flags_t flags) +{ + kern_status_t status = KERN_UNSUPPORTED; + struct char_device *cdev = CHAR_DEVICE(dev); + + if (cdev->c_ops && cdev->c_ops->write) { + status = cdev->c_ops->write(dev, buf, size, bytes_read, flags); + } + + return status; +} + +struct device_type_ops char_type_ops = { + .read = char_device_read, + .write = char_device_write, +}; diff --git a/dev/core.c b/dev/core.c index 23dfa1e..c36b648 100644 --- a/dev/core.c +++ b/dev/core.c @@ -19,6 +19,7 @@ static kern_status_t device_object_get_child_named(struct object *, const char * extern kern_status_t init_driver_tree(void); +extern struct device_type_ops char_type_ops; extern struct device_type_ops input_type_ops; extern struct device_type_ops framebuffer_type_ops; extern struct device_type_ops bus_type_ops; @@ -26,7 +27,7 @@ extern struct device_type_ops bus_type_ops; static struct device_type_ops *type_ops[] = { [DEV_TYPE_UNKNOWN] = NULL, [DEV_TYPE_BLOCK] = NULL, - [DEV_TYPE_CHAR] = NULL, + [DEV_TYPE_CHAR] = &char_type_ops, [DEV_TYPE_NET] = NULL, [DEV_TYPE_INPUT] = &input_type_ops, [DEV_TYPE_BUS] = &bus_type_ops, @@ -123,17 +124,24 @@ struct device *generic_device_create(void) kern_status_t device_read(struct device *dev, void *buf, size_t size, size_t *bytes_read, socks_flags_t flags) { - switch (dev->dev_type) { - case DEV_TYPE_INPUT: - return input_device_read(dev, buf, size, bytes_read, flags); - default: - return KERN_UNSUPPORTED; + kern_status_t status = KERN_UNSUPPORTED; + + if (type_ops[dev->dev_type] && type_ops[dev->dev_type]->read) { + status = type_ops[dev->dev_type]->read(dev, buf, size, bytes_read, flags); } + + return status; } kern_status_t device_write(struct device *dev, const void *buf, size_t size, size_t *bytes_written, socks_flags_t flags) { - return KERN_UNSUPPORTED; + kern_status_t status = KERN_UNSUPPORTED; + + if (type_ops[dev->dev_type] && type_ops[dev->dev_type]->write) { + status = type_ops[dev->dev_type]->write(dev, buf, size, bytes_written, flags); + } + + return status; } struct device *cast_to_device(struct object *obj) diff --git a/dev/input.c b/dev/input.c index caa0613..4167a9c 100644 --- a/dev/input.c +++ b/dev/input.c @@ -88,4 +88,5 @@ kern_status_t input_device_register(struct device *dev) struct device_type_ops input_type_ops = { .register_device = input_device_register, + .read = input_device_read, }; diff --git a/include/socks/device.h b/include/socks/device.h index a4c14d6..50be4a3 100644 --- a/include/socks/device.h +++ b/include/socks/device.h @@ -41,12 +41,14 @@ enum device_type { }; struct device_type_ops { + kern_status_t(*read)(struct device *, void *, size_t, size_t *, socks_flags_t); + kern_status_t(*write)(struct device *, const void *, size_t, size_t *, socks_flags_t); kern_status_t(*register_device)(struct device *); }; struct block_device_ops { - kern_status_t(*read_blocks)(struct device *, size_t, size_t *, void *, socks_flags_t); - kern_status_t(*write_blocks)(struct device *, size_t, size_t *, const void *, socks_flags_t); + kern_status_t(*read_blocks)(struct device *, void *, size_t, size_t *, socks_flags_t); + kern_status_t(*write_blocks)(struct device *, const void *, size_t, size_t *, socks_flags_t); kern_status_t(*ioctl)(struct device *, unsigned int, void *); }; @@ -58,8 +60,8 @@ struct net_device_ops { }; struct char_device_ops { - kern_status_t(*read)(struct device *, size_t, size_t *, void *, socks_flags_t); - kern_status_t(*write)(struct device *, size_t, size_t *, const void *, socks_flags_t); + kern_status_t(*read)(struct device *, void *, size_t, size_t *, socks_flags_t); + kern_status_t(*write)(struct device *, const void *, size_t, size_t *, socks_flags_t); }; struct input_device_ops { diff --git a/include/socks/tty.h b/include/socks/tty.h index 98d96d1..03faf4a 100644 --- a/include/socks/tty.h +++ b/include/socks/tty.h @@ -7,6 +7,9 @@ #include #include +#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))) + struct kext; /* The TTY system. @@ -82,9 +85,10 @@ 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; }; -extern kern_status_t tty_init(void); +extern kern_status_t tty_bootstrap(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); @@ -98,6 +102,9 @@ static inline struct driver *tty_driver_base(struct tty_driver *drv) return &drv->tty_base; } +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); + #ifdef __cplusplus } #endif diff --git a/kernel/tty/device.c b/kernel/tty/device.c index e5a094a..1cc6f69 100644 --- a/kernel/tty/device.c +++ b/kernel/tty/device.c @@ -2,6 +2,11 @@ #include #include +static struct char_device_ops tty_ops = { + .read = tty_read, + .write = tty_write, +}; + struct device *tty_device_create(void) { struct char_device *cdev = char_device_create(); @@ -15,7 +20,9 @@ struct device *tty_device_create(void) return NULL; } + cdev->c_ops = &tty_ops; cdev->c_tty = tty_dev; + return char_device_base(cdev); } diff --git a/kernel/tty/driver.c b/kernel/tty/driver.c index 0c382ae..e4fec84 100644 --- a/kernel/tty/driver.c +++ b/kernel/tty/driver.c @@ -8,7 +8,7 @@ static struct vm_cache tty_driver_cache = { static struct queue tty_drivers; static spin_lock_t tty_drivers_lock; -kern_status_t tty_init(void) +kern_status_t tty_bootstrap(void) { vm_cache_init(&tty_driver_cache); tty_drivers = QUEUE_INIT; diff --git a/kernel/tty/tty.c b/kernel/tty/tty.c new file mode 100644 index 0000000..80191a5 --- /dev/null +++ b/kernel/tty/tty.c @@ -0,0 +1,56 @@ +#include +#include + +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; + + if (!ops->tty_putc) { + return; + } + + if (tty_driver->tty_type == TTY_DRIVER_SIMPLE) { + ops->tty_putc(tty, c, -1, -1, 0); + return; + } + + 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) { + if (ops->tty_scroll) { + ops->tty_scroll(tty, TTY_SCROLL_DOWN, 1); + } else { + ttydev->tty_xcur = 0; + ttydev->tty_ycur = 0; + } + } + + ops->tty_move_cursor(tty, ttydev->tty_xcur, ttydev->tty_ycur); +} + +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; +}