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