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_compat.h"
37 #include "opt_evdev.h"
39 #include "opt_kbdmux.h"
41 #include <sys/param.h>
44 #include <sys/consio.h>
45 #include <sys/fcntl.h>
47 #include <sys/kernel.h>
48 #include <sys/limits.h>
50 #include <sys/malloc.h>
51 #include <sys/module.h>
52 #include <sys/mutex.h>
55 #include <sys/queue.h>
56 #include <sys/selinfo.h>
57 #include <sys/systm.h>
58 #include <sys/taskqueue.h>
60 #include <dev/kbd/kbdreg.h>
62 /* the initial key map, accent map and fkey strings */
63 #ifdef KBDMUX_DFLT_KEYMAP
64 #define KBD_DFLT_KEYMAP
65 #include "kbdmuxmap.h"
68 #include <dev/kbd/kbdtables.h>
71 #include <dev/evdev/evdev.h>
72 #include <dev/evdev/input.h>
75 #define KEYBOARD_NAME "kbdmux"
77 MALLOC_DECLARE(M_KBDMUX);
78 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
80 /*****************************************************************************
81 *****************************************************************************
83 *****************************************************************************
84 *****************************************************************************/
86 #define KBDMUX_Q_SIZE 512 /* input queue size */
90 * For now rely on Giant mutex to protect our data structures.
91 * Just like the rest of keyboard drivers and syscons(4) do.
92 * Note that callout is initialized as not MP-safe to make sure
97 #define KBDMUX_LOCK_DECL_GLOBAL \
99 #define KBDMUX_LOCK_INIT(s) \
100 mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
101 #define KBDMUX_LOCK_DESTROY(s) \
102 mtx_destroy(&(s)->ks_lock)
103 #define KBDMUX_LOCK(s) \
104 mtx_lock(&(s)->ks_lock)
105 #define KBDMUX_UNLOCK(s) \
106 mtx_unlock(&(s)->ks_lock)
107 #define KBDMUX_LOCK_ASSERT(s, w) \
108 mtx_assert(&(s)->ks_lock, (w))
109 #define KBDMUX_SLEEP(s, f, d, t) \
110 msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
111 #define KBDMUX_CALLOUT_INIT(s) \
112 callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
113 #define KBDMUX_QUEUE_INTR(s) \
114 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
116 #define KBDMUX_LOCK_DECL_GLOBAL
118 #define KBDMUX_LOCK_INIT(s)
120 #define KBDMUX_LOCK_DESTROY(s)
122 #define KBDMUX_LOCK(s)
124 #define KBDMUX_UNLOCK(s)
126 #define KBDMUX_LOCK_ASSERT(s, w)
128 #define KBDMUX_SLEEP(s, f, d, t) \
129 tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t))
130 #define KBDMUX_CALLOUT_INIT(s) \
131 callout_init(&(s)->ks_timo, 0)
132 #define KBDMUX_QUEUE_INTR(s) \
133 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
141 keyboard_t *kbd; /* keyboard */
142 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
145 typedef struct kbdmux_kbd kbdmux_kbd_t;
152 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
153 unsigned int ks_inq_start;
154 unsigned int ks_inq_length;
155 struct task ks_task; /* interrupt task */
156 struct callout ks_timo; /* timeout handler */
157 #define TICKS (hz) /* rate */
159 int ks_flags; /* flags */
160 #define COMPOSE (1 << 0) /* compose char flag */
161 #define TASK (1 << 2) /* interrupt task queued */
163 int ks_polling; /* poll nesting count */
164 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
165 int ks_state; /* state */
166 int ks_accents; /* accent key index (> 0) */
167 u_int ks_composed_char; /* composed char code */
168 u_char ks_prefix; /* AT scan code prefix */
171 struct evdev_dev * ks_evdev;
175 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
177 KBDMUX_LOCK_DECL_GLOBAL;
180 typedef struct kbdmux_state kbdmux_state_t;
182 /*****************************************************************************
183 *****************************************************************************
185 *****************************************************************************
186 *****************************************************************************/
188 static task_fn_t kbdmux_kbd_intr;
189 static timeout_t kbdmux_kbd_intr_timo;
190 static kbd_callback_func_t kbdmux_kbd_event;
193 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
197 if (state->ks_inq_length == KBDMUX_Q_SIZE)
200 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
201 state->ks_inq[p] = c;
202 state->ks_inq_length++;
206 kbdmux_kbd_getc(kbdmux_state_t *state)
210 if (state->ks_inq_length == 0)
213 c = state->ks_inq[state->ks_inq_start];
214 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
215 state->ks_inq_length--;
221 * Interrupt handler task
224 kbdmux_kbd_intr(void *xkbd, int pending)
226 keyboard_t *kbd = (keyboard_t *) xkbd;
227 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
229 kbdd_intr(kbd, NULL);
233 state->ks_flags &= ~TASK;
234 wakeup(&state->ks_task);
236 KBDMUX_UNLOCK(state);
240 * Schedule interrupt handler on timeout. Called with locked state.
243 kbdmux_kbd_intr_timo(void *xstate)
245 kbdmux_state_t *state = (kbdmux_state_t *) xstate;
247 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
249 if (callout_pending(&state->ks_timo))
250 return; /* callout was reset */
252 if (!callout_active(&state->ks_timo))
253 return; /* callout was stopped */
255 callout_deactivate(&state->ks_timo);
257 /* queue interrupt task if needed */
258 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
259 KBDMUX_QUEUE_INTR(state) == 0)
260 state->ks_flags |= TASK;
262 /* re-schedule timeout */
263 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
267 * Process event from one of our keyboards
270 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
272 kbdmux_state_t *state = (kbdmux_state_t *) arg;
275 case KBDIO_KEYINPUT: {
281 * Read all chars from the keyboard
283 * Turns out that atkbd(4) check_char() method may return
284 * "true" while read_char() method returns NOKEY. If this
285 * happens we could stuck in the loop below. Avoid this
286 * by breaking out of the loop if read_char() method returns
290 while (kbdd_check_char(kbd)) {
291 c = kbdd_read_char(kbd, 0);
295 continue; /* XXX ring bell */
296 if (!KBD_IS_BUSY(kbd))
297 continue; /* not open - discard the input */
299 kbdmux_kbd_putc(state, c);
302 /* queue interrupt task if needed */
303 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
304 KBDMUX_QUEUE_INTR(state) == 0)
305 state->ks_flags |= TASK;
307 KBDMUX_UNLOCK(state);
310 case KBDIO_UNLOADING: {
315 SLIST_FOREACH(k, &state->ks_kbds, next)
320 kbd_release(k->kbd, &k->kbd);
321 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
328 KBDMUX_UNLOCK(state);
339 /****************************************************************************
340 ****************************************************************************
342 ****************************************************************************
343 ****************************************************************************/
345 static int kbdmux_configure(int flags);
346 static kbd_probe_t kbdmux_probe;
347 static kbd_init_t kbdmux_init;
348 static kbd_term_t kbdmux_term;
349 static kbd_intr_t kbdmux_intr;
350 static kbd_test_if_t kbdmux_test_if;
351 static kbd_enable_t kbdmux_enable;
352 static kbd_disable_t kbdmux_disable;
353 static kbd_read_t kbdmux_read;
354 static kbd_check_t kbdmux_check;
355 static kbd_read_char_t kbdmux_read_char;
356 static kbd_check_char_t kbdmux_check_char;
357 static kbd_ioctl_t kbdmux_ioctl;
358 static kbd_lock_t kbdmux_lock;
359 static void kbdmux_clear_state_locked(kbdmux_state_t *state);
360 static kbd_clear_state_t kbdmux_clear_state;
361 static kbd_get_state_t kbdmux_get_state;
362 static kbd_set_state_t kbdmux_set_state;
363 static kbd_poll_mode_t kbdmux_poll;
365 static keyboard_switch_t kbdmuxsw = {
366 .probe = kbdmux_probe,
370 .test_if = kbdmux_test_if,
371 .enable = kbdmux_enable,
372 .disable = kbdmux_disable,
374 .check = kbdmux_check,
375 .read_char = kbdmux_read_char,
376 .check_char = kbdmux_check_char,
377 .ioctl = kbdmux_ioctl,
379 .clear_state = kbdmux_clear_state,
380 .get_state = kbdmux_get_state,
381 .set_state = kbdmux_set_state,
382 .get_fkeystr = genkbd_get_fkeystr,
388 static const struct evdev_methods kbdmux_evdev_methods = {
389 .ev_event = evdev_ev_kbd_event,
394 * Return the number of found keyboards
397 kbdmux_configure(int flags)
406 kbdmux_probe(int unit, void *arg, int flags)
408 if (resource_disabled(KEYBOARD_NAME, unit))
415 * Reset and initialize the keyboard (stolen from atkbd.c)
418 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
420 keyboard_t *kbd = NULL;
421 kbdmux_state_t *state = NULL;
422 keymap_t *keymap = NULL;
423 accentmap_t *accmap = NULL;
424 fkeytab_t *fkeymap = NULL;
425 int error, needfree, fkeymap_size, delay[2];
427 struct evdev_dev *evdev;
428 char phys_loc[NAMELEN];
432 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
433 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
434 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
435 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
436 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
437 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
440 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
441 (accmap == NULL) || (fkeymap == NULL)) {
446 KBDMUX_LOCK_INIT(state);
447 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
448 KBDMUX_CALLOUT_INIT(state);
449 SLIST_INIT(&state->ks_kbds);
450 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
454 state = (kbdmux_state_t *) kbd->kb_data;
455 keymap = kbd->kb_keymap;
456 accmap = kbd->kb_accentmap;
457 fkeymap = kbd->kb_fkeytab;
458 fkeymap_size = kbd->kb_fkeytab_size;
462 if (!KBD_IS_PROBED(kbd)) {
463 /* XXX assume 101/102 keys keyboard */
464 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
465 bcopy(&key_map, keymap, sizeof(key_map));
466 bcopy(&accent_map, accmap, sizeof(accent_map));
467 bcopy(fkey_tab, fkeymap,
468 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
469 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
470 kbd->kb_data = (void *)state;
472 KBD_FOUND_DEVICE(kbd);
476 kbdmux_clear_state_locked(state);
477 state->ks_mode = K_XLATE;
478 KBDMUX_UNLOCK(state);
481 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
482 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
484 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
486 delay[0] = kbd->kb_delay1;
487 delay[1] = kbd->kb_delay2;
488 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
491 /* register as evdev provider */
492 evdev = evdev_alloc();
493 evdev_set_name(evdev, "System keyboard multiplexer");
494 snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit);
495 evdev_set_phys(evdev, phys_loc);
496 evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
497 evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods);
498 evdev_support_event(evdev, EV_SYN);
499 evdev_support_event(evdev, EV_KEY);
500 evdev_support_event(evdev, EV_LED);
501 evdev_support_event(evdev, EV_REP);
502 evdev_support_all_known_keys(evdev);
503 evdev_support_led(evdev, LED_NUML);
504 evdev_support_led(evdev, LED_CAPSL);
505 evdev_support_led(evdev, LED_SCROLLL);
507 if (evdev_register(evdev))
510 state->ks_evdev = evdev;
511 state->ks_evdev_state = 0;
517 if (!KBD_IS_CONFIGURED(kbd)) {
518 if (kbd_register(kbd) < 0) {
523 KBD_CONFIG_DONE(kbd);
526 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
527 KBDMUX_UNLOCK(state);
534 free(state, M_KBDMUX);
536 free(keymap, M_KBDMUX);
538 free(accmap, M_KBDMUX);
540 free(fkeymap, M_KBDMUX);
543 *kbdp = NULL; /* insure ref doesn't leak to caller */
551 * Finish using this keyboard
554 kbdmux_term(keyboard_t *kbd)
556 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
562 callout_stop(&state->ks_timo);
564 /* wait for interrupt task */
565 while (state->ks_flags & TASK)
566 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
568 /* release all keyboards from the mux */
569 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
570 kbd_release(k->kbd, &k->kbd);
571 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
578 KBDMUX_UNLOCK(state);
583 evdev_free(state->ks_evdev);
586 KBDMUX_LOCK_DESTROY(state);
587 bzero(state, sizeof(*state));
588 free(state, M_KBDMUX);
590 free(kbd->kb_keymap, M_KBDMUX);
591 free(kbd->kb_accentmap, M_KBDMUX);
592 free(kbd->kb_fkeytab, M_KBDMUX);
599 * Keyboard interrupt routine
602 kbdmux_intr(keyboard_t *kbd, void *arg)
606 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
607 /* let the callback function to process the input */
608 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
609 kbd->kb_callback.kc_arg);
611 /* read and discard the input; no one is waiting for input */
613 c = kbdmux_read_char(kbd, FALSE);
614 } while (c != NOKEY);
621 * Test the interface to the device
624 kbdmux_test_if(keyboard_t *kbd)
630 * Enable the access to the device; until this function is called,
631 * the client cannot read from the keyboard.
634 kbdmux_enable(keyboard_t *kbd)
641 * Disallow the access to the device
644 kbdmux_disable(keyboard_t *kbd)
651 * Read one byte from the keyboard if it's allowed
654 kbdmux_read(keyboard_t *kbd, int wait)
656 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
660 c = kbdmux_kbd_getc(state);
661 KBDMUX_UNLOCK(state);
666 return (KBD_IS_ACTIVE(kbd)? c : -1);
670 * Check if data is waiting
673 kbdmux_check(keyboard_t *kbd)
675 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
678 if (!KBD_IS_ACTIVE(kbd))
682 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
683 KBDMUX_UNLOCK(state);
689 * Read char from the keyboard (stolen from atkbd.c)
692 kbdmux_read_char(keyboard_t *kbd, int wait)
694 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
696 int scancode, keycode;
702 /* do we have a composed char to return? */
703 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
704 action = state->ks_composed_char;
705 state->ks_composed_char = 0;
706 if (action > UCHAR_MAX) {
707 KBDMUX_UNLOCK(state);
712 KBDMUX_UNLOCK(state);
717 /* see if there is something in the keyboard queue */
718 scancode = kbdmux_kbd_getc(state);
719 if (scancode == -1) {
720 if (state->ks_polling != 0) {
723 SLIST_FOREACH(k, &state->ks_kbds, next) {
724 while (kbdd_check_char(k->kbd)) {
725 scancode = kbdd_read_char(k->kbd, 0);
726 if (scancode == NOKEY)
728 if (scancode == ERRKEY)
730 if (!KBD_IS_BUSY(k->kbd))
733 kbdmux_kbd_putc(state, scancode);
737 if (state->ks_inq_length > 0)
741 KBDMUX_UNLOCK(state);
744 /* XXX FIXME: check for -1 if wait == 1! */
749 /* push evdev event */
750 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) {
751 uint16_t key = evdev_scancode2key(&state->ks_evdev_state,
754 if (key != KEY_RESERVED) {
755 evdev_push_event(state->ks_evdev, EV_KEY,
756 key, scancode & 0x80 ? 0 : 1);
757 evdev_sync(state->ks_evdev);
762 /* return the byte as is for the K_RAW mode */
763 if (state->ks_mode == K_RAW) {
764 KBDMUX_UNLOCK(state);
768 /* translate the scan code into a keycode */
769 keycode = scancode & 0x7F;
770 switch (state->ks_prefix) {
771 case 0x00: /* normal scancode */
773 case 0xB8: /* left alt (compose key) released */
774 if (state->ks_flags & COMPOSE) {
775 state->ks_flags &= ~COMPOSE;
776 if (state->ks_composed_char > UCHAR_MAX)
777 state->ks_composed_char = 0;
780 case 0x38: /* left alt (compose key) pressed */
781 if (!(state->ks_flags & COMPOSE)) {
782 state->ks_flags |= COMPOSE;
783 state->ks_composed_char = 0;
788 state->ks_prefix = scancode;
792 case 0xE0: /* 0xE0 prefix */
793 state->ks_prefix = 0;
795 case 0x1C: /* right enter key */
798 case 0x1D: /* right ctrl key */
801 case 0x35: /* keypad divide key */
804 case 0x37: /* print scrn key */
807 case 0x38: /* right alt key (alt gr) */
810 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
813 case 0x47: /* grey home key */
816 case 0x48: /* grey up arrow key */
819 case 0x49: /* grey page up key */
822 case 0x4B: /* grey left arrow key */
825 case 0x4D: /* grey right arrow key */
828 case 0x4F: /* grey end key */
831 case 0x50: /* grey down arrow key */
834 case 0x51: /* grey page down key */
837 case 0x52: /* grey insert key */
840 case 0x53: /* grey delete key */
843 /* the following 3 are only used on the MS "Natural" keyboard */
844 case 0x5b: /* left Window key */
847 case 0x5c: /* right Window key */
850 case 0x5d: /* menu key */
853 case 0x5e: /* power key */
856 case 0x5f: /* sleep key */
859 case 0x63: /* wake key */
862 case 0x64: /* [JP106USB] backslash, underscore */
865 default: /* ignore everything else */
869 case 0xE1: /* 0xE1 prefix */
871 * The pause/break key on the 101 keyboard produces:
873 * Ctrl-pause/break produces:
874 * E0-46 E0-C6 (See above.)
876 state->ks_prefix = 0;
878 state->ks_prefix = 0x1D;
881 case 0x1D: /* pause / break */
882 state->ks_prefix = 0;
889 /* XXX assume 101/102 keys AT keyboard */
891 case 0x5c: /* print screen */
892 if (state->ks_flags & ALTS)
893 keycode = 0x54; /* sysrq */
895 case 0x68: /* pause/break */
896 if (state->ks_flags & CTLS)
897 keycode = 0x6c; /* break */
901 /* return the key code in the K_CODE mode */
902 if (state->ks_mode == K_CODE) {
903 KBDMUX_UNLOCK(state);
904 return (keycode | (scancode & 0x80));
907 /* compose a character code */
908 if (state->ks_flags & COMPOSE) {
909 switch (keycode | (scancode & 0x80)) {
910 /* key pressed, process it */
911 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
912 state->ks_composed_char *= 10;
913 state->ks_composed_char += keycode - 0x40;
914 if (state->ks_composed_char > UCHAR_MAX) {
915 KBDMUX_UNLOCK(state);
919 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
920 state->ks_composed_char *= 10;
921 state->ks_composed_char += keycode - 0x47;
922 if (state->ks_composed_char > UCHAR_MAX) {
923 KBDMUX_UNLOCK(state);
927 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
928 state->ks_composed_char *= 10;
929 state->ks_composed_char += keycode - 0x4E;
930 if (state->ks_composed_char > UCHAR_MAX) {
931 KBDMUX_UNLOCK(state);
935 case 0x52: /* keypad 0 */
936 state->ks_composed_char *= 10;
937 if (state->ks_composed_char > UCHAR_MAX) {
938 KBDMUX_UNLOCK(state);
943 /* key released, no interest here */
944 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
945 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
946 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
947 case 0xD2: /* keypad 0 */
950 case 0x38: /* left alt key */
954 if (state->ks_composed_char > 0) {
955 state->ks_flags &= ~COMPOSE;
956 state->ks_composed_char = 0;
957 KBDMUX_UNLOCK(state);
964 /* keycode to key action */
965 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
966 &state->ks_state, &state->ks_accents);
970 KBDMUX_UNLOCK(state);
976 * Check if char is waiting
979 kbdmux_check_char(keyboard_t *kbd)
981 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
984 if (!KBD_IS_ACTIVE(kbd))
989 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
992 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
994 KBDMUX_UNLOCK(state);
1003 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
1005 static int delays[] = {
1009 static int rates[] = {
1010 34, 38, 42, 46, 50, 55, 59, 63,
1011 68, 76, 84, 92, 100, 110, 118, 126,
1012 136, 152, 168, 184, 200, 220, 236, 252,
1013 272, 304, 336, 368, 400, 440, 472, 504
1016 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1018 keyboard_info_t *ki;
1019 int error = 0, mode;
1020 #ifdef COMPAT_FREEBSD6
1028 case KBADDKBD: /* add keyboard to the mux */
1029 ki = (keyboard_info_t *) arg;
1031 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1032 strcmp(ki->kb_name, "*") == 0)
1033 return (EINVAL); /* bad input */
1037 SLIST_FOREACH(k, &state->ks_kbds, next)
1038 if (k->kbd->kb_unit == ki->kb_unit &&
1039 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1043 KBDMUX_UNLOCK(state);
1045 return (0); /* keyboard already in the mux */
1048 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
1050 KBDMUX_UNLOCK(state);
1052 return (ENOMEM); /* out of memory */
1055 k->kbd = kbd_get_keyboard(
1060 kbdmux_kbd_event, (void *) state));
1061 if (k->kbd == NULL) {
1062 KBDMUX_UNLOCK(state);
1065 return (EINVAL); /* bad keyboard */
1068 kbdd_enable(k->kbd);
1069 kbdd_clear_state(k->kbd);
1071 /* set K_RAW mode on slave keyboard */
1073 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1075 /* set lock keys state on slave keyboard */
1076 mode = state->ks_state & LOCK_MASK;
1077 error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1081 KBDMUX_UNLOCK(state);
1083 kbd_release(k->kbd, &k->kbd);
1088 return (error); /* could not set mode */
1091 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1093 KBDMUX_UNLOCK(state);
1096 case KBRELKBD: /* release keyboard from the mux */
1097 ki = (keyboard_info_t *) arg;
1099 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1100 strcmp(ki->kb_name, "*") == 0)
1101 return (EINVAL); /* bad input */
1105 SLIST_FOREACH(k, &state->ks_kbds, next)
1106 if (k->kbd->kb_unit == ki->kb_unit &&
1107 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1111 error = kbd_release(k->kbd, &k->kbd);
1113 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1120 error = ENXIO; /* keyboard is not in the mux */
1122 KBDMUX_UNLOCK(state);
1125 case KDGKBMODE: /* get kyboard mode */
1127 *(int *)arg = state->ks_mode;
1128 KBDMUX_UNLOCK(state);
1131 #ifdef COMPAT_FREEBSD6
1133 ival = IOCPARM_IVAL(arg);
1134 arg = (caddr_t)&ival;
1137 case KDSKBMODE: /* set keyboard mode */
1140 switch (*(int *)arg) {
1142 if (state->ks_mode != K_XLATE) {
1143 /* make lock key state and LED state match */
1144 state->ks_state &= ~LOCK_MASK;
1145 state->ks_state |= KBD_LED_VAL(kbd);
1151 if (state->ks_mode != *(int *)arg) {
1152 kbdmux_clear_state_locked(state);
1153 state->ks_mode = *(int *)arg;
1162 KBDMUX_UNLOCK(state);
1165 case KDGETLED: /* get keyboard LED */
1167 *(int *)arg = KBD_LED_VAL(kbd);
1168 KBDMUX_UNLOCK(state);
1171 #ifdef COMPAT_FREEBSD6
1173 ival = IOCPARM_IVAL(arg);
1174 arg = (caddr_t)&ival;
1177 case KDSETLED: /* set keyboard LED */
1180 /* NOTE: lock key state in ks_state won't be changed */
1181 if (*(int *)arg & ~LOCK_MASK) {
1182 KBDMUX_UNLOCK(state);
1187 KBD_LED_VAL(kbd) = *(int *)arg;
1188 #ifdef EVDEV_SUPPORT
1189 if (state->ks_evdev != NULL &&
1190 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1191 evdev_push_leds(state->ks_evdev, *(int *)arg);
1193 /* KDSETLED on all slave keyboards */
1194 SLIST_FOREACH(k, &state->ks_kbds, next)
1195 (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
1197 KBDMUX_UNLOCK(state);
1200 case KDGKBSTATE: /* get lock key state */
1202 *(int *)arg = state->ks_state & LOCK_MASK;
1203 KBDMUX_UNLOCK(state);
1206 #ifdef COMPAT_FREEBSD6
1208 ival = IOCPARM_IVAL(arg);
1209 arg = (caddr_t)&ival;
1212 case KDSKBSTATE: /* set lock key state */
1215 if (*(int *)arg & ~LOCK_MASK) {
1216 KBDMUX_UNLOCK(state);
1221 state->ks_state &= ~LOCK_MASK;
1222 state->ks_state |= *(int *)arg;
1224 /* KDSKBSTATE on all slave keyboards */
1225 SLIST_FOREACH(k, &state->ks_kbds, next)
1226 (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
1228 KBDMUX_UNLOCK(state);
1230 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1233 #ifdef COMPAT_FREEBSD6
1236 ival = IOCPARM_IVAL(arg);
1237 arg = (caddr_t)&ival;
1240 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1241 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1244 if (cmd == KDSETREPEAT) {
1248 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1249 if (((int *)arg)[0] >= delays[i])
1254 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1255 if (((int *)arg)[1] >= rates[i])
1262 KBDMUX_UNLOCK(state);
1267 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1268 kbd->kb_delay2 = rates[mode & 0x1f];
1269 #ifdef EVDEV_SUPPORT
1270 if (state->ks_evdev != NULL &&
1271 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1272 evdev_push_repeats(state->ks_evdev, kbd);
1274 /* perform command on all slave keyboards */
1275 SLIST_FOREACH(k, &state->ks_kbds, next)
1276 (void)kbdd_ioctl(k->kbd, cmd, arg);
1278 KBDMUX_UNLOCK(state);
1281 case PIO_KEYMAP: /* set keyboard translation table */
1282 case OPIO_KEYMAP: /* set keyboard translation table (compat) */
1283 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1284 case PIO_DEADKEYMAP: /* set accent key translation table */
1286 state->ks_accents = 0;
1288 /* perform command on all slave keyboards */
1289 SLIST_FOREACH(k, &state->ks_kbds, next)
1290 (void)kbdd_ioctl(k->kbd, cmd, arg);
1292 KBDMUX_UNLOCK(state);
1296 error = genkbd_commonioctl(kbd, cmd, arg);
1304 * Lock the access to the keyboard
1307 kbdmux_lock(keyboard_t *kbd, int lock)
1309 return (1); /* XXX */
1313 * Clear the internal state of the keyboard
1316 kbdmux_clear_state_locked(kbdmux_state_t *state)
1318 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1320 state->ks_flags &= ~COMPOSE;
1321 state->ks_polling = 0;
1322 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1323 state->ks_accents = 0;
1324 state->ks_composed_char = 0;
1325 /* state->ks_prefix = 0; XXX */
1326 state->ks_inq_length = 0;
1330 kbdmux_clear_state(keyboard_t *kbd)
1332 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1335 kbdmux_clear_state_locked(state);
1336 KBDMUX_UNLOCK(state);
1340 * Save the internal state
1343 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1346 return (sizeof(kbdmux_state_t));
1347 if (len < sizeof(kbdmux_state_t))
1350 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1356 * Set the internal state
1359 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1361 if (len < sizeof(kbdmux_state_t))
1364 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1373 kbdmux_poll(keyboard_t *kbd, int on)
1375 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1381 state->ks_polling++;
1383 state->ks_polling--;
1385 /* set poll on slave keyboards */
1386 SLIST_FOREACH(k, &state->ks_kbds, next)
1387 kbdd_poll(k->kbd, on);
1389 KBDMUX_UNLOCK(state);
1394 /*****************************************************************************
1395 *****************************************************************************
1397 *****************************************************************************
1398 *****************************************************************************/
1400 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1403 kbdmux_modevent(module_t mod, int type, void *data)
1405 keyboard_switch_t *sw;
1411 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1414 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1415 kbd_delete_driver(&kbdmux_kbd_driver);
1422 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1423 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1424 kbd_delete_driver(&kbdmux_kbd_driver);
1428 #ifdef KBD_INSTALL_CDEV
1429 if ((error = kbd_attach(kbd)) != 0) {
1431 kbd_delete_driver(&kbdmux_kbd_driver);
1436 if ((error = (*sw->enable)(kbd)) != 0) {
1437 (*sw->disable)(kbd);
1438 #ifdef KBD_INSTALL_CDEV
1442 kbd_delete_driver(&kbdmux_kbd_driver);
1448 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1449 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1451 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1453 (*sw->disable)(kbd);
1454 #ifdef KBD_INSTALL_CDEV
1458 kbd_delete_driver(&kbdmux_kbd_driver);
1471 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1472 #ifdef EVDEV_SUPPORT
1473 MODULE_DEPEND(kbdmux, evdev, 1, 1, 1);