1 /* $NetBSD: aed.c,v 1.24 2009/03/14 21:04:11 dsl Exp $ */
4 * Copyright (C) 1994 Bradley A. Grantham
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: aed.c,v 1.24 2009/03/14 21:04:11 dsl Exp $");
31 #include <sys/param.h>
32 #include <sys/device.h>
33 #include <sys/fcntl.h>
35 #include <sys/select.h>
37 #include <sys/signalvar.h>
38 #include <sys/systm.h>
41 #include <machine/autoconf.h>
42 #include <machine/cpu.h>
43 #include <machine/keyboard.h>
45 #include <macppc/dev/adbvar.h>
46 #include <macppc/dev/aedvar.h>
47 #include <macppc/dev/akbdvar.h>
49 #define spladb splhigh
52 * Function declarations.
54 static int aedmatch(struct device
*, struct cfdata
*, void *);
55 static void aedattach(struct device
*, struct device
*, void *);
56 static void aed_emulate_mouse(adb_event_t
*event
);
57 static void aed_kbdrpt(void *kstate
);
58 static void aed_dokeyupdown(adb_event_t
*event
);
59 static void aed_handoff(adb_event_t
*event
);
60 static void aed_enqevent(adb_event_t
*event
);
65 extern int adb_polling
; /* Are we polling? (Debugger mode) */
70 static struct aed_softc
*aed_sc
= NULL
;
71 static int aed_options
= 0; /* | AED_MSEMUL; */
73 /* Driver definition */
74 CFATTACH_DECL(aed
, sizeof(struct aed_softc
),
75 aedmatch
, aedattach
, NULL
, NULL
);
77 extern struct cfdriver aed_cd
;
79 dev_type_open(aedopen
);
80 dev_type_close(aedclose
);
81 dev_type_read(aedread
);
82 dev_type_ioctl(aedioctl
);
83 dev_type_poll(aedpoll
);
84 dev_type_kqfilter(aedkqfilter
);
86 const struct cdevsw aed_cdevsw
= {
87 aedopen
, aedclose
, aedread
, nullwrite
, aedioctl
,
88 nostop
, notty
, aedpoll
, nommap
, aedkqfilter
,
92 aedmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
)
94 struct adb_attach_args
*aa_args
= (struct adb_attach_args
*)aux
;
95 static int aed_matched
= 0;
97 /* Allow only one instance. */
98 if ((aa_args
->origaddr
== 0) && (!aed_matched
)) {
106 aedattach(struct device
*parent
, struct device
*self
, void *aux
)
108 struct adb_attach_args
*aa_args
= (struct adb_attach_args
*)aux
;
109 struct aed_softc
*sc
= (struct aed_softc
*)self
;
111 callout_init(&sc
->sc_repeat_ch
, 0);
112 selinit(&sc
->sc_selinfo
);
114 sc
->origaddr
= aa_args
->origaddr
;
115 sc
->adbaddr
= aa_args
->adbaddr
;
116 sc
->handler_id
= aa_args
->handler_id
;
121 sc
->sc_rptdelay
= 20;
122 sc
->sc_rptinterval
= 6;
123 sc
->sc_repeating
= -1; /* not repeating */
125 /* Pull in the options flags. */
126 sc
->sc_options
= (device_cfdata(&sc
->sc_dev
)->cf_flags
| aed_options
);
128 sc
->sc_ioproc
= NULL
;
136 printf("ADB Event device\n");
142 * Given a keyboard ADB event, record the keycode and call the key
143 * repeat handler, optionally passing the event through the mouse
144 * button emulation handler first. Pass mouse events directly to
145 * the handoff function.
148 aed_input(adb_event_t
*event
)
150 adb_event_t new_event
= *event
;
152 switch (event
->def_addr
) {
154 if (aed_sc
->sc_options
& AED_MSEMUL
)
155 aed_emulate_mouse(&new_event
);
157 aed_dokeyupdown(&new_event
);
160 new_event
.u
.m
.buttons
|= aed_sc
->sc_buttons
;
161 aed_handoff(&new_event
);
163 default: /* God only knows. */
165 panic("aed: received event from unsupported device!");
173 * Handles mouse button emulation via the keyboard. If the emulation
174 * modifier key is down, left and right arrows will generate 2nd and
175 * 3rd mouse button events while the 1, 2, and 3 keys will generate
176 * the corresponding mouse button event.
179 aed_emulate_mouse(adb_event_t
*event
)
181 static int emulmodkey_down
= 0;
182 adb_event_t new_event
;
184 if (event
->u
.k
.key
== ADBK_KEYDOWN(ADBK_OPTION
)) {
186 } else if (event
->u
.k
.key
== ADBK_KEYUP(ADBK_OPTION
)) {
189 if (aed_sc
->sc_buttons
& 0xfe) {
190 aed_sc
->sc_buttons
&= 1;
191 new_event
.def_addr
= ADBADDR_MS
;
192 new_event
.u
.m
.buttons
= aed_sc
->sc_buttons
;
193 new_event
.u
.m
.dx
= new_event
.u
.m
.dy
= 0;
194 microtime(&new_event
.timestamp
);
195 aed_handoff(&new_event
);
197 } else if (emulmodkey_down
) {
198 switch(event
->u
.k
.key
) {
200 case ADBK_KEYDOWN(ADBK_1
):
201 aed_sc
->sc_buttons
|= 1; /* left down */
202 new_event
.def_addr
= ADBADDR_MS
;
203 new_event
.u
.m
.buttons
= aed_sc
->sc_buttons
;
204 new_event
.u
.m
.dx
= new_event
.u
.m
.dy
= 0;
205 microtime(&new_event
.timestamp
);
206 aed_handoff(&new_event
);
208 case ADBK_KEYUP(ADBK_1
):
209 aed_sc
->sc_buttons
&= ~1; /* left up */
210 new_event
.def_addr
= ADBADDR_MS
;
211 new_event
.u
.m
.buttons
= aed_sc
->sc_buttons
;
212 new_event
.u
.m
.dx
= new_event
.u
.m
.dy
= 0;
213 microtime(&new_event
.timestamp
);
214 aed_handoff(&new_event
);
217 case ADBK_KEYDOWN(ADBK_LEFT
):
219 case ADBK_KEYDOWN(ADBK_2
):
221 aed_sc
->sc_buttons
|= 2; /* middle down */
222 new_event
.def_addr
= ADBADDR_MS
;
223 new_event
.u
.m
.buttons
= aed_sc
->sc_buttons
;
224 new_event
.u
.m
.dx
= new_event
.u
.m
.dy
= 0;
225 microtime(&new_event
.timestamp
);
226 aed_handoff(&new_event
);
228 case ADBK_KEYUP(ADBK_LEFT
):
230 case ADBK_KEYUP(ADBK_2
):
232 aed_sc
->sc_buttons
&= ~2; /* middle up */
233 new_event
.def_addr
= ADBADDR_MS
;
234 new_event
.u
.m
.buttons
= aed_sc
->sc_buttons
;
235 new_event
.u
.m
.dx
= new_event
.u
.m
.dy
= 0;
236 microtime(&new_event
.timestamp
);
237 aed_handoff(&new_event
);
239 case ADBK_KEYDOWN(ADBK_RIGHT
):
241 case ADBK_KEYDOWN(ADBK_3
):
243 aed_sc
->sc_buttons
|= 4; /* right down */
244 new_event
.def_addr
= ADBADDR_MS
;
245 new_event
.u
.m
.buttons
= aed_sc
->sc_buttons
;
246 new_event
.u
.m
.dx
= new_event
.u
.m
.dy
= 0;
247 microtime(&new_event
.timestamp
);
248 aed_handoff(&new_event
);
250 case ADBK_KEYUP(ADBK_RIGHT
):
252 case ADBK_KEYUP(ADBK_3
):
254 aed_sc
->sc_buttons
&= ~4; /* right up */
255 new_event
.def_addr
= ADBADDR_MS
;
256 new_event
.u
.m
.buttons
= aed_sc
->sc_buttons
;
257 new_event
.u
.m
.dx
= new_event
.u
.m
.dy
= 0;
258 microtime(&new_event
.timestamp
);
259 aed_handoff(&new_event
);
261 case ADBK_KEYUP(ADBK_SHIFT
):
262 case ADBK_KEYDOWN(ADBK_SHIFT
):
263 case ADBK_KEYUP(ADBK_CONTROL
):
264 case ADBK_KEYDOWN(ADBK_CONTROL
):
265 case ADBK_KEYUP(ADBK_FLOWER
):
266 case ADBK_KEYDOWN(ADBK_FLOWER
):
267 /* ctrl, shift, cmd */
268 aed_dokeyupdown(event
);
271 if (event
->u
.k
.key
& 0x80)
278 /* send option-down */
279 new_event
.u
.k
.key
= ADBK_KEYDOWN(ADBK_OPTION
);
280 new_event
.bytes
[0] = new_event
.u
.k
.key
;
281 microtime(&new_event
.timestamp
);
282 aed_dokeyupdown(&new_event
);
285 new_event
.u
.k
.key
= event
->bytes
[0];
286 new_event
.bytes
[0] = new_event
.u
.k
.key
;
287 microtime(&new_event
.timestamp
);
288 aed_dokeyupdown(&new_event
);
292 ADBK_KEYUP(ADBK_KEYVAL(event
->bytes
[0]));
293 microtime(&new_event
.timestamp
);
294 new_event
.bytes
[0] = new_event
.u
.k
.key
;
295 aed_dokeyupdown(&new_event
);
298 new_event
.u
.k
.key
= ADBK_KEYUP(ADBK_OPTION
);
299 new_event
.bytes
[0] = new_event
.u
.k
.key
;
300 microtime(&new_event
.timestamp
);
301 aed_dokeyupdown(&new_event
);
305 aed_dokeyupdown(event
);
310 * Keyboard autorepeat timeout function. Sends key up/down events
311 * for the repeating key and schedules the next call at sc_rptinterval
312 * ticks in the future.
315 aed_kbdrpt(void *kstate
)
317 struct aed_softc
*sc
= (struct aed_softc
*)kstate
;
319 sc
->sc_rptevent
.bytes
[0] |= 0x80;
320 microtime(&sc
->sc_rptevent
.timestamp
);
321 aed_handoff(&sc
->sc_rptevent
); /* do key up */
323 sc
->sc_rptevent
.bytes
[0] &= 0x7f;
324 microtime(&sc
->sc_rptevent
.timestamp
);
325 aed_handoff(&sc
->sc_rptevent
); /* do key down */
327 if (sc
->sc_repeating
== sc
->sc_rptevent
.u
.k
.key
) {
328 callout_reset(&sc
->sc_repeat_ch
, sc
->sc_rptinterval
,
335 * Cancels the currently repeating key event if there is one, schedules
336 * a new repeating key event if needed, and hands the event off to the
337 * appropriate subsystem.
340 aed_dokeyupdown(adb_event_t
*event
)
344 kbd_key
= ADBK_KEYVAL(event
->u
.k
.key
);
345 if (ADBK_PRESS(event
->u
.k
.key
) && keyboard
[kbd_key
][0] != 0) {
346 /* ignore shift & control */
347 if (aed_sc
->sc_repeating
!= -1) {
348 callout_stop(&aed_sc
->sc_repeat_ch
);
350 aed_sc
->sc_rptevent
= *event
;
351 aed_sc
->sc_repeating
= kbd_key
;
352 callout_reset(&aed_sc
->sc_repeat_ch
, aed_sc
->sc_rptdelay
,
353 aed_kbdrpt
, (void *)aed_sc
);
355 if (aed_sc
->sc_repeating
!= -1) {
356 aed_sc
->sc_repeating
= -1;
357 callout_stop(&aed_sc
->sc_repeat_ch
);
359 aed_sc
->sc_rptevent
= *event
;
365 * Place the event in the event queue if a requesting device is open
366 * and we are not polling.
369 aed_handoff(adb_event_t
*event
)
371 if (aed_sc
->sc_open
&& !adb_polling
)
376 * Place the event in the event queue and wakeup any waiting processes.
379 aed_enqevent(adb_event_t
*event
)
386 if (aed_sc
->sc_evq_tail
< 0 || aed_sc
->sc_evq_tail
>= AED_MAX_EVENTS
)
387 panic("adb: event queue tail is out of bounds");
389 if (aed_sc
->sc_evq_len
< 0 || aed_sc
->sc_evq_len
> AED_MAX_EVENTS
)
390 panic("adb: event queue len is out of bounds");
393 if (aed_sc
->sc_evq_len
== AED_MAX_EVENTS
) {
395 return; /* Oh, well... */
397 aed_sc
->sc_evq
[(aed_sc
->sc_evq_len
+ aed_sc
->sc_evq_tail
) %
398 AED_MAX_EVENTS
] = *event
;
399 aed_sc
->sc_evq_len
++;
401 selnotify(&aed_sc
->sc_selinfo
, 0, 0);
402 if (aed_sc
->sc_ioproc
)
403 psignal(aed_sc
->sc_ioproc
, SIGIO
);
409 aedopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
421 if (aed_sc
->sc_open
) {
425 aed_sc
->sc_evq_tail
= 0;
426 aed_sc
->sc_evq_len
= 0;
428 aed_sc
->sc_ioproc
= l
->l_proc
;
436 aedclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
441 aed_sc
->sc_ioproc
= NULL
;
449 aedread(dev_t dev
, struct uio
*uio
, int flag
)
457 if (uio
->uio_resid
< sizeof(adb_event_t
))
458 return (EMSGSIZE
); /* close enough. */
461 if (aed_sc
->sc_evq_len
== 0) {
465 willfit
= howmany(uio
->uio_resid
, sizeof(adb_event_t
));
466 total
= (aed_sc
->sc_evq_len
< willfit
) ? aed_sc
->sc_evq_len
: willfit
;
468 firstmove
= (aed_sc
->sc_evq_tail
+ total
> AED_MAX_EVENTS
)
469 ? (AED_MAX_EVENTS
- aed_sc
->sc_evq_tail
) : total
;
471 error
= uiomove((void *) & aed_sc
->sc_evq
[aed_sc
->sc_evq_tail
],
472 firstmove
* sizeof(adb_event_t
), uio
);
477 moremove
= total
- firstmove
;
480 error
= uiomove((void *) & aed_sc
->sc_evq
[0],
481 moremove
* sizeof(adb_event_t
), uio
);
487 aed_sc
->sc_evq_tail
= (aed_sc
->sc_evq_tail
+ total
) % AED_MAX_EVENTS
;
488 aed_sc
->sc_evq_len
-= total
;
494 aedioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
497 case ADBIOCDEVSINFO
: {
499 ADBDataBlock adbdata
;
506 /* Initialize to no devices */
507 for (i
= 0; i
< 16; i
++)
508 di
->dev
[i
].addr
= -1;
510 totaldevs
= CountADBs();
511 for (i
= 1; i
<= totaldevs
; i
++) {
512 adbaddr
= GetIndADB(&adbdata
, i
);
513 di
->dev
[adbaddr
].addr
= adbaddr
;
514 di
->dev
[adbaddr
].default_addr
= (int)(adbdata
.origADBAddr
);
515 di
->dev
[adbaddr
].handler_id
= (int)(adbdata
.devType
);
518 /* Must call ADB Manager to get devices now */
522 case ADBIOCGETREPEAT
:{
526 ri
->delay_ticks
= aed_sc
->sc_rptdelay
;
527 ri
->interval_ticks
= aed_sc
->sc_rptinterval
;
531 case ADBIOCSETREPEAT
:{
535 aed_sc
->sc_rptdelay
= ri
->delay_ticks
;
536 aed_sc
->sc_rptinterval
= ri
->interval_ticks
;
541 /* Do nothing for now */
544 case ADBIOCLISTENCMD
:{
558 aedpoll(dev_t dev
, int events
, struct lwp
*l
)
562 revents
= events
& (POLLOUT
| POLLWRNORM
);
564 if ((events
& (POLLIN
| POLLRDNORM
)) == 0)
568 if (aed_sc
->sc_evq_len
> 0)
569 revents
|= events
& (POLLIN
| POLLRDNORM
);
571 selrecord(l
, &aed_sc
->sc_selinfo
);
578 filt_aedrdetach(struct knote
*kn
)
583 SLIST_REMOVE(&aed_sc
->sc_selinfo
.sel_klist
, kn
, knote
, kn_selnext
);
588 filt_aedread(struct knote
*kn
, long hint
)
591 kn
->kn_data
= aed_sc
->sc_evq_len
* sizeof(adb_event_t
);
592 return (kn
->kn_data
> 0);
595 static const struct filterops aedread_filtops
=
596 { 1, NULL
, filt_aedrdetach
, filt_aedread
};
598 static const struct filterops aed_seltrue_filtops
=
599 { 1, NULL
, filt_aedrdetach
, filt_seltrue
};
602 aedkqfilter(dev_t dev
, struct knote
*kn
)
607 switch (kn
->kn_filter
) {
609 klist
= &aed_sc
->sc_selinfo
.sel_klist
;
610 kn
->kn_fop
= &aedread_filtops
;
614 klist
= &aed_sc
->sc_selinfo
.sel_klist
;
615 kn
->kn_fop
= &aed_seltrue_filtops
;
625 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);