summaryrefslogtreecommitdiff
path: root/sys/src/cmd/usb/kb/kb.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@localhost>2011-08-26 05:24:55 +0200
committercinap_lenrek <cinap_lenrek@localhost>2011-08-26 05:24:55 +0200
commit1404cc50772688f05ab65a9eb2d5c8d4b85b0375 (patch)
tree010400734c4ba7998362bfdacc585842b8deca97 /sys/src/cmd/usb/kb/kb.c
parenta6e3c9fd83e72e5c911e83f763e77ab6605a17d2 (diff)
nusb: fix documentation, cleanup, remove /sys/src/cmd/usb
Diffstat (limited to 'sys/src/cmd/usb/kb/kb.c')
-rw-r--r--sys/src/cmd/usb/kb/kb.c610
1 files changed, 0 insertions, 610 deletions
diff --git a/sys/src/cmd/usb/kb/kb.c b/sys/src/cmd/usb/kb/kb.c
deleted file mode 100644
index 0880f5b51..000000000
--- a/sys/src/cmd/usb/kb/kb.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * USB Human Interaction Device: keyboard and mouse.
- *
- * 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.
- * Keyboard keycodes are translated to scan codes and sent to kbin(3).
- *
- */
-
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "hid.h"
-
-enum
-{
- Awakemsg=0xdeaddead,
- Diemsg = 0xbeefbeef,
-};
-
-typedef struct KDev KDev;
-typedef struct Kin Kin;
-
-struct KDev
-{
- Dev* dev; /* usb device*/
- Dev* ep; /* endpoint to get events */
- Kin* in; /* 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;
-};
-
-/*
- * Map for the logitech bluetooth mouse with 8 buttons and wheels.
- * { ptr ->mouse}
- * { 0x01, 0x01 }, // left
- * { 0x04, 0x02 }, // middle
- * { 0x02, 0x04 }, // right
- * { 0x40, 0x08 }, // up
- * { 0x80, 0x10 }, // down
- * { 0x10, 0x08 }, // side up
- * { 0x08, 0x10 }, // side down
- * { 0x20, 0x02 }, // page
- * besides wheel and regular up/down report the 4th byte as 1/-1
- */
-
-/*
- * key code to scan code; for the page table used by
- * the logitech bluetooth keyboard.
- */
-static char sctab[256] =
-{
-[0x00] 0x0, 0x0, 0x0, 0x0, 0x1e, 0x30, 0x2e, 0x20,
-[0x08] 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26,
-[0x10] 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14,
-[0x18] 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x2, 0x3,
-[0x20] 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb,
-[0x28] 0x1c, 0x1, 0xe, 0xf, 0x39, 0xc, 0xd, 0x1a,
-[0x30] 0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34,
-[0x38] 0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
-[0x40] 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0x63, 0x46,
-[0x48] 0x77, 0x52, 0x47, 0x49, 0x53, 0x4f, 0x51, 0x4d,
-[0x50] 0x4b, 0x50, 0x48, 0x45, 0x35, 0x37, 0x4a, 0x4e,
-[0x58] 0x1c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47,
-[0x60] 0x48, 0x49, 0x52, 0x53, 0x56, 0x7f, 0x74, 0x75,
-[0x68] 0x55, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-[0x70] 0x78, 0x79, 0x7a, 0x7b, 0x0, 0x0, 0x0, 0x0,
-[0x78] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71,
-[0x80] 0x73, 0x72, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0,
-[0x88] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0x90] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0x98] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xa0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xa8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xb0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xb8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xc0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xc8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xd0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xd8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[0xe0] 0x1d, 0x2a, 0x38, 0x7d, 0x61, 0x36, 0x64, 0x7e,
-[0xe8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x73, 0x72, 0x71,
-[0xf0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-[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
-setbootproto(KDev* f, int eid)
-{
- int r, id;
-
- r = Rh2d|Rclass|Riface;
- id = f->dev->usb->ep[eid]->iface->id;
- return usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0);
-}
-
-static int
-setleds(KDev* f, int eid, uchar leds)
-{
- return usbcmd(f->dev, Rh2d|Rclass|Riface, Setreport, Reportout, 0, &leds, 1);
-}
-
-/*
- * Try to recover from a babble error. A port reset is the only way out.
- * BUG: we should be careful not to reset a bundle with several devices.
- */
-static void
-recoverkb(KDev *f)
-{
- int i;
-
- close(f->dev->dfd); /* it's for usbd now */
- devctl(f->dev, "reset");
- for(i = 0; i < 10; i++){
- sleep(500);
- if(opendevdata(f->dev, ORDWR) >= 0){
- setbootproto(f, f->ep->id);
- break;
- }
- /* else usbd still working... */
- }
-}
-
-static void
-kbfatal(KDev *kd, char *sts)
-{
- Dev *dev;
-
- if(sts != nil)
- fprint(2, "kb: fatal: %s\n", sts);
- else
- fprint(2, "kb: exiting\n");
- 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.
- */
- threadexits(sts);
-}
-
-static int
-scale(KDev *f, int x)
-{
- int sign = 1;
-
- if(x < 0){
- sign = -1;
- x = -x;
- }
- switch(x){
- case 0:
- case 1:
- case 2:
- case 3:
- break;
- case 4:
- x = 6 + (f->accel>>2);
- break;
- case 5:
- x = 9 + (f->accel>>1);
- break;
- default:
- x *= MaxAcc;
- break;
- }
- 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 void
-ptrwork(void* a)
-{
- static char maptab[] = {0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7};
- int x, y, b, c, ptrfd;
- int mfd, nerrs;
- char buf[32];
- char mbuf[80];
- KDev* f = a;
- int hipri;
-
- hipri = nerrs = 0;
- ptrfd = f->ep->dfd;
- mfd = f->in->fd;
-
- if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf)
- kbfatal(f, "weird mouse maxpkt");
- for(;;){
- memset(buf, 0, sizeof buf);
- if(f->ep == nil)
- kbfatal(f, nil);
- c = read(ptrfd, buf, f->ep->maxpkt);
- assert(f->dev != nil);
- assert(f->ep != nil);
- if(c < 0){
- dprint(2, "kb: mouse: %s: read: %r\n", f->ep->dir);
- if(++nerrs < 3){
- recoverkb(f);
- continue;
- }
- }
- if(c <= 0)
- kbfatal(f, nil);
- if(c < 3)
- continue;
- if(f->accel){
- x = scale(f, buf[1]);
- y = scale(f, buf[2]);
- }else{
- x = buf[1];
- y = buf[2];
- }
- b = maptab[buf[0] & 0x7];
- if(c > 3 && buf[3] == 1) /* up */
- b |= 0x08;
- if(c > 3 && buf[3] == -1) /* down */
- b |= 0x10;
- if(kbdebug > 1)
- fprint(2, "kb: m%11d %11d %11d\n", x, y, b);
- seprint(mbuf, mbuf+sizeof(mbuf), "m%11d %11d %11d", x, y,b);
- if(write(mfd, mbuf, strlen(mbuf)) < 0)
- kbfatal(f, "mousein i/o");
- if(hipri == 0){
- sethipri();
- hipri = 1;
- }
- }
-}
-
-static void
-stoprepeat(KDev *f)
-{
- sendul(f->repeatc, Awakemsg);
-}
-
-static void
-startrepeat(KDev *f, uchar esc1, uchar sc)
-{
- ulong c;
-
- if(esc1)
- c = SCesc1 << 8 | (sc & 0xff);
- else
- c = sc;
- sendul(f->repeatc, c);
-}
-
-static void
-putscan(int kbinfd, uchar esc, uchar sc)
-{
- uchar s[2] = {SCesc1, 0};
-
- if(sc == 0x41){
- kbdebug += 2;
- return;
- }
- if(sc == 0x42){
- kbdebug = 0;
- return;
- }
- if(kbdebug)
- fprint(2, "sc: %x %x\n", (esc? SCesc1: 0), sc);
- s[1] = sc;
- if(esc && sc != 0)
- write(kbinfd, s, 2);
- else if(sc != 0)
- write(kbinfd, s+1, 1);
-}
-
-static void
-repeatproc(void* a)
-{
- KDev *f;
- Channel *repeatc;
- int kbdinfd;
- ulong l, t, i;
- uchar esc1, sc;
-
- /*
- * too many jumps here.
- * Rewrite instead of debug, if needed.
- */
- f = a;
- repeatc = f->repeatc;
- kbdinfd = f->in->fd;
- 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);
- }
- putscan(kbdinfd, esc1, sc);
- t = 30;
- }
-Abort:
- chanfree(repeatc);
- threadexits("aborted");
-
-}
-
-
-#define hasesc1(sc) (((sc) > 0x47) || ((sc) == 0x38))
-
-static void
-putmod(int fd, uchar mods, uchar omods, uchar mask, uchar esc, uchar sc)
-{
- /* BUG: Should be a single write */
- if((mods&mask) && !(omods&mask))
- putscan(fd, esc, sc);
- if(!(mods&mask) && (omods&mask))
- putscan(fd, esc, Keyup|sc);
-}
-
-/*
- * This routine diffs the state with the last known state
- * and invents the scan codes that would have been sent
- * by a non-usb keyboard in that case. This also requires supplying
- * the extra esc1 byte as well as keyup flags.
- * The aim is to allow future addition of other keycode pages
- * for other keyboards.
- */
-static uchar
-putkeys(KDev *f, uchar buf[], uchar obuf[], int n, uchar dk)
-{
- int i, j;
- uchar uk;
- int fd;
-
- fd = f->in->fd;
- 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);
- putmod(fd, buf[0], obuf[0], Mcompose, 0, SCcompose);
- putmod(fd, buf[0], obuf[0], Maltgr, 1, SCcompose);
-
- /* Report key downs */
- for(i = 2; i < n; i++){
- for(j = 2; j < n; j++)
- if(buf[i] == obuf[j])
- break;
- if(j == n && buf[i] != 0){
- dk = sctab[buf[i]];
- putscan(fd, hasesc1(dk), dk);
- startrepeat(f, hasesc1(dk), dk);
- }
- }
-
- /* Report key ups */
- uk = 0;
- for(i = 2; i < n; i++){
- for(j = 2; j < n; j++)
- if(obuf[i] == buf[j])
- break;
- if(j == n && obuf[i] != 0){
- uk = sctab[obuf[i]];
- putscan(fd, hasesc1(uk), uk|Keyup);
- }
- }
- if(uk && (dk == 0 || dk == uk)){
- stoprepeat(f);
- dk = 0;
- }
- return dk;
-}
-
-static int
-kbdbusy(uchar* buf, int n)
-{
- int i;
-
- for(i = 1; i < n; i++)
- if(buf[i] == 0 || buf[i] != buf[0])
- return 0;
- return 1;
-}
-
-static void
-kbdwork(void *a)
-{
- int c, i, kbdfd, nerrs;
- uchar dk, buf[64], lbuf[64];
- char err[128];
- KDev *f = a;
-
- kbdfd = f->ep->dfd;
-
- if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf)
- kbfatal(f, "weird maxpkt");
-
- f->repeatc = chancreate(sizeof(ulong), 0);
- if(f->repeatc == nil)
- kbfatal(f, "chancreate failed");
-
- proccreate(repeatproc, f, Stack);
- memset(lbuf, 0, sizeof lbuf);
- dk = nerrs = 0;
- for(;;){
- memset(buf, 0, sizeof buf);
- c = read(kbdfd, buf, f->ep->maxpkt);
- assert(f->dev != nil);
- assert(f->ep != nil);
- if(c < 0){
- rerrstr(err, sizeof(err));
- fprint(2, "kb: %s: read: %s\n", f->ep->dir, err);
- if(strstr(err, "babble") != 0 && ++nerrs < 3){
- recoverkb(f);
- continue;
- }
- }
- if(c <= 0)
- kbfatal(f, nil);
- if(c < 3)
- continue;
- if(kbdbusy(buf + 2, c - 2))
- continue;
- if(usbdebug > 2 || kbdebug > 1){
- fprint(2, "kbd mod %x: ", buf[0]);
- for(i = 2; i < c; i++)
- fprint(2, "kc %x ", buf[i]);
- fprint(2, "\n");
- }
- dk = putkeys(f, buf, lbuf, f->ep->maxpkt, dk);
- memmove(lbuf, buf, c);
- nerrs = 0;
- }
-}
-
-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);
- }
- dprint(2, "freekdev\n");
- free(kd);
-}
-
-static void
-kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), int accel)
-{
- KDev *kd;
-
- qlock(&inlck);
- if(in->fd < 0){
- in->fd = open(in->name, OWRITE);
- if(in->fd < 0){
- fprint(2, "kb: %s: %r\n", in->name);
- qunlock(&inlck);
- return;
- }
- }
- in->ref++; /* for kd->in = in */
- qunlock(&inlck);
- kd = d->aux = emallocz(sizeof(KDev), 1);
- d->free = freekdev;
- kd->in = in;
- kd->dev = d;
- if(setbootproto(kd, ep->id) < 0){
- fprint(2, "kb: %s: bootproto: %r\n", d->dir);
- return;
- }
- kd->accel = accel;
- kd->ep = openep(d, ep->id);
- if(kd->ep == nil){
- fprint(2, "kb: %s: openep %d: %r\n", d->dir, ep->id);
- return;
- }
- if(opendevdata(kd->ep, OREAD) < 0){
- fprint(2, "kb: %s: opendevdata: %r\n", kd->ep->dir);
- closedev(kd->ep);
- kd->ep = nil;
- return;
- }
- if(setleds(kd, ep->id, 0) < 0){
- fprint(2, "kb: %s: setleds: %r\n", d->dir);
- return;
- }
- incref(d);
- proccreate(f, kd, Stack);
-}
-
-static int
-usage(void)
-{
- werrstr("usage: usb/kb [-dkm] [-a n] [-N nb]");
- return -1;
-}
-
-int
-kbmain(Dev *d, int argc, char* argv[])
-{
- int i, kena, pena, accel, devid;
- Usbdev *ud;
- Ep *ep;
-
- kena = pena = 1;
- accel = 0;
- devid = d->id;
- ARGBEGIN{
- case 'a':
- accel = strtol(EARGF(usage()), nil, 0);
- break;
- case 'd':
- kbdebug++;
- break;
- case 'k':
- kena = 1;
- pena = 0;
- break;
- case 'm':
- kena = 0;
- pena = 1;
- break;
- case 'N':
- devid = atoi(EARGF(usage())); /* ignore dev number */
- break;
- default:
- return usage();
- }ARGEND;
- if(argc != 0){
- return usage();
- }
- USED(devid);
- ud = d->usb;
- d->aux = nil;
- dprint(2, "kb: main: dev %s ref %ld\n", d->dir, d->ref);
- for(i = 0; i < nelem(ud->ep); i++){
- if((ep = ud->ep[i]) == nil)
- break;
- if(kena && ep->type == Eintr && ep->dir == Ein)
- if(ep->iface->csp == KbdCSP)
- kbstart(d, ep, &kbdin, kbdwork, accel);
- if(pena && ep->type == Eintr && ep->dir == Ein)
- if(ep->iface->csp == PtrCSP)
- kbstart(d, ep, &ptrin, ptrwork, accel);
- }
- return 0;
-}