1 /* $NetBSD: aed.c,v 1.28 2014/03/16 05:20:25 dholland Exp $ */ 2 3 /* 4 * Copyright (C) 1994 Bradley A. Grantham 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: aed.c,v 1.28 2014/03/16 05:20:25 dholland Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/device.h> 33 #include <sys/fcntl.h> 34 #include <sys/poll.h> 35 #include <sys/select.h> 36 #include <sys/proc.h> 37 #include <sys/signalvar.h> 38 #include <sys/systm.h> 39 #include <sys/conf.h> 40 41 #include <machine/autoconf.h> 42 #include <machine/cpu.h> 43 #include <machine/keyboard.h> 44 45 #include <macppc/dev/adbvar.h> 46 #include <macppc/dev/aedvar.h> 47 #include <macppc/dev/akbdvar.h> 48 49 #define spladb splhigh 50 51 /* 52 * Function declarations. 53 */ 54 static int aedmatch(device_t, cfdata_t, void *); 55 static void aedattach(device_t, device_t, void *); 56 static void aed_emulate_mouse(adb_event_t *event); 57 static void aed_kbdrpt(void *kstate); 58 static void aed_dokeyupdown(adb_event_t *event); 59 static void aed_handoff(adb_event_t *event); 60 static void aed_enqevent(adb_event_t *event); 61 62 /* 63 * Global variables. 64 */ 65 extern int adb_polling; /* Are we polling? (Debugger mode) */ 66 67 /* 68 * Local variables. 69 */ 70 static struct aed_softc *aed_sc = NULL; 71 static int aed_options = 0; /* | AED_MSEMUL; */ 72 73 /* Driver definition */ 74 CFATTACH_DECL_NEW(aed, sizeof(struct aed_softc), 75 aedmatch, aedattach, NULL, NULL); 76 77 extern struct cfdriver aed_cd; 78 79 dev_type_open(aedopen); 80 dev_type_close(aedclose); 81 dev_type_read(aedread); 82 dev_type_ioctl(aedioctl); 83 dev_type_poll(aedpoll); 84 dev_type_kqfilter(aedkqfilter); 85 86 const struct cdevsw aed_cdevsw = { 87 .d_open = aedopen, 88 .d_close = aedclose, 89 .d_read = aedread, 90 .d_write = nullwrite, 91 .d_ioctl = aedioctl, 92 .d_stop = nostop, 93 .d_tty = notty, 94 .d_poll = aedpoll, 95 .d_mmap = nommap, 96 .d_kqfilter = aedkqfilter, 97 .d_flag = 0 98 }; 99 100 static int 101 aedmatch(device_t parent, cfdata_t cf, void *aux) 102 { 103 struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; 104 static int aed_matched = 0; 105 106 /* Allow only one instance. */ 107 if ((aa_args->origaddr == 0) && (!aed_matched)) { 108 aed_matched = 1; 109 return (1); 110 } else 111 return (0); 112 } 113 114 static void 115 aedattach(device_t parent, device_t self, void *aux) 116 { 117 struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; 118 struct aed_softc *sc = device_private(self); 119 120 callout_init(&sc->sc_repeat_ch, 0); 121 selinit(&sc->sc_selinfo); 122 123 sc->origaddr = aa_args->origaddr; 124 sc->adbaddr = aa_args->adbaddr; 125 sc->handler_id = aa_args->handler_id; 126 127 sc->sc_evq_tail = 0; 128 sc->sc_evq_len = 0; 129 130 sc->sc_rptdelay = 20; 131 sc->sc_rptinterval = 6; 132 sc->sc_repeating = -1; /* not repeating */ 133 134 /* Pull in the options flags. */ 135 sc->sc_options = (device_cfdata(self)->cf_flags | aed_options); 136 137 sc->sc_ioproc = NULL; 138 139 sc->sc_buttons = 0; 140 141 sc->sc_open = 0; 142 143 aed_sc = sc; 144 145 printf("ADB Event device\n"); 146 147 return; 148 } 149 150 /* 151 * Given a keyboard ADB event, record the keycode and call the key 152 * repeat handler, optionally passing the event through the mouse 153 * button emulation handler first. Pass mouse events directly to 154 * the handoff function. 155 */ 156 void 157 aed_input(adb_event_t *event) 158 { 159 adb_event_t new_event = *event; 160 161 switch (event->def_addr) { 162 case ADBADDR_KBD: 163 if (aed_sc->sc_options & AED_MSEMUL) 164 aed_emulate_mouse(&new_event); 165 else 166 aed_dokeyupdown(&new_event); 167 break; 168 case ADBADDR_MS: 169 new_event.u.m.buttons |= aed_sc->sc_buttons; 170 aed_handoff(&new_event); 171 break; 172 default: /* God only knows. */ 173 #ifdef DIAGNOSTIC 174 panic("aed: received event from unsupported device!"); 175 #endif 176 break; 177 } 178 179 } 180 181 /* 182 * Handles mouse button emulation via the keyboard. If the emulation 183 * modifier key is down, left and right arrows will generate 2nd and 184 * 3rd mouse button events while the 1, 2, and 3 keys will generate 185 * the corresponding mouse button event. 186 */ 187 static void 188 aed_emulate_mouse(adb_event_t *event) 189 { 190 static int emulmodkey_down = 0; 191 adb_event_t new_event; 192 193 if (event->u.k.key == ADBK_KEYDOWN(ADBK_OPTION)) { 194 emulmodkey_down = 1; 195 } else if (event->u.k.key == ADBK_KEYUP(ADBK_OPTION)) { 196 /* key up */ 197 emulmodkey_down = 0; 198 if (aed_sc->sc_buttons & 0xfe) { 199 aed_sc->sc_buttons &= 1; 200 new_event.def_addr = ADBADDR_MS; 201 new_event.u.m.buttons = aed_sc->sc_buttons; 202 new_event.u.m.dx = new_event.u.m.dy = 0; 203 microtime(&new_event.timestamp); 204 aed_handoff(&new_event); 205 } 206 } else if (emulmodkey_down) { 207 switch(event->u.k.key) { 208 #ifdef ALTXBUTTONS 209 case ADBK_KEYDOWN(ADBK_1): 210 aed_sc->sc_buttons |= 1; /* left down */ 211 new_event.def_addr = ADBADDR_MS; 212 new_event.u.m.buttons = aed_sc->sc_buttons; 213 new_event.u.m.dx = new_event.u.m.dy = 0; 214 microtime(&new_event.timestamp); 215 aed_handoff(&new_event); 216 break; 217 case ADBK_KEYUP(ADBK_1): 218 aed_sc->sc_buttons &= ~1; /* left up */ 219 new_event.def_addr = ADBADDR_MS; 220 new_event.u.m.buttons = aed_sc->sc_buttons; 221 new_event.u.m.dx = new_event.u.m.dy = 0; 222 microtime(&new_event.timestamp); 223 aed_handoff(&new_event); 224 break; 225 #endif 226 case ADBK_KEYDOWN(ADBK_LEFT): 227 #ifdef ALTXBUTTONS 228 case ADBK_KEYDOWN(ADBK_2): 229 #endif 230 aed_sc->sc_buttons |= 2; /* middle down */ 231 new_event.def_addr = ADBADDR_MS; 232 new_event.u.m.buttons = aed_sc->sc_buttons; 233 new_event.u.m.dx = new_event.u.m.dy = 0; 234 microtime(&new_event.timestamp); 235 aed_handoff(&new_event); 236 break; 237 case ADBK_KEYUP(ADBK_LEFT): 238 #ifdef ALTXBUTTONS 239 case ADBK_KEYUP(ADBK_2): 240 #endif 241 aed_sc->sc_buttons &= ~2; /* middle up */ 242 new_event.def_addr = ADBADDR_MS; 243 new_event.u.m.buttons = aed_sc->sc_buttons; 244 new_event.u.m.dx = new_event.u.m.dy = 0; 245 microtime(&new_event.timestamp); 246 aed_handoff(&new_event); 247 break; 248 case ADBK_KEYDOWN(ADBK_RIGHT): 249 #ifdef ALTXBUTTONS 250 case ADBK_KEYDOWN(ADBK_3): 251 #endif 252 aed_sc->sc_buttons |= 4; /* right down */ 253 new_event.def_addr = ADBADDR_MS; 254 new_event.u.m.buttons = aed_sc->sc_buttons; 255 new_event.u.m.dx = new_event.u.m.dy = 0; 256 microtime(&new_event.timestamp); 257 aed_handoff(&new_event); 258 break; 259 case ADBK_KEYUP(ADBK_RIGHT): 260 #ifdef ALTXBUTTONS 261 case ADBK_KEYUP(ADBK_3): 262 #endif 263 aed_sc->sc_buttons &= ~4; /* right up */ 264 new_event.def_addr = ADBADDR_MS; 265 new_event.u.m.buttons = aed_sc->sc_buttons; 266 new_event.u.m.dx = new_event.u.m.dy = 0; 267 microtime(&new_event.timestamp); 268 aed_handoff(&new_event); 269 break; 270 case ADBK_KEYUP(ADBK_SHIFT): 271 case ADBK_KEYDOWN(ADBK_SHIFT): 272 case ADBK_KEYUP(ADBK_CONTROL): 273 case ADBK_KEYDOWN(ADBK_CONTROL): 274 case ADBK_KEYUP(ADBK_FLOWER): 275 case ADBK_KEYDOWN(ADBK_FLOWER): 276 /* ctrl, shift, cmd */ 277 aed_dokeyupdown(event); 278 break; 279 default: 280 if (event->u.k.key & 0x80) 281 /* ignore keyup */ 282 break; 283 284 /* key down */ 285 new_event = *event; 286 287 /* send option-down */ 288 new_event.u.k.key = ADBK_KEYDOWN(ADBK_OPTION); 289 new_event.bytes[0] = new_event.u.k.key; 290 microtime(&new_event.timestamp); 291 aed_dokeyupdown(&new_event); 292 293 /* send key-down */ 294 new_event.u.k.key = event->bytes[0]; 295 new_event.bytes[0] = new_event.u.k.key; 296 microtime(&new_event.timestamp); 297 aed_dokeyupdown(&new_event); 298 299 /* send key-up */ 300 new_event.u.k.key = 301 ADBK_KEYUP(ADBK_KEYVAL(event->bytes[0])); 302 microtime(&new_event.timestamp); 303 new_event.bytes[0] = new_event.u.k.key; 304 aed_dokeyupdown(&new_event); 305 306 /* send option-up */ 307 new_event.u.k.key = ADBK_KEYUP(ADBK_OPTION); 308 new_event.bytes[0] = new_event.u.k.key; 309 microtime(&new_event.timestamp); 310 aed_dokeyupdown(&new_event); 311 break; 312 } 313 } else { 314 aed_dokeyupdown(event); 315 } 316 } 317 318 /* 319 * Keyboard autorepeat timeout function. Sends key up/down events 320 * for the repeating key and schedules the next call at sc_rptinterval 321 * ticks in the future. 322 */ 323 static void 324 aed_kbdrpt(void *kstate) 325 { 326 struct aed_softc *sc = (struct aed_softc *)kstate; 327 328 sc->sc_rptevent.bytes[0] |= 0x80; 329 microtime(&sc->sc_rptevent.timestamp); 330 aed_handoff(&sc->sc_rptevent); /* do key up */ 331 332 sc->sc_rptevent.bytes[0] &= 0x7f; 333 microtime(&sc->sc_rptevent.timestamp); 334 aed_handoff(&sc->sc_rptevent); /* do key down */ 335 336 if (sc->sc_repeating == sc->sc_rptevent.u.k.key) { 337 callout_reset(&sc->sc_repeat_ch, sc->sc_rptinterval, 338 aed_kbdrpt, kstate); 339 } 340 } 341 342 343 /* 344 * Cancels the currently repeating key event if there is one, schedules 345 * a new repeating key event if needed, and hands the event off to the 346 * appropriate subsystem. 347 */ 348 static void 349 aed_dokeyupdown(adb_event_t *event) 350 { 351 int kbd_key; 352 353 kbd_key = ADBK_KEYVAL(event->u.k.key); 354 if (ADBK_PRESS(event->u.k.key) && keyboard[kbd_key][0] != 0) { 355 /* ignore shift & control */ 356 if (aed_sc->sc_repeating != -1) { 357 callout_stop(&aed_sc->sc_repeat_ch); 358 } 359 aed_sc->sc_rptevent = *event; 360 aed_sc->sc_repeating = kbd_key; 361 callout_reset(&aed_sc->sc_repeat_ch, aed_sc->sc_rptdelay, 362 aed_kbdrpt, (void *)aed_sc); 363 } else { 364 if (aed_sc->sc_repeating != -1) { 365 aed_sc->sc_repeating = -1; 366 callout_stop(&aed_sc->sc_repeat_ch); 367 } 368 aed_sc->sc_rptevent = *event; 369 } 370 aed_handoff(event); 371 } 372 373 /* 374 * Place the event in the event queue if a requesting device is open 375 * and we are not polling. 376 */ 377 static void 378 aed_handoff(adb_event_t *event) 379 { 380 if (aed_sc->sc_open && !adb_polling) 381 aed_enqevent(event); 382 } 383 384 /* 385 * Place the event in the event queue and wakeup any waiting processes. 386 */ 387 static void 388 aed_enqevent(adb_event_t *event) 389 { 390 int s; 391 392 s = spladb(); 393 394 #ifdef DIAGNOSTIC 395 if (aed_sc->sc_evq_tail < 0 || aed_sc->sc_evq_tail >= AED_MAX_EVENTS) 396 panic("adb: event queue tail is out of bounds"); 397 398 if (aed_sc->sc_evq_len < 0 || aed_sc->sc_evq_len > AED_MAX_EVENTS) 399 panic("adb: event queue len is out of bounds"); 400 #endif 401 402 if (aed_sc->sc_evq_len == AED_MAX_EVENTS) { 403 splx(s); 404 return; /* Oh, well... */ 405 } 406 aed_sc->sc_evq[(aed_sc->sc_evq_len + aed_sc->sc_evq_tail) % 407 AED_MAX_EVENTS] = *event; 408 aed_sc->sc_evq_len++; 409 410 selnotify(&aed_sc->sc_selinfo, 0, 0); 411 if (aed_sc->sc_ioproc) 412 psignal(aed_sc->sc_ioproc, SIGIO); 413 414 splx(s); 415 } 416 417 int 418 aedopen(dev_t dev, int flag, int mode, struct lwp *l) 419 { 420 int unit; 421 int error = 0; 422 int s; 423 424 unit = minor(dev); 425 426 if (unit != 0) 427 return (ENXIO); 428 429 s = spladb(); 430 if (aed_sc->sc_open) { 431 splx(s); 432 return (EBUSY); 433 } 434 aed_sc->sc_evq_tail = 0; 435 aed_sc->sc_evq_len = 0; 436 aed_sc->sc_open = 1; 437 aed_sc->sc_ioproc = l->l_proc; 438 splx(s); 439 440 return (error); 441 } 442 443 444 int 445 aedclose(dev_t dev, int flag, int mode, struct lwp *l) 446 { 447 int s = spladb(); 448 449 aed_sc->sc_open = 0; 450 aed_sc->sc_ioproc = NULL; 451 splx(s); 452 453 return (0); 454 } 455 456 457 int 458 aedread(dev_t dev, struct uio *uio, int flag) 459 { 460 int s, error; 461 int willfit; 462 int total; 463 int firstmove; 464 int moremove; 465 466 if (uio->uio_resid < sizeof(adb_event_t)) 467 return (EMSGSIZE); /* close enough. */ 468 469 s = spladb(); 470 if (aed_sc->sc_evq_len == 0) { 471 splx(s); 472 return (0); 473 } 474 willfit = howmany(uio->uio_resid, sizeof(adb_event_t)); 475 total = (aed_sc->sc_evq_len < willfit) ? aed_sc->sc_evq_len : willfit; 476 477 firstmove = (aed_sc->sc_evq_tail + total > AED_MAX_EVENTS) 478 ? (AED_MAX_EVENTS - aed_sc->sc_evq_tail) : total; 479 480 error = uiomove((void *) & aed_sc->sc_evq[aed_sc->sc_evq_tail], 481 firstmove * sizeof(adb_event_t), uio); 482 if (error) { 483 splx(s); 484 return (error); 485 } 486 moremove = total - firstmove; 487 488 if (moremove > 0) { 489 error = uiomove((void *) & aed_sc->sc_evq[0], 490 moremove * sizeof(adb_event_t), uio); 491 if (error) { 492 splx(s); 493 return (error); 494 } 495 } 496 aed_sc->sc_evq_tail = (aed_sc->sc_evq_tail + total) % AED_MAX_EVENTS; 497 aed_sc->sc_evq_len -= total; 498 splx(s); 499 return (0); 500 } 501 502 int 503 aedioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 504 { 505 switch (cmd) { 506 case ADBIOCDEVSINFO: { 507 adb_devinfo_t *di; 508 ADBDataBlock adbdata; 509 int totaldevs; 510 int adbaddr; 511 int i; 512 513 di = (void *)data; 514 515 /* Initialize to no devices */ 516 for (i = 0; i < 16; i++) 517 di->dev[i].addr = -1; 518 519 totaldevs = CountADBs(); 520 for (i = 1; i <= totaldevs; i++) { 521 adbaddr = GetIndADB(&adbdata, i); 522 di->dev[adbaddr].addr = adbaddr; 523 di->dev[adbaddr].default_addr = (int)(adbdata.origADBAddr); 524 di->dev[adbaddr].handler_id = (int)(adbdata.devType); 525 } 526 527 /* Must call ADB Manager to get devices now */ 528 break; 529 } 530 531 case ADBIOCGETREPEAT:{ 532 adb_rptinfo_t *ri; 533 534 ri = (void *)data; 535 ri->delay_ticks = aed_sc->sc_rptdelay; 536 ri->interval_ticks = aed_sc->sc_rptinterval; 537 break; 538 } 539 540 case ADBIOCSETREPEAT:{ 541 adb_rptinfo_t *ri; 542 543 ri = (void *) data; 544 aed_sc->sc_rptdelay = ri->delay_ticks; 545 aed_sc->sc_rptinterval = ri->interval_ticks; 546 break; 547 } 548 549 case ADBIOCRESET: 550 /* Do nothing for now */ 551 break; 552 553 case ADBIOCLISTENCMD:{ 554 adb_listencmd_t *lc; 555 556 lc = (void *)data; 557 } 558 559 default: 560 return (EINVAL); 561 } 562 return (0); 563 } 564 565 566 int 567 aedpoll(dev_t dev, int events, struct lwp *l) 568 { 569 int s, revents; 570 571 revents = events & (POLLOUT | POLLWRNORM); 572 573 if ((events & (POLLIN | POLLRDNORM)) == 0) 574 return (revents); 575 576 s = spladb(); 577 if (aed_sc->sc_evq_len > 0) 578 revents |= events & (POLLIN | POLLRDNORM); 579 else 580 selrecord(l, &aed_sc->sc_selinfo); 581 splx(s); 582 583 return (revents); 584 } 585 586 static void 587 filt_aedrdetach(struct knote *kn) 588 { 589 int s; 590 591 s = spladb(); 592 SLIST_REMOVE(&aed_sc->sc_selinfo.sel_klist, kn, knote, kn_selnext); 593 splx(s); 594 } 595 596 static int 597 filt_aedread(struct knote *kn, long hint) 598 { 599 600 kn->kn_data = aed_sc->sc_evq_len * sizeof(adb_event_t); 601 return (kn->kn_data > 0); 602 } 603 604 static const struct filterops aedread_filtops = 605 { 1, NULL, filt_aedrdetach, filt_aedread }; 606 607 static const struct filterops aed_seltrue_filtops = 608 { 1, NULL, filt_aedrdetach, filt_seltrue }; 609 610 int 611 aedkqfilter(dev_t dev, struct knote *kn) 612 { 613 struct klist *klist; 614 int s; 615 616 switch (kn->kn_filter) { 617 case EVFILT_READ: 618 klist = &aed_sc->sc_selinfo.sel_klist; 619 kn->kn_fop = &aedread_filtops; 620 break; 621 622 case EVFILT_WRITE: 623 klist = &aed_sc->sc_selinfo.sel_klist; 624 kn->kn_fop = &aed_seltrue_filtops; 625 break; 626 627 default: 628 return (1); 629 } 630 631 kn->kn_hook = NULL; 632 633 s = spladb(); 634 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 635 splx(s); 636 637 return (0); 638 } 639