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 void 118 kbfatal(KDev *kd, char *sts) 119 { 120 Dev *dev; 121 122 if(sts != nil) 123 fprint(2, "kd: %s: fatal: %s\n", kd->ep->dir, sts); 124 dev = kd->dev; 125 devctl(dev, "detach"); 126 if(kd->repeatc != nil) 127 sendul(kd->repeatc, Diemsg); 128 closedev(kd->ep); 129 kd->ep = nil; 130 kd->dev = nil; 131 closedev(dev); 132 /* 133 * free(kd); done by closedev. 134 */ 135 threadexits(sts); 136 } 137 138 static int 139 scale(KDev *f, int x) 140 { 141 int sign = 1; 142 143 if(x < 0){ 144 sign = -1; 145 x = -x; 146 } 147 switch(x){ 148 case 0: 149 case 1: 150 case 2: 151 case 3: 152 break; 153 case 4: 154 x = 6 + (f->accel>>2); 155 break; 156 case 5: 157 x = 9 + (f->accel>>1); 158 break; 159 default: 160 x *= MaxAcc; 161 break; 162 } 163 return sign*x; 164 } 165 166 /* 167 * ps2 mouse is processed mostly at interrupt time. 168 * for usb we do what we can. 169 */ 170 static void 171 sethipri(void) 172 { 173 char fn[30]; 174 int fd; 175 176 snprint(fn, sizeof(fn), "/proc/%d/ctl", getpid()); 177 fd = open(fn, OWRITE); 178 if(fd < 0) 179 return; 180 fprint(fd, "pri 13"); 181 close(fd); 182 } 183 184 static void 185 ptrwork(void* a) 186 { 187 static char maptab[] = {0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7}; 188 int x, y, b, c, ptrfd; 189 int mfd; 190 char buf[32]; 191 char mbuf[80]; 192 KDev* f = a; 193 int hipri; 194 195 hipri = 0; 196 ptrfd = f->ep->dfd; 197 mfd = f->in->fd; 198 199 if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf) 200 kbfatal(f, "weird maxpkt"); 201 for(;;){ 202 memset(buf, 0, sizeof buf); 203 c = read(ptrfd, buf, f->ep->maxpkt); 204 if(c < 0) 205 fprint(2, "kb: %s: read: %r\n", f->ep->dir); 206 if(c <= 0) 207 kbfatal(f, nil); 208 if(c < 3) 209 continue; 210 if(f->accel){ 211 x = scale(f, buf[1]); 212 y = scale(f, buf[2]); 213 }else{ 214 x = buf[1]; 215 y = buf[2]; 216 } 217 b = maptab[buf[0] & 0x7]; 218 if(c > 3 && buf[3] == 1) /* up */ 219 b |= 0x08; 220 if(c > 3 && buf[3] == -1) /* down */ 221 b |= 0x10; 222 if(kbdebug) 223 fprint(2, "%s: ptr: m%11d %11d %11d\n", argv0, x, y, b); 224 seprint(mbuf, mbuf+sizeof(mbuf), "m%11d %11d %11d", x, y,b); 225 if(write(mfd, mbuf, strlen(mbuf)) < 0){ 226 fprint(2, "%s: #m/mousein: write: %r", argv0); 227 kbfatal(f, "mousein"); 228 } 229 if(hipri == 0){ 230 sethipri(); 231 hipri = 1; 232 } 233 } 234 } 235 236 static void 237 stoprepeat(KDev *f) 238 { 239 sendul(f->repeatc, Awakemsg); 240 } 241 242 static void 243 startrepeat(KDev *f, uchar esc1, uchar sc) 244 { 245 ulong c; 246 247 if(esc1) 248 c = SCesc1 << 8 | (sc & 0xff); 249 else 250 c = sc; 251 sendul(f->repeatc, c); 252 } 253 254 static void 255 putscan(int kbinfd, uchar esc, uchar sc) 256 { 257 uchar s[2] = {SCesc1, 0}; 258 259 if(sc == 0x41){ 260 kbdebug++; 261 return; 262 } 263 if(sc == 0x42){ 264 kbdebug = 0; 265 return; 266 } 267 if(kbdebug) 268 fprint(2, "sc: %x %x\n", (esc? SCesc1: 0), sc); 269 s[1] = sc; 270 if(esc && sc != 0) 271 write(kbinfd, s, 2); 272 else if(sc != 0) 273 write(kbinfd, s+1, 1); 274 } 275 276 static void 277 repeatproc(void* a) 278 { 279 KDev *f; 280 Channel *repeatc; 281 int kbdinfd; 282 ulong l, t, i; 283 uchar esc1, sc; 284 285 /* 286 * too many jumps here. 287 * Rewrite instead of debug, if needed. 288 */ 289 f = a; 290 repeatc = f->repeatc; 291 kbdinfd = f->in->fd; 292 l = Awakemsg; 293 Repeat: 294 if(l == Diemsg) 295 goto Abort; 296 while(l == Awakemsg) 297 l = recvul(repeatc); 298 if(l == Diemsg) 299 goto Abort; 300 esc1 = l >> 8; 301 sc = l; 302 t = 160; 303 for(;;){ 304 for(i = 0; i < t; i += 5){ 305 if(l = nbrecvul(repeatc)) 306 goto Repeat; 307 sleep(5); 308 } 309 putscan(kbdinfd, esc1, sc); 310 t = 30; 311 } 312 Abort: 313 chanfree(repeatc); 314 threadexits("aborted"); 315 316 } 317 318 319 #define hasesc1(sc) (((sc) > 0x47) || ((sc) == 0x38)) 320 321 static void 322 putmod(int fd, uchar mods, uchar omods, uchar mask, uchar esc, uchar sc) 323 { 324 /* BUG: Should be a single write */ 325 if((mods&mask) && !(omods&mask)) 326 putscan(fd, esc, sc); 327 if(!(mods&mask) && (omods&mask)) 328 putscan(fd, esc, Keyup|sc); 329 } 330 331 /* 332 * This routine diffs the state with the last known state 333 * and invents the scan codes that would have been sent 334 * by a non-usb keyboard in that case. This also requires supplying 335 * the extra esc1 byte as well as keyup flags. 336 * The aim is to allow future addition of other keycode pages 337 * for other keyboards. 338 */ 339 static uchar 340 putkeys(KDev *f, uchar buf[], uchar obuf[], int n, uchar dk) 341 { 342 int i, j; 343 uchar uk; 344 int fd; 345 346 fd = f->in->fd; 347 putmod(fd, buf[0], obuf[0], Mctrl, 0, SCctrl); 348 putmod(fd, buf[0], obuf[0], (1<<Mlshift), 0, SClshift); 349 putmod(fd, buf[0], obuf[0], (1<<Mrshift), 0, SCrshift); 350 putmod(fd, buf[0], obuf[0], Mcompose, 0, SCcompose); 351 putmod(fd, buf[0], obuf[0], Maltgr, 1, SCcompose); 352 353 /* Report key downs */ 354 for(i = 2; i < n; i++){ 355 for(j = 2; j < n; j++) 356 if(buf[i] == obuf[j]) 357 break; 358 if(j == n && buf[i] != 0){ 359 dk = sctab[buf[i]]; 360 putscan(fd, hasesc1(dk), dk); 361 startrepeat(f, hasesc1(dk), dk); 362 } 363 } 364 365 /* Report key ups */ 366 uk = 0; 367 for(i = 2; i < n; i++){ 368 for(j = 2; j < n; j++) 369 if(obuf[i] == buf[j]) 370 break; 371 if(j == n && obuf[i] != 0){ 372 uk = sctab[obuf[i]]; 373 putscan(fd, hasesc1(uk), uk|Keyup); 374 } 375 } 376 if(uk && (dk == 0 || dk == uk)){ 377 stoprepeat(f); 378 dk = 0; 379 } 380 return dk; 381 } 382 383 static int 384 kbdbusy(uchar* buf, int n) 385 { 386 int i; 387 388 for(i = 1; i < n; i++) 389 if(buf[i] == 0 || buf[i] != buf[0]) 390 return 0; 391 return 1; 392 } 393 394 static void 395 kbdwork(void *a) 396 { 397 int c, i, kbdfd; 398 uchar buf[64], lbuf[64]; 399 KDev *f = a; 400 uchar dk; 401 402 kbdfd = f->ep->dfd; 403 404 if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf) 405 kbfatal(f, "weird maxpkt"); 406 407 f->repeatc = chancreate(sizeof(ulong), 0); 408 if(f->repeatc == nil) 409 kbfatal(f, "chancreate failed"); 410 411 proccreate(repeatproc, f, Stack); 412 memset(lbuf, 0, sizeof lbuf); 413 dk = 0; 414 for(;;){ 415 memset(buf, 0, sizeof buf); 416 c = read(kbdfd, buf, f->ep->maxpkt); 417 if(c < 0) 418 fprint(2, "%s: %s: read: %r\n", argv0, f->ep->dir); 419 if(c <= 0) 420 kbfatal(f, "eof"); 421 if(c < 3) 422 continue; 423 if(kbdbusy(buf + 2, c - 2)) 424 continue; 425 if(usbdebug > 1 || kbdebug > 1){ 426 fprint(2, "kbd mod %x: ", buf[0]); 427 for(i = 2; i < c; i++) 428 fprint(2, "kc %x ", buf[i]); 429 fprint(2, "\n"); 430 } 431 dk = putkeys(f, buf, lbuf, f->ep->maxpkt, dk); 432 memmove(lbuf, buf, c); 433 } 434 } 435 436 static int 437 setbootproto(KDev* f, int eid) 438 { 439 int r, id; 440 441 r = Rh2d|Rclass|Riface; 442 id = f->dev->usb->ep[eid]->iface->id; 443 return usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0); 444 } 445 446 static void 447 freekdev(void *a) 448 { 449 KDev *kd; 450 451 kd = a; 452 if(kd->in != nil){ 453 qlock(&inlck); 454 if(--kd->in->ref == 0){ 455 close(kd->in->fd); 456 kd->in->fd = -1; 457 } 458 qunlock(&inlck); 459 } 460 free(kd); 461 } 462 463 static void 464 kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), int accel) 465 { 466 KDev *kd; 467 468 qlock(&inlck); 469 if(in->fd < 0){ 470 in->fd = open(in->name, OWRITE); 471 if(in->fd < 0){ 472 fprint(2, "kb: %s: %r\n", in->name); 473 qunlock(&inlck); 474 return; 475 } 476 } 477 qunlock(&inlck); 478 kd = d->aux; 479 if(kd == nil){ 480 kd = d->aux = emallocz(sizeof(KDev), 1); 481 d->free = freekdev; 482 kd->in = in; 483 qlock(&inlck); 484 kd->in->ref++; 485 qunlock(&inlck); 486 kd->dev = d; 487 if(setbootproto(kd, ep->id) < 0){ 488 fprint(2, "kb: %s: bootproto: %r\n", d->dir); 489 return; 490 } 491 } 492 kd->accel = accel; 493 kd->ep = openep(d, ep->id); 494 if(kd->ep == nil){ 495 fprint(2, "kb: %s: openep %d: %r\n", d->dir, ep->id); 496 return; 497 } 498 if(opendevdata(kd->ep, OREAD) < 0){ 499 fprint(2, "kb: %s: opendevdata: %r\n", kd->ep->dir); 500 closedev(kd->ep); 501 kd->ep = nil; 502 return; 503 } 504 505 incref(d); 506 proccreate(f, kd, Stack); 507 } 508 509 static int 510 usage(void) 511 { 512 werrstr("usage: usb/kb [-dkmn] [-a n]"); 513 return -1; 514 } 515 516 int 517 kbmain(Dev *d, int argc, char* argv[]) 518 { 519 int i; 520 int kena; 521 int pena; 522 int accel; 523 char *as; 524 Usbdev *ud; 525 Ep *ep; 526 527 kena = pena = 1; 528 accel = 0; 529 ARGBEGIN{ 530 case 'a': 531 as = ARGF(); 532 if(as == nil) 533 return usage(); 534 accel = strtol(as, nil, 0); 535 break; 536 case 'd': 537 kbdebug++; 538 break; 539 case 'k': 540 kena = 1; 541 pena = 0; 542 break; 543 case 'm': 544 kena = 0; 545 pena = 1; 546 break; 547 default: 548 return usage(); 549 }ARGEND; 550 if(argc != 0){ 551 return usage(); 552 } 553 ud = d->usb; 554 d->aux = nil; 555 dprint(2, "kb: main: dev %s ref %ld\n", d->dir, d->ref); 556 for(i = 0; i < nelem(ud->ep); i++){ 557 if((ep = ud->ep[i]) == nil) 558 break; 559 if(kena && ep->type == Eintr && ep->dir == Ein) 560 if(ep->iface->csp == KbdCSP) 561 kbstart(d, ep, &kbdin, kbdwork, accel); 562 if(pena && ep->type == Eintr && ep->dir == Ein) 563 if(ep->iface->csp == PtrCSP) 564 kbstart(d, ep, &ptrin, ptrwork, accel); 565 } 566 closedev(d); 567 return 0; 568 } 569