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