xref: /openbsd/sys/dev/wscons/wskbd.c (revision 09467b48)
1 /* $OpenBSD: wskbd.c,v 1.106 2020/07/29 05:53:52 anton Exp $ */
2 /* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */
3 
4 /*
5  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
6  *
7  * Keysym translator:
8  * Contributed to The NetBSD Foundation by Juergen Hannken-Illjes.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by Christopher G. Demetriou
21  *	for the NetBSD Project.
22  * 4. The name of the author may not be used to endorse or promote products
23  *    derived from this software without specific prior written permission
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1992, 1993
39  *	The Regents of the University of California.  All rights reserved.
40  *
41  * This software was developed by the Computer Systems Engineering group
42  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
43  * contributed to Berkeley.
44  *
45  * All advertising materials mentioning features or use of this software
46  * must display the following acknowledgement:
47  *	This product includes software developed by the University of
48  *	California, Lawrence Berkeley Laboratory.
49  *
50  * Redistribution and use in source and binary forms, with or without
51  * modification, are permitted provided that the following conditions
52  * are met:
53  * 1. Redistributions of source code must retain the above copyright
54  *    notice, this list of conditions and the following disclaimer.
55  * 2. Redistributions in binary form must reproduce the above copyright
56  *    notice, this list of conditions and the following disclaimer in the
57  *    documentation and/or other materials provided with the distribution.
58  * 3. Neither the name of the University nor the names of its contributors
59  *    may be used to endorse or promote products derived from this software
60  *    without specific prior written permission.
61  *
62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72  * SUCH DAMAGE.
73  *
74  *	@(#)kbd.c	8.2 (Berkeley) 10/30/93
75  */
76 
77 /*
78  * Keyboard driver (/dev/wskbd*).  Translates incoming bytes to ASCII or
79  * to `wscons_events' and passes them up to the appropriate reader.
80  */
81 
82 #include <sys/param.h>
83 #include <sys/conf.h>
84 #include <sys/device.h>
85 #include <sys/ioctl.h>
86 #include <sys/kernel.h>
87 #include <sys/proc.h>
88 #include <sys/syslog.h>
89 #include <sys/systm.h>
90 #include <sys/timeout.h>
91 #include <sys/malloc.h>
92 #include <sys/tty.h>
93 #include <sys/signalvar.h>
94 #include <sys/errno.h>
95 #include <sys/fcntl.h>
96 #include <sys/vnode.h>
97 #include <sys/poll.h>
98 
99 #include <ddb/db_var.h>
100 
101 #include <dev/wscons/wscons_features.h>
102 #include <dev/wscons/wsconsio.h>
103 #include <dev/wscons/wskbdvar.h>
104 #include <dev/wscons/wsksymdef.h>
105 #include <dev/wscons/wsksymvar.h>
106 #include <dev/wscons/wsdisplayvar.h>
107 #include <dev/wscons/wseventvar.h>
108 #include <dev/wscons/wscons_callbacks.h>
109 
110 #include "audio.h"		/* NAUDIO (mixer tuning) */
111 #include "wsdisplay.h"
112 #include "wskbd.h"
113 #include "wsmux.h"
114 
115 #ifdef WSKBD_DEBUG
116 #define DPRINTF(x)	if (wskbddebug) printf x
117 int	wskbddebug = 0;
118 #else
119 #define DPRINTF(x)
120 #endif
121 
122 #include <dev/wscons/wsmuxvar.h>
123 
124 struct wskbd_internal {
125 	const struct wskbd_consops *t_consops;
126 	void	*t_consaccesscookie;
127 
128 	int	t_modifiers;
129 	int	t_composelen;		/* remaining entries in t_composebuf */
130 	keysym_t t_composebuf[2];
131 
132 	int	t_flags;
133 #define WSKFL_METAESC 1
134 
135 #define MAXKEYSYMSPERKEY 2 /* ESC <key> at max */
136 	keysym_t t_symbols[MAXKEYSYMSPERKEY];
137 
138 	struct wskbd_softc *t_sc;	/* back pointer */
139 
140 	struct wskbd_mapdata t_keymap;	/* translation map table and
141 					   current layout */
142 };
143 
144 struct wskbd_softc {
145 	struct wsevsrc	sc_base;
146 
147 	struct wskbd_internal *id;
148 
149 	const struct wskbd_accessops *sc_accessops;
150 	void *sc_accesscookie;
151 
152 	int	sc_ledstate;
153 
154 	int	sc_isconsole;
155 
156 	struct wskbd_bell_data sc_bell_data;
157 	struct wskbd_keyrepeat_data sc_keyrepeat_data;
158 
159 	int	sc_repeating;		/* we've called timeout() */
160 	int	sc_repkey;
161 	struct timeout sc_repeat_ch;
162 	u_int	sc_repeat_type;
163 	int	sc_repeat_value;
164 
165 	int	sc_translating;		/* xlate to chars for emulation */
166 
167 	int	sc_maplen;		/* number of entries in sc_map */
168 	struct wscons_keymap *sc_map;	/* current translation map */
169 
170 	int	sc_refcnt;
171 	u_char	sc_dying;		/* device is being detached */
172 };
173 
174 #define MOD_SHIFT_L		(1 << 0)
175 #define MOD_SHIFT_R		(1 << 1)
176 #define MOD_SHIFTLOCK		(1 << 2)
177 #define MOD_CAPSLOCK		(1 << 3)
178 #define MOD_CONTROL_L		(1 << 4)
179 #define MOD_CONTROL_R		(1 << 5)
180 #define MOD_META_L		(1 << 6)
181 #define MOD_META_R		(1 << 7)
182 #define MOD_MODESHIFT		(1 << 8)
183 #define MOD_NUMLOCK		(1 << 9)
184 #define MOD_COMPOSE		(1 << 10)
185 #define MOD_HOLDSCREEN		(1 << 11)
186 #define MOD_COMMAND		(1 << 12)
187 #define MOD_COMMAND1		(1 << 13)
188 #define MOD_COMMAND2		(1 << 14)
189 #define MOD_MODELOCK		(1 << 15)
190 
191 #define MOD_ANYSHIFT		(MOD_SHIFT_L | MOD_SHIFT_R | MOD_SHIFTLOCK)
192 #define MOD_ANYCONTROL		(MOD_CONTROL_L | MOD_CONTROL_R)
193 #define MOD_ANYMETA		(MOD_META_L | MOD_META_R)
194 #define MOD_ANYLED		(MOD_SHIFTLOCK | MOD_CAPSLOCK | MOD_NUMLOCK | \
195 				 MOD_COMPOSE | MOD_HOLDSCREEN)
196 
197 #define MOD_ONESET(id, mask)	(((id)->t_modifiers & (mask)) != 0)
198 #define MOD_ALLSET(id, mask)	(((id)->t_modifiers & (mask)) == (mask))
199 
200 keysym_t ksym_upcase(keysym_t);
201 
202 int	wskbd_match(struct device *, void *, void *);
203 void	wskbd_attach(struct device *, struct device *, void *);
204 int	wskbd_detach(struct device *, int);
205 int	wskbd_activate(struct device *, int);
206 
207 int	wskbd_displayioctl(struct device *, u_long, caddr_t, int, struct proc *);
208 
209 void	update_leds(struct wskbd_internal *);
210 void	update_modifier(struct wskbd_internal *, u_int, int, int);
211 int	internal_command(struct wskbd_softc *, u_int *, keysym_t, keysym_t);
212 int	wskbd_translate(struct wskbd_internal *, u_int, int);
213 int	wskbd_enable(struct wskbd_softc *, int);
214 void	wskbd_debugger(struct wskbd_softc *);
215 #if NWSDISPLAY > 0
216 void	change_displayparam(struct wskbd_softc *, int, int, int);
217 #endif
218 
219 int	wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int,
220 	    struct proc *);
221 void	wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value);
222 
223 #if NWSMUX > 0
224 int	wskbd_mux_open(struct wsevsrc *, struct wseventvar *);
225 int	wskbd_mux_close(struct wsevsrc *);
226 #else
227 #define	wskbd_mux_open NULL
228 #define	wskbd_mux_close NULL
229 #endif
230 
231 int	wskbd_do_open(struct wskbd_softc *, struct wseventvar *);
232 int	wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *);
233 
234 int	(*wskbd_get_backlight)(struct wskbd_backlight *);
235 int	(*wskbd_set_backlight)(struct wskbd_backlight *);
236 
237 struct cfdriver wskbd_cd = {
238 	NULL, "wskbd", DV_TTY
239 };
240 
241 struct cfattach wskbd_ca = {
242 	sizeof (struct wskbd_softc), wskbd_match, wskbd_attach,
243 	wskbd_detach, wskbd_activate
244 };
245 
246 #if defined(__i386__) || defined(__amd64__)
247 extern int kbd_reset;
248 #endif
249 
250 #ifndef WSKBD_DEFAULT_BELL_PITCH
251 #define	WSKBD_DEFAULT_BELL_PITCH	400	/* 400Hz */
252 #endif
253 #ifndef WSKBD_DEFAULT_BELL_PERIOD
254 #define	WSKBD_DEFAULT_BELL_PERIOD	100	/* 100ms */
255 #endif
256 #ifndef WSKBD_DEFAULT_BELL_VOLUME
257 #define	WSKBD_DEFAULT_BELL_VOLUME	50	/* 50% volume */
258 #endif
259 
260 struct wskbd_bell_data wskbd_default_bell_data = {
261 	WSKBD_BELL_DOALL,
262 	WSKBD_DEFAULT_BELL_PITCH,
263 	WSKBD_DEFAULT_BELL_PERIOD,
264 	WSKBD_DEFAULT_BELL_VOLUME,
265 };
266 
267 #ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1
268 #define	WSKBD_DEFAULT_KEYREPEAT_DEL1	400	/* 400ms to start repeating */
269 #endif
270 #ifndef WSKBD_DEFAULT_KEYREPEAT_DELN
271 #define	WSKBD_DEFAULT_KEYREPEAT_DELN	100	/* 100ms to between repeats */
272 #endif
273 
274 struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = {
275 	WSKBD_KEYREPEAT_DOALL,
276 	WSKBD_DEFAULT_KEYREPEAT_DEL1,
277 	WSKBD_DEFAULT_KEYREPEAT_DELN,
278 };
279 
280 #if NWSMUX > 0 || NWSDISPLAY > 0
281 struct wssrcops wskbd_srcops = {
282 	.type		= WSMUX_KBD,
283 	.dopen		= wskbd_mux_open,
284 	.dclose		= wskbd_mux_close,
285 	.dioctl		= wskbd_do_ioctl,
286 	.ddispioctl	= wskbd_displayioctl,
287 #if NWSDISPLAY > 0
288 	.dsetdisplay	= wskbd_set_display,
289 #else
290 	.dsetdisplay	= NULL,
291 #endif
292 };
293 #endif
294 
295 #if NWSDISPLAY > 0
296 void wskbd_repeat(void *v);
297 #endif
298 
299 static int wskbd_console_initted;
300 static struct wskbd_softc *wskbd_console_device;
301 static struct wskbd_internal wskbd_console_data;
302 
303 void	wskbd_update_layout(struct wskbd_internal *, kbd_t);
304 
305 #if NAUDIO > 0
306 extern int wskbd_set_mixervolume(long, long);
307 #endif
308 
309 void
310 wskbd_update_layout(struct wskbd_internal *id, kbd_t enc)
311 {
312 	if (enc & KB_METAESC)
313 		id->t_flags |= WSKFL_METAESC;
314 	else
315 		id->t_flags &= ~WSKFL_METAESC;
316 
317 	id->t_keymap.layout = enc;
318 }
319 
320 /*
321  * Print function (for parent devices).
322  */
323 int
324 wskbddevprint(void *aux, const char *pnp)
325 {
326 #if 0
327 	struct wskbddev_attach_args *ap = aux;
328 #endif
329 
330 	if (pnp)
331 		printf("wskbd at %s", pnp);
332 #if 0
333 	printf(" console %d", ap->console);
334 #endif
335 
336 	return (UNCONF);
337 }
338 
339 int
340 wskbd_match(struct device *parent, void *match, void *aux)
341 {
342 	struct cfdata *cf = match;
343 	struct wskbddev_attach_args *ap = aux;
344 
345 	if (cf->wskbddevcf_console != WSKBDDEVCF_CONSOLE_UNK) {
346 		/*
347 		 * If console-ness of device specified, either match
348 		 * exactly (at high priority), or fail.
349 		 */
350 		if (cf->wskbddevcf_console != 0 && ap->console != 0)
351 			return (10);
352 		else
353 			return (0);
354 	}
355 
356 	/* If console-ness unspecified, it wins. */
357 	return (1);
358 }
359 
360 void
361 wskbd_attach(struct device *parent, struct device *self, void *aux)
362 {
363 	struct wskbd_softc *sc = (struct wskbd_softc *)self;
364 	struct wskbddev_attach_args *ap = aux;
365 	kbd_t layout;
366 #if NWSMUX > 0
367 	struct wsmux_softc *wsmux_sc = NULL;
368 	int mux, error;
369 #endif
370 
371 	sc->sc_isconsole = ap->console;
372 
373 #if NWSMUX > 0 || NWSDISPLAY > 0
374 	sc->sc_base.me_ops = &wskbd_srcops;
375 #endif
376 #if NWSMUX > 0
377 	mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux;
378 	if (mux >= 0)
379 		wsmux_sc = wsmux_getmux(mux);
380 #endif	/* NWSMUX > 0 */
381 
382 	if (ap->console) {
383 		sc->id = &wskbd_console_data;
384 	} else {
385 		sc->id = malloc(sizeof(struct wskbd_internal),
386 		    M_DEVBUF, M_WAITOK | M_ZERO);
387 		bcopy(ap->keymap, &sc->id->t_keymap, sizeof(sc->id->t_keymap));
388 	}
389 
390 #if NWSDISPLAY > 0
391 	timeout_set(&sc->sc_repeat_ch, wskbd_repeat, sc);
392 #endif
393 
394 	sc->id->t_sc = sc;
395 
396 	sc->sc_accessops = ap->accessops;
397 	sc->sc_accesscookie = ap->accesscookie;
398 	sc->sc_repeating = 0;
399 	sc->sc_translating = 1;
400 	sc->sc_ledstate = -1; /* force update */
401 
402 	/*
403 	 * If this layout is the default choice of the driver (i.e. the
404 	 * driver doesn't know better), pick the existing layout of the
405 	 * current mux, if any.
406 	 */
407 	layout = sc->id->t_keymap.layout;
408 #if NWSMUX > 0
409 	if (layout & KB_DEFAULT) {
410 		if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE)
411 			layout = wsmux_get_layout(wsmux_sc);
412 	}
413 #endif
414 	for (;;) {
415 		if (wskbd_load_keymap(&sc->id->t_keymap, layout, &sc->sc_map,
416 		    &sc->sc_maplen) == 0)
417 			break;
418 #if NWSMUX > 0
419 		if (layout == sc->id->t_keymap.layout)
420 			panic("cannot load keymap");
421 		if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE) {
422 			printf("\n%s: cannot load keymap, "
423 			    "falling back to default\n%s",
424 			    sc->sc_base.me_dv.dv_xname,
425 			    sc->sc_base.me_dv.dv_xname);
426 			layout = wsmux_get_layout(wsmux_sc);
427 		} else
428 #endif
429 			panic("cannot load keymap");
430 	}
431 	wskbd_update_layout(sc->id, layout);
432 
433 	/* set default bell and key repeat data */
434 	sc->sc_bell_data = wskbd_default_bell_data;
435 	sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data;
436 
437 	if (ap->console) {
438 		KASSERT(wskbd_console_initted);
439 		KASSERT(wskbd_console_device == NULL);
440 
441 		wskbd_console_device = sc;
442 
443 		printf(": console keyboard");
444 
445 #if NWSDISPLAY > 0
446 		wsdisplay_set_console_kbd(&sc->sc_base); /* sets sc_displaydv */
447 		if (sc->sc_displaydv != NULL)
448 			printf(", using %s", sc->sc_displaydv->dv_xname);
449 #endif
450 	}
451 
452 #if NWSMUX > 0
453 	/* Ignore mux for console; it always goes to the console mux. */
454 	if (wsmux_sc != NULL && ap->console == 0) {
455 		printf(" mux %d\n", mux);
456 		error = wsmux_attach_sc(wsmux_sc, &sc->sc_base);
457 		if (error)
458 			printf("%s: attach error=%d\n",
459 			    sc->sc_base.me_dv.dv_xname, error);
460 
461 		/*
462 		 * Try and set this encoding as the mux default if it
463 		 * hasn't any yet, and if this is not a driver default
464 		 * layout (i.e. parent driver pretends to know better).
465 		 * Note that wsmux_set_layout() rejects layouts with
466 		 * KB_DEFAULT set.
467 		 */
468 		if (wsmux_get_layout(wsmux_sc) == KB_NONE)
469 			wsmux_set_layout(wsmux_sc, layout);
470 	} else
471 #endif
472 	printf("\n");
473 
474 #if NWSDISPLAY > 0 && NWSMUX == 0
475 	if (ap->console == 0) {
476 		/*
477 		 * In the non-wsmux world, always connect wskbd0 and wsdisplay0
478 		 * together.
479 		 */
480 		extern struct cfdriver wsdisplay_cd;
481 
482 		if (wsdisplay_cd.cd_ndevs != 0 && self->dv_unit == 0) {
483 			if (wskbd_set_display(self,
484 			    wsdisplay_cd.cd_devs[0]) == 0)
485 				wsdisplay_set_kbd(wsdisplay_cd.cd_devs[0],
486 				    (struct wsevsrc *)sc);
487 		}
488 	}
489 #endif
490 }
491 
492 void
493 wskbd_cnattach(const struct wskbd_consops *consops, void *conscookie,
494     const struct wskbd_mapdata *mapdata)
495 {
496 
497 	KASSERT(!wskbd_console_initted);
498 
499 	bcopy(mapdata, &wskbd_console_data.t_keymap, sizeof(*mapdata));
500 	wskbd_update_layout(&wskbd_console_data, mapdata->layout);
501 
502 	wskbd_console_data.t_consops = consops;
503 	wskbd_console_data.t_consaccesscookie = conscookie;
504 
505 #if NWSDISPLAY > 0
506 	wsdisplay_set_cons_kbd(wskbd_cngetc, wskbd_cnpollc, wskbd_cnbell);
507 #endif
508 
509 	wskbd_console_initted = 1;
510 }
511 
512 void
513 wskbd_cndetach(void)
514 {
515 	KASSERT(wskbd_console_initted);
516 
517 	wskbd_console_data.t_keymap.keydesc = NULL;
518 	wskbd_console_data.t_keymap.layout = KB_NONE;
519 
520 	wskbd_console_data.t_consops = NULL;
521 	wskbd_console_data.t_consaccesscookie = NULL;
522 
523 #if NWSDISPLAY > 0
524 	wsdisplay_unset_cons_kbd();
525 #endif
526 
527 	wskbd_console_device = NULL;
528 	wskbd_console_initted = 0;
529 }
530 
531 #if NWSDISPLAY > 0
532 void
533 wskbd_repeat(void *v)
534 {
535 	struct wskbd_softc *sc = (struct wskbd_softc *)v;
536 	int s = spltty();
537 
538 	if (sc->sc_repeating == 0) {
539 		/*
540 		 * race condition: a "key up" event came in when wskbd_repeat()
541 		 * was already called but not yet spltty()'d
542 		 */
543 		splx(s);
544 		return;
545 	}
546 	if (sc->sc_translating) {
547 		/* deliver keys */
548 		if (sc->sc_displaydv != NULL)
549 			wsdisplay_kbdinput(sc->sc_displaydv,
550 			    sc->id->t_keymap.layout,
551 			    sc->id->t_symbols, sc->sc_repeating);
552 	} else {
553 		/* queue event */
554 		wskbd_deliver_event(sc, sc->sc_repeat_type,
555 		    sc->sc_repeat_value);
556 	}
557 	if (sc->sc_keyrepeat_data.delN != 0)
558 		timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.delN);
559 	splx(s);
560 }
561 #endif
562 
563 int
564 wskbd_activate(struct device *self, int act)
565 {
566 	struct wskbd_softc *sc = (struct wskbd_softc *)self;
567 
568 	if (act == DVACT_DEACTIVATE)
569 		sc->sc_dying = 1;
570 	return (0);
571 }
572 
573 /*
574  * Detach a keyboard.  To keep track of users of the softc we keep
575  * a reference count that's incremented while inside, e.g., read.
576  * If the keyboard is active and the reference count is > 0 (0 is the
577  * normal state) we post an event and then wait for the process
578  * that had the reference to wake us up again.  Then we blow away the
579  * vnode and return (which will deallocate the softc).
580  */
581 int
582 wskbd_detach(struct device  *self, int flags)
583 {
584 	struct wskbd_softc *sc = (struct wskbd_softc *)self;
585 	struct wseventvar *evar;
586 	int maj, mn;
587 	int s;
588 
589 #if NWSMUX > 0
590 	/* Tell parent mux we're leaving. */
591 	if (sc->sc_base.me_parent != NULL)
592 		wsmux_detach_sc(&sc->sc_base);
593 #endif
594 
595 #if NWSDISPLAY > 0
596 	if (sc->sc_repeating) {
597 		sc->sc_repeating = 0;
598 		timeout_del(&sc->sc_repeat_ch);
599 	}
600 #endif
601 
602 	if (sc->sc_isconsole) {
603 		KASSERT(wskbd_console_device == sc);
604 		wskbd_cndetach();
605 	}
606 
607 	evar = sc->sc_base.me_evp;
608 	if (evar != NULL) {
609 		s = spltty();
610 		if (--sc->sc_refcnt >= 0) {
611 			/* Wake everyone by generating a dummy event. */
612 			if (++evar->put >= WSEVENT_QSIZE)
613 				evar->put = 0;
614 			WSEVENT_WAKEUP(evar);
615 			/* Wait for processes to go away. */
616 			if (tsleep_nsec(sc, PZERO, "wskdet", SEC_TO_NSEC(60)))
617 				printf("wskbd_detach: %s didn't detach\n",
618 				       sc->sc_base.me_dv.dv_xname);
619 		}
620 		splx(s);
621 	}
622 
623 	free(sc->sc_map, M_DEVBUF,
624 	    sc->sc_maplen * sizeof(struct wscons_keymap));
625 
626 	/* locate the major number */
627 	for (maj = 0; maj < nchrdev; maj++)
628 		if (cdevsw[maj].d_open == wskbdopen)
629 			break;
630 
631 	/* Nuke the vnodes for any open instances. */
632 	mn = self->dv_unit;
633 	vdevgone(maj, mn, mn, VCHR);
634 
635 	return (0);
636 }
637 
638 void
639 wskbd_input(struct device *dev, u_int type, int value)
640 {
641 	struct wskbd_softc *sc = (struct wskbd_softc *)dev;
642 #if NWSDISPLAY > 0
643 	int num;
644 #endif
645 
646 #if NWSDISPLAY > 0
647 	if (sc->sc_repeating) {
648 		sc->sc_repeating = 0;
649 		timeout_del(&sc->sc_repeat_ch);
650 	}
651 
652 	/*
653 	 * If /dev/wskbdN is not connected in event mode translate and
654 	 * send upstream.
655 	 */
656 	if (sc->sc_translating) {
657 #ifdef HAVE_BURNER_SUPPORT
658 		if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_displaydv != NULL)
659 			wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_KBD);
660 #endif
661 		num = wskbd_translate(sc->id, type, value);
662 		if (num > 0) {
663 			if (sc->sc_displaydv != NULL) {
664 #ifdef HAVE_SCROLLBACK_SUPPORT
665 				/* XXX - Shift_R+PGUP(release) emits PrtSc */
666 				if (sc->id->t_symbols[0] != KS_Print_Screen) {
667 					wsscrollback(sc->sc_displaydv,
668 					    WSDISPLAY_SCROLL_RESET);
669 				}
670 #endif
671 				wsdisplay_kbdinput(sc->sc_displaydv,
672 				    sc->id->t_keymap.layout,
673 				    sc->id->t_symbols, num);
674 			}
675 
676 			if (sc->sc_keyrepeat_data.del1 != 0) {
677 				sc->sc_repeating = num;
678 				timeout_add_msec(&sc->sc_repeat_ch,
679 				    sc->sc_keyrepeat_data.del1);
680 			}
681 		}
682 		return;
683 	}
684 #endif
685 
686 	wskbd_deliver_event(sc, type, value);
687 
688 #if NWSDISPLAY > 0
689 	/* Repeat key presses if enabled. */
690 	if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_keyrepeat_data.del1 != 0) {
691 		sc->sc_repeat_type = type;
692 		sc->sc_repeat_value = value;
693 		sc->sc_repeating = 1;
694 		timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1);
695 	}
696 #endif
697 }
698 
699 /*
700  * Keyboard is generating events.  Turn this keystroke into an
701  * event and put it in the queue.  If the queue is full, the
702  * keystroke is lost (sorry!).
703  */
704 void
705 wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value)
706 {
707 	struct wseventvar *evar;
708 	struct wscons_event *ev;
709 	int put;
710 
711 	evar = sc->sc_base.me_evp;
712 
713 	if (evar == NULL) {
714 		DPRINTF(("%s: not open\n", __func__));
715 		return;
716 	}
717 
718 #ifdef DIAGNOSTIC
719 	if (evar->q == NULL) {
720 		printf("wskbd_input: evar->q=NULL\n");
721 		return;
722 	}
723 #endif
724 
725 	put = evar->put;
726 	ev = &evar->q[put];
727 	put = (put + 1) % WSEVENT_QSIZE;
728 	if (put == evar->get) {
729 		log(LOG_WARNING, "%s: event queue overflow\n",
730 		    sc->sc_base.me_dv.dv_xname);
731 		return;
732 	}
733 	ev->type = type;
734 	ev->value = value;
735 	nanotime(&ev->time);
736 	evar->put = put;
737 	WSEVENT_WAKEUP(evar);
738 }
739 
740 #ifdef WSDISPLAY_COMPAT_RAWKBD
741 void
742 wskbd_rawinput(struct device *dev, u_char *buf, int len)
743 {
744 #if NWSDISPLAY > 0
745 	struct wskbd_softc *sc = (struct wskbd_softc *)dev;
746 
747 	if (sc->sc_displaydv != NULL)
748 		wsdisplay_rawkbdinput(sc->sc_displaydv, buf, len);
749 #endif
750 }
751 #endif /* WSDISPLAY_COMPAT_RAWKBD */
752 
753 int
754 wskbd_enable(struct wskbd_softc *sc, int on)
755 {
756 	int error;
757 
758 #if NWSDISPLAY > 0
759 	if (sc->sc_displaydv != NULL)
760 		return (0);
761 
762 	/* Always cancel auto repeat when fiddling with the kbd. */
763 	if (sc->sc_repeating) {
764 		sc->sc_repeating = 0;
765 		timeout_del(&sc->sc_repeat_ch);
766 	}
767 #endif
768 
769 	error = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on);
770 	DPRINTF(("%s: sc=%p on=%d res=%d\n", __func__, sc, on, error));
771 	return (error);
772 }
773 
774 #if NWSMUX > 0
775 int
776 wskbd_mux_open(struct wsevsrc *me, struct wseventvar *evp)
777 {
778 	struct wskbd_softc *sc = (struct wskbd_softc *)me;
779 
780 	if (sc->sc_dying)
781 		return (EIO);
782 
783 	return (wskbd_do_open(sc, evp));
784 }
785 #endif
786 
787 int
788 wskbdopen(dev_t dev, int flags, int mode, struct proc *p)
789 {
790 	struct wskbd_softc *sc;
791 	struct wseventvar *evar;
792 	int unit, error;
793 
794 	unit = minor(dev);
795 	if (unit >= wskbd_cd.cd_ndevs ||	/* make sure it was attached */
796 	    (sc = wskbd_cd.cd_devs[unit]) == NULL)
797 		return (ENXIO);
798 
799 #if NWSMUX > 0
800 	DPRINTF(("%s: %s mux=%p\n", __func__, sc->sc_base.me_dv.dv_xname,
801 		 sc->sc_base.me_parent));
802 #endif
803 
804 	if (sc->sc_dying)
805 		return (EIO);
806 
807 	if ((flags & (FREAD | FWRITE)) == FWRITE) {
808 		/* Not opening for read, only ioctl is available. */
809 		return (0);
810 	}
811 
812 #if NWSMUX > 0
813 	if (sc->sc_base.me_parent != NULL) {
814 		/* Grab the keyboard out of the greedy hands of the mux. */
815 		DPRINTF(("%s: detach\n", __func__));
816 		wsmux_detach_sc(&sc->sc_base);
817 	}
818 #endif
819 
820 	if (sc->sc_base.me_evp != NULL)
821 		return (EBUSY);
822 
823 	evar = &sc->sc_base.me_evar;
824 	if (wsevent_init(evar))
825 		return (EBUSY);
826 
827 	error = wskbd_do_open(sc, evar);
828 	if (error)
829 		wsevent_fini(evar);
830 	return (error);
831 }
832 
833 int
834 wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp)
835 {
836 	int error;
837 
838 	/* The device could already be attached to a mux. */
839 	if (sc->sc_base.me_evp != NULL)
840 		return (EBUSY);
841 
842 	sc->sc_base.me_evp = evp;
843 	sc->sc_translating = 0;
844 
845 	error = wskbd_enable(sc, 1);
846 	if (error)
847 		sc->sc_base.me_evp = NULL;
848 	return (error);
849 }
850 
851 int
852 wskbdclose(dev_t dev, int flags, int mode, struct proc *p)
853 {
854 	struct wskbd_softc *sc =
855 	    (struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)];
856 	struct wseventvar *evar = sc->sc_base.me_evp;
857 
858 	if ((flags & (FREAD | FWRITE)) == FWRITE) {
859 		/* not open for read */
860 		return (0);
861 	}
862 
863 	sc->sc_base.me_evp = NULL;
864 	sc->sc_translating = 1;
865 	(void)wskbd_enable(sc, 0);
866 	wsevent_fini(evar);
867 
868 #if NWSMUX > 0
869 	if (sc->sc_base.me_parent == NULL) {
870 		int mux, error;
871 
872 		DPRINTF(("%s: attach\n", __func__));
873 		mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux;
874 		if (mux >= 0) {
875 			error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base);
876 			if (error)
877 				printf("%s: can't attach mux (error=%d)\n",
878 				    sc->sc_base.me_dv.dv_xname, error);
879 		}
880 	}
881 #endif
882 
883 	return (0);
884 }
885 
886 #if NWSMUX > 0
887 int
888 wskbd_mux_close(struct wsevsrc *me)
889 {
890 	struct wskbd_softc *sc = (struct wskbd_softc *)me;
891 
892 	(void)wskbd_enable(sc, 0);
893 	sc->sc_translating = 1;
894 	sc->sc_base.me_evp = NULL;
895 
896 	return (0);
897 }
898 #endif
899 
900 int
901 wskbdread(dev_t dev, struct uio *uio, int flags)
902 {
903 	struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
904 	int error;
905 
906 	if (sc->sc_dying)
907 		return (EIO);
908 
909 #ifdef DIAGNOSTIC
910 	if (sc->sc_base.me_evp == NULL) {
911 		printf("wskbdread: evp == NULL\n");
912 		return (EINVAL);
913 	}
914 #endif
915 
916 	sc->sc_refcnt++;
917 	error = wsevent_read(&sc->sc_base.me_evar, uio, flags);
918 	if (--sc->sc_refcnt < 0) {
919 		wakeup(sc);
920 		error = EIO;
921 	}
922 	return (error);
923 }
924 
925 int
926 wskbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
927 {
928 	return (wskbd_do_ioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, flag,p));
929 }
930 
931 /* A wrapper around the ioctl() workhorse to make reference counting easy. */
932 int
933 wskbd_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag,
934     struct proc *p)
935 {
936 	struct wskbd_softc *sc = (struct wskbd_softc *)dv;
937 	int error;
938 
939 	sc->sc_refcnt++;
940 	error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p);
941 	if (--sc->sc_refcnt < 0)
942 		wakeup(sc);
943 	return (error);
944 }
945 
946 int
947 wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag,
948      struct proc *p)
949 {
950 	struct wseventvar *evar;
951 	int error;
952 
953 	/*
954 	 * Try the generic ioctls that the wskbd interface supports.
955 	 */
956 	switch (cmd) {
957 	case FIONBIO:		/* we will remove this someday (soon???) */
958 		return (0);
959 
960 	case FIOASYNC:
961 		if (sc->sc_base.me_evp == NULL)
962 			return (EINVAL);
963 		sc->sc_base.me_evp->async = *(int *)data != 0;
964 		return (0);
965 
966 	case FIOGETOWN:
967 	case TIOCGPGRP:
968 		evar = sc->sc_base.me_evp;
969 		if (evar == NULL)
970 			return (EINVAL);
971 		sigio_getown(&evar->sigio, cmd, data);
972 		return (0);
973 
974 	case FIOSETOWN:
975 	case TIOCSPGRP:
976 		evar = sc->sc_base.me_evp;
977 		if (evar == NULL)
978 			return (EINVAL);
979 		return (sigio_setown(&evar->sigio, cmd, data));
980 	}
981 
982 	/*
983 	 * Try the keyboard driver for WSKBDIO ioctls.  It returns -1
984 	 * if it didn't recognize the request.
985 	 */
986 	error = wskbd_displayioctl(&sc->sc_base.me_dv, cmd, data, flag, p);
987 	return (error != -1 ? error : ENOTTY);
988 }
989 
990 /*
991  * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode.
992  * Some of these have no real effect in raw mode, however.
993  */
994 int
995 wskbd_displayioctl(struct device *dev, u_long cmd, caddr_t data, int flag,
996     struct proc *p)
997 {
998 	struct wskbd_softc *sc = (struct wskbd_softc *)dev;
999 	struct wskbd_bell_data *ubdp, *kbdp;
1000 	struct wskbd_keyrepeat_data *ukdp, *kkdp;
1001 	struct wskbd_map_data *umdp;
1002 	struct wskbd_encoding_data *uedp;
1003 	kbd_t enc;
1004 	void *buf;
1005 	int len, error;
1006 	int count, i;
1007 
1008 	switch (cmd) {
1009 	case WSKBDIO_BELL:
1010 	case WSKBDIO_COMPLEXBELL:
1011 	case WSKBDIO_SETBELL:
1012 	case WSKBDIO_SETKEYREPEAT:
1013 	case WSKBDIO_SETDEFAULTKEYREPEAT:
1014 	case WSKBDIO_SETMAP:
1015 	case WSKBDIO_SETENCODING:
1016 	case WSKBDIO_SETBACKLIGHT:
1017 		if ((flag & FWRITE) == 0)
1018 			return (EACCES);
1019 	}
1020 
1021 	switch (cmd) {
1022 #define	SETBELL(dstp, srcp, dfltp)					\
1023     do {								\
1024 	(dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH) ?		\
1025 	    (srcp)->pitch : (dfltp)->pitch;				\
1026 	(dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD) ?	\
1027 	    (srcp)->period : (dfltp)->period;				\
1028 	(dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME) ?	\
1029 	    (srcp)->volume : (dfltp)->volume;				\
1030 	(dstp)->which = WSKBD_BELL_DOALL;				\
1031     } while (0)
1032 
1033 	case WSKBDIO_BELL:
1034 		return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
1035 		    WSKBDIO_COMPLEXBELL, (caddr_t)&sc->sc_bell_data, flag, p));
1036 
1037 	case WSKBDIO_COMPLEXBELL:
1038 		ubdp = (struct wskbd_bell_data *)data;
1039 		SETBELL(ubdp, ubdp, &sc->sc_bell_data);
1040 		return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
1041 		    WSKBDIO_COMPLEXBELL, (caddr_t)ubdp, flag, p));
1042 
1043 	case WSKBDIO_SETBELL:
1044 		kbdp = &sc->sc_bell_data;
1045 setbell:
1046 		ubdp = (struct wskbd_bell_data *)data;
1047 		SETBELL(kbdp, ubdp, kbdp);
1048 		return (0);
1049 
1050 	case WSKBDIO_GETBELL:
1051 		kbdp = &sc->sc_bell_data;
1052 getbell:
1053 		ubdp = (struct wskbd_bell_data *)data;
1054 		SETBELL(ubdp, kbdp, kbdp);
1055 		return (0);
1056 
1057 	case WSKBDIO_SETDEFAULTBELL:
1058 		if ((error = suser(p)) != 0)
1059 			return (error);
1060 		kbdp = &wskbd_default_bell_data;
1061 		goto setbell;
1062 
1063 
1064 	case WSKBDIO_GETDEFAULTBELL:
1065 		kbdp = &wskbd_default_bell_data;
1066 		goto getbell;
1067 
1068 #undef SETBELL
1069 
1070 #define	SETKEYREPEAT(dstp, srcp, dfltp)					\
1071     do {								\
1072 	(dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL1) ?	\
1073 	    (srcp)->del1 : (dfltp)->del1;				\
1074 	(dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN) ?	\
1075 	    (srcp)->delN : (dfltp)->delN;				\
1076 	(dstp)->which = WSKBD_KEYREPEAT_DOALL;				\
1077     } while (0)
1078 
1079 	case WSKBDIO_SETKEYREPEAT:
1080 		kkdp = &sc->sc_keyrepeat_data;
1081 setkeyrepeat:
1082 		ukdp = (struct wskbd_keyrepeat_data *)data;
1083 		SETKEYREPEAT(kkdp, ukdp, kkdp);
1084 		return (0);
1085 
1086 	case WSKBDIO_GETKEYREPEAT:
1087 		kkdp = &sc->sc_keyrepeat_data;
1088 getkeyrepeat:
1089 		ukdp = (struct wskbd_keyrepeat_data *)data;
1090 		SETKEYREPEAT(ukdp, kkdp, kkdp);
1091 		return (0);
1092 
1093 	case WSKBDIO_SETDEFAULTKEYREPEAT:
1094 		if ((error = suser(p)) != 0)
1095 			return (error);
1096 		kkdp = &wskbd_default_keyrepeat_data;
1097 		goto setkeyrepeat;
1098 
1099 
1100 	case WSKBDIO_GETDEFAULTKEYREPEAT:
1101 		kkdp = &wskbd_default_keyrepeat_data;
1102 		goto getkeyrepeat;
1103 
1104 #undef SETKEYREPEAT
1105 
1106 	case WSKBDIO_SETMAP:
1107 		umdp = (struct wskbd_map_data *)data;
1108 		if (umdp->maplen > WSKBDIO_MAXMAPLEN)
1109 			return (EINVAL);
1110 
1111 		buf = mallocarray(umdp->maplen, sizeof(struct wscons_keymap),
1112 		    M_TEMP, M_WAITOK);
1113 		len = umdp->maplen * sizeof(struct wscons_keymap);
1114 
1115 		error = copyin(umdp->map, buf, len);
1116 		if (error == 0) {
1117 			wskbd_init_keymap(umdp->maplen,
1118 					  &sc->sc_map, &sc->sc_maplen);
1119 			memcpy(sc->sc_map, buf, len);
1120 			/* drop the variant bits handled by the map */
1121 			enc = KB_USER | (KB_VARIANT(sc->id->t_keymap.layout) &
1122 			    KB_HANDLEDBYWSKBD);
1123 			wskbd_update_layout(sc->id, enc);
1124 		}
1125 		free(buf, M_TEMP, len);
1126 		return(error);
1127 
1128 	case WSKBDIO_GETMAP:
1129 		umdp = (struct wskbd_map_data *)data;
1130 		if (umdp->maplen > sc->sc_maplen)
1131 			umdp->maplen = sc->sc_maplen;
1132 		error = copyout(sc->sc_map, umdp->map,
1133 				umdp->maplen*sizeof(struct wscons_keymap));
1134 		return(error);
1135 
1136 	case WSKBDIO_GETENCODING:
1137 		*((kbd_t *)data) = sc->id->t_keymap.layout & ~KB_DEFAULT;
1138 		return(0);
1139 
1140 	case WSKBDIO_SETENCODING:
1141 		enc = *((kbd_t *)data);
1142 		if (KB_ENCODING(enc) == KB_USER) {
1143 			/* user map must already be loaded */
1144 			if (KB_ENCODING(sc->id->t_keymap.layout) != KB_USER)
1145 				return (EINVAL);
1146 			/* map variants make no sense */
1147 			if (KB_VARIANT(enc) & ~KB_HANDLEDBYWSKBD)
1148 				return (EINVAL);
1149 		} else {
1150 			error = wskbd_load_keymap(&sc->id->t_keymap, enc,
1151 			    &sc->sc_map, &sc->sc_maplen);
1152 			if (error)
1153 				return (error);
1154 		}
1155 		wskbd_update_layout(sc->id, enc);
1156 #if NWSMUX > 0
1157 		/* Update mux default layout */
1158 		if (sc->sc_base.me_parent != NULL)
1159 			wsmux_set_layout(sc->sc_base.me_parent, enc);
1160 #endif
1161 		return (0);
1162 
1163 	case WSKBDIO_GETENCODINGS:
1164 		uedp = (struct wskbd_encoding_data *)data;
1165 		for (count = 0; sc->id->t_keymap.keydesc[count].name; count++)
1166 			;
1167 		if (uedp->nencodings > count)
1168 			uedp->nencodings = count;
1169 		for (i = 0; i < uedp->nencodings; i++) {
1170 			error = copyout(&sc->id->t_keymap.keydesc[i].name,
1171 			    &uedp->encodings[i], sizeof(kbd_t));
1172 			if (error)
1173 				return (error);
1174 		}
1175 		return (0);
1176 
1177 	case WSKBDIO_GETBACKLIGHT:
1178 		if (wskbd_get_backlight != NULL)
1179 			return (*wskbd_get_backlight)((struct wskbd_backlight *)data);
1180 		break;
1181 
1182 	case WSKBDIO_SETBACKLIGHT:
1183 		if (wskbd_set_backlight != NULL)
1184 			return (*wskbd_set_backlight)((struct wskbd_backlight *)data);
1185 		break;
1186 	}
1187 
1188 	/*
1189 	 * Try the keyboard driver for WSKBDIO ioctls.  It returns -1
1190 	 * if it didn't recognize the request, and in turn we return
1191 	 * -1 if we didn't recognize the request.
1192 	 */
1193 /* printf("kbdaccess\n"); */
1194 	error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data,
1195 					   flag, p);
1196 #ifdef WSDISPLAY_COMPAT_RAWKBD
1197 	if (!error && cmd == WSKBDIO_SETMODE && *(int *)data == WSKBD_RAW) {
1198 		int s = spltty();
1199 		sc->id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R
1200 					 | MOD_CONTROL_L | MOD_CONTROL_R
1201 					 | MOD_META_L | MOD_META_R
1202 					 | MOD_COMMAND
1203 					 | MOD_COMMAND1 | MOD_COMMAND2);
1204 #if NWSDISPLAY > 0
1205 		if (sc->sc_repeating) {
1206 			sc->sc_repeating = 0;
1207 			timeout_del(&sc->sc_repeat_ch);
1208 		}
1209 #endif
1210 		splx(s);
1211 	}
1212 #endif
1213 	return (error);
1214 }
1215 
1216 int
1217 wskbdpoll(dev_t dev, int events, struct proc *p)
1218 {
1219 	struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
1220 
1221 	if (sc->sc_base.me_evp == NULL)
1222 		return (POLLERR);
1223 	return (wsevent_poll(sc->sc_base.me_evp, events, p));
1224 }
1225 
1226 int
1227 wskbdkqfilter(dev_t dev, struct knote *kn)
1228 {
1229 	struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
1230 
1231 	if (sc->sc_base.me_evp == NULL)
1232 		return (ENXIO);
1233 	return (wsevent_kqfilter(sc->sc_base.me_evp, kn));
1234 }
1235 
1236 #if NWSDISPLAY > 0
1237 
1238 int
1239 wskbd_pickfree(void)
1240 {
1241 	int i;
1242 	struct wskbd_softc *sc;
1243 
1244 	for (i = 0; i < wskbd_cd.cd_ndevs; i++) {
1245 		if ((sc = wskbd_cd.cd_devs[i]) == NULL)
1246 			continue;
1247 		if (sc->sc_displaydv == NULL)
1248 			return (i);
1249 	}
1250 	return (-1);
1251 }
1252 
1253 struct wsevsrc *
1254 wskbd_set_console_display(struct device *displaydv, struct wsevsrc *me)
1255 {
1256 	struct wskbd_softc *sc = wskbd_console_device;
1257 
1258 	if (sc == NULL)
1259 		return (NULL);
1260 	sc->sc_displaydv = displaydv;
1261 #if NWSMUX > 0
1262 	(void)wsmux_attach_sc((struct wsmux_softc *)me, &sc->sc_base);
1263 #endif
1264 	return (&sc->sc_base);
1265 }
1266 
1267 int
1268 wskbd_set_display(struct device *dv, struct device *displaydv)
1269 {
1270 	struct wskbd_softc *sc = (struct wskbd_softc *)dv;
1271 	struct device *odisplaydv;
1272 	int error;
1273 
1274 	DPRINTF(("%s: %s odisp=%p disp=%p cons=%d\n", __func__,
1275 		 dv->dv_xname, sc->sc_displaydv, displaydv,
1276 		 sc->sc_isconsole));
1277 
1278 	if (sc->sc_isconsole)
1279 		return (EBUSY);
1280 
1281 	if (displaydv != NULL) {
1282 		if (sc->sc_displaydv != NULL)
1283 			return (EBUSY);
1284 	} else {
1285 		if (sc->sc_displaydv == NULL)
1286 			return (ENXIO);
1287 	}
1288 
1289 	odisplaydv = sc->sc_displaydv;
1290 	sc->sc_displaydv = NULL;
1291 	error = wskbd_enable(sc, displaydv != NULL);
1292 	sc->sc_displaydv = displaydv;
1293 	if (error) {
1294 		sc->sc_displaydv = odisplaydv;
1295 		return (error);
1296 	}
1297 
1298 	if (displaydv)
1299 		printf("%s: connecting to %s\n",
1300 		       sc->sc_base.me_dv.dv_xname, displaydv->dv_xname);
1301 	else
1302 		printf("%s: disconnecting from %s\n",
1303 		       sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname);
1304 
1305 	return (0);
1306 }
1307 
1308 #endif	/* NWSDISPLAY > 0 */
1309 
1310 #if NWSMUX > 0
1311 int
1312 wskbd_add_mux(int unit, struct wsmux_softc *muxsc)
1313 {
1314 	struct wskbd_softc *sc;
1315 
1316 	if (unit < 0 || unit >= wskbd_cd.cd_ndevs ||
1317 	    (sc = wskbd_cd.cd_devs[unit]) == NULL)
1318 		return (ENXIO);
1319 
1320 	if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL)
1321 		return (EBUSY);
1322 
1323 	return (wsmux_attach_sc(muxsc, &sc->sc_base));
1324 }
1325 #endif
1326 
1327 /*
1328  * Console interface.
1329  */
1330 int
1331 wskbd_cngetc(dev_t dev)
1332 {
1333 	static int num = 0;
1334 	static int pos;
1335 	u_int type;
1336 	int data;
1337 	keysym_t ks;
1338 
1339 	if (!wskbd_console_initted)
1340 		return 0;
1341 
1342 	if (wskbd_console_device != NULL &&
1343 	    !wskbd_console_device->sc_translating)
1344 		return 0;
1345 
1346 	for(;;) {
1347 		if (num-- > 0) {
1348 			ks = wskbd_console_data.t_symbols[pos++];
1349 			if (KS_GROUP(ks) == KS_GROUP_Ascii)
1350 				return (KS_VALUE(ks));
1351 		} else {
1352 			(*wskbd_console_data.t_consops->getc)
1353 				(wskbd_console_data.t_consaccesscookie,
1354 				 &type, &data);
1355 			num = wskbd_translate(&wskbd_console_data, type, data);
1356 			pos = 0;
1357 		}
1358 	}
1359 }
1360 
1361 void
1362 wskbd_cnpollc(dev_t dev, int poll)
1363 {
1364 	if (!wskbd_console_initted)
1365 		return;
1366 
1367 	if (wskbd_console_device != NULL &&
1368 	    !wskbd_console_device->sc_translating)
1369 		return;
1370 
1371 	(*wskbd_console_data.t_consops->pollc)
1372 	    (wskbd_console_data.t_consaccesscookie, poll);
1373 }
1374 
1375 void
1376 wskbd_cnbell(dev_t dev, u_int pitch, u_int period, u_int volume)
1377 {
1378 	if (!wskbd_console_initted)
1379 		return;
1380 
1381 	if (wskbd_console_data.t_consops->bell != NULL)
1382 		(*wskbd_console_data.t_consops->bell)
1383 		    (wskbd_console_data.t_consaccesscookie, pitch, period,
1384 			volume);
1385 }
1386 
1387 void
1388 update_leds(struct wskbd_internal *id)
1389 {
1390 	int new_state;
1391 
1392 	new_state = 0;
1393 	if (id->t_modifiers & (MOD_SHIFTLOCK | MOD_CAPSLOCK))
1394 		new_state |= WSKBD_LED_CAPS;
1395 	if (id->t_modifiers & MOD_NUMLOCK)
1396 		new_state |= WSKBD_LED_NUM;
1397 	if (id->t_modifiers & MOD_COMPOSE)
1398 		new_state |= WSKBD_LED_COMPOSE;
1399 	if (id->t_modifiers & MOD_HOLDSCREEN)
1400 		new_state |= WSKBD_LED_SCROLL;
1401 
1402 	if (id->t_sc && new_state != id->t_sc->sc_ledstate) {
1403 		(*id->t_sc->sc_accessops->set_leds)
1404 		    (id->t_sc->sc_accesscookie, new_state);
1405 		id->t_sc->sc_ledstate = new_state;
1406 	}
1407 }
1408 
1409 void
1410 update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask)
1411 {
1412 	if (toggle) {
1413 		if (type == WSCONS_EVENT_KEY_DOWN)
1414 			id->t_modifiers ^= mask;
1415 	} else {
1416 		if (type == WSCONS_EVENT_KEY_DOWN)
1417 			id->t_modifiers |= mask;
1418 		else
1419 			id->t_modifiers &= ~mask;
1420 	}
1421 	if (mask & MOD_ANYLED)
1422 		update_leds(id);
1423 }
1424 
1425 #if NWSDISPLAY > 0
1426 void
1427 change_displayparam(struct wskbd_softc *sc, int param, int updown,
1428     int wraparound)
1429 {
1430 	int res;
1431 	struct wsdisplay_param dp;
1432 
1433 	dp.param = param;
1434 	res = wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_GETPARAM, &dp);
1435 
1436 	if (res == EINVAL)
1437 		return; /* no such parameter */
1438 
1439 	dp.curval += updown;
1440 	if (dp.max < dp.curval)
1441 		dp.curval = wraparound ? dp.min : dp.max;
1442 	else
1443 	if (dp.curval < dp.min)
1444 		dp.curval = wraparound ? dp.max : dp.min;
1445 	wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_SETPARAM, &dp);
1446 }
1447 #endif
1448 
1449 int
1450 internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym,
1451     keysym_t ksym2)
1452 {
1453 	switch (ksym) {
1454 	case KS_Cmd:
1455 		update_modifier(sc->id, *type, 0, MOD_COMMAND);
1456 		ksym = ksym2;
1457 		break;
1458 
1459 	case KS_Cmd1:
1460 		update_modifier(sc->id, *type, 0, MOD_COMMAND1);
1461 		break;
1462 
1463 	case KS_Cmd2:
1464 		update_modifier(sc->id, *type, 0, MOD_COMMAND2);
1465 		break;
1466 	}
1467 
1468 	if (*type != WSCONS_EVENT_KEY_DOWN)
1469 		return (0);
1470 
1471 #ifdef HAVE_SCROLLBACK_SUPPORT
1472 #if NWSDISPLAY > 0
1473 	switch (ksym) {
1474 	case KS_Cmd_ScrollBack:
1475 		if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) {
1476 			if (sc->sc_displaydv != NULL)
1477 				wsscrollback(sc->sc_displaydv,
1478 				    WSDISPLAY_SCROLL_BACKWARD);
1479 			return (1);
1480 		}
1481 		break;
1482 
1483 	case KS_Cmd_ScrollFwd:
1484 		if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) {
1485 			if (sc->sc_displaydv != NULL)
1486 				wsscrollback(sc->sc_displaydv,
1487 				    WSDISPLAY_SCROLL_FORWARD);
1488 			return (1);
1489 		}
1490 		break;
1491 	}
1492 #endif
1493 #endif
1494 
1495 	if (!MOD_ONESET(sc->id, MOD_COMMAND) &&
1496 	    !MOD_ALLSET(sc->id, MOD_COMMAND1 | MOD_COMMAND2))
1497 		return (0);
1498 
1499 #ifdef DDB
1500 	if (ksym == KS_Cmd_Debugger) {
1501 		wskbd_debugger(sc);
1502 		/* discard this key (ddb discarded command modifiers) */
1503 		*type = WSCONS_EVENT_KEY_UP;
1504 		return (1);
1505 	}
1506 #endif
1507 
1508 #if NWSDISPLAY > 0
1509 	if (sc->sc_displaydv == NULL)
1510 		return (0);
1511 
1512 	switch (ksym) {
1513 	case KS_Cmd_Screen0:
1514 	case KS_Cmd_Screen1:
1515 	case KS_Cmd_Screen2:
1516 	case KS_Cmd_Screen3:
1517 	case KS_Cmd_Screen4:
1518 	case KS_Cmd_Screen5:
1519 	case KS_Cmd_Screen6:
1520 	case KS_Cmd_Screen7:
1521 	case KS_Cmd_Screen8:
1522 	case KS_Cmd_Screen9:
1523 	case KS_Cmd_Screen10:
1524 	case KS_Cmd_Screen11:
1525 		wsdisplay_switch(sc->sc_displaydv, ksym - KS_Cmd_Screen0, 0);
1526 		return (1);
1527 	case KS_Cmd_ResetEmul:
1528 		wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL);
1529 		return (1);
1530 	case KS_Cmd_ResetClose:
1531 		wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE);
1532 		return (1);
1533 #if defined(__i386__) || defined(__amd64__)
1534 	case KS_Cmd_KbdReset:
1535 		switch (kbd_reset) {
1536 #ifdef DDB
1537 		case 2:
1538 			wskbd_debugger(sc);
1539 			/* discard this key (ddb discarded command modifiers) */
1540 			*type = WSCONS_EVENT_KEY_UP;
1541 			break;
1542 #endif
1543 		case 1:
1544 			kbd_reset = 0;
1545 			prsignal(initprocess, SIGUSR1);
1546 			break;
1547 		default:
1548 			break;
1549 		}
1550 		return (1);
1551 #endif
1552 	case KS_Cmd_BacklightOn:
1553 	case KS_Cmd_BacklightOff:
1554 	case KS_Cmd_BacklightToggle:
1555 		change_displayparam(sc, WSDISPLAYIO_PARAM_BACKLIGHT,
1556 		    ksym == KS_Cmd_BacklightOff ? -1 : 1,
1557 		    ksym == KS_Cmd_BacklightToggle ? 1 : 0);
1558 		return (1);
1559 	case KS_Cmd_BrightnessUp:
1560 		wsdisplay_brightness_step(sc->sc_displaydv, 1);
1561 		return (1);
1562 	case KS_Cmd_BrightnessDown:
1563 		wsdisplay_brightness_step(sc->sc_displaydv, -1);
1564 		return (1);
1565 	case KS_Cmd_BrightnessRotate:
1566 		wsdisplay_brightness_cycle(sc->sc_displaydv);
1567 		return (1);
1568 	case KS_Cmd_ContrastUp:
1569 	case KS_Cmd_ContrastDown:
1570 	case KS_Cmd_ContrastRotate:
1571 		change_displayparam(sc, WSDISPLAYIO_PARAM_CONTRAST,
1572 		    ksym == KS_Cmd_ContrastDown ? -1 : 1,
1573 		    ksym == KS_Cmd_ContrastRotate ? 1 : 0);
1574 		return (1);
1575 	}
1576 #endif
1577 	return (0);
1578 }
1579 
1580 int
1581 wskbd_translate(struct wskbd_internal *id, u_int type, int value)
1582 {
1583 	struct wskbd_softc *sc = id->t_sc;
1584 	keysym_t ksym, res, *group;
1585 	struct wscons_keymap kpbuf, *kp;
1586 	int gindex, iscommand = 0;
1587 
1588 	if (type == WSCONS_EVENT_ALL_KEYS_UP) {
1589 #if NWSDISPLAY > 0
1590 		if (sc != NULL && sc->sc_repeating) {
1591 			sc->sc_repeating = 0;
1592 			timeout_del(&sc->sc_repeat_ch);
1593 		}
1594 #endif
1595 		id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R |
1596 		    MOD_CONTROL_L | MOD_CONTROL_R |
1597 		    MOD_META_L | MOD_META_R |
1598 		    MOD_MODESHIFT | MOD_MODELOCK |
1599 		    MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2);
1600 		return (0);
1601 	}
1602 
1603 	if (sc != NULL) {
1604 		if (value < 0 || value >= sc->sc_maplen) {
1605 #ifdef DEBUG
1606 			printf("wskbd_translate: keycode %d out of range\n",
1607 			       value);
1608 #endif
1609 			return (0);
1610 		}
1611 		kp = sc->sc_map + value;
1612 	} else {
1613 		kp = &kpbuf;
1614 		wskbd_get_mapentry(&id->t_keymap, value, kp);
1615 	}
1616 
1617 	/* if this key has a command, process it first */
1618 	if (sc != NULL && kp->command != KS_voidSymbol)
1619 		iscommand = internal_command(sc, &type, kp->command,
1620 		    kp->group1[0]);
1621 
1622 	/* Now update modifiers */
1623 	switch (kp->group1[0]) {
1624 	case KS_Shift_L:
1625 		update_modifier(id, type, 0, MOD_SHIFT_L);
1626 		break;
1627 
1628 	case KS_Shift_R:
1629 		update_modifier(id, type, 0, MOD_SHIFT_R);
1630 		break;
1631 
1632 	case KS_Shift_Lock:
1633 		update_modifier(id, type, 1, MOD_SHIFTLOCK);
1634 		break;
1635 
1636 	case KS_Caps_Lock:
1637 		update_modifier(id, type, 1, MOD_CAPSLOCK);
1638 		break;
1639 
1640 	case KS_Control_L:
1641 		update_modifier(id, type, 0, MOD_CONTROL_L);
1642 		break;
1643 
1644 	case KS_Control_R:
1645 		update_modifier(id, type, 0, MOD_CONTROL_R);
1646 		break;
1647 
1648 	case KS_Alt_L:
1649 		update_modifier(id, type, 0, MOD_META_L);
1650 		break;
1651 
1652 	case KS_Alt_R:
1653 		update_modifier(id, type, 0, MOD_META_R);
1654 		break;
1655 
1656 	case KS_Mode_switch:
1657 		update_modifier(id, type, 0, MOD_MODESHIFT);
1658 		break;
1659 
1660 	case KS_Mode_Lock:
1661 		update_modifier(id, type, 1, MOD_MODELOCK);
1662 		break;
1663 
1664 	case KS_Num_Lock:
1665 		update_modifier(id, type, 1, MOD_NUMLOCK);
1666 		break;
1667 
1668 #if NWSDISPLAY > 0
1669 	case KS_Hold_Screen:
1670 		if (sc != NULL) {
1671 			update_modifier(id, type, 1, MOD_HOLDSCREEN);
1672 			if (sc->sc_displaydv != NULL)
1673 				wsdisplay_kbdholdscreen(sc->sc_displaydv,
1674 				    id->t_modifiers & MOD_HOLDSCREEN);
1675 		}
1676 		break;
1677 
1678 	default:
1679 		if (sc != NULL && sc->sc_repeating &&
1680 		    ((type == WSCONS_EVENT_KEY_UP && value != sc->sc_repkey) ||
1681 		     (type == WSCONS_EVENT_KEY_DOWN && value == sc->sc_repkey)))
1682 			return (0);
1683 		break;
1684 #endif
1685 	}
1686 
1687 #if NWSDISPLAY > 0
1688 	if (sc != NULL) {
1689 		if (sc->sc_repeating) {
1690 			sc->sc_repeating = 0;
1691 			timeout_del(&sc->sc_repeat_ch);
1692 		}
1693 		sc->sc_repkey = value;
1694 	}
1695 #endif
1696 
1697 	/* If this is a key release or we are in command mode, we are done */
1698 	if (type != WSCONS_EVENT_KEY_DOWN || iscommand)
1699 		return (0);
1700 
1701 	/* Get the keysym */
1702 	if (id->t_modifiers & (MOD_MODESHIFT|MOD_MODELOCK) &&
1703 	    !MOD_ONESET(id, MOD_ANYCONTROL))
1704 		group = & kp->group2[0];
1705 	else
1706 		group = & kp->group1[0];
1707 
1708 	if ((id->t_modifiers & MOD_NUMLOCK) &&
1709 	    KS_GROUP(group[1]) == KS_GROUP_Keypad) {
1710 		gindex = !MOD_ONESET(id, MOD_ANYSHIFT);
1711 		ksym = group[gindex];
1712 	} else {
1713 		/* CAPS alone should only affect letter keys */
1714 		if ((id->t_modifiers & (MOD_CAPSLOCK | MOD_ANYSHIFT)) ==
1715 		    MOD_CAPSLOCK) {
1716 			gindex = 0;
1717 			ksym = ksym_upcase(group[0]);
1718 		} else {
1719 			gindex = MOD_ONESET(id, MOD_ANYSHIFT);
1720 			ksym = group[gindex];
1721 		}
1722 	}
1723 
1724 	/* Submit Audio keys for hotkey processing */
1725 	if (KS_GROUP(ksym) == KS_GROUP_Function) {
1726 		switch (ksym) {
1727 #if NAUDIO > 0
1728 		case KS_AudioMute:
1729 			wskbd_set_mixervolume(0, 1);
1730 			return (0);
1731 		case KS_AudioLower:
1732 			wskbd_set_mixervolume(-1, 1);
1733 			return (0);
1734 		case KS_AudioRaise:
1735 			wskbd_set_mixervolume(1, 1);
1736 			return (0);
1737 #endif
1738 		default:
1739 			break;
1740 		}
1741 	}
1742 
1743 	/* Process compose sequence and dead accents */
1744 	res = KS_voidSymbol;
1745 
1746 	switch (KS_GROUP(ksym)) {
1747 	case KS_GROUP_Ascii:
1748 	case KS_GROUP_Keypad:
1749 	case KS_GROUP_Function:
1750 		res = ksym;
1751 		break;
1752 
1753 	case KS_GROUP_Mod:
1754 		if (ksym == KS_Multi_key) {
1755 			update_modifier(id, 1, 0, MOD_COMPOSE);
1756 			id->t_composelen = 2;
1757 		}
1758 		break;
1759 
1760 	case KS_GROUP_Dead:
1761 		if (id->t_composelen == 0) {
1762 			update_modifier(id, 1, 0, MOD_COMPOSE);
1763 			id->t_composelen = 1;
1764 			id->t_composebuf[0] = ksym;
1765 		} else
1766 			res = ksym;
1767 		break;
1768 	}
1769 
1770 	if (res == KS_voidSymbol)
1771 		return (0);
1772 
1773 	if (id->t_composelen > 0) {
1774 		/*
1775 		 * If the compose key also serves as AltGr (i.e. set to both
1776 		 * KS_Multi_key and KS_Mode_switch), and would provide a valid,
1777 		 * distinct combination as AltGr, leave compose mode.
1778 	 	 */
1779 		if (id->t_composelen == 2 && group == &kp->group2[0]) {
1780 			if (kp->group1[gindex] != kp->group2[gindex])
1781 				id->t_composelen = 0;
1782 		}
1783 
1784 		if (id->t_composelen != 0) {
1785 			id->t_composebuf[2 - id->t_composelen] = res;
1786 			if (--id->t_composelen == 0) {
1787 				res = wskbd_compose_value(id->t_composebuf);
1788 				update_modifier(id, 0, 0, MOD_COMPOSE);
1789 			} else {
1790 				return (0);
1791 			}
1792 		}
1793 	}
1794 
1795 	/* We are done, return the symbol */
1796 	if (KS_GROUP(res) == KS_GROUP_Ascii) {
1797 		if (MOD_ONESET(id, MOD_ANYCONTROL)) {
1798 			if ((res >= KS_at && res <= KS_z) || res == KS_space)
1799 				res = res & 0x1f;
1800 			else if (res == KS_2)
1801 				res = 0x00;
1802 			else if (res >= KS_3 && res <= KS_7)
1803 				res = KS_Escape + (res - KS_3);
1804 			else if (res == KS_8)
1805 				res = KS_Delete;
1806 		}
1807 		if (MOD_ONESET(id, MOD_ANYMETA)) {
1808 			if (id->t_flags & WSKFL_METAESC) {
1809 				id->t_symbols[0] = KS_Escape;
1810 				id->t_symbols[1] = res;
1811 				return (2);
1812 			} else
1813 				res |= 0x80;
1814 		}
1815 	}
1816 
1817 	id->t_symbols[0] = res;
1818 	return (1);
1819 }
1820 
1821 void
1822 wskbd_debugger(struct wskbd_softc *sc)
1823 {
1824 #ifdef DDB
1825 	if (sc->sc_isconsole && db_console) {
1826 		if (sc->id->t_consops->debugger != NULL) {
1827 			(*sc->id->t_consops->debugger)
1828 				(sc->id->t_consaccesscookie);
1829 		} else
1830 			db_enter();
1831 	}
1832 #endif
1833 }
1834