xref: /dflybsd-src/sys/dev/misc/kbdmux/kbdmux.c (revision d43f76154bdfa1deafd46a37dc2310fcaa67b11c)
1 /*
2  * kbdmux.c
3  */
4 
5 /*-
6  * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
31  * $FreeBSD$
32  */
33 
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/conf.h>
37 #include <sys/consio.h>
38 #include <sys/fcntl.h>
39 #include <sys/kbio.h>
40 #include <sys/kernel.h>
41 #include <sys/limits.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/module.h>
45 #include <sys/mutex.h>
46 #include <sys/poll.h>
47 #include <sys/proc.h>
48 #include <sys/queue.h>
49 #include <sys/selinfo.h>
50 #include <sys/systm.h>
51 #include <sys/taskqueue.h>
52 #include <sys/uio.h>
53 #include <dev/misc/kbd/kbdreg.h>
54 #include <dev/misc/kbd/kbdtables.h>
55 
56 #define KEYBOARD_NAME	"kbdmux"
57 
58 MALLOC_DECLARE(M_KBDMUX);
59 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
60 
61 /*****************************************************************************
62  *****************************************************************************
63  **                             Keyboard state
64  *****************************************************************************
65  *****************************************************************************/
66 
67 #define	KBDMUX_Q_SIZE	512	/* input queue size */
68 
69 /*
70  * XXX
71  * For now rely on Giant mutex to protect our data structures.
72  * Just like the rest of keyboard drivers and syscons(4) do.
73  * Note that callout is initialized as not MP-safe to make sure
74  * Giant is held.
75  * XXX: I don't think we are MP-Safing the callout, maybe we
76  *      should, using get_mplock() around it? NFI
77  */
78 
79 #if 0 /* not yet */
80 #error "This stuff still needs porting!"
81 #define KBDMUX_LOCK_DECL_GLOBAL \
82 	struct mtx ks_lock
83 #define KBDMUX_LOCK_INIT(s) \
84 	mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
85 #define KBDMUX_LOCK_DESTROY(s) \
86 	mtx_destroy(&(s)->ks_lock)
87 #define KBDMUX_LOCK(s) \
88 	mtx_lock(&(s)->ks_lock)
89 #define KBDMUX_UNLOCK(s) \
90 	mtx_unlock(&(s)->ks_lock)
91 #define KBDMUX_LOCK_ASSERT(s, w) \
92 	mtx_assert(&(s)->ks_lock, (w))
93 #define KBDMUX_SLEEP(s, f, d, t) \
94 	msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
95 #define KBDMUX_CALLOUT_INIT(s) \
96 	callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
97 #define KBDMUX_QUEUE_INTR(s) \
98 	taskqueue_enqueue(taskqueue_swi, &(s)->ks_task)
99 #else
100 #define KBDMUX_LOCK_DECL_GLOBAL
101 
102 #define KBDMUX_LOCK_INIT(s)
103 
104 #define KBDMUX_LOCK_DESTROY(s)
105 
106 #define KBDMUX_LOCK(s)
107 
108 #define KBDMUX_UNLOCK(s)
109 
110 #define KBDMUX_LOCK_ASSERT(s, w)
111 
112 #define KBDMUX_SLEEP(s, f, d, t) \
113 	tsleep(&(s)->f, PCATCH | (84 + 1), (d), (t))
114 #define KBDMUX_CALLOUT_INIT(s) \
115 	callout_init(&(s)->ks_timo)
116 #define KBDMUX_QUEUE_INTR(s) \
117 	taskqueue_enqueue(taskqueue_swi, &(s)->ks_task)
118 #endif /* not yet */
119 
120 /*
121  * kbdmux keyboard
122  */
123 struct kbdmux_kbd
124 {
125 	keyboard_t		*kbd;	/* keyboard */
126 	SLIST_ENTRY(kbdmux_kbd)	 next;	/* link to next */
127 };
128 
129 typedef struct kbdmux_kbd	kbdmux_kbd_t;
130 
131 /*
132  * kbdmux state
133  */
134 struct kbdmux_state
135 {
136 	char			 ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
137 	unsigned int		 ks_inq_start;
138 	unsigned int		 ks_inq_length;
139 	struct task		 ks_task;	/* interrupt task */
140 	struct callout		 ks_timo;	/* timeout handler */
141 #define TICKS			(hz)		/* rate */
142 
143 	int			 ks_flags;	/* flags */
144 #define COMPOSE			(1 << 0)	/* compose char flag */
145 #define POLLING			(1 << 1)	/* polling */
146 #define TASK			(1 << 2)	/* interrupt task queued */
147 
148 	int			 ks_mode;	/* K_XLATE, K_RAW, K_CODE */
149 	int			 ks_state;	/* state */
150 	int			 ks_accents;	/* accent key index (> 0) */
151 	u_int			 ks_composed_char; /* composed char code */
152 	u_char			 ks_prefix;	/* AT scan code prefix */
153 
154 	SLIST_HEAD(, kbdmux_kbd) ks_kbds;	/* keyboards */
155 
156 	KBDMUX_LOCK_DECL_GLOBAL;
157 };
158 
159 typedef struct kbdmux_state	kbdmux_state_t;
160 
161 /*****************************************************************************
162  *****************************************************************************
163  **                             Helper functions
164  *****************************************************************************
165  *****************************************************************************/
166 
167 static task_fn_t		kbdmux_kbd_intr;
168 static timeout_t		kbdmux_kbd_intr_timo;
169 static kbd_callback_func_t	kbdmux_kbd_event;
170 
171 static void
172 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
173 {
174 	unsigned int p;
175 
176 	if (state->ks_inq_length == KBDMUX_Q_SIZE)
177 		return;
178 
179 	p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
180 	state->ks_inq[p] = c;
181 	state->ks_inq_length++;
182 }
183 
184 static int
185 kbdmux_kbd_getc(kbdmux_state_t *state)
186 {
187 	unsigned char c;
188 
189 	if (state->ks_inq_length == 0)
190 		return (-1);
191 
192 	c = state->ks_inq[state->ks_inq_start];
193 	state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
194 	state->ks_inq_length--;
195 
196 	return (c);
197 }
198 
199 /*
200  * Interrupt handler task
201  */
202 void
203 kbdmux_kbd_intr(void *xkbd, int pending)
204 {
205 	keyboard_t	*kbd = (keyboard_t *) xkbd;
206 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
207 
208 	kbd_intr(kbd, NULL);
209 
210 	KBDMUX_LOCK(state);
211 
212 	state->ks_flags &= ~TASK;
213 	wakeup(&state->ks_task);
214 
215 	KBDMUX_UNLOCK(state);
216 }
217 
218 /*
219  * Schedule interrupt handler on timeout. Called with locked state.
220  */
221 void
222 kbdmux_kbd_intr_timo(void *xstate)
223 {
224 	kbdmux_state_t	*state = (kbdmux_state_t *) xstate;
225 
226 	KBDMUX_LOCK_ASSERT(state, MA_OWNED);
227 
228 	if (callout_pending(&state->ks_timo))
229 		return; /* callout was reset */
230 
231 	if (!callout_active(&state->ks_timo))
232 		return; /* callout was stopped */
233 
234 	callout_deactivate(&state->ks_timo);
235 
236 	/* queue interrupt task if needed */
237 	if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
238 	    KBDMUX_QUEUE_INTR(state) == 0)
239 		state->ks_flags |= TASK;
240 
241 	/* re-schedule timeout */
242 	callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
243 }
244 
245 /*
246  * Process event from one of our keyboards
247  */
248 static int
249 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
250 {
251 	kbdmux_state_t	*state = (kbdmux_state_t *) arg;
252 
253 	switch (event) {
254 	case KBDIO_KEYINPUT: {
255 		int	c;
256 
257 		KBDMUX_LOCK(state);
258 
259 		/*
260 		 * Read all chars from the keyboard
261 		 *
262 		 * Turns out that atkbd(4) check_char() method may return
263 		 * "true" while read_char() method returns NOKEY. If this
264 		 * happens we could stuck in the loop below. Avoid this
265 		 * by breaking out of the loop if read_char() method returns
266 		 * NOKEY.
267 		 */
268 
269 		while (kbd_check_char(kbd)) {
270 			c = kbd_read_char(kbd, 0);
271 			if (c == NOKEY)
272 				break;
273 			if (c == ERRKEY)
274 				continue; /* XXX ring bell */
275 			if (!KBD_IS_BUSY(kbd))
276 				continue; /* not open - discard the input */
277 
278 			kbdmux_kbd_putc(state, c);
279 		}
280 
281 		/* queue interrupt task if needed */
282 		if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
283 		    KBDMUX_QUEUE_INTR(state) == 0)
284 			state->ks_flags |= TASK;
285 
286 		KBDMUX_UNLOCK(state);
287 		} break;
288 
289 	case KBDIO_UNLOADING: {
290 		kbdmux_kbd_t	*k;
291 
292 		KBDMUX_LOCK(state);
293 
294 		SLIST_FOREACH(k, &state->ks_kbds, next)
295 			if (k->kbd == kbd)
296 				break;
297 
298 		if (k != NULL) {
299 			kbd_release(k->kbd, &k->kbd);
300 			SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
301 
302 			k->kbd = NULL;
303 
304 			kfree(k, M_KBDMUX);
305 		}
306 
307 		KBDMUX_UNLOCK(state);
308 		} break;
309 
310 	default:
311 		return (EINVAL);
312 		/* NOT REACHED */
313 	}
314 
315 	return (0);
316 }
317 
318 /****************************************************************************
319  ****************************************************************************
320  **                              Keyboard driver
321  ****************************************************************************
322  ****************************************************************************/
323 
324 static int		kbdmux_configure(int flags);
325 static kbd_probe_t	kbdmux_probe;
326 static kbd_init_t	kbdmux_init;
327 static kbd_term_t	kbdmux_term;
328 static kbd_intr_t	kbdmux_intr;
329 static kbd_test_if_t	kbdmux_test_if;
330 static kbd_enable_t	kbdmux_enable;
331 static kbd_disable_t	kbdmux_disable;
332 static kbd_read_t	kbdmux_read;
333 static kbd_check_t	kbdmux_check;
334 static kbd_read_char_t	kbdmux_read_char;
335 static kbd_check_char_t	kbdmux_check_char;
336 static kbd_ioctl_t	kbdmux_ioctl;
337 static kbd_lock_t	kbdmux_lock;
338 static void		kbdmux_clear_state_locked(kbdmux_state_t *state);
339 static kbd_clear_state_t kbdmux_clear_state;
340 static kbd_get_state_t	kbdmux_get_state;
341 static kbd_set_state_t	kbdmux_set_state;
342 static kbd_poll_mode_t	kbdmux_poll;
343 
344 static keyboard_switch_t kbdmuxsw = {
345 	.probe =	kbdmux_probe,
346 	.init =		kbdmux_init,
347 	.term =		kbdmux_term,
348 	.intr =		kbdmux_intr,
349 	.test_if =	kbdmux_test_if,
350 	.enable =	kbdmux_enable,
351 	.disable =	kbdmux_disable,
352 	.read =		kbdmux_read,
353 	.check =	kbdmux_check,
354 	.read_char =	kbdmux_read_char,
355 	.check_char =	kbdmux_check_char,
356 	.ioctl =	kbdmux_ioctl,
357 	.lock =		kbdmux_lock,
358 	.clear_state =	kbdmux_clear_state,
359 	.get_state =	kbdmux_get_state,
360 	.set_state =	kbdmux_set_state,
361 	.get_fkeystr =	genkbd_get_fkeystr,
362 	.poll =		kbdmux_poll,
363 	.diag =		genkbd_diag,
364 };
365 
366 /*
367  * Return the number of found keyboards
368  */
369 static int
370 kbdmux_configure(int flags)
371 {
372 	return (1);
373 }
374 
375 /*
376  * Detect a keyboard
377  */
378 static int
379 kbdmux_probe(int unit, void *arg, int flags)
380 {
381 	if (resource_disabled(KEYBOARD_NAME, unit))
382 		return (ENXIO);
383 
384 	return (0);
385 }
386 
387 /*
388  * Reset and initialize the keyboard (stolen from atkbd.c)
389  */
390 static int
391 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
392 {
393 	keyboard_t	*kbd = NULL;
394 	kbdmux_state_t	*state = NULL;
395 	keymap_t	*keymap = NULL;
396         accentmap_t	*accmap = NULL;
397         fkeytab_t	*fkeymap = NULL;
398 	int		 error, needfree, fkeymap_size, delay[2];
399 
400 	if (*kbdp == NULL) {
401 		*kbdp = kbd = kmalloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
402 		state = kmalloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
403 		keymap = kmalloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
404 		accmap = kmalloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
405 		fkeymap = kmalloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
406 		fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
407 		needfree = 1;
408 
409 		if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
410 		    (accmap == NULL) || (fkeymap == NULL)) {
411 			error = ENOMEM;
412 			goto bad;
413 		}
414 
415 		KBDMUX_LOCK_INIT(state);
416 		TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
417 		KBDMUX_CALLOUT_INIT(state);
418 		SLIST_INIT(&state->ks_kbds);
419 	} else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
420 		return (0);
421 	} else {
422 		kbd = *kbdp;
423 		state = (kbdmux_state_t *) kbd->kb_data;
424 		keymap = kbd->kb_keymap;
425 		accmap = kbd->kb_accentmap;
426 		fkeymap = kbd->kb_fkeytab;
427 		fkeymap_size = kbd->kb_fkeytab_size;
428 		needfree = 0;
429 	}
430 
431 	if (!KBD_IS_PROBED(kbd)) {
432 		/* XXX assume 101/102 keys keyboard */
433 		kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags,
434 			    KB_PRI_MUX, 0, 0);
435 		bcopy(&key_map, keymap, sizeof(key_map));
436 		bcopy(&accent_map, accmap, sizeof(accent_map));
437 		bcopy(fkey_tab, fkeymap,
438 			imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
439 		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
440 		kbd->kb_data = (void *)state;
441 
442 		KBD_FOUND_DEVICE(kbd);
443 		KBD_PROBE_DONE(kbd);
444 
445 		KBDMUX_LOCK(state);
446 		kbdmux_clear_state_locked(state);
447 		state->ks_mode = K_XLATE;
448 		KBDMUX_UNLOCK(state);
449 	}
450 
451 	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
452 		kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
453 
454 		kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
455 
456 		delay[0] = kbd->kb_delay1;
457 		delay[1] = kbd->kb_delay2;
458 		kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
459 
460 		KBD_INIT_DONE(kbd);
461 	}
462 
463 	if (!KBD_IS_CONFIGURED(kbd)) {
464 		if (kbd_register(kbd) < 0) {
465 			error = ENXIO;
466 			goto bad;
467 		}
468 
469 		KBD_CONFIG_DONE(kbd);
470 
471 		KBDMUX_LOCK(state);
472 		callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
473 		KBDMUX_UNLOCK(state);
474 	}
475 
476 	return (0);
477 bad:
478 	if (needfree) {
479 		if (state != NULL)
480 			kfree(state, M_KBDMUX);
481 		if (keymap != NULL)
482 			kfree(keymap, M_KBDMUX);
483 		if (accmap != NULL)
484 			kfree(accmap, M_KBDMUX);
485 		if (fkeymap != NULL)
486 			kfree(fkeymap, M_KBDMUX);
487 		if (kbd != NULL) {
488 			kfree(kbd, M_KBDMUX);
489 			*kbdp = NULL;	/* insure ref doesn't leak to caller */
490 		}
491 	}
492 
493 	return (error);
494 }
495 
496 /*
497  * Finish using this keyboard
498  */
499 static int
500 kbdmux_term(keyboard_t *kbd)
501 {
502 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
503 	kbdmux_kbd_t	*k;
504 
505 	KBDMUX_LOCK(state);
506 
507 	/* kill callout */
508 	callout_stop(&state->ks_timo);
509 
510 	/* wait for interrupt task */
511 	while (state->ks_flags & TASK)
512 		KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
513 
514 	/* release all keyboards from the mux */
515 	while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
516 		kbd_release(k->kbd, &k->kbd);
517 		SLIST_REMOVE_HEAD(&state->ks_kbds, next);
518 
519 		k->kbd = NULL;
520 
521 		kfree(k, M_KBDMUX);
522 	}
523 
524 	KBDMUX_UNLOCK(state);
525 
526 	kbd_unregister(kbd);
527 
528 	KBDMUX_LOCK_DESTROY(state);
529 	bzero(state, sizeof(*state));
530 	kfree(state, M_KBDMUX);
531 
532 	kfree(kbd->kb_keymap, M_KBDMUX);
533 	kfree(kbd->kb_accentmap, M_KBDMUX);
534 	kfree(kbd->kb_fkeytab, M_KBDMUX);
535 	kfree(kbd, M_KBDMUX);
536 
537 	return (0);
538 }
539 
540 /*
541  * Keyboard interrupt routine
542  */
543 static int
544 kbdmux_intr(keyboard_t *kbd, void *arg)
545 {
546 	int	c;
547 
548 	if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
549 		/* let the callback function to process the input */
550 		(*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
551 					    kbd->kb_callback.kc_arg);
552 	} else {
553 		/* read and discard the input; no one is waiting for input */
554 		do {
555 			c = kbdmux_read_char(kbd, FALSE);
556 		} while (c != NOKEY);
557 	}
558 
559 	return (0);
560 }
561 
562 /*
563  * Test the interface to the device
564  */
565 static int
566 kbdmux_test_if(keyboard_t *kbd)
567 {
568 	return (0);
569 }
570 
571 /*
572  * Enable the access to the device; until this function is called,
573  * the client cannot read from the keyboard.
574  */
575 static int
576 kbdmux_enable(keyboard_t *kbd)
577 {
578 	KBD_ACTIVATE(kbd);
579 	return (0);
580 }
581 
582 /*
583  * Disallow the access to the device
584  */
585 static int
586 kbdmux_disable(keyboard_t *kbd)
587 {
588 	KBD_DEACTIVATE(kbd);
589 	return (0);
590 }
591 
592 /*
593  * Read one byte from the keyboard if it's allowed
594  */
595 static int
596 kbdmux_read(keyboard_t *kbd, int wait)
597 {
598 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
599 	int		 c;
600 
601 	KBDMUX_LOCK(state);
602 	c = kbdmux_kbd_getc(state);
603 	KBDMUX_UNLOCK(state);
604 
605 	if (c != -1)
606 		kbd->kb_count ++;
607 
608 	return (KBD_IS_ACTIVE(kbd)? c : -1);
609 }
610 
611 /*
612  * Check if data is waiting
613  */
614 static int
615 kbdmux_check(keyboard_t *kbd)
616 {
617 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
618 	int		 ready;
619 
620 	if (!KBD_IS_ACTIVE(kbd))
621 		return (FALSE);
622 
623 	KBDMUX_LOCK(state);
624 	ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
625 	KBDMUX_UNLOCK(state);
626 
627 	return (ready);
628 }
629 
630 /*
631  * Read char from the keyboard (stolen from atkbd.c)
632  */
633 static u_int
634 kbdmux_read_char(keyboard_t *kbd, int wait)
635 {
636 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
637 	u_int		 action;
638 	int		 scancode, keycode;
639 
640 	KBDMUX_LOCK(state);
641 
642 next_code:
643 
644 	/* do we have a composed char to return? */
645 	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
646 		action = state->ks_composed_char;
647 		state->ks_composed_char = 0;
648 		if (action > UCHAR_MAX) {
649 			KBDMUX_UNLOCK(state);
650 
651 			return (ERRKEY);
652 		}
653 
654 		KBDMUX_UNLOCK(state);
655 
656 		return (action);
657 	}
658 
659 	/* see if there is something in the keyboard queue */
660 	scancode = kbdmux_kbd_getc(state);
661 	if (scancode == -1) {
662 		if (state->ks_flags & POLLING) {
663 			kbdmux_kbd_t	*k;
664 
665 			SLIST_FOREACH(k, &state->ks_kbds, next) {
666 				while (kbd_check_char(k->kbd)) {
667 					scancode = kbd_read_char(k->kbd, 0);
668 					if (scancode == NOKEY)
669 						break;
670 					if (scancode == ERRKEY)
671 						continue;
672 					if (!KBD_IS_BUSY(k->kbd))
673 						continue;
674 
675 					kbdmux_kbd_putc(state, scancode);
676 				}
677 			}
678 
679 			if (state->ks_inq_length > 0)
680 				goto next_code;
681 		}
682 
683 		KBDMUX_UNLOCK(state);
684 		return (NOKEY);
685 	}
686 	/* XXX FIXME: check for -1 if wait == 1! */
687 
688 	kbd->kb_count ++;
689 
690 	/* return the byte as is for the K_RAW mode */
691 	if (state->ks_mode == K_RAW) {
692 		KBDMUX_UNLOCK(state);
693 		return (scancode);
694 	}
695 
696 	/* translate the scan code into a keycode */
697 	keycode = scancode & 0x7F;
698 	switch (state->ks_prefix) {
699 	case 0x00:	/* normal scancode */
700 		switch(scancode) {
701 		case 0xB8:	/* left alt (compose key) released */
702 			if (state->ks_flags & COMPOSE) {
703 				state->ks_flags &= ~COMPOSE;
704 				if (state->ks_composed_char > UCHAR_MAX)
705 					state->ks_composed_char = 0;
706 			}
707 			break;
708 		case 0x38:	/* left alt (compose key) pressed */
709 			if (!(state->ks_flags & COMPOSE)) {
710 				state->ks_flags |= COMPOSE;
711 				state->ks_composed_char = 0;
712 			}
713 			break;
714 		case 0xE0:
715 		case 0xE1:
716 			state->ks_prefix = scancode;
717 			goto next_code;
718 		}
719 		break;
720 	case 0xE0:      /* 0xE0 prefix */
721 		state->ks_prefix = 0;
722 		switch (keycode) {
723 		case 0x1C:	/* right enter key */
724 			keycode = 0x59;
725 			break;
726 		case 0x1D:	/* right ctrl key */
727 			keycode = 0x5A;
728 			break;
729 		case 0x35:	/* keypad divide key */
730 			keycode = 0x5B;
731 			break;
732 		case 0x37:	/* print scrn key */
733 			keycode = 0x5C;
734 			break;
735 		case 0x38:	/* right alt key (alt gr) */
736 			keycode = 0x5D;
737 			break;
738 		case 0x46:	/* ctrl-pause/break on AT 101 (see below) */
739 			keycode = 0x68;
740 			break;
741 		case 0x47:	/* grey home key */
742 			keycode = 0x5E;
743 			break;
744 		case 0x48:	/* grey up arrow key */
745 			keycode = 0x5F;
746 			break;
747 		case 0x49:	/* grey page up key */
748 			keycode = 0x60;
749 			break;
750 		case 0x4B:	/* grey left arrow key */
751 			keycode = 0x61;
752 			break;
753 		case 0x4D:	/* grey right arrow key */
754 			keycode = 0x62;
755 			break;
756 		case 0x4F:	/* grey end key */
757 			keycode = 0x63;
758 			break;
759 		case 0x50:	/* grey down arrow key */
760 			keycode = 0x64;
761 			break;
762 		case 0x51:	/* grey page down key */
763 			keycode = 0x65;
764 			break;
765 		case 0x52:	/* grey insert key */
766 			keycode = 0x66;
767 			break;
768 		case 0x53:	/* grey delete key */
769 			keycode = 0x67;
770 			break;
771 		/* the following 3 are only used on the MS "Natural" keyboard */
772 		case 0x5b:	/* left Window key */
773 			keycode = 0x69;
774 			break;
775 		case 0x5c:	/* right Window key */
776 			keycode = 0x6a;
777 			break;
778 		case 0x5d:	/* menu key */
779 			keycode = 0x6b;
780 			break;
781 		case 0x5e:	/* power key */
782 			keycode = 0x6d;
783 			break;
784 		case 0x5f:	/* sleep key */
785 			keycode = 0x6e;
786 			break;
787 		case 0x63:	/* wake key */
788 			keycode = 0x6f;
789 			break;
790 		case 0x64:	/* [JP106USB] backslash, underscore */
791 			keycode = 0x73;
792 			break;
793 		default:	/* ignore everything else */
794 			goto next_code;
795 		}
796 		break;
797 	case 0xE1:	/* 0xE1 prefix */
798 		/*
799 		 * The pause/break key on the 101 keyboard produces:
800 		 * E1-1D-45 E1-9D-C5
801 		 * Ctrl-pause/break produces:
802 		 * E0-46 E0-C6 (See above.)
803 		 */
804 		state->ks_prefix = 0;
805 		if (keycode == 0x1D)
806 			state->ks_prefix = 0x1D;
807 		goto next_code;
808 		/* NOT REACHED */
809 	case 0x1D:	/* pause / break */
810 		state->ks_prefix = 0;
811 		if (keycode != 0x45)
812 			goto next_code;
813 		keycode = 0x68;
814 		break;
815 	}
816 
817 	/* XXX assume 101/102 keys AT keyboard */
818 	switch (keycode) {
819 	case 0x5c:	/* print screen */
820 		if (state->ks_flags & ALTS)
821 			keycode = 0x54;	/* sysrq */
822 		break;
823 	case 0x68:	/* pause/break */
824 		if (state->ks_flags & CTLS)
825 			keycode = 0x6c;	/* break */
826 		break;
827 	}
828 
829 	/* return the key code in the K_CODE mode */
830 	if (state->ks_mode == K_CODE) {
831 		KBDMUX_UNLOCK(state);
832 		return (keycode | (scancode & 0x80));
833 	}
834 
835 	/* compose a character code */
836 	if (state->ks_flags & COMPOSE) {
837 		switch (keycode | (scancode & 0x80)) {
838 		/* key pressed, process it */
839 		case 0x47: case 0x48: case 0x49:	/* keypad 7,8,9 */
840 			state->ks_composed_char *= 10;
841 			state->ks_composed_char += keycode - 0x40;
842 			if (state->ks_composed_char > UCHAR_MAX) {
843 				KBDMUX_UNLOCK(state);
844 				return (ERRKEY);
845 			}
846 			goto next_code;
847 		case 0x4B: case 0x4C: case 0x4D:	/* keypad 4,5,6 */
848 			state->ks_composed_char *= 10;
849 			state->ks_composed_char += keycode - 0x47;
850 			if (state->ks_composed_char > UCHAR_MAX) {
851 				KBDMUX_UNLOCK(state);
852 				return (ERRKEY);
853 			}
854 			goto next_code;
855 		case 0x4F: case 0x50: case 0x51:	/* keypad 1,2,3 */
856 			state->ks_composed_char *= 10;
857 			state->ks_composed_char += keycode - 0x4E;
858 			if (state->ks_composed_char > UCHAR_MAX) {
859 				KBDMUX_UNLOCK(state);
860 				return (ERRKEY);
861 			}
862 			goto next_code;
863 		case 0x52:	/* keypad 0 */
864 			state->ks_composed_char *= 10;
865 			if (state->ks_composed_char > UCHAR_MAX) {
866 				KBDMUX_UNLOCK(state);
867 				return (ERRKEY);
868 			}
869 			goto next_code;
870 
871 		/* key released, no interest here */
872 		case 0xC7: case 0xC8: case 0xC9:	/* keypad 7,8,9 */
873 		case 0xCB: case 0xCC: case 0xCD:	/* keypad 4,5,6 */
874 		case 0xCF: case 0xD0: case 0xD1:	/* keypad 1,2,3 */
875 		case 0xD2:				/* keypad 0 */
876 			goto next_code;
877 
878 		case 0x38:				/* left alt key */
879 			break;
880 
881 		default:
882 			if (state->ks_composed_char > 0) {
883 				state->ks_flags &= ~COMPOSE;
884 				state->ks_composed_char = 0;
885 				KBDMUX_UNLOCK(state);
886 				return (ERRKEY);
887 			}
888 			break;
889 		}
890 	}
891 
892 	/* keycode to key action */
893 	action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
894 			&state->ks_state, &state->ks_accents);
895 	if (action == NOKEY)
896 		goto next_code;
897 
898 	KBDMUX_UNLOCK(state);
899 
900 	return (action);
901 }
902 
903 /*
904  * Check if char is waiting
905  */
906 static int
907 kbdmux_check_char(keyboard_t *kbd)
908 {
909 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
910 	int		 ready;
911 
912 	if (!KBD_IS_ACTIVE(kbd))
913 		return (FALSE);
914 
915 	KBDMUX_LOCK(state);
916 
917 	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
918 		ready = TRUE;
919 	else
920 		ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
921 
922 	KBDMUX_UNLOCK(state);
923 
924 	return (ready);
925 }
926 
927 /*
928  * Keyboard ioctl's
929  */
930 static int
931 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
932 {
933 	static int	 delays[] = {
934 		250, 500, 750, 1000
935 	};
936 
937 	static int	 rates[]  =  {
938 		34,  38,  42,  46,  50,   55,  59,  63,
939 		68,  76,  84,  92,  100, 110, 118, 126,
940 		136, 152, 168, 184, 200, 220, 236, 252,
941 		272, 304, 336, 368, 400, 440, 472, 504
942 	};
943 
944 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
945 	kbdmux_kbd_t	*k;
946 	keyboard_info_t	*ki;
947 	int		 error = 0, mode;
948 
949 	if (state == NULL)
950 		return (ENXIO);
951 
952 	switch (cmd) {
953 	case KBADDKBD: /* add keyboard to the mux */
954 		ki = (keyboard_info_t *) arg;
955 
956 		if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
957 		    strcmp(ki->kb_name, "*") == 0)
958 			return (EINVAL); /* bad input */
959 
960 		KBDMUX_LOCK(state);
961 
962 		SLIST_FOREACH(k, &state->ks_kbds, next)
963 			if (k->kbd->kb_unit == ki->kb_unit &&
964 			    strcmp(k->kbd->kb_name, ki->kb_name) == 0)
965 				break;
966 
967 		if (k != NULL) {
968 			KBDMUX_UNLOCK(state);
969 
970 			return (0); /* keyboard already in the mux */
971 		}
972 
973 		k = kmalloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
974 		if (k == NULL) {
975 			KBDMUX_UNLOCK(state);
976 
977 			return (ENOMEM); /* out of memory */
978 		}
979 
980 		k->kbd = kbd_get_keyboard(
981 				kbd_allocate(
982 					ki->kb_name,
983 					ki->kb_unit,
984 					(void *) &k->kbd,
985 					kbdmux_kbd_event, (void *) state));
986 		if (k->kbd == NULL) {
987 			KBDMUX_UNLOCK(state);
988 			kfree(k, M_KBDMUX);
989 
990 			return (EINVAL); /* bad keyboard */
991 		}
992 
993 		kbd_enable(k->kbd);
994 		kbd_clear_state(k->kbd);
995 
996 		/* set K_RAW mode on slave keyboard */
997 		mode = K_RAW;
998 		error = kbd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
999 		if (error == 0) {
1000 			/* set lock keys state on slave keyboard */
1001 			mode = state->ks_state & LOCK_MASK;
1002 			error = kbd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1003 		}
1004 
1005 		if (error != 0) {
1006 			KBDMUX_UNLOCK(state);
1007 
1008 			kbd_release(k->kbd, &k->kbd);
1009 			k->kbd = NULL;
1010 
1011 			kfree(k, M_KBDMUX);
1012 
1013 			return (error); /* could not set mode */
1014 		}
1015 
1016 		SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1017 
1018 		KBDMUX_UNLOCK(state);
1019 		break;
1020 
1021 	case KBRELKBD: /* release keyboard from the mux */
1022 		ki = (keyboard_info_t *) arg;
1023 
1024 		if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1025 		    strcmp(ki->kb_name, "*") == 0)
1026 			return (EINVAL); /* bad input */
1027 
1028 		KBDMUX_LOCK(state);
1029 
1030 		SLIST_FOREACH(k, &state->ks_kbds, next)
1031 			if (k->kbd->kb_unit == ki->kb_unit &&
1032 			    strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1033 				break;
1034 
1035 		if (k != NULL) {
1036 			error = kbd_release(k->kbd, &k->kbd);
1037 			if (error == 0) {
1038 				SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1039 
1040 				k->kbd = NULL;
1041 
1042 				kfree(k, M_KBDMUX);
1043 			}
1044 		} else
1045 			error = ENXIO; /* keyboard is not in the mux */
1046 
1047 		KBDMUX_UNLOCK(state);
1048 		break;
1049 
1050 	case KDGKBMODE: /* get kyboard mode */
1051 		KBDMUX_LOCK(state);
1052 		*(int *)arg = state->ks_mode;
1053 		KBDMUX_UNLOCK(state);
1054 		break;
1055 
1056 	case KDSKBMODE: /* set keyboard mode */
1057 		KBDMUX_LOCK(state);
1058 
1059 		switch (*(int *)arg) {
1060 		case K_XLATE:
1061 			if (state->ks_mode != K_XLATE) {
1062 				/* make lock key state and LED state match */
1063 				state->ks_state &= ~LOCK_MASK;
1064 				state->ks_state |= KBD_LED_VAL(kbd);
1065                         }
1066                         /* FALLTHROUGH */
1067 
1068 		case K_RAW:
1069 		case K_CODE:
1070 			if (state->ks_mode != *(int *)arg) {
1071 				kbdmux_clear_state_locked(state);
1072 				state->ks_mode = *(int *)arg;
1073 			}
1074 			break;
1075 
1076                 default:
1077 			error = EINVAL;
1078 			break;
1079 		}
1080 
1081 		KBDMUX_UNLOCK(state);
1082 		break;
1083 
1084 	case KDGETLED: /* get keyboard LED */
1085 		KBDMUX_LOCK(state);
1086 		*(int *)arg = KBD_LED_VAL(kbd);
1087 		KBDMUX_UNLOCK(state);
1088 		break;
1089 
1090 	case KDSETLED: /* set keyboard LED */
1091 		KBDMUX_LOCK(state);
1092 
1093 		/* NOTE: lock key state in ks_state won't be changed */
1094 		if (*(int *)arg & ~LOCK_MASK) {
1095 			KBDMUX_UNLOCK(state);
1096 
1097 			return (EINVAL);
1098 		}
1099 
1100 		KBD_LED_VAL(kbd) = *(int *)arg;
1101 
1102 		/* KDSETLED on all slave keyboards */
1103 		SLIST_FOREACH(k, &state->ks_kbds, next)
1104 			kbd_ioctl(k->kbd, KDSETLED, arg);
1105 
1106 		KBDMUX_UNLOCK(state);
1107 		break;
1108 
1109 	case KDGKBSTATE: /* get lock key state */
1110 		KBDMUX_LOCK(state);
1111 		*(int *)arg = state->ks_state & LOCK_MASK;
1112 		KBDMUX_UNLOCK(state);
1113 		break;
1114 
1115 	case KDSKBSTATE: /* set lock key state */
1116 		KBDMUX_LOCK(state);
1117 
1118 		if (*(int *)arg & ~LOCK_MASK) {
1119 			KBDMUX_UNLOCK(state);
1120 
1121 			return (EINVAL);
1122 		}
1123 
1124 		state->ks_state &= ~LOCK_MASK;
1125 		state->ks_state |= *(int *)arg;
1126 
1127 		/* KDSKBSTATE on all slave keyboards */
1128 		SLIST_FOREACH(k, &state->ks_kbds, next)
1129 			kbd_ioctl(k->kbd, KDSKBSTATE, arg);
1130 
1131 		KBDMUX_UNLOCK(state);
1132 
1133 		return (kbdmux_ioctl(kbd, KDSETLED, arg));
1134 		/* NOT REACHED */
1135 
1136 	case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1137 	case KDSETRAD: /* set keyboard repeat rate (old interface) */
1138 		KBDMUX_LOCK(state);
1139 
1140 		if (cmd == KDSETREPEAT) {
1141 			int	i;
1142 
1143 			/* lookup delay */
1144 			for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1145 				if (((int *)arg)[0] >= delays[i])
1146 					break;
1147 			mode = i << 5;
1148 
1149 			/* lookup rate */
1150 			for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1151 				if (((int *)arg)[1] >= rates[i])
1152 					break;
1153 			mode |= i;
1154 		} else
1155 			mode = *(int *)arg;
1156 
1157 		if (mode & ~0x7f) {
1158 			KBDMUX_UNLOCK(state);
1159 
1160 			return (EINVAL);
1161 		}
1162 
1163 		kbd->kb_delay1 = delays[(mode >> 5) & 3];
1164 		kbd->kb_delay2 = rates[mode & 0x1f];
1165 
1166 		/* perform command on all slave keyboards */
1167 		SLIST_FOREACH(k, &state->ks_kbds, next)
1168 			kbd_ioctl(k->kbd, cmd, arg);
1169 
1170 		KBDMUX_UNLOCK(state);
1171 		break;
1172 
1173 	case PIO_KEYMAP:	/* set keyboard translation table */
1174 	case PIO_KEYMAPENT:	/* set keyboard translation table entry */
1175 	case PIO_DEADKEYMAP:	/* set accent key translation table */
1176 		KBDMUX_LOCK(state);
1177                 state->ks_accents = 0;
1178 
1179 		/* perform command on all slave keyboards */
1180 		SLIST_FOREACH(k, &state->ks_kbds, next)
1181 			kbd_ioctl(k->kbd, cmd, arg);
1182 
1183 		KBDMUX_UNLOCK(state);
1184                 /* FALLTHROUGH */
1185 
1186 	default:
1187 		error = genkbd_commonioctl(kbd, cmd, arg);
1188 		break;
1189 	}
1190 
1191 	return (error);
1192 }
1193 
1194 /*
1195  * Lock the access to the keyboard
1196  */
1197 static int
1198 kbdmux_lock(keyboard_t *kbd, int lock)
1199 {
1200 	return (1); /* XXX */
1201 }
1202 
1203 /*
1204  * Clear the internal state of the keyboard
1205  */
1206 static void
1207 kbdmux_clear_state_locked(kbdmux_state_t *state)
1208 {
1209 	KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1210 
1211 	state->ks_flags &= ~(COMPOSE|POLLING);
1212 	state->ks_state &= LOCK_MASK;	/* preserve locking key state */
1213 	state->ks_accents = 0;
1214 	state->ks_composed_char = 0;
1215 /*	state->ks_prefix = 0;		XXX */
1216 	state->ks_inq_length = 0;
1217 }
1218 
1219 static void
1220 kbdmux_clear_state(keyboard_t *kbd)
1221 {
1222 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
1223 
1224 	KBDMUX_LOCK(state);
1225 	kbdmux_clear_state_locked(state);
1226 	KBDMUX_UNLOCK(state);
1227 }
1228 
1229 /*
1230  * Save the internal state
1231  */
1232 static int
1233 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1234 {
1235 	if (len == 0)
1236 		return (sizeof(kbdmux_state_t));
1237 	if (len < sizeof(kbdmux_state_t))
1238 		return (-1);
1239 
1240 	bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1241 
1242 	return (0);
1243 }
1244 
1245 /*
1246  * Set the internal state
1247  */
1248 static int
1249 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1250 {
1251 	if (len < sizeof(kbdmux_state_t))
1252 		return (ENOMEM);
1253 
1254 	bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1255 
1256 	return (0);
1257 }
1258 
1259 /*
1260  * Set polling
1261  */
1262 static int
1263 kbdmux_poll(keyboard_t *kbd, int on)
1264 {
1265 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
1266 	kbdmux_kbd_t	*k;
1267 
1268 	KBDMUX_LOCK(state);
1269 
1270 	if (on)
1271 		state->ks_flags |= POLLING;
1272 	else
1273 		state->ks_flags &= ~POLLING;
1274 
1275 	/* set poll on slave keyboards */
1276 	SLIST_FOREACH(k, &state->ks_kbds, next)
1277 		kbd_poll(k->kbd, on);
1278 
1279 	KBDMUX_UNLOCK(state);
1280 
1281 	return (0);
1282 }
1283 
1284 /*****************************************************************************
1285  *****************************************************************************
1286  **                                    Module
1287  *****************************************************************************
1288  *****************************************************************************/
1289 
1290 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1291 
1292 static int
1293 kbdmux_modevent(module_t mod, int type, void *data)
1294 {
1295 	keyboard_switch_t	*sw;
1296 	keyboard_t		*kbd;
1297 	int			 error;
1298 
1299 	switch (type) {
1300 	case MOD_LOAD:
1301 		if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1302 			break;
1303 
1304 		if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1305 			kbd_delete_driver(&kbdmux_kbd_driver);
1306 			error = ENXIO;
1307 			break;
1308 		}
1309 
1310 		kbd = NULL;
1311 
1312 		if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1313 		    (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1314 			kbd_delete_driver(&kbdmux_kbd_driver);
1315 			break;
1316 		}
1317 
1318 #ifdef KBD_INSTALL_CDEV
1319 		if ((error = kbd_attach(kbd)) != 0) {
1320 			(*sw->term)(kbd);
1321 			kbd_delete_driver(&kbdmux_kbd_driver);
1322 			break;
1323 		}
1324 #endif
1325 
1326 		if ((error = (*sw->enable)(kbd)) != 0) {
1327 			(*sw->disable)(kbd);
1328 #ifdef KBD_INSTALL_CDEV
1329 			kbd_detach(kbd);
1330 #endif
1331 			(*sw->term)(kbd);
1332 			kbd_delete_driver(&kbdmux_kbd_driver);
1333 			break;
1334 		}
1335 		break;
1336 
1337 	case MOD_UNLOAD:
1338 		if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1339 			panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1340 
1341 		kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1342 		if (kbd != NULL) {
1343 			(*sw->disable)(kbd);
1344 #ifdef KBD_INSTALL_CDEV
1345 			kbd_detach(kbd);
1346 #endif
1347 			(*sw->term)(kbd);
1348 			kbd_delete_driver(&kbdmux_kbd_driver);
1349 		}
1350 		error = 0;
1351 		break;
1352 
1353 	default:
1354 		error = EOPNOTSUPP;
1355 		break;
1356 	}
1357 
1358 	return (error);
1359 }
1360 
1361 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1362