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