xref: /netbsd-src/sys/arch/mac68k/dev/adb.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
1 /*	$NetBSD: adb.c,v 1.12 1996/10/13 03:21:13 christos 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/adbsys.h>
43 #include <machine/autoconf.h>
44 #include <machine/keyboard.h>
45 
46 #include "adbvar.h"
47 #include "itevar.h"
48 #include "../mac68k/macrom.h"
49 
50 /*
51  * Function declarations.
52  */
53 static int	adbmatch __P((struct device *, void *, void *));
54 static void	adbattach __P((struct device *, struct device *, void *));
55 
56 /*
57  * Global variables.
58  */
59 int     adb_polling = 0;	/* Are we polling?  (Debugger mode) */
60 
61 /*
62  * Local variables.
63  */
64 
65 /* External keyboard translation matrix */
66 extern unsigned char keyboard[128][3];
67 
68 /* Event queue definitions */
69 #if !defined(ADB_MAX_EVENTS)
70 #define ADB_MAX_EVENTS 200	/* Maximum events to be kept in queue */
71 				/* maybe should be higher for slower macs? */
72 #endif				/* !defined(ADB_MAX_EVENTS) */
73 static adb_event_t adb_evq[ADB_MAX_EVENTS];	/* ADB event queue */
74 static int adb_evq_tail = 0;	/* event queue tail */
75 static int adb_evq_len = 0;	/* event queue length */
76 
77 /* ADB device state information */
78 static int adb_isopen = 0;	/* Are we queuing events for adb_read? */
79 static struct selinfo adb_selinfo;	/* select() info */
80 static struct proc *adb_ioproc = NULL;	/* process to wakeup */
81 
82 /* Key repeat parameters */
83 static int adb_rptdelay = 20;	/* ticks before auto-repeat */
84 static int adb_rptinterval = 6;	/* ticks between auto-repeat */
85 static int adb_repeating = -1;	/* key that is auto-repeating */
86 static adb_event_t adb_rptevent;/* event to auto-repeat */
87 
88 /* Driver definition.  -- This should probably be a bus...  */
89 struct cfattach adb_ca = {
90 	sizeof(struct device), adbmatch, adbattach
91 };
92 
93 struct cfdriver adb_cd = {
94 	NULL, "adb", DV_DULL
95 };
96 
97 static int
98 adbmatch(pdp, match, auxp)
99 	struct device	*pdp;
100 	void	*match, *auxp;
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 		default:
337 			/* Classic Mouse Protocol (up to 2 buttons) */
338 			for (i = 0; i < 2; i++, button_bit <<= 1)
339 				/* 0 when button down */
340 				if (!(event->bytes[i] & 0x80))
341 					buttons |= button_bit;
342 				else
343 					buttons &= ~button_bit;
344 			/* Extended Protocol (up to 6 more buttons) */
345 			for (mask = 0x80; i < max_byte;
346 			     i += (mask == 0x80), button_bit <<= 1) {
347 				/* 0 when button down */
348 				if (!(event->bytes[i] & mask))
349 					buttons |= button_bit;
350 				else
351 					buttons &= ~button_bit;
352 				mask = ((mask >> 4) & 0xf)
353 					| ((mask & 0xf) << 4);
354 			}
355 			break;
356 		}
357 		new_event.u.m.buttons = adb_ms_buttons | buttons;
358 		new_event.u.m.dx = ((signed int) (event->bytes[1] & 0x3f)) -
359 					((event->bytes[1] & 0x40) ? 64 : 0);
360 		new_event.u.m.dy = ((signed int) (event->bytes[0] & 0x3f)) -
361 					((event->bytes[0] & 0x40) ? 64 : 0);
362 		adb_dokeyupdown(&new_event);
363 		break;
364 	default:		/* God only knows. */
365 		adb_dokeyupdown(event);
366 	}
367 }
368 
369 
370 int
371 adbopen(dev, flag, mode, p)
372     dev_t dev;
373     int flag, mode;
374     struct proc *p;
375 {
376 	register int unit;
377 	int error = 0;
378 	int s;
379 
380 	unit = minor(dev);
381 	if (unit != 0)
382 		return (ENXIO);
383 
384 	s = spladb();
385 	if (adb_isopen) {
386 		splx(s);
387 		return (EBUSY);
388 	}
389 	adb_evq_tail = 0;
390 	adb_evq_len = 0;
391 	adb_isopen = 1;
392 	adb_ioproc = p;
393 	splx(s);
394 
395 	return (error);
396 }
397 
398 
399 int
400 adbclose(dev, flag, mode, p)
401     dev_t dev;
402     int flag, mode;
403     struct proc *p;
404 {
405 	int s = spladb();
406 
407 	adb_isopen = 0;
408 	adb_ioproc = NULL;
409 	splx(s);
410 
411 	return (0);
412 }
413 
414 
415 int
416 adbread(dev, uio, flag)
417     dev_t dev;
418     struct uio *uio;
419     int flag;
420 {
421 	int s, error;
422 	int willfit;
423 	int total;
424 	int firstmove;
425 	int moremove;
426 
427 	if (uio->uio_resid < sizeof(adb_event_t))
428 		return (EMSGSIZE);	/* close enough. */
429 
430 	s = spladb();
431 	if (adb_evq_len == 0) {
432 		splx(s);
433 		return (0);
434 	}
435 	willfit = howmany(uio->uio_resid, sizeof(adb_event_t));
436 	total = (adb_evq_len < willfit) ? adb_evq_len : willfit;
437 
438 	firstmove = (adb_evq_tail + total > ADB_MAX_EVENTS)
439 	    ? (ADB_MAX_EVENTS - adb_evq_tail) : total;
440 
441 	error = uiomove((caddr_t) & adb_evq[adb_evq_tail],
442 	    firstmove * sizeof(adb_event_t), uio);
443 	if (error) {
444 		splx(s);
445 		return (error);
446 	}
447 	moremove = total - firstmove;
448 
449 	if (moremove > 0) {
450 		error = uiomove((caddr_t) & adb_evq[0],
451 		    moremove * sizeof(adb_event_t), uio);
452 		if (error) {
453 			splx(s);
454 			return (error);
455 		}
456 	}
457 	adb_evq_tail = (adb_evq_tail + total) % ADB_MAX_EVENTS;
458 	adb_evq_len -= total;
459 	splx(s);
460 	return (0);
461 }
462 
463 
464 int
465 adbwrite(dev, uio, flag)
466     dev_t dev;
467     struct uio *uio;
468     int flag;
469 {
470 	return 0;
471 }
472 
473 
474 int
475 adbioctl(dev, cmd, data, flag, p)
476     dev_t dev;
477     int cmd;
478     caddr_t data;
479     int flag;
480     struct proc *p;
481 {
482 	switch (cmd) {
483 	case ADBIOC_DEVSINFO: {
484 		adb_devinfo_t *di;
485 		ADBDataBlock adbdata;
486 		int totaldevs;
487 		int adbaddr;
488 		int i;
489 
490 		di = (void *) data;
491 
492 		/* Initialize to no devices */
493 		for (i = 0; i < 16; i++)
494 			di->dev[i].addr = -1;
495 
496 		totaldevs = CountADBs();
497 		for (i = 1; i <= totaldevs; i++) {
498 			adbaddr = GetIndADB(&adbdata, i);
499 			di->dev[adbaddr].addr = adbaddr;
500 			di->dev[adbaddr].default_addr = adbdata.origADBAddr;
501 			di->dev[adbaddr].handler_id = adbdata.devType;
502 			}
503 
504 		/* Must call ADB Manager to get devices now */
505 		break;
506 	}
507 
508 	case ADBIOC_GETREPEAT:{
509 		adb_rptinfo_t *ri;
510 
511 		ri = (void *) data;
512 		ri->delay_ticks = adb_rptdelay;
513 		ri->interval_ticks = adb_rptinterval;
514 		break;
515 	}
516 
517 	case ADBIOC_SETREPEAT:{
518 		adb_rptinfo_t *ri;
519 
520 		ri = (void *) data;
521 		adb_rptdelay = ri->delay_ticks;
522 		adb_rptinterval = ri->interval_ticks;
523 		break;
524 	}
525 
526 	case ADBIOC_RESET:
527 		adb_init();
528 		break;
529 
530 	case ADBIOC_LISTENCMD:{
531 		adb_listencmd_t *lc;
532 
533 		lc = (void *) data;
534 	}
535 
536 	default:
537 		return (EINVAL);
538 	}
539 	return (0);
540 }
541 
542 
543 int
544 adbpoll(dev, events, p)
545 	dev_t dev;
546 	int events;
547 	struct proc *p;
548 {
549 	int s, revents;
550 
551 	revents = events & (POLLOUT | POLLWRNORM);
552 
553 	if ((events & (POLLIN | POLLRDNORM)) == 0)
554 		return (revents);
555 
556 	s = spladb();
557 	if (adb_evq_len > 0)
558 		revents |= events & (POLLIN | POLLRDNORM);
559 	else
560 		selrecord(p, &adb_selinfo);
561 	splx(s);
562 
563 	return (revents);
564 }
565