From 86eaffdcaa36188b01ead140c6837276b9afc161 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Fri, 30 Nov 2012 19:01:59 +0100 Subject: nusb/kb: fix 5ms sleep polling in repeatproc, notegroup, cleanup fix repeatproc timeout handling, add constants for Kbdelay and Kbrepeat. set procname so one knows which is keyboard and which is mouse and on what endpoints they work. 9front's /dev/mousein and /dev/kbdin allow multiple opens, so theres no need for the refcounted Kin structures. spawn the worker procs in ther own note group, so they wont get killed on interrupt in the original notegroup. --- sys/src/cmd/nusb/kb/kb.c | 335 ++++++++++++++++++++++------------------------- 1 file changed, 158 insertions(+), 177 deletions(-) diff --git a/sys/src/cmd/nusb/kb/kb.c b/sys/src/cmd/nusb/kb/kb.c index c5d59425e..be96f9624 100644 --- a/sys/src/cmd/nusb/kb/kb.c +++ b/sys/src/cmd/nusb/kb/kb.c @@ -4,8 +4,8 @@ * If there's no usb keyboard, it tries to setup the mouse, if any. * It should be started at boot time. * - * Mouse events are converted to the format of mouse(3)'s - * mousein file. + * Mouse events are converted to the format of mouse(3) + * on mousein file. * Keyboard keycodes are translated to scan codes and sent to kbdfs(8) * on kbin file. * @@ -23,26 +23,19 @@ enum Diemsg = 0xbeefbeef, }; -typedef struct KDev KDev; -typedef struct Kin Kin; +enum +{ + Kbdelay = 500, + Kbrepeat = 100, +}; +typedef struct KDev KDev; struct KDev { Dev* dev; /* usb device*/ Dev* ep; /* endpoint to get events */ - Kin* in; /* used to send events to kernel */ + int infd; /* used to send events to kernel */ Channel*repeatc; /* only for keyboard */ - int accel; /* only for mouse */ -}; - -/* - * Kbdin and mousein files must be shared among all instances. - */ -struct Kin -{ - int ref; - int fd; - char* name; }; /* @@ -99,21 +92,8 @@ static char sctab[256] = [0xf8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; -static QLock inlck; -static Kin kbdin = -{ - .ref = 0, - .name = "/dev/kbin", - .fd = -1, -}; -static Kin ptrin = -{ - .ref = 0, - .name = "#m/mousein", - .fd = -1, -}; - static int kbdebug; +static int accel; static int setbootproto(KDev* f, int eid) @@ -153,31 +133,54 @@ recoverkb(KDev *f) } static void -kbfatal(KDev *kd, char *sts) +kbfree(KDev *kd) { - Dev *dev; + if(kd->infd >= 0) + close(kd->infd); + if(kd->ep != nil) + closedev(kd->ep); + if(kd->dev != nil) + closedev(kd->dev); + free(kd); +} +static void +kbfatal(KDev *kd, char *sts) +{ if(sts != nil) fprint(2, "%s: fatal: %s\n", argv0, sts); else fprint(2, "%s: exiting\n", argv0); if(kd->repeatc != nil) - nbsendul(kd->repeatc, Diemsg); - dev = kd->dev; - kd->dev = nil; - if(kd->ep != nil) - closedev(kd->ep); - kd->ep = nil; - devctl(dev, "detach"); - closedev(dev); - /* - * free(kd); done by closedev. - */ + sendul(kd->repeatc, Diemsg); + kbfree(kd); threadexits(sts); } +static void +kbprocname(KDev *kd, char *name) +{ + char buf[128]; + snprint(buf, sizeof(buf), "%s %s", name, kd->ep->dir); + threadsetname(buf); +} + +static void +sethipri(void) +{ + char fn[64]; + int fd; + + snprint(fn, sizeof(fn), "/proc/%d/ctl", getpid()); + fd = open(fn, OWRITE); + if(fd < 0) + return; + fprint(fd, "pri 13"); + close(fd); +} + static int -scale(KDev *f, int x) +scale(int x) { int sign = 1; @@ -192,10 +195,10 @@ scale(KDev *f, int x) case 3: break; case 4: - x = 6 + (f->accel>>2); + x = 6 + (accel>>2); break; case 5: - x = 9 + (f->accel>>1); + x = 9 + (accel>>1); break; default: x *= MaxAcc; @@ -204,24 +207,6 @@ scale(KDev *f, int x) return sign*x; } -/* - * ps2 mouse is processed mostly at interrupt time. - * for usb we do what we can. - */ -static void -sethipri(void) -{ - char fn[30]; - int fd; - - snprint(fn, sizeof(fn), "/proc/%d/ctl", getpid()); - fd = open(fn, OWRITE); - if(fd < 0) - return; - fprint(fd, "pri 13"); - close(fd); -} - static short s16(void *p) { @@ -238,7 +223,9 @@ ptrwork(void* a) char mbuf[80]; KDev* f = a; + kbprocname(f, "ptrwork"); sethipri(); + skiplead = -1; nerrs = 0; for(;;){ @@ -291,9 +278,9 @@ ptrwork(void* a) if(c > 3) z = buf[3]; } - if(f->accel){ - x = scale(f, x); - y = scale(f, y); + if(accel){ + x = scale(x); + y = scale(y); } b = maptab[buf[0] & 0x7]; if(z > 0) /* up */ @@ -303,106 +290,124 @@ ptrwork(void* a) if(kbdebug > 1) fprint(2, "%s: m%11d %11d %11d\n", argv0, x, y, b); seprint(mbuf, mbuf+sizeof(mbuf), "m%11d %11d %11d", x, y,b); - if(write(f->in->fd, mbuf, strlen(mbuf)) < 0) + if(write(f->infd, mbuf, strlen(mbuf)) < 0) kbfatal(f, "mousein i/o"); } } static void -stoprepeat(KDev *f) +putscan(int fd, uchar esc, uchar sc) { - sendul(f->repeatc, Awakemsg); + uchar s[2] = {SCesc1, 0}; + + s[1] = sc; + if(esc && sc != 0) + write(fd, s, 2); + else if(sc != 0) + write(fd, s+1, 1); } static void -startrepeat(KDev *f, uchar esc1, uchar sc) +putmod(int fd, uchar mods, uchar omods, uchar mask, uchar esc, uchar sc) { - ulong c; + uchar s[4], *p; - if(esc1) - c = SCesc1 << 8 | (sc & 0xff); - else - c = sc; - sendul(f->repeatc, c); + p = s; + if((mods&mask) && !(omods&mask)){ + if(esc) + *p++ = SCesc1; + *p++ = sc; + } + if(!(mods&mask) && (omods&mask)){ + if(esc) + *p++ = SCesc1; + *p++ = Keyup|sc; + } + if(p > s) + write(fd, s, p - s); } static void -putscan(int kbinfd, uchar esc, uchar sc) +sleepproc(void* a) { - uchar s[2] = {SCesc1, 0}; + Channel *c = a; + int ms; - s[1] = sc; - if(esc && sc != 0) - write(kbinfd, s, 2); - else if(sc != 0) - write(kbinfd, s+1, 1); + threadsetname("sleepproc"); + while((ms = recvul(c)) > 0) + sleep(ms); + chanfree(c); } static void -repeatproc(void* a) +repeatproc(void* arg) { - KDev *f; - Channel *repeatc; + KDev *f = arg; + Channel *repeatc, *sleepc; int kbdinfd; - ulong l, t, i; + ulong l, t; uchar esc1, sc; + Alt a[3]; - /* - * too many jumps here. - * Rewrite instead of debug, if needed. - */ - f = a; repeatc = f->repeatc; - kbdinfd = f->in->fd; + kbdinfd = f->infd; + threadsetname("repeatproc"); + + sleepc = chancreate(sizeof(ulong), 0); + if(sleepc != nil) + proccreate(sleepproc, sleepc, Stack); + + a[0].c = repeatc; + a[0].v = &l; + a[0].op = CHANRCV; + a[1].c = sleepc; + a[1].v = &t; + a[1].op = sleepc!=nil ? CHANSND : CHANNOP; + a[2].c = nil; + a[2].v = nil; + a[2].op = CHANEND; + l = Awakemsg; -Repeat: - if(l == Diemsg) - goto Abort; - while(l == Awakemsg) - l = recvul(repeatc); - if(l == Diemsg) - goto Abort; - esc1 = l >> 8; - sc = l; - t = 160; - for(;;){ - for(i = 0; i < t; i += 5){ - if(l = nbrecvul(repeatc)) - goto Repeat; - sleep(5); + while(l != Diemsg){ + if(l == Awakemsg){ + l = recvul(repeatc); + continue; + } + esc1 = l >> 8; + sc = l; + t = Kbdelay; + if(alt(a) == 1){ + t = Kbrepeat; + while(alt(a) == 1) + putscan(kbdinfd, esc1, sc); } - putscan(kbdinfd, esc1, sc); - t = 30; } -Abort: + if(sleepc != nil) + sendul(sleepc, 0); chanfree(repeatc); - threadexits("aborted"); - + threadexits(nil); } - -#define hasesc1(sc) (((sc) > 0x47) || ((sc) == 0x38)) +static void +stoprepeat(KDev *f) +{ + sendul(f->repeatc, Awakemsg); +} static void -putmod(int fd, uchar mods, uchar omods, uchar mask, uchar esc, uchar sc) +startrepeat(KDev *f, uchar esc1, uchar sc) { - uchar s[4], *p; + ulong c; - p = s; - if((mods&mask) && !(omods&mask)){ - if(esc) - *p++ = SCesc1; - *p++ = sc; - } - if(!(mods&mask) && (omods&mask)){ - if(esc) - *p++ = SCesc1; - *p++ = Keyup|sc; - } - if(p > s) - write(fd, s, p - s); + if(esc1) + c = SCesc1 << 8 | (sc & 0xff); + else + c = sc; + sendul(f->repeatc, c); } +#define hasesc1(sc) (((sc) > 0x47) || ((sc) == 0x38)) + /* * This routine diffs the state with the last known state * and invents the scan codes that would have been sent @@ -418,7 +423,7 @@ putkeys(KDev *f, uchar buf[], uchar obuf[], int n, uchar dk) uchar uk; int fd; - fd = f->in->fd; + fd = f->infd; putmod(fd, buf[0], obuf[0], Mctrl, 0, SCctrl); putmod(fd, buf[0], obuf[0], (1<repeatc = chancreate(sizeof(ulong), 0); if(f->repeatc == nil) kbfatal(f, "chancreate failed"); proccreate(repeatproc, f, Stack); - sethipri(); setleds(f, f->ep->id, 0); + sethipri(); memset(lbuf, 0, sizeof lbuf); dk = nerrs = 0; @@ -521,60 +528,35 @@ kbdwork(void *a) } static void -freekdev(void *a) -{ - KDev *kd; - - kd = a; - if(kd->in != nil){ - qlock(&inlck); - if(--kd->in->ref == 0){ - close(kd->in->fd); - kd->in->fd = -1; - } - qunlock(&inlck); - } - free(kd); -} - -static void -kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), int accel) +kbstart(Dev *d, Ep *ep, char *infile, void (*f)(void*)) { KDev *kd; - qlock(&inlck); - if(in->fd < 0){ - in->fd = open(in->name, OWRITE); - if(in->fd < 0){ - fprint(2, "%s: %s: %r\n", argv0, in->name); - qunlock(&inlck); - return; - } + kd = emallocz(sizeof(KDev), 1); + kd->infd = open(infile, OWRITE); + if(kd->infd < 0){ + fprint(2, "%s: %s: open: %r\n", argv0, d->dir); + goto Err; } - in->ref++; /* for kd->in = in */ - qunlock(&inlck); - kd = d->aux = emallocz(sizeof(KDev), 1); - d->free = freekdev; - kd->in = in; + incref(d); kd->dev = d; if(setbootproto(kd, ep->id) < 0){ fprint(2, "%s: %s: bootproto: %r\n", argv0, d->dir); - return; + goto Err; } - kd->accel = accel; - kd->ep = openep(d, ep->id); + kd->ep = openep(kd->dev, ep->id); if(kd->ep == nil){ fprint(2, "%s: %s: openep %d: %r\n", argv0, d->dir, ep->id); - return; + goto Err; } if(opendevdata(kd->ep, OREAD) < 0){ fprint(2, "%s: %s: opendevdata: %r\n", argv0, kd->ep->dir); - closedev(kd->ep); - kd->ep = nil; - return; + goto Err; } - incref(d); - proccreate(f, kd, Stack); + procrfork(f, kd, Stack, RFNOTEG); + return; +Err: + kbfree(kd); } static void @@ -587,12 +569,11 @@ usage(void) void threadmain(int argc, char* argv[]) { - int accel, i; + int i; Dev *d; Ep *ep; Usbdev *ud; - accel = 0; ARGBEGIN{ case 'a': accel = strtol(EARGF(usage()), nil, 0); @@ -613,9 +594,9 @@ threadmain(int argc, char* argv[]) if((ep = ud->ep[i]) == nil) break; if(ep->type == Eintr && ep->dir == Ein && ep->iface->csp == KbdCSP) - kbstart(d, ep, &kbdin, kbdwork, accel); + kbstart(d, ep, "/dev/kbin", kbdwork); if(ep->type == Eintr && ep->dir == Ein && ep->iface->csp == PtrCSP) - kbstart(d, ep, &ptrin, ptrwork, accel); + kbstart(d, ep, "/dev/mousein", ptrwork); } threadexits(nil); } -- cgit v1.2.3