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