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