1 /* $NetBSD: wskbd.c,v 1.122 2009/01/15 04:22:11 yamt Exp $ */
4 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christopher G. Demetriou
17 * for the NetBSD Project.
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
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 OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1998 The NetBSD Foundation, Inc.
35 * All rights reserved.
37 * Keysym translator contributed to The NetBSD Foundation by
38 * Juergen Hannken-Illjes.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
49 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
50 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
53 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 * POSSIBILITY OF SUCH DAMAGE.
63 * Copyright (c) 1992, 1993
64 * The Regents of the University of California. All rights reserved.
66 * This software was developed by the Computer Systems Engineering group
67 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
68 * contributed to Berkeley.
70 * All advertising materials mentioning features or use of this software
71 * must display the following acknowledgement:
72 * This product includes software developed by the University of
73 * California, Lawrence Berkeley Laboratory.
75 * Redistribution and use in source and binary forms, with or without
76 * modification, are permitted provided that the following conditions
78 * 1. Redistributions of source code must retain the above copyright
79 * notice, this list of conditions and the following disclaimer.
80 * 2. Redistributions in binary form must reproduce the above copyright
81 * notice, this list of conditions and the following disclaimer in the
82 * documentation and/or other materials provided with the distribution.
83 * 3. Neither the name of the University nor the names of its contributors
84 * may be used to endorse or promote products derived from this software
85 * without specific prior written permission.
87 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
88 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
89 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
90 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
91 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
92 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
93 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
94 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
95 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
96 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
99 * @(#)kbd.c 8.2 (Berkeley) 10/30/93
103 * Keyboard driver (/dev/wskbd*). Translates incoming bytes to ASCII or
104 * to `wscons_events' and passes them up to the appropriate reader.
107 #include <sys/cdefs.h>
108 __KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.122 2009/01/15 04:22:11 yamt Exp $");
111 #include "opt_kgdb.h"
112 #include "opt_wsdisplay_compat.h"
114 #include "wsdisplay.h"
118 #include <sys/param.h>
119 #include <sys/conf.h>
120 #include <sys/device.h>
121 #include <sys/ioctl.h>
122 #include <sys/poll.h>
123 #include <sys/kernel.h>
124 #include <sys/proc.h>
125 #include <sys/syslog.h>
126 #include <sys/systm.h>
127 #include <sys/callout.h>
128 #include <sys/malloc.h>
130 #include <sys/signalvar.h>
131 #include <sys/errno.h>
132 #include <sys/fcntl.h>
133 #include <sys/vnode.h>
134 #include <sys/kauth.h>
136 #include <dev/wscons/wsconsio.h>
137 #include <dev/wscons/wskbdvar.h>
138 #include <dev/wscons/wsksymdef.h>
139 #include <dev/wscons/wsksymvar.h>
140 #include <dev/wscons/wsdisplayvar.h>
141 #include <dev/wscons/wseventvar.h>
142 #include <dev/wscons/wscons_callbacks.h>
145 #include <sys/kgdb.h>
149 #define DPRINTF(x) if (wskbddebug) printf x
155 #include <dev/wscons/wsmuxvar.h>
157 struct wskbd_internal
{
158 const struct wskbd_mapdata
*t_keymap
;
160 const struct wskbd_consops
*t_consops
;
161 void *t_consaccesscookie
;
164 int t_composelen
; /* remaining entries in t_composebuf */
165 keysym_t t_composebuf
[2];
168 #define WSKFL_METAESC 1
170 #define MAXKEYSYMSPERKEY 2 /* ESC <key> at max */
171 keysym_t t_symbols
[MAXKEYSYMSPERKEY
];
173 struct wskbd_softc
*t_sc
; /* back pointer */
177 struct wsevsrc sc_base
;
179 struct wskbd_internal
*id
;
181 const struct wskbd_accessops
*sc_accessops
;
182 void *sc_accesscookie
;
188 struct wskbd_bell_data sc_bell_data
;
189 struct wskbd_keyrepeat_data sc_keyrepeat_data
;
190 #ifdef WSDISPLAY_SCROLLSUPPORT
191 struct wskbd_scroll_data sc_scroll_data
;
194 int sc_repeating
; /* we've called timeout() */
195 callout_t sc_repeat_ch
;
196 u_int sc_repeat_type
;
199 int sc_translating
; /* xlate to chars for emulation */
201 int sc_maplen
; /* number of entries in sc_map */
202 struct wscons_keymap
*sc_map
; /* current translation map */
203 kbd_t sc_layout
; /* current layout */
206 u_char sc_dying
; /* device is being detached */
208 wskbd_hotkey_plugin
*sc_hotkey
;
209 void *sc_hotkeycookie
;
212 #define MOD_SHIFT_L (1 << 0)
213 #define MOD_SHIFT_R (1 << 1)
214 #define MOD_SHIFTLOCK (1 << 2)
215 #define MOD_CAPSLOCK (1 << 3)
216 #define MOD_CONTROL_L (1 << 4)
217 #define MOD_CONTROL_R (1 << 5)
218 #define MOD_META_L (1 << 6)
219 #define MOD_META_R (1 << 7)
220 #define MOD_MODESHIFT (1 << 8)
221 #define MOD_NUMLOCK (1 << 9)
222 #define MOD_COMPOSE (1 << 10)
223 #define MOD_HOLDSCREEN (1 << 11)
224 #define MOD_COMMAND (1 << 12)
225 #define MOD_COMMAND1 (1 << 13)
226 #define MOD_COMMAND2 (1 << 14)
228 #define MOD_ANYSHIFT (MOD_SHIFT_L | MOD_SHIFT_R | MOD_SHIFTLOCK)
229 #define MOD_ANYCONTROL (MOD_CONTROL_L | MOD_CONTROL_R)
230 #define MOD_ANYMETA (MOD_META_L | MOD_META_R)
232 #define MOD_ONESET(id, mask) (((id)->t_modifiers & (mask)) != 0)
233 #define MOD_ALLSET(id, mask) (((id)->t_modifiers & (mask)) == (mask))
235 #define GETMODSTATE(src, dst) \
237 dst |= (src & MOD_SHIFT_L) ? MOD_SHIFT_L : 0; \
238 dst |= (src & MOD_SHIFT_R) ? MOD_SHIFT_R : 0; \
239 dst |= (src & MOD_CONTROL_L) ? MOD_CONTROL_L : 0; \
240 dst |= (src & MOD_CONTROL_R) ? MOD_CONTROL_R : 0; \
241 dst |= (src & MOD_META_L) ? MOD_META_L : 0; \
242 dst |= (src & MOD_META_R) ? MOD_META_R : 0; \
245 static int wskbd_match(device_t
, cfdata_t
, void *);
246 static void wskbd_attach(device_t
, device_t
, void *);
247 static int wskbd_detach(device_t
, int);
248 static int wskbd_activate(device_t
, enum devact
);
250 static int wskbd_displayioctl(device_t
, u_long
, void *, int,
253 static int wskbd_set_display(device_t
, struct wsevsrc
*);
255 #define wskbd_set_display NULL
258 static inline void update_leds(struct wskbd_internal
*);
259 static inline void update_modifier(struct wskbd_internal
*, u_int
, int, int);
260 static int internal_command(struct wskbd_softc
*, u_int
*, keysym_t
, keysym_t
);
261 static int wskbd_translate(struct wskbd_internal
*, u_int
, int);
262 static int wskbd_enable(struct wskbd_softc
*, int);
264 static void change_displayparam(struct wskbd_softc
*, int, int, int);
265 static void wskbd_holdscreen(struct wskbd_softc
*, int);
268 static int wskbd_do_ioctl_sc(struct wskbd_softc
*, u_long
, void *, int,
270 static void wskbd_deliver_event(struct wskbd_softc
*sc
, u_int type
, int value
);
273 static int wskbd_mux_open(struct wsevsrc
*, struct wseventvar
*);
274 static int wskbd_mux_close(struct wsevsrc
*);
276 #define wskbd_mux_open NULL
277 #define wskbd_mux_close NULL
280 static int wskbd_do_open(struct wskbd_softc
*, struct wseventvar
*);
281 static int wskbd_do_ioctl(device_t
, u_long
, void *, int, struct lwp
*);
283 CFATTACH_DECL_NEW(wskbd
, sizeof (struct wskbd_softc
),
284 wskbd_match
, wskbd_attach
, wskbd_detach
, wskbd_activate
);
286 extern struct cfdriver wskbd_cd
;
288 dev_type_open(wskbdopen
);
289 dev_type_close(wskbdclose
);
290 dev_type_read(wskbdread
);
291 dev_type_ioctl(wskbdioctl
);
292 dev_type_poll(wskbdpoll
);
293 dev_type_kqfilter(wskbdkqfilter
);
295 const struct cdevsw wskbd_cdevsw
= {
296 wskbdopen
, wskbdclose
, wskbdread
, nowrite
, wskbdioctl
,
297 nostop
, notty
, wskbdpoll
, nommap
, wskbdkqfilter
, D_OTHER
300 #ifndef WSKBD_DEFAULT_BELL_PITCH
301 #define WSKBD_DEFAULT_BELL_PITCH 1500 /* 1500Hz */
303 #ifndef WSKBD_DEFAULT_BELL_PERIOD
304 #define WSKBD_DEFAULT_BELL_PERIOD 100 /* 100ms */
306 #ifndef WSKBD_DEFAULT_BELL_VOLUME
307 #define WSKBD_DEFAULT_BELL_VOLUME 50 /* 50% volume */
310 struct wskbd_bell_data wskbd_default_bell_data
= {
312 WSKBD_DEFAULT_BELL_PITCH
,
313 WSKBD_DEFAULT_BELL_PERIOD
,
314 WSKBD_DEFAULT_BELL_VOLUME
,
317 #ifdef WSDISPLAY_SCROLLSUPPORT
318 struct wskbd_scroll_data wskbd_default_scroll_data
= {
320 WSKBD_SCROLL_MODE_NORMAL
,
321 #ifdef WSDISPLAY_SCROLLCOMBO
322 WSDISPLAY_SCROLLCOMBO
,
329 #ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1
330 #define WSKBD_DEFAULT_KEYREPEAT_DEL1 400 /* 400ms to start repeating */
332 #ifndef WSKBD_DEFAULT_KEYREPEAT_DELN
333 #define WSKBD_DEFAULT_KEYREPEAT_DELN 100 /* 100ms to between repeats */
336 struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data
= {
337 WSKBD_KEYREPEAT_DOALL
,
338 WSKBD_DEFAULT_KEYREPEAT_DEL1
,
339 WSKBD_DEFAULT_KEYREPEAT_DELN
,
342 #if NWSDISPLAY > 0 || NWSMUX > 0
343 struct wssrcops wskbd_srcops
= {
345 wskbd_mux_open
, wskbd_mux_close
, wskbd_do_ioctl
,
346 wskbd_displayioctl
, wskbd_set_display
350 static bool wskbd_suspend(device_t dv
, pmf_qual_t
);
351 static void wskbd_repeat(void *v
);
353 static int wskbd_console_initted
;
354 static struct wskbd_softc
*wskbd_console_device
;
355 static struct wskbd_internal wskbd_console_data
;
357 static void wskbd_update_layout(struct wskbd_internal
*, kbd_t
);
360 wskbd_update_layout(struct wskbd_internal
*id
, kbd_t enc
)
363 if (enc
& KB_METAESC
)
364 id
->t_flags
|= WSKFL_METAESC
;
366 id
->t_flags
&= ~WSKFL_METAESC
;
370 * Print function (for parent devices).
373 wskbddevprint(void *aux
, const char *pnp
)
376 struct wskbddev_attach_args
*ap
= aux
;
380 aprint_normal("wskbd at %s", pnp
);
382 aprint_normal(" console %d", ap
->console
);
389 wskbd_match(device_t parent
, cfdata_t match
, void *aux
)
391 struct wskbddev_attach_args
*ap
= aux
;
393 if (match
->wskbddevcf_console
!= WSKBDDEVCF_CONSOLE_UNK
) {
395 * If console-ness of device specified, either match
396 * exactly (at high priority), or fail.
398 if (match
->wskbddevcf_console
!= 0 && ap
->console
!= 0)
404 /* If console-ness unspecified, it wins. */
409 wskbd_attach(device_t parent
, device_t self
, void *aux
)
411 struct wskbd_softc
*sc
= device_private(self
);
412 struct wskbddev_attach_args
*ap
= aux
;
417 sc
->sc_base
.me_dv
= self
;
418 sc
->sc_isconsole
= ap
->console
;
419 sc
->sc_hotkey
= NULL
;
420 sc
->sc_hotkeycookie
= NULL
;
422 #if NWSMUX > 0 || NWSDISPLAY > 0
423 sc
->sc_base
.me_ops
= &wskbd_srcops
;
426 mux
= device_cfdata(sc
->sc_base
.me_dv
)->wskbddevcf_mux
;
428 /* Ignore mux for console; it always goes to the console mux. */
429 /* printf(" (mux %d ignored for console)", mux); */
433 aprint_normal(" mux %d", mux
);
435 if (device_cfdata(sc
->sc_base
.me_dv
)->wskbddevcf_mux
>= 0)
436 aprint_normal(" (mux ignored)");
440 sc
->id
= &wskbd_console_data
;
442 sc
->id
= malloc(sizeof(struct wskbd_internal
),
443 M_DEVBUF
, M_WAITOK
|M_ZERO
);
444 sc
->id
->t_keymap
= ap
->keymap
;
445 wskbd_update_layout(sc
->id
, ap
->keymap
->layout
);
448 callout_init(&sc
->sc_repeat_ch
, 0);
449 callout_setfunc(&sc
->sc_repeat_ch
, wskbd_repeat
, sc
);
453 sc
->sc_accessops
= ap
->accessops
;
454 sc
->sc_accesscookie
= ap
->accesscookie
;
455 sc
->sc_repeating
= 0;
456 sc
->sc_translating
= 1;
457 sc
->sc_ledstate
= -1; /* force update */
459 if (wskbd_load_keymap(sc
->id
->t_keymap
,
460 &sc
->sc_map
, &sc
->sc_maplen
) != 0)
461 panic("cannot load keymap");
463 sc
->sc_layout
= sc
->id
->t_keymap
->layout
;
465 /* set default bell and key repeat data */
466 sc
->sc_bell_data
= wskbd_default_bell_data
;
467 sc
->sc_keyrepeat_data
= wskbd_default_keyrepeat_data
;
469 #ifdef WSDISPLAY_SCROLLSUPPORT
470 sc
->sc_scroll_data
= wskbd_default_scroll_data
;
474 KASSERT(wskbd_console_initted
);
475 KASSERT(wskbd_console_device
== NULL
);
477 wskbd_console_device
= sc
;
479 aprint_naive(": console keyboard");
480 aprint_normal(": console keyboard");
483 wsdisplay_set_console_kbd(&sc
->sc_base
); /* sets me_dispv */
484 if (sc
->sc_base
.me_dispdv
!= NULL
)
485 aprint_normal(", using %s",
486 device_xname(sc
->sc_base
.me_dispdv
));
494 error
= wsmux_attach_sc(wsmux_getmux(mux
), &sc
->sc_base
);
496 aprint_error_dev(sc
->sc_base
.me_dv
,
497 "attach error=%d\n", error
);
501 if (!pmf_device_register(self
, wskbd_suspend
, NULL
))
502 aprint_error_dev(self
, "couldn't establish power handler\n");
503 else if (!pmf_class_input_register(self
))
504 aprint_error_dev(self
, "couldn't register as input device\n");
508 wskbd_suspend(device_t dv
, pmf_qual_t qual
)
510 struct wskbd_softc
*sc
= device_private(dv
);
512 sc
->sc_repeating
= 0;
513 callout_stop(&sc
->sc_repeat_ch
);
519 wskbd_cnattach(const struct wskbd_consops
*consops
, void *conscookie
,
520 const struct wskbd_mapdata
*mapdata
)
522 KASSERT(!wskbd_console_initted
);
524 wskbd_console_data
.t_keymap
= mapdata
;
525 wskbd_update_layout(&wskbd_console_data
, mapdata
->layout
);
527 wskbd_console_data
.t_consops
= consops
;
528 wskbd_console_data
.t_consaccesscookie
= conscookie
;
531 wsdisplay_set_cons_kbd(wskbd_cngetc
, wskbd_cnpollc
, wskbd_cnbell
);
534 wskbd_console_initted
= 1;
540 KASSERT(wskbd_console_initted
);
542 wskbd_console_data
.t_keymap
= 0;
544 wskbd_console_data
.t_consops
= 0;
545 wskbd_console_data
.t_consaccesscookie
= 0;
548 wsdisplay_unset_cons_kbd();
551 wskbd_console_initted
= 0;
555 wskbd_repeat(void *v
)
557 struct wskbd_softc
*sc
= (struct wskbd_softc
*)v
;
560 if (!sc
->sc_repeating
) {
562 * race condition: a "key up" event came in when wskbd_repeat()
563 * was already called but not yet spltty()'d
568 if (sc
->sc_translating
) {
571 if (sc
->sc_base
.me_dispdv
!= NULL
) {
573 for (i
= 0; i
< sc
->sc_repeating
; i
++)
574 wsdisplay_kbdinput(sc
->sc_base
.me_dispdv
,
575 sc
->id
->t_symbols
[i
]);
579 #if defined(WSKBD_EVENT_AUTOREPEAT)
581 wskbd_deliver_event(sc
, sc
->sc_repeat_type
,
582 sc
->sc_repeat_value
);
583 #endif /* defined(WSKBD_EVENT_AUTOREPEAT) */
585 callout_schedule(&sc
->sc_repeat_ch
, mstohz(sc
->sc_keyrepeat_data
.delN
));
590 wskbd_activate(device_t self
, enum devact act
)
592 struct wskbd_softc
*sc
= device_private(self
);
594 if (act
== DVACT_DEACTIVATE
)
600 * Detach a keyboard. To keep track of users of the softc we keep
601 * a reference count that's incremented while inside, e.g., read.
602 * If the keyboard is active and the reference count is > 0 (0 is the
603 * normal state) we post an event and then wait for the process
604 * that had the reference to wake us up again. Then we blow away the
605 * vnode and return (which will deallocate the softc).
608 wskbd_detach(device_t self
, int flags
)
610 struct wskbd_softc
*sc
= device_private(self
);
611 struct wseventvar
*evar
;
616 /* Tell parent mux we're leaving. */
617 if (sc
->sc_base
.me_parent
!= NULL
)
618 wsmux_detach_sc(&sc
->sc_base
);
621 callout_stop(&sc
->sc_repeat_ch
);
622 callout_destroy(&sc
->sc_repeat_ch
);
624 if (sc
->sc_isconsole
) {
625 KASSERT(wskbd_console_device
== sc
);
626 wskbd_console_device
= NULL
;
629 pmf_device_deregister(self
);
631 evar
= sc
->sc_base
.me_evp
;
632 if (evar
!= NULL
&& evar
->io
!= NULL
) {
634 if (--sc
->sc_refcnt
>= 0) {
635 struct wscons_event event
;
637 /* Wake everyone by generating a dummy event. */
640 if (wsevent_inject(evar
, &event
, 1) != 0)
641 wsevent_wakeup(evar
);
643 /* Wait for processes to go away. */
644 if (tsleep(sc
, PZERO
, "wskdet", hz
* 60))
645 aprint_error("wskbd_detach: %s didn't detach\n",
651 /* locate the major number */
652 maj
= cdevsw_lookup_major(&wskbd_cdevsw
);
654 /* Nuke the vnodes for any open instances. */
655 mn
= device_unit(self
);
656 vdevgone(maj
, mn
, mn
, VCHR
);
662 wskbd_input(device_t dev
, u_int type
, int value
)
664 struct wskbd_softc
*sc
= device_private(dev
);
669 if (sc
->sc_repeating
) {
670 sc
->sc_repeating
= 0;
671 callout_stop(&sc
->sc_repeat_ch
);
674 device_active(dev
, DVA_HARDWARE
);
678 * If /dev/wskbdN is not connected in event mode translate and
681 if (sc
->sc_translating
) {
682 num
= wskbd_translate(sc
->id
, type
, value
);
684 if (sc
->sc_base
.me_dispdv
!= NULL
) {
685 #ifdef WSDISPLAY_SCROLLSUPPORT
686 if (sc
->id
->t_symbols
[0] != KS_Print_Screen
) {
687 wsdisplay_scroll(sc
->sc_base
.
688 me_dispdv
, WSDISPLAY_SCROLL_RESET
);
691 for (i
= 0; i
< num
; i
++)
693 sc
->sc_base
.me_dispdv
,
694 sc
->id
->t_symbols
[i
]);
697 if (sc
->sc_keyrepeat_data
.del1
!= 0) {
698 sc
->sc_repeating
= num
;
699 callout_schedule(&sc
->sc_repeat_ch
,
700 mstohz(sc
->sc_keyrepeat_data
.del1
));
707 wskbd_deliver_event(sc
, type
, value
);
709 #if defined(WSKBD_EVENT_AUTOREPEAT)
710 /* Repeat key presses if set. */
711 if (type
== WSCONS_EVENT_KEY_DOWN
&& sc
->sc_keyrepeat_data
.del1
!= 0) {
712 sc
->sc_repeat_type
= type
;
713 sc
->sc_repeat_value
= value
;
714 sc
->sc_repeating
= 1;
715 callout_schedule(&sc
->sc_repeat_ch
,
716 mstohz(sc
->sc_keyrepeat_data
.del1
));
718 #endif /* defined(WSKBD_EVENT_AUTOREPEAT) */
722 * Keyboard is generating events. Turn this keystroke into an
723 * event and put it in the queue. If the queue is full, the
724 * keystroke is lost (sorry!).
727 wskbd_deliver_event(struct wskbd_softc
*sc
, u_int type
, int value
)
729 struct wseventvar
*evar
;
730 struct wscons_event event
;
732 evar
= sc
->sc_base
.me_evp
;
735 DPRINTF(("wskbd_input: not open\n"));
740 if (evar
->q
== NULL
) {
741 printf("wskbd_input: evar->q=NULL\n");
748 if (wsevent_inject(evar
, &event
, 1) != 0)
749 log(LOG_WARNING
, "%s: event queue overflow\n",
750 device_xname(sc
->sc_base
.me_dv
));
753 #ifdef WSDISPLAY_COMPAT_RAWKBD
755 wskbd_rawinput(device_t dev
, u_char
*tbuf
, int len
)
758 struct wskbd_softc
*sc
= device_private(dev
);
761 if (sc
->sc_base
.me_dispdv
!= NULL
)
762 for (i
= 0; i
< len
; i
++)
763 wsdisplay_kbdinput(sc
->sc_base
.me_dispdv
, tbuf
[i
]);
764 /* this is KS_GROUP_Ascii */
767 #endif /* WSDISPLAY_COMPAT_RAWKBD */
771 wskbd_holdscreen(struct wskbd_softc
*sc
, int hold
)
775 if (sc
->sc_base
.me_dispdv
!= NULL
) {
776 wsdisplay_kbdholdscreen(sc
->sc_base
.me_dispdv
, hold
);
777 new_state
= sc
->sc_ledstate
;
779 #ifdef WSDISPLAY_SCROLLSUPPORT
780 sc
->sc_scroll_data
.mode
= WSKBD_SCROLL_MODE_HOLD
;
782 new_state
|= WSKBD_LED_SCROLL
;
784 #ifdef WSDISPLAY_SCROLLSUPPORT
785 sc
->sc_scroll_data
.mode
= WSKBD_SCROLL_MODE_NORMAL
;
787 new_state
&= ~WSKBD_LED_SCROLL
;
789 if (new_state
!= sc
->sc_ledstate
) {
790 (*sc
->sc_accessops
->set_leds
)(sc
->sc_accesscookie
,
792 sc
->sc_ledstate
= new_state
;
793 #ifdef WSDISPLAY_SCROLLSUPPORT
795 wsdisplay_scroll(sc
->sc_base
.me_dispdv
,
796 WSDISPLAY_SCROLL_RESET
);
804 wskbd_enable(struct wskbd_softc
*sc
, int on
)
809 /* I don't understand the purpose of this code. And it seems to
810 * break things, so it's out. -- Lennart
812 if (!on
&& (!sc
->sc_translating
814 || sc
->sc_base
.me_dispdv
820 if (sc
->sc_base
.me_dispdv
!= NULL
)
824 /* Always cancel auto repeat when fiddling with the kbd. */
825 if (sc
->sc_repeating
) {
826 sc
->sc_repeating
= 0;
827 callout_stop(&sc
->sc_repeat_ch
);
830 error
= (*sc
->sc_accessops
->enable
)(sc
->sc_accesscookie
, on
);
831 DPRINTF(("wskbd_enable: sc=%p on=%d res=%d\n", sc
, on
, error
));
837 wskbd_mux_open(struct wsevsrc
*me
, struct wseventvar
*evp
)
839 struct wskbd_softc
*sc
= (struct wskbd_softc
*)me
;
844 if (sc
->sc_base
.me_evp
!= NULL
)
847 return (wskbd_do_open(sc
, evp
));
852 wskbdopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
854 struct wskbd_softc
*sc
= device_lookup_private(&wskbd_cd
, minor(dev
));
855 struct wseventvar
*evar
;
862 DPRINTF(("wskbdopen: %s mux=%p l=%p\n",
863 device_xname(sc
->sc_base
.me_dv
), sc
->sc_base
.me_parent
, l
));
869 if ((flags
& (FREAD
| FWRITE
)) == FWRITE
)
870 /* Not opening for read, only ioctl is available. */
874 if (sc
->sc_base
.me_parent
!= NULL
) {
875 /* Grab the keyboard out of the greedy hands of the mux. */
876 DPRINTF(("wskbdopen: detach\n"));
877 wsmux_detach_sc(&sc
->sc_base
);
881 if (sc
->sc_base
.me_evp
!= NULL
)
884 evar
= &sc
->sc_base
.me_evar
;
885 wsevent_init(evar
, l
->l_proc
);
887 error
= wskbd_do_open(sc
, evar
);
889 DPRINTF(("wskbdopen: %s open failed\n",
890 device_xname(sc
->sc_base
.me_dv
)));
891 sc
->sc_base
.me_evp
= NULL
;
898 wskbd_do_open(struct wskbd_softc
*sc
, struct wseventvar
*evp
)
900 sc
->sc_base
.me_evp
= evp
;
901 sc
->sc_translating
= 0;
903 return (wskbd_enable(sc
, 1));
907 wskbdclose(dev_t dev
, int flags
, int mode
,
910 struct wskbd_softc
*sc
=
911 device_lookup_private(&wskbd_cd
, minor(dev
));
912 struct wseventvar
*evar
= sc
->sc_base
.me_evp
;
915 /* not open for read */
918 sc
->sc_base
.me_evp
= NULL
;
919 sc
->sc_translating
= 1;
920 (void)wskbd_enable(sc
, 0);
928 wskbd_mux_close(struct wsevsrc
*me
)
930 struct wskbd_softc
*sc
= (struct wskbd_softc
*)me
;
932 sc
->sc_base
.me_evp
= NULL
;
933 sc
->sc_translating
= 1;
934 (void)wskbd_enable(sc
, 0);
941 wskbdread(dev_t dev
, struct uio
*uio
, int flags
)
943 struct wskbd_softc
*sc
=
944 device_lookup_private(&wskbd_cd
, minor(dev
));
951 if (sc
->sc_base
.me_evp
== NULL
) {
952 printf("wskbdread: evp == NULL\n");
958 error
= wsevent_read(sc
->sc_base
.me_evp
, uio
, flags
);
959 if (--sc
->sc_refcnt
< 0) {
967 wskbdioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
969 return (wskbd_do_ioctl(device_lookup(&wskbd_cd
, minor(dev
)),
973 /* A wrapper around the ioctl() workhorse to make reference counting easy. */
975 wskbd_do_ioctl(device_t dv
, u_long cmd
, void *data
, int flag
,
978 struct wskbd_softc
*sc
= device_private(dv
);
982 error
= wskbd_do_ioctl_sc(sc
, cmd
, data
, flag
, l
);
983 if (--sc
->sc_refcnt
< 0)
989 wskbd_do_ioctl_sc(struct wskbd_softc
*sc
, u_long cmd
, void *data
, int flag
,
994 * Try the generic ioctls that the wskbd interface supports.
997 case FIONBIO
: /* we will remove this someday (soon???) */
1001 if (sc
->sc_base
.me_evp
== NULL
)
1003 sc
->sc_base
.me_evp
->async
= *(int *)data
!= 0;
1007 if (sc
->sc_base
.me_evp
== NULL
)
1009 if (-*(int *)data
!= sc
->sc_base
.me_evp
->io
->p_pgid
1010 && *(int *)data
!= sc
->sc_base
.me_evp
->io
->p_pid
)
1015 if (sc
->sc_base
.me_evp
== NULL
)
1017 if (*(int *)data
!= sc
->sc_base
.me_evp
->io
->p_pgid
)
1023 * Try the keyboard driver for WSKBDIO ioctls. It returns EPASSTHROUGH
1024 * if it didn't recognize the request.
1026 return (wskbd_displayioctl(sc
->sc_base
.me_dv
, cmd
, data
, flag
, l
));
1030 * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode.
1031 * Some of these have no real effect in raw mode, however.
1034 wskbd_displayioctl(device_t dev
, u_long cmd
, void *data
, int flag
,
1037 #ifdef WSDISPLAY_SCROLLSUPPORT
1038 struct wskbd_scroll_data
*usdp
, *ksdp
;
1040 struct wskbd_softc
*sc
= device_private(dev
);
1041 struct wskbd_bell_data
*ubdp
, *kbdp
;
1042 struct wskbd_keyrepeat_data
*ukdp
, *kkdp
;
1043 struct wskbd_map_data
*umdp
;
1044 struct wskbd_mapdata md
;
1045 struct proc
*p
= l
? l
->l_proc
: NULL
;
1051 #define SETBELL(dstp, srcp, dfltp) \
1053 (dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH) ? \
1054 (srcp)->pitch : (dfltp)->pitch; \
1055 (dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD) ? \
1056 (srcp)->period : (dfltp)->period; \
1057 (dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME) ? \
1058 (srcp)->volume : (dfltp)->volume; \
1059 (dstp)->which = WSKBD_BELL_DOALL; \
1063 if ((flag
& FWRITE
) == 0)
1065 return ((*sc
->sc_accessops
->ioctl
)(sc
->sc_accesscookie
,
1066 WSKBDIO_COMPLEXBELL
, (void *)&sc
->sc_bell_data
, flag
, l
));
1068 case WSKBDIO_COMPLEXBELL
:
1069 if ((flag
& FWRITE
) == 0)
1071 ubdp
= (struct wskbd_bell_data
*)data
;
1072 SETBELL(ubdp
, ubdp
, &sc
->sc_bell_data
);
1073 return ((*sc
->sc_accessops
->ioctl
)(sc
->sc_accesscookie
,
1074 WSKBDIO_COMPLEXBELL
, (void *)ubdp
, flag
, l
));
1076 case WSKBDIO_SETBELL
:
1077 if ((flag
& FWRITE
) == 0)
1079 kbdp
= &sc
->sc_bell_data
;
1081 ubdp
= (struct wskbd_bell_data
*)data
;
1082 SETBELL(kbdp
, ubdp
, kbdp
);
1085 case WSKBDIO_GETBELL
:
1086 kbdp
= &sc
->sc_bell_data
;
1088 ubdp
= (struct wskbd_bell_data
*)data
;
1089 SETBELL(ubdp
, kbdp
, kbdp
);
1092 case WSKBDIO_SETDEFAULTBELL
:
1093 if (p
&& (error
= kauth_authorize_generic(l
->l_cred
,
1094 KAUTH_GENERIC_ISSUSER
, NULL
)) != 0)
1096 kbdp
= &wskbd_default_bell_data
;
1100 case WSKBDIO_GETDEFAULTBELL
:
1101 kbdp
= &wskbd_default_bell_data
;
1106 #define SETKEYREPEAT(dstp, srcp, dfltp) \
1108 (dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL1) ? \
1109 (srcp)->del1 : (dfltp)->del1; \
1110 (dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN) ? \
1111 (srcp)->delN : (dfltp)->delN; \
1112 (dstp)->which = WSKBD_KEYREPEAT_DOALL; \
1115 case WSKBDIO_SETKEYREPEAT
:
1116 if ((flag
& FWRITE
) == 0)
1118 kkdp
= &sc
->sc_keyrepeat_data
;
1120 ukdp
= (struct wskbd_keyrepeat_data
*)data
;
1121 SETKEYREPEAT(kkdp
, ukdp
, kkdp
);
1124 case WSKBDIO_GETKEYREPEAT
:
1125 kkdp
= &sc
->sc_keyrepeat_data
;
1127 ukdp
= (struct wskbd_keyrepeat_data
*)data
;
1128 SETKEYREPEAT(ukdp
, kkdp
, kkdp
);
1131 case WSKBDIO_SETDEFAULTKEYREPEAT
:
1132 if ((error
= kauth_authorize_generic(l
->l_cred
,
1133 KAUTH_GENERIC_ISSUSER
, NULL
)) != 0)
1135 kkdp
= &wskbd_default_keyrepeat_data
;
1139 case WSKBDIO_GETDEFAULTKEYREPEAT
:
1140 kkdp
= &wskbd_default_keyrepeat_data
;
1143 #ifdef WSDISPLAY_SCROLLSUPPORT
1144 #define SETSCROLLMOD(dstp, srcp, dfltp) \
1146 (dstp)->mode = ((srcp)->which & WSKBD_SCROLL_DOMODE) ? \
1147 (srcp)->mode : (dfltp)->mode; \
1148 (dstp)->modifier = ((srcp)->which & WSKBD_SCROLL_DOMODIFIER) ? \
1149 (srcp)->modifier : (dfltp)->modifier; \
1150 (dstp)->which = WSKBD_SCROLL_DOALL; \
1153 case WSKBDIO_SETSCROLL
:
1154 usdp
= (struct wskbd_scroll_data
*)data
;
1155 ksdp
= &sc
->sc_scroll_data
;
1156 SETSCROLLMOD(ksdp
, usdp
, ksdp
);
1159 case WSKBDIO_GETSCROLL
:
1160 usdp
= (struct wskbd_scroll_data
*)data
;
1161 ksdp
= &sc
->sc_scroll_data
;
1162 SETSCROLLMOD(usdp
, ksdp
, ksdp
);
1165 case WSKBDIO_GETSCROLL
:
1166 case WSKBDIO_SETSCROLL
:
1172 case WSKBDIO_SETMAP
:
1173 if ((flag
& FWRITE
) == 0)
1175 umdp
= (struct wskbd_map_data
*)data
;
1176 if (umdp
->maplen
> WSKBDIO_MAXMAPLEN
)
1179 len
= umdp
->maplen
*sizeof(struct wscons_keymap
);
1180 tbuf
= malloc(len
, M_TEMP
, M_WAITOK
);
1181 error
= copyin(umdp
->map
, tbuf
, len
);
1183 wskbd_init_keymap(umdp
->maplen
,
1184 &sc
->sc_map
, &sc
->sc_maplen
);
1185 memcpy(sc
->sc_map
, tbuf
, len
);
1186 /* drop the variant bits handled by the map */
1187 sc
->sc_layout
= KB_USER
|
1188 (KB_VARIANT(sc
->sc_layout
) & KB_HANDLEDBYWSKBD
);
1189 wskbd_update_layout(sc
->id
, sc
->sc_layout
);
1194 case WSKBDIO_GETMAP
:
1195 umdp
= (struct wskbd_map_data
*)data
;
1196 if (umdp
->maplen
> sc
->sc_maplen
)
1197 umdp
->maplen
= sc
->sc_maplen
;
1198 error
= copyout(sc
->sc_map
, umdp
->map
,
1199 umdp
->maplen
*sizeof(struct wscons_keymap
));
1202 case WSKBDIO_GETENCODING
:
1203 *((kbd_t
*) data
) = sc
->sc_layout
;
1206 case WSKBDIO_SETENCODING
:
1207 if ((flag
& FWRITE
) == 0)
1209 enc
= *((kbd_t
*)data
);
1210 if (KB_ENCODING(enc
) == KB_USER
) {
1211 /* user map must already be loaded */
1212 if (KB_ENCODING(sc
->sc_layout
) != KB_USER
)
1214 /* map variants make no sense */
1215 if (KB_VARIANT(enc
) & ~KB_HANDLEDBYWSKBD
)
1218 md
= *(sc
->id
->t_keymap
); /* structure assignment */
1220 error
= wskbd_load_keymap(&md
, &sc
->sc_map
,
1225 sc
->sc_layout
= enc
;
1226 wskbd_update_layout(sc
->id
, enc
);
1229 case WSKBDIO_SETVERSION
:
1230 return wsevent_setversion(sc
->sc_base
.me_evp
, *(int *)data
);
1234 * Try the keyboard driver for WSKBDIO ioctls. It returns -1
1235 * if it didn't recognize the request, and in turn we return
1236 * -1 if we didn't recognize the request.
1238 /* printf("kbdaccess\n"); */
1239 error
= (*sc
->sc_accessops
->ioctl
)(sc
->sc_accesscookie
, cmd
, data
,
1241 #ifdef WSDISPLAY_COMPAT_RAWKBD
1242 if (!error
&& cmd
== WSKBDIO_SETMODE
&& *(int *)data
== WSKBD_RAW
) {
1244 sc
->id
->t_modifiers
&= ~(MOD_SHIFT_L
| MOD_SHIFT_R
1245 | MOD_CONTROL_L
| MOD_CONTROL_R
1246 | MOD_META_L
| MOD_META_R
1248 | MOD_COMMAND1
| MOD_COMMAND2
);
1249 if (sc
->sc_repeating
) {
1250 sc
->sc_repeating
= 0;
1251 callout_stop(&sc
->sc_repeat_ch
);
1260 wskbdpoll(dev_t dev
, int events
, struct lwp
*l
)
1262 struct wskbd_softc
*sc
=
1263 device_lookup_private(&wskbd_cd
, minor(dev
));
1265 if (sc
->sc_base
.me_evp
== NULL
)
1267 return (wsevent_poll(sc
->sc_base
.me_evp
, events
, l
));
1271 wskbdkqfilter(dev_t dev
, struct knote
*kn
)
1273 struct wskbd_softc
*sc
=
1274 device_lookup_private(&wskbd_cd
, minor(dev
));
1276 if (sc
->sc_base
.me_evp
== NULL
)
1278 return (wsevent_kqfilter(sc
->sc_base
.me_evp
, kn
));
1284 wskbd_pickfree(void)
1287 struct wskbd_softc
*sc
;
1289 for (i
= 0; i
< wskbd_cd
.cd_ndevs
; i
++) {
1290 sc
= device_lookup_private(&wskbd_cd
, i
);
1293 if (sc
->sc_base
.me_dispdv
== NULL
)
1300 wskbd_set_console_display(device_t displaydv
, struct wsevsrc
*me
)
1302 struct wskbd_softc
*sc
= wskbd_console_device
;
1306 sc
->sc_base
.me_dispdv
= displaydv
;
1308 (void)wsmux_attach_sc((struct wsmux_softc
*)me
, &sc
->sc_base
);
1310 return (&sc
->sc_base
);
1314 wskbd_set_display(device_t dv
, struct wsevsrc
*me
)
1316 struct wskbd_softc
*sc
= device_private(dv
);
1317 device_t displaydv
= me
!= NULL
? me
->me_dispdv
: NULL
;
1318 device_t odisplaydv
;
1321 DPRINTF(("wskbd_set_display: %s me=%p odisp=%p disp=%p cons=%d\n",
1322 device_xname(dv
), me
, sc
->sc_base
.me_dispdv
, displaydv
,
1325 if (sc
->sc_isconsole
)
1328 if (displaydv
!= NULL
) {
1329 if (sc
->sc_base
.me_dispdv
!= NULL
)
1332 if (sc
->sc_base
.me_dispdv
== NULL
)
1336 odisplaydv
= sc
->sc_base
.me_dispdv
;
1337 sc
->sc_base
.me_dispdv
= NULL
;
1338 error
= wskbd_enable(sc
, displaydv
!= NULL
);
1339 sc
->sc_base
.me_dispdv
= displaydv
;
1341 sc
->sc_base
.me_dispdv
= odisplaydv
;
1346 aprint_verbose_dev(sc
->sc_base
.me_dv
, "connecting to %s\n",
1347 device_xname(displaydv
));
1349 aprint_verbose_dev(sc
->sc_base
.me_dv
, "disconnecting from %s\n",
1350 device_xname(odisplaydv
));
1355 #endif /* NWSDISPLAY > 0 */
1359 wskbd_add_mux(int unit
, struct wsmux_softc
*muxsc
)
1361 struct wskbd_softc
*sc
= device_lookup_private(&wskbd_cd
, unit
);
1366 if (sc
->sc_base
.me_parent
!= NULL
|| sc
->sc_base
.me_evp
!= NULL
)
1369 return (wsmux_attach_sc(muxsc
, &sc
->sc_base
));
1374 * Console interface.
1377 wskbd_cngetc(dev_t dev
)
1385 if (!wskbd_console_initted
)
1388 if (wskbd_console_device
!= NULL
&&
1389 !wskbd_console_device
->sc_translating
)
1394 ks
= wskbd_console_data
.t_symbols
[pos
++];
1395 if (KS_GROUP(ks
) == KS_GROUP_Ascii
)
1396 return (KS_VALUE(ks
));
1398 (*wskbd_console_data
.t_consops
->getc
)
1399 (wskbd_console_data
.t_consaccesscookie
,
1401 if (type
== WSCONS_EVENT_ASCII
) {
1403 * We assume that when the driver falls back
1404 * to deliver pure ASCII it is in a state that
1405 * it can not track press/release events
1406 * reliable - so we clear all previously
1407 * accumulated modifier state.
1409 wskbd_console_data
.t_modifiers
= 0;
1412 num
= wskbd_translate(&wskbd_console_data
, type
, data
);
1419 wskbd_cnpollc(dev_t dev
, int poll
)
1422 if (!wskbd_console_initted
)
1425 if (wskbd_console_device
!= NULL
&&
1426 !wskbd_console_device
->sc_translating
)
1429 (*wskbd_console_data
.t_consops
->pollc
)
1430 (wskbd_console_data
.t_consaccesscookie
, poll
);
1434 wskbd_cnbell(dev_t dev
, u_int pitch
, u_int period
, u_int volume
)
1437 if (!wskbd_console_initted
)
1440 if (wskbd_console_data
.t_consops
->bell
!= NULL
)
1441 (*wskbd_console_data
.t_consops
->bell
)
1442 (wskbd_console_data
.t_consaccesscookie
, pitch
, period
,
1447 update_leds(struct wskbd_internal
*id
)
1452 if (id
->t_modifiers
& (MOD_SHIFTLOCK
| MOD_CAPSLOCK
))
1453 new_state
|= WSKBD_LED_CAPS
;
1454 if (id
->t_modifiers
& MOD_NUMLOCK
)
1455 new_state
|= WSKBD_LED_NUM
;
1456 if (id
->t_modifiers
& MOD_COMPOSE
)
1457 new_state
|= WSKBD_LED_COMPOSE
;
1458 if (id
->t_modifiers
& MOD_HOLDSCREEN
)
1459 new_state
|= WSKBD_LED_SCROLL
;
1461 if (id
->t_sc
&& new_state
!= id
->t_sc
->sc_ledstate
) {
1462 (*id
->t_sc
->sc_accessops
->set_leds
)
1463 (id
->t_sc
->sc_accesscookie
, new_state
);
1464 id
->t_sc
->sc_ledstate
= new_state
;
1469 update_modifier(struct wskbd_internal
*id
, u_int type
, int toggle
, int mask
)
1472 if (type
== WSCONS_EVENT_KEY_DOWN
)
1473 id
->t_modifiers
^= mask
;
1475 if (type
== WSCONS_EVENT_KEY_DOWN
)
1476 id
->t_modifiers
|= mask
;
1478 id
->t_modifiers
&= ~mask
;
1484 change_displayparam(struct wskbd_softc
*sc
, int param
, int updown
,
1488 struct wsdisplay_param dp
;
1491 res
= wsdisplay_param(sc
->sc_base
.me_dispdv
, WSDISPLAYIO_GETPARAM
, &dp
);
1494 return; /* no such parameter */
1496 dp
.curval
+= updown
;
1497 if (dp
.max
< dp
.curval
)
1498 dp
.curval
= wraparound
? dp
.min
: dp
.max
;
1500 if (dp
.curval
< dp
.min
)
1501 dp
.curval
= wraparound
? dp
.max
: dp
.min
;
1502 wsdisplay_param(sc
->sc_base
.me_dispdv
, WSDISPLAYIO_SETPARAM
, &dp
);
1507 internal_command(struct wskbd_softc
*sc
, u_int
*type
, keysym_t ksym
,
1510 #ifdef WSDISPLAY_SCROLLSUPPORT
1514 case KS_Cmd_VolumeToggle
:
1515 if (*type
== WSCONS_EVENT_KEY_DOWN
)
1516 pmf_event_inject(NULL
, PMFE_AUDIO_VOLUME_TOGGLE
);
1518 case KS_Cmd_VolumeUp
:
1519 if (*type
== WSCONS_EVENT_KEY_DOWN
)
1520 pmf_event_inject(NULL
, PMFE_AUDIO_VOLUME_UP
);
1522 case KS_Cmd_VolumeDown
:
1523 if (*type
== WSCONS_EVENT_KEY_DOWN
)
1524 pmf_event_inject(NULL
, PMFE_AUDIO_VOLUME_DOWN
);
1526 #ifdef WSDISPLAY_SCROLLSUPPORT
1527 case KS_Cmd_ScrollFastUp
:
1528 case KS_Cmd_ScrollFastDown
:
1529 if (*type
== WSCONS_EVENT_KEY_DOWN
) {
1530 GETMODSTATE(sc
->id
->t_modifiers
, state
);
1531 if ((sc
->sc_scroll_data
.mode
== WSKBD_SCROLL_MODE_HOLD
1532 && MOD_ONESET(sc
->id
, MOD_HOLDSCREEN
))
1533 || (sc
->sc_scroll_data
.mode
== WSKBD_SCROLL_MODE_NORMAL
1534 && sc
->sc_scroll_data
.modifier
== state
)) {
1535 update_modifier(sc
->id
, *type
, 0, MOD_COMMAND
);
1536 wsdisplay_scroll(sc
->sc_base
.me_dispdv
,
1537 (ksym
== KS_Cmd_ScrollFastUp
) ?
1538 WSDISPLAY_SCROLL_BACKWARD
:
1539 WSDISPLAY_SCROLL_FORWARD
);
1546 case KS_Cmd_ScrollSlowUp
:
1547 case KS_Cmd_ScrollSlowDown
:
1548 if (*type
== WSCONS_EVENT_KEY_DOWN
) {
1549 GETMODSTATE(sc
->id
->t_modifiers
, state
);
1550 if ((sc
->sc_scroll_data
.mode
== WSKBD_SCROLL_MODE_HOLD
1551 && MOD_ONESET(sc
->id
, MOD_HOLDSCREEN
))
1552 || (sc
->sc_scroll_data
.mode
== WSKBD_SCROLL_MODE_NORMAL
1553 && sc
->sc_scroll_data
.modifier
== state
)) {
1554 update_modifier(sc
->id
, *type
, 0, MOD_COMMAND
);
1555 wsdisplay_scroll(sc
->sc_base
.me_dispdv
,
1556 (ksym
== KS_Cmd_ScrollSlowUp
) ?
1557 WSDISPLAY_SCROLL_BACKWARD
| WSDISPLAY_SCROLL_LOW
:
1558 WSDISPLAY_SCROLL_FORWARD
| WSDISPLAY_SCROLL_LOW
);
1567 update_modifier(sc
->id
, *type
, 0, MOD_COMMAND
);
1572 update_modifier(sc
->id
, *type
, 0, MOD_COMMAND1
);
1576 update_modifier(sc
->id
, *type
, 0, MOD_COMMAND2
);
1580 if (*type
!= WSCONS_EVENT_KEY_DOWN
||
1581 (! MOD_ONESET(sc
->id
, MOD_COMMAND
) &&
1582 ! MOD_ALLSET(sc
->id
, MOD_COMMAND1
| MOD_COMMAND2
)))
1585 #if defined(DDB) || defined(KGDB)
1586 if (ksym
== KS_Cmd_Debugger
) {
1587 if (sc
->sc_isconsole
) {
1595 /* discard this key (ddb discarded command modifiers) */
1596 *type
= WSCONS_EVENT_KEY_UP
;
1602 if (sc
->sc_base
.me_dispdv
== NULL
)
1606 case KS_Cmd_Screen0
:
1607 case KS_Cmd_Screen1
:
1608 case KS_Cmd_Screen2
:
1609 case KS_Cmd_Screen3
:
1610 case KS_Cmd_Screen4
:
1611 case KS_Cmd_Screen5
:
1612 case KS_Cmd_Screen6
:
1613 case KS_Cmd_Screen7
:
1614 case KS_Cmd_Screen8
:
1615 case KS_Cmd_Screen9
:
1616 wsdisplay_switch(sc
->sc_base
.me_dispdv
, ksym
- KS_Cmd_Screen0
, 0);
1618 case KS_Cmd_ResetEmul
:
1619 wsdisplay_reset(sc
->sc_base
.me_dispdv
, WSDISPLAY_RESETEMUL
);
1621 case KS_Cmd_ResetClose
:
1622 wsdisplay_reset(sc
->sc_base
.me_dispdv
, WSDISPLAY_RESETCLOSE
);
1624 case KS_Cmd_BacklightOn
:
1625 case KS_Cmd_BacklightOff
:
1626 case KS_Cmd_BacklightToggle
:
1627 change_displayparam(sc
, WSDISPLAYIO_PARAM_BACKLIGHT
,
1628 ksym
== KS_Cmd_BacklightOff
? -1 : 1,
1629 ksym
== KS_Cmd_BacklightToggle
? 1 : 0);
1631 case KS_Cmd_BrightnessUp
:
1632 case KS_Cmd_BrightnessDown
:
1633 case KS_Cmd_BrightnessRotate
:
1634 change_displayparam(sc
, WSDISPLAYIO_PARAM_BRIGHTNESS
,
1635 ksym
== KS_Cmd_BrightnessDown
? -1 : 1,
1636 ksym
== KS_Cmd_BrightnessRotate
? 1 : 0);
1638 case KS_Cmd_ContrastUp
:
1639 case KS_Cmd_ContrastDown
:
1640 case KS_Cmd_ContrastRotate
:
1641 change_displayparam(sc
, WSDISPLAYIO_PARAM_CONTRAST
,
1642 ksym
== KS_Cmd_ContrastDown
? -1 : 1,
1643 ksym
== KS_Cmd_ContrastRotate
? 1 : 0);
1652 wskbd_hotkey_register(device_t self
, void *cookie
, wskbd_hotkey_plugin
*hotkey
)
1654 struct wskbd_softc
*sc
= device_private(self
);
1656 sc
->sc_hotkey
= hotkey
;
1657 sc
->sc_hotkeycookie
= cookie
;
1658 return sc
->sc_base
.me_dv
;
1662 wskbd_translate(struct wskbd_internal
*id
, u_int type
, int value
)
1664 struct wskbd_softc
*sc
= id
->t_sc
;
1665 keysym_t ksym
, res
, *group
;
1666 struct wscons_keymap kpbuf
, *kp
;
1670 if (type
== WSCONS_EVENT_ALL_KEYS_UP
) {
1671 id
->t_modifiers
&= ~(MOD_SHIFT_L
| MOD_SHIFT_R
1672 | MOD_CONTROL_L
| MOD_CONTROL_R
1673 | MOD_META_L
| MOD_META_R
1675 | MOD_COMMAND
| MOD_COMMAND1
| MOD_COMMAND2
);
1681 if (sc
->sc_hotkey
!= NULL
)
1682 ishotkey
= sc
->sc_hotkey(sc
, sc
->sc_hotkeycookie
,
1687 if (value
< 0 || value
>= sc
->sc_maplen
) {
1689 printf("%s: keycode %d out of range\n",
1694 kp
= sc
->sc_map
+ value
;
1697 wskbd_get_mapentry(id
->t_keymap
, value
, kp
);
1700 /* if this key has a command, process it first */
1701 if (sc
!= NULL
&& kp
->command
!= KS_voidSymbol
)
1702 iscommand
= internal_command(sc
, &type
, kp
->command
,
1705 /* Now update modifiers */
1706 switch (kp
->group1
[0]) {
1708 update_modifier(id
, type
, 0, MOD_SHIFT_L
);
1712 update_modifier(id
, type
, 0, MOD_SHIFT_R
);
1716 update_modifier(id
, type
, 1, MOD_SHIFTLOCK
);
1720 update_modifier(id
, type
, 1, MOD_CAPSLOCK
);
1724 update_modifier(id
, type
, 0, MOD_CONTROL_L
);
1728 update_modifier(id
, type
, 0, MOD_CONTROL_R
);
1732 update_modifier(id
, type
, 0, MOD_META_L
);
1736 update_modifier(id
, type
, 0, MOD_META_R
);
1739 case KS_Mode_switch
:
1740 update_modifier(id
, type
, 0, MOD_MODESHIFT
);
1744 update_modifier(id
, type
, 1, MOD_NUMLOCK
);
1748 case KS_Hold_Screen
:
1750 update_modifier(id
, type
, 1, MOD_HOLDSCREEN
);
1751 wskbd_holdscreen(sc
, id
->t_modifiers
& MOD_HOLDSCREEN
);
1757 /* If this is a key release or we are in command mode, we are done */
1758 if (type
!= WSCONS_EVENT_KEY_DOWN
|| iscommand
) {
1763 /* Get the keysym */
1764 if (id
->t_modifiers
& MOD_MODESHIFT
)
1765 group
= & kp
->group2
[0];
1767 group
= & kp
->group1
[0];
1769 if ((id
->t_modifiers
& MOD_NUMLOCK
) != 0 &&
1770 KS_GROUP(group
[1]) == KS_GROUP_Keypad
) {
1771 if (MOD_ONESET(id
, MOD_ANYSHIFT
))
1775 } else if (! MOD_ONESET(id
, MOD_ANYSHIFT
| MOD_CAPSLOCK
)) {
1777 } else if (MOD_ONESET(id
, MOD_CAPSLOCK
)) {
1778 if (! MOD_ONESET(id
, MOD_SHIFT_L
| MOD_SHIFT_R
))
1782 if (ksym
>= KS_a
&& ksym
<= KS_z
)
1783 ksym
+= KS_A
- KS_a
;
1784 else if (ksym
>= KS_agrave
&& ksym
<= KS_thorn
&&
1785 ksym
!= KS_division
)
1786 ksym
+= KS_Agrave
- KS_agrave
;
1787 } else if (MOD_ONESET(id
, MOD_ANYSHIFT
)) {
1793 /* Process compose sequence and dead accents */
1794 res
= KS_voidSymbol
;
1796 switch (KS_GROUP(ksym
)) {
1797 case KS_GROUP_Ascii
:
1798 case KS_GROUP_Keypad
:
1799 case KS_GROUP_Function
:
1804 if (ksym
== KS_Multi_key
) {
1805 update_modifier(id
, 1, 0, MOD_COMPOSE
);
1806 id
->t_composelen
= 2;
1811 if (id
->t_composelen
== 0) {
1812 update_modifier(id
, 1, 0, MOD_COMPOSE
);
1813 id
->t_composelen
= 1;
1814 id
->t_composebuf
[0] = ksym
;
1820 if (res
== KS_voidSymbol
) {
1825 if (id
->t_composelen
> 0) {
1826 id
->t_composebuf
[2 - id
->t_composelen
] = res
;
1827 if (--id
->t_composelen
== 0) {
1828 res
= wskbd_compose_value(id
->t_composebuf
);
1829 update_modifier(id
, 0, 0, MOD_COMPOSE
);
1837 /* We are done, return the symbol */
1838 if (KS_GROUP(res
) == KS_GROUP_Ascii
) {
1839 if (MOD_ONESET(id
, MOD_ANYCONTROL
)) {
1840 if ((res
>= KS_at
&& res
<= KS_z
) || res
== KS_space
)
1842 else if (res
== KS_2
)
1844 else if (res
>= KS_3
&& res
<= KS_7
)
1845 res
= KS_Escape
+ (res
- KS_3
);
1846 else if (res
== KS_8
)
1849 if (MOD_ONESET(id
, MOD_ANYMETA
)) {
1850 if (id
->t_flags
& WSKFL_METAESC
) {
1851 id
->t_symbols
[0] = KS_Escape
;
1852 id
->t_symbols
[1] = res
;
1859 id
->t_symbols
[0] = res
;