summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/shared/include/camellia/errno.h1
-rw-r--r--src/user/app/init/driver/ps2.c66
-rw-r--r--src/user/app/shell/builtins.c4
-rw-r--r--src/user/lib/include/__errno.h1
4 files changed, 56 insertions, 16 deletions
diff --git a/src/shared/include/camellia/errno.h b/src/shared/include/camellia/errno.h
index e29f3d7..1177f54 100644
--- a/src/shared/include/camellia/errno.h
+++ b/src/shared/include/camellia/errno.h
@@ -25,3 +25,4 @@
#define EINTR 205
#define EWOULDBLOCK 206
#define EEXIST 207
+#define EAGAIN 208
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);
}
diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c
index 734370b..9c294b2 100644
--- a/src/user/app/shell/builtins.c
+++ b/src/user/app/shell/builtins.c
@@ -35,6 +35,10 @@ static void cmd_cat(int argc, char **argv) {
if (len <= 0) break;
fwrite(buf, 1, len, stdout);
}
+ if (ferror(file)) {
+ perror(argv[i]);
+ return;
+ }
fclose(file);
}
}
diff --git a/src/user/lib/include/__errno.h b/src/user/lib/include/__errno.h
index 0808ac6..7551ce0 100644
--- a/src/user/lib/include/__errno.h
+++ b/src/user/lib/include/__errno.h
@@ -22,4 +22,5 @@ E(204, "ENOEXEC")
E(205, "EINTR")
E(206, "EWOULDBLOCK")
E(207, "EEXIST")
+E(208, "EAGAIN")
#endif