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