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 timeout_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,
381 .get_fkeystr = genkbd_get_fkeystr,
387 static evdev_event_t kbdmux_ev_event;
389 static const struct evdev_methods kbdmux_evdev_methods = {
390 .ev_event = kbdmux_ev_event,
395 * Return the number of found keyboards
398 kbdmux_configure(int flags)
407 kbdmux_probe(int unit, void *arg, int flags)
409 if (resource_disabled(KEYBOARD_NAME, unit))
416 * Reset and initialize the keyboard (stolen from atkbd.c)
419 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
421 keyboard_t *kbd = NULL;
422 kbdmux_state_t *state = NULL;
423 keymap_t *keymap = NULL;
424 accentmap_t *accmap = NULL;
425 fkeytab_t *fkeymap = NULL;
426 int error, needfree, fkeymap_size, delay[2];
428 struct evdev_dev *evdev;
429 char phys_loc[NAMELEN];
433 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
434 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
435 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
436 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
437 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
438 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
441 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
442 (accmap == NULL) || (fkeymap == NULL)) {
447 KBDMUX_LOCK_INIT(state);
448 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
449 KBDMUX_CALLOUT_INIT(state);
450 SLIST_INIT(&state->ks_kbds);
451 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
455 state = (kbdmux_state_t *) kbd->kb_data;
456 keymap = kbd->kb_keymap;
457 accmap = kbd->kb_accentmap;
458 fkeymap = kbd->kb_fkeytab;
459 fkeymap_size = kbd->kb_fkeytab_size;
463 if (!KBD_IS_PROBED(kbd)) {
464 /* XXX assume 101/102 keys keyboard */
465 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
466 bcopy(&key_map, keymap, sizeof(key_map));
467 bcopy(&accent_map, accmap, sizeof(accent_map));
468 bcopy(fkey_tab, fkeymap,
469 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
470 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
471 kbd->kb_data = (void *)state;
473 KBD_FOUND_DEVICE(kbd);
477 kbdmux_clear_state_locked(state);
478 state->ks_mode = K_XLATE;
479 KBDMUX_UNLOCK(state);
482 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
483 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
485 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
487 delay[0] = kbd->kb_delay1;
488 delay[1] = kbd->kb_delay2;
489 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
492 /* register as evdev provider */
493 evdev = evdev_alloc();
494 evdev_set_name(evdev, "System keyboard multiplexer");
495 snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit);
496 evdev_set_phys(evdev, phys_loc);
497 evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
498 evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods);
499 evdev_support_event(evdev, EV_SYN);
500 evdev_support_event(evdev, EV_KEY);
501 evdev_support_event(evdev, EV_LED);
502 evdev_support_event(evdev, EV_REP);
503 evdev_support_all_known_keys(evdev);
504 evdev_support_led(evdev, LED_NUML);
505 evdev_support_led(evdev, LED_CAPSL);
506 evdev_support_led(evdev, LED_SCROLLL);
508 if (evdev_register(evdev))
511 state->ks_evdev = evdev;
512 state->ks_evdev_state = 0;
518 if (!KBD_IS_CONFIGURED(kbd)) {
519 if (kbd_register(kbd) < 0) {
524 KBD_CONFIG_DONE(kbd);
527 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
528 KBDMUX_UNLOCK(state);
535 free(state, M_KBDMUX);
537 free(keymap, M_KBDMUX);
539 free(accmap, M_KBDMUX);
541 free(fkeymap, M_KBDMUX);
544 *kbdp = NULL; /* insure ref doesn't leak to caller */
552 * Finish using this keyboard
555 kbdmux_term(keyboard_t *kbd)
557 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
563 callout_stop(&state->ks_timo);
565 /* wait for interrupt task */
566 while (state->ks_flags & TASK)
567 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
569 /* release all keyboards from the mux */
570 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
571 kbd_release(k->kbd, &k->kbd);
572 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
579 KBDMUX_UNLOCK(state);
584 evdev_free(state->ks_evdev);
587 KBDMUX_LOCK_DESTROY(state);
588 bzero(state, sizeof(*state));
589 free(state, M_KBDMUX);
591 free(kbd->kb_keymap, M_KBDMUX);
592 free(kbd->kb_accentmap, M_KBDMUX);
593 free(kbd->kb_fkeytab, M_KBDMUX);
600 * Keyboard interrupt routine
603 kbdmux_intr(keyboard_t *kbd, void *arg)
607 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
608 /* let the callback function to process the input */
609 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
610 kbd->kb_callback.kc_arg);
612 /* read and discard the input; no one is waiting for input */
614 c = kbdmux_read_char(kbd, FALSE);
615 } while (c != NOKEY);
622 * Test the interface to the device
625 kbdmux_test_if(keyboard_t *kbd)
631 * Enable the access to the device; until this function is called,
632 * the client cannot read from the keyboard.
635 kbdmux_enable(keyboard_t *kbd)
642 * Disallow the access to the device
645 kbdmux_disable(keyboard_t *kbd)
652 * Read one byte from the keyboard if it's allowed
655 kbdmux_read(keyboard_t *kbd, int wait)
657 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
661 c = kbdmux_kbd_getc(state);
662 KBDMUX_UNLOCK(state);
667 return (KBD_IS_ACTIVE(kbd)? c : -1);
671 * Check if data is waiting
674 kbdmux_check(keyboard_t *kbd)
676 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
679 if (!KBD_IS_ACTIVE(kbd))
683 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
684 KBDMUX_UNLOCK(state);
690 * Read char from the keyboard (stolen from atkbd.c)
693 kbdmux_read_char(keyboard_t *kbd, int wait)
695 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
697 int scancode, keycode;
703 /* do we have a composed char to return? */
704 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
705 action = state->ks_composed_char;
706 state->ks_composed_char = 0;
707 if (action > UCHAR_MAX) {
708 KBDMUX_UNLOCK(state);
713 KBDMUX_UNLOCK(state);
718 /* see if there is something in the keyboard queue */
719 scancode = kbdmux_kbd_getc(state);
720 if (scancode == -1) {
721 if (state->ks_polling != 0) {
724 SLIST_FOREACH(k, &state->ks_kbds, next) {
725 while (kbdd_check_char(k->kbd)) {
726 scancode = kbdd_read_char(k->kbd, 0);
727 if (scancode == NOKEY)
729 if (scancode == ERRKEY)
731 if (!KBD_IS_BUSY(k->kbd))
734 kbdmux_kbd_putc(state, scancode);
738 if (state->ks_inq_length > 0)
742 KBDMUX_UNLOCK(state);
745 /* XXX FIXME: check for -1 if wait == 1! */
750 /* push evdev event */
751 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) {
752 uint16_t key = evdev_scancode2key(&state->ks_evdev_state,
755 if (key != KEY_RESERVED) {
756 evdev_push_event(state->ks_evdev, EV_KEY,
757 key, scancode & 0x80 ? 0 : 1);
758 evdev_sync(state->ks_evdev);
763 /* return the byte as is for the K_RAW mode */
764 if (state->ks_mode == K_RAW) {
765 KBDMUX_UNLOCK(state);
769 /* translate the scan code into a keycode */
770 keycode = scancode & 0x7F;
771 switch (state->ks_prefix) {
772 case 0x00: /* normal scancode */
774 case 0xB8: /* left alt (compose key) released */
775 if (state->ks_flags & COMPOSE) {
776 state->ks_flags &= ~COMPOSE;
777 if (state->ks_composed_char > UCHAR_MAX)
778 state->ks_composed_char = 0;
781 case 0x38: /* left alt (compose key) pressed */
782 if (!(state->ks_flags & COMPOSE)) {
783 state->ks_flags |= COMPOSE;
784 state->ks_composed_char = 0;
789 state->ks_prefix = scancode;
793 case 0xE0: /* 0xE0 prefix */
794 state->ks_prefix = 0;
796 case 0x1C: /* right enter key */
799 case 0x1D: /* right ctrl key */
802 case 0x35: /* keypad divide key */
805 case 0x37: /* print scrn key */
808 case 0x38: /* right alt key (alt gr) */
811 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
814 case 0x47: /* grey home key */
817 case 0x48: /* grey up arrow key */
820 case 0x49: /* grey page up key */
823 case 0x4B: /* grey left arrow key */
826 case 0x4D: /* grey right arrow key */
829 case 0x4F: /* grey end key */
832 case 0x50: /* grey down arrow key */
835 case 0x51: /* grey page down key */
838 case 0x52: /* grey insert key */
841 case 0x53: /* grey delete key */
844 /* the following 3 are only used on the MS "Natural" keyboard */
845 case 0x5b: /* left Window key */
848 case 0x5c: /* right Window key */
851 case 0x5d: /* menu key */
854 case 0x5e: /* power key */
857 case 0x5f: /* sleep key */
860 case 0x63: /* wake key */
863 case 0x64: /* [JP106USB] backslash, underscore */
866 default: /* ignore everything else */
870 case 0xE1: /* 0xE1 prefix */
872 * The pause/break key on the 101 keyboard produces:
874 * Ctrl-pause/break produces:
875 * E0-46 E0-C6 (See above.)
877 state->ks_prefix = 0;
879 state->ks_prefix = 0x1D;
882 case 0x1D: /* pause / break */
883 state->ks_prefix = 0;
890 /* XXX assume 101/102 keys AT keyboard */
892 case 0x5c: /* print screen */
893 if (state->ks_flags & ALTS)
894 keycode = 0x54; /* sysrq */
896 case 0x68: /* pause/break */
897 if (state->ks_flags & CTLS)
898 keycode = 0x6c; /* break */
902 /* return the key code in the K_CODE mode */
903 if (state->ks_mode == K_CODE) {
904 KBDMUX_UNLOCK(state);
905 return (keycode | (scancode & 0x80));
908 /* compose a character code */
909 if (state->ks_flags & COMPOSE) {
910 switch (keycode | (scancode & 0x80)) {
911 /* key pressed, process it */
912 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
913 state->ks_composed_char *= 10;
914 state->ks_composed_char += keycode - 0x40;
915 if (state->ks_composed_char > UCHAR_MAX) {
916 KBDMUX_UNLOCK(state);
920 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
921 state->ks_composed_char *= 10;
922 state->ks_composed_char += keycode - 0x47;
923 if (state->ks_composed_char > UCHAR_MAX) {
924 KBDMUX_UNLOCK(state);
928 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
929 state->ks_composed_char *= 10;
930 state->ks_composed_char += keycode - 0x4E;
931 if (state->ks_composed_char > UCHAR_MAX) {
932 KBDMUX_UNLOCK(state);
936 case 0x52: /* keypad 0 */
937 state->ks_composed_char *= 10;
938 if (state->ks_composed_char > UCHAR_MAX) {
939 KBDMUX_UNLOCK(state);
944 /* key released, no interest here */
945 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
946 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
947 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
948 case 0xD2: /* keypad 0 */
951 case 0x38: /* left alt key */
955 if (state->ks_composed_char > 0) {
956 state->ks_flags &= ~COMPOSE;
957 state->ks_composed_char = 0;
958 KBDMUX_UNLOCK(state);
965 /* keycode to key action */
966 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
967 &state->ks_state, &state->ks_accents);
971 KBDMUX_UNLOCK(state);
977 * Check if char is waiting
980 kbdmux_check_char(keyboard_t *kbd)
982 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
985 if (!KBD_IS_ACTIVE(kbd))
990 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
993 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
995 KBDMUX_UNLOCK(state);
1004 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
1006 static int delays[] = {
1010 static int rates[] = {
1011 34, 38, 42, 46, 50, 55, 59, 63,
1012 68, 76, 84, 92, 100, 110, 118, 126,
1013 136, 152, 168, 184, 200, 220, 236, 252,
1014 272, 304, 336, 368, 400, 440, 472, 504
1017 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1019 keyboard_info_t *ki;
1020 int error = 0, mode;
1021 #ifdef COMPAT_FREEBSD6
1029 case KBADDKBD: /* add keyboard to the mux */
1030 ki = (keyboard_info_t *) arg;
1032 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1033 strcmp(ki->kb_name, "*") == 0)
1034 return (EINVAL); /* bad input */
1038 SLIST_FOREACH(k, &state->ks_kbds, next)
1039 if (k->kbd->kb_unit == ki->kb_unit &&
1040 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1044 KBDMUX_UNLOCK(state);
1046 return (0); /* keyboard already in the mux */
1049 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
1051 KBDMUX_UNLOCK(state);
1053 return (ENOMEM); /* out of memory */
1056 k->kbd = kbd_get_keyboard(
1061 kbdmux_kbd_event, (void *) state));
1062 if (k->kbd == NULL) {
1063 KBDMUX_UNLOCK(state);
1066 return (EINVAL); /* bad keyboard */
1069 kbdd_enable(k->kbd);
1070 kbdd_clear_state(k->kbd);
1072 /* set K_RAW mode on slave keyboard */
1074 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1076 /* set lock keys state on slave keyboard */
1077 mode = state->ks_state & LOCK_MASK;
1078 error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1082 KBDMUX_UNLOCK(state);
1084 kbd_release(k->kbd, &k->kbd);
1089 return (error); /* could not set mode */
1092 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1094 KBDMUX_UNLOCK(state);
1097 case KBRELKBD: /* release keyboard from the mux */
1098 ki = (keyboard_info_t *) arg;
1100 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1101 strcmp(ki->kb_name, "*") == 0)
1102 return (EINVAL); /* bad input */
1106 SLIST_FOREACH(k, &state->ks_kbds, next)
1107 if (k->kbd->kb_unit == ki->kb_unit &&
1108 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1112 error = kbd_release(k->kbd, &k->kbd);
1114 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1121 error = ENXIO; /* keyboard is not in the mux */
1123 KBDMUX_UNLOCK(state);
1126 case KDGKBMODE: /* get kyboard mode */
1128 *(int *)arg = state->ks_mode;
1129 KBDMUX_UNLOCK(state);
1132 #ifdef COMPAT_FREEBSD6
1134 ival = IOCPARM_IVAL(arg);
1135 arg = (caddr_t)&ival;
1138 case KDSKBMODE: /* set keyboard mode */
1141 switch (*(int *)arg) {
1143 if (state->ks_mode != K_XLATE) {
1144 /* make lock key state and LED state match */
1145 state->ks_state &= ~LOCK_MASK;
1146 state->ks_state |= KBD_LED_VAL(kbd);
1152 if (state->ks_mode != *(int *)arg) {
1153 kbdmux_clear_state_locked(state);
1154 state->ks_mode = *(int *)arg;
1163 KBDMUX_UNLOCK(state);
1166 case KDGETLED: /* get keyboard LED */
1168 *(int *)arg = KBD_LED_VAL(kbd);
1169 KBDMUX_UNLOCK(state);
1172 #ifdef COMPAT_FREEBSD6
1174 ival = IOCPARM_IVAL(arg);
1175 arg = (caddr_t)&ival;
1178 case KDSETLED: /* set keyboard LED */
1181 /* NOTE: lock key state in ks_state won't be changed */
1182 if (*(int *)arg & ~LOCK_MASK) {
1183 KBDMUX_UNLOCK(state);
1188 KBD_LED_VAL(kbd) = *(int *)arg;
1189 #ifdef EVDEV_SUPPORT
1190 if (state->ks_evdev != NULL &&
1191 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1192 evdev_push_leds(state->ks_evdev, *(int *)arg);
1194 /* KDSETLED on all slave keyboards */
1195 SLIST_FOREACH(k, &state->ks_kbds, next)
1196 (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
1198 KBDMUX_UNLOCK(state);
1201 case KDGKBSTATE: /* get lock key state */
1203 *(int *)arg = state->ks_state & LOCK_MASK;
1204 KBDMUX_UNLOCK(state);
1207 #ifdef COMPAT_FREEBSD6
1209 ival = IOCPARM_IVAL(arg);
1210 arg = (caddr_t)&ival;
1213 case KDSKBSTATE: /* set lock key state */
1216 if (*(int *)arg & ~LOCK_MASK) {
1217 KBDMUX_UNLOCK(state);
1222 state->ks_state &= ~LOCK_MASK;
1223 state->ks_state |= *(int *)arg;
1225 /* KDSKBSTATE on all slave keyboards */
1226 SLIST_FOREACH(k, &state->ks_kbds, next)
1227 (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
1229 KBDMUX_UNLOCK(state);
1231 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1234 #ifdef COMPAT_FREEBSD6
1237 ival = IOCPARM_IVAL(arg);
1238 arg = (caddr_t)&ival;
1241 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1242 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1245 if (cmd == KDSETREPEAT) {
1249 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1250 if (((int *)arg)[0] >= delays[i])
1255 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1256 if (((int *)arg)[1] >= rates[i])
1263 KBDMUX_UNLOCK(state);
1268 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1269 kbd->kb_delay2 = rates[mode & 0x1f];
1270 #ifdef EVDEV_SUPPORT
1271 if (state->ks_evdev != NULL &&
1272 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1273 evdev_push_repeats(state->ks_evdev, kbd);
1275 /* perform command on all slave keyboards */
1276 SLIST_FOREACH(k, &state->ks_kbds, next)
1277 (void)kbdd_ioctl(k->kbd, cmd, arg);
1279 KBDMUX_UNLOCK(state);
1282 case PIO_KEYMAP: /* set keyboard translation table */
1283 case OPIO_KEYMAP: /* set keyboard translation table (compat) */
1284 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1285 case PIO_DEADKEYMAP: /* set accent key translation table */
1287 state->ks_accents = 0;
1289 /* perform command on all slave keyboards */
1290 SLIST_FOREACH(k, &state->ks_kbds, next)
1291 (void)kbdd_ioctl(k->kbd, cmd, arg);
1293 KBDMUX_UNLOCK(state);
1297 error = genkbd_commonioctl(kbd, cmd, arg);
1305 * Lock the access to the keyboard
1308 kbdmux_lock(keyboard_t *kbd, int lock)
1310 return (1); /* XXX */
1314 * Clear the internal state of the keyboard
1317 kbdmux_clear_state_locked(kbdmux_state_t *state)
1319 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1321 state->ks_flags &= ~COMPOSE;
1322 state->ks_polling = 0;
1323 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1324 state->ks_accents = 0;
1325 state->ks_composed_char = 0;
1326 /* state->ks_prefix = 0; XXX */
1327 state->ks_inq_length = 0;
1331 kbdmux_clear_state(keyboard_t *kbd)
1333 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1336 kbdmux_clear_state_locked(state);
1337 KBDMUX_UNLOCK(state);
1341 * Save the internal state
1344 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1347 return (sizeof(kbdmux_state_t));
1348 if (len < sizeof(kbdmux_state_t))
1351 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1357 * Set the internal state
1360 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1362 if (len < sizeof(kbdmux_state_t))
1365 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1374 kbdmux_poll(keyboard_t *kbd, int on)
1376 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1382 state->ks_polling++;
1384 state->ks_polling--;
1386 /* set poll on slave keyboards */
1387 SLIST_FOREACH(k, &state->ks_kbds, next)
1388 kbdd_poll(k->kbd, on);
1390 KBDMUX_UNLOCK(state);
1395 #ifdef EVDEV_SUPPORT
1397 kbdmux_ev_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
1400 keyboard_t *kbd = evdev_get_softc(evdev);
1402 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX &&
1403 (type == EV_LED || type == EV_REP)) {
1405 kbd_ev_event(kbd, type, code, value);
1411 /*****************************************************************************
1412 *****************************************************************************
1414 *****************************************************************************
1415 *****************************************************************************/
1417 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1420 kbdmux_modevent(module_t mod, int type, void *data)
1422 keyboard_switch_t *sw;
1428 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1431 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1432 kbd_delete_driver(&kbdmux_kbd_driver);
1439 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1440 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1441 kbd_delete_driver(&kbdmux_kbd_driver);
1445 #ifdef KBD_INSTALL_CDEV
1446 if ((error = kbd_attach(kbd)) != 0) {
1448 kbd_delete_driver(&kbdmux_kbd_driver);
1453 if ((error = (*sw->enable)(kbd)) != 0) {
1454 (*sw->disable)(kbd);
1455 #ifdef KBD_INSTALL_CDEV
1459 kbd_delete_driver(&kbdmux_kbd_driver);
1465 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1466 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1468 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1470 (*sw->disable)(kbd);
1471 #ifdef KBD_INSTALL_CDEV
1475 kbd_delete_driver(&kbdmux_kbd_driver);
1488 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1489 #ifdef EVDEV_SUPPORT
1490 MODULE_DEPEND(kbdmux, evdev, 1, 1, 1);