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