1 /* $NetBSD: adb.c,v 1.12 1996/10/13 03:21:13 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 e* 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/param.h> 34 #include <sys/device.h> 35 #include <sys/fcntl.h> 36 #include <sys/poll.h> 37 #include <sys/select.h> 38 #include <sys/proc.h> 39 #include <sys/signalvar.h> 40 #include <sys/systm.h> 41 42 #include <machine/adbsys.h> 43 #include <machine/autoconf.h> 44 #include <machine/keyboard.h> 45 46 #include "adbvar.h" 47 #include "itevar.h" 48 #include "../mac68k/macrom.h" 49 50 /* 51 * Function declarations. 52 */ 53 static int adbmatch __P((struct device *, void *, void *)); 54 static void adbattach __P((struct device *, struct device *, void *)); 55 56 /* 57 * Global variables. 58 */ 59 int adb_polling = 0; /* Are we polling? (Debugger mode) */ 60 61 /* 62 * Local variables. 63 */ 64 65 /* External keyboard translation matrix */ 66 extern unsigned char keyboard[128][3]; 67 68 /* Event queue definitions */ 69 #if !defined(ADB_MAX_EVENTS) 70 #define ADB_MAX_EVENTS 200 /* Maximum events to be kept in queue */ 71 /* maybe should be higher for slower macs? */ 72 #endif /* !defined(ADB_MAX_EVENTS) */ 73 static adb_event_t adb_evq[ADB_MAX_EVENTS]; /* ADB event queue */ 74 static int adb_evq_tail = 0; /* event queue tail */ 75 static int adb_evq_len = 0; /* event queue length */ 76 77 /* ADB device state information */ 78 static int adb_isopen = 0; /* Are we queuing events for adb_read? */ 79 static struct selinfo adb_selinfo; /* select() info */ 80 static struct proc *adb_ioproc = NULL; /* process to wakeup */ 81 82 /* Key repeat parameters */ 83 static int adb_rptdelay = 20; /* ticks before auto-repeat */ 84 static int adb_rptinterval = 6; /* ticks between auto-repeat */ 85 static int adb_repeating = -1; /* key that is auto-repeating */ 86 static adb_event_t adb_rptevent;/* event to auto-repeat */ 87 88 /* Driver definition. -- This should probably be a bus... */ 89 struct cfattach adb_ca = { 90 sizeof(struct device), adbmatch, adbattach 91 }; 92 93 struct cfdriver adb_cd = { 94 NULL, "adb", DV_DULL 95 }; 96 97 static int 98 adbmatch(pdp, match, auxp) 99 struct device *pdp; 100 void *match, *auxp; 101 { 102 return 1; 103 } 104 105 static void 106 adbattach(parent, dev, aux) 107 struct device *parent, *dev; 108 void *aux; 109 { 110 printf(" (ADB event device)\n"); 111 } 112 113 void 114 adb_enqevent(event) 115 adb_event_t *event; 116 { 117 int s; 118 119 s = spladb(); 120 121 #ifdef DIAGNOSTIC 122 if (adb_evq_tail < 0 || adb_evq_tail >= ADB_MAX_EVENTS) 123 panic("adb: event queue tail is out of bounds"); 124 125 if (adb_evq_len < 0 || adb_evq_len > ADB_MAX_EVENTS) 126 panic("adb: event queue len is out of bounds"); 127 #endif 128 129 if (adb_evq_len == ADB_MAX_EVENTS) { 130 splx(s); 131 return; /* Oh, well... */ 132 } 133 adb_evq[(adb_evq_len + adb_evq_tail) % ADB_MAX_EVENTS] = 134 *event; 135 adb_evq_len++; 136 137 selwakeup(&adb_selinfo); 138 if (adb_ioproc) 139 psignal(adb_ioproc, SIGIO); 140 141 splx(s); 142 } 143 144 void 145 adb_handoff(event) 146 adb_event_t *event; 147 { 148 if (adb_isopen && !adb_polling) { 149 adb_enqevent(event); 150 } else { 151 if (event->def_addr == 2) 152 ite_intr(event); 153 } 154 } 155 156 157 void 158 adb_autorepeat(keyp) 159 void *keyp; 160 { 161 int key = (int) keyp; 162 163 adb_rptevent.bytes[0] |= 0x80; 164 microtime(&adb_rptevent.timestamp); 165 adb_handoff(&adb_rptevent); /* do key up */ 166 167 adb_rptevent.bytes[0] &= 0x7f; 168 microtime(&adb_rptevent.timestamp); 169 adb_handoff(&adb_rptevent); /* do key down */ 170 171 if (adb_repeating == key) { 172 timeout(adb_autorepeat, keyp, adb_rptinterval); 173 } 174 } 175 176 177 void 178 adb_dokeyupdown(event) 179 adb_event_t *event; 180 { 181 int adb_key; 182 183 if (event->def_addr == 2) { 184 adb_key = event->u.k.key & 0x7f; 185 if (!(event->u.k.key & 0x80) && 186 keyboard[event->u.k.key & 0x7f][0] != 0) { 187 /* ignore shift & control */ 188 if (adb_repeating != -1) { 189 untimeout(adb_autorepeat, 190 (void *) adb_rptevent.u.k.key); 191 } 192 adb_rptevent = *event; 193 adb_repeating = adb_key; 194 timeout(adb_autorepeat, 195 (void *) adb_key, adb_rptdelay); 196 } else { 197 if (adb_repeating != -1) { 198 adb_repeating = -1; 199 untimeout(adb_autorepeat, 200 (void *) adb_rptevent.u.k.key); 201 } 202 adb_rptevent = *event; 203 } 204 } 205 adb_handoff(event); 206 } 207 208 static adb_ms_buttons = 0; 209 210 void 211 adb_keymaybemouse(event) 212 adb_event_t *event; 213 { 214 static int optionkey_down = 0; 215 adb_event_t new_event; 216 217 if (event->u.k.key == ADBK_KEYDOWN(ADBK_OPTION)) { 218 optionkey_down = 1; 219 } else if (event->u.k.key == ADBK_KEYUP(ADBK_OPTION)) { 220 /* key up */ 221 optionkey_down = 0; 222 if (adb_ms_buttons & 0xfe) { 223 adb_ms_buttons &= 1; 224 new_event.def_addr = ADBADDR_MS; 225 new_event.u.m.buttons = adb_ms_buttons; 226 new_event.u.m.dx = new_event.u.m.dy = 0; 227 microtime(&new_event.timestamp); 228 adb_dokeyupdown(&new_event); 229 } 230 } else if (optionkey_down) { 231 if (event->u.k.key == ADBK_KEYDOWN(ADBK_LEFT)) { 232 adb_ms_buttons |= 2; /* middle down */ 233 new_event.def_addr = ADBADDR_MS; 234 new_event.u.m.buttons = adb_ms_buttons; 235 new_event.u.m.dx = new_event.u.m.dy = 0; 236 microtime(&new_event.timestamp); 237 adb_dokeyupdown(&new_event); 238 } else if (event->u.k.key == ADBK_KEYUP(ADBK_LEFT)) { 239 adb_ms_buttons &= ~2; /* middle up */ 240 new_event.def_addr = ADBADDR_MS; 241 new_event.u.m.buttons = adb_ms_buttons; 242 new_event.u.m.dx = new_event.u.m.dy = 0; 243 microtime(&new_event.timestamp); 244 adb_dokeyupdown(&new_event); 245 } else if (event->u.k.key == ADBK_KEYDOWN(ADBK_RIGHT)) { 246 adb_ms_buttons |= 4; /* right down */ 247 new_event.def_addr = ADBADDR_MS; 248 new_event.u.m.buttons = adb_ms_buttons; 249 new_event.u.m.dx = new_event.u.m.dy = 0; 250 microtime(&new_event.timestamp); 251 adb_dokeyupdown(&new_event); 252 } else if (event->u.k.key == ADBK_KEYUP(ADBK_RIGHT)) { 253 adb_ms_buttons &= ~4; /* right up */ 254 new_event.def_addr = ADBADDR_MS; 255 new_event.u.m.buttons = adb_ms_buttons; 256 new_event.u.m.dx = new_event.u.m.dy = 0; 257 microtime(&new_event.timestamp); 258 adb_dokeyupdown(&new_event); 259 } else if (ADBK_MODIFIER(event->u.k.key)) { 260 /* ctrl, shift, cmd */ 261 adb_dokeyupdown(event); 262 } else if (!(event->u.k.key & 0x80)) { 263 /* key down */ 264 new_event = *event; 265 266 /* send option-down */ 267 new_event.u.k.key = ADBK_KEYDOWN(ADBK_OPTION); 268 new_event.bytes[0] = new_event.u.k.key; 269 microtime(&new_event.timestamp); 270 adb_dokeyupdown(&new_event); 271 272 /* send key-down */ 273 new_event.u.k.key = event->bytes[0]; 274 new_event.bytes[0] = new_event.u.k.key; 275 microtime(&new_event.timestamp); 276 adb_dokeyupdown(&new_event); 277 278 /* send key-up */ 279 new_event.u.k.key = 280 ADBK_KEYUP(ADBK_KEYVAL(event->bytes[0])); 281 microtime(&new_event.timestamp); 282 new_event.bytes[0] = new_event.u.k.key; 283 adb_dokeyupdown(&new_event); 284 285 /* send option-up */ 286 new_event.u.k.key = ADBK_KEYUP(ADBK_OPTION); 287 new_event.bytes[0] = new_event.u.k.key; 288 microtime(&new_event.timestamp); 289 adb_dokeyupdown(&new_event); 290 } else { 291 /* option-keyup -- do nothing. */ 292 } 293 } else { 294 adb_dokeyupdown(event); 295 } 296 } 297 298 299 void 300 adb_processevent(event) 301 adb_event_t *event; 302 { 303 adb_event_t new_event; 304 int i, button_bit, max_byte, mask, buttons; 305 306 new_event = *event; 307 buttons = 0; 308 309 switch (event->def_addr) { 310 case ADBADDR_KBD: 311 new_event.u.k.key = event->bytes[0]; 312 new_event.bytes[1] = 0xff; 313 adb_keymaybemouse(&new_event); 314 if (event->bytes[1] != 0xff) { 315 new_event.u.k.key = event->bytes[1]; 316 new_event.bytes[0] = event->bytes[1]; 317 new_event.bytes[1] = 0xff; 318 adb_keymaybemouse(&new_event); 319 } 320 break; 321 case ADBADDR_MS: 322 /* 323 * This should handle both plain ol' Apple mice and mice 324 * that claim to support the Extended Apple Mouse Protocol. 325 */ 326 max_byte = event->byte_count; 327 button_bit = 1; 328 switch (event->hand_id) { 329 case ADBMS_USPEED: 330 /* MicroSpeed mouse */ 331 if (max_byte == 4) 332 buttons = (~event->bytes[2]) & 0xff; 333 else 334 buttons = (event->bytes[0] & 0x80) ? 0 : 1; 335 break; 336 default: 337 /* Classic Mouse Protocol (up to 2 buttons) */ 338 for (i = 0; i < 2; i++, button_bit <<= 1) 339 /* 0 when button down */ 340 if (!(event->bytes[i] & 0x80)) 341 buttons |= button_bit; 342 else 343 buttons &= ~button_bit; 344 /* Extended Protocol (up to 6 more buttons) */ 345 for (mask = 0x80; i < max_byte; 346 i += (mask == 0x80), button_bit <<= 1) { 347 /* 0 when button down */ 348 if (!(event->bytes[i] & mask)) 349 buttons |= button_bit; 350 else 351 buttons &= ~button_bit; 352 mask = ((mask >> 4) & 0xf) 353 | ((mask & 0xf) << 4); 354 } 355 break; 356 } 357 new_event.u.m.buttons = adb_ms_buttons | buttons; 358 new_event.u.m.dx = ((signed int) (event->bytes[1] & 0x3f)) - 359 ((event->bytes[1] & 0x40) ? 64 : 0); 360 new_event.u.m.dy = ((signed int) (event->bytes[0] & 0x3f)) - 361 ((event->bytes[0] & 0x40) ? 64 : 0); 362 adb_dokeyupdown(&new_event); 363 break; 364 default: /* God only knows. */ 365 adb_dokeyupdown(event); 366 } 367 } 368 369 370 int 371 adbopen(dev, flag, mode, p) 372 dev_t dev; 373 int flag, mode; 374 struct proc *p; 375 { 376 register int unit; 377 int error = 0; 378 int s; 379 380 unit = minor(dev); 381 if (unit != 0) 382 return (ENXIO); 383 384 s = spladb(); 385 if (adb_isopen) { 386 splx(s); 387 return (EBUSY); 388 } 389 adb_evq_tail = 0; 390 adb_evq_len = 0; 391 adb_isopen = 1; 392 adb_ioproc = p; 393 splx(s); 394 395 return (error); 396 } 397 398 399 int 400 adbclose(dev, flag, mode, p) 401 dev_t dev; 402 int flag, mode; 403 struct proc *p; 404 { 405 int s = spladb(); 406 407 adb_isopen = 0; 408 adb_ioproc = NULL; 409 splx(s); 410 411 return (0); 412 } 413 414 415 int 416 adbread(dev, uio, flag) 417 dev_t dev; 418 struct uio *uio; 419 int flag; 420 { 421 int s, error; 422 int willfit; 423 int total; 424 int firstmove; 425 int moremove; 426 427 if (uio->uio_resid < sizeof(adb_event_t)) 428 return (EMSGSIZE); /* close enough. */ 429 430 s = spladb(); 431 if (adb_evq_len == 0) { 432 splx(s); 433 return (0); 434 } 435 willfit = howmany(uio->uio_resid, sizeof(adb_event_t)); 436 total = (adb_evq_len < willfit) ? adb_evq_len : willfit; 437 438 firstmove = (adb_evq_tail + total > ADB_MAX_EVENTS) 439 ? (ADB_MAX_EVENTS - adb_evq_tail) : total; 440 441 error = uiomove((caddr_t) & adb_evq[adb_evq_tail], 442 firstmove * sizeof(adb_event_t), uio); 443 if (error) { 444 splx(s); 445 return (error); 446 } 447 moremove = total - firstmove; 448 449 if (moremove > 0) { 450 error = uiomove((caddr_t) & adb_evq[0], 451 moremove * sizeof(adb_event_t), uio); 452 if (error) { 453 splx(s); 454 return (error); 455 } 456 } 457 adb_evq_tail = (adb_evq_tail + total) % ADB_MAX_EVENTS; 458 adb_evq_len -= total; 459 splx(s); 460 return (0); 461 } 462 463 464 int 465 adbwrite(dev, uio, flag) 466 dev_t dev; 467 struct uio *uio; 468 int flag; 469 { 470 return 0; 471 } 472 473 474 int 475 adbioctl(dev, cmd, data, flag, p) 476 dev_t dev; 477 int cmd; 478 caddr_t data; 479 int flag; 480 struct proc *p; 481 { 482 switch (cmd) { 483 case ADBIOC_DEVSINFO: { 484 adb_devinfo_t *di; 485 ADBDataBlock adbdata; 486 int totaldevs; 487 int adbaddr; 488 int i; 489 490 di = (void *) data; 491 492 /* Initialize to no devices */ 493 for (i = 0; i < 16; i++) 494 di->dev[i].addr = -1; 495 496 totaldevs = CountADBs(); 497 for (i = 1; i <= totaldevs; i++) { 498 adbaddr = GetIndADB(&adbdata, i); 499 di->dev[adbaddr].addr = adbaddr; 500 di->dev[adbaddr].default_addr = adbdata.origADBAddr; 501 di->dev[adbaddr].handler_id = adbdata.devType; 502 } 503 504 /* Must call ADB Manager to get devices now */ 505 break; 506 } 507 508 case ADBIOC_GETREPEAT:{ 509 adb_rptinfo_t *ri; 510 511 ri = (void *) data; 512 ri->delay_ticks = adb_rptdelay; 513 ri->interval_ticks = adb_rptinterval; 514 break; 515 } 516 517 case ADBIOC_SETREPEAT:{ 518 adb_rptinfo_t *ri; 519 520 ri = (void *) data; 521 adb_rptdelay = ri->delay_ticks; 522 adb_rptinterval = ri->interval_ticks; 523 break; 524 } 525 526 case ADBIOC_RESET: 527 adb_init(); 528 break; 529 530 case ADBIOC_LISTENCMD:{ 531 adb_listencmd_t *lc; 532 533 lc = (void *) data; 534 } 535 536 default: 537 return (EINVAL); 538 } 539 return (0); 540 } 541 542 543 int 544 adbpoll(dev, events, p) 545 dev_t dev; 546 int events; 547 struct proc *p; 548 { 549 int s, revents; 550 551 revents = events & (POLLOUT | POLLWRNORM); 552 553 if ((events & (POLLIN | POLLRDNORM)) == 0) 554 return (revents); 555 556 s = spladb(); 557 if (adb_evq_len > 0) 558 revents |= events & (POLLIN | POLLRDNORM); 559 else 560 selrecord(p, &adb_selinfo); 561 splx(s); 562 563 return (revents); 564 } 565