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