]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/aux/kbdfs/kbdfs.c
kbdfs: add shift+altgr table 7 for polish keymaps
[plan9front.git] / sys / src / cmd / aux / kbdfs / kbdfs.c
index 7373ef1b08caf4178d48950c150db4b8d7ceeb96..c4dd3362a9ad30c5d3dd7e335c708e120f96297f 100644 (file)
@@ -89,15 +89,20 @@ char Ewalk[] = "walk in non directory";
 char Ephase[] = "the front fell off";
 char Eintr[] = "interrupted";
 
-int scanfd;
-int ledsfd;
-int consfd;
-int mctlfd;
-int notefd;
+int kbdifd = -1;
+int scanfd = -1;
+int ledsfd = -1;
+int consfd = -1;
+int mctlfd = -1;
+int msinfd = -1;
+int notefd = -1;
+int killfd = -1;
 
 int kbdopen;
 int consctlopen;
 int quiet = 0;
+char *sname = nil;
+char *mntpt = "/dev";
 
 int debug;
 
@@ -113,6 +118,7 @@ Channel *runechan;  /* chan(Rune) */
 
 Channel *conschan;     /* chan(char*) */
 Channel *kbdchan;      /* chan(char*) */
+Channel *intchan;      /* chan(int) */
 
 /*
  * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
@@ -155,7 +161,7 @@ Rune kbtabshift[Nscan] =
 [0x60] 0,      0,      0,      0,      0,      0,      0,      0,
 [0x68] 0,      0,      0,      0,      0,      0,      0,      0,
 [0x70] 0,      0,      0,      0,      0,      0,      0,      0,
-[0x78] 0,      Kup,    0,      Kup,    0,      0,      0,      0,
+[0x78] 0,      Kdown,  0,      Kup,    0,      0,      0,      0,
 };
 
 Rune kbtabesc1[Nscan] =
@@ -178,6 +184,46 @@ Rune kbtabesc1[Nscan] =
 [0x78] 0,      Kup,    0,      0,      0,      0,      0,      0,
 };
 
+Rune kbtabshiftesc1[Nscan] =
+{
+[0x00] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x08] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x10] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x18] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x20] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x28] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x30] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x38] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x40] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x48] Kup,    0,      0,      0,      0,      0,      0,      0,
+[0x50] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x58] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x60] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x68] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x70] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x78] 0,      Kup,    0,      0,      0,      0,      0,      0,
+};
+
+Rune kbtabctrlesc1[Nscan] =
+{
+[0x00] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x08] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x10] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x18] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x20] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x28] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x30] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x38] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x40] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x48] Kup,    0,      0,      0,      0,      0,      0,      0,
+[0x50] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x58] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x60] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x68] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x70] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x78] 0,      Kup,    0,      0,      0,      0,      0,      0,
+};
+
 Rune kbtabaltgr[Nscan] =
 {
 [0x00] 0,      0,      0,      0,      0,      0,      0,      0,
@@ -218,7 +264,69 @@ Rune kbtabctl[Nscan] =
 [0x78] 0,      '\a',    0,      '\b',   0,      0,      0,      0,
 };
 
-void reboot(void);
+Rune kbtabshiftaltgr[Nscan] =
+{
+[0x00] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x08] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x10] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x18] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x20] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x28] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x30] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x38] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x40] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x48] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x50] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x58] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x60] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x68] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x70] 0,      0,      0,      0,      0,      0,      0,      0,
+[0x78] 0,      0,      0,      0,      0,      0,      0,      0,
+};
+
+char*
+dev(char *file)
+{
+       static char *buf = nil;
+       free(buf);
+       buf = smprint("%s/%s", mntpt, file);
+       return buf;
+}
+
+int
+eopen(char *name, int mode)
+{
+       int fd;
+
+       fd = open(name, mode);
+       if(fd < 0 && !quiet)
+               fprint(2, "%s: warning: can't open %s: %r\n", argv0, name);
+       return fd;
+}
+
+void
+reboot(void)
+{
+       int fd;
+
+       if(debug)
+               return;
+
+       if((fd = eopen(dev("reboot"), OWRITE)) < 0)
+               return;
+       fprint(fd, "reboot\n");
+       close(fd);
+}
+
+void
+shutdown(void)
+{
+       if(notefd >= 0)
+               write(notefd, "hangup", 6);
+       if(killfd >= 0)
+               write(killfd, "hangup", 6);
+       threadexitsall(nil);
+}
 
 /*
  * Scan code processing
@@ -249,8 +357,18 @@ kbdputsc(Scan *scan, int c)
        if(c >= Nscan)
                return;
 
-       if(scan->esc1)
+       /* qemu workarround: emulate e0 for numpad */
+       if(c != 0 && strchr("GHIKMOPQRS", c) != nil)
+               scan->esc1 |= !scan->num;
+
+       if(scan->esc1 && scan->ctl && kbtabctrlesc1[c] != 0)
+               key.r = kbtabctrlesc1[c];
+       else if(scan->esc1 && scan->shift && kbtabshiftesc1[c] != 0)
+               key.r = kbtabshiftesc1[c];
+       else if(scan->esc1)
                key.r = kbtabesc1[c];
