6 * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
30 * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
34 #include "opt_compat.h"
36 #include "opt_kbdmux.h"
38 #include <sys/param.h>
41 #include <sys/consio.h>
42 #include <sys/fcntl.h>
44 #include <sys/kernel.h>
45 #include <sys/limits.h>
47 #include <sys/malloc.h>
48 #include <sys/module.h>
49 #include <sys/mutex.h>
52 #include <sys/queue.h>
53 #include <sys/selinfo.h>
54 #include <sys/systm.h>
55 #include <sys/taskqueue.h>
57 #include <dev/kbd/kbdreg.h>
59 /* the initial key map, accent map and fkey strings */
60 #ifdef KBDMUX_DFLT_KEYMAP
61 #define KBD_DFLT_KEYMAP
62 #include "kbdmuxmap.h"
65 #include <dev/kbd/kbdtables.h>
67 #define KEYBOARD_NAME "kbdmux"
69 MALLOC_DECLARE(M_KBDMUX);
70 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
72 /*****************************************************************************
73 *****************************************************************************
75 *****************************************************************************
76 *****************************************************************************/
78 #define KBDMUX_Q_SIZE 512 /* input queue size */
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
89 #define KBDMUX_LOCK_DECL_GLOBAL \
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)
108 #define KBDMUX_LOCK_DECL_GLOBAL
110 #define KBDMUX_LOCK_INIT(s)
112 #define KBDMUX_LOCK_DESTROY(s)
114 #define KBDMUX_LOCK(s)
116 #define KBDMUX_UNLOCK(s)
118 #define KBDMUX_LOCK_ASSERT(s, w)
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)
133 keyboard_t *kbd; /* keyboard */
134 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
137 typedef struct kbdmux_kbd kbdmux_kbd_t;
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 */
151 int ks_flags; /* flags */
152 #define COMPOSE (1 << 0) /* compose char flag */
153 #define TASK (1 << 2) /* interrupt task queued */
155 int ks_polling; /* poll nesting count */
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 */
162 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
164 KBDMUX_LOCK_DECL_GLOBAL;
167 typedef struct kbdmux_state kbdmux_state_t;
169 /*****************************************************************************
170 *****************************************************************************
172 *****************************************************************************
173 *****************************************************************************/
175 static task_fn_t kbdmux_kbd_intr;
176 static timeout_t kbdmux_kbd_intr_timo;
177 static kbd_callback_func_t kbdmux_kbd_event;
180 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
184 if (state->ks_inq_length == KBDMUX_Q_SIZE)
187 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
188 state->ks_inq[p] = c;
189 state->ks_inq_length++;
193 kbdmux_kbd_getc(kbdmux_state_t *state)
197 if (state->ks_inq_length == 0)
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--;
208 * Interrupt handler task
211 kbdmux_kbd_intr(void *xkbd, int pending)
213 keyboard_t *kbd = (keyboard_t *) xkbd;
214 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
216 kbdd_intr(kbd, NULL);
220 state->ks_flags &= ~TASK;
221 wakeup(&state->ks_task);
223 KBDMUX_UNLOCK(state);
227 * Schedule interrupt handler on timeout. Called with locked state.
230 kbdmux_kbd_intr_timo(void *xstate)
232 kbdmux_state_t *state = (kbdmux_state_t *) xstate;
234 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
236 if (callout_pending(&state->ks_timo))
237 return; /* callout was reset */
239 if (!callout_active(&state->ks_timo))
240 return; /* callout was stopped */
242 callout_deactivate(&state->ks_timo);
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;
249 /* re-schedule timeout */
250 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
254 * Process event from one of our keyboards
257 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
259 kbdmux_state_t *state = (kbdmux_state_t *) arg;
262 case KBDIO_KEYINPUT: {
268 * Read all chars from the keyboard
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
277 while (kbdd_check_char(kbd)) {
278 c = kbdd_read_char(kbd, 0);
282 continue; /* XXX ring bell */
283 if (!KBD_IS_BUSY(kbd))
284 continue; /* not open - discard the input */
286 kbdmux_kbd_putc(state, c);
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;
294 KBDMUX_UNLOCK(state);
297 case KBDIO_UNLOADING: {
302 SLIST_FOREACH(k, &state->ks_kbds, next)
307 kbd_release(k->kbd, &k->kbd);
308 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
315 KBDMUX_UNLOCK(state);
326 /****************************************************************************
327 ****************************************************************************
329 ****************************************************************************
330 ****************************************************************************/
332 static int kbdmux_configure(int flags);
333 static kbd_probe_t kbdmux_probe;
334 static kbd_init_t kbdmux_init;
335 static kbd_term_t kbdmux_term;
336 static kbd_intr_t kbdmux_intr;
337 static kbd_test_if_t kbdmux_test_if;
338 static kbd_enable_t kbdmux_enable;
339 static kbd_disable_t kbdmux_disable;
340 static kbd_read_t kbdmux_read;
341 static kbd_check_t kbdmux_check;
342 static kbd_read_char_t kbdmux_read_char;
343 static kbd_check_char_t kbdmux_check_char;
344 static kbd_ioctl_t kbdmux_ioctl;
345 static kbd_lock_t kbdmux_lock;
346 static void kbdmux_clear_state_locked(kbdmux_state_t *state);
347 static kbd_clear_state_t kbdmux_clear_state;
348 static kbd_get_state_t kbdmux_get_state;
349 static kbd_set_state_t kbdmux_set_state;
350 static kbd_poll_mode_t kbdmux_poll;
352 static keyboard_switch_t kbdmuxsw = {
353 .probe = kbdmux_probe,
357 .test_if = kbdmux_test_if,
358 .enable = kbdmux_enable,
359 .disable = kbdmux_disable,
361 .check = kbdmux_check,
362 .read_char = kbdmux_read_char,
363 .check_char = kbdmux_check_char,
364 .ioctl = kbdmux_ioctl,
366 .clear_state = kbdmux_clear_state,
367 .get_state = kbdmux_get_state,
368 .set_state = kbdmux_set_state,
369 .get_fkeystr = genkbd_get_fkeystr,
375 * Return the number of found keyboards
378 kbdmux_configure(int flags)
387 kbdmux_probe(int unit, void *arg, int flags)
389 if (resource_disabled(KEYBOARD_NAME, unit))
396 * Reset and initialize the keyboard (stolen from atkbd.c)
399 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
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];
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]);
417 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
418 (accmap == NULL) || (fkeymap == NULL)) {
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)) {
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;
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;
449 KBD_FOUND_DEVICE(kbd);
453 kbdmux_clear_state_locked(state);
454 state->ks_mode = K_XLATE;
455 KBDMUX_UNLOCK(state);
458 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
459 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
461 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
463 delay[0] = kbd->kb_delay1;
464 delay[1] = kbd->kb_delay2;
465 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
470 if (!KBD_IS_CONFIGURED(kbd)) {
471 if (kbd_register(kbd) < 0) {
476 KBD_CONFIG_DONE(kbd);
479 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
480 KBDMUX_UNLOCK(state);
487 free(state, M_KBDMUX);
489 free(keymap, M_KBDMUX);
491 free(accmap, M_KBDMUX);
493 free(fkeymap, M_KBDMUX);
496 *kbdp = NULL; /* insure ref doesn't leak to caller */
504 * Finish using this keyboard
507 kbdmux_term(keyboard_t *kbd)
509 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
515 callout_stop(&state->ks_timo);
517 /* wait for interrupt task */
518 while (state->ks_flags & TASK)
519 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
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);
531 KBDMUX_UNLOCK(state);
535 KBDMUX_LOCK_DESTROY(state);
536 bzero(state, sizeof(*state));
537 free(state, M_KBDMUX);
539 free(kbd->kb_keymap, M_KBDMUX);
540 free(kbd->kb_accentmap, M_KBDMUX);
541 free(kbd->kb_fkeytab, M_KBDMUX);
548 * Keyboard interrupt routine
551 kbdmux_intr(keyboard_t *kbd, void *arg)
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);
560 /* read and discard the input; no one is waiting for input */
562 c = kbdmux_read_char(kbd, FALSE);
563 } while (c != NOKEY);
570 * Test the interface to the device
573 kbdmux_test_if(keyboard_t *kbd)
579 * Enable the access to the device; until this function is called,
580 * the client cannot read from the keyboard.
583 kbdmux_enable(keyboard_t *kbd)
590 * Disallow the access to the device
593 kbdmux_disable(keyboard_t *kbd)
600 * Read one byte from the keyboard if it's allowed
603 kbdmux_read(keyboard_t *kbd, int wait)
605 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
609 c = kbdmux_kbd_getc(state);
610 KBDMUX_UNLOCK(state);
615 return (KBD_IS_ACTIVE(kbd)? c : -1);
619 * Check if data is waiting
622 kbdmux_check(keyboard_t *kbd)
624 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
627 if (!KBD_IS_ACTIVE(kbd))
631 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
632 KBDMUX_UNLOCK(state);
638 * Read char from the keyboard (stolen from atkbd.c)
641 kbdmux_read_char(keyboard_t *kbd, int wait)
643 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
645 int scancode, keycode;
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);
661 KBDMUX_UNLOCK(state);
666 /* see if there is something in the keyboard queue */
667 scancode = kbdmux_kbd_getc(state);
668 if (scancode == -1) {
669 if (state->ks_polling != 0) {
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)
677 if (scancode == ERRKEY)
679 if (!KBD_IS_BUSY(k->kbd))
682 kbdmux_kbd_putc(state, scancode);
686 if (state->ks_inq_length > 0)
690 KBDMUX_UNLOCK(state);
693 /* XXX FIXME: check for -1 if wait == 1! */
697 /* return the byte as is for the K_RAW mode */
698 if (state->ks_mode == K_RAW) {
699 KBDMUX_UNLOCK(state);
703 /* translate the scan code into a keycode */
704 keycode = scancode & 0x7F;
705 switch (state->ks_prefix) {
706 case 0x00: /* normal 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;
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;
723 state->ks_prefix = scancode;
727 case 0xE0: /* 0xE0 prefix */
728 state->ks_prefix = 0;
730 case 0x1C: /* right enter key */
733 case 0x1D: /* right ctrl key */
736 case 0x35: /* keypad divide key */
739 case 0x37: /* print scrn key */
742 case 0x38: /* right alt key (alt gr) */
745 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
748 case 0x47: /* grey home key */
751 case 0x48: /* grey up arrow key */
754 case 0x49: /* grey page up key */
757 case 0x4B: /* grey left arrow key */
760 case 0x4D: /* grey right arrow key */
763 case 0x4F: /* grey end key */
766 case 0x50: /* grey down arrow key */
769 case 0x51: /* grey page down key */
772 case 0x52: /* grey insert key */
775 case 0x53: /* grey delete key */
778 /* the following 3 are only used on the MS "Natural" keyboard */
779 case 0x5b: /* left Window key */
782 case 0x5c: /* right Window key */
785 case 0x5d: /* menu key */
788 case 0x5e: /* power key */
791 case 0x5f: /* sleep key */
794 case 0x63: /* wake key */
797 case 0x64: /* [JP106USB] backslash, underscore */
800 default: /* ignore everything else */
804 case 0xE1: /* 0xE1 prefix */
806 * The pause/break key on the 101 keyboard produces:
808 * Ctrl-pause/break produces:
809 * E0-46 E0-C6 (See above.)
811 state->ks_prefix = 0;
813 state->ks_prefix = 0x1D;
816 case 0x1D: /* pause / break */
817 state->ks_prefix = 0;
824 /* XXX assume 101/102 keys AT keyboard */
826 case 0x5c: /* print screen */
827 if (state->ks_flags & ALTS)
828 keycode = 0x54; /* sysrq */
830 case 0x68: /* pause/break */
831 if (state->ks_flags & CTLS)
832 keycode = 0x6c; /* break */
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));
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);
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);
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);
870 case 0x52: /* keypad 0 */
871 state->ks_composed_char *= 10;
872 if (state->ks_composed_char > UCHAR_MAX) {
873 KBDMUX_UNLOCK(state);
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 */
885 case 0x38: /* left alt key */
889 if (state->ks_composed_char > 0) {
890 state->ks_flags &= ~COMPOSE;
891 state->ks_composed_char = 0;
892 KBDMUX_UNLOCK(state);
899 /* keycode to key action */
900 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
901 &state->ks_state, &state->ks_accents);
905 KBDMUX_UNLOCK(state);
911 * Check if char is waiting
914 kbdmux_check_char(keyboard_t *kbd)
916 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
919 if (!KBD_IS_ACTIVE(kbd))
924 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
927 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
929 KBDMUX_UNLOCK(state);
938 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
940 static int delays[] = {
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
951 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
955 #ifdef COMPAT_FREEBSD6
963 case KBADDKBD: /* add keyboard to the mux */
964 ki = (keyboard_info_t *) arg;
966 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
967 strcmp(ki->kb_name, "*") == 0)
968 return (EINVAL); /* bad input */
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)
978 KBDMUX_UNLOCK(state);
980 return (0); /* keyboard already in the mux */
983 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
985 KBDMUX_UNLOCK(state);
987 return (ENOMEM); /* out of memory */
990 k->kbd = kbd_get_keyboard(
995 kbdmux_kbd_event, (void *) state));
996 if (k->kbd == NULL) {
997 KBDMUX_UNLOCK(state);
1000 return (EINVAL); /* bad keyboard */
1003 kbdd_enable(k->kbd);
1004 kbdd_clear_state(k->kbd);
1006 /* set K_RAW mode on slave keyboard */
1008 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
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);
1016 KBDMUX_UNLOCK(state);
1018 kbd_release(k->kbd, &k->kbd);
1023 return (error); /* could not set mode */
1026 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1028 KBDMUX_UNLOCK(state);
1031 case KBRELKBD: /* release keyboard from the mux */
1032 ki = (keyboard_info_t *) arg;
1034 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1035 strcmp(ki->kb_name, "*") == 0)
1036 return (EINVAL); /* bad input */
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)
1046 error = kbd_release(k->kbd, &k->kbd);
1048 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1055 error = ENXIO; /* keyboard is not in the mux */
1057 KBDMUX_UNLOCK(state);
1060 case KDGKBMODE: /* get kyboard mode */
1062 *(int *)arg = state->ks_mode;
1063 KBDMUX_UNLOCK(state);
1066 #ifdef COMPAT_FREEBSD6
1068 ival = IOCPARM_IVAL(arg);
1069 arg = (caddr_t)&ival;
1072 case KDSKBMODE: /* set keyboard mode */
1075 switch (*(int *)arg) {
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);
1086 if (state->ks_mode != *(int *)arg) {
1087 kbdmux_clear_state_locked(state);
1088 state->ks_mode = *(int *)arg;
1097 KBDMUX_UNLOCK(state);
1100 case KDGETLED: /* get keyboard LED */
1102 *(int *)arg = KBD_LED_VAL(kbd);
1103 KBDMUX_UNLOCK(state);
1106 #ifdef COMPAT_FREEBSD6
1108 ival = IOCPARM_IVAL(arg);
1109 arg = (caddr_t)&ival;
1112 case KDSETLED: /* set keyboard LED */
1115 /* NOTE: lock key state in ks_state won't be changed */
1116 if (*(int *)arg & ~LOCK_MASK) {
1117 KBDMUX_UNLOCK(state);
1122 KBD_LED_VAL(kbd) = *(int *)arg;
1124 /* KDSETLED on all slave keyboards */
1125 SLIST_FOREACH(k, &state->ks_kbds, next)
1126 (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
1128 KBDMUX_UNLOCK(state);
1131 case KDGKBSTATE: /* get lock key state */
1133 *(int *)arg = state->ks_state & LOCK_MASK;
1134 KBDMUX_UNLOCK(state);
1137 #ifdef COMPAT_FREEBSD6
1139 ival = IOCPARM_IVAL(arg);
1140 arg = (caddr_t)&ival;
1143 case KDSKBSTATE: /* set lock key state */
1146 if (*(int *)arg & ~LOCK_MASK) {
1147 KBDMUX_UNLOCK(state);
1152 state->ks_state &= ~LOCK_MASK;
1153 state->ks_state |= *(int *)arg;
1155 /* KDSKBSTATE on all slave keyboards */
1156 SLIST_FOREACH(k, &state->ks_kbds, next)
1157 (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
1159 KBDMUX_UNLOCK(state);
1161 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1164 #ifdef COMPAT_FREEBSD6
1167 ival = IOCPARM_IVAL(arg);
1168 arg = (caddr_t)&ival;
1171 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1172 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1175 if (cmd == KDSETREPEAT) {
1179 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1180 if (((int *)arg)[0] >= delays[i])
1185 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1186 if (((int *)arg)[1] >= rates[i])
1193 KBDMUX_UNLOCK(state);
1198 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1199 kbd->kb_delay2 = rates[mode & 0x1f];
1201 /* perform command on all slave keyboards */
1202 SLIST_FOREACH(k, &state->ks_kbds, next)
1203 (void)kbdd_ioctl(k->kbd, cmd, arg);
1205 KBDMUX_UNLOCK(state);
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 */
1213 state->ks_accents = 0;
1215 /* perform command on all slave keyboards */
1216 SLIST_FOREACH(k, &state->ks_kbds, next)
1217 (void)kbdd_ioctl(k->kbd, cmd, arg);
1219 KBDMUX_UNLOCK(state);
1223 error = genkbd_commonioctl(kbd, cmd, arg);
1231 * Lock the access to the keyboard
1234 kbdmux_lock(keyboard_t *kbd, int lock)
1236 return (1); /* XXX */
1240 * Clear the internal state of the keyboard
1243 kbdmux_clear_state_locked(kbdmux_state_t *state)
1245 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1247 state->ks_flags &= ~COMPOSE;
1248 state->ks_polling = 0;
1249 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1250 state->ks_accents = 0;
1251 state->ks_composed_char = 0;
1252 /* state->ks_prefix = 0; XXX */
1253 state->ks_inq_length = 0;
1257 kbdmux_clear_state(keyboard_t *kbd)
1259 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1262 kbdmux_clear_state_locked(state);
1263 KBDMUX_UNLOCK(state);
1267 * Save the internal state
1270 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1273 return (sizeof(kbdmux_state_t));
1274 if (len < sizeof(kbdmux_state_t))
1277 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1283 * Set the internal state
1286 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1288 if (len < sizeof(kbdmux_state_t))
1291 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1300 kbdmux_poll(keyboard_t *kbd, int on)
1302 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1308 state->ks_polling++;
1310 state->ks_polling--;
1312 /* set poll on slave keyboards */
1313 SLIST_FOREACH(k, &state->ks_kbds, next)
1314 kbdd_poll(k->kbd, on);
1316 KBDMUX_UNLOCK(state);
1321 /*****************************************************************************
1322 *****************************************************************************
1324 *****************************************************************************
1325 *****************************************************************************/
1327 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1330 kbdmux_modevent(module_t mod, int type, void *data)
1332 keyboard_switch_t *sw;
1338 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1341 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1342 kbd_delete_driver(&kbdmux_kbd_driver);
1349 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1350 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1351 kbd_delete_driver(&kbdmux_kbd_driver);
1355 #ifdef KBD_INSTALL_CDEV
1356 if ((error = kbd_attach(kbd)) != 0) {
1358 kbd_delete_driver(&kbdmux_kbd_driver);
1363 if ((error = (*sw->enable)(kbd)) != 0) {
1364 (*sw->disable)(kbd);
1365 #ifdef KBD_INSTALL_CDEV
1369 kbd_delete_driver(&kbdmux_kbd_driver);
1375 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1376 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1378 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1380 (*sw->disable)(kbd);
1381 #ifdef KBD_INSTALL_CDEV
1385 kbd_delete_driver(&kbdmux_kbd_driver);
1398 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);