From mboxrd@z Thu Jan 1 00:00:00 1970 To: 9fans@9fans.net Date: Mon, 7 Jul 2014 13:58:59 +0900 From: kokamoto@hera.eonet.ne.jp Message-ID: <2679b40bcf47aea51e9f995c6e1e775c@eonet.ne.jp> In-Reply-To: References: <7005f4ccd307af5bad9ba72cd7fabff6@quintile.net> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="upas-vsuwtekxtjyxjfkqimizvcyrdu" Subject: Re: [9fans] Building a Raspberry Pi image / Keyboard support Topicbox-Message-UUID: 00d15f88-ead9-11e9-9d60-3106f5b1d025 This is a multi-part message in MIME format. --upas-vsuwtekxtjyxjfkqimizvcyrdu Content-Disposition: inline Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit > PS: I decided to perchase it. Igot pi board from amazon.jp, and yes it's nice for Plan9 terminal. I'm using max 1.8A power supply, and usb mose and keyboard. No problem so far. I can use Japanese keyboard here. I'm using 20" Sharp LC-20E90 with HDMI cable, then I got 1184x624 display size (sigh). Any idea to exand this? As I have this TV in a diffrent room from the network rooter, so I have to use wireless LAN which I've not purchased bridge. Therefore, this is standalone, isolated Plan9 terminal, Hmmm. I attached my Japanese keyboard program here, which deals with multibyte sequence of key codes. Base is same as Gorka's (probably) program. This is the same one which I sent to eric. If anyone want to modify this for your language, don't warry about lisense etc. Just run games/mahjongg, and got good feeling of the graphic speed from this toy like board! Kenji --upas-vsuwtekxtjyxjfkqimizvcyrdu Content-Disposition: attachment; filename=kbjpn.c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable /* * 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). * * If there is no keyboard, it tries to setup the mouse properly, else it= falls * back to boot protocol. */ #include #include #include #include "usb.h" #include "hid.h" enum { Stoprpt =3D -2, Tick =3D -3, Exiting =3D -4, Msec =3D 1000*1000, /* msec per ns */ Dwcidle =3D 8, }; typedef struct KDev KDev; typedef struct Kbd Kbd; typedef struct Mouse Mouse; typedef struct Kin Kin; struct Kbd { Channel* repeatc; Channel* exitc; long nproc; }; struct Mouse { int accel; /* only for mouse */ }; struct KDev { Dev* dev; /* usb device*/ Dev* ep; /* endpoint to get events */ Kin* in; /* used to send events to kernel */ int idle; /* min time between reports (=C3=97 4ms) */ int bootp; /* has associated keyboard */ int debug; Kbd; Mouse; HidRepTempl templ; int (*ptrvals)(KDev *kd, Chain *ch, int *px, int *py, int *pb); }; /* * 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. =3D=3D=3Ddeleted by K.Okamoto=3D=3D=3D * static char sctab[256] =3D { [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, }; */ /* K.Okamoto */ static char sctab[256] =3D=20 { [0x00] 0x0, 0xff, 0xfc, 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, 0x37, 0x46, [0x48] 0xc6, 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, 0x0, 0x5e, 0x59, [0x68] 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, [0x70] 0x6c, 0x6d, 0x6e, 0x76, 0x0, 0x0, 0x0, 0x0, [0x78] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, [0x80] 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e, 0x0, 0x73, [0x88] 0x70, 0x7d, 0x79, 0x7b, 0x5c, 0x0, 0x0, 0x0, [0x90] 0xf2, 0xf1, 0x78, 0x77, 0x76, 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, 0x5b, 0x1d, 0x36, 0x38, 0x5c, [0xe8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, [0xf0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, [0xf8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; static QLock inlck; static Kin kbdin =3D { .ref =3D 0, .name =3D "#=CE=99/kbin", .fd =3D -1, }; static Kin ptrin =3D { .ref =3D 0, .name =3D "#m/mousein", .fd =3D -1, }; static int ptrbootpvals(KDev *kd, Chain *ch, int *px, int *py, int *pb); static int ptrrepvals(KDev *kd, Chain *ch, int *px, int *py, int *pb); static int setbootproto(KDev* f, int eid, uchar *, int) { int nr, r, id; f->ptrvals =3D ptrbootpvals; r =3D Rh2d|Rclass|Riface; dprint(2, "setting boot protocol\n"); id =3D f->dev->usb->ep[eid]->iface->id; nr =3D usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0); if(nr < 0) return -1; usbcmd(f->dev, r, Setidle, f->idle<<8, id, nil, 0); return nr; } static uchar ignoredesc[128]; static int setfirstconfig(KDev* f, int eid, uchar *desc, int descsz) { int nr, r, id, i; dprint(2, "setting first config\n"); if(desc =3D=3D nil){ descsz =3D sizeof ignoredesc; desc =3D ignoredesc; } id =3D f->dev->usb->ep[eid]->iface->id; r =3D Rh2d | Rstd | Rdev; nr =3D usbcmd(f->dev, r, Rsetconf, 1, 0, nil, 0); if(nr < 0) return -1; r =3D Rh2d | Rclass | Riface; nr =3D usbcmd(f->dev, r, Setidle, f->idle<<8, id, nil, 0); if(nr < 0) return -1; r =3D Rd2h | Rstd | Riface; nr=3Dusbcmd(f->dev, r, Rgetdesc, Dreport<<8, id, desc, descsz); if(nr <=3D 0) return -1; if(f->debug){ fprint(2, "report descriptor:"); for(i =3D 0; i < nr; i++){ if(i%8 =3D=3D 0) fprint(2, "\n\t"); fprint(2, "%#2.2ux ", desc[i]); } fprint(2, "\n"); } f->ptrvals =3D ptrrepvals; return nr; } /* * 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 =3D 0; i < 10; i++){ if(i =3D=3D 5) f->bootp++; sleep(500); if(opendevdata(f->dev, ORDWR) >=3D 0){ if(f->bootp) /* TODO func pointer */ setbootproto(f, f->ep->id, nil, 0); else setfirstconfig(f, f->ep->id, nil, 0); break; } /* else usbd still working... */ } } static void kbfatal(KDev *kd, char *sts) { Dev *dev; if(sts !=3D nil) fprint(2, "kb: fatal: %s\n", sts); else fprint(2, "kb: exiting\n"); if(kd->repeatc !=3D nil){ chanclose(kd->repeatc); for(; kd->nproc !=3D 0; kd->nproc--) recvul(kd->exitc); chanfree(kd->repeatc); chanfree(kd->exitc); kd->repeatc =3D nil; kd->exitc =3D nil; } dev =3D kd->dev; kd->dev =3D nil; if(kd->ep !=3D nil) closedev(kd->ep); kd->ep =3D nil; devctl(dev, "detach"); closedev(dev); /* * free(kd); done by closedev. */ threadexits(sts); } static int scale(KDev *f, int x) { int sign =3D 1; if(x < 0){ sign =3D -1; x =3D -x; } switch(x){ case 0: case 1: case 2: case 3: break; case 4: x =3D 6 + (f->accel>>2); break; case 5: x =3D 9 + (f->accel>>1); break; default: x *=3D 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 =3D open(fn, OWRITE); if(fd >=3D 0) { fprint(fd, "pri 13"); close(fd); } } static int ptrrepvals(KDev *kd, Chain *ch, int *px, int *py, int *pb) { int i, x, y, b, c; static char buts[] =3D {0x0, 0x2, 0x1}; c =3D ch->e / 8; /* sometimes there is a report id, sometimes not */ if(c =3D=3D kd->templ.sz + 1) if(ch->buf[0] =3D=3D kd->templ.id) ch->b +=3D 8; else return -1; parsereport(&kd->templ, ch); if(kd->debug > 1) dumpreport(&kd->templ); if(c < 3) return -1; x =3D hidifcval(&kd->templ, KindX, 0); y =3D hidifcval(&kd->templ, KindY, 0); b =3D 0; for(i =3D 0; itempl, KindButtons, i) & 1) << buts[i]; if(c > 3 && hidifcval(&kd->templ, KindWheel, 0) > 0) /* up */ b |=3D 0x10; if(c > 3 && hidifcval(&kd->templ, KindWheel, 0) < 0) /* down */ b |=3D 0x08; *px =3D x; *py =3D y; *pb =3D b; return 0; } static int ptrbootpvals(KDev *kd, Chain *ch, int *px, int *py, int *pb) { int b, c; char x, y; static char maptab[] =3D {0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7}; c =3D ch->e / 8; if(c < 3) return -1; if(kd->templ.nifcs){ x =3D hidifcval(&kd->templ, KindX, 0); y =3D hidifcval(&kd->templ, KindY, 0); }else{ /* no report descriptor for boot protocol */ x =3D ((signed char*)ch->buf)[1]; y =3D ((signed char*)ch->buf)[2]; } b =3D maptab[ch->buf[0] & 0x7]; if(c > 3 && ch->buf[3] =3D=3D 1) /* up */ b |=3D 0x08; if(c > 3 && ch->buf[3] =3D=3D 0xff) /* down */ b |=3D 0x10; *px =3D x; *py =3D y; *pb =3D b; return 0; } static void ptrwork(void* a) { int hipri, mfd, nerrs, x, y, b, c, ptrfd; char mbuf[80]; Chain ch; KDev* f =3D a; threadsetname("ptr %s", f->ep->dir); hipri =3D nerrs =3D 0; ptrfd =3D f->ep->dfd; mfd =3D f->in->fd; if(f->ep->maxpkt < 3 || f->ep->maxpkt > MaxChLen) kbfatal(f, "weird mouse maxpkt"); for(;;){ memset(ch.buf, 0, MaxChLen); if(f->ep =3D=3D nil) kbfatal(f, nil); c =3D read(ptrfd, ch.buf, f->ep->maxpkt); assert(f->dev !=3D nil); assert(f->ep !=3D nil); if(c < 0){ dprint(2, "kb: mouse: %s: read: %r\n", f->ep->dir); if(++nerrs < 3){ recoverkb(f); continue; } } if(c <=3D 0) kbfatal(f, nil); ch.b =3D 0; ch.e =3D 8 * c; if(f->ptrvals(f, &ch, &x, &y, &b) < 0) continue; if(f->accel){ x =3D scale(f, x); y =3D scale(f, y); } if(f->debug > 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 =3D=3D 0){ sethipri(); hipri =3D 1; } } } static void stoprepeat(KDev *f) { sendul(f->repeatc, Stoprpt); } static void startrepeat(KDev *f, uchar esc1, uchar sc) { ulong c; if(esc1) c =3D SCesc1 << 8 | (sc & 0xff); else c =3D sc; sendul(f->repeatc, c); } static void putscan(KDev *f, uchar esc, uchar sc) { int kbinfd; uchar s[2] =3D {SCesc1, 0}; kbinfd =3D f->in->fd; if(sc =3D=3D 0x41){ f->debug +=3D 2; return; } if(sc =3D=3D 0x42){ f->debug =3D 0; return; } if(f->debug > 1) fprint(2, "sc: %x %x\n", (esc? SCesc1: 0), sc); s[1] =3D sc; if(esc && sc !=3D 0) write(kbinfd, s, 2); else if(sc !=3D 0) write(kbinfd, s+1, 1); } static void repeattimerproc(void *a) { Channel *c; KDev *f; threadsetname("kbd reptimer"); f =3D a; c =3D f->repeatc; for(;;){ sleep(30); if(sendul(c, Tick) =3D=3D -1) break; } sendul(f->exitc, Exiting); threadexits("aborted"); } static void repeatproc(void* a) { KDev *f; Channel *c; int code; uint l; uvlong timeout; threadsetname("kbd repeat"); f =3D a; c =3D f->repeatc; timeout =3D 0; code =3D -1; for(;;){ switch(l =3D recvul(c)){ default: code =3D l; timeout =3D nsec() + 500*Msec; break; case ~0ul: sendul(f->exitc, Exiting); threadexits("aborted"); break; case Stoprpt: code =3D -1; break; case Tick: if(code =3D=3D -1 || nsec() < timeout) continue; putscan(f, (uchar)(code>>8), (uchar)code); timeout =3D nsec() + 30*Msec; break; } } } static uchar hasesc1(uchar usage) /* added by K.Okamoto */ { if(usage=3D=3D0x46 || (usage>0x47 && usage <0x53) || usage=3D=3D0x54 || usage=3D=3D0x66 || ((usage>0xe2 && usage<0xe8) && usage!=3D0xe5)) return 1; else return 0; } static void putmod(KDev *f, uchar mods, uchar omods, uchar mask, uchar esc, uchar sc) { /* BUG: Should be a single write */ if((mods&mask) && !(omods&mask)) putscan(f, esc, sc); if(!(mods&mask) && (omods&mask)) putscan(f, 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; putmod(f, buf[0], obuf[0], Mctrl, 0, SCctrl); putmod(f, buf[0], obuf[0], (1<ep->dir); kbdfd =3D f->ep->dfd; if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf) kbfatal(f, "weird maxpkt"); f->exitc =3D chancreate(sizeof(ulong), 0); if(f->exitc =3D=3D nil) kbfatal(f, "chancreate failed"); f->repeatc =3D chancreate(sizeof(ulong), 0); if(f->repeatc =3D=3D nil){ chanfree(f->exitc); kbfatal(f, "chancreate failed"); } f->nproc =3D 2; proccreate(repeatproc, f, Stack); proccreate(repeattimerproc, f, Stack); memset(lbuf, 0, sizeof lbuf); dk =3D nerrs =3D 0; for(;;){ memset(buf, 0, sizeof buf); c =3D read(kbdfd, buf, f->ep->maxpkt); assert(f->dev !=3D nil); assert(f->ep !=3D nil); if(c < 0){ rerrstr(err, sizeof(err)); fprint(2, "kb: %s: read: %s\n", f->ep->dir, err); if(strstr(err, "babble") !=3D 0 && ++nerrs < 3){ recoverkb(f); continue; } } if(c <=3D 0) kbfatal(f, nil); if(c < 3) continue; if(kbdbusy(buf + 2, c - 2)) continue; if(usbdebug > 2 || f->debug > 1){ fprint(2, "kbd mod %x: ", buf[0]); for(i =3D 2; i < c; i++) fprint(2, "kc %x ", buf[i]); fprint(2, "\n"); } dk =3D putkeys(f, buf, lbuf, f->ep->maxpkt, dk); memmove(lbuf, buf, c); nerrs =3D 0; } } static void freekdev(void *a) { KDev *kd; kd =3D a; if(kd->in !=3D nil){ qlock(&inlck); if(--kd->in->ref =3D=3D 0){ close(kd->in->fd); kd->in->fd =3D -1; } qunlock(&inlck); } dprint(2, "freekdev\n"); free(kd); } static void kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), KDev *kd) { uchar desc[512]; int n, res; qlock(&inlck); if(in->fd < 0){ in->fd =3D open(in->name, OWRITE); if(in->fd < 0){ fprint(2, "kb: %s: %r\n", in->name); qunlock(&inlck); return; } } in->ref++; /* for kd->in =3D in */ qunlock(&inlck); d->free =3D freekdev; kd->in =3D in; kd->dev =3D d; res =3D -1; kd->ep =3D openep(d, ep->id); if(kd->ep =3D=3D nil){ fprint(2, "kb: %s: openep %d: %r\n", d->dir, ep->id); return; } if(in =3D=3D &kbdin){ /* * DWC OTG controller misses some split transaction inputs. * Set nonzero idle time to return more frequent reports * of keyboard state, to avoid losing key up/down events. */ n =3D read(d->cfd, desc, sizeof desc - 1); if(n > 0){ desc[n] =3D 0; if(strstr((char*)desc, "dwcotg") !=3D nil) kd->idle =3D Dwcidle; } } if(!kd->bootp) res=3D setfirstconfig(kd, ep->id, desc, sizeof desc); if(res > 0) res =3D parsereportdesc(&kd->templ, desc, sizeof desc); /* if we could not set the first config, we give up */ if(kd->bootp || res < 0){ kd->bootp =3D 1; if(setbootproto(kd, ep->id, nil, 0) < 0){ fprint(2, "kb: %s: bootproto: %r\n", d->dir); return; } }else if(kd->debug) dumpreport(&kd->templ); if(opendevdata(kd->ep, OREAD) < 0){ fprint(2, "kb: %s: opendevdata: %r\n", kd->ep->dir); closedev(kd->ep); kd->ep =3D nil; return; } incref(d); proccreate(f, kd, Stack); } static int usage(void) { werrstr("usage: usb/kb [-bdkm] [-a n] [-N nb]"); return -1; } int kbmain(Dev *d, int argc, char* argv[]) { int bootp, i, kena, pena, accel, devid, debug; Ep *ep; KDev *kd; Usbdev *ud; kena =3D pena =3D 1; bootp =3D 0; accel =3D 0; debug =3D 0; devid =3D d->id; ARGBEGIN{ case 'a': accel =3D strtol(EARGF(usage()), nil, 0); break; case 'd': debug++; break; case 'k': kena =3D 1; pena =3D 0; break; case 'm': kena =3D 0; pena =3D 1; break; case 'N': devid =3D atoi(EARGF(usage())); /* ignore dev number */ break; case 'b': bootp++; break; default: return usage(); }ARGEND; if(argc !=3D 0) return usage(); USED(devid); ud =3D d->usb; d->aux =3D nil; dprint(2, "kb: main: dev %s ref %ld\n", d->dir, d->ref); if(kena) for(i =3D 0; i < nelem(ud->ep); i++) if((ep =3D ud->ep[i]) =3D=3D nil) break; else if(ep->iface->csp =3D=3D KbdCSP) bootp =3D 1; for(i =3D 0; i < nelem(ud->ep); i++){ if((ep =3D ud->ep[i]) =3D=3D nil) continue; if(kena && ep->type =3D=3D Eintr && ep->dir =3D=3D Ein && ep->iface->csp =3D=3D KbdCSP){ kd =3D d->aux =3D emallocz(sizeof(KDev), 1); kd->accel =3D 0; kd->bootp =3D 1; kd->debug =3D debug; kbstart(d, ep, &kbdin, kbdwork, kd); } if(pena && ep->type =3D=3D Eintr && ep->dir =3D=3D Ein && ep->iface->csp =3D=3D PtrCSP){ kd =3D d->aux =3D emallocz(sizeof(KDev), 1); kd->accel =3D accel; kd->bootp =3D bootp; kd->debug =3D debug; kbstart(d, ep, &ptrin, ptrwork, kd); } } return 0; } --upas-vsuwtekxtjyxjfkqimizvcyrdu--