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