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