adb.c revision 1.2 1 /* $NetBSD: adb.c,v 1.2 1995/04/21 02:47:41 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 = ADBK_KEYVAL(event->bytes[0]);
263 adb_dokeyupdown(&new_event);
264 microtime(&new_event.timestamp);
265 new_event.bytes[0] = new_event.u.k.key;
266
267 /* send option-up */
268 new_event.u.k.key = ADBK_OPTION;
269 new_event.bytes[0] = new_event.u.k.key;
270 microtime(&new_event.timestamp);
271 adb_dokeyupdown(&new_event);
272 } else {
273 /* option-keyup -- do nothing. */
274 }
275 } else {
276 adb_dokeyupdown(event);
277 }
278 }
279
280
281 void
282 adb_processevent(event)
283 adb_event_t *event;
284 {
285 adb_event_t new_event;
286
287 new_event = *event;
288
289 switch (event->def_addr) {
290 case ADBADDR_KBD:
291 new_event.u.k.key = event->bytes[0];
292 new_event.bytes[1] = 0xff;
293 adb_keymaybemouse(&new_event);
294 if (event->bytes[1] != 0xff) {
295 new_event.u.k.key = event->bytes[1];
296 new_event.bytes[0] = event->bytes[1];
297 new_event.bytes[1] = 0xff;
298 adb_keymaybemouse(&new_event);
299 }
300 break;
301 case ADBADDR_MS:
302 if (!(event->bytes[0] & 0x80)) /* 0 is button down */
303 adb_ms_buttons |= 1;
304 else
305 adb_ms_buttons &= 0xfe;
306 new_event.u.m.buttons = adb_ms_buttons;
307 new_event.u.m.dx = ((signed int) (event->bytes[1] & 0x3f)) -
308 ((event->bytes[1] & 0x40) ? 64 : 0);
309 new_event.u.m.dy = ((signed int) (event->bytes[0] & 0x3f)) -
310 ((event->bytes[0] & 0x40) ? 64 : 0);
311 adb_dokeyupdown(&new_event);
312 break;
313 default: /* God only knows. */
314 adb_dokeyupdown(event);
315 }
316 }
317
318
319 int
320 adbopen(dev, flag, mode, p)
321 dev_t dev;
322 int flag, mode;
323 struct proc *p;
324 {
325 register int unit;
326 int error = 0;
327 int s;
328
329 unit = minor(dev);
330 if (unit != 0)
331 return (ENXIO);
332
333 s = splhigh();
334 if (adb_isopen) {
335 splx(s);
336 return (EBUSY);
337 }
338 splx(s);
339 adb_evq_tail = 0;
340 adb_evq_len = 0;
341 adb_isopen = 1;
342 adb_ioproc = p;
343
344 return (error);
345 }
346
347
348 int
349 adbclose(dev, flag, mode, p)
350 dev_t dev;
351 int flag, mode;
352 struct proc *p;
353 {
354 adb_isopen = 0;
355 adb_ioproc = NULL;
356 return (0);
357 }
358
359
360 int
361 adbread(dev, uio, flag)
362 dev_t dev;
363 struct uio *uio;
364 int flag;
365 {
366 int s, error;
367 int willfit;
368 int total;
369 int firstmove;
370 int moremove;
371
372 if (uio->uio_resid < sizeof(adb_event_t))
373 return (EMSGSIZE); /* close enough. */
374
375 s = splhigh();
376 if (adb_evq_len == 0) {
377 splx(s);
378 return (0);
379 }
380 willfit = howmany(uio->uio_resid, sizeof(adb_event_t));
381 total = (adb_evq_len < willfit) ? adb_evq_len : willfit;
382
383 firstmove = (adb_evq_tail + total > ADB_MAX_EVENTS)
384 ? (ADB_MAX_EVENTS - adb_evq_tail) : total;
385
386 error = uiomove((caddr_t) & adb_evq[adb_evq_tail],
387 firstmove * sizeof(adb_event_t), uio);
388 if (error) {
389 splx(s);
390 return (error);
391 }
392 moremove = total - firstmove;
393
394 if (moremove > 0) {
395 error = uiomove((caddr_t) & adb_evq[0],
396 moremove * sizeof(adb_event_t), uio);
397 if (error) {
398 splx(s);
399 return (error);
400 }
401 }
402 adb_evq_tail = (adb_evq_tail + total) % ADB_MAX_EVENTS;
403 adb_evq_len -= total;
404 splx(s);
405 return (0);
406 }
407
408
409 int
410 adbwrite(dev, uio, flag)
411 dev_t dev;
412 struct uio *uio;
413 int flag;
414 {
415 return 0;
416 }
417
418
419 int
420 adbioctl(dev, cmd, data, flag, p)
421 dev_t dev;
422 int cmd;
423 caddr_t data;
424 int flag;
425 struct proc *p;
426 {
427 switch (cmd) {
428 case ADBIOC_DEVSINFO: {
429 adb_devinfo_t *di;
430 ADBDataBlock adbdata;
431 int totaldevs;
432 int adbaddr;
433 int i;
434
435 di = (void *) data;
436
437 /* Initialize to no devices */
438 for (i = 0; i < 16; i++)
439 di->dev[i].addr = -1;
440
441 totaldevs = CountADBs();
442 for (i = 1; i <= totaldevs; i++) {
443 adbaddr = GetIndADB(&adbdata, i);
444 di->dev[adbaddr].addr = adbaddr;
445 di->dev[adbaddr].default_addr = adbdata.origADBAddr;
446 di->dev[adbaddr].handler_id = adbdata.devType;
447 }
448
449 /* Must call ADB Manager to get devices now */
450 break;
451 }
452
453 case ADBIOC_GETREPEAT:{
454 adb_rptinfo_t *ri;
455
456 ri = (void *) data;
457 ri->delay_ticks = adb_rptdelay;
458 ri->interval_ticks = adb_rptinterval;
459 break;
460 }
461
462 case ADBIOC_SETREPEAT:{
463 adb_rptinfo_t *ri;
464
465 ri = (void *) data;
466 adb_rptdelay = ri->delay_ticks;
467 adb_rptinterval = ri->interval_ticks;
468 break;
469 }
470
471 case ADBIOC_RESET:
472 adb_init();
473 break;
474
475 case ADBIOC_LISTENCMD:{
476 adb_listencmd_t *lc;
477
478 lc = (void *) data;
479 }
480
481 default:
482 return (EINVAL);
483 }
484 return (0);
485 }
486
487
488 int
489 adbselect(dev, rw, p)
490 dev_t dev;
491 int rw;
492 struct proc *p;
493 {
494 switch (rw) {
495 case FREAD:
496 /* succeed if there is something to read */
497 if (adb_evq_len > 0)
498 return (1);
499 selrecord(p, &adb_selinfo);
500 break;
501
502 case FWRITE:
503 return (1); /* always fails => never blocks */
504 break;
505 }
506
507 return (0);
508 }
509