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