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