diff options
Diffstat (limited to 'src/user/app/init')
-rw-r--r-- | src/user/app/init/driver/ps2.c | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/src/user/app/init/driver/ps2.c b/src/user/app/init/driver/ps2.c index 2752238..5470249 100644 --- a/src/user/app/init/driver/ps2.c +++ b/src/user/app/init/driver/ps2.c @@ -1,10 +1,12 @@ #include "driver.h" +#include <assert.h> #include <camellia/compat.h> #include <camellia/syscalls.h> #include <errno.h> #include <shared/ring.h> #include <stdbool.h> #include <stdlib.h> +#include <thread.h> static const char keymap_lower[] = { @@ -51,36 +53,68 @@ static void parse_scancode(uint8_t s) { if (down && c) ring_put1b((void*)&backlog, c); } -static void main_loop(void) { + +/** Is a thread waiting for /kdev/ps2/kb? */ +static volatile bool blocked = false; +/* for use in read_thread */ +static hid_t rt_reqh; +static size_t rt_cap; + +static void read_thread(void *unused) { + char buf[512]; + (void)unused; + + assert(blocked); + while (ring_used((void*)&backlog) == 0) { + /* read raw input until we have something to output */ + int len = _sys_read(fd, buf, sizeof buf, 0); + if (len == 0) break; + for (int i = 0; i < len; i++) + parse_scancode(buf[i]); + } + if (ring_used((void*)&backlog) > 0) { + int ret = ring_get((void*)&backlog, buf, rt_cap); + _sys_fs_respond(rt_reqh, buf, ret, 0); + } else { + _sys_fs_respond(rt_reqh, 0, -EGENERIC, 0); + } + blocked = false; +} + +static void fs_loop(void) { static char buf[512]; - struct ufs_request res; int ret; - while (!c0_fs_wait(buf, sizeof buf, &res)) { - // TODO don't hang on ps2 reads + for (;;) { + struct ufs_request res; + hid_t reqh = _sys_fs_wait(buf, sizeof buf, &res); + if (reqh < 0) return; switch (res.op) { case VFSOP_OPEN: if (res.len == 0) { - c0_fs_respond(NULL, 1, 0); + _sys_fs_respond(reqh, NULL, 1, 0); } else { - c0_fs_respond(NULL, -ENOENT, 0); + _sys_fs_respond(reqh, NULL, -ENOENT, 0); } break; case VFSOP_READ: - while (ring_used((void*)&backlog) == 0) { - /* read raw input until we have something to output */ - int len = _sys_read(fd, buf, sizeof buf, 0); - if (len == 0) break; - for (int i = 0; i < len; i++) - parse_scancode(buf[i]); + if (blocked) { + _sys_fs_respond(reqh, NULL, -EAGAIN, 0); + break; + } else if (ring_used((void*)&backlog) > 0) { + ret = ring_get((void*)&backlog, buf, res.capacity); + _sys_fs_respond(reqh, buf, ret, 0); + } else { + blocked = true; + rt_reqh = reqh; + rt_cap = res.capacity; + thread_create(0, read_thread, 0); } - ret = ring_get((void*)&backlog, buf, res.capacity); - c0_fs_respond(buf, ret, 0); break; default: - c0_fs_respond(NULL, -1, 0); + _sys_fs_respond(reqh, NULL, -1, 0); break; } } @@ -90,6 +124,6 @@ void ps2_drv(void) { fd = _sys_open("/kdev/ps2/kb", 12, 0); if (fd < 0) exit(1); - main_loop(); + fs_loop(); exit(0); } |