1 /* $NetBSD: aed.c,v 1.16 2002/11/26 19:50:26 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 "opt_adb.h" 34 35 #include <sys/param.h> 36 #include <sys/device.h> 37 #include <sys/fcntl.h> 38 #include <sys/poll.h> 39 #include <sys/select.h> 40 #include <sys/proc.h> 41 #include <sys/signalvar.h> 42 #include <sys/systm.h> 43 #include <sys/conf.h> 44 45 #include <machine/autoconf.h> 46 #include <machine/cpu.h> 47 #include <machine/keyboard.h> 48 49 #include <mac68k/mac68k/macrom.h> 50 #include <mac68k/dev/adbvar.h> 51 #include <mac68k/dev/aedvar.h> 52 #include <mac68k/dev/akbdvar.h> 53 54 /* 55 * Function declarations. 56 */ 57 static int aedmatch __P((struct device *, struct cfdata *, void *)); 58 static void aedattach __P((struct device *, struct device *, void *)); 59 static void aed_emulate_mouse __P((adb_event_t *event)); 60 static void aed_kbdrpt __P((void *kstate)); 61 static void aed_dokeyupdown __P((adb_event_t *event)); 62 static void aed_handoff __P((adb_event_t *event)); 63 static void aed_enqevent __P((adb_event_t *event)); 64 65 /* 66 * Local variables. 67 */ 68 static struct aed_softc *aed_sc = NULL; 69 static int aed_options = 0 | AED_MSEMUL; 70 71 /* Driver definition */ 72 CFATTACH_DECL(aed, sizeof(struct aed_softc), 73 aedmatch, aedattach, NULL, NULL); 74 75 extern struct cfdriver aed_cd; 76 77 dev_type_open(aedopen); 78 dev_type_close(aedclose); 79 dev_type_read(aedread); 80 dev_type_ioctl(aedioctl); 81 dev_type_poll(aedpoll); 82 dev_type_kqfilter(aedkqfilter); 83 84 const struct cdevsw aed_cdevsw = { 85 aedopen, aedclose, aedread, nullwrite, aedioctl, 86 nostop, notty, aedpoll, nommap, aedkqfilter, 87 }; 88 89 static int 90 aedmatch(parent, cf, aux) 91 struct device *parent; 92 struct cfdata *cf; 93 void *aux; 94 { 95 struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; 96 static int aed_matched = 0; 97 98 /* Allow only one instance. */ 99 if ((aa_args->origaddr == 0) && (!aed_matched)) { 100 aed_matched = 1; 101 return (1); 102 } else 103 return (0); 104 } 105 106 static void 107 aedattach(parent, self, aux) 108 struct device *parent, *self; 109 void *aux; 110 { 111 struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; 112 struct aed_softc *sc = (struct aed_softc *)self; 113 114 callout_init(&sc->sc_repeat_ch); 115 116 sc->origaddr = aa_args->origaddr; 117 sc->adbaddr = aa_args->adbaddr; 118 sc->handler_id = aa_args->handler_id; 119 120 sc->sc_evq_tail = 0; 121 sc->sc_evq_len = 0; 122 123 sc->sc_rptdelay = 20; 124 sc->sc_rptinterval = 6; 125 sc->sc_repeating = -1; /* not repeating */ 126 127 /* Pull in the options flags. */ 128 sc->sc_options = (sc->sc_dev.dv_cfdata->cf_flags | aed_options); 129 130 sc->sc_ioproc = NULL; 131 132 sc->sc_buttons = 0; 133 134 sc->sc_open = 0; 135 136 aed_sc = sc; 137 138 printf("ADB Event device\n"); 139 140 return; 141 } 142 143 /* 144 * Given a keyboard ADB event, record the keycode and call the key 145 * repeat handler, optionally passing the event through the mouse 146 * button emulation handler first. Pass mouse events directly to 147 * the handoff function. 148 */ 149 int 150 aed_input(event) 151 adb_event_t *event; 152 { 153 adb_event_t new_event = *event; 154 int rv = aed_sc->sc_open; 155 156 switch (event->def_addr) { 157 case ADBADDR_KBD: 158 if (aed_sc->sc_options & AED_MSEMUL) 159 aed_emulate_mouse(&new_event); 160 else 161 aed_dokeyupdown(&new_event); 162 break; 163 case ADBADDR_MS: 164 new_event.u.m.buttons |= aed_sc->sc_buttons; 165 aed_handoff(&new_event); 166 break; 167 default: /* God only knows. */ 168 #ifdef DIAGNOSTIC 169 panic("aed: received event from unsupported device!"); 170 #endif 171 rv = 0; 172 break; 173 } 174 175 return (rv); 176 } 177 178 /* 179 * Handles mouse button emulation via the keyboard. If the emulation 180 * modifier key is down, left and right arrows will generate 2nd and 181 * 3rd mouse button events while the 1, 2, and 3 keys will generate 182 * the corresponding mouse button event. 183 */ 184 static void 185 aed_emulate_mouse(event) 186 adb_event_t *event; 187 { 188 static int emulmodkey_down = 0; 189 adb_event_t new_event; 190 191 if (event->u.k.key == ADBK_KEYDOWN(ADBK_OPTION)) { 192 emulmodkey_down = 1; 193 } else if (event->u.k.key == ADBK_KEYUP(ADBK_OPTION)) { 194 /* key up */ 195 emulmodkey_down = 0; 196 if (aed_sc->sc_buttons & 0xfe) { 197 aed_sc->sc_buttons &= 1; 198 new_event.def_addr = ADBADDR_MS; 199 new_event.u.m.buttons = aed_sc->sc_buttons; 200 new_event.u.m.dx = new_event.u.m.dy = 0; 201 microtime(&new_event.timestamp); 202 aed_handoff(&new_event); 203 } 204 } else if (emulmodkey_down) { 205 switch(event->u.k.key) { 206 #ifdef ALTXBUTTONS 207 case ADBK_KEYDOWN(ADBK_1): 208 aed_sc->sc_buttons |= 1; /* left down */ 209 new_event.def_addr = ADBADDR_MS; 210 new_event.u.m.buttons = aed_sc->sc_buttons; 211 new_event.u.m.dx = new_event.u.m.dy = 0; 212 microtime(&new_event.timestamp); 213 aed_handoff(&new_event); 214 break; 215 case ADBK_KEYUP(ADBK_1): 216 aed_sc->sc_buttons &= ~1; /* left up */ 217 new_event.def_addr = ADBADDR_MS; 218 new_event.u.m.buttons = aed_sc->sc_buttons; 219 new_event.u.m.dx = new_event.u.m.dy = 0; 220 microtime(&new_event.timestamp); 221 aed_handoff(&new_event); 222 break; 223 #endif 224 case ADBK_KEYDOWN(ADBK_LEFT): 225 #ifdef ALTXBUTTONS 226 case ADBK_KEYDOWN(ADBK_2): 227 #endif 228 aed_sc->sc_buttons |= 2; /* middle down */ 229 new_event.def_addr = ADBADDR_MS; 230 new_event.u.m.buttons = aed_sc->sc_buttons; 231 new_event.u.m.dx = new_event.u.m.dy = 0; 232 microtime(&new_event.timestamp); 233 aed_handoff(&new_event); 234 break; 235 case ADBK_KEYUP(ADBK_LEFT): 236 #ifdef ALTXBUTTONS 237 case ADBK_KEYUP(ADBK_2): 238 #endif 239 aed_sc->sc_buttons &= ~2; /* middle up */ 240 new_event.def_addr = ADBADDR_MS; 241 new_event.u.m.buttons = aed_sc->sc_buttons; 242 new_event.u.m.dx = new_event.u.m.dy = 0; 243 microtime(&new_event.timestamp); 244 aed_handoff(&new_event); 245 break; 246 case ADBK_KEYDOWN(ADBK_RIGHT): 247 #ifdef ALTXBUTTONS 248 case ADBK_KEYDOWN(ADBK_3): 249 #endif 250 aed_sc->sc_buttons |= 4; /* right down */ 251 new_event.def_addr = ADBADDR_MS; 252 new_event.u.m.buttons = aed_sc->sc_buttons; 253 new_event.u.m.dx = new_event.u.m.dy = 0; 254 microtime(&new_event.timestamp); 255 aed_handoff(&new_event); 256 break; 257 case ADBK_KEYUP(ADBK_RIGHT): 258 #ifdef ALTXBUTTONS 259 case ADBK_KEYUP(ADBK_3): 260 #endif 261 aed_sc->sc_buttons &= ~4; /* right up */ 262 new_event.def_addr = ADBADDR_MS; 263 new_event.u.m.buttons = aed_sc->sc_buttons; 264 new_event.u.m.dx = new_event.u.m.dy = 0; 265 microtime(&new_event.timestamp); 266 aed_handoff(&new_event); 267 break; 268 case ADBK_KEYUP(ADBK_SHIFT): 269 case ADBK_KEYDOWN(ADBK_SHIFT): 270 case ADBK_KEYUP(ADBK_CONTROL): 271 case ADBK_KEYDOWN(ADBK_CONTROL): 272 case ADBK_KEYUP(ADBK_FLOWER): 273 case ADBK_KEYDOWN(ADBK_FLOWER): 274 /* ctrl, shift, cmd */ 275 aed_dokeyupdown(event); 276 break; 277 default: 278 if (event->u.k.key & 0x80) 279 /* ignore keyup */ 280 break; 281 282 /* key down */ 283 new_event = *event; 284 285 /* send option-down */ 286 new_event.u.k.key = ADBK_KEYDOWN(ADBK_OPTION); 287 new_event.bytes[0] = new_event.u.k.key; 288 microtime(&new_event.timestamp); 289 aed_dokeyupdown(&new_event); 290 291 /* send key-down */ 292 new_event.u.k.key = event->bytes[0]; 293 new_event.bytes[0] = new_event.u.k.key; 294 microtime(&new_event.timestamp); 295 aed_dokeyupdown(&new_event); 296 297 /* send key-up */ 298 new_event.u.k.key = 299 ADBK_KEYUP(ADBK_KEYVAL(event->bytes[0])); 300 microtime(&new_event.timestamp); 301 new_event.bytes[0] = new_event.u.k.key; 302 aed_dokeyupdown(&new_event); 303 304 /* send option-up */ 305 new_event.u.k.key = ADBK_KEYUP(ADBK_OPTION); 306 new_event.bytes[0] = new_event.u.k.key; 307 microtime(&new_event.timestamp); 308 aed_dokeyupdown(&new_event); 309 break; 310 } 311 } else { 312 aed_dokeyupdown(event); 313 } 314 } 315 316 /* 317 * Keyboard autorepeat timeout function. Sends key up/down events 318 * for the repeating key and schedules the next call at sc_rptinterval 319 * ticks in the future. 320 */ 321 static void 322 aed_kbdrpt(kstate) 323 void *kstate; 324 { 325 struct aed_softc *aed_sc = (struct aed_softc *)kstate; 326 327 aed_sc->sc_rptevent.bytes[0] |= 0x80; 328 microtime(&aed_sc->sc_rptevent.timestamp); 329 aed_handoff(&aed_sc->sc_rptevent); /* do key up */ 330 331 aed_sc->sc_rptevent.bytes[0] &= 0x7f; 332 microtime(&aed_sc->sc_rptevent.timestamp); 333 aed_handoff(&aed_sc->sc_rptevent); /* do key down */ 334 335 if (aed_sc->sc_repeating == aed_sc->sc_rptevent.u.k.key) { 336 callout_reset(&aed_sc->sc_repeat_ch, aed_sc->sc_rptinterval, 337 aed_kbdrpt, kstate); 338 } 339 } 340 341 342 /* 343 * Cancels the currently repeating key event if there is one, schedules 344 * a new repeating key event if needed, and hands the event off to the 345 * appropriate subsystem. 346 */ 347 static void 348 aed_dokeyupdown(event) 349 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, otherwise, pass it up to the console driver. 376 */ 377 static void 378 aed_handoff(event) 379 adb_event_t *event; 380 { 381 if (aed_sc->sc_open && !adb_polling) 382 aed_enqevent(event); 383 } 384 385 /* 386 * Place the event in the event queue and wakeup any waiting processes. 387 */ 388 static void 389 aed_enqevent(event) 390 adb_event_t *event; 391 { 392 int s; 393 394 s = spladb(); 395 396 #ifdef DIAGNOSTIC 397 if (aed_sc->sc_evq_tail < 0 || aed_sc->sc_evq_tail >= AED_MAX_EVENTS) 398 panic("adb: event queue tail is out of bounds"); 399 400 if (aed_sc->sc_evq_len < 0 || aed_sc->sc_evq_len > AED_MAX_EVENTS) 401 panic("adb: event queue len is out of bounds"); 402 #endif 403 404 if (aed_sc->sc_evq_len == AED_MAX_EVENTS) { 405 splx(s); 406 return; /* Oh, well... */ 407 } 408 aed_sc->sc_evq[(aed_sc->sc_evq_len + aed_sc->sc_evq_tail) % 409 AED_MAX_EVENTS] = *event; 410 aed_sc->sc_evq_len++; 411 412 selnotify(&aed_sc->sc_selinfo, 0); 413 if (aed_sc->sc_ioproc) 414 psignal(aed_sc->sc_ioproc, SIGIO); 415 416 splx(s); 417 } 418 419 int 420 aedopen(dev, flag, mode, p) 421 dev_t dev; 422 int flag, mode; 423 struct proc *p; 424 { 425 int unit; 426 int error = 0; 427 int s; 428 429 unit = minor(dev); 430 431 if (unit != 0) 432 return (ENXIO); 433 434 s = spladb(); 435 if (aed_sc->sc_open) { 436 splx(s); 437 return (EBUSY); 438 } 439 aed_sc->sc_evq_tail = 0; 440 aed_sc->sc_evq_len = 0; 441 aed_sc->sc_open = 1; 442 aed_sc->sc_ioproc = p; 443 splx(s); 444 445 return (error); 446 } 447 448 449 int 450 aedclose(dev, flag, mode, p) 451 dev_t dev; 452 int flag, mode; 453 struct proc *p; 454 { 455 int s = spladb(); 456 457 aed_sc->sc_open = 0; 458 aed_sc->sc_ioproc = NULL; 459 splx(s); 460 461 return (0); 462 } 463 464 465 int 466 aedread(dev, uio, flag) 467 dev_t dev; 468 struct uio *uio; 469 int flag; 470 { 471 int s, error; 472 int willfit; 473 int total; 474 int firstmove; 475 int moremove; 476 477 if (uio->uio_resid < sizeof(adb_event_t)) 478 return (EMSGSIZE); /* close enough. */ 479 480 s = spladb(); 481 if (aed_sc->sc_evq_len == 0) { 482 splx(s); 483 return (0); 484 } 485 willfit = howmany(uio->uio_resid, sizeof(adb_event_t)); 486 total = (aed_sc->sc_evq_len < willfit) ? aed_sc->sc_evq_len : willfit; 487 488 firstmove = (aed_sc->sc_evq_tail + total > AED_MAX_EVENTS) 489 ? (AED_MAX_EVENTS - aed_sc->sc_evq_tail) : total; 490 491 error = uiomove((caddr_t) & aed_sc->sc_evq[aed_sc->sc_evq_tail], 492 firstmove * sizeof(adb_event_t), uio); 493 if (error) { 494 splx(s); 495 return (error); 496 } 497 moremove = total - firstmove; 498 499 if (moremove > 0) { 500 error = uiomove((caddr_t) & aed_sc->sc_evq[0], 501 moremove * sizeof(adb_event_t), uio); 502 if (error) { 503 splx(s); 504 return (error); 505 } 506 } 507 aed_sc->sc_evq_tail = (aed_sc->sc_evq_tail + total) % AED_MAX_EVENTS; 508 aed_sc->sc_evq_len -= total; 509 splx(s); 510 return (0); 511 } 512 513 int 514 aedioctl(dev, cmd, data, flag, p) 515 dev_t dev; 516 u_long cmd; 517 caddr_t data; 518 int flag; 519 struct proc *p; 520 { 521 switch (cmd) { 522 case ADBIOC_DEVSINFO: { 523 adb_devinfo_t *di; 524 ADBDataBlock adbdata; 525 int totaldevs; 526 int adbaddr; 527 int i; 528 529 di = (void *)data; 530 531 /* Initialize to no devices */ 532 for (i = 0; i < 16; i++) 533 di->dev[i].addr = -1; 534 535 totaldevs = CountADBs(); 536 for (i = 1; i <= totaldevs; i++) { 537 adbaddr = GetIndADB(&adbdata, i); 538 di->dev[adbaddr].addr = adbaddr; 539 di->dev[adbaddr].default_addr = (int)(adbdata.origADBAddr); 540 di->dev[adbaddr].handler_id = (int)(adbdata.devType); 541 } 542 543 /* Must call ADB Manager to get devices now */ 544 break; 545 } 546 547 case ADBIOC_GETREPEAT:{ 548 adb_rptinfo_t *ri; 549 550 ri = (void *)data; 551 ri->delay_ticks = aed_sc->sc_rptdelay; 552 ri->interval_ticks = aed_sc->sc_rptinterval; 553 break; 554 } 555 556 case ADBIOC_SETREPEAT:{ 557 adb_rptinfo_t *ri; 558 559 ri = (void *) data; 560 aed_sc->sc_rptdelay = ri->delay_ticks; 561 aed_sc->sc_rptinterval = ri->interval_ticks; 562 break; 563 } 564 565 case ADBIOC_RESET: 566 /* Do nothing for now */ 567 break; 568 569 case ADBIOC_LISTENCMD:{ 570 adb_listencmd_t *lc; 571 572 lc = (void *)data; 573 } 574 575 default: 576 return (EINVAL); 577 } 578 return (0); 579 } 580 581 582 int 583 aedpoll(dev, events, p) 584 dev_t dev; 585 int events; 586 struct proc *p; 587 { 588 int s, revents; 589 590 revents = events & (POLLOUT | POLLWRNORM); 591 592 if ((events & (POLLIN | POLLRDNORM)) == 0) 593 return (revents); 594 595 s = spladb(); 596 if (aed_sc->sc_evq_len > 0) 597 revents |= events & (POLLIN | POLLRDNORM); 598 else 599 selrecord(p, &aed_sc->sc_selinfo); 600 splx(s); 601 602 return (revents); 603 } 604 605 static void 606 filt_aedrdetach(struct knote *kn) 607 { 608 int s; 609 610 s = spladb(); 611 SLIST_REMOVE(&aed_sc->sc_selinfo.sel_klist, kn, knote, kn_selnext); 612 splx(s); 613 } 614 615 static int 616 filt_aedread(struct knote *kn, long hint) 617 { 618 619 kn->kn_data = aed_sc->sc_evq_len * sizeof(adb_event_t); 620 return (kn->kn_data > 0); 621 } 622 623 static const struct filterops aedread_filtops = 624 { 1, NULL, filt_aedrdetach, filt_aedread }; 625 626 static const struct filterops aed_seltrue_filtops = 627 { 1, NULL, filt_aedrdetach, filt_seltrue }; 628 629 int 630 aedkqfilter(dev_t dev, struct knote *kn) 631 { 632 struct klist *klist; 633 int s; 634 635 switch (kn->kn_filter) { 636 case EVFILT_READ: 637 klist = &aed_sc->sc_selinfo.sel_klist; 638 kn->kn_fop = &aedread_filtops; 639 break; 640 641 case EVFILT_WRITE: 642 klist = &aed_sc->sc_selinfo.sel_klist; 643 kn->kn_fop = &aed_seltrue_filtops; 644 break; 645 646 default: 647 return (1); 648 } 649 650 kn->kn_hook = NULL; 651 652 s = spladb(); 653 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 654 splx(s); 655 656 return (0); 657 } 658