1 /* $NetBSD: aed.c,v 1.7 1999/02/16 01:08:16 ender 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 44 #include <machine/autoconf.h> 45 #include <machine/cpu.h> 46 #include <machine/keyboard.h> 47 48 #include <mac68k/mac68k/macrom.h> 49 #include <mac68k/dev/adbvar.h> 50 #include <mac68k/dev/aedvar.h> 51 #include <mac68k/dev/itevar.h> 52 #include <mac68k/dev/kbdvar.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 * Global variables. 67 */ 68 extern int ite_polling; /* Are we polling? (Debugger mode) */ 69 70 /* 71 * Local variables. 72 */ 73 static struct aed_softc *aed_sc = NULL; 74 static int aed_options = 0 | AED_MSEMUL; 75 76 /* Driver definition */ 77 struct cfattach aed_ca = { 78 sizeof(struct aed_softc), aedmatch, aedattach 79 }; 80 81 extern struct cfdriver aed_cd; 82 83 static int 84 aedmatch(parent, cf, aux) 85 struct device *parent; 86 struct cfdata *cf; 87 void *aux; 88 { 89 struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; 90 static int aed_matched = 0; 91 92 /* Allow only one instance. */ 93 if ((aa_args->origaddr == 0) && (!aed_matched)) { 94 aed_matched = 1; 95 return (1); 96 } else 97 return (0); 98 } 99 100 static void 101 aedattach(parent, self, aux) 102 struct device *parent, *self; 103 void *aux; 104 { 105 struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; 106 struct aed_softc *sc = (struct aed_softc *)self; 107 108 sc->origaddr = aa_args->origaddr; 109 sc->adbaddr = aa_args->adbaddr; 110 sc->handler_id = aa_args->handler_id; 111 112 sc->sc_evq_tail = 0; 113 sc->sc_evq_len = 0; 114 115 sc->sc_rptdelay = 20; 116 sc->sc_rptinterval = 6; 117 sc->sc_repeating = -1; /* not repeating */ 118 119 /* Pull in the options flags. */ 120 sc->sc_options = (sc->sc_dev.dv_cfdata->cf_flags | aed_options); 121 122 sc->sc_ioproc = NULL; 123 124 sc->sc_buttons = 0; 125 126 sc->sc_open = 0; 127 128 aed_sc = sc; 129 130 printf("ADB Event device\n"); 131 132 return; 133 } 134 135 /* 136 * Given a keyboard ADB event, record the keycode and call the key 137 * repeat handler, optionally passing the event through the mouse 138 * button emulation handler first. Pass mouse events directly to 139 * the handoff function. 140 */ 141 void 142 aed_input(event) 143 adb_event_t *event; 144 { 145 adb_event_t new_event = *event; 146 147 switch (event->def_addr) { 148 case ADBADDR_KBD: 149 if (aed_sc->sc_options & AED_MSEMUL) 150 aed_emulate_mouse(&new_event); 151 else 152 aed_dokeyupdown(&new_event); 153 break; 154 case ADBADDR_MS: 155 new_event.u.m.buttons |= aed_sc->sc_buttons; 156 aed_handoff(&new_event); 157 break; 158 default: /* God only knows. */ 159 #ifdef DIAGNOSTIC 160 panic("aed: received event from unsupported device!\n"); 161 #endif 162 break; 163 } 164 165 } 166 167 /* 168 * Handles mouse button emulation via the keyboard. If the emulation 169 * modifier key is down, left and right arrows will generate 2nd and 170 * 3rd mouse button events while the 1, 2, and 3 keys will generate 171 * the corresponding mouse button event. 172 */ 173 static void 174 aed_emulate_mouse(event) 175 adb_event_t *event; 176 { 177 static int emulmodkey_down = 0; 178 adb_event_t new_event; 179 180 if (event->u.k.key == ADBK_KEYDOWN(ADBK_OPTION)) { 181 emulmodkey_down = 1; 182 } else if (event->u.k.key == ADBK_KEYUP(ADBK_OPTION)) { 183 /* key up */ 184 emulmodkey_down = 0; 185 if (aed_sc->sc_buttons & 0xfe) { 186 aed_sc->sc_buttons &= 1; 187 new_event.def_addr = ADBADDR_MS; 188 new_event.u.m.buttons = aed_sc->sc_buttons; 189 new_event.u.m.dx = new_event.u.m.dy = 0; 190 microtime(&new_event.timestamp); 191 aed_handoff(&new_event); 192 } 193 } else if (emulmodkey_down) { 194 switch(event->u.k.key) { 195 #ifdef ALTXBUTTONS 196 case ADBK_KEYDOWN(ADBK_1): 197 aed_sc->sc_buttons |= 1; /* left down */ 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 break; 204 case ADBK_KEYUP(ADBK_1): 205 aed_sc->sc_buttons &= ~1; /* left up */ 206 new_event.def_addr = ADBADDR_MS; 207 new_event.u.m.buttons = aed_sc->sc_buttons; 208 new_event.u.m.dx = new_event.u.m.dy = 0; 209 microtime(&new_event.timestamp); 210 aed_handoff(&new_event); 211 break; 212 #endif 213 case ADBK_KEYDOWN(ADBK_LEFT): 214 #ifdef ALTXBUTTONS 215 case ADBK_KEYDOWN(ADBK_2): 216 #endif 217 aed_sc->sc_buttons |= 2; /* middle down */ 218 new_event.def_addr = ADBADDR_MS; 219 new_event.u.m.buttons = aed_sc->sc_buttons; 220 new_event.u.m.dx = new_event.u.m.dy = 0; 221 microtime(&new_event.timestamp); 222 aed_handoff(&new_event); 223 break; 224 case ADBK_KEYUP(ADBK_LEFT): 225 #ifdef ALTXBUTTONS 226 case ADBK_KEYUP(ADBK_2): 227 #endif 228 aed_sc->sc_buttons &= ~2; /* middle up */ 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_KEYDOWN(ADBK_RIGHT): 236 #ifdef ALTXBUTTONS 237 case ADBK_KEYDOWN(ADBK_3): 238 #endif 239 aed_sc->sc_buttons |= 4; /* right down */ 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_KEYUP(ADBK_RIGHT): 247 #ifdef ALTXBUTTONS 248 case ADBK_KEYUP(ADBK_3): 249 #endif 250 aed_sc->sc_buttons &= ~4; /* right up */ 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_SHIFT): 258 case ADBK_KEYDOWN(ADBK_SHIFT): 259 case ADBK_KEYUP(ADBK_CONTROL): 260 case ADBK_KEYDOWN(ADBK_CONTROL): 261 case ADBK_KEYUP(ADBK_FLOWER): 262 case ADBK_KEYDOWN(ADBK_FLOWER): 263 /* ctrl, shift, cmd */ 264 aed_dokeyupdown(event); 265 break; 266 default: 267 if (event->u.k.key & 0x80) 268 /* ignore keyup */ 269 break; 270 271 /* key down */ 272 new_event = *event; 273 274 /* send option-down */ 275 new_event.u.k.key = ADBK_KEYDOWN(ADBK_OPTION); 276 new_event.bytes[0] = new_event.u.k.key; 277 microtime(&new_event.timestamp); 278 aed_dokeyupdown(&new_event); 279 280 /* send key-down */ 281 new_event.u.k.key = event->bytes[0]; 282 new_event.bytes[0] = new_event.u.k.key; 283 microtime(&new_event.timestamp); 284 aed_dokeyupdown(&new_event); 285 286 /* send key-up */ 287 new_event.u.k.key = 288 ADBK_KEYUP(ADBK_KEYVAL(event->bytes[0])); 289 microtime(&new_event.timestamp); 290 new_event.bytes[0] = new_event.u.k.key; 291 aed_dokeyupdown(&new_event); 292 293 /* send option-up */ 294 new_event.u.k.key = ADBK_KEYUP(ADBK_OPTION); 295 new_event.bytes[0] = new_event.u.k.key; 296 microtime(&new_event.timestamp); 297 aed_dokeyupdown(&new_event); 298 break; 299 } 300 } else { 301 aed_dokeyupdown(event); 302 } 303 } 304 305 /* 306 * Keyboard autorepeat timeout function. Sends key up/down events 307 * for the repeating key and schedules the next call at sc_rptinterval 308 * ticks in the future. 309 */ 310 static void 311 aed_kbdrpt(kstate) 312 void *kstate; 313 { 314 struct aed_softc *aed_sc = (struct aed_softc *)kstate; 315 316 aed_sc->sc_rptevent.bytes[0] |= 0x80; 317 microtime(&aed_sc->sc_rptevent.timestamp); 318 aed_handoff(&aed_sc->sc_rptevent); /* do key up */ 319 320 aed_sc->sc_rptevent.bytes[0] &= 0x7f; 321 microtime(&aed_sc->sc_rptevent.timestamp); 322 aed_handoff(&aed_sc->sc_rptevent); /* do key down */ 323 324 if (aed_sc->sc_repeating == aed_sc->sc_rptevent.u.k.key) { 325 timeout(aed_kbdrpt, kstate, aed_sc->sc_rptinterval); 326 } 327 } 328 329 330 /* 331 * Cancels the currently repeating key event if there is one, schedules 332 * a new repeating key event if needed, and hands the event off to the 333 * appropriate subsystem. 334 */ 335 static void 336 aed_dokeyupdown(event) 337 adb_event_t *event; 338 { 339 int kbd_key; 340 341 kbd_key = ADBK_KEYVAL(event->u.k.key); 342 if (ADBK_PRESS(event->u.k.key) && keyboard[kbd_key][0] != 0) { 343 /* ignore shift & control */ 344 if (aed_sc->sc_repeating != -1) { 345 untimeout(aed_kbdrpt, (void *)aed_sc); 346 } 347 aed_sc->sc_rptevent = *event; 348 aed_sc->sc_repeating = kbd_key; 349 timeout(aed_kbdrpt, (void *)aed_sc, aed_sc->sc_rptdelay); 350 } else { 351 if (aed_sc->sc_repeating != -1) { 352 aed_sc->sc_repeating = -1; 353 untimeout(aed_kbdrpt, (void *)aed_sc); 354 } 355 aed_sc->sc_rptevent = *event; 356 } 357 aed_handoff(event); 358 } 359 360 /* 361 * Place the event in the event queue if a requesting device is open 362 * and we are not polling, otherwise, pass it up to the console driver. 363 */ 364 static void 365 aed_handoff(event) 366 adb_event_t *event; 367 { 368 if (aed_sc->sc_open && !ite_polling) 369 aed_enqevent(event); 370 else { 371 if (event->def_addr == 2) 372 ite_intr(event); 373 } 374 } 375 376 /* 377 * Place the event in the event queue and wakeup any waiting processes. 378 */ 379 static void 380 aed_enqevent(event) 381 adb_event_t *event; 382 { 383 int s; 384 385 s = spladb(); 386 387 #ifdef DIAGNOSTIC 388 if (aed_sc->sc_evq_tail < 0 || aed_sc->sc_evq_tail >= AED_MAX_EVENTS) 389 panic("adb: event queue tail is out of bounds"); 390 391 if (aed_sc->sc_evq_len < 0 || aed_sc->sc_evq_len > AED_MAX_EVENTS) 392 panic("adb: event queue len is out of bounds"); 393 #endif 394 395 if (aed_sc->sc_evq_len == AED_MAX_EVENTS) { 396 splx(s); 397 return; /* Oh, well... */ 398 } 399 aed_sc->sc_evq[(aed_sc->sc_evq_len + aed_sc->sc_evq_tail) % 400 AED_MAX_EVENTS] = *event; 401 aed_sc->sc_evq_len++; 402 403 selwakeup(&aed_sc->sc_selinfo); 404 if (aed_sc->sc_ioproc) 405 psignal(aed_sc->sc_ioproc, SIGIO); 406 407 splx(s); 408 } 409 410 int 411 aedopen(dev, flag, mode, p) 412 dev_t dev; 413 int flag, mode; 414 struct proc *p; 415 { 416 int unit; 417 int error = 0; 418 int s; 419 420 unit = minor(dev); 421 422 if (unit != 0) 423 return (ENXIO); 424 425 s = spladb(); 426 if (aed_sc->sc_open) { 427 splx(s); 428 return (EBUSY); 429 } 430 aed_sc->sc_evq_tail = 0; 431 aed_sc->sc_evq_len = 0; 432 aed_sc->sc_open = 1; 433 aed_sc->sc_ioproc = p; 434 splx(s); 435 436 return (error); 437 } 438 439 440 int 441 aedclose(dev, flag, mode, p) 442 dev_t dev; 443 int flag, mode; 444 struct proc *p; 445 { 446 int s = spladb(); 447 448 aed_sc->sc_open = 0; 449 aed_sc->sc_ioproc = NULL; 450 splx(s); 451 452 return (0); 453 } 454 455 456 int 457 aedread(dev, uio, flag) 458 dev_t dev; 459 struct uio *uio; 460 int flag; 461 { 462 int s, error; 463 int willfit; 464 int total; 465 int firstmove; 466 int moremove; 467 468 if (uio->uio_resid < sizeof(adb_event_t)) 469 return (EMSGSIZE); /* close enough. */ 470 471 s = spladb(); 472 if (aed_sc->sc_evq_len == 0) { 473 splx(s); 474 return (0); 475 } 476 willfit = howmany(uio->uio_resid, sizeof(adb_event_t)); 477 total = (aed_sc->sc_evq_len < willfit) ? aed_sc->sc_evq_len : willfit; 478 479 firstmove = (aed_sc->sc_evq_tail + total > AED_MAX_EVENTS) 480 ? (AED_MAX_EVENTS - aed_sc->sc_evq_tail) : total; 481 482 error = uiomove((caddr_t) & aed_sc->sc_evq[aed_sc->sc_evq_tail], 483 firstmove * sizeof(adb_event_t), uio); 484 if (error) { 485 splx(s); 486 return (error); 487 } 488 moremove = total - firstmove; 489 490 if (moremove > 0) { 491 error = uiomove((caddr_t) & aed_sc->sc_evq[0], 492 moremove * sizeof(adb_event_t), uio); 493 if (error) { 494 splx(s); 495 return (error); 496 } 497 } 498 aed_sc->sc_evq_tail = (aed_sc->sc_evq_tail + total) % AED_MAX_EVENTS; 499 aed_sc->sc_evq_len -= total; 500 splx(s); 501 return (0); 502 } 503 504 505 int 506 aedwrite(dev, uio, flag) 507 dev_t dev; 508 struct uio *uio; 509 int flag; 510 { 511 return 0; 512 } 513 514 515 int 516 aedioctl(dev, cmd, data, flag, p) 517 dev_t dev; 518 int cmd; 519 caddr_t data; 520 int flag; 521 struct proc *p; 522 { 523 switch (cmd) { 524 case ADBIOC_DEVSINFO: { 525 adb_devinfo_t *di; 526 ADBDataBlock adbdata; 527 int totaldevs; 528 int adbaddr; 529 int i; 530 531 di = (void *)data; 532 533 /* Initialize to no devices */ 534 for (i = 0; i < 16; i++) 535 di->dev[i].addr = -1; 536 537 totaldevs = CountADBs(); 538 for (i = 1; i <= totaldevs; i++) { 539 adbaddr = GetIndADB(&adbdata, i); 540 di->dev[adbaddr].addr = adbaddr; 541 di->dev[adbaddr].default_addr = (int)(adbdata.origADBAddr); 542 di->dev[adbaddr].handler_id = (int)(adbdata.devType); 543 } 544 545 /* Must call ADB Manager to get devices now */ 546 break; 547 } 548 549 case ADBIOC_GETREPEAT:{ 550 adb_rptinfo_t *ri; 551 552 ri = (void *)data; 553 ri->delay_ticks = aed_sc->sc_rptdelay; 554 ri->interval_ticks = aed_sc->sc_rptinterval; 555 break; 556 } 557 558 case ADBIOC_SETREPEAT:{ 559 adb_rptinfo_t *ri; 560 561 ri = (void *) data; 562 aed_sc->sc_rptdelay = ri->delay_ticks; 563 aed_sc->sc_rptinterval = ri->interval_ticks; 564 break; 565 } 566 567 case ADBIOC_RESET: 568 /* Do nothing for now */ 569 break; 570 571 case ADBIOC_LISTENCMD:{ 572 adb_listencmd_t *lc; 573 574 lc = (void *)data; 575 } 576 577 default: 578 return (EINVAL); 579 } 580 return (0); 581 } 582 583 584 int 585 aedpoll(dev, events, p) 586 dev_t dev; 587 int events; 588 struct proc *p; 589 { 590 int s, revents; 591 592 revents = events & (POLLOUT | POLLWRNORM); 593 594 if ((events & (POLLIN | POLLRDNORM)) == 0) 595 return (revents); 596 597 s = spladb(); 598 if (aed_sc->sc_evq_len > 0) 599 revents |= events & (POLLIN | POLLRDNORM); 600 else 601 selrecord(p, &aed_sc->sc_selinfo); 602 splx(s); 603 604 return (revents); 605 } 606