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