diff options
Diffstat (limited to 'src/libdraw/keyboard.c')
-rw-r--r-- | src/libdraw/keyboard.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/libdraw/keyboard.c b/src/libdraw/keyboard.c new file mode 100644 index 00000000..5ab911ab --- /dev/null +++ b/src/libdraw/keyboard.c @@ -0,0 +1,102 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <thread.h> +#include <keyboard.h> + + +void +closekeyboard(Keyboardctl *kc) +{ + if(kc == nil) + return; + + postnote(PNPROC, kc->pid, "kill"); + +#ifdef BUG + /* Drain the channel */ + while(?kc->c) + <-kc->c; +#endif + + close(kc->ctlfd); + close(kc->consfd); + free(kc->file); + free(kc->c); + free(kc); +} + +static +void +_ioproc(void *arg) +{ + int m, n; + char buf[20]; + Rune r; + Keyboardctl *kc; + + kc = arg; + threadsetname("kbdproc"); + kc->pid = getpid(); + n = 0; + for(;;){ + while(n>0 && fullrune(buf, n)){ + m = chartorune(&r, buf); + n -= m; + memmove(buf, buf+m, n); + send(kc->c, &r); + } + m = read(kc->consfd, buf+n, sizeof buf-n); + if(m <= 0){ + yield(); /* if error is due to exiting, we'll exit here */ + fprint(2, "keyboard read error: %r\n"); + threadexits("error"); + } + n += m; + } +} + +Keyboardctl* +initkeyboard(char *file) +{ + Keyboardctl *kc; + char *t; + + kc = mallocz(sizeof(Keyboardctl), 1); + if(kc == nil) + return nil; + if(file == nil) + file = "/dev/cons"; + kc->file = strdup(file); + kc->consfd = open(file, ORDWR|OCEXEC); + t = malloc(strlen(file)+16); + if(kc->consfd<0 || t==nil){ +Error1: + free(kc); + return nil; + } + sprint(t, "%sctl", file); + kc->ctlfd = open(t, OWRITE|OCEXEC); + if(kc->ctlfd < 0){ + fprint(2, "initkeyboard: can't open %s: %r\n", t); +Error2: + close(kc->consfd); + free(t); + goto Error1; + } + if(ctlkeyboard(kc, "rawon") < 0){ + fprint(2, "initkeyboard: can't turn on raw mode on %s: %r\n", t); + close(kc->ctlfd); + goto Error2; + } + free(t); + kc->c = chancreate(sizeof(Rune), 20); + proccreate(_ioproc, kc, 4096); + return kc; +} + +int +ctlkeyboard(Keyboardctl *kc, char *m) +{ + return write(kc->ctlfd, m, strlen(m)); +} |