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