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

Cache object: 53cfae64e9ce31e5b5aa838858421bf4


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