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

Cache object: e38ca162f612d5b301455d3e353eb52a


[ 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.