+       else if(scan->shift && scan->altgr && kbtabshiftaltgr[c] != 0)
+               key.r = kbtabshiftaltgr[c];
        else if(scan->shift)
                key.r = kbtabshift[c];
        else if(scan->altgr)
@@ -297,6 +415,81 @@ kbdputsc(Scan *scan, int c)
        scan->esc1 = 0;
 }
 
+static void
+kbdin(Scan *a, char *p, int n)
+{
+       char *s;
+       Key k;
+       int i;
+
+       if(n > 0 && p[n-1] != 0){
+               /*
+                * old format as used by bitsy keyboard:
+                * just a string of characters, no keyup
+                * information.
+                */
+               s = emalloc9p(n+1);
+               memmove(s, p, n);
+               s[n] = 0;
+               p = s;
+               while(*p){
+                       p += chartorune(&k.r, p);
+                       if(k.r)
+                               send(rawchan, &k.r);
+               }
+               free(s);
+               return;
+       }
+Nextmsg:
+       if(n < 2)
+               return;
+       switch(p[0]){
+       case 'R':
+       case 'r':
+               /* rune up/down */
+               chartorune(&k.r, p+1);
+               if(k.r == 0)
+                       break;
+               k.b = k.r;
+               k.down = (p[0] == 'r');
+               /*
+                * assign button according to keymap.
+                */
+               for(i=0; i<Nscan; i++){
+                       if((a->shift && kbtabshift[i] == k.r) || (kbtab[i] == k.r)){
+                               if(kbtab[i])
+                                       k.b = kbtab[i];
+                               break;
+                       }
+               }
+               send(keychan, &k);
+               if(k.r == Kshift)
+                       a->shift = k.down;
+               else if(k.r == Kaltgr)
+                       a->altgr = k.down;
+               else if(k.r == Kctl)
+                       a->ctl = k.down;
+               break;
+
+       case 'c':
+               chartorune(&k.r, p+1);
+               nbsend(runechan, &k.r);
+               break;
+
+       default:
+               if(!kbdopen)
+                       break;
+               i = strlen(p)+1;
+               s = emalloc9p(i);
+               memmove(s, p, i);
+               if(nbsendp(kbdchan, s) <= 0)
+                       free(s);
+       }
+       i = strlen(p)+1;
+       n -= i, p += i;
+       goto Nextmsg;
+}
+
 void
 setleds(Scan *scan, int leds)
 {
@@ -328,6 +521,24 @@ scanproc(void *)
                        kbdputsc(&scan, buf[i]);
                setleds(&scan, (scan.num<<1) | (scan.caps<<2));
        }
+
+       shutdown();
+}
+
+void
+kbdiproc(void *)
+{
+       char buf[1024];
+       Scan scan;
+       int n;
+
+       threadsetname("kbdiproc");
+
+       memset(&scan, 0, sizeof scan);
+       while((n = read(kbdifd, buf, sizeof buf)) > 0)
+               kbdin(&scan, buf, n);
+
+       shutdown();
 }
 
 char*
