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