diff options
author | Richard Braun <rbraun@sceen.net> | 2017-05-28 17:03:27 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2017-05-28 17:54:08 +0200 |
commit | c5680f01485f35c1735cdae08b16b63e300b9f6d (patch) | |
tree | 4210d0975efb8a3aac56930473055e2c14314dac /kern/console.c | |
parent | df6e8f87ad6800ecb348f11b01a42db48237b371 (diff) |
kern/console: implement input handling
Diffstat (limited to 'kern/console.c')
-rw-r--r-- | kern/console.c | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/kern/console.c b/kern/console.c index eb1306f8..c82e7dc9 100644 --- a/kern/console.c +++ b/kern/console.c @@ -22,10 +22,14 @@ #include <kern/arg.h> #include <kern/assert.h> +#include <kern/error.h> #include <kern/init.h> #include <kern/console.h> #include <kern/list.h> +#include <kern/mutex.h> #include <kern/spinlock.h> +#include <kern/thread.h> +#include <machine/cpu.h> /* * Registered consoles. @@ -51,10 +55,14 @@ console_name_match(const char *name) void __init console_init(struct console *console, const char *name, - console_putc_fn putc) + const struct console_ops *ops) { + assert(ops != NULL); + spinlock_init(&console->lock); - console->putc = putc; + console->ops = ops; + cbuf_init(&console->recvbuf, console->buffer, sizeof(console->buffer)); + console->waiter = NULL; strlcpy(console->name, name, sizeof(console->name)); } @@ -64,10 +72,44 @@ console_putc(struct console *console, char c) unsigned long flags; spinlock_lock_intr_save(&console->lock, &flags); - console->putc(console, c); + console->ops->putc(console_dev, c); spinlock_unlock_intr_restore(&console->lock, flags); } +static char +console_getc(struct console *console) +{ + unsigned long flags; + int error; + char c; + + spinlock_lock_intr_save(&console->lock, &flags); + + if (console->waiter != NULL) { + c = EOF; + goto out; + } + + console->waiter = thread_self(); + + for (;;) { + error = cbuf_pop(&console->recvbuf, &c); + + if (!error) { + break; + } + + thread_sleep(&console->lock, console, "consgetc"); + } + + console->waiter = NULL; + +out: + spinlock_unlock_intr_restore(&console->lock, flags); + + return c; +} + void __init console_setup(void) { @@ -78,6 +120,8 @@ console_setup(void) void __init console_register(struct console *console) { + assert(console->ops != NULL); + list_insert_tail(&console_devs, &console->node); if ((console_dev == NULL) && console_name_match(console->name)) { @@ -92,7 +136,28 @@ console_register(struct console *console) } void -console_write_char(char c) +console_intr(struct console *console, char c) +{ + assert(!cpu_intr_enabled()); + + spinlock_lock(&console->lock); + + if (cbuf_size(&console->recvbuf) == cbuf_capacity(&console->recvbuf)) { + goto out; + } + + cbuf_push(&console->recvbuf, c); + + if ((console->waiter != NULL) && (console->waiter != thread_self())) { + thread_wakeup(console->waiter); + } + +out: + spinlock_unlock(&console->lock); +} + +void +console_putchar(char c) { if (console_dev == NULL) { return; @@ -100,3 +165,19 @@ console_write_char(char c) console_putc(console_dev, c); } + +char +console_getchar(void) +{ + char c; + + if (console_dev == NULL) { + c = EOF; + goto out; + } + + c = console_getc(console_dev); + +out: + return c; +} |