6 * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
34 #include "opt_compat.h"
35 #include "opt_evdev.h"
37 #include "opt_kbdmux.h"
39 #include <sys/param.h>
42 #include <sys/consio.h>
43 #include <sys/fcntl.h>
45 #include <sys/kernel.h>
46 #include <sys/limits.h>
48 #include <sys/malloc.h>
49 #include <sys/module.h>
50 #include <sys/mutex.h>
53 #include <sys/queue.h>
54 #include <sys/selinfo.h>
55 #include <sys/systm.h>
56 #include <sys/taskqueue.h>
58 #include <dev/kbd/kbdreg.h>
60 /* the initial key map, accent map and fkey strings */
61 #ifdef KBDMUX_DFLT_KEYMAP
62 #define KBD_DFLT_KEYMAP
63 #include "kbdmuxmap.h"
66 #include <dev/kbd/kbdtables.h>
69 #include <dev/evdev/evdev.h>
70 #include <dev/evdev/input.h>
73 #define KEYBOARD_NAME "kbdmux"
75 MALLOC_DECLARE(M_KBDMUX);
76 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
78 /*****************************************************************************
79 *****************************************************************************
81 *****************************************************************************
82 *****************************************************************************/
84 #define KBDMUX_Q_SIZE 512 /* input queue size */
88 * For now rely on Giant mutex to protect our data structures.
89 * Just like the rest of keyboard drivers and syscons(4) do.
90 * Note that callout is initialized as not MP-safe to make sure
95 #define KBDMUX_LOCK_DECL_GLOBAL \
97 #define KBDMUX_LOCK_INIT(s) \
98 mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
99 #define KBDMUX_LOCK_DESTROY(s) \
100 mtx_destroy(&(s)->ks_lock)
101 #define KBDMUX_LOCK(s) \
102 mtx_lock(&(s)->ks_lock)
103 #define KBDMUX_UNLOCK(s) \
104 mtx_unlock(&(s)->ks_lock)
105 #define KBDMUX_LOCK_ASSERT(s, w) \
106 mtx_assert(&(s)->ks_lock, (w))
107 #define KBDMUX_SLEEP(s, f, d, t) \
108 msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
109 #define KBDMUX_CALLOUT_INIT(s) \
110 callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
111 #define KBDMUX_QUEUE_INTR(s) \
112 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
114 #define KBDMUX_LOCK_DECL_GLOBAL
116 #define KBDMUX_LOCK_INIT(s)
118 #define KBDMUX_LOCK_DESTROY(s)
120 #define KBDMUX_LOCK(s)
122 #define KBDMUX_UNLOCK(s)
124 #define KBDMUX_LOCK_ASSERT(s, w)
126 #define KBDMUX_SLEEP(s, f, d, t) \
127 tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t))
128 #define KBDMUX_CALLOUT_INIT(s) \
129 callout_init(&(s)->ks_timo, 0)
130 #define KBDMUX_QUEUE_INTR(s) \
131 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
139 keyboard_t *kbd; /* keyboard */
140 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
143 typedef struct kbdmux_kbd kbdmux_kbd_t;
150 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
151 unsigned int ks_inq_start;
152 unsigned int ks_inq_length;
153 struct task ks_task; /* interrupt task */
154 struct callout ks_timo; /* timeout handler */
155 #define TICKS (hz) /* rate */
157 int ks_flags; /* flags */
158 #define COMPOSE (1 << 0) /* compose char flag */
159 #define TASK (1 << 2) /* interrupt task queued */
161 int ks_polling; /* poll nesting count */
162 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
163 int ks_state; /* state */
164 int ks_accents; /* accent key index (> 0) */
165 u_int ks_composed_char; /* composed char code */
166 u_char ks_prefix; /* AT scan code prefix */
169 struct evdev_dev * ks_evdev;
173 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
175 KBDMUX_LOCK_DECL_GLOBAL;
178 typedef struct kbdmux_state kbdmux_state_t;
180 /*****************************************************************************
181 *****************************************************************************
183 *****************************************************************************
184 *****************************************************************************/
186 static task_fn_t kbdmux_kbd_intr;
187 static timeout_t kbdmux_kbd_intr_timo;
188 static kbd_callback_func_t kbdmux_kbd_event;
191 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
195 if (state->ks_inq_length == KBDMUX_Q_SIZE)
198 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
199 state->ks_inq[p] = c;
200 state->ks_inq_length++;
204 kbdmux_kbd_getc(kbdmux_state_t *state)
208 if (state->ks_inq_length == 0)
211 c = state->ks_inq[state->ks_inq_start];
212 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
213 state->ks_inq_length--;
219 * Interrupt handler task
222 kbdmux_kbd_intr(void *xkbd, int pending)
224 keyboard_t *kbd = (keyboard_t *) xkbd;
225 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
227 kbdd_intr(kbd, NULL);
231 state->ks_flags &= ~TASK;
232 wakeup(&state->ks_task);
234 KBDMUX_UNLOCK(state);
238 * Schedule interrupt handler on timeout. Called with locked state.
241 kbdmux_kbd_intr_timo(void *xstate)
243 kbdmux_state_t *state = (kbdmux_state_t *) xstate;
245 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
247 if (callout_pending(&state->ks_timo))
248 return; /* callout was reset */
250 if (!callout_active(&state->ks_timo))
251 return; /* callout was stopped */
253 callout_deactivate(&state->ks_timo);
255 /* queue interrupt task if needed */
256 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
257 KBDMUX_QUEUE_INTR(state) == 0)
258 state->ks_flags |= TASK;
260 /* re-schedule timeout */
261 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
265 * Process event from one of our keyboards
268 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
270 kbdmux_state_t *state = (kbdmux_state_t *) arg;
273 case KBDIO_KEYINPUT: {
279 * Read all chars from the keyboard
281 * Turns out that atkbd(4) check_char() method may return
282 * "true" while read_char() method returns NOKEY. If this
283 * happens we could stuck in the loop below. Avoid this
284 * by breaking out of the loop if read_char() method returns
288 while (kbdd_check_char(kbd)) {
289 c = kbdd_read_char(kbd, 0);
293 continue; /* XXX ring bell */
294 if (!KBD_IS_BUSY(kbd))
295 continue; /* not open - discard the input */
297 kbdmux_kbd_putc(state, c);
300 /* queue interrupt task if needed */
301 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
302 KBDMUX_QUEUE_INTR(state) == 0)
303 state->ks_flags |= TASK;
305 KBDMUX_UNLOCK(state);
308 case KBDIO_UNLOADING: {
313 SLIST_FOREACH(k, &state->ks_kbds, next)
318 kbd_release(k->kbd, &k->kbd);
319 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
326 KBDMUX_UNLOCK(state);
337 /****************************************************************************
338 ****************************************************************************
340 ****************************************************************************
341 ****************************************************************************/
343 static int kbdmux_configure(int flags);
344 static kbd_probe_t kbdmux_probe;
345 static kbd_init_t kbdmux_init;
346 static kbd_term_t kbdmux_term;
347 static kbd_intr_t kbdmux_intr;
348 static kbd_test_if_t kbdmux_test_if;
349 static kbd_enable_t kbdmux_enable;
350 static kbd_disable_t kbdmux_disable;
351 static kbd_read_t kbdmux_read;
352 static kbd_check_t kbdmux_check;
353 static kbd_read_char_t kbdmux_read_char;
354 static kbd_check_char_t kbdmux_check_char;
355 static kbd_ioctl_t kbdmux_ioctl;
356 static kbd_lock_t kbdmux_lock;
357 static void kbdmux_clear_state_locked(kbdmux_state_t *state);
358 static kbd_clear_state_t kbdmux_clear_state;
359 static kbd_get_state_t kbdmux_get_state;
360 static kbd_set_state_t kbdmux_set_state;
361 static kbd_poll_mode_t kbdmux_poll;
363 static keyboard_switch_t kbdmuxsw = {
364 .probe = kbdmux_probe,
368 .test_if = kbdmux_test_if,
369 .enable = kbdmux_enable,
370 .disable = kbdmux_disable,
372 .check = kbdmux_check,
373 .read_char = kbdmux_read_char,
374 .check_char = kbdmux_check_char,
375 .ioctl = kbdmux_ioctl,
377 .clear_state = kbdmux_clear_state,
378 .get_state = kbdmux_get_state,
379 .set_state = kbdmux_set_state,
380 .get_fkeystr = genkbd_get_fkeystr,
386 static const struct evdev_methods kbdmux_evdev_methods = {
387 .ev_event = evdev_ev_kbd_event,
392 * Return the number of found keyboards
395 kbdmux_configure(int flags)
404 kbdmux_probe(int unit, void *arg, int flags)
406 if (resource_disabled(KEYBOARD_NAME, unit))
413 * Reset and initialize the keyboard (stolen from atkbd.c)
416 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
418 keyboard_t *kbd = NULL;
419 kbdmux_state_t *state = NULL;
420 keymap_t *keymap = NULL;
421 accentmap_t *accmap = NULL;
422 fkeytab_t *fkeymap = NULL;
423 int error, needfree, fkeymap_size, delay[2];
425 struct evdev_dev *evdev;
426 char phys_loc[NAMELEN];
430 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
431 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
432 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
433 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
434 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
435 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
438 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
439 (accmap == NULL) || (fkeymap == NULL)) {
444 KBDMUX_LOCK_INIT(state);
445 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
446 KBDMUX_CALLOUT_INIT(state);
447 SLIST_INIT(&state->ks_kbds);
448 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
452 state = (kbdmux_state_t *) kbd->kb_data;
453 keymap = kbd->kb_keymap;
454 accmap = kbd->kb_accentmap;
455 fkeymap = kbd->kb_fkeytab;
456 fkeymap_size = kbd->kb_fkeytab_size;
460 if (!KBD_IS_PROBED(kbd)) {
461 /* XXX assume 101/102 keys keyboard */
462 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
463 bcopy(&key_map, keymap, sizeof(key_map));
464 bcopy(&accent_map, accmap, sizeof(accent_map));
465 bcopy(fkey_tab, fkeymap,
466 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
467 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
468 kbd->kb_data = (void *)state;
470 KBD_FOUND_DEVICE(kbd);
474 kbdmux_clear_state_locked(state);
475 state->ks_mode = K_XLATE;
476 KBDMUX_UNLOCK(state);
479 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
480 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
482 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
484 delay[0] = kbd->kb_delay1;
485 delay[1] = kbd->kb_delay2;
486 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
489 /* register as evdev provider */
490 evdev = evdev_alloc();
491 evdev_set_name(evdev, "System keyboard multiplexer");
492 snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit);
493 evdev_set_phys(evdev, phys_loc);
494 evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
495 evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods);
496 evdev_support_event(evdev, EV_SYN);
497 evdev_support_event(evdev, EV_KEY);
498 evdev_support_event(evdev, EV_LED);
499 evdev_support_event(evdev, EV_REP);
500 evdev_support_all_known_keys(evdev);
501 evdev_support_led(evdev, LED_NUML);
502 evdev_support_led(evdev, LED_CAPSL);
503 evdev_support_led(evdev, LED_SCROLLL);
505 if (evdev_register(evdev))
508 state->ks_evdev = evdev;
509 state->ks_evdev_state = 0;
515 if (!KBD_IS_CONFIGURED(kbd)) {
516 if (kbd_register(kbd) < 0) {
521 KBD_CONFIG_DONE(kbd);
524 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
525 KBDMUX_UNLOCK(state);
532 free(state, M_KBDMUX);
534 free(keymap, M_KBDMUX);
536 free(accmap, M_KBDMUX);
538 free(fkeymap, M_KBDMUX);
541 *kbdp = NULL; /* insure ref doesn't leak to caller */
549 * Finish using this keyboard
552 kbdmux_term(keyboard_t *kbd)
554 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
560 callout_stop(&state->ks_timo);
562 /* wait for interrupt task */
563 while (state->ks_flags & TASK)
564 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
566 /* release all keyboards from the mux */
567 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
568 kbd_release(k->kbd, &k->kbd);
569 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
576 KBDMUX_UNLOCK(state);
581 evdev_free(state->ks_evdev);
584 KBDMUX_LOCK_DESTROY(state);
585 bzero(state, sizeof(*state));
586 free(state, M_KBDMUX);
588 free(kbd->kb_keymap, M_KBDMUX);
589 free(kbd->kb_accentmap, M_KBDMUX);
590 free(kbd->kb_fkeytab, M_KBDMUX);
597 * Keyboard interrupt routine
600 kbdmux_intr(keyboard_t *kbd, void *arg)
604 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
605 /* let the callback function to process the input */
606 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
607 kbd->kb_callback.kc_arg);
609 /* read and discard the input; no one is waiting for input */
611 c = kbdmux_read_char(kbd, FALSE);
612 } while (c != NOKEY);
619 * Test the interface to the device
622 kbdmux_test_if(keyboard_t *kbd)
628 * Enable the access to the device; until this function is called,
629 * the client cannot read from the keyboard.
632 kbdmux_enable(keyboard_t *kbd)
639 * Disallow the access to the device
642 kbdmux_disable(keyboard_t *kbd)
649 * Read one byte from the keyboard if it's allowed
652 kbdmux_read(keyboard_t *kbd, int wait)
654 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
658 c = kbdmux_kbd_getc(state);
659 KBDMUX_UNLOCK(state);
664 return (KBD_IS_ACTIVE(kbd)? c : -1);
668 * Check if data is waiting
671 kbdmux_check(keyboard_t *kbd)
673 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
676 if (!KBD_IS_ACTIVE(kbd))
680 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
681 KBDMUX_UNLOCK(state);
687 * Read char from the keyboard (stolen from atkbd.c)
690 kbdmux_read_char(keyboard_t *kbd, int wait)
692 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
694 int scancode, keycode;
700 /* do we have a composed char to return? */
701 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
702 action = state->ks_composed_char;
703 state->ks_composed_char = 0;
704 if (action > UCHAR_MAX) {
705 KBDMUX_UNLOCK(state);
710 KBDMUX_UNLOCK(state);
715 /* see if there is something in the keyboard queue */
716 scancode = kbdmux_kbd_getc(state);
717 if (scancode == -1) {
718 if (state->ks_polling != 0) {
721 SLIST_FOREACH(k, &state->ks_kbds, next) {
722 while (kbdd_check_char(k->kbd)) {
723 scancode = kbdd_read_char(k->kbd, 0);
724 if (scancode == NOKEY)
726 if (scancode == ERRKEY)
728 if (!KBD_IS_BUSY(k->kbd))
731 kbdmux_kbd_putc(state, scancode);
735 if (state->ks_inq_length > 0)
739 KBDMUX_UNLOCK(state);
742 /* XXX FIXME: check for -1 if wait == 1! */
747 /* push evdev event */
748 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) {
749 uint16_t key = evdev_scancode2key(&state->ks_evdev_state,
752 if (key != KEY_RESERVED) {
753 evdev_push_event(state->ks_evdev, EV_KEY,
754 key, scancode & 0x80 ? 0 : 1);
755 evdev_sync(state->ks_evdev);
760 /* return the byte as is for the K_RAW mode */
761 if (state->ks_mode == K_RAW) {
762 KBDMUX_UNLOCK(state);
766 /* translate the scan code into a keycode */
767 keycode = scancode & 0x7F;
768 switch (state->ks_prefix) {
769 case 0x00: /* normal scancode */
771 case 0xB8: /* left alt (compose key) released */
772 if (state->ks_flags & COMPOSE) {
773 state->ks_flags &= ~COMPOSE;
774 if (state->ks_composed_char > UCHAR_MAX)
775 state->ks_composed_char = 0;
778 case 0x38: /* left alt (compose key) pressed */
779 if (!(state->ks_flags & COMPOSE)) {
780 state->ks_flags |= COMPOSE;
781 state->ks_composed_char = 0;
786 state->ks_prefix = scancode;
790 case 0xE0: /* 0xE0 prefix */
791 state->ks_prefix = 0;
793 case 0x1C: /* right enter key */
796 case 0x1D: /* right ctrl key */
799 case 0x35: /* keypad divide key */
802 case 0x37: /* print scrn key */
805 case 0x38: /* right alt key (alt gr) */
808 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
811 case 0x47: /* grey home key */
814 case 0x48: /* grey up arrow key */
817 case 0x49: /* grey page up key */
820 case 0x4B: /* grey left arrow key */
823 case 0x4D: /* grey right arrow key */
826 case 0x4F: /* grey end key */
829 case 0x50: /* grey down arrow key */
832 case 0x51: /* grey page down key */
835 case 0x52: /* grey insert key */
838 case 0x53: /* grey delete key */
841 /* the following 3 are only used on the MS "Natural" keyboard */
842 case 0x5b: /* left Window key */
845 case 0x5c: /* right Window key */
848 case 0x5d: /* menu key */
851 case 0x5e: /* power key */
854 case 0x5f: /* sleep key */
857 case 0x63: /* wake key */
860 case 0x64: /* [JP106USB] backslash, underscore */
863 default: /* ignore everything else */
867 case 0xE1: /* 0xE1 prefix */
869 * The pause/break key on the 101 keyboard produces:
871 * Ctrl-pause/break produces:
872 * E0-46 E0-C6 (See above.)
874 state->ks_prefix = 0;
876 state->ks_prefix = 0x1D;
879 case 0x1D: /* pause / break */
880 state->ks_prefix = 0;
887 /* XXX assume 101/102 keys AT keyboard */
889 case 0x5c: /* print screen */
890 if (state->ks_flags & ALTS)
891 keycode = 0x54; /* sysrq */
893 case 0x68: /* pause/break */
894 if (state->ks_flags & CTLS)
895 keycode = 0x6c; /* break */
899 /* return the key code in the K_CODE mode */
900 if (state->ks_mode == K_CODE) {
901 KBDMUX_UNLOCK(state);
902 return (keycode | (scancode & 0x80));
905 /* compose a character code */
906 if (state->ks_flags & COMPOSE) {
907 switch (keycode | (scancode & 0x80)) {
908 /* key pressed, process it */
909 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
910 state->ks_composed_char *= 10;
911 state->ks_composed_char += keycode - 0x40;
912 if (state->ks_composed_char > UCHAR_MAX) {
913 KBDMUX_UNLOCK(state);
917 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
918 state->ks_composed_char *= 10;
919 state->ks_composed_char += keycode - 0x47;
920 if (state->ks_composed_char > UCHAR_MAX) {
921 KBDMUX_UNLOCK(state);
925 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
926 state->ks_composed_char *= 10;
927 state->ks_composed_char += keycode - 0x4E;
928 if (state->ks_composed_char > UCHAR_MAX) {
929 KBDMUX_UNLOCK(state);
933 case 0x52: /* keypad 0 */
934 state->ks_composed_char *= 10;
935 if (state->ks_composed_char > UCHAR_MAX) {
936 KBDMUX_UNLOCK(state);
941 /* key released, no interest here */
942 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
943 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
944 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
945 case 0xD2: /* keypad 0 */
948 case 0x38: /* left alt key */
952 if (state->ks_composed_char > 0) {
953 state->ks_flags &= ~COMPOSE;
954 state->ks_composed_char = 0;
955 KBDMUX_UNLOCK(state);
962 /* keycode to key action */
963 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
964 &state->ks_state, &state->ks_accents);
968 KBDMUX_UNLOCK(state);
974 * Check if char is waiting
977 kbdmux_check_char(keyboard_t *kbd)
979 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
982 if (!KBD_IS_ACTIVE(kbd))
987 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
990 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
992 KBDMUX_UNLOCK(state);
1001 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
1003 static int delays[] = {
1007 static int rates[] = {
1008 34, 38, 42, 46, 50, 55, 59, 63,
1009 68, 76, 84, 92, 100, 110, 118, 126,
1010 136, 152, 168, 184, 200, 220, 236, 252,
1011 272, 304, 336, 368, 400, 440, 472, 504
1014 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1016 keyboard_info_t *ki;
1017 int error = 0, mode;
1018 #ifdef COMPAT_FREEBSD6
1026 case KBADDKBD: /* add keyboard to the mux */
1027 ki = (keyboard_info_t *) arg;
1029 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1030 strcmp(ki->kb_name, "*") == 0)
1031 return (EINVAL); /* bad input */
1035 SLIST_FOREACH(k, &state->ks_kbds, next)
1036 if (k->kbd->kb_unit == ki->kb_unit &&
1037 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1041 KBDMUX_UNLOCK(state);
1043 return (0); /* keyboard already in the mux */
1046 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
1048 KBDMUX_UNLOCK(state);
1050 return (ENOMEM); /* out of memory */
1053 k->kbd = kbd_get_keyboard(
1058 kbdmux_kbd_event, (void *) state));
1059 if (k->kbd == NULL) {
1060 KBDMUX_UNLOCK(state);
1063 return (EINVAL); /* bad keyboard */
1066 kbdd_enable(k->kbd);
1067 kbdd_clear_state(k->kbd);
1069 /* set K_RAW mode on slave keyboard */
1071 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1073 /* set lock keys state on slave keyboard */
1074 mode = state->ks_state & LOCK_MASK;
1075 error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1079 KBDMUX_UNLOCK(state);
1081 kbd_release(k->kbd, &k->kbd);
1086 return (error); /* could not set mode */
1089 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1091 KBDMUX_UNLOCK(state);
1094 case KBRELKBD: /* release keyboard from the mux */
1095 ki = (keyboard_info_t *) arg;
1097 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1098 strcmp(ki->kb_name, "*") == 0)
1099 return (EINVAL); /* bad input */
1103 SLIST_FOREACH(k, &state->ks_kbds, next)
1104 if (k->kbd->kb_unit == ki->kb_unit &&
1105 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1109 error = kbd_release(k->kbd, &k->kbd);
1111 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1118 error = ENXIO; /* keyboard is not in the mux */
1120 KBDMUX_UNLOCK(state);
1123 case KDGKBMODE: /* get kyboard mode */
1125 *(int *)arg = state->ks_mode;
1126 KBDMUX_UNLOCK(state);
1129 #ifdef COMPAT_FREEBSD6
1131 ival = IOCPARM_IVAL(arg);
1132 arg = (caddr_t)&ival;
1135 case KDSKBMODE: /* set keyboard mode */
1138 switch (*(int *)arg) {
1140 if (state->ks_mode != K_XLATE) {
1141 /* make lock key state and LED state match */
1142 state->ks_state &= ~LOCK_MASK;
1143 state->ks_state |= KBD_LED_VAL(kbd);
1149 if (state->ks_mode != *(int *)arg) {
1150 kbdmux_clear_state_locked(state);
1151 state->ks_mode = *(int *)arg;
1160 KBDMUX_UNLOCK(state);
1163 case KDGETLED: /* get keyboard LED */
1165 *(int *)arg = KBD_LED_VAL(kbd);
1166 KBDMUX_UNLOCK(state);
1169 #ifdef COMPAT_FREEBSD6
1171 ival = IOCPARM_IVAL(arg);
1172 arg = (caddr_t)&ival;
1175 case KDSETLED: /* set keyboard LED */
1178 /* NOTE: lock key state in ks_state won't be changed */
1179 if (*(int *)arg & ~LOCK_MASK) {
1180 KBDMUX_UNLOCK(state);
1185 KBD_LED_VAL(kbd) = *(int *)arg;
1186 #ifdef EVDEV_SUPPORT
1187 if (state->ks_evdev != NULL &&
1188 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1189 evdev_push_leds(state->ks_evdev, *(int *)arg);
1191 /* KDSETLED on all slave keyboards */
1192 SLIST_FOREACH(k, &state->ks_kbds, next)
1193 (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
1195 KBDMUX_UNLOCK(state);
1198 case KDGKBSTATE: /* get lock key state */
1200 *(int *)arg = state->ks_state & LOCK_MASK;
1201 KBDMUX_UNLOCK(state);
1204 #ifdef COMPAT_FREEBSD6
1206 ival = IOCPARM_IVAL(arg);
1207 arg = (caddr_t)&ival;
1210 case KDSKBSTATE: /* set lock key state */
1213 if (*(int *)arg & ~LOCK_MASK) {
1214 KBDMUX_UNLOCK(state);
1219 state->ks_state &= ~LOCK_MASK;
1220 state->ks_state |= *(int *)arg;
1222 /* KDSKBSTATE on all slave keyboards */
1223 SLIST_FOREACH(k, &state->ks_kbds, next)
1224 (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
1226 KBDMUX_UNLOCK(state);
1228 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1231 #ifdef COMPAT_FREEBSD6
1234 ival = IOCPARM_IVAL(arg);
1235 arg = (caddr_t)&ival;
1238 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1239 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1242 if (cmd == KDSETREPEAT) {
1246 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1247 if (((int *)arg)[0] >= delays[i])
1252 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1253 if (((int *)arg)[1] >= rates[i])
1260 KBDMUX_UNLOCK(state);
1265 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1266 kbd->kb_delay2 = rates[mode & 0x1f];
1267 #ifdef EVDEV_SUPPORT
1268 if (state->ks_evdev != NULL &&
1269 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1270 evdev_push_repeats(state->ks_evdev, kbd);
1272 /* perform command on all slave keyboards */
1273 SLIST_FOREACH(k, &state->ks_kbds, next)
1274 (void)kbdd_ioctl(k->kbd, cmd, arg);
1276 KBDMUX_UNLOCK(state);
1279 case PIO_KEYMAP: /* set keyboard translation table */
1280 case OPIO_KEYMAP: /* set keyboard translation table (compat) */
1281 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1282 case PIO_DEADKEYMAP: /* set accent key translation table */
1284 state->ks_accents = 0;
1286 /* perform command on all slave keyboards */
1287 SLIST_FOREACH(k, &state->ks_kbds, next)
1288 (void)kbdd_ioctl(k->kbd, cmd, arg);
1290 KBDMUX_UNLOCK(state);
1294 error = genkbd_commonioctl(kbd, cmd, arg);
1302 * Lock the access to the keyboard
1305 kbdmux_lock(keyboard_t *kbd, int lock)
1307 return (1); /* XXX */
1311 * Clear the internal state of the keyboard
1314 kbdmux_clear_state_locked(kbdmux_state_t *state)
1316 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1318 state->ks_flags &= ~COMPOSE;
1319 state->ks_polling = 0;
1320 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1321 state->ks_accents = 0;
1322 state->ks_composed_char = 0;
1323 /* state->ks_prefix = 0; XXX */
1324 state->ks_inq_length = 0;
1328 kbdmux_clear_state(keyboard_t *kbd)
1330 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1333 kbdmux_clear_state_locked(state);
1334 KBDMUX_UNLOCK(state);
1338 * Save the internal state
1341 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1344 return (sizeof(kbdmux_state_t));
1345 if (len < sizeof(kbdmux_state_t))
1348 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1354 * Set the internal state
1357 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1359 if (len < sizeof(kbdmux_state_t))
1362 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1371 kbdmux_poll(keyboard_t *kbd, int on)
1373 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1379 state->ks_polling++;
1381 state->ks_polling--;
1383 /* set poll on slave keyboards */
1384 SLIST_FOREACH(k, &state->ks_kbds, next)
1385 kbdd_poll(k->kbd, on);
1387 KBDMUX_UNLOCK(state);
1392 /*****************************************************************************
1393 *****************************************************************************
1395 *****************************************************************************
1396 *****************************************************************************/
1398 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1401 kbdmux_modevent(module_t mod, int type, void *data)
1403 keyboard_switch_t *sw;
1409 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1412 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1413 kbd_delete_driver(&kbdmux_kbd_driver);
1420 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1421 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1422 kbd_delete_driver(&kbdmux_kbd_driver);
1426 #ifdef KBD_INSTALL_CDEV
1427 if ((error = kbd_attach(kbd)) != 0) {
1429 kbd_delete_driver(&kbdmux_kbd_driver);
1434 if ((error = (*sw->enable)(kbd)) != 0) {
1435 (*sw->disable)(kbd);
1436 #ifdef KBD_INSTALL_CDEV
1440 kbd_delete_driver(&kbdmux_kbd_driver);
1446 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1447 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1449 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1451 (*sw->disable)(kbd);
1452 #ifdef KBD_INSTALL_CDEV
1456 kbd_delete_driver(&kbdmux_kbd_driver);
1469 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1470 #ifdef EVDEV_SUPPORT
1471 MODULE_DEPEND(kbdmux, evdev, 1, 1, 1);