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