| #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); |
| chansetname(kc->c, "kbdc"); |
| proccreate(_ioproc, kc, 4096); |
| return kc; |
| } |
| |
| int |
| ctlkeyboard(Keyboardctl *kc, char *m) |
| { |
| return write(kc->ctlfd, m, strlen(m)); |
| } |