adb.c revision 1.24 1 /* $NetBSD: adb.c,v 1.24 1998/08/11 20:07:59 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 "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 case ADBMS_UCONTOUR:
375 /* MicroSpeed mouse and Contour Mouse */
376 if (max_byte == 4)
377 buttons = (~event->bytes[2]) & 0xff;
378 else
379 buttons = (event->bytes[0] & 0x80) ? 0 : 1;
380 break;
381 case ADBMS_MSA3:
382 /* Mouse Systems A3 mouse */
383 if (max_byte == 3)
384 buttons = (~event->bytes[2]) & 0x07;
385 else
386 buttons = (event->bytes[0] & 0x80) ? 0 : 1;
387 break;
388 default:
389 /* Classic Mouse Protocol (up to 2 buttons) */
390 for (i = 0; i < 2; i++, button_bit <<= 1)
391 /* 0 when button down */
392 if (!(event->bytes[i] & 0x80))
393 buttons |= button_bit;
394 else
395 buttons &= ~button_bit;
396 /* Extended Protocol (up to 6 more buttons) */
397 for (mask = 0x80; i < max_byte;
398 i += (mask == 0x80), button_bit <<= 1) {
399 /* 0 when button down */
400 if (!(event->bytes[i] & mask))
401 buttons |= button_bit;
402 else
403 buttons &= ~button_bit;
404 mask = ((mask >> 4) & 0xf)
405 | ((mask & 0xf) << 4);
406 }
407 break;
408 }
409 new_event.u.m.buttons = adb_ms_buttons | buttons;
410 new_event.u.m.dx = ((signed int) (event->bytes[1] & 0x3f)) -
411 ((event->bytes[1] & 0x40) ? 64 : 0);
412 new_event.u.m.dy = ((signed int) (event->bytes[0] & 0x3f)) -
413 ((event->bytes[0] & 0x40) ? 64 : 0);
414 adb_dokeyupdown(&new_event);
415 break;
416 default: /* God only knows. */
417 adb_dokeyupdown(event);
418 }
419 }
420
421
422 int
423 adbopen(dev, flag, mode, p)
424 dev_t dev;
425 int flag, mode;
426 struct proc *p;
427 {
428 register int unit;
429 int error = 0;
430 int s;
431
432 unit = minor(dev);
433 if (unit != 0 || !adb_initted)
434 return (ENXIO);
435
436 s = spladb();
437 if (adb_isopen) {
438 splx(s);
439 return (EBUSY);
440 }
441 adb_evq_tail = 0;
442 adb_evq_len = 0;
443 adb_isopen = 1;
444 adb_ioproc = p;
445 splx(s);
446
447 return (error);
448 }
449
450
451 int
452 adbclose(dev, flag, mode, p)
453 dev_t dev;
454 int flag, mode;
455 struct proc *p;
456 {
457 int s = spladb();
458
459 adb_isopen = 0;
460 adb_ioproc = NULL;
461 splx(s);
462
463 return (0);
464 }
465
466
467 int
468 adbread(dev, uio, flag)
469 dev_t dev;
470 struct uio *uio;
471 int flag;
472 {
473 int s, error;
474 int willfit;
475 int total;
476 int firstmove;
477 int moremove;
478
479 if (uio->uio_resid < sizeof(adb_event_t))
480 return (EMSGSIZE); /* close enough. */
481
482 s = spladb();
483 if (adb_evq_len == 0) {
484 splx(s);
485 return (0);
486 }
487 willfit = howmany(uio->uio_resid, sizeof(adb_event_t));
488 total = (adb_evq_len < willfit) ? adb_evq_len : willfit;
489
490 firstmove = (adb_evq_tail + total > ADB_MAX_EVENTS)
491 ? (ADB_MAX_EVENTS - adb_evq_tail) : total;
492
493 error = uiomove((caddr_t) & adb_evq[adb_evq_tail],
494 firstmove * sizeof(adb_event_t), uio);
495 if (error) {
496 splx(s);
497 return (error);
498 }
499 moremove = total - firstmove;
500
501 if (moremove > 0) {
502 error = uiomove((caddr_t) & adb_evq[0],
503 moremove * sizeof(adb_event_t), uio);
504 if (error) {
505 splx(s);
506 return (error);
507 }
508 }
509 adb_evq_tail = (adb_evq_tail + total) % ADB_MAX_EVENTS;
510 adb_evq_len -= total;
511 splx(s);
512 return (0);
513 }
514
515
516 int
517 adbwrite(dev, uio, flag)
518 dev_t dev;
519 struct uio *uio;
520 int flag;
521 {
522 return 0;
523 }
524
525
526 int
527 adbioctl(dev, cmd, data, flag, p)
528 dev_t dev;
529 int cmd;
530 caddr_t data;
531 int flag;
532 struct proc *p;
533 {
534 switch (cmd) {
535 case ADBIOC_DEVSINFO: {
536 adb_devinfo_t *di;
537 ADBDataBlock adbdata;
538 int totaldevs;
539 int adbaddr;
540 int i;
541
542 di = (void *)data;
543
544 /* Initialize to no devices */
545 for (i = 0; i < 16; i++)
546 di->dev[i].addr = -1;
547
548 totaldevs = CountADBs();
549 for (i = 1; i <= totaldevs; i++) {
550 adbaddr = GetIndADB(&adbdata, i);
551 di->dev[adbaddr].addr = adbaddr;
552 di->dev[adbaddr].default_addr = adbdata.origADBAddr;
553 di->dev[adbaddr].handler_id = adbdata.devType;
554 }
555
556 /* Must call ADB Manager to get devices now */
557 break;
558 }
559
560 case ADBIOC_GETREPEAT:{
561 adb_rptinfo_t *ri;
562
563 ri = (void *)data;
564 ri->delay_ticks = adb_rptdelay;
565 ri->interval_ticks = adb_rptinterval;
566 break;
567 }
568
569 case ADBIOC_SETREPEAT:{
570 adb_rptinfo_t *ri;
571
572 ri = (void *)data;
573 adb_rptdelay = ri->delay_ticks;
574 adb_rptinterval = ri->interval_ticks;
575 break;
576 }
577
578 case ADBIOC_RESET:
579 adb_init();
580 break;
581
582 case ADBIOC_LISTENCMD:{
583 adb_listencmd_t *lc;
584
585 lc = (void *)data;
586 }
587
588 default:
589 return (EINVAL);
590 }
591 return (0);
592 }
593
594
595 int
596 adbpoll(dev, events, p)
597 dev_t dev;
598 int events;
599 struct proc *p;
600 {
601 int s, revents;
602
603 revents = events & (POLLOUT | POLLWRNORM);
604
605 if ((events & (POLLIN | POLLRDNORM)) == 0)
606 return (revents);
607
608 s = spladb();
609 if (adb_evq_len > 0)
610 revents |= events & (POLLIN | POLLRDNORM);
611 else
612 selrecord(p, &adb_selinfo);
613 splx(s);
614
615 return (revents);
616 }
617