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