6 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
8 * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
36 #include "opt_evdev.h"
38 #include "opt_kbdmux.h"
40 #include <sys/param.h>
43 #include <sys/consio.h>
44 #include <sys/fcntl.h>
46 #include <sys/kernel.h>
47 #include <sys/limits.h>
49 #include <sys/malloc.h>
50 #include <sys/module.h>
51 #include <sys/mutex.h>
54 #include <sys/queue.h>
55 #include <sys/selinfo.h>
56 #include <sys/systm.h>
57 #include <sys/taskqueue.h>
59 #include <dev/kbd/kbdreg.h>
61 /* the initial key map, accent map and fkey strings */
62 #ifdef KBDMUX_DFLT_KEYMAP
63 #define KBD_DFLT_KEYMAP
64 #include "kbdmuxmap.h"
67 #include <dev/kbd/kbdtables.h>
70 #include <dev/evdev/evdev.h>
71 #include <dev/evdev/input.h>
74 #define KEYBOARD_NAME "kbdmux"
76 MALLOC_DECLARE(M_KBDMUX);
77 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
79 /*****************************************************************************
80 *****************************************************************************
82 *****************************************************************************
83 *****************************************************************************/
85 #define KBDMUX_Q_SIZE 512 /* input queue size */
89 * For now rely on Giant mutex to protect our data structures.
90 * Just like the rest of keyboard drivers and syscons(4) do.
91 * Note that callout is initialized as not MP-safe to make sure
96 #define KBDMUX_LOCK_DECL_GLOBAL \
98 #define KBDMUX_LOCK_INIT(s) \
99 mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
100 #define KBDMUX_LOCK_DESTROY(s) \
101 mtx_destroy(&(s)->ks_lock)
102 #define KBDMUX_LOCK(s) \
103 mtx_lock(&(s)->ks_lock)
104 #define KBDMUX_UNLOCK(s) \
105 mtx_unlock(&(s)->ks_lock)
106 #define KBDMUX_LOCK_ASSERT(s, w) \
107 mtx_assert(&(s)->ks_lock, (w))
108 #define KBDMUX_SLEEP(s, f, d, t) \
109 msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
110 #define KBDMUX_CALLOUT_INIT(s) \
111 callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
112 #define KBDMUX_QUEUE_INTR(s) \
113 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
115 #define KBDMUX_LOCK_DECL_GLOBAL
117 #define KBDMUX_LOCK_INIT(s)
119 #define KBDMUX_LOCK_DESTROY(s)
121 #define KBDMUX_LOCK(s)
123 #define KBDMUX_UNLOCK(s)
125 #define KBDMUX_LOCK_ASSERT(s, w)
127 #define KBDMUX_SLEEP(s, f, d, t) \
128 tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t))
129 #define KBDMUX_CALLOUT_INIT(s) \
130 callout_init(&(s)->ks_timo, 0)
131 #define KBDMUX_QUEUE_INTR(s) \
132 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
140 keyboard_t *kbd; /* keyboard */
141 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
144 typedef struct kbdmux_kbd kbdmux_kbd_t;
151 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
152 unsigned int ks_inq_start;
153 unsigned int ks_inq_length;
154 struct task ks_task; /* interrupt task */
155 struct callout ks_timo; /* timeout handler */
156 #define TICKS (hz) /* rate */
158 int ks_flags; /* flags */
159 #define COMPOSE (1 << 0) /* compose char flag */
160 #define TASK (1 << 2) /* interrupt task queued */
162 int ks_polling; /* poll nesting count */
163 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
164 int ks_state; /* state */
165 int ks_accents; /* accent key index (> 0) */
166 u_int ks_composed_char; /* composed char code */
167 u_char ks_prefix; /* AT scan code prefix */
170 struct evdev_dev * ks_evdev;
174 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
176 KBDMUX_LOCK_DECL_GLOBAL;
179 typedef struct kbdmux_state kbdmux_state_t;
181 /*****************************************************************************
182 *****************************************************************************
184 *****************************************************************************
185 *****************************************************************************/
187 static task_fn_t kbdmux_kbd_intr;
188 static callout_func_t kbdmux_kbd_intr_timo;
189 static kbd_callback_func_t kbdmux_kbd_event;
192 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
196 if (state->ks_inq_length == KBDMUX_Q_SIZE)
199 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
200 state->ks_inq[p] = c;
201 state->ks_inq_length++;
205 kbdmux_kbd_getc(kbdmux_state_t *state)
209 if (state->ks_inq_length == 0)
212 c = state->ks_inq[state->ks_inq_start];
213 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
214 state->ks_inq_length--;
220 * Interrupt handler task
223 kbdmux_kbd_intr(void *xkbd, int pending)
225 keyboard_t *kbd = (keyboard_t *) xkbd;
226 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
228 kbdd_intr(kbd, NULL);
232 state->ks_flags &= ~TASK;
233 wakeup(&state->ks_task);
235 KBDMUX_UNLOCK(state);
239 * Schedule interrupt handler on timeout. Called with locked state.
242 kbdmux_kbd_intr_timo(void *xstate)
244 kbdmux_state_t *state = (kbdmux_state_t *) xstate;
246 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
248 if (callout_pending(&state->ks_timo))
249 return; /* callout was reset */
251 if (!callout_active(&state->ks_timo))
252 return; /* callout was stopped */
254 callout_deactivate(&state->ks_timo);
256 /* queue interrupt task if needed */
257 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
258 KBDMUX_QUEUE_INTR(state) == 0)
259 state->ks_flags |= TASK;
261 /* re-schedule timeout */
262 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
266 * Process event from one of our keyboards
269 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
271 kbdmux_state_t *state = (kbdmux_state_t *) arg;
274 case KBDIO_KEYINPUT: {
280 * Read all chars from the keyboard
282 * Turns out that atkbd(4) check_char() method may return
283 * "true" while read_char() method returns NOKEY. If this
284 * happens we could stuck in the loop below. Avoid this
285 * by breaking out of the loop if read_char() method returns
289 while (kbdd_check_char(kbd)) {
290 c = kbdd_read_char(kbd, 0);
294 continue; /* XXX ring bell */
295 if (!KBD_IS_BUSY(kbd))
296 continue; /* not open - discard the input */
298 kbdmux_kbd_putc(state, c);
301 /* queue interrupt task if needed */
302 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
303 KBDMUX_QUEUE_INTR(state) == 0)
304 state->ks_flags |= TASK;
306 KBDMUX_UNLOCK(state);
309 case KBDIO_UNLOADING: {
314 SLIST_FOREACH(k, &state->ks_kbds, next)
319 kbd_release(k->kbd, &k->kbd);
320 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
327 KBDMUX_UNLOCK(state);
338 /****************************************************************************
339 ****************************************************************************
341 ****************************************************************************
342 ****************************************************************************/
344 static int kbdmux_configure(int flags);
345 static kbd_probe_t kbdmux_probe;
346 static kbd_init_t kbdmux_init;
347 static kbd_term_t kbdmux_term;
348 static kbd_intr_t kbdmux_intr;
349 static kbd_test_if_t kbdmux_test_if;
350 static kbd_enable_t kbdmux_enable;
351 static kbd_disable_t kbdmux_disable;
352 static kbd_read_t kbdmux_read;
353 static kbd_check_t kbdmux_check;
354 static kbd_read_char_t kbdmux_read_char;
355 static kbd_check_char_t kbdmux_check_char;
356 static kbd_ioctl_t kbdmux_ioctl;
357 static kbd_lock_t kbdmux_lock;
358 static void kbdmux_clear_state_locked(kbdmux_state_t *state);
359 static kbd_clear_state_t kbdmux_clear_state;
360 static kbd_get_state_t kbdmux_get_state;
361 static kbd_set_state_t kbdmux_set_state;
362 static kbd_poll_mode_t kbdmux_poll;
364 static keyboard_switch_t kbdmuxsw = {
365 .probe = kbdmux_probe,
369 .test_if = kbdmux_test_if,
370 .enable = kbdmux_enable,
371 .disable = kbdmux_disable,
373 .check = kbdmux_check,
374 .read_char = kbdmux_read_char,
375 .check_char = kbdmux_check_char,
376 .ioctl = kbdmux_ioctl,
378 .clear_state = kbdmux_clear_state,
379 .get_state = kbdmux_get_state,
380 .set_state = kbdmux_set_state,
385 static evdev_event_t kbdmux_ev_event;
387 static const struct evdev_methods kbdmux_evdev_methods = {
388 .ev_event = kbdmux_ev_event,
393 * Return the number of found keyboards
396 kbdmux_configure(int flags)
405 kbdmux_probe(int unit, void *arg, int flags)
407 if (resource_disabled(KEYBOARD_NAME, unit))
414 * Reset and initialize the keyboard (stolen from atkbd.c)
417 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
419 keyboard_t *kbd = NULL;
420 kbdmux_state_t *state = NULL;
421 keymap_t *keymap = NULL;
422 accentmap_t *accmap = NULL;
423 fkeytab_t *fkeymap = NULL;
424 int error, needfree, fkeymap_size, delay[2];
426 struct evdev_dev *evdev;
427 char phys_loc[NAMELEN];
431 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
432 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
433 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
434 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
435 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
436 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
439 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
440 (accmap == NULL) || (fkeymap == NULL)) {
445 KBDMUX_LOCK_INIT(state);
446 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
447 KBDMUX_CALLOUT_INIT(state);
448 SLIST_INIT(&state->ks_kbds);
449 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
453 state = (kbdmux_state_t *) kbd->kb_data;
454 keymap = kbd->kb_keymap;
455 accmap = kbd->kb_accentmap;
456 fkeymap = kbd->kb_fkeytab;
457 fkeymap_size = kbd->kb_fkeytab_size;
461 if (!KBD_IS_PROBED(kbd)) {
462 /* XXX assume 101/102 keys keyboard */
463 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
464 bcopy(&key_map, keymap, sizeof(key_map));
465 bcopy(&accent_map, accmap, sizeof(accent_map));
466 bcopy(fkey_tab, fkeymap,
467 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
468 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
469 kbd->kb_data = (void *)state;
471 KBD_FOUND_DEVICE(kbd);
475 kbdmux_clear_state_locked(state);
476 state->ks_mode = K_XLATE;
477 KBDMUX_UNLOCK(state);
480 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
481 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
483 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
485 delay[0] = kbd->kb_delay1;
486 delay[1] = kbd->kb_delay2;
487 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
490 /* register as evdev provider */
491 evdev = evdev_alloc();
492 evdev_set_name(evdev, "System keyboard multiplexer");
493 snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit);
494 evdev_set_phys(evdev, phys_loc);
495 evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
496 evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods);
497 evdev_support_event(evdev, EV_SYN);
498 evdev_support_event(evdev, EV_KEY);
499 evdev_support_event(evdev, EV_LED);
500 evdev_support_event(evdev, EV_REP);
501 evdev_support_all_known_keys(evdev);
502 evdev_support_led(evdev, LED_NUML);
503 evdev_support_led(evdev, LED_CAPSL);
504 evdev_support_led(evdev, LED_SCROLLL);
506 if (evdev_register_mtx(evdev, &Giant))
509 state->ks_evdev = evdev;
510 state->ks_evdev_state = 0;
516 if (!KBD_IS_CONFIGURED(kbd)) {
517 if (kbd_register(kbd) < 0) {
522 KBD_CONFIG_DONE(kbd);
525 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
526 KBDMUX_UNLOCK(state);
533 free(state, M_KBDMUX);
535 free(keymap, M_KBDMUX);
537 free(accmap, M_KBDMUX);
539 free(fkeymap, M_KBDMUX);
542 *kbdp = NULL; /* insure ref doesn't leak to caller */
550 * Finish using this keyboard
553 kbdmux_term(keyboard_t *kbd)
555 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
561 callout_stop(&state->ks_timo);
563 /* wait for interrupt task */
564 while (state->ks_flags & TASK)
565 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
567 /* release all keyboards from the mux */
568 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
569 kbd_release(k->kbd, &k->kbd);
570 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
577 KBDMUX_UNLOCK(state);
582 evdev_free(state->ks_evdev);
585 KBDMUX_LOCK_DESTROY(state);
586 bzero(state, sizeof(*state));
587 free(state, M_KBDMUX);
589 free(kbd->kb_keymap, M_KBDMUX);
590 free(kbd->kb_accentmap, M_KBDMUX);
591 free(kbd->kb_fkeytab, M_KBDMUX);
598 * Keyboard interrupt routine
601 kbdmux_intr(keyboard_t *kbd, void *arg)
605 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
606 /* let the callback function to process the input */
607 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
608 kbd->kb_callback.kc_arg);
610 /* read and discard the input; no one is waiting for input */
612 c = kbdmux_read_char(kbd, FALSE);
613 } while (c != NOKEY);
620 * Test the interface to the device
623 kbdmux_test_if(keyboard_t *kbd)
629 * Enable the access to the device; until this function is called,
630 * the client cannot read from the keyboard.
633 kbdmux_enable(keyboard_t *kbd)
640 * Disallow the access to the device
643 kbdmux_disable(keyboard_t *kbd)
650 * Read one byte from the keyboard if it's allowed
653 kbdmux_read(keyboard_t *kbd, int wait)
655 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
659 c = kbdmux_kbd_getc(state);
660 KBDMUX_UNLOCK(state);
665 return (KBD_IS_ACTIVE(kbd)? c : -1);
669 * Check if data is waiting
672 kbdmux_check(keyboard_t *kbd)
674 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
677 if (!KBD_IS_ACTIVE(kbd))
681 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
682 KBDMUX_UNLOCK(state);
688 * Read char from the keyboard (stolen from atkbd.c)
691 kbdmux_read_char(keyboard_t *kbd, int wait)
693 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
695 int scancode, keycode;
701 /* do we have a composed char to return? */
702 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
703 action = state->ks_composed_char;
704 state->ks_composed_char = 0;
705 if (action > UCHAR_MAX) {
706 KBDMUX_UNLOCK(state);
711 KBDMUX_UNLOCK(state);
716 /* see if there is something in the keyboard queue */
717 scancode = kbdmux_kbd_getc(state);
718 if (scancode == -1) {
719 if (state->ks_polling != 0) {
722 SLIST_FOREACH(k, &state->ks_kbds, next) {
723 while (kbdd_check_char(k->kbd)) {
724 scancode = kbdd_read_char(k->kbd, 0);
725 if (scancode == NOKEY)
727 if (scancode == ERRKEY)
729 if (!KBD_IS_BUSY(k->kbd))
732 kbdmux_kbd_putc(state, scancode);
736 if (state->ks_inq_length > 0)
740 KBDMUX_UNLOCK(state);
743 /* XXX FIXME: check for -1 if wait == 1! */
748 /* push evdev event */
749 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) {
750 uint16_t key = evdev_scancode2key(&state->ks_evdev_state,
753 if (key != KEY_RESERVED) {
754 evdev_push_event(state->ks_evdev, EV_KEY,
755 key, scancode & 0x80 ? 0 : 1);
756 evdev_sync(state->ks_evdev);
761 /* return the byte as is for the K_RAW mode */
762 if (state->ks_mode == K_RAW) {
763 KBDMUX_UNLOCK(state);
767 /* translate the scan code into a keycode */
768 keycode = scancode & 0x7F;
769 switch (state->ks_prefix) {
770 case 0x00: /* normal scancode */
772 case 0xB8: /* left alt (compose key) released */
773 if (state->ks_flags & COMPOSE) {
774 state->ks_flags &= ~COMPOSE;
775 if (state->ks_composed_char > UCHAR_MAX)
776 state->ks_composed_char = 0;
779 case 0x38: /* left alt (compose key) pressed */
780 if (!(state->ks_flags & COMPOSE)) {
781 state->ks_flags |= COMPOSE;
782 state->ks_composed_char = 0;
787 state->ks_prefix = scancode;
791 case 0xE0: /* 0xE0 prefix */
792 state->ks_prefix = 0;
794 case 0x1C: /* right enter key */
797 case 0x1D: /* right ctrl key */
800 case 0x35: /* keypad divide key */
803 case 0x37: /* print scrn key */
806 case 0x38: /* right alt key (alt gr) */
809 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
812 case 0x47: /* grey home key */
815 case 0x48: /* grey up arrow key */
818 case 0x49: /* grey page up key */
821 case 0x4B: /* grey left arrow key */
824 case 0x4D: /* grey right arrow key */
827 case 0x4F: /* grey end key */
830 case 0x50: /* grey down arrow key */
833 case 0x51: /* grey page down key */
836 case 0x52: /* grey insert key */
839 case 0x53: /* grey delete key */
842 /* the following 3 are only used on the MS "Natural" keyboard */
843 case 0x5b: /* left Window key */
846 case 0x5c: /* right Window key */
849 case 0x5d: /* menu key */
852 case 0x5e: /* power key */
855 case 0x5f: /* sleep key */
858 case 0x63: /* wake key */
861 case 0x64: /* [JP106USB] backslash, underscore */
864 default: /* ignore everything else */
868 case 0xE1: /* 0xE1 prefix */
870 * The pause/break key on the 101 keyboard produces:
872 * Ctrl-pause/break produces:
873 * E0-46 E0-C6 (See above.)
875 state->ks_prefix = 0;
877 state->ks_prefix = 0x1D;
880 case 0x1D: /* pause / break */
881 state->ks_prefix = 0;
888 /* XXX assume 101/102 keys AT keyboard */
890 case 0x5c: /* print screen */
891 if (state->ks_flags & ALTS)
892 keycode = 0x54; /* sysrq */
894 case 0x68: /* pause/break */
895 if (state->ks_flags & CTLS)
896 keycode = 0x6c; /* break */
900 /* return the key code in the K_CODE mode */
901 if (state->ks_mode == K_CODE) {
902 KBDMUX_UNLOCK(state);
903 return (keycode | (scancode & 0x80));
906 /* compose a character code */
907 if (state->ks_flags & COMPOSE) {
908 switch (keycode | (scancode & 0x80)) {
909 /* key pressed, process it */
910 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
911 state->ks_composed_char *= 10;
912 state->ks_composed_char += keycode - 0x40;
913 if (state->ks_composed_char > UCHAR_MAX) {
914 KBDMUX_UNLOCK(state);
918 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
919 state->ks_composed_char *= 10;
920 state->ks_composed_char += keycode - 0x47;
921 if (state->ks_composed_char > UCHAR_MAX) {
922 KBDMUX_UNLOCK(state);
926 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
927 state->ks_composed_char *= 10;
928 state->ks_composed_char += keycode - 0x4E;
929 if (state->ks_composed_char > UCHAR_MAX) {
930 KBDMUX_UNLOCK(state);
934 case 0x52: /* keypad 0 */
935 state->ks_composed_char *= 10;
936 if (state->ks_composed_char > UCHAR_MAX) {
937 KBDMUX_UNLOCK(state);
942 /* key released, no interest here */
943 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
944 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
945 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
946 case 0xD2: /* keypad 0 */
949 case 0x38: /* left alt key */
953 if (state->ks_composed_char > 0) {
954 state->ks_flags &= ~COMPOSE;
955 state->ks_composed_char = 0;
956 KBDMUX_UNLOCK(state);
963 /* keycode to key action */
964 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
965 &state->ks_state, &state->ks_accents);
969 KBDMUX_UNLOCK(state);
975 * Check if char is waiting
978 kbdmux_check_char(keyboard_t *kbd)
980 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
983 if (!KBD_IS_ACTIVE(kbd))
988 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
991 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
993 KBDMUX_UNLOCK(state);
1002 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
1004 static int delays[] = {
1008 static int rates[] = {
1009 34, 38, 42, 46, 50, 55, 59, 63,
1010 68, 76, 84, 92, 100, 110, 118, 126,
1011 136, 152, 168, 184, 200, 220, 236, 252,
1012 272, 304, 336, 368, 400, 440, 472, 504
1015 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1017 keyboard_info_t *ki;
1018 int error = 0, mode;
1019 #ifdef COMPAT_FREEBSD6
1027 case KBADDKBD: /* add keyboard to the mux */
1028 ki = (keyboard_info_t *) arg;
1030 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1031 strcmp(ki->kb_name, "*") == 0)
1032 return (EINVAL); /* bad input */
1036 SLIST_FOREACH(k, &state->ks_kbds, next)
1037 if (k->kbd->kb_unit == ki->kb_unit &&
1038 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1042 KBDMUX_UNLOCK(state);
1044 return (0); /* keyboard already in the mux */
1047 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
1049 KBDMUX_UNLOCK(state);
1051 return (ENOMEM); /* out of memory */
1054 k->kbd = kbd_get_keyboard(
1059 kbdmux_kbd_event, (void *) state));
1060 if (k->kbd == NULL) {
1061 KBDMUX_UNLOCK(state);
1064 return (EINVAL); /* bad keyboard */
1067 kbdd_enable(k->kbd);
1068 kbdd_clear_state(k->kbd);
1070 /* set K_RAW mode on slave keyboard */
1072 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1074 /* set lock keys state on slave keyboard */
1075 mode = state->ks_state & LOCK_MASK;
1076 error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1080 KBDMUX_UNLOCK(state);
1082 kbd_release(k->kbd, &k->kbd);
1087 return (error); /* could not set mode */
1090 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1092 KBDMUX_UNLOCK(state);
1095 case KBRELKBD: /* release keyboard from the mux */
1096 ki = (keyboard_info_t *) arg;
1098 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1099 strcmp(ki->kb_name, "*") == 0)
1100 return (EINVAL); /* bad input */
1104 SLIST_FOREACH(k, &state->ks_kbds, next)
1105 if (k->kbd->kb_unit == ki->kb_unit &&
1106 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1110 error = kbd_release(k->kbd, &k->kbd);
1112 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1119 error = ENXIO; /* keyboard is not in the mux */
1121 KBDMUX_UNLOCK(state);
1124 case KDGKBMODE: /* get kyboard mode */
1126 *(int *)arg = state->ks_mode;
1127 KBDMUX_UNLOCK(state);
1130 #ifdef COMPAT_FREEBSD6
1132 ival = IOCPARM_IVAL(arg);
1133 arg = (caddr_t)&ival;
1136 case KDSKBMODE: /* set keyboard mode */
1139 switch (*(int *)arg) {
1141 if (state->ks_mode != K_XLATE) {
1142 /* make lock key state and LED state match */
1143 state->ks_state &= ~LOCK_MASK;
1144 state->ks_state |= KBD_LED_VAL(kbd);
1150 if (state->ks_mode != *(int *)arg) {
1151 kbdmux_clear_state_locked(state);
1152 state->ks_mode = *(int *)arg;
1161 KBDMUX_UNLOCK(state);
1164 case KDGETLED: /* get keyboard LED */
1166 *(int *)arg = KBD_LED_VAL(kbd);
1167 KBDMUX_UNLOCK(state);
1170 #ifdef COMPAT_FREEBSD6
1172 ival = IOCPARM_IVAL(arg);
1173 arg = (caddr_t)&ival;
1176 case KDSETLED: /* set keyboard LED */
1179 /* NOTE: lock key state in ks_state won't be changed */
1180 if (*(int *)arg & ~LOCK_MASK) {
1181 KBDMUX_UNLOCK(state);
1186 KBD_LED_VAL(kbd) = *(int *)arg;
1187 #ifdef EVDEV_SUPPORT
1188 if (state->ks_evdev != NULL &&
1189 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1190 evdev_push_leds(state->ks_evdev, *(int *)arg);
1192 /* KDSETLED on all slave keyboards */
1193 SLIST_FOREACH(k, &state->ks_kbds, next)
1194 (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
1196 KBDMUX_UNLOCK(state);
1199 case KDGKBSTATE: /* get lock key state */
1201 *(int *)arg = state->ks_state & LOCK_MASK;
1202 KBDMUX_UNLOCK(state);
1205 #ifdef COMPAT_FREEBSD6
1207 ival = IOCPARM_IVAL(arg);
1208 arg = (caddr_t)&ival;
1211 case KDSKBSTATE: /* set lock key state */
1214 if (*(int *)arg & ~LOCK_MASK) {
1215 KBDMUX_UNLOCK(state);
1220 state->ks_state &= ~LOCK_MASK;
1221 state->ks_state |= *(int *)arg;
1223 /* KDSKBSTATE on all slave keyboards */
1224 SLIST_FOREACH(k, &state->ks_kbds, next)
1225 (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
1227 KBDMUX_UNLOCK(state);
1229 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1232 #ifdef COMPAT_FREEBSD6
1235 ival = IOCPARM_IVAL(arg);
1236 arg = (caddr_t)&ival;
1239 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1240 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1243 if (cmd == KDSETREPEAT) {
1247 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1248 if (((int *)arg)[0] >= delays[i])
1253 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1254 if (((int *)arg)[1] >= rates[i])
1261 KBDMUX_UNLOCK(state);
1266 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1267 kbd->kb_delay2 = rates[mode & 0x1f];
1268 #ifdef EVDEV_SUPPORT
1269 if (state->ks_evdev != NULL &&
1270 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1271 evdev_push_repeats(state->ks_evdev, kbd);
1273 /* perform command on all slave keyboards */
1274 SLIST_FOREACH(k, &state->ks_kbds, next)
1275 (void)kbdd_ioctl(k->kbd, cmd, arg);
1277 KBDMUX_UNLOCK(state);
1280 case PIO_KEYMAP: /* set keyboard translation table */
1281 case OPIO_KEYMAP: /* set keyboard translation table (compat) */
1282 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1283 case PIO_DEADKEYMAP: /* set accent key translation table */
1285 state->ks_accents = 0;
1287 /* perform command on all slave keyboards */
1288 SLIST_FOREACH(k, &state->ks_kbds, next)
1289 (void)kbdd_ioctl(k->kbd, cmd, arg);
1291 KBDMUX_UNLOCK(state);
1295 error = genkbd_commonioctl(kbd, cmd, arg);
1303 * Lock the access to the keyboard
1306 kbdmux_lock(keyboard_t *kbd, int lock)
1308 return (1); /* XXX */
1312 * Clear the internal state of the keyboard
1315 kbdmux_clear_state_locked(kbdmux_state_t *state)
1317 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1319 state->ks_flags &= ~COMPOSE;
1320 state->ks_polling = 0;
1321 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1322 state->ks_accents = 0;
1323 state->ks_composed_char = 0;
1324 /* state->ks_prefix = 0; XXX */
1325 state->ks_inq_length = 0;
1329 kbdmux_clear_state(keyboard_t *kbd)
1331 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1334 kbdmux_clear_state_locked(state);
1335 KBDMUX_UNLOCK(state);
1339 * Save the internal state
1342 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1345 return (sizeof(kbdmux_state_t));
1346 if (len < sizeof(kbdmux_state_t))
1349 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1355 * Set the internal state
1358 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1360 if (len < sizeof(kbdmux_state_t))
1363 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1372 kbdmux_poll(keyboard_t *kbd, int on)
1374 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1380 state->ks_polling++;
1382 state->ks_polling--;
1384 /* set poll on slave keyboards */
1385 SLIST_FOREACH(k, &state->ks_kbds, next)
1386 kbdd_poll(k->kbd, on);
1388 KBDMUX_UNLOCK(state);
1393 #ifdef EVDEV_SUPPORT
1395 kbdmux_ev_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
1398 keyboard_t *kbd = evdev_get_softc(evdev);
1400 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX &&
1401 (type == EV_LED || type == EV_REP)) {
1403 kbd_ev_event(kbd, type, code, value);
1409 /*****************************************************************************
1410 *****************************************************************************
1412 *****************************************************************************
1413 *****************************************************************************/
1415 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1418 kbdmux_modevent(module_t mod, int type, void *data)
1420 keyboard_switch_t *sw;
1426 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1429 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1436 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1437 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0)
1440 #ifdef KBD_INSTALL_CDEV
1441 if ((error = kbd_attach(kbd)) != 0) {
1447 if ((error = (*sw->enable)(kbd)) != 0)
1452 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1457 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1459 (*sw->disable)(kbd);
1460 #ifdef KBD_INSTALL_CDEV
1465 kbd_delete_driver(&kbdmux_kbd_driver);
1477 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1478 #ifdef EVDEV_SUPPORT
1479 MODULE_DEPEND(kbdmux, evdev, 1, 1, 1);