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))
109 #define KBDMUX_LOCK_DECL_GLOBAL
111 #define KBDMUX_LOCK_INIT(s)
113 #define KBDMUX_LOCK_DESTROY(s)
115 #define KBDMUX_LOCK(s)
117 #define KBDMUX_UNLOCK(s)
119 #define KBDMUX_LOCK_ASSERT(s, w)
128 keyboard_t *kbd; /* keyboard */
129 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
132 typedef struct kbdmux_kbd kbdmux_kbd_t;
139 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
140 unsigned int ks_inq_start;
141 unsigned int ks_inq_length;
142 struct task ks_task; /* interrupt task */
143 struct callout ks_timo; /* timeout handler */
144 #define TICKS (hz) /* rate */
146 int ks_flags; /* flags */
147 #define COMPOSE (1 << 0) /* compose char flag */
149 int ks_polling; /* poll nesting count */
150 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
151 int ks_state; /* state */
152 int ks_accents; /* accent key index (> 0) */
153 u_int ks_composed_char; /* composed char code */
154 u_char ks_prefix; /* AT scan code prefix */
157 struct evdev_dev * ks_evdev;
161 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
163 KBDMUX_LOCK_DECL_GLOBAL;
166 typedef struct kbdmux_state kbdmux_state_t;
168 /*****************************************************************************
169 *****************************************************************************
171 *****************************************************************************
172 *****************************************************************************/
174 static task_fn_t kbdmux_kbd_intr;
175 static callout_func_t kbdmux_kbd_intr_timo;
176 static kbd_callback_func_t kbdmux_kbd_event;
179 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
183 if (state->ks_inq_length == KBDMUX_Q_SIZE)
186 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
187 state->ks_inq[p] = c;
188 state->ks_inq_length++;
192 kbdmux_kbd_getc(kbdmux_state_t *state)
196 if (state->ks_inq_length == 0)
199 c = state->ks_inq[state->ks_inq_start];
200 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
201 state->ks_inq_length--;
207 * Interrupt handler task
210 kbdmux_kbd_intr(void *xkbd, int pending)
212 keyboard_t *kbd = (keyboard_t *) xkbd;
214 kbdd_intr(kbd, NULL);
218 * Schedule interrupt handler on timeout. Called with locked state.
221 kbdmux_kbd_intr_timo(void *xstate)
223 kbdmux_state_t *state = (kbdmux_state_t *) xstate;
225 /* queue interrupt task if needed */
226 if (state->ks_inq_length > 0)
227 taskqueue_enqueue(taskqueue_swi_giant, &state->ks_task);
229 /* re-schedule timeout */
230 callout_schedule(&state->ks_timo, TICKS);
234 * Process event from one of our keyboards
237 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
239 kbdmux_state_t *state = (kbdmux_state_t *) arg;
242 case KBDIO_KEYINPUT: {
248 * Read all chars from the keyboard
250 * Turns out that atkbd(4) check_char() method may return
251 * "true" while read_char() method returns NOKEY. If this
252 * happens we could stuck in the loop below. Avoid this
253 * by breaking out of the loop if read_char() method returns
257 while (kbdd_check_char(kbd)) {
258 c = kbdd_read_char(kbd, 0);
262 continue; /* XXX ring bell */
263 if (!KBD_IS_BUSY(kbd))
264 continue; /* not open - discard the input */
266 kbdmux_kbd_putc(state, c);
269 /* queue interrupt task if needed */
270 if (state->ks_inq_length > 0)
271 taskqueue_enqueue(taskqueue_swi_giant, &state->ks_task);
273 KBDMUX_UNLOCK(state);
276 case KBDIO_UNLOADING: {
281 SLIST_FOREACH(k, &state->ks_kbds, next)
286 kbd_release(k->kbd, &k->kbd);
287 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
294 KBDMUX_UNLOCK(state);
305 /****************************************************************************
306 ****************************************************************************
308 ****************************************************************************
309 ****************************************************************************/
311 static int kbdmux_configure(int flags);
312 static kbd_probe_t kbdmux_probe;
313 static kbd_init_t kbdmux_init;
314 static kbd_term_t kbdmux_term;
315 static kbd_intr_t kbdmux_intr;
316 static kbd_test_if_t kbdmux_test_if;
317 static kbd_enable_t kbdmux_enable;
318 static kbd_disable_t kbdmux_disable;
319 static kbd_read_t kbdmux_read;
320 static kbd_check_t kbdmux_check;
321 static kbd_read_char_t kbdmux_read_char;
322 static kbd_check_char_t kbdmux_check_char;
323 static kbd_ioctl_t kbdmux_ioctl;
324 static kbd_lock_t kbdmux_lock;
325 static void kbdmux_clear_state_locked(kbdmux_state_t *state);
326 static kbd_clear_state_t kbdmux_clear_state;
327 static kbd_get_state_t kbdmux_get_state;
328 static kbd_set_state_t kbdmux_set_state;
329 static kbd_poll_mode_t kbdmux_poll;
331 static keyboard_switch_t kbdmuxsw = {
332 .probe = kbdmux_probe,
336 .test_if = kbdmux_test_if,
337 .enable = kbdmux_enable,
338 .disable = kbdmux_disable,
340 .check = kbdmux_check,
341 .read_char = kbdmux_read_char,
342 .check_char = kbdmux_check_char,
343 .ioctl = kbdmux_ioctl,
345 .clear_state = kbdmux_clear_state,
346 .get_state = kbdmux_get_state,
347 .set_state = kbdmux_set_state,
352 static evdev_event_t kbdmux_ev_event;
354 static const struct evdev_methods kbdmux_evdev_methods = {
355 .ev_event = kbdmux_ev_event,
360 * Return the number of found keyboards
363 kbdmux_configure(int flags)
372 kbdmux_probe(int unit, void *arg, int flags)
374 if (resource_disabled(KEYBOARD_NAME, unit))
381 * Reset and initialize the keyboard (stolen from atkbd.c)
384 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
386 keyboard_t *kbd = NULL;
387 kbdmux_state_t *state = NULL;
388 keymap_t *keymap = NULL;
389 accentmap_t *accmap = NULL;
390 fkeytab_t *fkeymap = NULL;
391 int error, needfree, fkeymap_size, delay[2];
393 struct evdev_dev *evdev;
394 char phys_loc[NAMELEN];
398 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
399 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
400 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
401 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
402 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
403 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
406 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
407 (accmap == NULL) || (fkeymap == NULL)) {
412 KBDMUX_LOCK_INIT(state);
413 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
414 callout_init(&state->ks_timo, 1);
415 SLIST_INIT(&state->ks_kbds);
416 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
420 state = (kbdmux_state_t *) kbd->kb_data;
421 keymap = kbd->kb_keymap;
422 accmap = kbd->kb_accentmap;
423 fkeymap = kbd->kb_fkeytab;
424 fkeymap_size = kbd->kb_fkeytab_size;
428 if (!KBD_IS_PROBED(kbd)) {
429 /* XXX assume 101/102 keys keyboard */
430 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
431 bcopy(&key_map, keymap, sizeof(key_map));
432 bcopy(&accent_map, accmap, sizeof(accent_map));
433 bcopy(fkey_tab, fkeymap,
434 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
435 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
436 kbd->kb_data = (void *)state;
438 KBD_FOUND_DEVICE(kbd);
442 kbdmux_clear_state_locked(state);
443 state->ks_mode = K_XLATE;
444 KBDMUX_UNLOCK(state);
447 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
448 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
450 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
452 delay[0] = kbd->kb_delay1;
453 delay[1] = kbd->kb_delay2;
454 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
457 /* register as evdev provider */
458 evdev = evdev_alloc();
459 evdev_set_name(evdev, "System keyboard multiplexer");
460 snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit);
461 evdev_set_phys(evdev, phys_loc);
462 evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
463 evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods);
464 evdev_support_event(evdev, EV_SYN);
465 evdev_support_event(evdev, EV_KEY);
466 evdev_support_event(evdev, EV_LED);
467 evdev_support_event(evdev, EV_REP);
468 evdev_support_all_known_keys(evdev);
469 evdev_support_led(evdev, LED_NUML);
470 evdev_support_led(evdev, LED_CAPSL);
471 evdev_support_led(evdev, LED_SCROLLL);
473 if (evdev_register_mtx(evdev, &Giant))
476 state->ks_evdev = evdev;
477 state->ks_evdev_state = 0;
483 if (!KBD_IS_CONFIGURED(kbd)) {
484 if (kbd_register(kbd) < 0) {
489 KBD_CONFIG_DONE(kbd);
491 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
498 free(state, M_KBDMUX);
500 free(keymap, M_KBDMUX);
502 free(accmap, M_KBDMUX);
504 free(fkeymap, M_KBDMUX);
507 *kbdp = NULL; /* insure ref doesn't leak to caller */
515 * Finish using this keyboard
518 kbdmux_term(keyboard_t *kbd)
520 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
523 /* release all keyboards from the mux */
525 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
526 kbd_release(k->kbd, &k->kbd);
527 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
533 KBDMUX_UNLOCK(state);
535 callout_drain(&state->ks_timo);
536 taskqueue_drain(taskqueue_swi_giant, &state->ks_task);
541 evdev_free(state->ks_evdev);
544 KBDMUX_LOCK_DESTROY(state);
545 bzero(state, sizeof(*state));
546 free(state, M_KBDMUX);
548 free(kbd->kb_keymap, M_KBDMUX);
549 free(kbd->kb_accentmap, M_KBDMUX);
550 free(kbd->kb_fkeytab, M_KBDMUX);
557 * Keyboard interrupt routine
560 kbdmux_intr(keyboard_t *kbd, void *arg)
564 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
565 /* let the callback function to process the input */
566 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
567 kbd->kb_callback.kc_arg);
569 /* read and discard the input; no one is waiting for input */
571 c = kbdmux_read_char(kbd, FALSE);
572 } while (c != NOKEY);
579 * Test the interface to the device
582 kbdmux_test_if(keyboard_t *kbd)
588 * Enable the access to the device; until this function is called,
589 * the client cannot read from the keyboard.
592 kbdmux_enable(keyboard_t *kbd)
599 * Disallow the access to the device
602 kbdmux_disable(keyboard_t *kbd)
609 * Read one byte from the keyboard if it's allowed
612 kbdmux_read(keyboard_t *kbd, int wait)
614 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
618 c = kbdmux_kbd_getc(state);
619 KBDMUX_UNLOCK(state);
624 return (KBD_IS_ACTIVE(kbd)? c : -1);
628 * Check if data is waiting
631 kbdmux_check(keyboard_t *kbd)
633 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
636 if (!KBD_IS_ACTIVE(kbd))
640 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
641 KBDMUX_UNLOCK(state);
647 * Read char from the keyboard (stolen from atkbd.c)
650 kbdmux_read_char(keyboard_t *kbd, int wait)
652 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
654 int scancode, keycode;
660 /* do we have a composed char to return? */
661 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
662 action = state->ks_composed_char;
663 state->ks_composed_char = 0;
664 if (action > UCHAR_MAX) {
665 KBDMUX_UNLOCK(state);
670 KBDMUX_UNLOCK(state);
675 /* see if there is something in the keyboard queue */
676 scancode = kbdmux_kbd_getc(state);
677 if (scancode == -1) {
678 if (state->ks_polling != 0) {
681 SLIST_FOREACH(k, &state->ks_kbds, next) {
682 while (kbdd_check_char(k->kbd)) {
683 scancode = kbdd_read_char(k->kbd, 0);
684 if (scancode == NOKEY)
686 if (scancode == ERRKEY)
688 if (!KBD_IS_BUSY(k->kbd))
691 kbdmux_kbd_putc(state, scancode);
695 if (state->ks_inq_length > 0)
699 KBDMUX_UNLOCK(state);
702 /* XXX FIXME: check for -1 if wait == 1! */
707 /* push evdev event */
708 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) {
709 uint16_t key = evdev_scancode2key(&state->ks_evdev_state,
712 if (key != KEY_RESERVED) {
713 evdev_push_event(state->ks_evdev, EV_KEY,
714 key, scancode & 0x80 ? 0 : 1);
715 evdev_sync(state->ks_evdev);
720 /* return the byte as is for the K_RAW mode */
721 if (state->ks_mode == K_RAW) {
722 KBDMUX_UNLOCK(state);
726 /* translate the scan code into a keycode */
727 keycode = scancode & 0x7F;
728 switch (state->ks_prefix) {
729 case 0x00: /* normal scancode */
731 case 0xB8: /* left alt (compose key) released */
732 if (state->ks_flags & COMPOSE) {
733 state->ks_flags &= ~COMPOSE;
734 if (state->ks_composed_char > UCHAR_MAX)
735 state->ks_composed_char = 0;
738 case 0x38: /* left alt (compose key) pressed */
739 if (!(state->ks_flags & COMPOSE)) {
740 state->ks_flags |= COMPOSE;
741 state->ks_composed_char = 0;
746 state->ks_prefix = scancode;
750 case 0xE0: /* 0xE0 prefix */
751 state->ks_prefix = 0;
753 case 0x1C: /* right enter key */
756 case 0x1D: /* right ctrl key */
759 case 0x35: /* keypad divide key */
762 case 0x37: /* print scrn key */
765 case 0x38: /* right alt key (alt gr) */
768 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
771 case 0x47: /* grey home key */
774 case 0x48: /* grey up arrow key */
777 case 0x49: /* grey page up key */
780 case 0x4B: /* grey left arrow key */
783 case 0x4D: /* grey right arrow key */
786 case 0x4F: /* grey end key */
789 case 0x50: /* grey down arrow key */
792 case 0x51: /* grey page down key */
795 case 0x52: /* grey insert key */
798 case 0x53: /* grey delete key */
801 /* the following 3 are only used on the MS "Natural" keyboard */
802 case 0x5b: /* left Window key */
805 case 0x5c: /* right Window key */
808 case 0x5d: /* menu key */
811 case 0x5e: /* power key */
814 case 0x5f: /* sleep key */
817 case 0x63: /* wake key */
820 case 0x64: /* [JP106USB] backslash, underscore */
823 default: /* ignore everything else */
827 case 0xE1: /* 0xE1 prefix */
829 * The pause/break key on the 101 keyboard produces:
831 * Ctrl-pause/break produces:
832 * E0-46 E0-C6 (See above.)
834 state->ks_prefix = 0;
836 state->ks_prefix = 0x1D;
839 case 0x1D: /* pause / break */
840 state->ks_prefix = 0;
847 /* XXX assume 101/102 keys AT keyboard */
849 case 0x5c: /* print screen */
850 if (state->ks_flags & ALTS)
851 keycode = 0x54; /* sysrq */
853 case 0x68: /* pause/break */
854 if (state->ks_flags & CTLS)
855 keycode = 0x6c; /* break */
859 /* return the key code in the K_CODE mode */
860 if (state->ks_mode == K_CODE) {
861 KBDMUX_UNLOCK(state);
862 return (keycode | (scancode & 0x80));
865 /* compose a character code */
866 if (state->ks_flags & COMPOSE) {
867 switch (keycode | (scancode & 0x80)) {
868 /* key pressed, process it */
869 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
870 state->ks_composed_char *= 10;
871 state->ks_composed_char += keycode - 0x40;
872 if (state->ks_composed_char > UCHAR_MAX) {
873 KBDMUX_UNLOCK(state);
877 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
878 state->ks_composed_char *= 10;
879 state->ks_composed_char += keycode - 0x47;
880 if (state->ks_composed_char > UCHAR_MAX) {
881 KBDMUX_UNLOCK(state);
885 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
886 state->ks_composed_char *= 10;
887 state->ks_composed_char += keycode - 0x4E;
888 if (state->ks_composed_char > UCHAR_MAX) {
889 KBDMUX_UNLOCK(state);
893 case 0x52: /* keypad 0 */
894 state->ks_composed_char *= 10;
895 if (state->ks_composed_char > UCHAR_MAX) {
896 KBDMUX_UNLOCK(state);
901 /* key released, no interest here */
902 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
903 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
904 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
905 case 0xD2: /* keypad 0 */
908 case 0x38: /* left alt key */
912 if (state->ks_composed_char > 0) {
913 state->ks_flags &= ~COMPOSE;
914 state->ks_composed_char = 0;
915 KBDMUX_UNLOCK(state);
922 /* keycode to key action */
923 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
924 &state->ks_state, &state->ks_accents);
928 KBDMUX_UNLOCK(state);
934 * Check if char is waiting
937 kbdmux_check_char(keyboard_t *kbd)
939 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
942 if (!KBD_IS_ACTIVE(kbd))
947 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
950 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
952 KBDMUX_UNLOCK(state);
961 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
963 static int delays[] = {
967 static int rates[] = {
968 34, 38, 42, 46, 50, 55, 59, 63,
969 68, 76, 84, 92, 100, 110, 118, 126,
970 136, 152, 168, 184, 200, 220, 236, 252,
971 272, 304, 336, 368, 400, 440, 472, 504
974 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
978 #ifdef COMPAT_FREEBSD6
986 case KBADDKBD: /* add keyboard to the mux */
987 ki = (keyboard_info_t *) arg;
989 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
990 strcmp(ki->kb_name, "*") == 0)
991 return (EINVAL); /* bad input */
995 SLIST_FOREACH(k, &state->ks_kbds, next)
996 if (k->kbd->kb_unit == ki->kb_unit &&
997 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1001 KBDMUX_UNLOCK(state);
1003 return (0); /* keyboard already in the mux */
1006 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
1008 KBDMUX_UNLOCK(state);
1010 return (ENOMEM); /* out of memory */
1013 k->kbd = kbd_get_keyboard(
1018 kbdmux_kbd_event, (void *) state));
1019 if (k->kbd == NULL) {
1020 KBDMUX_UNLOCK(state);
1023 return (EINVAL); /* bad keyboard */
1026 kbdd_enable(k->kbd);
1027 kbdd_clear_state(k->kbd);
1029 /* set K_RAW mode on slave keyboard */
1031 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1033 /* set lock keys state on slave keyboard */
1034 mode = state->ks_state & LOCK_MASK;
1035 error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1039 KBDMUX_UNLOCK(state);
1041 kbd_release(k->kbd, &k->kbd);
1046 return (error); /* could not set mode */
1049 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1051 KBDMUX_UNLOCK(state);
1054 case KBRELKBD: /* release keyboard from the mux */
1055 ki = (keyboard_info_t *) arg;
1057 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1058 strcmp(ki->kb_name, "*") == 0)
1059 return (EINVAL); /* bad input */
1063 SLIST_FOREACH(k, &state->ks_kbds, next)
1064 if (k->kbd->kb_unit == ki->kb_unit &&
1065 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1069 error = kbd_release(k->kbd, &k->kbd);
1071 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1078 error = ENXIO; /* keyboard is not in the mux */
1080 KBDMUX_UNLOCK(state);
1083 case KDGKBMODE: /* get kyboard mode */
1085 *(int *)arg = state->ks_mode;
1086 KBDMUX_UNLOCK(state);
1089 #ifdef COMPAT_FREEBSD6
1091 ival = IOCPARM_IVAL(arg);
1092 arg = (caddr_t)&ival;
1095 case KDSKBMODE: /* set keyboard mode */
1098 switch (*(int *)arg) {
1100 if (state->ks_mode != K_XLATE) {
1101 /* make lock key state and LED state match */
1102 state->ks_state &= ~LOCK_MASK;
1103 state->ks_state |= KBD_LED_VAL(kbd);
1109 if (state->ks_mode != *(int *)arg) {
1110 kbdmux_clear_state_locked(state);
1111 state->ks_mode = *(int *)arg;
1120 KBDMUX_UNLOCK(state);
1123 case KDGETLED: /* get keyboard LED */
1125 *(int *)arg = KBD_LED_VAL(kbd);
1126 KBDMUX_UNLOCK(state);
1129 #ifdef COMPAT_FREEBSD6
1131 ival = IOCPARM_IVAL(arg);
1132 arg = (caddr_t)&ival;
1135 case KDSETLED: /* set keyboard LED */
1138 /* NOTE: lock key state in ks_state won't be changed */
1139 if (*(int *)arg & ~LOCK_MASK) {
1140 KBDMUX_UNLOCK(state);
1145 KBD_LED_VAL(kbd) = *(int *)arg;
1146 #ifdef EVDEV_SUPPORT
1147 if (state->ks_evdev != NULL &&
1148 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1149 evdev_push_leds(state->ks_evdev, *(int *)arg);
1151 /* KDSETLED on all slave keyboards */
1152 SLIST_FOREACH(k, &state->ks_kbds, next)
1153 (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
1155 KBDMUX_UNLOCK(state);
1158 case KDGKBSTATE: /* get lock key state */
1160 *(int *)arg = state->ks_state & LOCK_MASK;
1161 KBDMUX_UNLOCK(state);
1164 #ifdef COMPAT_FREEBSD6
1166 ival = IOCPARM_IVAL(arg);
1167 arg = (caddr_t)&ival;
1170 case KDSKBSTATE: /* set lock key state */
1173 if (*(int *)arg & ~LOCK_MASK) {
1174 KBDMUX_UNLOCK(state);
1179 state->ks_state &= ~LOCK_MASK;
1180 state->ks_state |= *(int *)arg;
1182 /* KDSKBSTATE on all slave keyboards */
1183 SLIST_FOREACH(k, &state->ks_kbds, next)
1184 (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
1186 KBDMUX_UNLOCK(state);
1188 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1191 #ifdef COMPAT_FREEBSD6
1194 ival = IOCPARM_IVAL(arg);
1195 arg = (caddr_t)&ival;
1198 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1199 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1202 if (cmd == KDSETREPEAT) {
1206 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1207 if (((int *)arg)[0] >= delays[i])
1212 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1213 if (((int *)arg)[1] >= rates[i])
1220 KBDMUX_UNLOCK(state);
1225 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1226 kbd->kb_delay2 = rates[mode & 0x1f];
1227 #ifdef EVDEV_SUPPORT
1228 if (state->ks_evdev != NULL &&
1229 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1230 evdev_push_repeats(state->ks_evdev, kbd);
1232 /* perform command on all slave keyboards */
1233 SLIST_FOREACH(k, &state->ks_kbds, next)
1234 (void)kbdd_ioctl(k->kbd, cmd, arg);
1236 KBDMUX_UNLOCK(state);
1239 case PIO_KEYMAP: /* set keyboard translation table */
1240 case OPIO_KEYMAP: /* set keyboard translation table (compat) */
1241 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1242 case PIO_DEADKEYMAP: /* set accent key translation table */
1244 state->ks_accents = 0;
1246 /* perform command on all slave keyboards */
1247 SLIST_FOREACH(k, &state->ks_kbds, next)
1248 (void)kbdd_ioctl(k->kbd, cmd, arg);
1250 KBDMUX_UNLOCK(state);
1254 error = genkbd_commonioctl(kbd, cmd, arg);
1262 * Lock the access to the keyboard
1265 kbdmux_lock(keyboard_t *kbd, int lock)
1267 return (1); /* XXX */
1271 * Clear the internal state of the keyboard
1274 kbdmux_clear_state_locked(kbdmux_state_t *state)
1276 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1278 state->ks_flags &= ~COMPOSE;
1279 state->ks_polling = 0;
1280 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1281 state->ks_accents = 0;
1282 state->ks_composed_char = 0;
1283 /* state->ks_prefix = 0; XXX */
1284 state->ks_inq_length = 0;
1288 kbdmux_clear_state(keyboard_t *kbd)
1290 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1293 kbdmux_clear_state_locked(state);
1294 KBDMUX_UNLOCK(state);
1298 * Save the internal state
1301 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1304 return (sizeof(kbdmux_state_t));
1305 if (len < sizeof(kbdmux_state_t))
1308 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1314 * Set the internal state
1317 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1319 if (len < sizeof(kbdmux_state_t))
1322 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1331 kbdmux_poll(keyboard_t *kbd, int on)
1333 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1339 state->ks_polling++;
1341 state->ks_polling--;
1343 /* set poll on slave keyboards */
1344 SLIST_FOREACH(k, &state->ks_kbds, next)
1345 kbdd_poll(k->kbd, on);
1347 KBDMUX_UNLOCK(state);
1352 #ifdef EVDEV_SUPPORT
1354 kbdmux_ev_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
1357 keyboard_t *kbd = evdev_get_softc(evdev);
1359 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX &&
1360 (type == EV_LED || type == EV_REP)) {
1362 kbd_ev_event(kbd, type, code, value);
1368 /*****************************************************************************
1369 *****************************************************************************
1371 *****************************************************************************
1372 *****************************************************************************/
1374 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1377 kbdmux_modevent(module_t mod, int type, void *data)
1379 keyboard_switch_t *sw;
1385 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1388 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1395 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1396 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0)
1399 #ifdef KBD_INSTALL_CDEV
1400 if ((error = kbd_attach(kbd)) != 0) {
1406 if ((error = (*sw->enable)(kbd)) != 0)
1411 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1416 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1418 (*sw->disable)(kbd);
1419 #ifdef KBD_INSTALL_CDEV
1424 kbd_delete_driver(&kbdmux_kbd_driver);
1436 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1437 #ifdef EVDEV_SUPPORT
1438 MODULE_DEPEND(kbdmux, evdev, 1, 1, 1);