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