@@ -353,13 +564,24 @@ keyproc(void *)
 {
        Rune rb[Nscan+1];
        Key key;
-       int i, nb;
+       int i, nb, mouseb;
        char *s;
 
        threadsetname("keyproc");
 
        nb = 0;
+       mouseb = 0;
        while(recv(keychan, &key) > 0){
+               if(msinfd >= 0 && key.r >= Kmouse+1 && key.r <= Kmouse+5){
+                       i = 1<<(key.r-(Kmouse+1));
+                       if(key.down)
+                               mouseb |= i;
+                       else
+                               mouseb &= ~i;
+                       fprint(msinfd, "m%11d %11d %11d", 0, 0, mouseb);
+                       continue; /* ignored when mapped to mouse button */
+               }
+
                rb[0] = 0;
                for(i=0; i<nb && rb[i+1] != key.b; i++)
                        ;
@@ -431,6 +653,8 @@ consproc(void *)
                memmove(buf, p, n);
                p = buf + n;
        }
+
+       shutdown();
 }
 
 static int
@@ -501,22 +725,22 @@ Forward:
                if(nextrune(rawchan, &r))
                        continue;
 
-               if(r == 'X'){
+               if(r == 'x' || r == 'X'){
+                       i = (r == 'X') ? 4 : 6;
                        r = 0;
-                       for(i = 0; i<4; i++){
+                       do {
                                if(nextrune(rawchan, &rr))
                                        break;
-                               r <<= 4;
                                if(rr >= '0' && rr <= '9')
-                                       r |= (rr - '0');
+                                       r = (r << 4) | (rr - '0');
                                else if(rr >= 'a' && rr <= 'f')
-                                       r |= 10 + (rr - 'a');
+                                       r = (r << 4) | (10 + (rr - 'a'));
                                else if(rr >= 'A' && rr <= 'F')
-                                       r |= 10 + (rr - 'A');
+                                       r = (r << 4) | (10 + (rr - 'A'));
                                else
                                        break;
-                       }
-                       if(i == 4 && r)
+                       } while(--i > 0);
+                       if((i == 0 || rr == ';') && r != 0 && r <= Runemax)
                                goto Forward;
                } else {
                        if(nextrune(rawchan, &rr))
@@ -543,6 +767,21 @@ Forward:
        }
 }
 
+/*
+ * Need to do this in a separate proc because if process we're interrupting
+ * is dying and trying to print tombstone, kernel is blocked holding p->debug lock.
+ */
+void
+intrproc(void *)
+{
+       threadsetname("intrproc");
+
+       for(;;){
+               if(recv(intchan, nil) > 0)
+                       write(notefd, "interrupt", 9);
+       }
+}
+
 /*
  * Cook lines for cons
  */
