xref: /netbsd-src/sys/arch/mac68k/dev/adb.c (revision 07bae7edddbb1ce4c926b2e8db425804589074c9)
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