The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/kbdmux/kbdmux.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * kbdmux.c
    3  */
    4 
    5 /*-
    6  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    7  *
    8  * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   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.
   19  *
   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
   30  * SUCH DAMAGE.
   31  *
   32  * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
   33  * $FreeBSD$
   34  */
   35 
   36 #include "opt_evdev.h"
   37 #include "opt_kbd.h"
   38 #include "opt_kbdmux.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/bus.h>
   42 #include <sys/conf.h>
   43 #include <sys/consio.h>
   44 #include <sys/fcntl.h>
   45 #include <sys/kbio.h>
   46 #include <sys/kernel.h>
   47 #include <sys/limits.h>
   48 #include <sys/lock.h>
   49 #include <sys/malloc.h>
   50 #include <sys/module.h>
   51 #include <sys/mutex.h>
   52 #include <sys/poll.h>
   53 #include <sys/proc.h>
   54 #include <sys/queue.h>
   55 #include <sys/selinfo.h>
   56 #include <sys/systm.h>
   57 #include <sys/taskqueue.h>
   58 #include <sys/uio.h>
   59 #include <dev/kbd/kbdreg.h>
   60 
   61 /* the initial key map, accent map and fkey strings */
   62 #ifdef KBDMUX_DFLT_KEYMAP
   63 #define KBD_DFLT_KEYMAP
   64 #include "kbdmuxmap.h"
   65 #endif
   66 
   67 #include <dev/kbd/kbdtables.h>
   68 
   69 #ifdef EVDEV_SUPPORT
   70 #include <dev/evdev/evdev.h>
   71 #include <dev/evdev/input.h>
   72 #endif
   73 
   74 #define KEYBOARD_NAME   "kbdmux"
   75 
   76 MALLOC_DECLARE(M_KBDMUX);
   77 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
   78 
   79 /*****************************************************************************
   80  *****************************************************************************
   81  **                             Keyboard state
   82  *****************************************************************************
   83  *****************************************************************************/
   84 
   85 #define KBDMUX_Q_SIZE   512     /* input queue size */
   86 
   87 /*
   88  * XXX
   89  * For now rely on Giant mutex to protect our data structures.
   90  * Just like the rest of keyboard drivers and syscons(4) do.
   91  * Note that callout is initialized as not MP-safe to make sure
   92  * Giant is held.
   93  */
   94 
   95 #if 0 /* not yet */
   96 #define KBDMUX_LOCK_DECL_GLOBAL \
   97         struct mtx ks_lock
   98 #define KBDMUX_LOCK_INIT(s) \
   99         mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
  100 #define KBDMUX_LOCK_DESTROY(s) \
  101         mtx_destroy(&(s)->ks_lock)
  102 #define KBDMUX_LOCK(s) \
  103         mtx_lock(&(s)->ks_lock)
  104 #define KBDMUX_UNLOCK(s) \
  105         mtx_unlock(&(s)->ks_lock)
  106 #define KBDMUX_LOCK_ASSERT(s, w) \
  107         mtx_assert(&(s)->ks_lock, (w))
  108 #define KBDMUX_SLEEP(s, f, d, t) \
  109         msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
  110 #define KBDMUX_CALLOUT_INIT(s) \
  111         callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
  112 #define KBDMUX_QUEUE_INTR(s) \
  113         taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
  114 #else
  115 #define KBDMUX_LOCK_DECL_GLOBAL
  116 
  117 #define KBDMUX_LOCK_INIT(s)
  118 
  119 #define KBDMUX_LOCK_DESTROY(s)
  120 
  121 #define KBDMUX_LOCK(s)
  122 
  123 #define KBDMUX_UNLOCK(s)
  124 
  125 #define KBDMUX_LOCK_ASSERT(s, w)
  126 
  127 #define KBDMUX_SLEEP(s, f, d, t) \
  128         tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t))
  129 #define KBDMUX_CALLOUT_INIT(s) \
  130         callout_init(&(s)->ks_timo, 0)
  131 #define KBDMUX_QUEUE_INTR(s) \
  132         taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
  133 #endif /* not yet */
  134 
  135 /*
  136  * kbdmux keyboard
  137  */
  138 struct kbdmux_kbd
  139 {
  140         keyboard_t              *kbd;   /* keyboard */
  141         SLIST_ENTRY(kbdmux_kbd)  next;  /* link to next */
  142 };
  143 
  144 typedef struct kbdmux_kbd       kbdmux_kbd_t;
  145 
  146 /*
  147  * kbdmux state
  148  */
  149 struct kbdmux_state
  150 {
  151         char                     ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
  152         unsigned int             ks_inq_start;
  153         unsigned int             ks_inq_length;
  154         struct task              ks_task;       /* interrupt task */
  155         struct callout           ks_timo;       /* timeout handler */
  156 #define TICKS                   (hz)            /* rate */
  157 
  158         int                      ks_flags;      /* flags */
  159 #define COMPOSE                 (1 << 0)        /* compose char flag */ 
  160 #define TASK                    (1 << 2)        /* interrupt task queued */
  161 
  162         int                      ks_polling;    /* poll nesting count */
  163         int                      ks_mode;       /* K_XLATE, K_RAW, K_CODE */
  164         int                      ks_state;      /* state */
  165         int                      ks_accents;    /* accent key index (> 0) */
  166         u_int                    ks_composed_char; /* composed char code */
  167         u_char                   ks_prefix;     /* AT scan code prefix */
  168 
  169 #ifdef EVDEV_SUPPORT
  170         struct evdev_dev *       ks_evdev;
  171         int                      ks_evdev_state;
  172 #endif
  173 
  174         SLIST_HEAD(, kbdmux_kbd) ks_kbds;       /* keyboards */
  175 
  176         KBDMUX_LOCK_DECL_GLOBAL;
  177 };
  178 
  179 typedef struct kbdmux_state     kbdmux_state_t;
  180 
  181 /*****************************************************************************
  182  *****************************************************************************
  183  **                             Helper functions
  184  *****************************************************************************
  185  *****************************************************************************/
  186 
  187 static task_fn_t                kbdmux_kbd_intr;
  188 static callout_func_t           kbdmux_kbd_intr_timo;
  189 static kbd_callback_func_t      kbdmux_kbd_event;
  190 
  191 static void
  192 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
  193 {
  194         unsigned int p;
  195 
  196         if (state->ks_inq_length == KBDMUX_Q_SIZE)
  197                 return;
  198 
  199         p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
  200         state->ks_inq[p] = c;
  201         state->ks_inq_length++;
  202 }
  203 
  204 static int
  205 kbdmux_kbd_getc(kbdmux_state_t *state)
  206 {
  207         unsigned char c;
  208 
  209         if (state->ks_inq_length == 0)
  210                 return (-1);
  211 
  212         c = state->ks_inq[state->ks_inq_start];
  213         state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
  214         state->ks_inq_length--;
  215 
  216         return (c);
  217 }
  218 
  219 /*
  220  * Interrupt handler task
  221  */
  222 void
  223 kbdmux_kbd_intr(void *xkbd, int pending)
  224 {
  225         keyboard_t      *kbd = (keyboard_t *) xkbd;
  226         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
  227 
  228         kbdd_intr(kbd, NULL);
  229 
  230         KBDMUX_LOCK(state);
  231 
  232         state->ks_flags &= ~TASK;
  233         wakeup(&state->ks_task);
  234 
  235         KBDMUX_UNLOCK(state);
  236 }
  237 
  238 /*
  239  * Schedule interrupt handler on timeout. Called with locked state.
  240  */
  241 void
  242 kbdmux_kbd_intr_timo(void *xstate)
  243 {
  244         kbdmux_state_t  *state = (kbdmux_state_t *) xstate;
  245 
  246         KBDMUX_LOCK_ASSERT(state, MA_OWNED);
  247 
  248         if (callout_pending(&state->ks_timo))
  249                 return; /* callout was reset */
  250 
  251         if (!callout_active(&state->ks_timo))
  252                 return; /* callout was stopped */
  253 
  254         callout_deactivate(&state->ks_timo);
  255 
  256         /* queue interrupt task if needed */
  257         if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
  258             KBDMUX_QUEUE_INTR(state) == 0)
  259                 state->ks_flags |= TASK;
  260 
  261         /* re-schedule timeout */
  262         callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
  263 }
  264 
  265 /*
  266  * Process event from one of our keyboards
  267  */
  268 static int
  269 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
  270 {
  271         kbdmux_state_t  *state = (kbdmux_state_t *) arg;
  272 
  273         switch (event) {
  274         case KBDIO_KEYINPUT: {
  275                 int     c;
  276 
  277                 KBDMUX_LOCK(state);
  278 
  279                 /*
  280                  * Read all chars from the keyboard
  281                  *
  282                  * Turns out that atkbd(4) check_char() method may return
  283                  * "true" while read_char() method returns NOKEY. If this
  284                  * happens we could stuck in the loop below. Avoid this
  285                  * by breaking out of the loop if read_char() method returns
  286                  * NOKEY.
  287                  */
  288 
  289                 while (kbdd_check_char(kbd)) {
  290                         c = kbdd_read_char(kbd, 0);
  291                         if (c == NOKEY)
  292                                 break;
  293                         if (c == ERRKEY)
  294                                 continue; /* XXX ring bell */
  295                         if (!KBD_IS_BUSY(kbd))
  296                                 continue; /* not open - discard the input */
  297 
  298                         kbdmux_kbd_putc(state, c);
  299                 }
  300 
  301                 /* queue interrupt task if needed */
  302                 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
  303                     KBDMUX_QUEUE_INTR(state) == 0)
  304                         state->ks_flags |= TASK;
  305 
  306                 KBDMUX_UNLOCK(state);
  307                 } break;
  308 
  309         case KBDIO_UNLOADING: {
  310                 kbdmux_kbd_t    *k;
  311 
  312                 KBDMUX_LOCK(state);
  313 
  314                 SLIST_FOREACH(k, &state->ks_kbds, next)
  315                         if (k->kbd == kbd)
  316                                 break;
  317 
  318                 if (k != NULL) {
  319                         kbd_release(k->kbd, &k->kbd);
  320                         SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
  321 
  322                         k->kbd = NULL;
  323 
  324                         free(k, M_KBDMUX);
  325                 }
  326 
  327                 KBDMUX_UNLOCK(state);
  328                 } break;
  329 
  330         default:
  331                 return (EINVAL);
  332                 /* NOT REACHED */
  333         }
  334 
  335         return (0);
  336 }
  337 
  338 /****************************************************************************
  339  ****************************************************************************
  340  **                              Keyboard driver
  341  ****************************************************************************
  342  ****************************************************************************/
  343 
  344 static int              kbdmux_configure(int flags);
  345 static kbd_probe_t      kbdmux_probe;
  346 static kbd_init_t       kbdmux_init;
  347 static kbd_term_t       kbdmux_term;
  348 static kbd_intr_t       kbdmux_intr;
  349 static kbd_test_if_t    kbdmux_test_if;
  350 static kbd_enable_t     kbdmux_enable;
  351 static kbd_disable_t    kbdmux_disable;
  352 static kbd_read_t       kbdmux_read;
  353 static kbd_check_t      kbdmux_check;
  354 static kbd_read_char_t  kbdmux_read_char;
  355 static kbd_check_char_t kbdmux_check_char;
  356 static kbd_ioctl_t      kbdmux_ioctl;
  357 static kbd_lock_t       kbdmux_lock;
  358 static void             kbdmux_clear_state_locked(kbdmux_state_t *state);
  359 static kbd_clear_state_t kbdmux_clear_state;
  360 static kbd_get_state_t  kbdmux_get_state;
  361 static kbd_set_state_t  kbdmux_set_state;
  362 static kbd_poll_mode_t  kbdmux_poll;
  363 
  364 static keyboard_switch_t kbdmuxsw = {
  365         .probe =        kbdmux_probe,
  366         .init =         kbdmux_init,
  367         .term =         kbdmux_term,
  368         .intr =         kbdmux_intr,
  369         .test_if =      kbdmux_test_if,
  370         .enable =       kbdmux_enable,
  371         .disable =      kbdmux_disable,
  372         .read =         kbdmux_read,
  373         .check =        kbdmux_check,
  374         .read_char =    kbdmux_read_char,
  375         .check_char =   kbdmux_check_char,
  376         .ioctl =        kbdmux_ioctl,
  377         .lock =         kbdmux_lock,
  378         .clear_state =  kbdmux_clear_state,
  379         .get_state =    kbdmux_get_state,
  380         .set_state =    kbdmux_set_state,
  381         .poll =         kbdmux_poll,
  382 };
  383 
  384 #ifdef EVDEV_SUPPORT
  385 static evdev_event_t kbdmux_ev_event;
  386 
  387 static const struct evdev_methods kbdmux_evdev_methods = {
  388         .ev_event = kbdmux_ev_event,
  389 };
  390 #endif
  391 
  392 /*
  393  * Return the number of found keyboards
  394  */
  395 static int
  396 kbdmux_configure(int flags)
  397 {
  398         return (1);
  399 }
  400 
  401 /*
  402  * Detect a keyboard
  403  */
  404 static int
  405 kbdmux_probe(int unit, void *arg, int flags)
  406 {
  407         if (resource_disabled(KEYBOARD_NAME, unit))
  408                 return (ENXIO);
  409 
  410         return (0);
  411 }
  412 
  413 /*
  414  * Reset and initialize the keyboard (stolen from atkbd.c)
  415  */
  416 static int
  417 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
  418 {
  419         keyboard_t      *kbd = NULL;
  420         kbdmux_state_t  *state = NULL;
  421         keymap_t        *keymap = NULL;
  422         accentmap_t     *accmap = NULL;
  423         fkeytab_t       *fkeymap = NULL;
  424         int              error, needfree, fkeymap_size, delay[2];
  425 #ifdef EVDEV_SUPPORT
  426         struct evdev_dev *evdev;
  427         char             phys_loc[NAMELEN];
  428 #endif
  429 
  430         if (*kbdp == NULL) {
  431                 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
  432                 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
  433                 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
  434                 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
  435                 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
  436                 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
  437                 needfree = 1;
  438 
  439                 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
  440                     (accmap == NULL) || (fkeymap == NULL)) {
  441                         error = ENOMEM;
  442                         goto bad;
  443                 }
  444 
  445                 KBDMUX_LOCK_INIT(state);
  446                 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
  447                 KBDMUX_CALLOUT_INIT(state);
  448                 SLIST_INIT(&state->ks_kbds);
  449         } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
  450                 return (0);
  451         } else {
  452                 kbd = *kbdp;
  453                 state = (kbdmux_state_t *) kbd->kb_data;
  454                 keymap = kbd->kb_keymap;
  455                 accmap = kbd->kb_accentmap;
  456                 fkeymap = kbd->kb_fkeytab;
  457                 fkeymap_size = kbd->kb_fkeytab_size;
  458                 needfree = 0;
  459         }
  460 
  461         if (!KBD_IS_PROBED(kbd)) {
  462                 /* XXX assume 101/102 keys keyboard */
  463                 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
  464                 bcopy(&key_map, keymap, sizeof(key_map));
  465                 bcopy(&accent_map, accmap, sizeof(accent_map));
  466                 bcopy(fkey_tab, fkeymap,
  467                         imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
  468                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
  469                 kbd->kb_data = (void *)state;
  470         
  471                 KBD_FOUND_DEVICE(kbd);
  472                 KBD_PROBE_DONE(kbd);
  473 
  474                 KBDMUX_LOCK(state);
  475                 kbdmux_clear_state_locked(state);
  476                 state->ks_mode = K_XLATE;
  477                 KBDMUX_UNLOCK(state);
  478         }
  479 
  480         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
  481                 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
  482 
  483                 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
  484 
  485                 delay[0] = kbd->kb_delay1;
  486                 delay[1] = kbd->kb_delay2;
  487                 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
  488 
  489 #ifdef EVDEV_SUPPORT
  490                 /* register as evdev provider */
  491                 evdev = evdev_alloc();
  492                 evdev_set_name(evdev, "System keyboard multiplexer");
  493                 snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit);
  494                 evdev_set_phys(evdev, phys_loc);
  495                 evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0);
  496                 evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods);
  497                 evdev_support_event(evdev, EV_SYN);
  498                 evdev_support_event(evdev, EV_KEY);
  499                 evdev_support_event(evdev, EV_LED);
  500                 evdev_support_event(evdev, EV_REP);
  501                 evdev_support_all_known_keys(evdev);
  502                 evdev_support_led(evdev, LED_NUML);
  503                 evdev_support_led(evdev, LED_CAPSL);
  504                 evdev_support_led(evdev, LED_SCROLLL);
  505 
  506                 if (evdev_register_mtx(evdev, &Giant))
  507                         evdev_free(evdev);
  508                 else
  509                         state->ks_evdev = evdev;
  510                 state->ks_evdev_state = 0;
  511 #endif
  512 
  513                 KBD_INIT_DONE(kbd);
  514         }
  515 
  516         if (!KBD_IS_CONFIGURED(kbd)) {
  517                 if (kbd_register(kbd) < 0) {
  518                         error = ENXIO;
  519                         goto bad;
  520                 }
  521 
  522                 KBD_CONFIG_DONE(kbd);
  523 
  524                 KBDMUX_LOCK(state);
  525                 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
  526                 KBDMUX_UNLOCK(state);
  527         }
  528 
  529         return (0);
  530 bad:
  531         if (needfree) {
  532                 if (state != NULL)
  533                         free(state, M_KBDMUX);
  534                 if (keymap != NULL)
  535                         free(keymap, M_KBDMUX);
  536                 if (accmap != NULL)
  537                         free(accmap, M_KBDMUX);
  538                 if (fkeymap != NULL)
  539                         free(fkeymap, M_KBDMUX);
  540                 if (kbd != NULL) {
  541                         free(kbd, M_KBDMUX);
  542                         *kbdp = NULL;   /* insure ref doesn't leak to caller */
  543                 }
  544         }
  545 
  546         return (error);
  547 }
  548 
  549 /*
  550  * Finish using this keyboard
  551  */
  552 static int
  553 kbdmux_term(keyboard_t *kbd)
  554 {
  555         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
  556         kbdmux_kbd_t    *k;
  557 
  558         KBDMUX_LOCK(state);
  559 
  560         /* kill callout */
  561         callout_stop(&state->ks_timo);
  562 
  563         /* wait for interrupt task */
  564         while (state->ks_flags & TASK)
  565                 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
  566 
  567         /* release all keyboards from the mux */
  568         while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
  569                 kbd_release(k->kbd, &k->kbd);
  570                 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
  571 
  572                 k->kbd = NULL;
  573 
  574                 free(k, M_KBDMUX);
  575         }
  576 
  577         KBDMUX_UNLOCK(state);
  578 
  579         kbd_unregister(kbd);
  580 
  581 #ifdef EVDEV_SUPPORT
  582         evdev_free(state->ks_evdev);
  583 #endif
  584 
  585         KBDMUX_LOCK_DESTROY(state);
  586         bzero(state, sizeof(*state));
  587         free(state, M_KBDMUX);
  588 
  589         free(kbd->kb_keymap, M_KBDMUX);
  590         free(kbd->kb_accentmap, M_KBDMUX);
  591         free(kbd->kb_fkeytab, M_KBDMUX);
  592         free(kbd, M_KBDMUX);
  593 
  594         return (0);
  595 }
  596 
  597 /*
  598  * Keyboard interrupt routine
  599  */
  600 static int
  601 kbdmux_intr(keyboard_t *kbd, void *arg)
  602 {
  603         int     c;
  604 
  605         if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
  606                 /* let the callback function to process the input */
  607                 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
  608                                             kbd->kb_callback.kc_arg);
  609         } else {
  610                 /* read and discard the input; no one is waiting for input */
  611                 do {
  612                         c = kbdmux_read_char(kbd, FALSE);
  613                 } while (c != NOKEY);
  614         }
  615 
  616         return (0);
  617 }
  618 
  619 /*
  620  * Test the interface to the device
  621  */
  622 static int
  623 kbdmux_test_if(keyboard_t *kbd)
  624 {
  625         return (0);
  626 }
  627 
  628 /* 
  629  * Enable the access to the device; until this function is called,
  630  * the client cannot read from the keyboard.
  631  */
  632 static int
  633 kbdmux_enable(keyboard_t *kbd)
  634 {
  635         KBD_ACTIVATE(kbd);
  636         return (0);
  637 }
  638 
  639 /*
  640  * Disallow the access to the device
  641  */
  642 static int
  643 kbdmux_disable(keyboard_t *kbd)
  644 {
  645         KBD_DEACTIVATE(kbd);
  646         return (0);
  647 }
  648 
  649 /*
  650  * Read one byte from the keyboard if it's allowed
  651  */
  652 static int
  653 kbdmux_read(keyboard_t *kbd, int wait)
  654 {
  655         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
  656         int              c;
  657 
  658         KBDMUX_LOCK(state);
  659         c = kbdmux_kbd_getc(state);
  660         KBDMUX_UNLOCK(state);
  661 
  662         if (c != -1)
  663                 kbd->kb_count ++;
  664 
  665         return (KBD_IS_ACTIVE(kbd)? c : -1);
  666 }
  667 
  668 /*
  669  * Check if data is waiting
  670  */
  671 static int
  672 kbdmux_check(keyboard_t *kbd)
  673 {
  674         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
  675         int              ready;
  676 
  677         if (!KBD_IS_ACTIVE(kbd))
  678                 return (FALSE);
  679 
  680         KBDMUX_LOCK(state);
  681         ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
  682         KBDMUX_UNLOCK(state);
  683 
  684         return (ready);
  685 }
  686 
  687 /*
  688  * Read char from the keyboard (stolen from atkbd.c)
  689  */
  690 static u_int
  691 kbdmux_read_char(keyboard_t *kbd, int wait)
  692 {
  693         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
  694         u_int            action;
  695         int              scancode, keycode;
  696 
  697         KBDMUX_LOCK(state);
  698 
  699 next_code:
  700 
  701         /* do we have a composed char to return? */
  702         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
  703                 action = state->ks_composed_char;
  704                 state->ks_composed_char = 0;
  705                 if (action > UCHAR_MAX) {
  706                         KBDMUX_UNLOCK(state);
  707 
  708                         return (ERRKEY);
  709                 }
  710 
  711                 KBDMUX_UNLOCK(state);
  712 
  713                 return (action);
  714         }
  715 
  716         /* see if there is something in the keyboard queue */
  717         scancode = kbdmux_kbd_getc(state);
  718         if (scancode == -1) {
  719                 if (state->ks_polling != 0) {
  720                         kbdmux_kbd_t    *k;
  721 
  722                         SLIST_FOREACH(k, &state->ks_kbds, next) {
  723                                 while (kbdd_check_char(k->kbd)) {
  724                                         scancode = kbdd_read_char(k->kbd, 0);
  725                                         if (scancode == NOKEY)
  726                                                 break;
  727                                         if (scancode == ERRKEY)
  728                                                 continue;
  729                                         if (!KBD_IS_BUSY(k->kbd))
  730                                                 continue; 
  731 
  732                                         kbdmux_kbd_putc(state, scancode);
  733                                 }
  734                         }
  735 
  736                         if (state->ks_inq_length > 0)
  737                                 goto next_code;
  738                 }
  739 
  740                 KBDMUX_UNLOCK(state);
  741                 return (NOKEY);
  742         }
  743         /* XXX FIXME: check for -1 if wait == 1! */
  744 
  745         kbd->kb_count ++;
  746 
  747 #ifdef EVDEV_SUPPORT
  748         /* push evdev event */
  749         if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) {
  750                 uint16_t key = evdev_scancode2key(&state->ks_evdev_state,
  751                     scancode);
  752 
  753                 if (key != KEY_RESERVED) {
  754                         evdev_push_event(state->ks_evdev, EV_KEY,
  755                             key, scancode & 0x80 ? 0 : 1);
  756                         evdev_sync(state->ks_evdev);
  757                 }
  758         }
  759 #endif
  760 
  761         /* return the byte as is for the K_RAW mode */
  762         if (state->ks_mode == K_RAW) {
  763                 KBDMUX_UNLOCK(state);
  764                 return (scancode);
  765         }
  766 
  767         /* translate the scan code into a keycode */
  768         keycode = scancode & 0x7F;
  769         switch (state->ks_prefix) {
  770         case 0x00:      /* normal scancode */
  771                 switch(scancode) {
  772                 case 0xB8:      /* left alt (compose key) released */
  773                         if (state->ks_flags & COMPOSE) {
  774                                 state->ks_flags &= ~COMPOSE;
  775                                 if (state->ks_composed_char > UCHAR_MAX)
  776                                         state->ks_composed_char = 0;
  777                         }
  778                         break;
  779                 case 0x38:      /* left alt (compose key) pressed */
  780                         if (!(state->ks_flags & COMPOSE)) {
  781                                 state->ks_flags |= COMPOSE;
  782                                 state->ks_composed_char = 0;
  783                         }
  784                         break;
  785                 case 0xE0:
  786                 case 0xE1:
  787                         state->ks_prefix = scancode;
  788                         goto next_code;
  789                 }
  790                 break;
  791         case 0xE0:      /* 0xE0 prefix */
  792                 state->ks_prefix = 0;
  793                 switch (keycode) {
  794                 case 0x1C:      /* right enter key */
  795                         keycode = 0x59;
  796                         break;
  797                 case 0x1D:      /* right ctrl key */
  798                         keycode = 0x5A;
  799                         break;
  800                 case 0x35:      /* keypad divide key */
  801                         keycode = 0x5B;
  802                         break;
  803                 case 0x37:      /* print scrn key */
  804                         keycode = 0x5C;
  805                         break;
  806                 case 0x38:      /* right alt key (alt gr) */
  807                         keycode = 0x5D;
  808                         break;
  809                 case 0x46:      /* ctrl-pause/break on AT 101 (see below) */
  810                         keycode = 0x68;
  811                         break;
  812                 case 0x47:      /* grey home key */
  813                         keycode = 0x5E;
  814                         break;
  815                 case 0x48:      /* grey up arrow key */
  816                         keycode = 0x5F;
  817                         break;
  818                 case 0x49:      /* grey page up key */
  819                         keycode = 0x60;
  820                         break;
  821                 case 0x4B:      /* grey left arrow key */
  822                         keycode = 0x61;
  823                         break;
  824                 case 0x4D:      /* grey right arrow key */
  825                         keycode = 0x62;
  826                         break;
  827                 case 0x4F:      /* grey end key */
  828                         keycode = 0x63;
  829                         break;
  830                 case 0x50:      /* grey down arrow key */
  831                         keycode = 0x64;
  832                         break;
  833                 case 0x51:      /* grey page down key */
  834                         keycode = 0x65;
  835                         break;
  836                 case 0x52:      /* grey insert key */
  837                         keycode = 0x66;
  838                         break;
  839                 case 0x53:      /* grey delete key */
  840                         keycode = 0x67;
  841                         break;
  842                 /* the following 3 are only used on the MS "Natural" keyboard */
  843                 case 0x5b:      /* left Window key */
  844                         keycode = 0x69;
  845                         break;
  846                 case 0x5c:      /* right Window key */
  847                         keycode = 0x6a;
  848                         break;
  849                 case 0x5d:      /* menu key */
  850                         keycode = 0x6b;
  851                         break;
  852                 case 0x5e:      /* power key */
  853                         keycode = 0x6d;
  854                         break;
  855                 case 0x5f:      /* sleep key */
  856                         keycode = 0x6e;
  857                         break;
  858                 case 0x63:      /* wake key */
  859                         keycode = 0x6f;
  860                         break;
  861                 case 0x64:      /* [JP106USB] backslash, underscore */
  862                         keycode = 0x73;
  863                         break;
  864                 default:        /* ignore everything else */
  865                         goto next_code;
  866                 }
  867                 break;
  868         case 0xE1:      /* 0xE1 prefix */
  869                 /* 
  870                  * The pause/break key on the 101 keyboard produces:
  871                  * E1-1D-45 E1-9D-C5
  872                  * Ctrl-pause/break produces:
  873                  * E0-46 E0-C6 (See above.)
  874                  */
  875                 state->ks_prefix = 0;
  876                 if (keycode == 0x1D)
  877                         state->ks_prefix = 0x1D;
  878                 goto next_code;
  879                 /* NOT REACHED */
  880         case 0x1D:      /* pause / break */
  881                 state->ks_prefix = 0;
  882                 if (keycode != 0x45)
  883                         goto next_code;
  884                 keycode = 0x68;
  885                 break;
  886         }
  887 
  888         /* XXX assume 101/102 keys AT keyboard */
  889         switch (keycode) {
  890         case 0x5c:      /* print screen */
  891                 if (state->ks_flags & ALTS)
  892                         keycode = 0x54; /* sysrq */
  893                 break;
  894         case 0x68:      /* pause/break */
  895                 if (state->ks_flags & CTLS)
  896                         keycode = 0x6c; /* break */
  897                 break;
  898         }
  899 
  900         /* return the key code in the K_CODE mode */
  901         if (state->ks_mode == K_CODE) {
  902                 KBDMUX_UNLOCK(state);
  903                 return (keycode | (scancode & 0x80));
  904         }
  905 
  906         /* compose a character code */
  907         if (state->ks_flags & COMPOSE) {
  908                 switch (keycode | (scancode & 0x80)) {
  909                 /* key pressed, process it */
  910                 case 0x47: case 0x48: case 0x49:        /* keypad 7,8,9 */
  911                         state->ks_composed_char *= 10;
  912                         state->ks_composed_char += keycode - 0x40;
  913                         if (state->ks_composed_char > UCHAR_MAX) {
  914                                 KBDMUX_UNLOCK(state);
  915                                 return (ERRKEY);
  916                         }
  917                         goto next_code;
  918                 case 0x4B: case 0x4C: case 0x4D:        /* keypad 4,5,6 */
  919                         state->ks_composed_char *= 10;
  920                         state->ks_composed_char += keycode - 0x47;
  921                         if (state->ks_composed_char > UCHAR_MAX) {
  922                                 KBDMUX_UNLOCK(state);
  923                                 return (ERRKEY);
  924                         }
  925                         goto next_code;
  926                 case 0x4F: case 0x50: case 0x51:        /* keypad 1,2,3 */
  927                         state->ks_composed_char *= 10;
  928                         state->ks_composed_char += keycode - 0x4E;
  929                         if (state->ks_composed_char > UCHAR_MAX) {
  930                                 KBDMUX_UNLOCK(state);
  931                                 return (ERRKEY);
  932                         }
  933                         goto next_code;
  934                 case 0x52:      /* keypad 0 */
  935                         state->ks_composed_char *= 10;
  936                         if (state->ks_composed_char > UCHAR_MAX) {
  937                                 KBDMUX_UNLOCK(state);
  938                                 return (ERRKEY);
  939                         }
  940                         goto next_code;
  941 
  942                 /* key released, no interest here */
  943                 case 0xC7: case 0xC8: case 0xC9:        /* keypad 7,8,9 */
  944                 case 0xCB: case 0xCC: case 0xCD:        /* keypad 4,5,6 */
  945                 case 0xCF: case 0xD0: case 0xD1:        /* keypad 1,2,3 */
  946                 case 0xD2:                              /* keypad 0 */
  947                         goto next_code;
  948 
  949                 case 0x38:                              /* left alt key */
  950                         break;
  951 
  952                 default:
  953                         if (state->ks_composed_char > 0) {
  954                                 state->ks_flags &= ~COMPOSE;
  955                                 state->ks_composed_char = 0;
  956                                 KBDMUX_UNLOCK(state);
  957                                 return (ERRKEY);
  958                         }
  959                         break;
  960                 }
  961         }
  962 
  963         /* keycode to key action */
  964         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
  965                         &state->ks_state, &state->ks_accents);
  966         if (action == NOKEY)
  967                 goto next_code;
  968 
  969         KBDMUX_UNLOCK(state);
  970 
  971         return (action);
  972 }
  973 
  974 /*
  975  * Check if char is waiting
  976  */
  977 static int
  978 kbdmux_check_char(keyboard_t *kbd)
  979 {
  980         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
  981         int              ready;
  982 
  983         if (!KBD_IS_ACTIVE(kbd))
  984                 return (FALSE);
  985 
  986         KBDMUX_LOCK(state);
  987 
  988         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
  989                 ready = TRUE;
  990         else
  991                 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
  992 
  993         KBDMUX_UNLOCK(state);
  994 
  995         return (ready);
  996 }
  997 
  998 /*
  999  * Keyboard ioctl's
 1000  */
 1001 static int
 1002 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
 1003 {
 1004         static int       delays[] = {
 1005                 250, 500, 750, 1000
 1006         };
 1007 
 1008         static int       rates[]  =  {
 1009                 34,  38,  42,  46,  50,   55,  59,  63,
 1010                 68,  76,  84,  92,  100, 110, 118, 126,
 1011                 136, 152, 168, 184, 200, 220, 236, 252,
 1012                 272, 304, 336, 368, 400, 440, 472, 504
 1013         };
 1014 
 1015         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
 1016         kbdmux_kbd_t    *k;
 1017         keyboard_info_t *ki;
 1018         int              error = 0, mode;
 1019 #ifdef COMPAT_FREEBSD6
 1020         int              ival;
 1021 #endif
 1022 
 1023         if (state == NULL)
 1024                 return (ENXIO);
 1025 
 1026         switch (cmd) {
 1027         case KBADDKBD: /* add keyboard to the mux */
 1028                 ki = (keyboard_info_t *) arg;
 1029 
 1030                 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
 1031                     strcmp(ki->kb_name, "*") == 0)
 1032                         return (EINVAL); /* bad input */
 1033 
 1034                 KBDMUX_LOCK(state);
 1035 
 1036                 SLIST_FOREACH(k, &state->ks_kbds, next)
 1037                         if (k->kbd->kb_unit == ki->kb_unit &&
 1038                             strcmp(k->kbd->kb_name, ki->kb_name) == 0)
 1039                                 break;
 1040 
 1041                 if (k != NULL) {
 1042                         KBDMUX_UNLOCK(state);
 1043 
 1044                         return (0); /* keyboard already in the mux */
 1045                 }
 1046 
 1047                 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
 1048                 if (k == NULL) {
 1049                         KBDMUX_UNLOCK(state);
 1050 
 1051                         return (ENOMEM); /* out of memory */
 1052                 }
 1053 
 1054                 k->kbd = kbd_get_keyboard(
 1055                                 kbd_allocate(
 1056                                         ki->kb_name,
 1057                                         ki->kb_unit,
 1058                                         (void *) &k->kbd,
 1059                                         kbdmux_kbd_event, (void *) state));
 1060                 if (k->kbd == NULL) {
 1061                         KBDMUX_UNLOCK(state);
 1062                         free(k, M_KBDMUX);
 1063 
 1064                         return (EINVAL); /* bad keyboard */
 1065                 }
 1066 
 1067                 kbdd_enable(k->kbd);
 1068                 kbdd_clear_state(k->kbd);
 1069 
 1070                 /* set K_RAW mode on slave keyboard */
 1071                 mode = K_RAW;
 1072                 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
 1073                 if (error == 0) {
 1074                         /* set lock keys state on slave keyboard */
 1075                         mode = state->ks_state & LOCK_MASK;
 1076                         error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
 1077                 }
 1078 
 1079                 if (error != 0) {
 1080                         KBDMUX_UNLOCK(state);
 1081 
 1082                         kbd_release(k->kbd, &k->kbd);
 1083                         k->kbd = NULL;
 1084 
 1085                         free(k, M_KBDMUX);
 1086 
 1087                         return (error); /* could not set mode */
 1088                 }
 1089 
 1090                 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
 1091 
 1092                 KBDMUX_UNLOCK(state);
 1093                 break;
 1094 
 1095         case KBRELKBD: /* release keyboard from the mux */
 1096                 ki = (keyboard_info_t *) arg;
 1097 
 1098                 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
 1099                     strcmp(ki->kb_name, "*") == 0)
 1100                         return (EINVAL); /* bad input */
 1101 
 1102                 KBDMUX_LOCK(state);
 1103 
 1104                 SLIST_FOREACH(k, &state->ks_kbds, next)
 1105                         if (k->kbd->kb_unit == ki->kb_unit &&
 1106                             strcmp(k->kbd->kb_name, ki->kb_name) == 0)
 1107                                 break;
 1108 
 1109                 if (k != NULL) {
 1110                         error = kbd_release(k->kbd, &k->kbd);
 1111                         if (error == 0) {
 1112                                 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
 1113 
 1114                                 k->kbd = NULL;
 1115 
 1116                                 free(k, M_KBDMUX);
 1117                         }
 1118                 } else
 1119                         error = ENXIO; /* keyboard is not in the mux */
 1120 
 1121                 KBDMUX_UNLOCK(state);
 1122                 break;
 1123 
 1124         case KDGKBMODE: /* get kyboard mode */
 1125                 KBDMUX_LOCK(state);
 1126                 *(int *)arg = state->ks_mode;
 1127                 KBDMUX_UNLOCK(state);
 1128                 break;
 1129 
 1130 #ifdef COMPAT_FREEBSD6
 1131         case _IO('K', 7):
 1132                 ival = IOCPARM_IVAL(arg);
 1133                 arg = (caddr_t)&ival;
 1134                 /* FALLTHROUGH */
 1135 #endif
 1136         case KDSKBMODE: /* set keyboard mode */
 1137                 KBDMUX_LOCK(state);
 1138 
 1139                 switch (*(int *)arg) {
 1140                 case K_XLATE:
 1141                         if (state->ks_mode != K_XLATE) {
 1142                                 /* make lock key state and LED state match */
 1143                                 state->ks_state &= ~LOCK_MASK;
 1144                                 state->ks_state |= KBD_LED_VAL(kbd);
 1145                         }
 1146                         /* FALLTHROUGH */
 1147 
 1148                 case K_RAW:
 1149                 case K_CODE:
 1150                         if (state->ks_mode != *(int *)arg) {
 1151                                 kbdmux_clear_state_locked(state);
 1152                                 state->ks_mode = *(int *)arg;
 1153                         }
 1154                         break;
 1155 
 1156                 default:
 1157                         error = EINVAL;
 1158                         break;
 1159                 }
 1160 
 1161                 KBDMUX_UNLOCK(state);
 1162                 break;
 1163 
 1164         case KDGETLED: /* get keyboard LED */
 1165                 KBDMUX_LOCK(state);
 1166                 *(int *)arg = KBD_LED_VAL(kbd);
 1167                 KBDMUX_UNLOCK(state);
 1168                 break;
 1169 
 1170 #ifdef COMPAT_FREEBSD6
 1171         case _IO('K', 66):
 1172                 ival = IOCPARM_IVAL(arg);
 1173                 arg = (caddr_t)&ival;
 1174                 /* FALLTHROUGH */
 1175 #endif
 1176         case KDSETLED: /* set keyboard LED */
 1177                 KBDMUX_LOCK(state);
 1178 
 1179                 /* NOTE: lock key state in ks_state won't be changed */
 1180                 if (*(int *)arg & ~LOCK_MASK) {
 1181                         KBDMUX_UNLOCK(state);
 1182 
 1183                         return (EINVAL);
 1184                 }
 1185 
 1186                 KBD_LED_VAL(kbd) = *(int *)arg;
 1187 #ifdef EVDEV_SUPPORT
 1188                 if (state->ks_evdev != NULL &&
 1189                     evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
 1190                         evdev_push_leds(state->ks_evdev, *(int *)arg);
 1191 #endif
 1192                 /* KDSETLED on all slave keyboards */
 1193                 SLIST_FOREACH(k, &state->ks_kbds, next)
 1194                         (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
 1195 
 1196                 KBDMUX_UNLOCK(state);
 1197                 break;
 1198 
 1199         case KDGKBSTATE: /* get lock key state */
 1200                 KBDMUX_LOCK(state);
 1201                 *(int *)arg = state->ks_state & LOCK_MASK;
 1202                 KBDMUX_UNLOCK(state);
 1203                 break;
 1204 
 1205 #ifdef COMPAT_FREEBSD6
 1206         case _IO('K', 20):
 1207                 ival = IOCPARM_IVAL(arg);
 1208                 arg = (caddr_t)&ival;
 1209                 /* FALLTHROUGH */
 1210 #endif
 1211         case KDSKBSTATE: /* set lock key state */
 1212                 KBDMUX_LOCK(state);
 1213 
 1214                 if (*(int *)arg & ~LOCK_MASK) {
 1215                         KBDMUX_UNLOCK(state);
 1216 
 1217                         return (EINVAL);
 1218                 }
 1219 
 1220                 state->ks_state &= ~LOCK_MASK;
 1221                 state->ks_state |= *(int *)arg;
 1222 
 1223                 /* KDSKBSTATE on all slave keyboards */
 1224                 SLIST_FOREACH(k, &state->ks_kbds, next)
 1225                         (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
 1226 
 1227                 KBDMUX_UNLOCK(state);
 1228 
 1229                 return (kbdmux_ioctl(kbd, KDSETLED, arg));
 1230                 /* NOT REACHED */
 1231 
 1232 #ifdef COMPAT_FREEBSD6
 1233         case _IO('K', 67):
 1234                 cmd = KDSETRAD;
 1235                 ival = IOCPARM_IVAL(arg);
 1236                 arg = (caddr_t)&ival;
 1237                 /* FALLTHROUGH */
 1238 #endif
 1239         case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
 1240         case KDSETRAD: /* set keyboard repeat rate (old interface) */
 1241                 KBDMUX_LOCK(state);
 1242 
 1243                 if (cmd == KDSETREPEAT) {
 1244                         int     i;
 1245 
 1246                         /* lookup delay */
 1247                         for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
 1248                                 if (((int *)arg)[0] >= delays[i])
 1249                                         break;
 1250                         mode = i << 5;
 1251 
 1252                         /* lookup rate */
 1253                         for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
 1254                                 if (((int *)arg)[1] >= rates[i])
 1255                                         break;
 1256                         mode |= i;
 1257                 } else
 1258                         mode = *(int *)arg;
 1259 
 1260                 if (mode & ~0x7f) {
 1261                         KBDMUX_UNLOCK(state);
 1262 
 1263                         return (EINVAL);
 1264                 }
 1265 
 1266                 kbd->kb_delay1 = delays[(mode >> 5) & 3];
 1267                 kbd->kb_delay2 = rates[mode & 0x1f];
 1268 #ifdef EVDEV_SUPPORT
 1269                 if (state->ks_evdev != NULL &&
 1270                     evdev_rcpt_mask & EVDEV_RCPT_KBDMUX)
 1271                         evdev_push_repeats(state->ks_evdev, kbd);
 1272 #endif
 1273                 /* perform command on all slave keyboards */
 1274                 SLIST_FOREACH(k, &state->ks_kbds, next)
 1275                         (void)kbdd_ioctl(k->kbd, cmd, arg);
 1276 
 1277                 KBDMUX_UNLOCK(state);
 1278                 break;
 1279 
 1280         case PIO_KEYMAP:        /* set keyboard translation table */
 1281         case OPIO_KEYMAP:       /* set keyboard translation table (compat) */
 1282         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
 1283         case PIO_DEADKEYMAP:    /* set accent key translation table */
 1284                 KBDMUX_LOCK(state);
 1285                 state->ks_accents = 0;
 1286 
 1287                 /* perform command on all slave keyboards */
 1288                 SLIST_FOREACH(k, &state->ks_kbds, next)
 1289                         (void)kbdd_ioctl(k->kbd, cmd, arg);
 1290 
 1291                 KBDMUX_UNLOCK(state);
 1292                 /* FALLTHROUGH */
 1293 
 1294         default:
 1295                 error = genkbd_commonioctl(kbd, cmd, arg);
 1296                 break;
 1297         }
 1298 
 1299         return (error);
 1300 }
 1301 
 1302 /*
 1303  * Lock the access to the keyboard
 1304  */
 1305 static int
 1306 kbdmux_lock(keyboard_t *kbd, int lock)
 1307 {
 1308         return (1); /* XXX */
 1309 }
 1310 
 1311 /*
 1312  * Clear the internal state of the keyboard
 1313  */
 1314 static void
 1315 kbdmux_clear_state_locked(kbdmux_state_t *state)
 1316 {
 1317         KBDMUX_LOCK_ASSERT(state, MA_OWNED);
 1318 
 1319         state->ks_flags &= ~COMPOSE;
 1320         state->ks_polling = 0;
 1321         state->ks_state &= LOCK_MASK;   /* preserve locking key state */
 1322         state->ks_accents = 0;
 1323         state->ks_composed_char = 0;
 1324 /*      state->ks_prefix = 0;           XXX */
 1325         state->ks_inq_length = 0;
 1326 }
 1327 
 1328 static void
 1329 kbdmux_clear_state(keyboard_t *kbd)
 1330 {
 1331         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
 1332 
 1333         KBDMUX_LOCK(state);
 1334         kbdmux_clear_state_locked(state);
 1335         KBDMUX_UNLOCK(state);
 1336 }
 1337 
 1338 /*
 1339  * Save the internal state
 1340  */
 1341 static int
 1342 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
 1343 {
 1344         if (len == 0)
 1345                 return (sizeof(kbdmux_state_t));
 1346         if (len < sizeof(kbdmux_state_t))
 1347                 return (-1);
 1348 
 1349         bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
 1350 
 1351         return (0);
 1352 }
 1353 
 1354 /*
 1355  * Set the internal state
 1356  */
 1357 static int
 1358 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
 1359 {
 1360         if (len < sizeof(kbdmux_state_t))
 1361                 return (ENOMEM);
 1362 
 1363         bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
 1364 
 1365         return (0);
 1366 }
 1367 
 1368 /*
 1369  * Set polling
 1370  */
 1371 static int
 1372 kbdmux_poll(keyboard_t *kbd, int on)
 1373 {
 1374         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
 1375         kbdmux_kbd_t    *k;
 1376 
 1377         KBDMUX_LOCK(state);
 1378 
 1379         if (on)
 1380                 state->ks_polling++;
 1381         else
 1382                 state->ks_polling--;
 1383 
 1384         /* set poll on slave keyboards */
 1385         SLIST_FOREACH(k, &state->ks_kbds, next)
 1386                 kbdd_poll(k->kbd, on);
 1387 
 1388         KBDMUX_UNLOCK(state);
 1389 
 1390         return (0);
 1391 }
 1392 
 1393 #ifdef EVDEV_SUPPORT
 1394 static void
 1395 kbdmux_ev_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
 1396     int32_t value)
 1397 {
 1398         keyboard_t *kbd = evdev_get_softc(evdev);
 1399 
 1400         if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX &&
 1401             (type == EV_LED || type == EV_REP)) {
 1402                 mtx_lock(&Giant);
 1403                 kbd_ev_event(kbd, type, code, value);
 1404                 mtx_unlock(&Giant);
 1405         }
 1406 }
 1407 #endif
 1408 
 1409 /*****************************************************************************
 1410  *****************************************************************************
 1411  **                                    Module 
 1412  *****************************************************************************
 1413  *****************************************************************************/
 1414 
 1415 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
 1416 
 1417 static int
 1418 kbdmux_modevent(module_t mod, int type, void *data)
 1419 {
 1420         keyboard_switch_t       *sw;
 1421         keyboard_t              *kbd;
 1422         int                      error;
 1423 
 1424         switch (type) {
 1425         case MOD_LOAD:
 1426                 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
 1427                         break;
 1428 
 1429                 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
 1430                         error = ENXIO;
 1431                         break;
 1432                 }
 1433 
 1434                 kbd = NULL;
 1435 
 1436                 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
 1437                     (error = (*sw->init)(0, &kbd, NULL, 0)) != 0)
 1438                         break;
 1439 
 1440 #ifdef KBD_INSTALL_CDEV
 1441                 if ((error = kbd_attach(kbd)) != 0) {
 1442                         (*sw->term)(kbd);
 1443                         break;
 1444                 }
 1445 #endif
 1446 
 1447                 if ((error = (*sw->enable)(kbd)) != 0)
 1448                         break;
 1449                 break;
 1450 
 1451         case MOD_UNLOAD:
 1452                 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
 1453                         error = 0;
 1454                         break;
 1455                 }
 1456 
 1457                 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
 1458                 if (kbd != NULL) {
 1459                         (*sw->disable)(kbd);
 1460 #ifdef KBD_INSTALL_CDEV
 1461                         kbd_detach(kbd);
 1462 #endif
 1463                         (*sw->term)(kbd);
 1464                 }
 1465                 kbd_delete_driver(&kbdmux_kbd_driver);
 1466                 error = 0;
 1467                 break;
 1468 
 1469         default:
 1470                 error = EOPNOTSUPP;
 1471                 break;
 1472         }
 1473 
 1474         return (error);
 1475 }
 1476 
 1477 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
 1478 #ifdef EVDEV_SUPPORT
 1479 MODULE_DEPEND(kbdmux, evdev, 1, 1, 1);
 1480 #endif

Cache object: bcedc242f20dfbfe3d12f7fbd3e1bc5c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.