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