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_LOCK_DECL_GLOBAL \
72 #define KBDMUX_SLEEP(s, f, d, t) \
73 lksleep(&(s)->f, &(s)->ks_lock, PCATCH, (d), (t))
75 #define KBDMUX_CALLOUT_INIT(s) \
76 callout_init_mp(&(s)->ks_timo)
78 #define KBDMUX_QUEUE_INTR(s) \
79 taskqueue_enqueue(taskqueue_swi, &(s)->ks_task)
86 keyboard_t *kbd; /* keyboard */
87 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
90 typedef struct kbdmux_kbd kbdmux_kbd_t;
97 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
98 unsigned int ks_inq_start;
99 unsigned int ks_inq_length;
100 struct task ks_task; /* interrupt task */
101 struct callout ks_timo; /* timeout handler */
102 #define TICKS (hz) /* rate */
104 int ks_flags; /* flags */
105 #define COMPOSE (1 << 0) /* compose char flag */
106 #define POLLING (1 << 1) /* polling */
107 #define TASK (1 << 2) /* interrupt task queued */
109 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
110 int ks_state; /* state */
111 int ks_accents; /* accent key index (> 0) */
112 u_int ks_composed_char; /* composed char code */
113 u_char ks_prefix; /* AT scan code prefix */
115 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
117 KBDMUX_LOCK_DECL_GLOBAL;
120 typedef struct kbdmux_state kbdmux_state_t;
122 /*****************************************************************************
123 *****************************************************************************
125 *****************************************************************************
126 *****************************************************************************/
128 static task_fn_t kbdmux_kbd_intr;
129 static timeout_t kbdmux_kbd_intr_timo;
130 static kbd_callback_func_t kbdmux_kbd_event;
133 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
137 if (state->ks_inq_length == KBDMUX_Q_SIZE)
140 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
141 state->ks_inq[p] = c;
142 state->ks_inq_length++;
146 kbdmux_kbd_getc(kbdmux_state_t *state)
150 if (state->ks_inq_length == 0)
153 c = state->ks_inq[state->ks_inq_start];
154 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
155 state->ks_inq_length--;
161 * Interrupt handler task
164 kbdmux_kbd_intr(void *xkbd, int pending)
166 keyboard_t *kbd = (keyboard_t *) xkbd;
167 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
170 KBD_LOCK(kbd); /* recursive so ok */
172 state->ks_flags &= ~TASK;
173 wakeup(&state->ks_task);
178 * Schedule interrupt handler on timeout. Called with locked state.
181 kbdmux_kbd_intr_timo(void *xkbd)
183 keyboard_t *kbd = (keyboard_t *) xkbd;
184 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
189 if (callout_pending(&state->ks_timo)) {
191 return; /* callout was reset */
194 if (!callout_active(&state->ks_timo)) {
196 return; /* callout was stopped */
199 callout_deactivate(&state->ks_timo);
201 /* queue interrupt task if needed */
202 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
203 KBDMUX_QUEUE_INTR(state) == 0)
204 state->ks_flags |= TASK;
206 /* re-schedule timeout */
207 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, kbd);
212 * Process event from one of our keyboards
215 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
217 kbdmux_state_t *state = (kbdmux_state_t *) arg;
220 case KBDIO_KEYINPUT: {
224 * Read all chars from the keyboard
226 * Turns out that atkbd(4) check_char() method may return
227 * "true" while read_char() method returns NOKEY. If this
228 * happens we could stuck in the loop below. Avoid this
229 * by breaking out of the loop if read_char() method returns
233 while (kbd_check_char(kbd)) {
234 c = kbd_read_char(kbd, 0);
238 continue; /* XXX ring bell */
239 if (!KBD_IS_BUSY(kbd))
240 continue; /* not open - discard the input */
242 kbdmux_kbd_putc(state, c);
245 /* queue interrupt task if needed */
246 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
247 KBDMUX_QUEUE_INTR(state) == 0)
248 state->ks_flags |= TASK;
252 case KBDIO_UNLOADING: {
255 SLIST_FOREACH(k, &state->ks_kbds, next)
260 kbd_release(k->kbd, &k->kbd);
261 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
277 /****************************************************************************
278 ****************************************************************************
280 ****************************************************************************
281 ****************************************************************************/
283 static int kbdmux_configure(int flags);
284 static kbd_probe_t kbdmux_probe;
285 static kbd_init_t kbdmux_init;
286 static kbd_term_t kbdmux_term;
287 static kbd_intr_t kbdmux_intr;
288 static kbd_test_if_t kbdmux_test_if;
289 static kbd_enable_t kbdmux_enable;
290 static kbd_disable_t kbdmux_disable;
291 static kbd_read_t kbdmux_read;
292 static kbd_check_t kbdmux_check;
293 static kbd_read_char_t kbdmux_read_char;
294 static kbd_check_char_t kbdmux_check_char;
295 static kbd_ioctl_t kbdmux_ioctl;
296 static kbd_lock_t kbdmux_lock;
297 static kbd_clear_state_t kbdmux_clear_state;
298 static kbd_get_state_t kbdmux_get_state;
299 static kbd_set_state_t kbdmux_set_state;
300 static kbd_poll_mode_t kbdmux_poll;
302 static keyboard_switch_t kbdmuxsw = {
303 .probe = kbdmux_probe,
307 .test_if = kbdmux_test_if,
308 .enable = kbdmux_enable,
309 .disable = kbdmux_disable,
311 .check = kbdmux_check,
312 .read_char = kbdmux_read_char,
313 .check_char = kbdmux_check_char,
314 .ioctl = kbdmux_ioctl,
316 .clear_state = kbdmux_clear_state,
317 .get_state = kbdmux_get_state,
318 .set_state = kbdmux_set_state,
319 .get_fkeystr = genkbd_get_fkeystr,
325 * Return the number of found keyboards
328 kbdmux_configure(int flags)
337 kbdmux_probe(int unit, void *arg, int flags)
339 if (resource_disabled(KEYBOARD_NAME, unit))
346 * Reset and initialize the keyboard (stolen from atkbd.c)
348 * Called without kbd lock held.
351 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
353 kbdmux_state_t *state = NULL;
354 keymap_t *keymap = NULL;
355 accentmap_t *accmap = NULL;
356 fkeytab_t *fkeymap = NULL;
357 keyboard_t *kbd = NULL;
358 int error, needfree, fkeymap_size, delay[2];
361 *kbdp = kbd = kmalloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
362 state = kmalloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
363 keymap = kmalloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
364 accmap = kmalloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
365 fkeymap = kmalloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
366 fkeymap_size = NELEM(fkey_tab);
369 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
370 (accmap == NULL) || (fkeymap == NULL)) {
375 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
376 KBDMUX_CALLOUT_INIT(state);
377 SLIST_INIT(&state->ks_kbds);
378 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
382 state = (kbdmux_state_t *) kbd->kb_data;
383 keymap = kbd->kb_keymap;
384 accmap = kbd->kb_accentmap;
385 fkeymap = kbd->kb_fkeytab;
386 fkeymap_size = kbd->kb_fkeytab_size;
390 if (!KBD_IS_PROBED(kbd)) {
391 /* XXX assume 101/102 keys keyboard */
392 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags,
394 bcopy(&key_map, keymap, sizeof(key_map));
395 bcopy(&accent_map, accmap, sizeof(accent_map));
396 bcopy(fkey_tab, fkeymap,
397 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
398 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
399 kbd->kb_data = (void *)state;
401 KBD_FOUND_DEVICE(kbd);
404 kbdmux_clear_state(kbd);
405 state->ks_mode = K_XLATE;
408 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
409 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
411 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
413 delay[0] = kbd->kb_delay1;
414 delay[1] = kbd->kb_delay2;
415 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
420 if (!KBD_IS_CONFIGURED(kbd)) {
421 if (kbd_register(kbd) < 0) {
426 KBD_CONFIG_DONE(kbd);
428 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, kbd);
435 kfree(state, M_KBDMUX);
437 kfree(keymap, M_KBDMUX);
439 kfree(accmap, M_KBDMUX);
441 kfree(fkeymap, M_KBDMUX);
443 kfree(kbd, M_KBDMUX);
444 *kbdp = NULL; /* insure ref doesn't leak to caller */
452 * Finish using this keyboard
454 * NOTE: deregistration automatically unlocks lock.
457 kbdmux_term(keyboard_t *kbd)
459 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
463 callout_stop(&state->ks_timo);
465 /* wait for interrupt task */
466 while (state->ks_flags & TASK)
467 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
469 /* release all keyboards from the mux */
470 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
471 kbd_release(k->kbd, &k->kbd);
472 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
481 bzero(state, sizeof(*state));
482 kfree(state, M_KBDMUX);
484 kfree(kbd->kb_keymap, M_KBDMUX);
485 kfree(kbd->kb_accentmap, M_KBDMUX);
486 kfree(kbd->kb_fkeytab, M_KBDMUX);
487 kfree(kbd, M_KBDMUX);
493 * Keyboard interrupt routine
496 kbdmux_intr(keyboard_t *kbd, void *arg)
500 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
501 /* let the callback function to process the input */
502 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
503 kbd->kb_callback.kc_arg);
505 /* read and discard the input; no one is waiting for input */
507 c = kbdmux_read_char(kbd, FALSE);
508 } while (c != NOKEY);
515 * Test the interface to the device
518 kbdmux_test_if(keyboard_t *kbd)
524 * Enable the access to the device; until this function is called,
525 * the client cannot read from the keyboard.
528 kbdmux_enable(keyboard_t *kbd)
535 * Disallow the access to the device
538 kbdmux_disable(keyboard_t *kbd)
545 * Read one byte from the keyboard if it's allowed
548 kbdmux_read(keyboard_t *kbd, int wait)
550 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
554 c = kbdmux_kbd_getc(state);
555 } while (c == -1 && wait);
560 ret = (KBD_IS_ACTIVE(kbd)? c : -1);
566 * Check if data is waiting
569 kbdmux_check(keyboard_t *kbd)
571 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
574 if (!KBD_IS_ACTIVE(kbd))
577 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
583 * Read char from the keyboard (stolen from atkbd.c)
585 * Note: We do not attempt to detect the case where no keyboards are
586 * present in the wait case. If the kernel is sitting at the
587 * debugger prompt we want someone to be able to plug in a keyboard
588 * and have it work, and not just panic or fall through or do
589 * something equally nasty.
592 kbdmux_read_char(keyboard_t *kbd, int wait)
594 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
596 int scancode, keycode;
600 /* do we have a composed char to return? */
601 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
602 action = state->ks_composed_char;
603 state->ks_composed_char = 0;
604 if (action > UCHAR_MAX) {
611 * See if there is something in the keyboard queue
613 scancode = kbdmux_kbd_getc(state);
615 if (scancode == -1) {
616 if (state->ks_flags & POLLING) {
619 SLIST_FOREACH(k, &state->ks_kbds, next) {
620 while (kbd_check_char(k->kbd)) {
621 scancode = kbd_read_char(k->kbd, 0);
622 if (scancode == ERRKEY)
624 if (scancode == NOKEY)
626 if (!KBD_IS_BUSY(k->kbd))
628 kbdmux_kbd_putc(state, scancode);
632 if (state->ks_inq_length > 0)
638 KBDMUX_SLEEP(state, ks_task, "kbdwai", hz/10);
647 /* return the byte as is for the K_RAW mode */
648 if (state->ks_mode == K_RAW)
651 /* translate the scan code into a keycode */
652 keycode = scancode & 0x7F;
653 switch (state->ks_prefix) {
654 case 0x00: /* normal scancode */
656 case 0xB8: /* left alt (compose key) released */
657 if (state->ks_flags & COMPOSE) {
658 state->ks_flags &= ~COMPOSE;
659 if (state->ks_composed_char > UCHAR_MAX)
660 state->ks_composed_char = 0;
663 case 0x38: /* left alt (compose key) pressed */
664 if (!(state->ks_flags & COMPOSE)) {
665 state->ks_flags |= COMPOSE;
666 state->ks_composed_char = 0;
671 state->ks_prefix = scancode;
675 case 0xE0: /* 0xE0 prefix */
676 state->ks_prefix = 0;
678 case 0x1C: /* right enter key */
681 case 0x1D: /* right ctrl key */
684 case 0x35: /* keypad divide key */
687 case 0x37: /* print scrn key */
690 case 0x38: /* right alt key (alt gr) */
693 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
696 case 0x47: /* grey home key */
699 case 0x48: /* grey up arrow key */
702 case 0x49: /* grey page up key */
705 case 0x4B: /* grey left arrow key */
708 case 0x4D: /* grey right arrow key */
711 case 0x4F: /* grey end key */
714 case 0x50: /* grey down arrow key */
717 case 0x51: /* grey page down key */
720 case 0x52: /* grey insert key */
723 case 0x53: /* grey delete key */
726 /* the following 3 are only used on the MS "Natural" keyboard */
727 case 0x5b: /* left Window key */
730 case 0x5c: /* right Window key */
733 case 0x5d: /* menu key */
736 case 0x5e: /* power key */
739 case 0x5f: /* sleep key */
742 case 0x63: /* wake key */
745 case 0x64: /* [JP106USB] backslash, underscore */
748 default: /* ignore everything else */
752 case 0xE1: /* 0xE1 prefix */
754 * The pause/break key on the 101 keyboard produces:
756 * Ctrl-pause/break produces:
757 * E0-46 E0-C6 (See above.)
759 state->ks_prefix = 0;
761 state->ks_prefix = 0x1D;
764 case 0x1D: /* pause / break */
765 state->ks_prefix = 0;
772 /* XXX assume 101/102 keys AT keyboard */
774 case 0x5c: /* print screen */
775 if (state->ks_flags & ALTS)
776 keycode = 0x54; /* sysrq */
778 case 0x68: /* pause/break */
779 if (state->ks_flags & CTLS)
780 keycode = 0x6c; /* break */
784 /* return the key code in the K_CODE mode */
785 if (state->ks_mode == K_CODE)
786 return (keycode | (scancode & 0x80));
788 /* compose a character code */
789 if (state->ks_flags & COMPOSE) {
790 switch (keycode | (scancode & 0x80)) {
791 /* key pressed, process it */
792 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
793 state->ks_composed_char *= 10;
794 state->ks_composed_char += keycode - 0x40;
795 if (state->ks_composed_char > UCHAR_MAX)
798 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
799 state->ks_composed_char *= 10;
800 state->ks_composed_char += keycode - 0x47;
801 if (state->ks_composed_char > UCHAR_MAX)
804 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
805 state->ks_composed_char *= 10;
806 state->ks_composed_char += keycode - 0x4E;
807 if (state->ks_composed_char > UCHAR_MAX)
810 case 0x52: /* keypad 0 */
811 state->ks_composed_char *= 10;
812 if (state->ks_composed_char > UCHAR_MAX)
816 /* key released, no interest here */
817 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
818 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
819 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
820 case 0xD2: /* keypad 0 */
823 case 0x38: /* left alt key */
827 if (state->ks_composed_char > 0) {
828 state->ks_flags &= ~COMPOSE;
829 state->ks_composed_char = 0;
836 /* keycode to key action */
837 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
838 &state->ks_state, &state->ks_accents);
846 * Check if char is waiting
849 kbdmux_check_char(keyboard_t *kbd)
851 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
854 if (!KBD_IS_ACTIVE(kbd))
857 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
860 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
869 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
871 static int delays[] = {
875 static int rates[] = {
876 34, 38, 42, 46, 50, 55, 59, 63,
877 68, 76, 84, 92, 100, 110, 118, 126,
878 136, 152, 168, 184, 200, 220, 236, 252,
879 272, 304, 336, 368, 400, 440, 472, 504
882 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
891 case KBADDKBD: /* add keyboard to the mux */
892 ki = (keyboard_info_t *) arg;
894 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
895 strcmp(ki->kb_name, "*") == 0) {
896 return (EINVAL); /* bad input */
899 SLIST_FOREACH(k, &state->ks_kbds, next)
900 if (k->kbd->kb_unit == ki->kb_unit &&
901 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
905 return (0); /* keyboard already in the mux */
907 k = kmalloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
909 return (ENOMEM); /* out of memory */
911 k->kbd = kbd_get_keyboard(
916 kbdmux_kbd_event, (void *) state));
917 if (k->kbd == NULL) {
919 return (EINVAL); /* bad keyboard */
923 kbd_clear_state(k->kbd);
925 /* set K_RAW mode on slave keyboard */
927 error = kbd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
929 /* set lock keys state on slave keyboard */
930 mode = state->ks_state & LOCK_MASK;
931 error = kbd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
935 kbd_release(k->kbd, &k->kbd);
938 return (error); /* could not set mode */
941 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
944 case KBRELKBD: /* release keyboard from the mux */
945 ki = (keyboard_info_t *) arg;
947 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
948 strcmp(ki->kb_name, "*") == 0) {
949 return (EINVAL); /* bad input */
952 SLIST_FOREACH(k, &state->ks_kbds, next)
953 if (k->kbd->kb_unit == ki->kb_unit &&
954 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
958 error = kbd_release(k->kbd, &k->kbd);
960 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
967 error = ENXIO; /* keyboard is not in the mux */
971 case KDGKBMODE: /* get kyboard mode */
972 *(int *)arg = state->ks_mode;
975 case KDSKBMODE: /* set keyboard mode */
976 switch (*(int *)arg) {
978 if (state->ks_mode != K_XLATE) {
979 /* make lock key state and LED state match */
980 state->ks_state &= ~LOCK_MASK;
981 state->ks_state |= KBD_LED_VAL(kbd);
987 if (state->ks_mode != *(int *)arg) {
988 kbdmux_clear_state(kbd);
989 state->ks_mode = *(int *)arg;
999 case KDGETLED: /* get keyboard LED */
1000 *(int *)arg = KBD_LED_VAL(kbd);
1003 case KDSETLED: /* set keyboard LED */
1004 /* NOTE: lock key state in ks_state won't be changed */
1005 if (*(int *)arg & ~LOCK_MASK)
1008 KBD_LED_VAL(kbd) = *(int *)arg;
1010 /* KDSETLED on all slave keyboards */
1011 SLIST_FOREACH(k, &state->ks_kbds, next)
1012 kbd_ioctl(k->kbd, KDSETLED, arg);
1015 case KDGKBSTATE: /* get lock key state */
1016 *(int *)arg = state->ks_state & LOCK_MASK;
1019 case KDSKBSTATE: /* set lock key state */
1020 if (*(int *)arg & ~LOCK_MASK)
1023 state->ks_state &= ~LOCK_MASK;
1024 state->ks_state |= *(int *)arg;
1026 /* KDSKBSTATE on all slave keyboards */
1027 SLIST_FOREACH(k, &state->ks_kbds, next)
1028 kbd_ioctl(k->kbd, KDSKBSTATE, arg);
1030 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1033 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1034 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1035 if (cmd == KDSETREPEAT) {
1039 for (i = NELEM(delays) - 1; i > 0; i --)
1040 if (((int *)arg)[0] >= delays[i])
1045 for (i = NELEM(rates) - 1; i > 0; i --)
1046 if (((int *)arg)[1] >= rates[i])
1055 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1056 kbd->kb_delay2 = rates[mode & 0x1f];
1058 /* perform command on all slave keyboards */
1059 SLIST_FOREACH(k, &state->ks_kbds, next)
1060 kbd_ioctl(k->kbd, cmd, arg);
1063 case PIO_KEYMAP: /* set keyboard translation table */
1064 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1065 case PIO_DEADKEYMAP: /* set accent key translation table */
1066 state->ks_accents = 0;
1068 /* perform command on all slave keyboards */
1069 SLIST_FOREACH(k, &state->ks_kbds, next)
1070 kbd_ioctl(k->kbd, cmd, arg);
1074 error = genkbd_commonioctl(kbd, cmd, arg);
1081 * Lock the access to the keyboard
1084 kbdmux_lock(keyboard_t *kbd, int lock)
1086 return (1); /* XXX */
1090 * Clear the internal state of the keyboard
1092 * NOTE: May be called unlocked from init
1095 kbdmux_clear_state(keyboard_t *kbd)
1097 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1099 state->ks_flags &= ~(COMPOSE|POLLING);
1100 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1101 state->ks_accents = 0;
1102 state->ks_composed_char = 0;
1103 /* state->ks_prefix = 0; XXX */
1104 state->ks_inq_length = 0;
1108 * Save the internal state
1111 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1114 return (sizeof(kbdmux_state_t));
1115 if (len < sizeof(kbdmux_state_t))
1118 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1124 * Set the internal state
1127 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1129 if (len < sizeof(kbdmux_state_t))
1132 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1140 * Caller interlocks all keyboard calls. We must not lock here.
1143 kbdmux_poll(keyboard_t *kbd, int on)
1145 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1149 state->ks_flags |= POLLING;
1151 state->ks_flags &= ~POLLING;
1153 /* set poll on slave keyboards */
1154 SLIST_FOREACH(k, &state->ks_kbds, next)
1155 kbd_poll(k->kbd, on);
1160 /*****************************************************************************
1161 *****************************************************************************
1163 *****************************************************************************
1164 *****************************************************************************/
1166 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1169 kbdmux_modevent(module_t mod, int type, void *data)
1171 keyboard_switch_t *sw;
1177 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1180 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1181 kbd_delete_driver(&kbdmux_kbd_driver);
1188 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1189 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1190 kbd_delete_driver(&kbdmux_kbd_driver);
1194 #ifdef KBD_INSTALL_CDEV
1195 if ((error = kbd_attach(kbd)) != 0) {
1197 kbd_delete_driver(&kbdmux_kbd_driver);
1202 if ((error = (*sw->enable)(kbd)) != 0) {
1203 (*sw->disable)(kbd);
1204 #ifdef KBD_INSTALL_CDEV
1208 kbd_delete_driver(&kbdmux_kbd_driver);
1214 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1215 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1217 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1219 (*sw->disable)(kbd);
1220 #ifdef KBD_INSTALL_CDEV
1224 kbd_delete_driver(&kbdmux_kbd_driver);
1236 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);