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