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