xref: /plan9/sys/src/cmd/usb/kb/kb.c (revision d1da931c1953c14f6f98c26297030a0b55cb02f6)
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 /*
20  * Map for the logitech bluetooth mouse with 8 buttons and wheels.
21  *	{ ptr ->mouse}
22  *	{ 0x01, 0x01 },	// left
23  *	{ 0x04, 0x02 },	// middle
24  *	{ 0x02, 0x04 },	// right
25  *	{ 0x40, 0x08 },	// up
26  *	{ 0x80, 0x10 },	// down
27  *	{ 0x10, 0x08 },	// side up
28  *	{ 0x08, 0x10 },	// side down
29  *	{ 0x20, 0x02 }, // page
30  * besides wheel and regular up/down report the 4th byte as 1/-1
31  */
32 
33 /*
34  * key code to scan code; for the page table used by
35  * the logitech bluetooth keyboard.
36  */
37 char sctab[256] =
38 {
39 [0x00]	0x0,	0x0,	0x0,	0x0,	0x1e,	0x30,	0x2e,	0x20,
40 [0x08]	0x12,	0x21,	0x22,	0x23,	0x17,	0x24,	0x25,	0x26,
41 [0x10]	0x32,	0x31,	0x18,	0x19,	0x10,	0x13,	0x1f,	0x14,
42 [0x18]	0x16,	0x2f,	0x11,	0x2d,	0x15,	0x2c,	0x2,	0x3,
43 [0x20]	0x4,	0x5,	0x6,	0x7,	0x8,	0x9,	0xa,	0xb,
44 [0x28]	0x1c,	0x1,	0xe,	0xf,	0x39,	0xc,	0xd,	0x1a,
45 [0x30]	0x1b,	0x2b,	0x2b,	0x27,	0x28,	0x29,	0x33,	0x34,
46 [0x38]	0x35,	0x3a,	0x3b,	0x3c,	0x3d,	0x3e,	0x3f,	0x40,
47 [0x40]	0x41,	0x42,	0x43,	0x44,	0x57,	0x58,	0x63,	0x46,
48 [0x48]	0x77,	0x52,	0x47,	0x49,	0x53,	0x4f,	0x51,	0x4d,
49 [0x50]	0x4b,	0x50,	0x48,	0x45,	0x35,	0x37,	0x4a,	0x4e,
50 [0x58]	0x1c,	0x4f,	0x50,	0x51,	0x4b,	0x4c,	0x4d,	0x47,
51 [0x60]	0x48,	0x49,	0x52,	0x53,	0x56,	0x7f,	0x74,	0x75,
52 [0x68]	0x55,	0x59,	0x5a,	0x5b,	0x5c,	0x5d,	0x5e,	0x5f,
53 [0x70]	0x78,	0x79,	0x7a,	0x7b,	0x0,	0x0,	0x0,	0x0,
54 [0x78]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x71,
55 [0x80]	0x73,	0x72,	0x0,	0x0,	0x0,	0x7c,	0x0,	0x0,
56 [0x88]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
57 [0x90]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
58 [0x98]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
59 [0xa0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
60 [0xa8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
61 [0xb0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
62 [0xb8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
63 [0xc0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
64 [0xc8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
65 [0xd0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
66 [0xd8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
67 [0xe0]	0x1d,	0x2a,	0x38,	0x7d,	0x61,	0x36,	0x64,	0x7e,
68 [0xe8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x73,	0x72,	0x71,
69 [0xf0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
70 [0xf8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
71 };
72 
73 typedef struct Dev Dev;
74 struct Dev {
75 	char*	name;		/* debug */
76 	void	(*proc)(void*);	/* handler process */
77 	int	csp;		/* the csp we want */
78 	int	enabled;	/* can we start it? */
79 	int	ctlrno;		/* controller number, for probing*/
80 	int	id;		/* device id, for probing*/
81 	int	ep;		/* endpoint used to get events */
82 	int	msz;		/* message size */
83 	int	fd;		/* to the endpoint data file */
84 	Device*	dev;		/* usb device*/
85 };
86 
87 
88 Dev	kf, pf;			/* kbd and pointer drivers*/
89 Channel *repeatc;		/* channel to request key repeating*/
90 
91 void (*dprinter[])(Device *, int, ulong, void *b, int n) = {
92 	[STRING] pstring,
93 	[DEVICE] pdevice,
94 	[HID] phid,
95 };
96 
97 int	accel;
98 int	hdebug;
99 int	dryrun;
100 int	verbose;
101 
102 int mainstacksize = 32*1024;
103 
104 int
105 robusthandler(void*, char *s)
106 {
107 	if(hdebug)
108 		fprint(2, "inthandler: %s\n", s);
109 	return (s && (strstr(s, "interrupted")|| strstr(s, "hangup")));
110 }
111 
112 long
113 robustread(int fd, void *buf, long sz)
114 {
115 	long r;
116 	char err[ERRMAX];
117 
118 	do {
119 		r = read(fd , buf, sz);
120 		if(r < 0)
121 			rerrstr(err, sizeof err);
122 	} while(r < 0 && robusthandler(nil, err));
123 	return r;
124 }
125 
126 static int
127 scale(int x)
128 {
129 	int sign = 1;
130 
131 	if(x < 0){
132 		sign = -1;
133 		x = -x;
134 	}
135 	switch(x){
136 	case 0:
137 	case 1:
138 	case 2:
139 	case 3:
140 		break;
141 	case 4:
142 		x = 6 + (accel>>2);
143 		break;
144 	case 5:
145 		x = 9 + (accel>>1);
146 		break;
147 	default:
148 		x *= MaxAcc;
149 		break;
150 	}
151 	return sign*x;
152 }
153 
154 void
155 ptrwork(void* a)
156 {
157 	int x, y, b, c, mfd, ptrfd;
158 	char	buf[32];
159 	Dev*	f = a;
160 	static char maptab[] = {0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7};
161 
162 	ptrfd = f->fd;
163 	if(ptrfd < 0)
164 		return;
165 	mfd = -1;
166 	if(f->msz < 3 || f->msz > sizeof buf)
167 		sysfatal("bug: ptrwork: bad mouse maxpkt");
168 	if(!dryrun){
169 		mfd = open("#m/mousein", OWRITE);
170 		if(mfd < 0)
171 			sysfatal("%s: mousein: %r", f->name);
172 	}
173 	for(;;){
174 		memset(buf, 0, sizeof buf);
175 		c = robustread(ptrfd, buf, f->msz);
176 		if(c == 0)
177 			fprint(2, "%s: %s: eof\n", argv0, f->name);
178 		if(c < 0)
179 			fprint(2, "%s: %s: read: %r\n", argv0, f->name);
180 		if(c <= 0){
181 			if(!dryrun)
182 				close(mfd);
183 			close(f->fd);
184 			threadexits("read");
185 		}
186 		if(c < 3)
187 			continue;
188 		if(accel) {
189 			x = scale(buf[1]);
190 			y = scale(buf[2]);
191 		} else {
192 			x = buf[1];
193 			y = buf[2];
194 		}
195 		b = maptab[buf[0] & 0x7];
196 		if(c > 3 && buf[3] == 1)	/* up */
197 			b |= 0x08;
198 		if(c > 3 && buf[3] == -1)	/* down */
199 			b |= 0x10;
200 		if(hdebug)
201 			fprint(2, "%s: %s: m%11d %11d %11d\n",
202 				argv0, f->name, x, y, b);
203 		if(!dryrun)
204 			if(fprint(mfd, "m%11d %11d %11d", x, y, b) < 0){
205 				fprint(2, "%s: #m/mousein: write: %r", argv0);
206 				close(mfd);
207 				close(f->fd);
208 				threadexits("write");
209 			}
210 	}
211 }
212 
213 static void
214 stoprepeat(void)
215 {
216 	sendul(repeatc, Awakemsg);
217 }
218 
219 static void
220 startrepeat(uchar esc1, uchar sc)
221 {
222 	ulong c;
223 
224 	if(esc1)
225 		c = SCesc1 << 8 | (sc & 0xff);
226 	else
227 		c = sc;
228 	sendul(repeatc, c);
229 }
230 
231 static int kbinfd = -1;
232 
233 static void
234 putscan(uchar esc, uchar sc)
235 {
236 	static uchar s[2] = {SCesc1, 0};
237 
238 	if(sc == 0x41){
239 		hdebug = 1;
240 		return;
241 	}
242 	if(sc == 0x42){
243 		hdebug = 0;
244 		return;
245 	}
246 	if(kbinfd < 0 && !dryrun)
247 		kbinfd = open("#Ι/kbin", OWRITE);
248 	if(kbinfd < 0 && !dryrun)
249 		sysfatal("/dev/kbin: %r");
250 	if(hdebug)
251 		fprint(2, "sc: %x %x\n", (esc? SCesc1: 0), sc);
252 	if(!dryrun){
253 			s[1] = sc;
254 		if(esc && sc != 0)
255 			write(kbinfd, s, 2);
256 		else if(sc != 0)
257 			write(kbinfd, s+1, 1);
258 }
259 }
260 
261 static void
262 repeatproc(void*)
263 {
264 	ulong l;
265 	uchar esc1, sc;
266 
267 	assert(sizeof(int) <= sizeof(void*));
268 
269 	for(;;){
270 		l = recvul(repeatc);		/*  wait for work*/
271 		if(l == 0xdeaddead)
272 			continue;
273 		esc1 = l >> 8;
274 		sc = l;
275 		for(;;){
276 			putscan(esc1, sc);
277 			sleep(80);
278 			l = nbrecvul(repeatc);
279 			if(l != 0){		/*  stop repeating*/
280 				if(l != Awakemsg)
281 					fprint(2, "kb: race: should be awake mesg\n");
282 				break;
283 			}
284 		}
285 	}
286 }
287 
288 
289 #define hasesc1(sc)	(((sc) > 0x47) || ((sc) == 0x38))
290 
291 static void
292 putmod(uchar mods, uchar omods, uchar mask, uchar esc, uchar sc)
293 {
294 	if((mods&mask) && !(omods&mask))
295 		putscan(esc, sc);
296 	if(!(mods&mask) && (omods&mask))
297 		putscan(esc, Keyup|sc);
298 }
299 
300 /*
301  * This routine diffs the state with the last known state
302  * and invents the scan codes that would have been sent
303  * by a non-usb keyboard in that case. This also requires supplying
304  * the extra esc1 byte as well as keyup flags.
305  * The aim is to allow future addition of other keycode pages
306  * for other keyboards.
307  */
308 static void
309 putkeys(uchar buf[], uchar obuf[], int n)
310 {
311 	int i, j;
312 	uchar sc;
313 	static int repeating = 0, times = 0;
314 	static uchar last = 0;
315 
316 	putmod(buf[0], obuf[0], Mctrl, 0, SCctrl);
317 	putmod(buf[0], obuf[0], (1<<Mlshift), 0, SClshift);
318 	putmod(buf[0], obuf[0], (1<<Mrshift), 0, SCrshift);
319 	putmod(buf[0], obuf[0], Mcompose, 0, SCcompose);
320 	putmod(buf[0], obuf[0], Maltgr, 1, SCcompose);
321 
322 	/*
323 	 * If we get three times the same (single) key, we start
324 	 * repeating. Otherwise, we stop repeating and
325 	 * perform normal processing.
326 	 */
327 	if(buf[2] != 0 && buf[3] == 0 && buf[2] == last){
328 		if(repeating)
329 			return;	/* already being done */
330 		times++;
331 		if(times >= 2){
332 			repeating = 1;
333 			sc = sctab[buf[2]];
334 			startrepeat(hasesc1(sc), sc);
335 			return;
336 		}
337 	} else
338 		times = 0;
339 	last = buf[2];
340 	if(repeating){
341 		repeating = 0;
342 		stoprepeat();
343 	}
344 
345 	/* Report key downs */
346 	for(i = 2; i < n; i++){
347 		for(j = 2; j < n; j++)
348 			if(buf[i] == obuf[j])
349 			 	break;
350 		if(j == n && buf[i] != 0){
351 			sc = sctab[buf[i]];
352 			putscan(hasesc1(sc), sc);
353 		}
354 	}
355 
356 	/* Report key ups */
357 	for(i = 2; i < n; i++){
358 		for(j = 2; j < n; j++)
359 			if(obuf[i] == buf[j])
360 				break;
361 		if(j == n && obuf[i] != 0){
362 			sc = sctab[obuf[i]];
363 			putscan(hasesc1(sc), sc|Keyup);
364 		}
365 	}
366 }
367 
368 static int
369 kbdbusy(uchar* buf, int n)
370 {
371 	int i;
372 
373 	for(i = 1; i < n; i++)
374 		if(buf[i] == 0 || buf[i] != buf[0])
375 			return 0;
376 	return 1;
377 }
378 
379 void
380 kbdwork(void *a)
381 {
382 	int c, i, kbdfd;
383 	uchar buf[64], lbuf[64];
384 	Dev *f = a;
385 
386 	kbdfd = f->fd;
387 	if(kbdfd < 0)
388 		return;
389 	if(f->msz < 3 || f->msz > sizeof buf)
390 		sysfatal("bug: ptrwork: bad kbd maxpkt");
391 	repeatc = chancreate(sizeof(ulong), 0);
392 	if(repeatc == nil)
393 		sysfatal("repeat chan: %r");
394 	proccreate(repeatproc, nil, 32*1024);
395 	memset(lbuf, 0, sizeof lbuf);
396 	for(;;) {
397 		memset(buf, 0, sizeof buf);
398 		c = robustread(kbdfd, buf, f->msz);
399 		if(c == 0)
400 			fprint(2, "%s: %s: eof\n", argv0, f->name);
401 		if(c < 0)
402 			fprint(2, "%s: %s: read: %r\n", argv0, f->name);
403 		if(c <= 0){
404 			if(!dryrun)
405 				close(kbinfd);
406 			close(f->fd);
407 			threadexits("read");
408 		}
409 		if(c < 3)
410 			continue;
411 		if(kbdbusy(buf + 2, c - 2))
412 			continue;
413 		if(hdebug > 1){
414 			fprint(2, "kbd mod %x: ", buf[0]);
415 			for(i = 2; i < c; i++)
416 				fprint(2, "kc %x ", buf[i]);
417 			fprint(2, "\n");
418 		}
419 		putkeys(buf, lbuf, f->msz);
420 		memmove(lbuf, buf, c);
421 	}
422 }
423 
424 static int
425 probeif(Dev* f, int ctlrno, int i, int kcsp, int csp, int, int)
426 {
427 	int found, n, sfd;
428 	char buf[256], cspstr[50], kcspstr[50];
429 
430 	seprint(cspstr, cspstr + sizeof cspstr, "0x%0.06x", csp);
431 	seprint(buf, buf + sizeof buf, "/dev/usb%d/%d/status", ctlrno, i);
432 	sfd = open(buf, OREAD);
433 	if(sfd < 0)
434 		return -1;
435 	n = read(sfd, buf, sizeof buf - 1);
436 	if(n <= 0){
437 		close(sfd);
438 		return -1;
439 	}
440 	buf[n] = 0;
441 	close(sfd);
442 	/*
443 	 * Mouse + keyboard combos may report the interface as Kbdcsp,
444 	 * because it's the endpoint the one with the right csp.
445 	 */
446 	sprint(cspstr, "Enabled 0x%0.06x", csp);
447 	found = (strncmp(buf, cspstr, strlen(cspstr)) == 0);
448 	if(!found){
449 		sprint(cspstr, " 0x%0.06x", csp);
450 		sprint(kcspstr, "Enabled 0x%0.06x", kcsp);
451 		if(strncmp(buf, kcspstr, strlen(kcspstr)) == 0 &&
452 		   strstr(buf, cspstr) != nil)
453 			found = 1;
454 	}
455 	if(found){
456 		f->ctlrno = ctlrno;
457 		f->id = i;
458 		f->enabled = 1;
459 		if(hdebug)
460 			fprint(2, "%s: csp 0x%x at /dev/usb%d/%d\n",
461 				f->name, csp, f->ctlrno, f->id);
462 		return 0;
463 	}
464 	if(hdebug)
465 		fprint(2, "%s: not found %s\n", f->name, cspstr);
466 	return -1;
467 
468 }
469 
470 static int
471 probedev(Dev* f, int kcsp, int csp, int vid, int did)
472 {
473 	int c, i;
474 
475 	for(c = 0; c < 16; c++)
476 		if(f->ctlrno == 0 || c == f->ctlrno)
477 			for(i = 1; i < 128; i++)
478 				if(f->id == 0 || i == f->id)
479 				if(probeif(f, c, i, kcsp, csp, vid, did) != -1){
480 					f->csp = csp;
481 					return 0;
482 				}
483 	f->enabled = 0;
484 	if(hdebug || verbose)
485 		fprint(2, "%s: csp 0x%x: not found\n", f->name, csp);
486 	return -1;
487 }
488 
489 static void
490 initdev(Dev* f)
491 {
492 	int i;
493 
494 	f->dev = opendev(f->ctlrno, f->id);
495 	if(f->dev == nil || describedevice(f->dev) < 0) {
496 		fprint(2, "init failed: %s: %r\n", f->name);
497 		f->enabled = 0;
498 		f->ctlrno = f->id = -1;
499 		return;
500 	}
501 	memset(f->dev->config, 0, sizeof f->dev->config);
502 	for(i = 0; i < f->dev->nconf; i++){
503 		f->dev->config[i] = mallocz(sizeof *f->dev->config[i], 1);
504 		loadconfig(f->dev, i);
505 	}
506 	if(verbose || hdebug){
507 		fprint(2, "%s found: ctlrno=%d id=%d\n",
508 			f->name, f->ctlrno, f->id);
509 //		printdevice(f->dev);	// TODO
510 	}
511 }
512 
513 static int
514 setbootproto(Dev* f)
515 {
516 	int r, id;
517 	Endpt* ep;
518 
519 	ep = f->dev->ep[0];
520 	r = RH2D | Rclass | Rinterface;
521 	id = f->dev->ep[f->ep]->iface->interface;
522 	return setupreq(ep, r, SET_PROTO, BOOT_PROTO, id, 0);
523 }
524 
525 static void
526 startdev(Dev* f)
527 {
528 	int i;
529 	char buf[128];
530 	Endpt* ep;
531 
532 	f->ep = -1;
533 	ep = nil;
534 	for(i = 0; i < Nendpt; i++)
535 		if((ep = f->dev->ep[i]) != nil &&
536 		    ep->csp == f->csp && ep->type == Eintr && ep->dir == Ein){
537 			f->ep = i;
538 			f->msz = ep->maxpkt;
539 			break;
540 		}
541 	if(ep == nil){
542 		fprint(2, "%s: %s: bug: no endpoint\n", argv0, f->name);
543 		return;
544 	}
545 	sprint(buf, "ep %d 10 r %d", f->ep, f->msz);
546 	if(hdebug)
547 		fprint(2, "%s: %s: ep %d: ctl %s\n", argv0, f->name, f->ep, buf);
548 	if(write(f->dev->ctl, buf, strlen(buf)) != strlen(buf)){
549 		fprint(2, "%s: %s: startdev: %r\n", argv0, f->name);
550 		return;
551 	}
552 	sprint(buf, "/dev/usb%d/%d/ep%ddata", f->ctlrno, f->id, f->ep);
553 	f->fd = open(buf, OREAD);
554 	if(f->fd < 0){
555 		fprint(2, "%s: opening %s: %s: %r", argv0, f->name, buf);
556 		return;
557 	}
558 	if(setbootproto(f) < 0)
559 		fprint(2, "%s: %s: setbootproto: %r\n", argv0, f->name);
560 	if(hdebug)
561 		fprint(2, "starting %s\n", f->name);
562 	proccreate(f->proc, f, 32*1024);
563 }
564 
565 static void
566 usage(void)
567 {
568 	fprint(2, "usage: %s [-dkmn] [-a n] [ctlrno usbport]\n", argv0);
569 	threadexitsall("usage");
570 }
571 
572 void
573 threadmain(int argc, char **argv)
574 {
575 
576 	quotefmtinstall();
577 	usbfmtinit();
578 
579 	pf.enabled = kf.enabled = 1;
580 	ARGBEGIN{
581 	case 'a':
582 		accel = strtol(EARGF(usage()), nil, 0);
583 		break;
584 	case 'd':
585 		hdebug++;
586 		usbdebug++;
587 		break;
588 	case 'k':
589 		kf.enabled = 1;
590 		pf.enabled = 0;
591 		break;
592 	case 'm':
593 		kf.enabled = 0;
594 		pf.enabled = 1;
595 		break;
596 	case 'n':
597 		dryrun = 1;
598 		break;
599 	default:
600 		usage();
601 	}ARGEND;
602 
603 	switch(argc){
604 	case 0:
605 		break;
606 	case 2:
607 		pf.ctlrno = kf.ctlrno = atoi(argv[0]);
608 		pf.id = kf.id = atoi(argv[1]);
609 		break;
610 	default:
611 		usage();
612 	}
613 	threadnotify(robusthandler, 1);
614 
615 	kf.name = "kbd";
616 	kf.proc = kbdwork;
617 	pf.name = "mouse";
618 	pf.proc = ptrwork;
619 
620 	if(kf.enabled)
621 		probedev(&kf, KbdCSP, KbdCSP, 0, 0);
622 	if(kf.enabled)
623 		initdev(&kf);
624 	if(pf.enabled)
625 		probedev(&pf, KbdCSP, PtrCSP, 0, 0);
626 	if(pf.enabled)
627 		if(kf.enabled && pf.ctlrno == kf.ctlrno && pf.id == kf.id)
628 			pf.dev = kf.dev;
629 		else
630 			initdev(&pf);
631 	rfork(RFNOTEG);
632 	if(kf.enabled)
633 		startdev(&kf);
634 	if(pf.enabled)
635 		startdev(&pf);
636 	threadexits(nil);
637 }
638