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