@@ -565,9 +804,8 @@ lineproc(void *aux)
                        recv(cook, &r);
                        switch(r){
                        case Kdel:
-                               if(notefd < 0)
+                               if(nbsend(intchan, &notefd) <= 0)
                                        continue;
-                               write(notefd, "interrupt", 9);
                                /* no break */
                        case '\0':      /* flush */
                                nr = 0;
@@ -613,10 +851,11 @@ reqproc(void *aux)
        Channel **ac;
        Req *r, *q, **qq;
        char *s, *p, *e;
-       int n;
+       int n, m;
 
        threadsetname("reqproc");
 
+       e = nil;
        s = nil;
        p = nil;
 
@@ -634,7 +873,7 @@ reqproc(void *aux)
        a[AEND].op = CHANEND;
 
        for(;;){
-               a[ASTR].op = s ? CHANNOP : CHANRCV;
+               a[ASTR].op = s != nil ? CHANNOP : CHANRCV;
 
                switch(alt(a)){
                case AREQ:
@@ -665,27 +904,38 @@ reqproc(void *aux)
                                p = s;
                        }
 
-                       while(s && q){
+                       while(s != nil && q != nil){
                                r = q;
                                if((q = q->aux) == nil)
                                        qq = &q;
-
-                               e = s + strlen(s);
-                               if(p == s && r->fid->qid.path == Qkbd)
-                                       e++; /* send terminating \0 if its kbd file */
+                               r->ofcall.count = 0;
+                               if(s == p){
+                               More:
+                                       e = s + strlen(s);
+                                       if(r->fid->qid.path == Qkbd)
+                                               e++; /* send terminating \0 if its kbd file */
+                               }
                                n = e - p;
-                               if(n > r->ifcall.count)
-                                       n = r->ifcall.count;
-
-                               r->ofcall.count = n;
-                               memmove(r->ofcall.data, p, n);
-                               respond(r, nil);
-
+                               m = r->ifcall.count - r->ofcall.count;
+                               if(n > m){
+                                       if(r->ofcall.count > 0){
+                                               respond(r, nil);
+                                               continue;
+                                       }
+                                       n = m;
+                               }
+                               memmove((char*)r->ofcall.data + r->ofcall.count, p, n);
+                               r->ofcall.count += n;
                                p += n;
                                if(p >= e){
                                        free(s);
-                                       s = nil;
+                                       s = nbrecvp(a[ASTR].c);
+                                       if(s != nil){
+                                               p = s;
+                                               goto More;
+                                       }
                                }
+                               respond(r, nil);
                        }
                }
        }
@@ -707,10 +957,14 @@ ctlproc(void *)
 
        threadsetname("ctlproc");
 
+       if(kbdifd >= 0)
+               proccreate(kbdiproc, nil, STACK);       /* kbdifd -> kbdin() */
        if(scanfd >= 0)
                proccreate(scanproc, nil, STACK);       /* scanfd -> keychan */
        if(consfd >= 0)
                proccreate(consproc, nil, STACK);       /* consfd -> runechan */
+       if(notefd >= 0)
+               proccreate(intrproc, nil, STACK);       /* intchan -> notefd */
 
        threadcreate(keyproc, nil, STACK);              /* keychan -> rawchan, kbdchan */
        threadcreate(runeproc, nil, STACK);             /* rawchan -> runechan */
@@ -779,22 +1033,19 @@ ctlproc(void *)
 Rune*
 kbmapent(int t, int sc)
 {
-       if(sc < 0 || sc >= Nscan)
-               return nil;
-       switch(t){
-       default:
-               return nil;
-       case 0:
-               return &kbtab[sc];
-       case 1:
-               return &kbtabshift[sc];
-       case 2:
-               return &kbtabesc1[sc];
-       case 3:
-               return &kbtabaltgr[sc];
-       case 4:
-               return &kbtabctl[sc];
-       }
+       static Rune *tabs[] = { 
+       /* 0 */ kbtab,
+       /* 1 */ kbtabshift,
+       /* 2 */ kbtabesc1,
+       /* 3 */ kbtabaltgr,
+       /* 4 */ kbtabctl,
+       /* 5 */ kbtabctrlesc1,
+       /* 6 */ kbtabshiftesc1,
+       /* 7 */ kbtabshiftaltgr,
+       };
+       if(t >= 0 && t < nelem(tabs) && sc >= 0 && sc < Nscan)
+               return &tabs[t][sc];
+       return nil;
 }
 
 void
@@ -881,7 +1132,7 @@ kbmapwrite(Req *req)
                                else
                                        goto Badarg;
                        }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
-                               r = 0xF900+lp[1]-'0';
+                               r = Kmouse+lp[1]-'0';
                        else if(*lp>='0' && *lp<='9') /* includes 0x... */
                                r = strtoul(lp, &lp, 0);
                        else
