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"
37 #include <sys/param.h>
40 #include <sys/consio.h>
41 #include <sys/fcntl.h>
43 #include <sys/kernel.h>
44 #include <sys/limits.h>
46 #include <sys/malloc.h>
47 #include <sys/module.h>
48 #include <sys/mutex.h>
51 #include <sys/queue.h>
52 #include <sys/selinfo.h>
53 #include <sys/systm.h>
54 #include <sys/taskqueue.h>
57 #include <dev/kbd/kbdreg.h>
58 #include <dev/kbd/kbdtables.h>
60 #define KEYBOARD_NAME "kbdmux"
62 MALLOC_DECLARE(M_KBDMUX);
63 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
65 /*****************************************************************************
66 *****************************************************************************
68 *****************************************************************************
69 *****************************************************************************/
71 #define KBDMUX_Q_SIZE 512 /* input queue size */
75 * For now rely on Giant mutex to protect our data structures.
76 * Just like the rest of keyboard drivers and syscons(4) do.
77 * Note that callout is initialized as not MP-safe to make sure
82 #define KBDMUX_LOCK_DECL_GLOBAL \
84 #define KBDMUX_LOCK_INIT(s) \
85 mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
86 #define KBDMUX_LOCK_DESTROY(s) \
87 mtx_destroy(&(s)->ks_lock)
88 #define KBDMUX_LOCK(s) \
89 mtx_lock(&(s)->ks_lock)
90 #define KBDMUX_UNLOCK(s) \
91 mtx_unlock(&(s)->ks_lock)
92 #define KBDMUX_LOCK_ASSERT(s, w) \
93 mtx_assert(&(s)->ks_lock, (w))
94 #define KBDMUX_SLEEP(s, f, d, t) \
95 msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
96 #define KBDMUX_CALLOUT_INIT(s) \
97 callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
98 #define KBDMUX_QUEUE_INTR(s) \
99 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
101 #define KBDMUX_LOCK_DECL_GLOBAL
103 #define KBDMUX_LOCK_INIT(s)
105 #define KBDMUX_LOCK_DESTROY(s)
107 #define KBDMUX_LOCK(s)
109 #define KBDMUX_UNLOCK(s)
111 #define KBDMUX_LOCK_ASSERT(s, w)
113 #define KBDMUX_SLEEP(s, f, d, t) \
114 tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t))
115 #define KBDMUX_CALLOUT_INIT(s) \
116 callout_init(&(s)->ks_timo, 0)
117 #define KBDMUX_QUEUE_INTR(s) \
118 taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
121 #define KBDMUX_INTR(kbd, arg) \
122 (*kbdsw[(kbd)->kb_index]->intr)((kbd), (arg))
124 #define KBDMUX_IOCTL(kbd, cmd, arg) \
125 (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (caddr_t) (arg))
127 #define KBDMUX_CHECK_CHAR(kbd) \
128 (*kbdsw[(kbd)->kb_index]->check_char)((kbd))
130 #define KBDMUX_READ_CHAR(kbd, wait) \
131 (*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait))
133 #define KBDMUX_ENABLE(kbd) \
134 (*kbdsw[(kbd)->kb_index]->enable)((kbd))
136 #define KBDMUX_POLL(kbd, on) \
137 (*kbdsw[(kbd)->kb_index]->poll)((kbd), (on))
139 #define KBDMUX_CLEAR_STATE(kbd) \
140 (*kbdsw[(kbd)->kb_index]->clear_state)((kbd))
147 keyboard_t *kbd; /* keyboard */
148 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
151 typedef struct kbdmux_kbd kbdmux_kbd_t;
158 struct clist ks_inq; /* input chars queue */
159 struct task ks_task; /* interrupt task */
160 struct callout ks_timo; /* timeout handler */
161 #define TICKS (hz) /* rate */
163 int ks_flags; /* flags */
164 #define COMPOSE (1 << 0) /* compose char flag */
165 #define POLLING (1 << 1) /* polling */
166 #define TASK (1 << 2) /* interrupt task queued */
168 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
169 int ks_state; /* state */
170 int ks_accents; /* accent key index (> 0) */
171 u_int ks_composed_char; /* composed char code */
172 u_char ks_prefix; /* AT scan code prefix */
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 * Interrupt handler task
195 kbdmux_kbd_intr(void *xkbd, int pending)
197 keyboard_t *kbd = (keyboard_t *) xkbd;
198 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
200 KBDMUX_INTR(kbd, NULL);
204 state->ks_flags &= ~TASK;
205 wakeup(&state->ks_task);
207 KBDMUX_UNLOCK(state);
211 * Schedule interrupt handler on timeout. Called with locked state.
214 kbdmux_kbd_intr_timo(void *xstate)
216 kbdmux_state_t *state = (kbdmux_state_t *) xstate;
218 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
220 if (callout_pending(&state->ks_timo))
221 return; /* callout was reset */
223 if (!callout_active(&state->ks_timo))
224 return; /* callout was stopped */
226 callout_deactivate(&state->ks_timo);
228 /* queue interrupt task if needed */
229 if (state->ks_inq.c_cc > 0 && !(state->ks_flags & TASK) &&
230 KBDMUX_QUEUE_INTR(state) == 0)
231 state->ks_flags |= TASK;
233 /* re-schedule timeout */
234 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
238 * Process event from one of our keyboards
241 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
243 kbdmux_state_t *state = (kbdmux_state_t *) arg;
246 case KBDIO_KEYINPUT: {
252 * Read all chars from the keyboard
254 * Turns out that atkbd(4) check_char() method may return
255 * "true" while read_char() method returns NOKEY. If this
256 * happens we could stuck in the loop below. Avoid this
257 * by breaking out of the loop if read_char() method returns
261 while (KBDMUX_CHECK_CHAR(kbd)) {
262 c = KBDMUX_READ_CHAR(kbd, 0);
266 continue; /* XXX ring bell */
267 if (!KBD_IS_BUSY(kbd))
268 continue; /* not open - discard the input */
270 putc(c, &state->ks_inq);
273 /* queue interrupt task if needed */
274 if (state->ks_inq.c_cc > 0 && !(state->ks_flags & TASK) &&
275 KBDMUX_QUEUE_INTR(state) == 0)
276 state->ks_flags |= TASK;
278 KBDMUX_UNLOCK(state);
281 case KBDIO_UNLOADING: {
286 SLIST_FOREACH(k, &state->ks_kbds, next)
291 kbd_release(k->kbd, &k->kbd);
292 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
299 KBDMUX_UNLOCK(state);
310 /****************************************************************************
311 ****************************************************************************
313 ****************************************************************************
314 ****************************************************************************/
316 static int kbdmux_configure(int flags);
317 static kbd_probe_t kbdmux_probe;
318 static kbd_init_t kbdmux_init;
319 static kbd_term_t kbdmux_term;
320 static kbd_intr_t kbdmux_intr;
321 static kbd_test_if_t kbdmux_test_if;
322 static kbd_enable_t kbdmux_enable;
323 static kbd_disable_t kbdmux_disable;
324 static kbd_read_t kbdmux_read;
325 static kbd_check_t kbdmux_check;
326 static kbd_read_char_t kbdmux_read_char;
327 static kbd_check_char_t kbdmux_check_char;
328 static kbd_ioctl_t kbdmux_ioctl;
329 static kbd_lock_t kbdmux_lock;
330 static void kbdmux_clear_state_locked(kbdmux_state_t *state);
331 static kbd_clear_state_t kbdmux_clear_state;
332 static kbd_get_state_t kbdmux_get_state;
333 static kbd_set_state_t kbdmux_set_state;
334 static kbd_poll_mode_t kbdmux_poll;
336 static keyboard_switch_t kbdmuxsw = {
337 .probe = kbdmux_probe,
341 .test_if = kbdmux_test_if,
342 .enable = kbdmux_enable,
343 .disable = kbdmux_disable,
345 .check = kbdmux_check,
346 .read_char = kbdmux_read_char,
347 .check_char = kbdmux_check_char,
348 .ioctl = kbdmux_ioctl,
350 .clear_state = kbdmux_clear_state,
351 .get_state = kbdmux_get_state,
352 .set_state = kbdmux_set_state,
353 .get_fkeystr = genkbd_get_fkeystr,
359 * Return the number of found keyboards
362 kbdmux_configure(int flags)
371 kbdmux_probe(int unit, void *arg, int flags)
373 if (resource_disabled(KEYBOARD_NAME, unit))
380 * Reset and initialize the keyboard (stolen from atkbd.c)
383 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
385 keyboard_t *kbd = NULL;
386 kbdmux_state_t *state = NULL;
387 keymap_t *keymap = NULL;
388 accentmap_t *accmap = NULL;
389 fkeytab_t *fkeymap = NULL;
390 int error, needfree, fkeymap_size, delay[2];
393 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
394 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
395 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
396 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
397 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
398 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
401 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
402 (accmap == NULL) || (fkeymap == NULL)) {
407 KBDMUX_LOCK_INIT(state);
408 clist_alloc_cblocks(&state->ks_inq,
409 KBDMUX_Q_SIZE, KBDMUX_Q_SIZE / 2);
410 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
411 KBDMUX_CALLOUT_INIT(state);
412 SLIST_INIT(&state->ks_kbds);
413 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
417 state = (kbdmux_state_t *) kbd->kb_data;
418 keymap = kbd->kb_keymap;
419 accmap = kbd->kb_accentmap;
420 fkeymap = kbd->kb_fkeytab;
421 fkeymap_size = kbd->kb_fkeytab_size;
425 if (!KBD_IS_PROBED(kbd)) {
426 /* XXX assume 101/102 keys keyboard */
427 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
428 bcopy(&key_map, keymap, sizeof(key_map));
429 bcopy(&accent_map, accmap, sizeof(accent_map));
430 bcopy(fkey_tab, fkeymap,
431 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
432 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
433 kbd->kb_data = (void *)state;
435 KBD_FOUND_DEVICE(kbd);
439 kbdmux_clear_state_locked(state);
440 state->ks_mode = K_XLATE;
441 KBDMUX_UNLOCK(state);
444 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
445 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
447 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
449 delay[0] = kbd->kb_delay1;
450 delay[1] = kbd->kb_delay2;
451 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
456 if (!KBD_IS_CONFIGURED(kbd)) {
457 if (kbd_register(kbd) < 0) {
462 KBD_CONFIG_DONE(kbd);
465 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
466 KBDMUX_UNLOCK(state);
473 clist_free_cblocks(&state->ks_inq);
474 free(state, M_KBDMUX);
477 free(keymap, M_KBDMUX);
479 free(accmap, M_KBDMUX);
481 free(fkeymap, M_KBDMUX);
484 *kbdp = NULL; /* insure ref doesn't leak to caller */
492 * Finish using this keyboard
495 kbdmux_term(keyboard_t *kbd)
497 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
503 callout_stop(&state->ks_timo);
505 /* wait for interrupt task */
506 while (state->ks_flags & TASK)
507 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
509 /* release all keyboards from the mux */
510 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
511 kbd_release(k->kbd, &k->kbd);
512 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
519 /* flush input queue */
520 ndflush(&state->ks_inq, state->ks_inq.c_cc);
521 clist_free_cblocks(&state->ks_inq);
523 KBDMUX_UNLOCK(state);
527 KBDMUX_LOCK_DESTROY(state);
528 bzero(state, sizeof(*state));
529 free(state, M_KBDMUX);
531 free(kbd->kb_keymap, M_KBDMUX);
532 free(kbd->kb_accentmap, M_KBDMUX);
533 free(kbd->kb_fkeytab, M_KBDMUX);
540 * Keyboard interrupt routine
543 kbdmux_intr(keyboard_t *kbd, void *arg)
547 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
548 /* let the callback function to process the input */
549 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
550 kbd->kb_callback.kc_arg);
552 /* read and discard the input; no one is waiting for input */
554 c = kbdmux_read_char(kbd, FALSE);
555 } while (c != NOKEY);
562 * Test the interface to the device
565 kbdmux_test_if(keyboard_t *kbd)
571 * Enable the access to the device; until this function is called,
572 * the client cannot read from the keyboard.
575 kbdmux_enable(keyboard_t *kbd)
582 * Disallow the access to the device
585 kbdmux_disable(keyboard_t *kbd)
592 * Read one byte from the keyboard if it's allowed
595 kbdmux_read(keyboard_t *kbd, int wait)
597 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
601 c = getc(&state->ks_inq);
602 KBDMUX_UNLOCK(state);
607 return (KBD_IS_ACTIVE(kbd)? c : -1);
611 * Check if data is waiting
614 kbdmux_check(keyboard_t *kbd)
616 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
619 if (!KBD_IS_ACTIVE(kbd))
623 ready = (state->ks_inq.c_cc > 0)? TRUE : FALSE;
624 KBDMUX_UNLOCK(state);
630 * Read char from the keyboard (stolen from atkbd.c)
633 kbdmux_read_char(keyboard_t *kbd, int wait)
635 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
637 int scancode, keycode;
643 /* do we have a composed char to return? */
644 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
645 action = state->ks_composed_char;
646 state->ks_composed_char = 0;
647 if (action > UCHAR_MAX) {
648 KBDMUX_UNLOCK(state);
653 KBDMUX_UNLOCK(state);
658 /* see if there is something in the keyboard queue */
659 scancode = getc(&state->ks_inq);
660 if (scancode == -1) {
661 if (state->ks_flags & POLLING) {
664 SLIST_FOREACH(k, &state->ks_kbds, next) {
665 while (KBDMUX_CHECK_CHAR(k->kbd)) {
666 scancode = KBDMUX_READ_CHAR(k->kbd, 0);
667 if (scancode == NOKEY)
669 if (scancode == ERRKEY)
671 if (!KBD_IS_BUSY(k->kbd))
674 putc(scancode, &state->ks_inq);
678 if (state->ks_inq.c_cc > 0)
682 KBDMUX_UNLOCK(state);
685 /* XXX FIXME: check for -1 if wait == 1! */
689 /* return the byte as is for the K_RAW mode */
690 if (state->ks_mode == K_RAW) {
691 KBDMUX_UNLOCK(state);
695 /* translate the scan code into a keycode */
696 keycode = scancode & 0x7F;
697 switch (state->ks_prefix) {
698 case 0x00: /* normal scancode */
700 case 0xB8: /* left alt (compose key) released */
701 if (state->ks_flags & COMPOSE) {
702 state->ks_flags &= ~COMPOSE;
703 if (state->ks_composed_char > UCHAR_MAX)
704 state->ks_composed_char = 0;
707 case 0x38: /* left alt (compose key) pressed */
708 if (!(state->ks_flags & COMPOSE)) {
709 state->ks_flags |= COMPOSE;
710 state->ks_composed_char = 0;
715 state->ks_prefix = scancode;
719 case 0xE0: /* 0xE0 prefix */
720 state->ks_prefix = 0;
722 case 0x1C: /* right enter key */
725 case 0x1D: /* right ctrl key */
728 case 0x35: /* keypad divide key */
731 case 0x37: /* print scrn key */
734 case 0x38: /* right alt key (alt gr) */
737 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
740 case 0x47: /* grey home key */
743 case 0x48: /* grey up arrow key */
746 case 0x49: /* grey page up key */
749 case 0x4B: /* grey left arrow key */
752 case 0x4D: /* grey right arrow key */
755 case 0x4F: /* grey end key */
758 case 0x50: /* grey down arrow key */
761 case 0x51: /* grey page down key */
764 case 0x52: /* grey insert key */
767 case 0x53: /* grey delete key */
770 /* the following 3 are only used on the MS "Natural" keyboard */
771 case 0x5b: /* left Window key */
774 case 0x5c: /* right Window key */
777 case 0x5d: /* menu key */
780 case 0x5e: /* power key */
783 case 0x5f: /* sleep key */
786 case 0x63: /* wake key */
789 case 0x64: /* [JP106USB] backslash, underscore */
792 default: /* ignore everything else */
796 case 0xE1: /* 0xE1 prefix */
798 * The pause/break key on the 101 keyboard produces:
800 * Ctrl-pause/break produces:
801 * E0-46 E0-C6 (See above.)
803 state->ks_prefix = 0;
805 state->ks_prefix = 0x1D;
808 case 0x1D: /* pause / break */
809 state->ks_prefix = 0;
816 /* XXX assume 101/102 keys AT keyboard */
818 case 0x5c: /* print screen */
819 if (state->ks_flags & ALTS)
820 keycode = 0x54; /* sysrq */
822 case 0x68: /* pause/break */
823 if (state->ks_flags & CTLS)
824 keycode = 0x6c; /* break */
828 /* return the key code in the K_CODE mode */
829 if (state->ks_mode == K_CODE) {
830 KBDMUX_UNLOCK(state);
831 return (keycode | (scancode & 0x80));
834 /* compose a character code */
835 if (state->ks_flags & COMPOSE) {
836 switch (keycode | (scancode & 0x80)) {
837 /* key pressed, process it */
838 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
839 state->ks_composed_char *= 10;
840 state->ks_composed_char += keycode - 0x40;
841 if (state->ks_composed_char > UCHAR_MAX) {
842 KBDMUX_UNLOCK(state);
846 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
847 state->ks_composed_char *= 10;
848 state->ks_composed_char += keycode - 0x47;
849 if (state->ks_composed_char > UCHAR_MAX) {
850 KBDMUX_UNLOCK(state);
854 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
855 state->ks_composed_char *= 10;
856 state->ks_composed_char += keycode - 0x4E;
857 if (state->ks_composed_char > UCHAR_MAX) {
858 KBDMUX_UNLOCK(state);
862 case 0x52: /* keypad 0 */
863 state->ks_composed_char *= 10;
864 if (state->ks_composed_char > UCHAR_MAX) {
865 KBDMUX_UNLOCK(state);
870 /* key released, no interest here */
871 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
872 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
873 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
874 case 0xD2: /* keypad 0 */
877 case 0x38: /* left alt key */
881 if (state->ks_composed_char > 0) {
882 state->ks_flags &= ~COMPOSE;
883 state->ks_composed_char = 0;
884 KBDMUX_UNLOCK(state);
891 /* keycode to key action */
892 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
893 &state->ks_state, &state->ks_accents);
897 KBDMUX_UNLOCK(state);
903 * Check if char is waiting
906 kbdmux_check_char(keyboard_t *kbd)
908 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
911 if (!KBD_IS_ACTIVE(kbd))
916 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
919 ready = (state->ks_inq.c_cc > 0)? TRUE : FALSE;
921 KBDMUX_UNLOCK(state);
930 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
932 static int delays[] = {
936 static int rates[] = {
937 34, 38, 42, 46, 50, 55, 59, 63,
938 68, 76, 84, 92, 100, 110, 118, 126,
939 136, 152, 168, 184, 200, 220, 236, 252,
940 272, 304, 336, 368, 400, 440, 472, 504
943 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
947 #ifdef COMPAT_FREEBSD6
955 case KBADDKBD: /* add keyboard to the mux */
956 ki = (keyboard_info_t *) arg;
958 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
959 strcmp(ki->kb_name, "*") == 0)
960 return (EINVAL); /* bad input */
964 SLIST_FOREACH(k, &state->ks_kbds, next)
965 if (k->kbd->kb_unit == ki->kb_unit &&
966 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
970 KBDMUX_UNLOCK(state);
972 return (0); /* keyboard already in the mux */
975 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
977 KBDMUX_UNLOCK(state);
979 return (ENOMEM); /* out of memory */
982 k->kbd = kbd_get_keyboard(
987 kbdmux_kbd_event, (void *) state));
988 if (k->kbd == NULL) {
989 KBDMUX_UNLOCK(state);
992 return (EINVAL); /* bad keyboard */
995 KBDMUX_ENABLE(k->kbd);
996 KBDMUX_CLEAR_STATE(k->kbd);
998 /* set K_RAW mode on slave keyboard */
1000 error = KBDMUX_IOCTL(k->kbd, KDSKBMODE, &mode);
1002 /* set lock keys state on slave keyboard */
1003 mode = state->ks_state & LOCK_MASK;
1004 error = KBDMUX_IOCTL(k->kbd, KDSKBSTATE, &mode);
1008 KBDMUX_UNLOCK(state);
1010 kbd_release(k->kbd, &k->kbd);
1015 return (error); /* could not set mode */
1018 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1020 KBDMUX_UNLOCK(state);
1023 case KBRELKBD: /* release keyboard from the mux */
1024 ki = (keyboard_info_t *) arg;
1026 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1027 strcmp(ki->kb_name, "*") == 0)
1028 return (EINVAL); /* bad input */
1032 SLIST_FOREACH(k, &state->ks_kbds, next)
1033 if (k->kbd->kb_unit == ki->kb_unit &&
1034 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1038 error = kbd_release(k->kbd, &k->kbd);
1040 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1047 error = ENXIO; /* keyboard is not in the mux */
1049 KBDMUX_UNLOCK(state);
1052 case KDGKBMODE: /* get kyboard mode */
1054 *(int *)arg = state->ks_mode;
1055 KBDMUX_UNLOCK(state);
1058 #ifdef COMPAT_FREEBSD6
1060 ival = IOCPARM_IVAL(arg);
1061 arg = (caddr_t)&ival;
1064 case KDSKBMODE: /* set keyboard mode */
1067 switch (*(int *)arg) {
1069 if (state->ks_mode != K_XLATE) {
1070 /* make lock key state and LED state match */
1071 state->ks_state &= ~LOCK_MASK;
1072 state->ks_state |= KBD_LED_VAL(kbd);
1078 if (state->ks_mode != *(int *)arg) {
1079 kbdmux_clear_state_locked(state);
1080 state->ks_mode = *(int *)arg;
1089 KBDMUX_UNLOCK(state);
1092 case KDGETLED: /* get keyboard LED */
1094 *(int *)arg = KBD_LED_VAL(kbd);
1095 KBDMUX_UNLOCK(state);
1098 #ifdef COMPAT_FREEBSD6
1100 ival = IOCPARM_IVAL(arg);
1101 arg = (caddr_t)&ival;
1104 case KDSETLED: /* set keyboard LED */
1107 /* NOTE: lock key state in ks_state won't be changed */
1108 if (*(int *)arg & ~LOCK_MASK) {
1109 KBDMUX_UNLOCK(state);
1114 KBD_LED_VAL(kbd) = *(int *)arg;
1116 /* KDSETLED on all slave keyboards */
1117 SLIST_FOREACH(k, &state->ks_kbds, next)
1118 KBDMUX_IOCTL(k->kbd, KDSETLED, arg);
1120 KBDMUX_UNLOCK(state);
1123 case KDGKBSTATE: /* get lock key state */
1125 *(int *)arg = state->ks_state & LOCK_MASK;
1126 KBDMUX_UNLOCK(state);
1129 #ifdef COMPAT_FREEBSD6
1131 ival = IOCPARM_IVAL(arg);
1132 arg = (caddr_t)&ival;
1135 case KDSKBSTATE: /* set lock key state */
1138 if (*(int *)arg & ~LOCK_MASK) {
1139 KBDMUX_UNLOCK(state);
1144 state->ks_state &= ~LOCK_MASK;
1145 state->ks_state |= *(int *)arg;
1147 /* KDSKBSTATE on all slave keyboards */
1148 SLIST_FOREACH(k, &state->ks_kbds, next)
1149 KBDMUX_IOCTL(k->kbd, KDSKBSTATE, arg);
1151 KBDMUX_UNLOCK(state);
1153 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1156 #ifdef COMPAT_FREEBSD6
1159 ival = IOCPARM_IVAL(arg);
1160 arg = (caddr_t)&ival;
1163 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1164 case KDSETRAD: /* set keyboard repeat rate (old interface) */
1167 if (cmd == KDSETREPEAT) {
1171 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1172 if (((int *)arg)[0] >= delays[i])
1177 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1178 if (((int *)arg)[1] >= rates[i])
1185 KBDMUX_UNLOCK(state);
1190 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1191 kbd->kb_delay2 = rates[mode & 0x1f];
1193 /* perform command on all slave keyboards */
1194 SLIST_FOREACH(k, &state->ks_kbds, next)
1195 KBDMUX_IOCTL(k->kbd, cmd, arg);
1197 KBDMUX_UNLOCK(state);
1200 case PIO_KEYMAP: /* set keyboard translation table */
1201 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1202 case PIO_DEADKEYMAP: /* set accent key translation table */
1204 state->ks_accents = 0;
1206 /* perform command on all slave keyboards */
1207 SLIST_FOREACH(k, &state->ks_kbds, next)
1208 KBDMUX_IOCTL(k->kbd, cmd, arg);
1210 KBDMUX_UNLOCK(state);
1214 error = genkbd_commonioctl(kbd, cmd, arg);
1222 * Lock the access to the keyboard
1225 kbdmux_lock(keyboard_t *kbd, int lock)
1227 return (1); /* XXX */
1231 * Clear the internal state of the keyboard
1234 kbdmux_clear_state_locked(kbdmux_state_t *state)
1236 KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1238 state->ks_flags &= ~(COMPOSE|POLLING);
1239 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1240 state->ks_accents = 0;
1241 state->ks_composed_char = 0;
1242 /* state->ks_prefix = 0; XXX */
1244 ndflush(&state->ks_inq, state->ks_inq.c_cc);
1248 kbdmux_clear_state(keyboard_t *kbd)
1250 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1253 kbdmux_clear_state_locked(state);
1254 KBDMUX_UNLOCK(state);
1258 * Save the internal state
1261 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1264 return (sizeof(kbdmux_state_t));
1265 if (len < sizeof(kbdmux_state_t))
1268 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1274 * Set the internal state
1277 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1279 if (len < sizeof(kbdmux_state_t))
1282 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1291 kbdmux_poll(keyboard_t *kbd, int on)
1293 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1299 state->ks_flags |= POLLING;
1301 state->ks_flags &= ~POLLING;
1303 /* set poll on slave keyboards */
1304 SLIST_FOREACH(k, &state->ks_kbds, next)
1305 KBDMUX_POLL(k->kbd, on);
1307 KBDMUX_UNLOCK(state);
1312 /*****************************************************************************
1313 *****************************************************************************
1315 *****************************************************************************
1316 *****************************************************************************/
1318 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1321 kbdmux_modevent(module_t mod, int type, void *data)
1323 keyboard_switch_t *sw;
1329 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1332 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1333 kbd_delete_driver(&kbdmux_kbd_driver);
1340 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1341 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1342 kbd_delete_driver(&kbdmux_kbd_driver);
1346 #ifdef KBD_INSTALL_CDEV
1347 if ((error = kbd_attach(kbd)) != 0) {
1349 kbd_delete_driver(&kbdmux_kbd_driver);
1354 if ((error = (*sw->enable)(kbd)) != 0) {
1355 (*sw->disable)(kbd);
1356 #ifdef KBD_INSTALL_CDEV
1360 kbd_delete_driver(&kbdmux_kbd_driver);
1366 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1367 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1369 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1371 (*sw->disable)(kbd);
1372 #ifdef KBD_INSTALL_CDEV
1376 kbd_delete_driver(&kbdmux_kbd_driver);
1389 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);