tty: implement read/write support
This commit is contained in:
@@ -154,7 +154,7 @@ int ml_init(uintptr_t arg)
|
||||
acpi_init();
|
||||
#endif
|
||||
|
||||
tty_init();
|
||||
tty_bootstrap();
|
||||
|
||||
ml_int_enable();
|
||||
|
||||
|
||||
29
dev/char.c
29
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,
|
||||
};
|
||||
|
||||
22
dev/core.c
22
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)
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <socks/object.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
#include <socks/device.h>
|
||||
#include <socks/libc/stdio.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
56
kernel/tty/tty.c
Normal file
56
kernel/tty/tty.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <socks/tty.h>
|
||||
#include <socks/printk.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user