@@ -1083,29 +1334,25 @@ static void
 fswrite(Req *r)
 {
        Fid *f;
-       Scan *a;
-       char *p, *s;
+       char *p;
        int n, i;
-       Key k;
 
        f = r->fid;
+       p = r->ifcall.data;
+       n = r->ifcall.count;
        switch((ulong)f->qid.path){
        default:
                respond(r, Ephase);
                return;
 
        case Qcons:
-               n = r->ifcall.count;
-               if(write(1, r->ifcall.data, n) != n){
+               if(write(1, p, n) != n){
                        responderror(r);
                        return;
                }
-               r->ofcall.count = n;
                break;
 
        case Qconsctl:
-               p = r->ifcall.data;
-               n = r->ifcall.count;
                if(n >= 5 && memcmp(p, "rawon", 5) == 0)
                        sendul(ctlchan, Rawon);
                else if(n >= 6 && memcmp(p, "rawoff", 6) == 0)
@@ -1114,91 +1361,22 @@ fswrite(Req *r)
                        respond(r, Ebadarg);
                        return;
                }
-               r->ofcall.count = n;
                break;
 
+       case Qkbin:
        case Qkbdin:
-               p = r->ifcall.data;
-               n = r->ifcall.count;
-               r->ofcall.count = n;
                if(n == 0)
                        break;
-               if(p[n-1] != 0){
-                       /*
-                        * old format as used by bitsy keyboard:
-                        * just a string of characters, no keyup
-                        * information.
-                        */
-                       s = emalloc9p(n+1);
-                       memmove(s, p, n);
-                       s[n] = 0;
-                       p = s;
-                       while(*p){
-                               p += chartorune(&k.r, p);
-                               if(k.r)
-                                       send(rawchan, &k.r);
-                       }
-                       free(s);
-                       break;
-               }
-               switch(p[0]){
-               case 'R':
-               case 'r':
-                       /* rune up/down */
-                       chartorune(&k.r, p+1);
-                       if(k.r == 0)
-                               break;
-                       k.b = k.r;
-                       k.down = (p[0] == 'r');
-                       if(f->aux == nil){
-                               f->aux = emalloc9p(sizeof(Scan));
-                               memset(f->aux, 0, sizeof(Scan));
-                       }
-                       a = f->aux;
-                       /*
-                        * handle ^X forms according to keymap and
-                        * assign button.
-                        */
-                       for(i=0; i<Nscan; i++){
-                               if((a->shift && kbtabshift[i] == k.r) || (kbtab[i] == k.r)){
-                                       if(kbtab[i])
-                                               k.b = kbtab[i];
-                                       if(a->shift)
-                                               k.r = kbtabshift[i];
-                                       else if(a->altgr)
-                                               k.r = kbtabaltgr[i];
-                                       else if(a->ctl)
-                                               k.r = kbtabctl[i];
-                                       break;
-                               }
-                       }
-                       if(k.b)
-                               send(keychan, &k);
-                       if(k.r == Kshift)
-                               a->shift = k.down;
-                       else if(k.r == Kaltgr)
-                               a->altgr = k.down;
-                       else if(k.r == Kctl)
-                               a->ctl = k.down;
-                       break;
-               default:
-                       if(!kbdopen)
-                               break;
-                       s = emalloc9p(n);
-                       memmove(s, p, n);
-                       if(nbsendp(kbdchan, s) <= 0)
-                               free(s);
-               }
-               break;
-
-       case Qkbin:
                if(f->aux == nil){
                        f->aux = emalloc9p(sizeof(Scan));
                        memset(f->aux, 0, sizeof(Scan));
                }
-               for(i=0; i<r->ifcall.count; i++)
-                       kbdputsc((Scan*)f->aux, (uchar)r->ifcall.data[i]);
-               r->ofcall.count = i;
+               if(f->qid.path == Qkbin){
+                       for(i=0; i<n; i++)
+                               kbdputsc((Scan*)f->aux, (uchar)p[i]);
+               } else {
+                       kbdin((Scan*)f->aux, p, n);
+               }
                break;
 
        case Qkbmap:
@@ -1206,6 +1384,7 @@ fswrite(Req *r)
                return;
 
        }
+       r->ofcall.count = n;
        respond(r, nil);
 }
 
@@ -1248,50 +1427,7 @@ fsdestroyfid(Fid *f)
                }
 }
 
