xref: /plan9/sys/src/cmd/usb/kb/kb.c (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
1 /*
2  * USB Human Interaction Device: keyboard and mouse.
3  *
4  * If there's no usb keyboard, it tries to setup the mouse, if any.
5  * It should be started at boot time.
6  *
7  * Mouse events are converted to the format of mouse(3)'s mousein file.
8  * Keyboard keycodes are translated to scan codes and sent to kbin(3).
9  *
10  * If there is no keyboard, it tries to setup the mouse properly, else it falls
11  * back to boot protocol.
12  */
13 
14 #include <u.h>
15 #include <libc.h>
16 #include <thread.h>
17 #include "usb.h"
18 #include "hid.h"
19 
20 enum
21 {
22 	Awakemsg= 0xdeaddead,
23 	Diemsg	= 0xbeefbeef,
24 	Dwcidle	= 8,
25 };
26 
27 typedef struct KDev KDev;
28 typedef struct Kin Kin;
29 
30 struct KDev
31 {
32 	Dev*	dev;		/* usb device*/
33 	Dev*	ep;		/* endpoint to get events */
34 	Kin*	in;		/* used to send events to kernel */
35 	int	idle;		/* min time between reports (× 4ms) */
36 	Channel*repeatc;	/* only for keyboard */
37 	int	accel;		/* only for mouse */
38 	int	bootp;		/* has associated keyboard */
39 	int	debug;
40 	HidRepTempl templ;
41 	int	(*ptrvals)(KDev *kd, Chain *ch, int *px, int *py, int *pb);
42 };
43 
44 /*
45  * Kbdin and mousein files must be shared among all instances.
46  */
47 struct Kin
48 {
49 	int	ref;
50 	int	fd;
51 	char*	name;
52 };
53 
54 /*
55  * Map for the logitech bluetooth mouse with 8 buttons and wheels.
56  *	{ ptr ->mouse}
57  *	{ 0x01, 0x01 },	// left
58  *	{ 0x04, 0x02 },	// middle
59  *	{ 0x02, 0x04 },	// right
60  *	{ 0x40, 0x08 },	// up
61  *	{ 0x80, 0x10 },	// down
62  *	{ 0x10, 0x08 },	// side up
63  *	{ 0x08, 0x10 },	// side down
64  *	{ 0x20, 0x02 }, // page
65  * besides wheel and regular up/down report the 4th byte as 1/-1
66  */
67 
68 /*
69  * key code to scan code; for the page table used by
70  * the logitech bluetooth keyboard.
71  */
72 static char sctab[256] =
73 {
74 [0x00]	0x0,	0x0,	0x0,	0x0,	0x1e,	0x30,	0x2e,	0x20,
75 [0x08]	0x12,	0x21,	0x22,	0x23,	0x17,	0x24,	0x25,	0x26,
76 [0x10]	0x32,	0x31,	0x18,	0x19,	0x10,	0x13,	0x1f,	0x14,
77 [0x18]	0x16,	0x2f,	0x11,	0x2d,	0x15,	0x2c,	0x2,	0x3,
78 [0x20]	0x4,	0x5,	0x6,	0x7,	0x8,	0x9,	0xa,	0xb,
79 [0x28]	0x1c,	0x1,	0xe,	0xf,	0x39,	0xc,	0xd,	0x1a,
80 [0x30]	0x1b,	0x2b,	0x2b,	0x27,	0x28,	0x29,	0x33,	0x34,
81 [0x38]	0x35,	0x3a,	0x3b,	0x3c,	0x3d,	0x3e,	0x3f,	0x40,
82 [0x40]	0x41,	0x42,	0x43,	0x44,	0x57,	0x58,	0x63,	0x46,
83 [0x48]	0x77,	0x52,	0x47,	0x49,	0x53,	0x4f,	0x51,	0x4d,
84 [0x50]	0x4b,	0x50,	0x48,	0x45,	0x35,	0x37,	0x4a,	0x4e,
85 [0x58]	0x1c,	0x4f,	0x50,	0x51,	0x4b,	0x4c,	0x4d,	0x47,
86 [0x60]	0x48,	0x49,	0x52,	0x53,	0x56,	0x7f,	0x74,	0x75,
87 [0x68]	0x55,	0x59,	0x5a,	0x5b,	0x5c,	0x5d,	0x5e,	0x5f,
88 [0x70]	0x78,	0x79,	0x7a,	0x7b,	0x0,	0x0,	0x0,	0x0,
89 [0x78]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x71,
90 [0x80]	0x73,	0x72,	0x0,	0x0,	0x0,	0x7c,	0x0,	0x0,
91 [0x88]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
92 [0x90]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
93 [0x98]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
94 [0xa0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
95 [0xa8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
96 [0xb0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
97 [0xb8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
98 [0xc0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
99 [0xc8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
100 [0xd0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
101 [0xd8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
102 [0xe0]	0x1d,	0x2a,	0x38,	0x7d,	0x61,	0x36,	0x64,	0x7e,
103 [0xe8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x73,	0x72,	0x71,
104 [0xf0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
105 [0xf8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
106 };
107 
108 static QLock inlck;
109 static Kin kbdin =
110 {
111 	.ref = 0,
112 	.name = "#Ι/kbin",
113 	.fd = -1,
114 };
115 static Kin ptrin =
116 {
117 	.ref = 0,
118 	.name = "#m/mousein",
119 	.fd = -1,
120 };
121 
122 static int ptrbootpvals(KDev *kd, Chain *ch, int *px, int *py, int *pb);
123 static int ptrrepvals(KDev *kd, Chain *ch, int *px, int *py, int *pb);
124 
125 static int
setbootproto(KDev * f,int eid,uchar *,int)126 setbootproto(KDev* f, int eid, uchar *, int)
127 {
128 	int nr, r, id;
129 
130 	f->ptrvals = ptrbootpvals;
131 	r = Rh2d|Rclass|Riface;
132 	dprint(2, "setting boot protocol\n");
133 	id = f->dev->usb->ep[eid]->iface->id;
134 	nr = usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0);
135 	if(nr < 0)
136 		return -1;
137 	usbcmd(f->dev, r, Setidle, f->idle<<8, id, nil, 0);
138 	return nr;
139 }
140 
141 static uchar ignoredesc[128];
142 
143 static int
setfirstconfig(KDev * f,int eid,uchar * desc,int descsz)144 setfirstconfig(KDev* f, int eid, uchar *desc, int descsz)
145 {
146 	int nr, r, id, i;
147 
148 	dprint(2, "setting first config\n");
149 	if(desc == nil){
150 		descsz = sizeof ignoredesc;
151 		desc = ignoredesc;
152 	}
153 	id = f->dev->usb->ep[eid]->iface->id;
154 	r = Rh2d | Rstd | Rdev;
155 	nr = usbcmd(f->dev,  r, Rsetconf, 1, 0, nil, 0);
156 	if(nr < 0)
157 		return -1;
158 	r = Rh2d | Rclass | Riface;
159 	nr = usbcmd(f->dev, r, Setidle, f->idle<<8, id, nil, 0);
160 	if(nr < 0)
161 		return -1;
162 	r = Rd2h | Rstd | Riface;
163 	nr=usbcmd(f->dev,  r, Rgetdesc, Dreport<<8, id, desc, descsz);
164 	if(nr <= 0)
165 		return -1;
166 	if(f->debug){
167 		fprint(2, "report descriptor:");
168 		for(i = 0; i < nr; i++){
169 			if(i%8 == 0)
170 				fprint(2, "\n\t");
171 			fprint(2, "%#2.2ux ", desc[i]);
172 		}
173 		fprint(2, "\n");
174 	}
175 	f->ptrvals = ptrrepvals;
176 	return nr;
177 }
178 
179 /*
180  * Try to recover from a babble error. A port reset is the only way out.
181  * BUG: we should be careful not to reset a bundle with several devices.
182  */
183 static void
recoverkb(KDev * f)184 recoverkb(KDev *f)
185 {
186 	int i;
187 
188 	close(f->dev->dfd);		/* it's for usbd now */
189 	devctl(f->dev, "reset");
190 	for(i = 0; i < 10; i++){
191 		if(i == 5)
192 			f->bootp++;
193 		sleep(500);
194 		if(opendevdata(f->dev, ORDWR) >= 0){
195 			if(f->bootp)
196 				/* TODO func pointer */
197 				setbootproto(f, f->ep->id, nil, 0);
198 			else
199 				setfirstconfig(f, f->ep->id, nil, 0);
200 			break;
201 		}
202 		/* else usbd still working... */
203 	}
204 }
205 
206 static void
kbfatal(KDev * kd,char * sts)207 kbfatal(KDev *kd, char *sts)
208 {
209 	Dev *dev;
210 
211 	if(sts != nil)
212 		fprint(2, "kb: fatal: %s\n", sts);
213 	else
214 		fprint(2, "kb: exiting\n");
215 	if(kd->repeatc != nil)
216 		nbsendul(kd->repeatc, Diemsg);
217 	dev = kd->dev;
218 	kd->dev = nil;
219 	if(kd->ep != nil)
220 		closedev(kd->ep);
221 	kd->ep = nil;
222 	devctl(dev, "detach");
223 	closedev(dev);
224 	/*
225 	 * free(kd); done by closedev.
226 	 */
227 	threadexits(sts);
228 }
229 
230 static int
scale(KDev * f,int x)231 scale(KDev *f, int x)
232 {
233 	int sign = 1;
234 
235 	if(x < 0){
236 		sign = -1;
237 		x = -x;
238 	}
239 	switch(x){
240 	case 0:
241 	case 1:
242 	case 2:
243 	case 3:
244 		break;
245 	case 4:
246 		x = 6 + (f->accel>>2);
247 		break;
248 	case 5:
249 		x = 9 + (f->accel>>1);
250 		break;
251 	default:
252 		x *= MaxAcc;
253 		break;
254 	}
255 	return sign*x;
256 }
257 
258 /*
259  * ps2 mouse is processed mostly at interrupt time.
260  * for usb we do what we can.
261  */
262 static void
sethipri(void)263 sethipri(void)
264 {
265 	char fn[30];
266 	int fd;
267 
268 	snprint(fn, sizeof fn, "/proc/%d/ctl", getpid());
269 	fd = open(fn, OWRITE);
270 	if(fd >= 0) {
271 		fprint(fd, "pri 13");
272 		close(fd);
273 	}
274 }
275 
276 static int
ptrrepvals(KDev * kd,Chain * ch,int * px,int * py,int * pb)277 ptrrepvals(KDev *kd, Chain *ch, int *px, int *py, int *pb)
278 {
279 	int i, x, y, b, c;
280 	static char buts[] = {0x0, 0x2, 0x1};
281 
282 	c = ch->e / 8;
283 
284 	/* sometimes there is a report id, sometimes not */
285 	if(c == kd->templ.sz + 1)
286 		if(ch->buf[0] == kd->templ.id)
287 			ch->b += 8;
288 		else
289 			return -1;
290 	parsereport(&kd->templ, ch);
291 
292 	if(kd->debug > 1)
293 		dumpreport(&kd->templ);
294 	if(c < 3)
295 		return -1;
296 	x = hidifcval(&kd->templ, KindX, 0);
297 	y = hidifcval(&kd->templ, KindY, 0);
298 	b = 0;
299 	for(i = 0; i<sizeof buts; i++)
300 		b |= (hidifcval(&kd->templ, KindButtons, i) & 1) << buts[i];
301 	if(c > 3 && hidifcval(&kd->templ, KindWheel, 0) > 0)	/* up */
302 		b |= 0x08;
303 	if(c > 3 && hidifcval(&kd->templ, KindWheel, 0) < 0)	/* down */
304 		b |= 0x10;
305 
306 	*px = x;
307 	*py = y;
308 	*pb = b;
309 	return 0;
310 }
311 
312 static int
ptrbootpvals(KDev * kd,Chain * ch,int * px,int * py,int * pb)313 ptrbootpvals(KDev *kd, Chain *ch, int *px, int *py, int *pb)
314 {
315 	int b, c;
316 	char x, y;
317 	static char maptab[] = {0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7};
318 
319 	c = ch->e / 8;
320 	if(c < 3)
321 		return -1;
322 	if(kd->templ.nifcs){
323 		x = hidifcval(&kd->templ, KindX, 0);
324 		y = hidifcval(&kd->templ, KindY, 0);
325 	}else{
326 		/* no report descriptor for boot protocol */
327 		x = ((signed char*)ch->buf)[1];
328 		y = ((signed char*)ch->buf)[2];
329 	}
330 
331 	b = maptab[ch->buf[0] & 0x7];
332 	if(c > 3 && ch->buf[3] == 1)		/* up */
333 		b |= 0x08;
334 	if(c > 3 && ch->buf[3] == 0xff)		/* down */
335 		b |= 0x10;
336 	*px = x;
337 	*py = y;
338 	*pb = b;
339 	return 0;
340 }
341 
342 static void
ptrwork(void * a)343 ptrwork(void* a)
344 {
345 	int hipri, mfd, nerrs, x, y, b, c, ptrfd;
346 	char mbuf[80];
347 	Chain ch;
348 	KDev* f = a;
349 
350 	threadsetname("ptr %s", f->ep->dir);
351 	hipri = nerrs = 0;
352 	ptrfd = f->ep->dfd;
353 	mfd = f->in->fd;
354 	if(f->ep->maxpkt < 3 || f->ep->maxpkt > MaxChLen)
355 		kbfatal(f, "weird mouse maxpkt");
356 	for(;;){
357 		memset(ch.buf, 0, MaxChLen);
358 		if(f->ep == nil)
359 			kbfatal(f, nil);
360 		c = read(ptrfd, ch.buf, f->ep->maxpkt);
361 		assert(f->dev != nil);
362 		assert(f->ep != nil);
363 		if(c < 0){
364 			dprint(2, "kb: mouse: %s: read: %r\n", f->ep->dir);
365 			if(++nerrs < 3){
366 				recoverkb(f);
367 				continue;
368 			}
369 		}
370 		if(c <= 0)
371 			kbfatal(f, nil);
372 		ch.b = 0;
373 		ch.e = 8 * c;
374 		if(f->ptrvals(f, &ch, &x, &y, &b) < 0)
375 			continue;
376 		if(f->accel){
377 			x = scale(f, x);
378 			y = scale(f, y);
379 		}
380 		if(f->debug > 1)
381 			fprint(2, "kb: m%11d %11d %11d\n", x, y, b);
382 		seprint(mbuf, mbuf+sizeof(mbuf), "m%11d %11d %11d", x, y,b);
383 		if(write(mfd, mbuf, strlen(mbuf)) < 0)
384 			kbfatal(f, "mousein i/o");
385 		if(hipri == 0){
386 			sethipri();
387 			hipri = 1;
388 		}
389 	}
390 }
391 
392 static void
stoprepeat(KDev * f)393 stoprepeat(KDev *f)
394 {
395 	sendul(f->repeatc, Awakemsg);
396 }
397 
398 static void
startrepeat(KDev * f,uchar esc1,uchar sc)399 startrepeat(KDev *f, uchar esc1, uchar sc)
400 {
401 	ulong c;
402 
403 	if(esc1)
404 		c = SCesc1 << 8 | (sc & 0xff);
405 	else
406 		c = sc;
407 	sendul(f->repeatc, c);
408 }
409 
410 static void
putscan(KDev * f,uchar esc,uchar sc)411 putscan(KDev *f, uchar esc, uchar sc)
412 {
413 	int kbinfd;
414 	uchar s[2] = {SCesc1, 0};
415 
416 	kbinfd = f->in->fd;
417 	if(sc == 0x41){
418 		f->debug += 2;
419 		return;
420 	}
421 	if(sc == 0x42){
422 		f->debug = 0;
423 		return;
424 	}
425 	if(f->debug > 1)
426 		fprint(2, "sc: %x %x\n", (esc? SCesc1: 0), sc);
427 	s[1] = sc;
428 	if(esc && sc != 0)
429 		write(kbinfd, s, 2);
430 	else if(sc != 0)
431 		write(kbinfd, s+1, 1);
432 }
433 
434 static void
repeatproc(void * a)435 repeatproc(void* a)
436 {
437 	KDev *f;
438 	Channel *repeatc;
439 	ulong l, t, i;
440 	uchar esc1, sc;
441 
442 	threadsetname("kbd repeat");
443 	/*
444 	 * too many jumps here.
445 	 * Rewrite instead of debug, if needed.
446 	 */
447 	f = a;
448 	repeatc = f->repeatc;
449 	l = Awakemsg;
450 Repeat:
451 	if(l == Diemsg)
452 		goto Abort;
453 	while(l == Awakemsg)
454 		l = recvul(repeatc);
455 	if(l == Diemsg)
456 		goto Abort;
457 	esc1 = l >> 8;
458 	sc = l;
459 	t = 160;
460 	for(;;){
461 		for(i = 0; i < t; i += 5){
462 			if(l = nbrecvul(repeatc))
463 				goto Repeat;
464 			sleep(5);
465 		}
466 		putscan(f, esc1, sc);
467 		t = 30;
468 	}
469 Abort:
470 	chanfree(repeatc);
471 	threadexits("aborted");
472 
473 }
474 
475 
476 #define hasesc1(sc)	((sc) >= 0x47 || (sc) == 0x38)
477 
478 static void
putmod(KDev * f,uchar mods,uchar omods,uchar mask,uchar esc,uchar sc)479 putmod(KDev *f, uchar mods, uchar omods, uchar mask, uchar esc, uchar sc)
480 {
481 	/* BUG: Should be a single write */
482 	if((mods&mask) && !(omods&mask))
483 		putscan(f, esc, sc);
484 	if(!(mods&mask) && (omods&mask))
485 		putscan(f, esc, Keyup|sc);
486 }
487 
488 /*
489  * This routine diffs the state with the last known state
490  * and invents the scan codes that would have been sent
491  * by a non-usb keyboard in that case. This also requires supplying
492  * the extra esc1 byte as well as keyup flags.
493  * The aim is to allow future addition of other keycode pages
494  * for other keyboards.
495  */
496 static uchar
putkeys(KDev * f,uchar buf[],uchar obuf[],int n,uchar dk)497 putkeys(KDev *f, uchar buf[], uchar obuf[], int n, uchar dk)
498 {
499 	int i, j;
500 	uchar uk;
501 
502 	putmod(f, buf[0], obuf[0], Mctrl, 0, SCctrl);
503 	putmod(f, buf[0], obuf[0], (1<<Mlshift), 0, SClshift);
504 	putmod(f, buf[0], obuf[0], (1<<Mrshift), 0, SCrshift);
505 	putmod(f, buf[0], obuf[0], Mcompose, 0, SCcompose);
506 	putmod(f, buf[0], obuf[0], Maltgr, 1, SCcompose);
507 
508 	/* Report key downs */
509 	for(i = 2; i < n; i++){
510 		for(j = 2; j < n; j++)
511 			if(buf[i] == obuf[j])
512 			 	break;
513 		if(j == n && buf[i] != 0){
514 			dk = sctab[buf[i]];
515 			putscan(f, hasesc1(dk), dk);
516 			startrepeat(f, hasesc1(dk), dk);
517 		}
518 	}
519 
520 	/* Report key ups */
521 	uk = 0;
522 	for(i = 2; i < n; i++){
523 		for(j = 2; j < n; j++)
524 			if(obuf[i] == buf[j])
525 				break;
526 		if(j == n && obuf[i] != 0){
527 			uk = sctab[obuf[i]];
528 			putscan(f, hasesc1(uk), uk|Keyup);
529 		}
530 	}
531 	if(uk && (dk == 0 || dk == uk)){
532 		stoprepeat(f);
533 		dk = 0;
534 	}
535 	return dk;
536 }
537 
538 static int
kbdbusy(uchar * buf,int n)539 kbdbusy(uchar* buf, int n)
540 {
541 	int i;
542 
543 	for(i = 1; i < n; i++)
544 		if(buf[i] == 0 || buf[i] != buf[0])
545 			return 0;
546 	return 1;
547 }
548 
549 static void
kbdwork(void * a)550 kbdwork(void *a)
551 {
552 	int c, i, kbdfd, nerrs;
553 	uchar dk, buf[64], lbuf[64];
554 	char err[128];
555 	KDev *f = a;
556 
557 	threadsetname("kbd %s", f->ep->dir);
558 	kbdfd = f->ep->dfd;
559 
560 	if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf)
561 		kbfatal(f, "weird maxpkt");
562 
563 	f->repeatc = chancreate(sizeof(ulong), 0);
564 	if(f->repeatc == nil)
565 		kbfatal(f, "chancreate failed");
566 
567 	proccreate(repeatproc, f, Stack);
568 	memset(lbuf, 0, sizeof lbuf);
569 	dk = nerrs = 0;
570 	for(;;){
571 		memset(buf, 0, sizeof buf);
572 		c = read(kbdfd, buf, f->ep->maxpkt);
573 		assert(f->dev != nil);
574 		assert(f->ep != nil);
575 		if(c < 0){
576 			rerrstr(err, sizeof(err));
577 			fprint(2, "kb: %s: read: %s\n", f->ep->dir, err);
578 			if(strstr(err, "babble") != 0 && ++nerrs < 3){
579 				recoverkb(f);
580 				continue;
581 			}
582 		}
583 		if(c <= 0)
584 			kbfatal(f, nil);
585 		if(c < 3)
586 			continue;
587 		if(kbdbusy(buf + 2, c - 2))
588 			continue;
589 		if(usbdebug > 2 || f->debug > 1){
590 			fprint(2, "kbd mod %x: ", buf[0]);
591 			for(i = 2; i < c; i++)
592 				fprint(2, "kc %x ", buf[i]);
593 			fprint(2, "\n");
594 		}
595 		dk = putkeys(f, buf, lbuf, f->ep->maxpkt, dk);
596 		memmove(lbuf, buf, c);
597 		nerrs = 0;
598 	}
599 }
600 
601 static void
freekdev(void * a)602 freekdev(void *a)
603 {
604 	KDev *kd;
605 
606 	kd = a;
607 	if(kd->in != nil){
608 		qlock(&inlck);
609 		if(--kd->in->ref == 0){
610 			close(kd->in->fd);
611 			kd->in->fd = -1;
612 		}
613 		qunlock(&inlck);
614 	}
615 	dprint(2, "freekdev\n");
616 	free(kd);
617 }
618 
619 static void
kbstart(Dev * d,Ep * ep,Kin * in,void (* f)(void *),KDev * kd)620 kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), KDev *kd)
621 {
622 	uchar desc[512];
623 	int n, res;
624 
625 	qlock(&inlck);
626 	if(in->fd < 0){
627 		in->fd = open(in->name, OWRITE);
628 		if(in->fd < 0){
629 			fprint(2, "kb: %s: %r\n", in->name);
630 			qunlock(&inlck);
631 			return;
632 		}
633 	}
634 	in->ref++;	/* for kd->in = in */
635 	qunlock(&inlck);
636 	d->free = freekdev;
637 	kd->in = in;
638 	kd->dev = d;
639 	res = -1;
640 	kd->ep = openep(d, ep->id);
641 	if(kd->ep == nil){
642 		fprint(2, "kb: %s: openep %d: %r\n", d->dir, ep->id);
643 		return;
644 	}
645 	if(in == &kbdin){
646 		/*
647 		 * DWC OTG controller misses some split transaction inputs.
648 		 * Set nonzero idle time to return more frequent reports
649 		 * of keyboard state, to avoid losing key up/down events.
650 		 */
651 		n = read(d->cfd, desc, sizeof desc - 1);
652 		if(n > 0){
653 			desc[n] = 0;
654 			if(strstr((char*)desc, "dwcotg") != nil)
655 				kd->idle = Dwcidle;
656 		}
657 	}
658 	if(!kd->bootp)
659 		res= setfirstconfig(kd, ep->id, desc, sizeof desc);
660 	if(res > 0)
661 		res = parsereportdesc(&kd->templ, desc, sizeof desc);
662 	/* if we could not set the first config, we give up */
663 	if(kd->bootp || res < 0){
664 		kd->bootp = 1;
665 		if(setbootproto(kd, ep->id, nil, 0) < 0){
666 			fprint(2, "kb: %s: bootproto: %r\n", d->dir);
667 			return;
668 		}
669 	}else if(kd->debug)
670 		dumpreport(&kd->templ);
671 	if(opendevdata(kd->ep, OREAD) < 0){
672 		fprint(2, "kb: %s: opendevdata: %r\n", kd->ep->dir);
673 		closedev(kd->ep);
674 		kd->ep = nil;
675 		return;
676 	}
677 
678 	incref(d);
679 	proccreate(f, kd, Stack);
680 }
681 
682 static int
usage(void)683 usage(void)
684 {
685 	werrstr("usage: usb/kb [-bdkm] [-a n] [-N nb]");
686 	return -1;
687 }
688 
689 int
kbmain(Dev * d,int argc,char * argv[])690 kbmain(Dev *d, int argc, char* argv[])
691 {
692 	int bootp, i, kena, pena, accel, devid, debug;
693 	Ep *ep;
694 	KDev *kd;
695 	Usbdev *ud;
696 
697 	kena = pena = 1;
698 	bootp = 0;
699 	accel = 0;
700 	debug = 0;
701 	devid = d->id;
702 	ARGBEGIN{
703 	case 'a':
704 		accel = strtol(EARGF(usage()), nil, 0);
705 		break;
706 	case 'd':
707 		debug++;
708 		break;
709 	case 'k':
710 		kena = 1;
711 		pena = 0;
712 		break;
713 	case 'm':
714 		kena = 0;
715 		pena = 1;
716 		break;
717 	case 'N':
718 		devid = atoi(EARGF(usage()));		/* ignore dev number */
719 		break;
720 	case 'b':
721 		bootp++;
722 		break;
723 	default:
724 		return usage();
725 	}ARGEND;
726 	if(argc != 0)
727 		return usage();
728 	USED(devid);
729 	ud = d->usb;
730 	d->aux = nil;
731 	dprint(2, "kb: main: dev %s ref %ld\n", d->dir, d->ref);
732 
733 	if(kena)
734 		for(i = 0; i < nelem(ud->ep); i++)
735 			if((ep = ud->ep[i]) == nil)
736 				break;
737 			else if(ep->iface->csp == KbdCSP)
738 				bootp = 1;
739 
740 	for(i = 0; i < nelem(ud->ep); i++){
741 		if((ep = ud->ep[i]) == nil)
742 			continue;
743 		if(kena && ep->type == Eintr && ep->dir == Ein &&
744 		    ep->iface->csp == KbdCSP){
745 			kd = d->aux = emallocz(sizeof(KDev), 1);
746 			kd->accel = 0;
747 			kd->bootp = 1;
748 			kd->debug = debug;
749 			kbstart(d, ep, &kbdin, kbdwork, kd);
750 		}
751 		if(pena && ep->type == Eintr && ep->dir == Ein &&
752 		    ep->iface->csp == PtrCSP){
753 			kd = d->aux = emallocz(sizeof(KDev), 1);
754 			kd->accel = accel;
755 			kd->bootp = bootp;
756 			kd->debug = debug;
757 			kbstart(d, ep, &ptrin, ptrwork, kd);
758 		}
759 	}
760 	return 0;
761 }
762