kernel: Remove <sys/mutex.h> from all files that don't need it (2/2).
[dragonfly.git] / sys / dev / misc / kbdmux / kbdmux.c
blobe29be84a0371e14cc364b5227bd11a56c80847d7
1 /*-
2 * (MPSAFE)
4 * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
28 * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
29 * $FreeBSD$
32 #include "opt_evdev.h"
33 #include "opt_kbd.h"
35 #include <sys/param.h>
36 #include <sys/bus.h>
37 #include <sys/conf.h>
38 #include <sys/consio.h>
39 #include <sys/fcntl.h>
40 #include <sys/kbio.h>
41 #include <sys/kernel.h>
42 #include <sys/limits.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/module.h>
46 #include <sys/poll.h>
47 #include <sys/proc.h>
48 #include <sys/queue.h>
49 #include <sys/event.h>
50 #include <sys/systm.h>
51 #include <sys/taskqueue.h>
52 #include <sys/uio.h>
53 #include <dev/misc/kbd/kbdreg.h>
54 #include <dev/misc/kbd/kbdtables.h>
56 #ifdef EVDEV_SUPPORT
57 #include <dev/misc/evdev/evdev.h>
58 #include <dev/misc/evdev/input.h>
59 #endif
61 #define KEYBOARD_NAME "kbdmux"
63 MALLOC_DECLARE(M_KBDMUX);
64 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
66 /*****************************************************************************
67 *****************************************************************************
68 ** Keyboard state
69 *****************************************************************************
70 *****************************************************************************/
72 #define KBDMUX_Q_SIZE 512 /* input queue size */
75 * kbdmux keyboard
77 struct kbdmux_kbd
79 keyboard_t *kbd; /* keyboard */
80 SLIST_ENTRY(kbdmux_kbd) next; /* link to next */
83 typedef struct kbdmux_kbd kbdmux_kbd_t;
86 * kbdmux state
88 struct kbdmux_state
90 char ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
91 unsigned int ks_inq_start;
92 unsigned int ks_inq_length;
93 struct task ks_task; /* interrupt task */
95 int ks_flags; /* flags */
96 #define COMPOSE (1 << 0) /* compose char flag */
97 #define POLLING (1 << 1) /* polling */
99 int ks_mode; /* K_XLATE, K_RAW, K_CODE */
100 int ks_state; /* state */
101 int ks_accents; /* accent key index (> 0) */
102 u_int ks_composed_char; /* composed char code */
103 u_char ks_prefix; /* AT scan code prefix */
105 #ifdef EVDEV_SUPPORT
106 struct evdev_dev * ks_evdev;
107 int ks_evdev_state;
108 #endif
110 SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */
113 typedef struct kbdmux_state kbdmux_state_t;
115 /*****************************************************************************
116 *****************************************************************************
117 ** Helper functions
118 *****************************************************************************
119 *****************************************************************************/
121 static task_fn_t kbdmux_kbd_intr;
122 static kbd_callback_func_t kbdmux_kbd_event;
124 static void
125 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
127 unsigned int p;
129 if (state->ks_inq_length == KBDMUX_Q_SIZE)
130 return;
132 p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
133 state->ks_inq[p] = c;
134 state->ks_inq_length++;
137 static int
138 kbdmux_kbd_getc(kbdmux_state_t *state)
140 unsigned char c;
142 if (state->ks_inq_length == 0)
143 return (-1);
145 c = state->ks_inq[state->ks_inq_start];
146 state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
147 state->ks_inq_length--;
149 return (c);
153 * Interrupt handler task
155 static void
156 kbdmux_kbd_intr(void *xkbd, int pending)
158 keyboard_t *kbd = (keyboard_t *) xkbd;
159 KBD_LOCK_DECLARE;
161 KBD_LOCK(kbd); /* recursive so ok */
162 kbd_intr(kbd, NULL);
163 KBD_UNLOCK(kbd);
167 * Process event from one of our keyboards
169 static int
170 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
172 kbdmux_state_t *state = (kbdmux_state_t *) arg;
174 switch (event) {
175 case KBDIO_KEYINPUT: {
176 int c;
179 * Read all chars from the keyboard
181 * Turns out that atkbd(4) check_char() method may return
182 * "true" while read_char() method returns NOKEY. If this
183 * happens we could stuck in the loop below. Avoid this
184 * by breaking out of the loop if read_char() method returns
185 * NOKEY.
188 while (kbd_check_char(kbd)) {
189 c = kbd_read_char(kbd, 0);
190 if (c == NOKEY)
191 break;
192 if (c == ERRKEY)
193 continue; /* XXX ring bell */
194 if (!KBD_IS_BUSY(kbd))
195 continue; /* not open - discard the input */
197 kbdmux_kbd_putc(state, c);
200 /* queue interrupt task if needed */
201 if (state->ks_inq_length > 0)
202 taskqueue_enqueue(taskqueue_swi, &state->ks_task);
204 } break;
206 case KBDIO_UNLOADING: {
207 kbdmux_kbd_t *k;
209 SLIST_FOREACH(k, &state->ks_kbds, next)
210 if (k->kbd == kbd)
211 break;
213 if (k != NULL) {
214 kbd_release(k->kbd, &k->kbd);
215 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
217 k->kbd = NULL;
219 kfree(k, M_KBDMUX);
222 } break;
224 default:
225 return (EINVAL);
226 /* NOT REACHED */
228 return (0);
231 /****************************************************************************
232 ****************************************************************************
233 ** Keyboard driver
234 ****************************************************************************
235 ****************************************************************************/
237 static int kbdmux_configure(int flags);
238 static kbd_probe_t kbdmux_probe;
239 static kbd_init_t kbdmux_init;
240 static kbd_term_t kbdmux_term;
241 static kbd_intr_t kbdmux_intr;
242 static kbd_test_if_t kbdmux_test_if;
243 static kbd_enable_t kbdmux_enable;
244 static kbd_disable_t kbdmux_disable;
245 static kbd_read_t kbdmux_read;
246 static kbd_check_t kbdmux_check;
247 static kbd_read_char_t kbdmux_read_char;
248 static kbd_check_char_t kbdmux_check_char;
249 static kbd_ioctl_t kbdmux_ioctl;
250 static kbd_lock_t kbdmux_lock;
251 static kbd_clear_state_t kbdmux_clear_state;
252 static kbd_get_state_t kbdmux_get_state;
253 static kbd_set_state_t kbdmux_set_state;
254 static kbd_poll_mode_t kbdmux_poll;
256 static keyboard_switch_t kbdmuxsw = {
257 .probe = kbdmux_probe,
258 .init = kbdmux_init,
259 .term = kbdmux_term,
260 .intr = kbdmux_intr,
261 .test_if = kbdmux_test_if,
262 .enable = kbdmux_enable,
263 .disable = kbdmux_disable,
264 .read = kbdmux_read,
265 .check = kbdmux_check,
266 .read_char = kbdmux_read_char,
267 .check_char = kbdmux_check_char,
268 .ioctl = kbdmux_ioctl,
269 .lock = kbdmux_lock,
270 .clear_state = kbdmux_clear_state,
271 .get_state = kbdmux_get_state,
272 .set_state = kbdmux_set_state,
273 .get_fkeystr = genkbd_get_fkeystr,
274 .poll = kbdmux_poll,
275 .diag = genkbd_diag,
278 #ifdef EVDEV_SUPPORT
279 static const struct evdev_methods kbdmux_evdev_methods = {
280 .ev_event = evdev_ev_kbd_event,
282 #endif
285 * Return the number of found keyboards
287 static int
288 kbdmux_configure(int flags)
290 return (1);
294 * Detect a keyboard
296 static int
297 kbdmux_probe(int unit, void *arg, int flags)
299 if (resource_disabled(KEYBOARD_NAME, unit))
300 return (ENXIO);
302 return (0);
306 * Reset and initialize the keyboard (stolen from atkbd.c)
308 * Called without kbd lock held.
310 static int
311 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
313 kbdmux_state_t *state = NULL;
314 keymap_t *keymap = NULL;
315 accentmap_t *accmap = NULL;
316 fkeytab_t *fkeymap = NULL;
317 keyboard_t *kbd = NULL;
318 int error, needfree, fkeymap_size, delay[2];
319 #ifdef EVDEV_SUPPORT
320 struct evdev_dev *evdev;
321 char phys_loc[NAMELEN];
322 #endif
324 if (*kbdp == NULL) {
325 *kbdp = kbd = kmalloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
326 state = kmalloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
327 keymap = kmalloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
328 accmap = kmalloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
329 fkeymap = kmalloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
330 fkeymap_size = NELEM(fkey_tab);
331 needfree = 1;
333 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
334 (accmap == NULL) || (fkeymap == NULL)) {
335 error = ENOMEM;
336 goto bad;
339 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
340 SLIST_INIT(&state->ks_kbds);
341 } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
342 return (0);
343 } else {
344 kbd = *kbdp;
345 state = (kbdmux_state_t *) kbd->kb_data;
346 keymap = kbd->kb_keymap;
347 accmap = kbd->kb_accentmap;
348 fkeymap = kbd->kb_fkeytab;
349 fkeymap_size = kbd->kb_fkeytab_size;
350 needfree = 0;
353 if (!KBD_IS_PROBED(kbd)) {
354 /* XXX assume 101/102 keys keyboard */
355 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags,
356 KB_PRI_MUX, 0, 0);
357 bcopy(&key_map, keymap, sizeof(key_map));
358 bcopy(&accent_map, accmap, sizeof(accent_map));
359 bcopy(fkey_tab, fkeymap,
360 imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
361 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
362 kbd->kb_data = (void *)state;
364 KBD_FOUND_DEVICE(kbd);
365 KBD_PROBE_DONE(kbd);
367 kbdmux_clear_state(kbd);
368 state->ks_mode = K_XLATE;
371 if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
372 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
374 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
376 delay[0] = kbd->kb_delay1;
377 delay[1] = kbd->kb_delay2;
378 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
380 #ifdef EVDEV_SUPPORT
381 /* register as evdev provider */
382 evdev = evdev_alloc();
383 evdev_set_name(evdev, "System keyboard multiplexer");
384 ksnprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit);
385 evdev_set_phys(evdev, phys_loc);
386 evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
387 evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods);
388 evdev_support_event(evdev, EV_SYN);
389 evdev_support_event(evdev, EV_KEY);
390 evdev_support_event(evdev, EV_LED);
391 evdev_support_event(evdev, EV_REP);
392 evdev_support_all_known_keys(evdev);
393 evdev_support_led(evdev, LED_NUML);
394 evdev_support_led(evdev, LED_CAPSL);
395 evdev_support_led(evdev, LED_SCROLLL);
397 if (evdev_register(evdev))
398 evdev_free(evdev);
399 else
400 state->ks_evdev = evdev;
401 state->ks_evdev_state = 0;
402 #endif
404 KBD_INIT_DONE(kbd);
407 if (!KBD_IS_CONFIGURED(kbd)) {
408 if (kbd_register(kbd) < 0) {
409 error = ENXIO;
410 goto bad;
413 KBD_CONFIG_DONE(kbd);
416 return (0);
417 bad:
418 if (needfree) {
419 if (state != NULL)
420 kfree(state, M_KBDMUX);
421 if (keymap != NULL)
422 kfree(keymap, M_KBDMUX);
423 if (accmap != NULL)
424 kfree(accmap, M_KBDMUX);
425 if (fkeymap != NULL)
426 kfree(fkeymap, M_KBDMUX);
427 if (kbd != NULL) {
428 kfree(kbd, M_KBDMUX);
429 *kbdp = NULL; /* insure ref doesn't leak to caller */
433 return (error);
437 * Finish using this keyboard
439 * NOTE: deregistration automatically unlocks lock.
441 static int
442 kbdmux_term(keyboard_t *kbd)
444 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
445 kbdmux_kbd_t *k;
447 /* wait for interrupt task */
448 while (taskqueue_cancel(taskqueue_swi, &state->ks_task, NULL) != 0)
449 taskqueue_drain(taskqueue_swi, &state->ks_task);
451 /* release all keyboards from the mux */
452 while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
453 kbd_release(k->kbd, &k->kbd);
454 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
456 k->kbd = NULL;
458 kfree(k, M_KBDMUX);
461 kbd_unregister(kbd);
463 #ifdef EVDEV_SUPPORT
464 evdev_free(state->ks_evdev);
465 #endif
467 bzero(state, sizeof(*state));
468 kfree(state, M_KBDMUX);
470 kfree(kbd->kb_keymap, M_KBDMUX);
471 kfree(kbd->kb_accentmap, M_KBDMUX);
472 kfree(kbd->kb_fkeytab, M_KBDMUX);
473 kfree(kbd, M_KBDMUX);
475 return (0);
479 * Keyboard interrupt routine
481 static int
482 kbdmux_intr(keyboard_t *kbd, void *arg)
484 int c;
486 if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
487 /* let the callback function to process the input */
488 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
489 kbd->kb_callback.kc_arg);
490 } else {
491 /* read and discard the input; no one is waiting for input */
492 do {
493 c = kbdmux_read_char(kbd, FALSE);
494 } while (c != NOKEY);
497 return (0);
501 * Test the interface to the device
503 static int
504 kbdmux_test_if(keyboard_t *kbd)
506 return (0);
510 * Enable the access to the device; until this function is called,
511 * the client cannot read from the keyboard.
513 static int
514 kbdmux_enable(keyboard_t *kbd)
516 KBD_ACTIVATE(kbd);
517 return (0);
521 * Disallow the access to the device
523 static int
524 kbdmux_disable(keyboard_t *kbd)
526 KBD_DEACTIVATE(kbd);
527 return (0);
531 * Read one byte from the keyboard if it's allowed
533 static int
534 kbdmux_read(keyboard_t *kbd, int wait)
536 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
537 int c, ret;
539 do {
540 c = kbdmux_kbd_getc(state);
541 } while (c == -1 && wait);
543 if (c != -1)
544 kbd->kb_count++;
546 ret = (KBD_IS_ACTIVE(kbd)? c : -1);
548 return ret;
552 * Check if data is waiting
554 static int
555 kbdmux_check(keyboard_t *kbd)
557 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
558 int ready;
560 if (!KBD_IS_ACTIVE(kbd))
561 return (FALSE);
563 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
565 return (ready);
569 * Read char from the keyboard (stolen from atkbd.c)
571 * Note: We do not attempt to detect the case where no keyboards are
572 * present in the wait case. If the kernel is sitting at the
573 * debugger prompt we want someone to be able to plug in a keyboard
574 * and have it work, and not just panic or fall through or do
575 * something equally nasty.
577 static u_int
578 kbdmux_read_char(keyboard_t *kbd, int wait)
580 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
581 u_int action;
582 int scancode, keycode;
584 next_code:
586 /* do we have a composed char to return? */
587 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
588 action = state->ks_composed_char;
589 state->ks_composed_char = 0;
590 if (action > UCHAR_MAX) {
591 return (ERRKEY);
593 return (action);
597 * See if there is something in the keyboard queue
599 scancode = kbdmux_kbd_getc(state);
601 if (scancode == -1) {
602 if (state->ks_flags & POLLING) {
603 kbdmux_kbd_t *k;
605 SLIST_FOREACH(k, &state->ks_kbds, next) {
606 while (kbd_check_char(k->kbd)) {
607 scancode = kbd_read_char(k->kbd, 0);
608 if (scancode == ERRKEY)
609 continue;
610 if (scancode == NOKEY)
611 break;
612 if (!KBD_IS_BUSY(k->kbd))
613 continue;
614 kbdmux_kbd_putc(state, scancode);
618 if (state->ks_inq_length > 0)
619 goto next_code;
620 if (wait)
621 goto next_code;
622 } else {
623 if (wait) {
624 if (kbd->kb_flags & KB_POLLED) {
625 tsleep(&state->ks_task, PCATCH,
626 "kbdwai", hz/10);
627 } else {
628 lksleep(&state->ks_task,
629 &kbd->kb_lock, PCATCH,
630 "kbdwai", hz/10);
632 goto next_code;
635 return (NOKEY);
638 kbd->kb_count++;
640 #ifdef EVDEV_SUPPORT
641 /* push evdev event */
642 if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) {
643 uint16_t key = evdev_scancode2key(&state->ks_evdev_state,
644 scancode);
646 if (key != KEY_RESERVED) {
647 evdev_push_event(state->ks_evdev, EV_KEY,
648 key, scancode & 0x80 ? 0 : 1);
649 evdev_sync(state->ks_evdev);
652 #endif
654 /* return the byte as is for the K_RAW mode */
655 if (state->ks_mode == K_RAW)
656 return (scancode);
658 /* translate the scan code into a keycode */
659 keycode = scancode & 0x7F;
660 switch (state->ks_prefix) {
661 case 0x00: /* normal scancode */
662 switch(scancode) {
663 case 0xB8: /* left alt (compose key) released */
664 if (state->ks_flags & COMPOSE) {
665 state->ks_flags &= ~COMPOSE;
666 if (state->ks_composed_char > UCHAR_MAX)
667 state->ks_composed_char = 0;
669 break;
670 case 0x38: /* left alt (compose key) pressed */
671 if (!(state->ks_flags & COMPOSE)) {
672 state->ks_flags |= COMPOSE;
673 state->ks_composed_char = 0;
675 break;
676 case 0xE0:
677 case 0xE1:
678 state->ks_prefix = scancode;
679 goto next_code;
681 break;
682 case 0xE0: /* 0xE0 prefix */
683 state->ks_prefix = 0;
684 switch (keycode) {
685 case 0x1C: /* right enter key */
686 keycode = 0x59;
687 break;
688 case 0x1D: /* right ctrl key */
689 keycode = 0x5A;
690 break;
691 case 0x35: /* keypad divide key */
692 keycode = 0x5B;
693 break;
694 case 0x37: /* print scrn key */
695 keycode = 0x5C;
696 break;
697 case 0x38: /* right alt key (alt gr) */
698 keycode = 0x5D;
699 break;
700 case 0x46: /* ctrl-pause/break on AT 101 (see below) */
701 keycode = 0x68;
702 break;
703 case 0x47: /* grey home key */
704 keycode = 0x5E;
705 break;
706 case 0x48: /* grey up arrow key */
707 keycode = 0x5F;
708 break;
709 case 0x49: /* grey page up key */
710 keycode = 0x60;
711 break;
712 case 0x4B: /* grey left arrow key */
713 keycode = 0x61;
714 break;
715 case 0x4D: /* grey right arrow key */
716 keycode = 0x62;
717 break;
718 case 0x4F: /* grey end key */
719 keycode = 0x63;
720 break;
721 case 0x50: /* grey down arrow key */
722 keycode = 0x64;
723 break;
724 case 0x51: /* grey page down key */
725 keycode = 0x65;
726 break;
727 case 0x52: /* grey insert key */
728 keycode = 0x66;
729 break;
730 case 0x53: /* grey delete key */
731 keycode = 0x67;
732 break;
733 /* the following 3 are only used on the MS "Natural" keyboard */
734 case 0x5b: /* left Window key */
735 keycode = 0x69;
736 break;
737 case 0x5c: /* right Window key */
738 keycode = 0x6a;
739 break;
740 case 0x5d: /* menu key */
741 keycode = 0x6b;
742 break;
743 case 0x5e: /* power key */
744 keycode = 0x6d;
745 break;
746 case 0x5f: /* sleep key */
747 keycode = 0x6e;
748 break;
749 case 0x63: /* wake key */
750 keycode = 0x6f;
751 break;
752 case 0x64: /* [JP106USB] backslash, underscore */
753 keycode = 0x73;
754 break;
755 default: /* ignore everything else */
756 goto next_code;
758 break;
759 case 0xE1: /* 0xE1 prefix */
761 * The pause/break key on the 101 keyboard produces:
762 * E1-1D-45 E1-9D-C5
763 * Ctrl-pause/break produces:
764 * E0-46 E0-C6 (See above.)
766 state->ks_prefix = 0;
767 if (keycode == 0x1D)
768 state->ks_prefix = 0x1D;
769 goto next_code;
770 /* NOT REACHED */
771 case 0x1D: /* pause / break */
772 state->ks_prefix = 0;
773 if (keycode != 0x45)
774 goto next_code;
775 keycode = 0x68;
776 break;
779 /* XXX assume 101/102 keys AT keyboard */
780 switch (keycode) {
781 case 0x5c: /* print screen */
782 if (state->ks_flags & ALTS)
783 keycode = 0x54; /* sysrq */
784 break;
785 case 0x68: /* pause/break */
786 if (state->ks_flags & CTLS)
787 keycode = 0x6c; /* break */
788 break;
791 /* return the key code in the K_CODE mode */
792 if (state->ks_mode == K_CODE)
793 return (keycode | (scancode & 0x80));
795 /* compose a character code */
796 if (state->ks_flags & COMPOSE) {
797 switch (keycode | (scancode & 0x80)) {
798 /* key pressed, process it */
799 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
800 state->ks_composed_char *= 10;
801 state->ks_composed_char += keycode - 0x40;
802 if (state->ks_composed_char > UCHAR_MAX)
803 return (ERRKEY);
804 goto next_code;
805 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
806 state->ks_composed_char *= 10;
807 state->ks_composed_char += keycode - 0x47;
808 if (state->ks_composed_char > UCHAR_MAX)
809 return (ERRKEY);
810 goto next_code;
811 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
812 state->ks_composed_char *= 10;
813 state->ks_composed_char += keycode - 0x4E;
814 if (state->ks_composed_char > UCHAR_MAX)
815 return (ERRKEY);
816 goto next_code;
817 case 0x52: /* keypad 0 */
818 state->ks_composed_char *= 10;
819 if (state->ks_composed_char > UCHAR_MAX)
820 return (ERRKEY);
821 goto next_code;
823 /* key released, no interest here */
824 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */
825 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */
826 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */
827 case 0xD2: /* keypad 0 */
828 goto next_code;
830 case 0x38: /* left alt key */
831 break;
833 default:
834 if (state->ks_composed_char > 0) {
835 state->ks_flags &= ~COMPOSE;
836 state->ks_composed_char = 0;
837 return (ERRKEY);
839 break;
843 /* keycode to key action */
844 action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
845 &state->ks_state, &state->ks_accents);
846 if (action == NOKEY)
847 goto next_code;
849 return (action);
853 * Check if char is waiting
855 static int
856 kbdmux_check_char(keyboard_t *kbd)
858 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
859 int ready;
861 if (!KBD_IS_ACTIVE(kbd))
862 return (FALSE);
864 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
865 ready = TRUE;
866 else
867 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
869 return (ready);
873 * Keyboard ioctl's
875 static int
876 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
878 static int delays[] = {
879 250, 500, 750, 1000
882 static int rates[] = {
883 34, 38, 42, 46, 50, 55, 59, 63,
884 68, 76, 84, 92, 100, 110, 118, 126,
885 136, 152, 168, 184, 200, 220, 236, 252,
886 272, 304, 336, 368, 400, 440, 472, 504
889 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
890 kbdmux_kbd_t *k;
891 keyboard_info_t *ki;
892 int error = 0, mode, i;
894 if (state == NULL)
895 return (ENXIO);
897 switch (cmd) {
898 case KBADDKBD: /* add keyboard to the mux */
899 ki = (keyboard_info_t *) arg;
901 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
902 strcmp(ki->kb_name, "*") == 0) {
903 return (EINVAL); /* bad input */
906 SLIST_FOREACH(k, &state->ks_kbds, next)
907 if (k->kbd->kb_unit == ki->kb_unit &&
908 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
909 break;
911 if (k != NULL)
912 return (0); /* keyboard already in the mux */
914 k = kmalloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
915 if (k == NULL)
916 return (ENOMEM); /* out of memory */
918 k->kbd = kbd_get_keyboard(
919 kbd_allocate(
920 ki->kb_name,
921 ki->kb_unit,
922 (void *) &k->kbd,
923 kbdmux_kbd_event, (void *) state));
924 if (k->kbd == NULL) {
925 kfree(k, M_KBDMUX);
926 return (EINVAL); /* bad keyboard */
929 kbd_enable(k->kbd);
930 kbd_clear_state(k->kbd);
932 /* set K_RAW mode on slave keyboard */
933 mode = K_RAW;
934 error = kbd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
935 if (error == 0) {
936 /* set lock keys state on slave keyboard */
937 mode = state->ks_state & LOCK_MASK;
938 error = kbd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
941 if (error != 0) {
942 kbd_release(k->kbd, &k->kbd);
943 k->kbd = NULL;
944 kfree(k, M_KBDMUX);
945 return (error); /* could not set mode */
948 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
949 break;
951 case KBRELKBD: /* release keyboard from the mux */
952 ki = (keyboard_info_t *) arg;
954 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
955 strcmp(ki->kb_name, "*") == 0) {
956 return (EINVAL); /* bad input */
959 SLIST_FOREACH(k, &state->ks_kbds, next)
960 if (k->kbd->kb_unit == ki->kb_unit &&
961 strcmp(k->kbd->kb_name, ki->kb_name) == 0)
962 break;
964 if (k != NULL) {
965 error = kbd_release(k->kbd, &k->kbd);
966 if (error == 0) {
967 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
969 k->kbd = NULL;
971 kfree(k, M_KBDMUX);
973 } else
974 error = ENXIO; /* keyboard is not in the mux */
976 break;
978 case KDGKBMODE: /* get kyboard mode */
979 *(int *)arg = state->ks_mode;
980 break;
982 case KDSKBMODE: /* set keyboard mode */
983 switch (*(int *)arg) {
984 case K_XLATE:
985 if (state->ks_mode != K_XLATE) {
986 /* make lock key state and LED state match */
987 state->ks_state &= ~LOCK_MASK;
988 state->ks_state |= KBD_LED_VAL(kbd);
990 /* FALLTHROUGH */
992 case K_RAW:
993 case K_CODE:
994 if (state->ks_mode != *(int *)arg) {
995 kbdmux_clear_state(kbd);
996 state->ks_mode = *(int *)arg;
998 break;
1000 default:
1001 error = EINVAL;
1002 break;
1004 break;
1006 case KDGETLED: /* get keyboard LED */
1007 *(int *)arg = KBD_LED_VAL(kbd);
1008 break;
1010 case KDSETLED: /* set keyboard LED */
1011 /* NOTE: lock key state in ks_state won't be changed */
1012 if (*(int *)arg & ~LOCK_MASK)
1013 return (EINVAL);
1015 KBD_LED_VAL(kbd) = *(int *)arg;
1016 #ifdef EVDEV_SUPPORT
1017 if (state->ks_evdev != NULL &&
1018 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1019 evdev_push_leds(state->ks_evdev, *(int *)arg);
1020 #endif
1021 /* KDSETLED on all slave keyboards */
1022 SLIST_FOREACH(k, &state->ks_kbds, next)
1023 kbd_ioctl(k->kbd, KDSETLED, arg);
1024 break;
1026 case KDGKBSTATE: /* get lock key state */
1027 *(int *)arg = state->ks_state & LOCK_MASK;
1028 break;
1030 case KDSKBSTATE: /* set lock key state */
1031 if (*(int *)arg & ~LOCK_MASK)
1032 return (EINVAL);
1034 state->ks_state &= ~LOCK_MASK;
1035 state->ks_state |= *(int *)arg;
1037 /* KDSKBSTATE on all slave keyboards */
1038 SLIST_FOREACH(k, &state->ks_kbds, next)
1039 kbd_ioctl(k->kbd, KDSKBSTATE, arg);
1041 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1042 /* NOT REACHED */
1044 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1045 /* lookup delay */
1046 for (i = NELEM(delays) - 1; i > 0; i --)
1047 if (((int *)arg)[0] >= delays[i])
1048 break;
1049 mode = i << 5;
1051 /* lookup rate */
1052 for (i = NELEM(rates) - 1; i > 0; i --)
1053 if (((int *)arg)[1] >= rates[i])
1054 break;
1055 mode |= i;
1057 if (mode & ~0x7f)
1058 return (EINVAL);
1060 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1061 kbd->kb_delay2 = rates[mode & 0x1f];
1062 #ifdef EVDEV_SUPPORT
1063 if (state->ks_evdev != NULL &&
1064 evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
1065 evdev_push_repeats(state->ks_evdev, kbd);
1066 #endif
1067 /* perform command on all slave keyboards */
1068 SLIST_FOREACH(k, &state->ks_kbds, next)
1069 kbd_ioctl(k->kbd, cmd, arg);
1070 break;
1072 case PIO_KEYMAP: /* set keyboard translation table */
1073 case PIO_KEYMAPENT: /* set keyboard translation table entry */
1074 case PIO_DEADKEYMAP: /* set accent key translation table */
1075 state->ks_accents = 0;
1077 /* perform command on all slave keyboards */
1078 SLIST_FOREACH(k, &state->ks_kbds, next)
1079 kbd_ioctl(k->kbd, cmd, arg);
1080 /* FALLTHROUGH */
1082 default:
1083 error = genkbd_commonioctl(kbd, cmd, arg);
1084 break;
1086 return (error);
1090 * Lock the access to the keyboard
1092 static int
1093 kbdmux_lock(keyboard_t *kbd, int lock)
1095 return (1); /* XXX */
1099 * Clear the internal state of the keyboard
1101 * NOTE: May be called unlocked from init
1103 static void
1104 kbdmux_clear_state(keyboard_t *kbd)
1106 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1108 state->ks_flags &= ~(COMPOSE|POLLING);
1109 state->ks_state &= LOCK_MASK; /* preserve locking key state */
1110 state->ks_accents = 0;
1111 state->ks_composed_char = 0;
1112 /* state->ks_prefix = 0; XXX */
1113 state->ks_inq_length = 0;
1117 * Save the internal state
1119 static int
1120 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1122 if (len == 0)
1123 return (sizeof(kbdmux_state_t));
1124 if (len < sizeof(kbdmux_state_t))
1125 return (-1);
1127 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1129 return (0);
1133 * Set the internal state
1135 static int
1136 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1138 if (len < sizeof(kbdmux_state_t))
1139 return (ENOMEM);
1141 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1143 return (0);
1147 * Set polling
1149 * Caller interlocks all keyboard calls. We must not lock here.
1151 static int
1152 kbdmux_poll(keyboard_t *kbd, int on)
1154 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data;
1155 kbdmux_kbd_t *k;
1157 if (on)
1158 state->ks_flags |= POLLING;
1159 else
1160 state->ks_flags &= ~POLLING;
1162 /* set poll on slave keyboards */
1163 SLIST_FOREACH(k, &state->ks_kbds, next)
1164 kbd_poll(k->kbd, on);
1166 return (0);
1169 /*****************************************************************************
1170 *****************************************************************************
1171 ** Module
1172 *****************************************************************************
1173 *****************************************************************************/
1175 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1177 static int
1178 kbdmux_modevent(module_t mod, int type, void *data)
1180 keyboard_switch_t *sw;
1181 keyboard_t *kbd;
1182 int error;
1184 switch (type) {
1185 case MOD_LOAD:
1186 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1187 break;
1189 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1190 kbd_delete_driver(&kbdmux_kbd_driver);
1191 error = ENXIO;
1192 break;
1195 kbd = NULL;
1197 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1198 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1199 kbd_delete_driver(&kbdmux_kbd_driver);
1200 break;
1203 #ifdef KBD_INSTALL_CDEV
1204 if ((error = kbd_attach(kbd)) != 0) {
1205 (*sw->term)(kbd);
1206 kbd_delete_driver(&kbdmux_kbd_driver);
1207 break;
1209 #endif
1211 if ((error = (*sw->enable)(kbd)) != 0) {
1212 (*sw->disable)(kbd);
1213 #ifdef KBD_INSTALL_CDEV
1214 kbd_detach(kbd);
1215 #endif
1216 (*sw->term)(kbd);
1217 kbd_delete_driver(&kbdmux_kbd_driver);
1218 break;
1220 break;
1222 case MOD_UNLOAD:
1223 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1224 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1226 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1227 if (kbd != NULL) {
1228 (*sw->disable)(kbd);
1229 #ifdef KBD_INSTALL_CDEV
1230 kbd_detach(kbd);
1231 #endif
1232 (*sw->term)(kbd);
1233 kbd_delete_driver(&kbdmux_kbd_driver);
1235 error = 0;
1236 break;
1238 default:
1239 error = EOPNOTSUPP;
1240 break;
1242 return (error);
1245 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1246 #ifdef EVDEV_SUPPORT
1247 MODULE_DEPEND(kbdmux, evdev, 1, 1, 1);
1248 #endif