summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/cmd/nusb/kb/kb.c335
1 files 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<<Mlshift), 0, SClshift);
putmod(fd, buf[0], obuf[0], (1<<Mrshift), 0, SCrshift);
@@ -474,13 +479,15 @@ kbdwork(void *a)
char err[128];
KDev *f = a;
+ kbprocname(f, "kbdwork");
+
f->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);
}