xref: /freebsd/sys/dev/kbdmux/kbdmux.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
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/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 /*
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 	kbdd_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 (kbdd_check_char(kbd)) {
270 			c = kbdd_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 			free(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 = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
402 		state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
403 		keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
404 		accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
405 		fkeymap = malloc(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, 0, 0);
434 		bcopy(&key_map, keymap, sizeof(key_map));
435 		bcopy(&accent_map, accmap, sizeof(accent_map));
436 		bcopy(fkey_tab, fkeymap,
437 			imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
438 		kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
439 		kbd->kb_data = (void *)state;
440 
441 		KBD_FOUND_DEVICE(kbd);
442 		KBD_PROBE_DONE(kbd);
443 
444 		KBDMUX_LOCK(state);
445 		kbdmux_clear_state_locked(state);
446 		state->ks_mode = K_XLATE;
447 		KBDMUX_UNLOCK(state);
448 	}
449 
450 	if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
451 		kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
452 
453 		kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
454 
455 		delay[0] = kbd->kb_delay1;
456 		delay[1] = kbd->kb_delay2;
457 		kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
458 
459 		KBD_INIT_DONE(kbd);
460 	}
461 
462 	if (!KBD_IS_CONFIGURED(kbd)) {
463 		if (kbd_register(kbd) < 0) {
464 			error = ENXIO;
465 			goto bad;
466 		}
467 
468 		KBD_CONFIG_DONE(kbd);
469 
470 		KBDMUX_LOCK(state);
471 		callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
472 		KBDMUX_UNLOCK(state);
473 	}
474 
475 	return (0);
476 bad:
477 	if (needfree) {
478 		if (state != NULL)
479 			free(state, M_KBDMUX);
480 		if (keymap != NULL)
481 			free(keymap, M_KBDMUX);
482 		if (accmap != NULL)
483 			free(accmap, M_KBDMUX);
484 		if (fkeymap != NULL)
485 			free(fkeymap, M_KBDMUX);
486 		if (kbd != NULL) {
487 			free(kbd, M_KBDMUX);
488 			*kbdp = NULL;	/* insure ref doesn't leak to caller */
489 		}
490 	}
491 
492 	return (error);
493 }
494 
495 /*
496  * Finish using this keyboard
497  */
498 static int
499 kbdmux_term(keyboard_t *kbd)
500 {
501 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
502 	kbdmux_kbd_t	*k;
503 
504 	KBDMUX_LOCK(state);
505 
506 	/* kill callout */
507 	callout_stop(&state->ks_timo);
508 
509 	/* wait for interrupt task */
510 	while (state->ks_flags & TASK)
511 		KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
512 
513 	/* release all keyboards from the mux */
514 	while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
515 		kbd_release(k->kbd, &k->kbd);
516 		SLIST_REMOVE_HEAD(&state->ks_kbds, next);
517 
518 		k->kbd = NULL;
519 
520 		free(k, M_KBDMUX);
521 	}
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 = kbdmux_kbd_getc(state);
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_length > 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 = kbdmux_kbd_getc(state);
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 (kbdd_check_char(k->kbd)) {
666 					scancode = kbdd_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 					kbdmux_kbd_putc(state, scancode);
675 				}
676 			}
677 
678 			if (state->ks_inq_length > 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_length > 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 		kbdd_enable(k->kbd);
996 		kbdd_clear_state(k->kbd);
997 
998 		/* set K_RAW mode on slave keyboard */
999 		mode = K_RAW;
1000 		error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1001 		if (error == 0) {
1002 			/* set lock keys state on slave keyboard */
1003 			mode = state->ks_state & LOCK_MASK;
1004 			error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&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 			(void)kbdd_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 			(void)kbdd_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 			(void)kbdd_ioctl(k->kbd, cmd, arg);
1196 
1197 		KBDMUX_UNLOCK(state);
1198 		break;
1199 
1200 	case PIO_KEYMAP:	/* set keyboard translation table */
1201 	case OPIO_KEYMAP:	/* set keyboard translation table (compat) */
1202 	case PIO_KEYMAPENT:	/* set keyboard translation table entry */
1203 	case PIO_DEADKEYMAP:	/* set accent key translation table */
1204 		KBDMUX_LOCK(state);
1205                 state->ks_accents = 0;
1206 
1207 		/* perform command on all slave keyboards */
1208 		SLIST_FOREACH(k, &state->ks_kbds, next)
1209 			(void)kbdd_ioctl(k->kbd, cmd, arg);
1210 
1211 		KBDMUX_UNLOCK(state);
1212                 /* FALLTHROUGH */
1213 
1214 	default:
1215 		error = genkbd_commonioctl(kbd, cmd, arg);
1216 		break;
1217 	}
1218 
1219 	return (error);
1220 }
1221 
1222 /*
1223  * Lock the access to the keyboard
1224  */
1225 static int
1226 kbdmux_lock(keyboard_t *kbd, int lock)
1227 {
1228 	return (1); /* XXX */
1229 }
1230 
1231 /*
1232  * Clear the internal state of the keyboard
1233  */
1234 static void
1235 kbdmux_clear_state_locked(kbdmux_state_t *state)
1236 {
1237 	KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1238 
1239 	state->ks_flags &= ~(COMPOSE|POLLING);
1240 	state->ks_state &= LOCK_MASK;	/* preserve locking key state */
1241 	state->ks_accents = 0;
1242 	state->ks_composed_char = 0;
1243 /*	state->ks_prefix = 0;		XXX */
1244 	state->ks_inq_length = 0;
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 		kbdd_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 			(*sw->disable)(kbd);
1372 #ifdef KBD_INSTALL_CDEV
1373 			kbd_detach(kbd);
1374 #endif
1375 			(*sw->term)(kbd);
1376 			kbd_delete_driver(&kbdmux_kbd_driver);
1377 		}
1378 		error = 0;
1379 		break;
1380 
1381 	default:
1382 		error = EOPNOTSUPP;
1383 		break;
1384 	}
1385 
1386 	return (error);
1387 }
1388 
1389 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1390 
1391