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