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