-static void
-fsend(Srv*)
-{
-       threadexitsall(nil);
-}
-
-Srv fs = {
-       .attach=                        fsattach,
-       .walk1=                 fswalk1,
-       .open=                  fsopen,
-       .read=                  fsread,
-       .write=                 fswrite,
-       .stat=                  fsstat,
-       .flush=                 fsflush,
-       .destroyfid=            fsdestroyfid,
-       .end=                   fsend,
-};
-
-int
-eopen(char *name, int mode)
-{
-       int fd;
-
-       fd = open(name, mode);
-       if(fd < 0 && !quiet)
-               fprint(2, "%s: warning: can't open %s: %r\n", argv0, name);
-       return fd;
-}
-
-void
-reboot(void)
-{
-       int fd;
-
-       if(debug)
-               return;
-
-       if((fd = eopen("/dev/reboot", OWRITE)) < 0)
-               return;
-       fprint(fd, "reboot\n");
-       close(fd);
-}
-
-int
+static int
 procopen(int pid, char *name, int mode)
 {
        char buf[128];
@@ -1300,7 +1436,7 @@ procopen(int pid, char *name, int mode)
        return eopen(buf, mode);
 }
 
-void
+static void
 elevate(void)
 {
        Dir *d, nd;
@@ -1329,21 +1465,43 @@ elevate(void)
        close(fd);
 }
 
+static void
+fsstart(Srv*)
+{
+       killfd = procopen(getpid(), "notepg", OWRITE);
+       elevate();
+       proccreate(ctlproc, nil, STACK);
+}
+
+static void
+fsend(Srv*)
+{
+       shutdown();
+}
+
+Srv fs = {
+       .start=                 fsstart,
+       .attach=                fsattach,
+       .walk1=                 fswalk1,
+       .open=                  fsopen,
+       .read=                  fsread,
+       .write=                 fswrite,
+       .stat=                  fsstat,
+       .flush=                 fsflush,
+       .destroyfid=            fsdestroyfid,
+       .end=                   fsend,
+};
+
 void
 usage(void)
 {
-       fprint(2, "usage: %s [ -qdD ] [ -s srv ] [ -m mntpnt ] [ file ]\n", argv0);
+       fprint(2, "usage: %s [ -qdD ] [ -s sname ] [ -m mntpnt ] [ file ]\n", argv0);
        exits("usage");
 }
 
 void
 threadmain(int argc, char** argv)
 {
-       char *mtpt = "/dev";
-       char *srv = nil;
-
-       consfd = -1;
-
        ARGBEGIN{
        case 'd':
                debug++;
@@ -1352,10 +1510,10 @@ threadmain(int argc, char** argv)
                chatty9p++;
                break;
        case 's':
-               srv = EARGF(usage());
+               sname = EARGF(usage());
                break;
        case 'm':
-               mtpt = EARGF(usage());
+               mntpt = EARGF(usage());
                break;
        case 'q':
                quiet++;
@@ -1364,15 +1522,19 @@ threadmain(int argc, char** argv)
                usage();
        }ARGEND
 
-       notefd = procopen(getpid(), "notepg", OWRITE);
-
-       scanfd = eopen("/dev/scancode", OREAD);
-       ledsfd = eopen("/dev/leds", OWRITE);
-       mctlfd = eopen("/dev/mousectl", OWRITE);
-
        if(*argv)
                consfd = eopen(*argv, OREAD);
 
+       kbdifd = open(dev("kbd"), OREAD);
+       if(kbdifd < 0){
+               scanfd = eopen(dev("scancode"), OREAD);
+               ledsfd = eopen(dev("leds"), OWRITE);
+               mctlfd = eopen(dev("mousectl"), OWRITE);
+               msinfd = eopen(dev("mousein"), OWRITE);
+       }
+
+       notefd = procopen(getpid(), "notepg", OWRITE);
+
        consreqchan = chancreate(sizeof(Req*), 0);
        kbdreqchan = chancreate(sizeof(Req*), 0);
 
@@ -1382,8 +1544,8 @@ threadmain(int argc, char** argv)
        runechan = chancreate(sizeof(Rune), 32);
        conschan = chancreate(sizeof(char*), 16);
        kbdchan = chancreate(sizeof(char*), 16);
+       intchan = chancreate(sizeof(int), 0);
 
-       elevate();
-       procrfork(ctlproc, nil, STACK, RFNAMEG|RFNOTEG);
-       threadpostmountsrv(&fs, srv, mtpt, MBEFORE);
+       threadpostmountsrv(&fs, sname, mntpt, MBEFORE);
+       threadexits(0);
 }