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