4 * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
34 #include <sys/param.h>
37 #include <sys/consio.h>
38 #include <sys/fcntl.h>
40 #include <sys/kernel.h>
41 #include <sys/limits.h>
43 #include <sys/malloc.h>
44 #include <sys/module.h>
45 #include <sys/mutex.h>
48 #include <sys/queue.h>
49 #include <sys/event.h>
50 #include <sys/systm.h>
51 #include <sys/taskqueue.h>
53 #include <dev/misc/kbd/kbdreg.h>
54 #include <dev/misc/kbd/kbdtables.h>
56 #define KEYBOARD_NAME "kbdmux"
58 MALLOC_DECLARE(M_KBDMUX);
59 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
61 /*****************************************************************************
62 *****************************************************************************
64 *****************************************************************************
65 *****************************************************************************/
67 #define KBDMUX_Q_SIZE 512 /* input queue size */
69 #define KBDMUX_CALLOUT_INIT(s) \
70 callout_init_mp(&(s)->ks_timo)
72 #define KBDMUX_QUEUE_INTR(s) \
73 taskqueue_enqueue(taskqueue_swi, &(s)->ks_task)
80 keyboard_t *kbd; /* keyboard */
81 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
84 typedef struct kbdmux_kbd kbdmux_kbd_t;
91 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
92 unsigned int ks_inq_start;
93 unsigned int ks_inq_length;
94 struct task ks_task; /* interrupt task */
95 struct callout ks_timo; /* timeout handler */
96 #define TICKS (hz) /* rate */
98 int ks_flags; /* flags */
99 #define COMPOSE (1 << 0) /* compose char flag */
100 #define POLLING (1 << 1) /* polling */
101 #define TASK (1 << 2) /* interrupt task queued */
103 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
104 int ks_state; /* state */
105 int ks_accents; /* accent key index (> 0) */
106 u_int ks_composed_char; /* composed char code */
107 u_char ks_prefix; /* AT scan code prefix */
109 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
112 typedef struct kbdmux_state kbdmux_state_t;
114 /*****************************************************************************
115 *****************************************************************************
117 *****************************************************************************
118 *****************************************************************************/
120 static task_fn_t kbdmux_kbd_intr;
121 static timeout_t kbdmux_kbd_intr_timo;
122 static kbd_callback_func_t kbdmux_kbd_event;
125 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
129 if (state->ks_inq_length == KBDMUX_Q_SIZE)
132 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
133 state->ks_inq[p] = c;
134 state->ks_inq_length++;
138 kbdmux_kbd_getc(kbdmux_state_t *state)
142 if (state->ks_inq_length == 0)
145 c = state->ks_inq[state->ks_inq_start];
146 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
147 state->ks_inq_length--;
153 * Interrupt handler task
156 kbdmux_kbd_intr(void *xkbd, int pending)
158 keyboard_t *kbd = (keyboard_t *) xkbd;
159 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
162 KBD_LOCK(kbd); /* recursive so ok */
164 state->ks_flags &= ~TASK;
165 wakeup(&state->ks_task);
170 * Schedule interrupt handler on timeout. Called with locked state.
173 kbdmux_kbd_intr_timo(void *xkbd)
175 keyboard_t *kbd = (keyboard_t *) xkbd;
176 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
181 if (callout_pending(&state->ks_timo)) {
183 return; /* callout was reset */
186 if (!callout_active(&state->ks_timo)) {
188 return; /* callout was stopped */
191 callout_deactivate(&state->ks_timo);
193 /* queue interrupt task if needed */
194 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
195 KBDMUX_QUEUE_INTR(state) == 0)
196 state->ks_flags |= TASK;
198 /* re-schedule timeout */
199 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, kbd);
204 * Process event from one of our keyboards
207 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
209 kbdmux_state_t *state = (kbdmux_state_t *) arg;
212 case KBDIO_KEYINPUT: {
216 * Read all chars from the keyboard
218 * Turns out that atkbd(4) check_char() method may return
219 * "true" while read_char() method returns NOKEY. If this
220 * happens we could stuck in the loop below. Avoid this
221 * by breaking out of the loop if read_char() method returns
225 while (kbd_check_char(kbd)) {
226 c = kbd_read_char(kbd, 0);
230 continue; /* XXX ring bell */
231 if (!KBD_IS_BUSY(kbd))
232 continue; /* not open - discard the input */
234 kbdmux_kbd_putc(state, c);
237 /* queue interrupt task if needed */
238 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
239 KBDMUX_QUEUE_INTR(state) == 0)
240 state->ks_flags |= TASK;
244 case KBDIO_UNLOADING: {
247 SLIST_FOREACH(k, &state->ks_kbds, next)
252 kbd_release(k->kbd, &k->kbd);
253 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
269 /****************************************************************************
270 ****************************************************************************
272 ****************************************************************************
273 ****************************************************************************/
275 static int kbdmux_configure(int flags);
276 static kbd_probe_t kbdmux_probe;
277 static kbd_init_t kbdmux_init;
278 static kbd_term_t kbdmux_term;
279 static kbd_intr_t kbdmux_intr;
280 static kbd_test_if_t kbdmux_test_if;
281 static kbd_enable_t kbdmux_enable;
282 static kbd_disable_t kbdmux_disable;
283 static kbd_read_t kbdmux_read;
284 static kbd_check_t kbdmux_check;
285 static kbd_read_char_t kbdmux_read_char;
286 static kbd_check_char_t kbdmux_check_char;
287 static kbd_ioctl_t kbdmux_ioctl;
288 static kbd_lock_t kbdmux_lock;
289 static kbd_clear_state_t kbdmux_clear_state;
290 static kbd_get_state_t kbdmux_get_state;
291 static kbd_set_state_t kbdmux_set_state;
292 static kbd_poll_mode_t kbdmux_poll;
294 static keyboard_switch_t kbdmuxsw = {
295 .probe = kbdmux_probe,
299 .test_if = kbdmux_test_if,
300 .enable = kbdmux_enable,
301 .disable = kbdmux_disable,
303 .check = kbdmux_check,
304 .read_char = kbdmux_read_char,
305 .check_char = kbdmux_check_char,
306 .ioctl = kbdmux_ioctl,
308 .clear_state = kbdmux_clear_state,
309 .get_state = kbdmux_get_state,
310 .set_state = kbdmux_set_state,
311 .get_fkeystr = genkbd_get_fkeystr,
317 * Return the number of found keyboards
320 kbdmux_configure(int flags)
329 kbdmux_probe(int unit, void *arg, int flags)
331 if (resource_disabled(KEYBOARD_NAME, unit))
338 * Reset and initialize the keyboard (stolen from atkbd.c)
340 * Called without kbd lock held.
343 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
345 kbdmux_state_t *state = NULL;
346 keymap_t *keymap = NULL;
347 accentmap_t *accmap = NULL;
348 fkeytab_t *fkeymap = NULL;
349 keyboard_t *kbd = NULL;
350 int error, needfree, fkeymap_size, delay[2];
353 *kbdp = kbd = kmalloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
354 state = kmalloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
355 keymap = kmalloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
356 accmap = kmalloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
357 fkeymap = kmalloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
358 fkeymap_size = NELEM(fkey_tab);
361 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
362 (accmap == NULL) || (fkeymap == NULL)) {
367 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
368 KBDMUX_CALLOUT_INIT(state);
369 SLIST_INIT(&state->ks_kbds);
370 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
374 state = (kbdmux_state_t *) kbd->kb_data;
375 keymap = kbd->kb_keymap;
376 accmap = kbd->kb_accentmap;
377 fkeymap = kbd->kb_fkeytab;
378 fkeymap_size = kbd->kb_fkeytab_size;
382 if (!KBD_IS_PROBED(kbd)) {
383 /* XXX assume 101/102 keys keyboard */
384 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags,
386 bcopy(&key_map, keymap, sizeof(key_map));
387 bcopy(&accent_map, accmap, sizeof(accent_map));
388 bcopy(fkey_tab, fkeymap,
389 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
390 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
391 kbd->kb_data = (void *)state;
393 KBD_FOUND_DEVICE(kbd);
396 kbdmux_clear_state(kbd);
397 state->ks_mode = K_XLATE;
400 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
401 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
403 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
405 delay[0] = kbd->kb_delay1;
406 delay[1] = kbd->kb_delay2;
407 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
412 if (!KBD_IS_CONFIGURED(kbd)) {
413 if (kbd_register(kbd) < 0) {
418 KBD_CONFIG_DONE(kbd);
420 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, kbd);
427 kfree(state, M_KBDMUX);
429 kfree(keymap, M_KBDMUX);
431 kfree(accmap, M_KBDMUX);
433 kfree(fkeymap, M_KBDMUX);
435 kfree(kbd, M_KBDMUX);
436 *kbdp = NULL; /* insure ref doesn't leak to caller */
444 * Finish using this keyboard
446 * NOTE: deregistration automatically unlocks lock.
449 kbdmux_term(keyboard_t *kbd)
451 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
455 callout_stop(&state->ks_timo);
457 /* wait for interrupt task */
458 while (state->ks_flags & TASK)
459 lksleep(&state->ks_task, &kbd->kb_lock, PCATCH, "kbdmuxc", 0);
461 /* release all keyboards from the mux */
462 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
463 kbd_release(k->kbd, &k->kbd);
464 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
473 bzero(state, sizeof(*state));
474 kfree(state, M_KBDMUX);
476 kfree(kbd->kb_keymap, M_KBDMUX);
477 kfree(kbd->kb_accentmap, M_KBDMUX);
478 kfree(kbd->kb_fkeytab, M_KBDMUX);
479 kfree(kbd, M_KBDMUX);
485 * Keyboard interrupt routine
488 kbdmux_intr(keyboard_t *kbd, void *arg)
492 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
493 /* let the callback function to process the input */
494 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
495 kbd->kb_callback.kc_arg);
497 /* read and discard the input; no one is waiting for input */
499 c = kbdmux_read_char(kbd, FALSE);
500 } while (c != NOKEY);
507 * Test the interface to the device
510 kbdmux_test_if(keyboard_t *kbd)
516 * Enable the access to the device; until this function is called,
517 * the client cannot read from the keyboard.
520 kbdmux_enable(keyboard_t *kbd)
527 * Disallow the access to the device
530 kbdmux_disable(keyboard_t *kbd)
537 * Read one byte from the keyboard if it's allowed
540 kbdmux_read(keyboard_t *kbd, int wait)
542 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
546 c = kbdmux_kbd_getc(state);
547 } while (c == -1 && wait);
552 ret = (KBD_IS_ACTIVE(kbd)? c : -1);
558 * Check if data is waiting
561 kbdmux_check(keyboard_t *kbd)
563 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
566 if (!KBD_IS_ACTIVE(kbd))
569 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
575 * Read char from the keyboard (stolen from atkbd.c)
577 * Note: We do not attempt to detect the case where no keyboards are
578 * present in the wait case. If the kernel is sitting at the
579 * debugger prompt we want someone to be able to plug in a keyboard
580 * and have it work, and not just panic or fall through or do
581 * something equally nasty.
584 kbdmux_read_char(keyboard_t *kbd, int wait)
586 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
588 int scancode, keycode;
592 /* do we have a composed char to return? */
593 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
594 action = state->ks_composed_char;
595 state->ks_composed_char = 0;
596 if (action > UCHAR_MAX) {
603 * See if there is something in the keyboard queue
605 scancode = kbdmux_kbd_getc(state);
607 if (scancode == -1) {
608 if (state->ks_flags & POLLING) {
611 SLIST_FOREACH(k, &state->ks_kbds, next) {
612 while (kbd_check_char(k->kbd)) {
613 scancode = kbd_read_char(k->kbd, 0);
614 if (scancode == ERRKEY)
616 if (scancode == NOKEY)
618 if (!KBD_IS_BUSY(k->kbd))
620 kbdmux_kbd_putc(state, scancode);
624 if (state->ks_inq_length > 0)
630 lksleep(&state->ks_task, &kbd->kb_lock, PCATCH,
640 /* return the byte as is for the K_RAW mode */
641 if (state->ks_mode == K_RAW)
644 /* translate the scan code into a keycode */
645 keycode = scancode & 0x7F;
646 switch (state->ks_prefix) {
647 case 0x00: /* normal scancode */
649 case 0xB8: /* left alt (compose key) released */
650 if (state->ks_flags & COMPOSE) {
651 state->ks_flags &= ~COMPOSE;
652 if (state->ks_composed_char > UCHAR_MAX)
653 state->ks_composed_char = 0;
656 case 0x38: /* left alt (compose key) pressed */
657 if (!(state->ks_flags & COMPOSE)) {
658 state->ks_flags |= COMPOSE;
659 state->ks_composed_char = 0;
664 state->ks_prefix = scancode;
668 case 0xE0: /* 0xE0 prefix */
669 state->ks_prefix = 0;
671 case 0x1C: /* right enter key */
674 case 0x1D: /* right ctrl key */
677 case 0x35: /* keypad divide key */
680 case 0x37: /* print scrn key */
683 case 0x38: /* right alt key (alt gr) */
686 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
689 case 0x47: /* grey home key */
692 case 0x48: /* grey up arrow key */
695 case 0x49: /* grey page up key */
698 case 0x4B: /* grey left arrow key */
701 case 0x4D: /* grey right arrow key */
704 case 0x4F: /* grey end key */
707 case 0x50: /* grey down arrow key */
710 case 0x51: /* grey page down key */
713 case 0x52: /* grey insert key */
716 case 0x53: /* grey delete key */
719 /* the following 3 are only used on the MS "Natural" keyboard */
720 case 0x5b: /* left Window key */
723 case 0x5c: /* right Window key */
726 case 0x5d: /* menu key */
729 case 0x5e: /* power key */
732 case 0x5f: /* sleep key */
735 case 0x63: /* wake key */
738 case 0x64: /* [JP106USB] backslash, underscore */
741 default: /* ignore everything else */
745 case 0xE1: /* 0xE1 prefix */
747 * The pause/break key on the 101 keyboard produces:
749 * Ctrl-pause/break produces:
750 * E0-46 E0-C6 (See above.)
752 state->ks_prefix = 0;
754 state->ks_prefix = 0x1D;
757 case 0x1D: /* pause / break */
758 state->ks_prefix = 0;
765 /* XXX assume 101/102 keys AT keyboard */
767 case 0x5c: /* print screen */
768 if (state->ks_flags & ALTS)
769 keycode = 0x54; /* sysrq */
771 case 0x68: /* pause/break */
772 if (state->ks_flags & CTLS)
773 keycode = 0x6c; /* break */
777 /* return the key code in the K_CODE mode */
778 if (state->ks_mode == K_CODE)
779 return (keycode | (scancode & 0x80));
781 /* compose a character code */
782 if (state->ks_flags & COMPOSE) {
783 switch (keycode | (scancode & 0x80)) {
784 /* key pressed, process it */
785 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
786 state->ks_composed_char *= 10;
787 state->ks_composed_char += keycode - 0x40;
788 if (state->ks_composed_char > UCHAR_MAX)
791 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
792 state->ks_composed_char *= 10;
793 state->ks_composed_char += keycode - 0x47;
794 if (state->ks_composed_char > UCHAR_MAX)
797 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
798 state->ks_composed_char *= 10;
799 state->ks_composed_char += keycode - 0x4E;
800 if (state->ks_composed_char > UCHAR_MAX)
803 case 0x52: /* keypad 0 */
804 state->ks_composed_char *= 10;
805 if (state->ks_composed_char > UCHAR_MAX)
809 /* key released, no interest here */
810 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
811 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
812 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
813 case 0xD2: /* keypad 0 */
816 case 0x38: /* left alt key */
820 if (state->ks_composed_char > 0) {
821 state->ks_flags &= ~COMPOSE;
822 state->ks_composed_char = 0;
829 /* keycode to key action */
830 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
831 &state->ks_state, &state->ks_accents);
839 * Check if char is waiting
842 kbdmux_check_char(keyboard_t *kbd)
844 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
847 if (!KBD_IS_ACTIVE(kbd))
850 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
853 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
862 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
864 static int delays[] = {
868 static int rates[] = {
869 34, 38, 42, 46, 50, 55, 59, 63,
870 68, 76, 84, 92, 100, 110, 118, 126,
871 136, 152, 168, 184, 200, 220, 236, 252,
872 272, 304, 336, 368, 400, 440, 472, 504
875 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
884 case KBADDKBD: /* add keyboard to the mux */
885 ki = (keyboard_info_t *) arg;
887 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
888 strcmp(ki->kb_name, "*") == 0) {
889 return (EINVAL); /* bad input */
892 SLIST_FOREACH(k, &state->ks_kbds, next)
893 if (k->kbd->kb_unit == ki->kb_unit &&
894 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
898 return (0); /* keyboard already in the mux */
900 k = kmalloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
902 return (ENOMEM); /* out of memory */
904 k->kbd = kbd_get_keyboard(
909 kbdmux_kbd_event, (void *) state));
910 if (k->kbd == NULL) {
912 return (EINVAL); /* bad keyboard */
916 kbd_clear_state(k->kbd);
918 /* set K_RAW mode on slave keyboard */
920 error = kbd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
922 /* set lock keys state on slave keyboard */
923 mode = state->ks_state & LOCK_MASK;
924 error = kbd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
928 kbd_release(k->kbd, &k->kbd);
931 return (error); /* could not set mode */
934 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
937 case KBRELKBD: /* release keyboard from the mux */
938 ki = (keyboard_info_t *) arg;
940 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
941 strcmp(ki->kb_name, "*") == 0) {
942 return (EINVAL); /* bad input */
945 SLIST_FOREACH(k, &state->ks_kbds, next)
946 if (k->kbd->kb_unit == ki->kb_unit &&
947 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
951 error = kbd_release(k->kbd, &k->kbd);
953 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
960 error = ENXIO; /* keyboard is not in the mux */
964 case KDGKBMODE: /* get kyboard mode */
965 *(int *)arg = state->ks_mode;
968 case KDSKBMODE: /* set keyboard mode */
969 switch (*(int *)arg) {
971 if (state->ks_mode != K_XLATE) {
972 /* make lock key state and LED state match */
973 state->ks_state &= ~LOCK_MASK;
974 state->ks_state |= KBD_LED_VAL(kbd);
980 if (state->ks_mode != *(int *)arg) {
981 kbdmux_clear_state(kbd);
982 state->ks_mode = *(int *)arg;
992 case KDGETLED: /* get keyboard LED */
993 *(int *)arg = KBD_LED_VAL(kbd);
996 case KDSETLED: /* set keyboard LED */
997 /* NOTE: lock key state in ks_state won't be changed */
998 if (*(int *)arg & ~LOCK_MASK)
1001 KBD_LED_VAL(kbd) = *(int *)arg;
1003 /* KDSETLED on all slave keyboards */
1004 SLIST_FOREACH(k, &state->ks_kbds, next)
1005 kbd_ioctl(k->kbd, KDSETLED, arg);
1008 case KDGKBSTATE: /* get lock key state */
1009 *(int *)arg = state->ks_state & LOCK_MASK;
1012 case KDSKBSTATE: /* set lock key state */
1013 if (*(int *)arg & ~LOCK_MASK)
1016 state->ks_state &= ~LOCK_MASK;
1017 state->ks_state |= *(int *)arg;
1019 /* KDSKBSTATE on all slave keyboards */
1020 SLIST_FOREACH(k, &state->ks_kbds, next)
1021 kbd_ioctl(k->kbd, KDSKBSTATE, arg);
1023 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1026 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1027 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1028 if (cmd == KDSETREPEAT) {
1032 for (i = NELEM(delays) - 1; i > 0; i --)
1033 if (((int *)arg)[0] >= delays[i])
1038 for (i = NELEM(rates) - 1; i > 0; i --)
1039 if (((int *)arg)[1] >= rates[i])
1048 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1049 kbd->kb_delay2 = rates[mode & 0x1f];
1051 /* perform command on all slave keyboards */
1052 SLIST_FOREACH(k, &state->ks_kbds, next)
1053 kbd_ioctl(k->kbd, cmd, arg);
1056 case PIO_KEYMAP: /* set keyboard translation table */
1057 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1058 case PIO_DEADKEYMAP: /* set accent key translation table */
1059 state->ks_accents = 0;
1061 /* perform command on all slave keyboards */
1062 SLIST_FOREACH(k, &state->ks_kbds, next)
1063 kbd_ioctl(k->kbd, cmd, arg);
1067 error = genkbd_commonioctl(kbd, cmd, arg);
1074 * Lock the access to the keyboard
1077 kbdmux_lock(keyboard_t *kbd, int lock)
1079 return (1); /* XXX */
1083 * Clear the internal state of the keyboard
1085 * NOTE: May be called unlocked from init
1088 kbdmux_clear_state(keyboard_t *kbd)
1090 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1092 state->ks_flags &= ~(COMPOSE|POLLING);
1093 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1094 state->ks_accents = 0;
1095 state->ks_composed_char = 0;
1096 /* state->ks_prefix = 0; XXX */
1097 state->ks_inq_length = 0;
1101 * Save the internal state
1104 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1107 return (sizeof(kbdmux_state_t));
1108 if (len < sizeof(kbdmux_state_t))
1111 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1117 * Set the internal state
1120 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1122 if (len < sizeof(kbdmux_state_t))
1125 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1133 * Caller interlocks all keyboard calls. We must not lock here.
1136 kbdmux_poll(keyboard_t *kbd, int on)
1138 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1142 state->ks_flags |= POLLING;
1144 state->ks_flags &= ~POLLING;
1146 /* set poll on slave keyboards */
1147 SLIST_FOREACH(k, &state->ks_kbds, next)
1148 kbd_poll(k->kbd, on);
1153 /*****************************************************************************
1154 *****************************************************************************
1156 *****************************************************************************
1157 *****************************************************************************/
1159 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1162 kbdmux_modevent(module_t mod, int type, void *data)
1164 keyboard_switch_t *sw;
1170 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1173 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1174 kbd_delete_driver(&kbdmux_kbd_driver);
1181 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1182 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1183 kbd_delete_driver(&kbdmux_kbd_driver);
1187 #ifdef KBD_INSTALL_CDEV
1188 if ((error = kbd_attach(kbd)) != 0) {
1190 kbd_delete_driver(&kbdmux_kbd_driver);
1195 if ((error = (*sw->enable)(kbd)) != 0) {
1196 (*sw->disable)(kbd);
1197 #ifdef KBD_INSTALL_CDEV
1201 kbd_delete_driver(&kbdmux_kbd_driver);
1207 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1208 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1210 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1212 (*sw->disable)(kbd);
1213 #ifdef KBD_INSTALL_CDEV
1217 kbd_delete_driver(&kbdmux_kbd_driver);
1229 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);