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