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 $
36 #include <sys/param.h>
39 #include <sys/consio.h>
40 #include <sys/fcntl.h>
42 #include <sys/kernel.h>
43 #include <sys/limits.h>
45 #include <sys/malloc.h>
46 #include <sys/module.h>
47 #include <sys/mutex.h>
50 #include <sys/queue.h>
51 #include <sys/selinfo.h>
52 #include <sys/systm.h>
53 #include <sys/taskqueue.h>
55 #include <dev/misc/kbd/kbdreg.h>
56 #include <dev/misc/kbd/kbdtables.h>
58 #define KEYBOARD_NAME "kbdmux"
60 MALLOC_DECLARE(M_KBDMUX);
61 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
63 /*****************************************************************************
64 *****************************************************************************
66 *****************************************************************************
67 *****************************************************************************/
69 #define KBDMUX_Q_SIZE 512 /* input queue size */
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
77 * XXX: I don't think we are MP-Safing the callout, maybe we
78 * should, using get_mplock() around it? NFI
82 #error "This stuff still needs porting!"
83 #define KBDMUX_LOCK_DECL_GLOBAL \
85 #define KBDMUX_LOCK_INIT(s) \
86 mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
87 #define KBDMUX_LOCK_DESTROY(s) \
88 mtx_destroy(&(s)->ks_lock)
89 #define KBDMUX_LOCK(s) \
90 mtx_lock(&(s)->ks_lock)
91 #define KBDMUX_UNLOCK(s) \
92 mtx_unlock(&(s)->ks_lock)
93 #define KBDMUX_LOCK_ASSERT(s, w) \
94 mtx_assert(&(s)->ks_lock, (w))
95 #define KBDMUX_SLEEP(s, f, d, t) \
96 msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
97 #define KBDMUX_CALLOUT_INIT(s) \
98 callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
99 #define KBDMUX_QUEUE_INTR(s) \
100 taskqueue_enqueue(taskqueue_swi, &(s)->ks_task)
102 #define KBDMUX_LOCK_DECL_GLOBAL
104 #define KBDMUX_LOCK_INIT(s)
106 #define KBDMUX_LOCK_DESTROY(s)
108 #define KBDMUX_LOCK(s)
110 #define KBDMUX_UNLOCK(s)
112 #define KBDMUX_LOCK_ASSERT(s, w)
114 #define KBDMUX_SLEEP(s, f, d, t) \
115 tsleep(&(s)->f, PCATCH | (84 + 1), (d), (t))
116 #define KBDMUX_CALLOUT_INIT(s) \
117 callout_init(&(s)->ks_timo)
118 #define KBDMUX_QUEUE_INTR(s) \
119 taskqueue_enqueue(taskqueue_swi, &(s)->ks_task)
127 keyboard_t *kbd; /* keyboard */
128 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
131 typedef struct kbdmux_kbd kbdmux_kbd_t;
138 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
139 unsigned int ks_inq_start;
140 unsigned int ks_inq_length;
141 struct task ks_task; /* interrupt task */
142 struct callout ks_timo; /* timeout handler */
143 #define TICKS (hz) /* rate */
145 int ks_flags; /* flags */
146 #define COMPOSE (1 << 0) /* compose char flag */
147 #define POLLING (1 << 1) /* polling */
148 #define TASK (1 << 2) /* interrupt task queued */
150 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
151 int ks_state; /* state */
152 int ks_accents; /* accent key index (> 0) */
153 u_int ks_composed_char; /* composed char code */
154 u_char ks_prefix; /* AT scan code prefix */
156 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
158 KBDMUX_LOCK_DECL_GLOBAL;
161 typedef struct kbdmux_state kbdmux_state_t;
163 /*****************************************************************************
164 *****************************************************************************
166 *****************************************************************************
167 *****************************************************************************/
169 static task_fn_t kbdmux_kbd_intr;
170 static timeout_t kbdmux_kbd_intr_timo;
171 static kbd_callback_func_t kbdmux_kbd_event;
174 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
178 if (state->ks_inq_length == KBDMUX_Q_SIZE)
181 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
182 state->ks_inq[p] = c;
183 state->ks_inq_length++;
187 kbdmux_kbd_getc(kbdmux_state_t *state)
191 if (state->ks_inq_length == 0)
194 c = state->ks_inq[state->ks_inq_start];
195 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
196 state->ks_inq_length--;
202 * Interrupt handler task
205 kbdmux_kbd_intr(void *xkbd, int pending)
207 keyboard_t *kbd = (keyboard_t *) xkbd;
208 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
214 state->ks_flags &= ~TASK;
215 wakeup(&state->ks_task);
217 KBDMUX_UNLOCK(state);
221 * Schedule interrupt handler on timeout. Called with locked state.
224 kbdmux_kbd_intr_timo(void *xstate)
226 kbdmux_state_t *state = (kbdmux_state_t *) xstate;
228 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
230 if (callout_pending(&state->ks_timo))
231 return; /* callout was reset */
233 if (!callout_active(&state->ks_timo))
234 return; /* callout was stopped */
236 callout_deactivate(&state->ks_timo);
238 /* queue interrupt task if needed */
239 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
240 KBDMUX_QUEUE_INTR(state) == 0)
241 state->ks_flags |= TASK;
243 /* re-schedule timeout */
244 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
248 * Process event from one of our keyboards
251 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
253 kbdmux_state_t *state = (kbdmux_state_t *) arg;
256 case KBDIO_KEYINPUT: {
262 * Read all chars from the keyboard
264 * Turns out that atkbd(4) check_char() method may return
265 * "true" while read_char() method returns NOKEY. If this
266 * happens we could stuck in the loop below. Avoid this
267 * by breaking out of the loop if read_char() method returns
271 while (kbd_check_char(kbd)) {
272 c = kbd_read_char(kbd, 0);
276 continue; /* XXX ring bell */
277 if (!KBD_IS_BUSY(kbd))
278 continue; /* not open - discard the input */
280 kbdmux_kbd_putc(state, c);
283 /* queue interrupt task if needed */
284 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
285 KBDMUX_QUEUE_INTR(state) == 0)
286 state->ks_flags |= TASK;
288 KBDMUX_UNLOCK(state);
291 case KBDIO_UNLOADING: {
296 SLIST_FOREACH(k, &state->ks_kbds, next)
301 kbd_release(k->kbd, &k->kbd);
302 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
309 KBDMUX_UNLOCK(state);
320 /****************************************************************************
321 ****************************************************************************
323 ****************************************************************************
324 ****************************************************************************/
326 static int kbdmux_configure(int flags);
327 static kbd_probe_t kbdmux_probe;
328 static kbd_init_t kbdmux_init;
329 static kbd_term_t kbdmux_term;
330 static kbd_intr_t kbdmux_intr;
331 static kbd_test_if_t kbdmux_test_if;
332 static kbd_enable_t kbdmux_enable;
333 static kbd_disable_t kbdmux_disable;
334 static kbd_read_t kbdmux_read;
335 static kbd_check_t kbdmux_check;
336 static kbd_read_char_t kbdmux_read_char;
337 static kbd_check_char_t kbdmux_check_char;
338 static kbd_ioctl_t kbdmux_ioctl;
339 static kbd_lock_t kbdmux_lock;
340 static void kbdmux_clear_state_locked(kbdmux_state_t *state);
341 static kbd_clear_state_t kbdmux_clear_state;
342 static kbd_get_state_t kbdmux_get_state;
343 static kbd_set_state_t kbdmux_set_state;
344 static kbd_poll_mode_t kbdmux_poll;
346 static keyboard_switch_t kbdmuxsw = {
347 .probe = kbdmux_probe,
351 .test_if = kbdmux_test_if,
352 .enable = kbdmux_enable,
353 .disable = kbdmux_disable,
355 .check = kbdmux_check,
356 .read_char = kbdmux_read_char,
357 .check_char = kbdmux_check_char,
358 .ioctl = kbdmux_ioctl,
360 .clear_state = kbdmux_clear_state,
361 .get_state = kbdmux_get_state,
362 .set_state = kbdmux_set_state,
363 .get_fkeystr = genkbd_get_fkeystr,
369 * Return the number of found keyboards
372 kbdmux_configure(int flags)
381 kbdmux_probe(int unit, void *arg, int flags)
383 if (resource_disabled(KEYBOARD_NAME, unit))
390 * Reset and initialize the keyboard (stolen from atkbd.c)
393 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
395 keyboard_t *kbd = NULL;
396 kbdmux_state_t *state = NULL;
397 keymap_t *keymap = NULL;
398 accentmap_t *accmap = NULL;
399 fkeytab_t *fkeymap = NULL;
400 int error, needfree, fkeymap_size, delay[2];
403 *kbdp = kbd = kmalloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
404 state = kmalloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
405 keymap = kmalloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
406 accmap = kmalloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
407 fkeymap = kmalloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
408 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
411 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
412 (accmap == NULL) || (fkeymap == NULL)) {
417 KBDMUX_LOCK_INIT(state);
418 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
419 KBDMUX_CALLOUT_INIT(state);
420 SLIST_INIT(&state->ks_kbds);
421 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
425 state = (kbdmux_state_t *) kbd->kb_data;
426 keymap = kbd->kb_keymap;
427 accmap = kbd->kb_accentmap;
428 fkeymap = kbd->kb_fkeytab;
429 fkeymap_size = kbd->kb_fkeytab_size;
433 if (!KBD_IS_PROBED(kbd)) {
434 /* XXX assume 101/102 keys keyboard */
435 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags,
437 bcopy(&key_map, keymap, sizeof(key_map));
438 bcopy(&accent_map, accmap, sizeof(accent_map));
439 bcopy(fkey_tab, fkeymap,
440 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
441 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
442 kbd->kb_data = (void *)state;
444 KBD_FOUND_DEVICE(kbd);
448 kbdmux_clear_state_locked(state);
449 state->ks_mode = K_XLATE;
450 KBDMUX_UNLOCK(state);
453 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
454 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
456 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
458 delay[0] = kbd->kb_delay1;
459 delay[1] = kbd->kb_delay2;
460 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
465 if (!KBD_IS_CONFIGURED(kbd)) {
466 if (kbd_register(kbd) < 0) {
471 KBD_CONFIG_DONE(kbd);
474 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
475 KBDMUX_UNLOCK(state);
482 kfree(state, M_KBDMUX);
484 kfree(keymap, M_KBDMUX);
486 kfree(accmap, M_KBDMUX);
488 kfree(fkeymap, M_KBDMUX);
490 kfree(kbd, M_KBDMUX);
491 *kbdp = NULL; /* insure ref doesn't leak to caller */
499 * Finish using this keyboard
502 kbdmux_term(keyboard_t *kbd)
504 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
510 callout_stop(&state->ks_timo);
512 /* wait for interrupt task */
513 while (state->ks_flags & TASK)
514 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
516 /* release all keyboards from the mux */
517 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
518 kbd_release(k->kbd, &k->kbd);
519 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
526 KBDMUX_UNLOCK(state);
530 KBDMUX_LOCK_DESTROY(state);
531 bzero(state, sizeof(*state));
532 kfree(state, M_KBDMUX);
534 kfree(kbd->kb_keymap, M_KBDMUX);
535 kfree(kbd->kb_accentmap, M_KBDMUX);
536 kfree(kbd->kb_fkeytab, M_KBDMUX);
537 kfree(kbd, M_KBDMUX);
543 * Keyboard interrupt routine
546 kbdmux_intr(keyboard_t *kbd, void *arg)
550 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
551 /* let the callback function to process the input */
552 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
553 kbd->kb_callback.kc_arg);
555 /* read and discard the input; no one is waiting for input */
557 c = kbdmux_read_char(kbd, FALSE);
558 } while (c != NOKEY);
565 * Test the interface to the device
568 kbdmux_test_if(keyboard_t *kbd)
574 * Enable the access to the device; until this function is called,
575 * the client cannot read from the keyboard.
578 kbdmux_enable(keyboard_t *kbd)
585 * Disallow the access to the device
588 kbdmux_disable(keyboard_t *kbd)
595 * Read one byte from the keyboard if it's allowed
598 kbdmux_read(keyboard_t *kbd, int wait)
600 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
605 c = kbdmux_kbd_getc(state);
606 } while (c == -1 && wait);
607 KBDMUX_UNLOCK(state);
612 return (KBD_IS_ACTIVE(kbd)? c : -1);
616 * Check if data is waiting
619 kbdmux_check(keyboard_t *kbd)
621 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
624 if (!KBD_IS_ACTIVE(kbd))
628 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
629 KBDMUX_UNLOCK(state);
635 * Read char from the keyboard (stolen from atkbd.c)
637 * Note: We do not attempt to detect the case where no keyboards are
638 * present in the wait case. If the kernel is sitting at the
639 * debugger prompt we want someone to be able to plug in a keyboard
640 * and have it work, and not just panic or fall through or do
641 * something equally nasty.
644 kbdmux_read_char(keyboard_t *kbd, int wait)
646 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
648 int scancode, keycode;
654 /* do we have a composed char to return? */
655 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
656 action = state->ks_composed_char;
657 state->ks_composed_char = 0;
658 if (action > UCHAR_MAX) {
659 KBDMUX_UNLOCK(state);
664 KBDMUX_UNLOCK(state);
670 * See if there is something in the keyboard queue
672 scancode = kbdmux_kbd_getc(state);
674 if (scancode == -1) {
675 if (state->ks_flags & POLLING) {
678 SLIST_FOREACH(k, &state->ks_kbds, next) {
679 while (kbd_check_char(k->kbd)) {
680 scancode = kbd_read_char(k->kbd, 0);
681 if (scancode == ERRKEY)
683 if (scancode == NOKEY)
685 if (!KBD_IS_BUSY(k->kbd))
687 kbdmux_kbd_putc(state, scancode);
691 if (state->ks_inq_length > 0)
697 KBDMUX_SLEEP(state, ks_task, "kbdwai", hz/10);
702 KBDMUX_UNLOCK(state);
708 /* return the byte as is for the K_RAW mode */
709 if (state->ks_mode == K_RAW) {
710 KBDMUX_UNLOCK(state);
714 /* translate the scan code into a keycode */
715 keycode = scancode & 0x7F;
716 switch (state->ks_prefix) {
717 case 0x00: /* normal scancode */
719 case 0xB8: /* left alt (compose key) released */
720 if (state->ks_flags & COMPOSE) {
721 state->ks_flags &= ~COMPOSE;
722 if (state->ks_composed_char > UCHAR_MAX)
723 state->ks_composed_char = 0;
726 case 0x38: /* left alt (compose key) pressed */
727 if (!(state->ks_flags & COMPOSE)) {
728 state->ks_flags |= COMPOSE;
729 state->ks_composed_char = 0;
734 state->ks_prefix = scancode;
738 case 0xE0: /* 0xE0 prefix */
739 state->ks_prefix = 0;
741 case 0x1C: /* right enter key */
744 case 0x1D: /* right ctrl key */
747 case 0x35: /* keypad divide key */
750 case 0x37: /* print scrn key */
753 case 0x38: /* right alt key (alt gr) */
756 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
759 case 0x47: /* grey home key */
762 case 0x48: /* grey up arrow key */
765 case 0x49: /* grey page up key */
768 case 0x4B: /* grey left arrow key */
771 case 0x4D: /* grey right arrow key */
774 case 0x4F: /* grey end key */
777 case 0x50: /* grey down arrow key */
780 case 0x51: /* grey page down key */
783 case 0x52: /* grey insert key */
786 case 0x53: /* grey delete key */
789 /* the following 3 are only used on the MS "Natural" keyboard */
790 case 0x5b: /* left Window key */
793 case 0x5c: /* right Window key */
796 case 0x5d: /* menu key */
799 case 0x5e: /* power key */
802 case 0x5f: /* sleep key */
805 case 0x63: /* wake key */
808 case 0x64: /* [JP106USB] backslash, underscore */
811 default: /* ignore everything else */
815 case 0xE1: /* 0xE1 prefix */
817 * The pause/break key on the 101 keyboard produces:
819 * Ctrl-pause/break produces:
820 * E0-46 E0-C6 (See above.)
822 state->ks_prefix = 0;
824 state->ks_prefix = 0x1D;
827 case 0x1D: /* pause / break */
828 state->ks_prefix = 0;
835 /* XXX assume 101/102 keys AT keyboard */
837 case 0x5c: /* print screen */
838 if (state->ks_flags & ALTS)
839 keycode = 0x54; /* sysrq */
841 case 0x68: /* pause/break */
842 if (state->ks_flags & CTLS)
843 keycode = 0x6c; /* break */
847 /* return the key code in the K_CODE mode */
848 if (state->ks_mode == K_CODE) {
849 KBDMUX_UNLOCK(state);
850 return (keycode | (scancode & 0x80));
853 /* compose a character code */
854 if (state->ks_flags & COMPOSE) {
855 switch (keycode | (scancode & 0x80)) {
856 /* key pressed, process it */
857 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
858 state->ks_composed_char *= 10;
859 state->ks_composed_char += keycode - 0x40;
860 if (state->ks_composed_char > UCHAR_MAX) {
861 KBDMUX_UNLOCK(state);
865 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
866 state->ks_composed_char *= 10;
867 state->ks_composed_char += keycode - 0x47;
868 if (state->ks_composed_char > UCHAR_MAX) {
869 KBDMUX_UNLOCK(state);
873 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
874 state->ks_composed_char *= 10;
875 state->ks_composed_char += keycode - 0x4E;
876 if (state->ks_composed_char > UCHAR_MAX) {
877 KBDMUX_UNLOCK(state);
881 case 0x52: /* keypad 0 */
882 state->ks_composed_char *= 10;
883 if (state->ks_composed_char > UCHAR_MAX) {
884 KBDMUX_UNLOCK(state);
889 /* key released, no interest here */
890 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
891 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
892 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
893 case 0xD2: /* keypad 0 */
896 case 0x38: /* left alt key */
900 if (state->ks_composed_char > 0) {
901 state->ks_flags &= ~COMPOSE;
902 state->ks_composed_char = 0;
903 KBDMUX_UNLOCK(state);
910 /* keycode to key action */
911 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
912 &state->ks_state, &state->ks_accents);
916 KBDMUX_UNLOCK(state);
922 * Check if char is waiting
925 kbdmux_check_char(keyboard_t *kbd)
927 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
930 if (!KBD_IS_ACTIVE(kbd))
935 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
938 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
940 KBDMUX_UNLOCK(state);
949 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
951 static int delays[] = {
955 static int rates[] = {
956 34, 38, 42, 46, 50, 55, 59, 63,
957 68, 76, 84, 92, 100, 110, 118, 126,
958 136, 152, 168, 184, 200, 220, 236, 252,
959 272, 304, 336, 368, 400, 440, 472, 504
962 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
971 case KBADDKBD: /* add keyboard to the mux */
972 ki = (keyboard_info_t *) arg;
974 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
975 strcmp(ki->kb_name, "*") == 0)
976 return (EINVAL); /* bad input */
980 SLIST_FOREACH(k, &state->ks_kbds, next)
981 if (k->kbd->kb_unit == ki->kb_unit &&
982 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
986 KBDMUX_UNLOCK(state);
988 return (0); /* keyboard already in the mux */
991 k = kmalloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
993 KBDMUX_UNLOCK(state);
995 return (ENOMEM); /* out of memory */
998 k->kbd = kbd_get_keyboard(
1003 kbdmux_kbd_event, (void *) state));
1004 if (k->kbd == NULL) {
1005 KBDMUX_UNLOCK(state);
1008 return (EINVAL); /* bad keyboard */
1012 kbd_clear_state(k->kbd);
1014 /* set K_RAW mode on slave keyboard */
1016 error = kbd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1018 /* set lock keys state on slave keyboard */
1019 mode = state->ks_state & LOCK_MASK;
1020 error = kbd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1024 KBDMUX_UNLOCK(state);
1026 kbd_release(k->kbd, &k->kbd);
1031 return (error); /* could not set mode */
1034 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1036 KBDMUX_UNLOCK(state);
1039 case KBRELKBD: /* release keyboard from the mux */
1040 ki = (keyboard_info_t *) arg;
1042 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1043 strcmp(ki->kb_name, "*") == 0)
1044 return (EINVAL); /* bad input */
1048 SLIST_FOREACH(k, &state->ks_kbds, next)
1049 if (k->kbd->kb_unit == ki->kb_unit &&
1050 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1054 error = kbd_release(k->kbd, &k->kbd);
1056 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1063 error = ENXIO; /* keyboard is not in the mux */
1065 KBDMUX_UNLOCK(state);
1068 case KDGKBMODE: /* get kyboard mode */
1070 *(int *)arg = state->ks_mode;
1071 KBDMUX_UNLOCK(state);
1074 case KDSKBMODE: /* set keyboard mode */
1077 switch (*(int *)arg) {
1079 if (state->ks_mode != K_XLATE) {
1080 /* make lock key state and LED state match */
1081 state->ks_state &= ~LOCK_MASK;
1082 state->ks_state |= KBD_LED_VAL(kbd);
1088 if (state->ks_mode != *(int *)arg) {
1089 kbdmux_clear_state_locked(state);
1090 state->ks_mode = *(int *)arg;
1099 KBDMUX_UNLOCK(state);
1102 case KDGETLED: /* get keyboard LED */
1104 *(int *)arg = KBD_LED_VAL(kbd);
1105 KBDMUX_UNLOCK(state);
1108 case KDSETLED: /* set keyboard LED */
1111 /* NOTE: lock key state in ks_state won't be changed */
1112 if (*(int *)arg & ~LOCK_MASK) {
1113 KBDMUX_UNLOCK(state);
1118 KBD_LED_VAL(kbd) = *(int *)arg;
1120 /* KDSETLED on all slave keyboards */
1121 SLIST_FOREACH(k, &state->ks_kbds, next)
1122 kbd_ioctl(k->kbd, KDSETLED, arg);
1124 KBDMUX_UNLOCK(state);
1127 case KDGKBSTATE: /* get lock key state */
1129 *(int *)arg = state->ks_state & LOCK_MASK;
1130 KBDMUX_UNLOCK(state);
1133 case KDSKBSTATE: /* set lock key state */
1136 if (*(int *)arg & ~LOCK_MASK) {
1137 KBDMUX_UNLOCK(state);
1142 state->ks_state &= ~LOCK_MASK;
1143 state->ks_state |= *(int *)arg;
1145 /* KDSKBSTATE on all slave keyboards */
1146 SLIST_FOREACH(k, &state->ks_kbds, next)
1147 kbd_ioctl(k->kbd, KDSKBSTATE, arg);
1149 KBDMUX_UNLOCK(state);
1151 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1154 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1155 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1158 if (cmd == KDSETREPEAT) {
1162 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1163 if (((int *)arg)[0] >= delays[i])
1168 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1169 if (((int *)arg)[1] >= rates[i])
1176 KBDMUX_UNLOCK(state);
1181 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1182 kbd->kb_delay2 = rates[mode & 0x1f];
1184 /* perform command on all slave keyboards */
1185 SLIST_FOREACH(k, &state->ks_kbds, next)
1186 kbd_ioctl(k->kbd, cmd, arg);
1188 KBDMUX_UNLOCK(state);
1191 case PIO_KEYMAP: /* set keyboard translation table */
1192 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1193 case PIO_DEADKEYMAP: /* set accent key translation table */
1195 state->ks_accents = 0;
1197 /* perform command on all slave keyboards */
1198 SLIST_FOREACH(k, &state->ks_kbds, next)
1199 kbd_ioctl(k->kbd, cmd, arg);
1201 KBDMUX_UNLOCK(state);
1205 error = genkbd_commonioctl(kbd, cmd, arg);
1213 * Lock the access to the keyboard
1216 kbdmux_lock(keyboard_t *kbd, int lock)
1218 return (1); /* XXX */
1222 * Clear the internal state of the keyboard
1225 kbdmux_clear_state_locked(kbdmux_state_t *state)
1227 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1229 state->ks_flags &= ~(COMPOSE|POLLING);
1230 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1231 state->ks_accents = 0;
1232 state->ks_composed_char = 0;
1233 /* state->ks_prefix = 0; XXX */
1234 state->ks_inq_length = 0;
1238 kbdmux_clear_state(keyboard_t *kbd)
1240 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1243 kbdmux_clear_state_locked(state);
1244 KBDMUX_UNLOCK(state);
1248 * Save the internal state
1251 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1254 return (sizeof(kbdmux_state_t));
1255 if (len < sizeof(kbdmux_state_t))
1258 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1264 * Set the internal state
1267 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1269 if (len < sizeof(kbdmux_state_t))
1272 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1281 kbdmux_poll(keyboard_t *kbd, int on)
1283 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1289 state->ks_flags |= POLLING;
1291 state->ks_flags &= ~POLLING;
1293 /* set poll on slave keyboards */
1294 SLIST_FOREACH(k, &state->ks_kbds, next)
1295 kbd_poll(k->kbd, on);
1297 KBDMUX_UNLOCK(state);
1302 /*****************************************************************************
1303 *****************************************************************************
1305 *****************************************************************************
1306 *****************************************************************************/
1308 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1311 kbdmux_modevent(module_t mod, int type, void *data)
1313 keyboard_switch_t *sw;
1319 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1322 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1323 kbd_delete_driver(&kbdmux_kbd_driver);
1330 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1331 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1332 kbd_delete_driver(&kbdmux_kbd_driver);
1336 #ifdef KBD_INSTALL_CDEV
1337 if ((error = kbd_attach(kbd)) != 0) {
1339 kbd_delete_driver(&kbdmux_kbd_driver);
1344 if ((error = (*sw->enable)(kbd)) != 0) {
1345 (*sw->disable)(kbd);
1346 #ifdef KBD_INSTALL_CDEV
1350 kbd_delete_driver(&kbdmux_kbd_driver);
1356 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1357 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1359 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1361 (*sw->disable)(kbd);
1362 #ifdef KBD_INSTALL_CDEV
1366 kbd_delete_driver(&kbdmux_kbd_driver);
1379 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);