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/kbd/kbd.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer as
   12  *    the first lines of this file unmodified.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include "opt_kbd.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/malloc.h>
   39 #include <sys/conf.h>
   40 #include <sys/fcntl.h>
   41 #include <sys/poll.h>
   42 #include <sys/priv.h>
   43 #include <sys/proc.h>
   44 #include <sys/selinfo.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/uio.h>
   47 
   48 #include <sys/kbio.h>
   49 
   50 #include <dev/evdev/input-event-codes.h>
   51 #include <dev/kbd/kbdreg.h>
   52 
   53 #define KBD_INDEX(dev)  dev2unit(dev)
   54 
   55 #define KB_QSIZE        512
   56 #define KB_BUFSIZE      64
   57 
   58 typedef struct genkbd_softc {
   59         int             gkb_flags;      /* flag/status bits */
   60 #define KB_ASLEEP       (1 << 0)
   61         struct selinfo  gkb_rsel;
   62         char            gkb_q[KB_QSIZE];                /* input queue */
   63         unsigned int    gkb_q_start;
   64         unsigned int    gkb_q_length;
   65 } genkbd_softc_t;
   66 
   67 static  SLIST_HEAD(, keyboard_driver) keyboard_drivers =
   68         SLIST_HEAD_INITIALIZER(keyboard_drivers);
   69 
   70 SET_DECLARE(kbddriver_set, const keyboard_driver_t);
   71 
   72 /* local arrays */
   73 
   74 /*
   75  * We need at least one entry each in order to initialize a keyboard
   76  * for the kernel console.  The arrays will be increased dynamically
   77  * when necessary.
   78  */
   79 
   80 static int              keyboards = 1;
   81 static keyboard_t       *kbd_ini;
   82 static keyboard_t       **keyboard = &kbd_ini;
   83 static keyboard_switch_t *kbdsw_ini;
   84        keyboard_switch_t **kbdsw = &kbdsw_ini;
   85 
   86 static int keymap_restrict_change;
   87 static SYSCTL_NODE(_hw, OID_AUTO, kbd, CTLFLAG_RD, 0, "kbd");
   88 SYSCTL_INT(_hw_kbd, OID_AUTO, keymap_restrict_change, CTLFLAG_RW,
   89     &keymap_restrict_change, 0, "restrict ability to change keymap");
   90 
   91 #define ARRAY_DELTA     4
   92 
   93 static int
   94 kbd_realloc_array(void)
   95 {
   96         keyboard_t **new_kbd;
   97         keyboard_switch_t **new_kbdsw;
   98         int newsize;
   99         int s;
  100 
  101         s = spltty();
  102         newsize = rounddown(keyboards + ARRAY_DELTA, ARRAY_DELTA);
  103         new_kbd = malloc(sizeof(*new_kbd)*newsize, M_DEVBUF, M_NOWAIT|M_ZERO);
  104         if (new_kbd == NULL) {
  105                 splx(s);
  106                 return (ENOMEM);
  107         }
  108         new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF,
  109                             M_NOWAIT|M_ZERO);
  110         if (new_kbdsw == NULL) {
  111                 free(new_kbd, M_DEVBUF);
  112                 splx(s);
  113                 return (ENOMEM);
  114         }
  115         bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards);
  116         bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards);
  117         if (keyboards > 1) {
  118                 free(keyboard, M_DEVBUF);
  119                 free(kbdsw, M_DEVBUF);
  120         }
  121         keyboard = new_kbd;
  122         kbdsw = new_kbdsw;
  123         keyboards = newsize;
  124         splx(s);
  125 
  126         if (bootverbose)
  127                 printf("kbd: new array size %d\n", keyboards);
  128 
  129         return (0);
  130 }
  131 
  132 /*
  133  * Low-level keyboard driver functions
  134  * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard
  135  * driver, call these functions to initialize the keyboard_t structure
  136  * and register it to the virtual keyboard driver `kbd'.
  137  */
  138 
  139 /* initialize the keyboard_t structure */
  140 void
  141 kbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config,
  142                 int port, int port_size)
  143 {
  144         kbd->kb_flags = KB_NO_DEVICE;   /* device has not been found */
  145         kbd->kb_name = name;
  146         kbd->kb_type = type;
  147         kbd->kb_unit = unit;
  148         kbd->kb_config = config & ~KB_CONF_PROBE_ONLY;
  149         kbd->kb_led = 0;                /* unknown */
  150         kbd->kb_io_base = port;
  151         kbd->kb_io_size = port_size;
  152         kbd->kb_data = NULL;
  153         kbd->kb_keymap = NULL;
  154         kbd->kb_accentmap = NULL;
  155         kbd->kb_fkeytab = NULL;
  156         kbd->kb_fkeytab_size = 0;
  157         kbd->kb_delay1 = KB_DELAY1;     /* these values are advisory only */
  158         kbd->kb_delay2 = KB_DELAY2;
  159         kbd->kb_count = 0L;
  160         bzero(kbd->kb_lastact, sizeof(kbd->kb_lastact));
  161 }
  162 
  163 void
  164 kbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap,
  165              fkeytab_t *fkeymap, int fkeymap_size)
  166 {
  167         kbd->kb_keymap = keymap;
  168         kbd->kb_accentmap = accmap;
  169         kbd->kb_fkeytab = fkeymap;
  170         kbd->kb_fkeytab_size = fkeymap_size;
  171 }
  172 
  173 /* declare a new keyboard driver */
  174 int
  175 kbd_add_driver(keyboard_driver_t *driver)
  176 {
  177         if (SLIST_NEXT(driver, link))
  178                 return (EINVAL);
  179         if (driver->kbdsw->get_fkeystr == NULL)
  180                 driver->kbdsw->get_fkeystr = genkbd_get_fkeystr;
  181         if (driver->kbdsw->diag == NULL)
  182                 driver->kbdsw->diag = genkbd_diag;
  183         SLIST_INSERT_HEAD(&keyboard_drivers, driver, link);
  184         return (0);
  185 }
  186 
  187 int
  188 kbd_delete_driver(keyboard_driver_t *driver)
  189 {
  190         SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link);
  191         SLIST_NEXT(driver, link) = NULL;
  192         return (0);
  193 }
  194 
  195 /* register a keyboard and associate it with a function table */
  196 int
  197 kbd_register(keyboard_t *kbd)
  198 {
  199         const keyboard_driver_t **list;
  200         const keyboard_driver_t *p;
  201         keyboard_t *mux;
  202         keyboard_info_t ki;
  203         int index;
  204 
  205         mux = kbd_get_keyboard(kbd_find_keyboard("kbdmux", -1));
  206 
  207         for (index = 0; index < keyboards; ++index) {
  208                 if (keyboard[index] == NULL)
  209                         break;
  210         }
  211         if (index >= keyboards) {
  212                 if (kbd_realloc_array())
  213                         return (-1);
  214         }
  215 
  216         kbd->kb_index = index;
  217         KBD_UNBUSY(kbd);
  218         KBD_VALID(kbd);
  219         kbd->kb_active = 0;     /* disabled until someone calls kbd_enable() */
  220         kbd->kb_token = NULL;
  221         kbd->kb_callback.kc_func = NULL;
  222         kbd->kb_callback.kc_arg = NULL;
  223 
  224         SLIST_FOREACH(p, &keyboard_drivers, link) {
  225                 if (strcmp(p->name, kbd->kb_name) == 0) {
  226                         keyboard[index] = kbd;
  227                         kbdsw[index] = p->kbdsw;
  228 
  229                         if (mux != NULL) {
  230                                 bzero(&ki, sizeof(ki));
  231                                 strcpy(ki.kb_name, kbd->kb_name);
  232                                 ki.kb_unit = kbd->kb_unit;
  233 
  234                                 (void)kbdd_ioctl(mux, KBADDKBD, (caddr_t) &ki);
  235                         }
  236 
  237                         return (index);
  238                 }
  239         }
  240         SET_FOREACH(list, kbddriver_set) {
  241                 p = *list;
  242                 if (strcmp(p->name, kbd->kb_name) == 0) {
  243                         keyboard[index] = kbd;
  244                         kbdsw[index] = p->kbdsw;
  245 
  246                         if (mux != NULL) {
  247                                 bzero(&ki, sizeof(ki));
  248                                 strcpy(ki.kb_name, kbd->kb_name);
  249                                 ki.kb_unit = kbd->kb_unit;
  250 
  251                                 (void)kbdd_ioctl(mux, KBADDKBD, (caddr_t) &ki);
  252                         }
  253 
  254                         return (index);
  255                 }
  256         }
  257 
  258         return (-1);
  259 }
  260 
  261 int
  262 kbd_unregister(keyboard_t *kbd)
  263 {
  264         int error;
  265         int s;
  266 
  267         if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards))
  268                 return (ENOENT);
  269         if (keyboard[kbd->kb_index] != kbd)
  270                 return (ENOENT);
  271 
  272         s = spltty();
  273         if (KBD_IS_BUSY(kbd)) {
  274                 error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING,
  275                     kbd->kb_callback.kc_arg);
  276                 if (error) {
  277                         splx(s);
  278                         return (error);
  279                 }
  280                 if (KBD_IS_BUSY(kbd)) {
  281                         splx(s);
  282                         return (EBUSY);
  283                 }
  284         }
  285         KBD_INVALID(kbd);
  286         keyboard[kbd->kb_index] = NULL;
  287         kbdsw[kbd->kb_index] = NULL;
  288 
  289         splx(s);
  290         return (0);
  291 }
  292 
  293 /* find a function table by the driver name */
  294 keyboard_switch_t *
  295 kbd_get_switch(char *driver)
  296 {
  297         const keyboard_driver_t **list;
  298         const keyboard_driver_t *p;
  299 
  300         SLIST_FOREACH(p, &keyboard_drivers, link) {
  301                 if (strcmp(p->name, driver) == 0)
  302                         return (p->kbdsw);
  303         }
  304         SET_FOREACH(list, kbddriver_set) {
  305                 p = *list;
  306                 if (strcmp(p->name, driver) == 0)
  307                         return (p->kbdsw);
  308         }
  309 
  310         return (NULL);
  311 }
  312 
  313 /*
  314  * Keyboard client functions
  315  * Keyboard clients, such as the console driver `syscons' and the keyboard
  316  * cdev driver, use these functions to claim and release a keyboard for
  317  * exclusive use.
  318  */
  319 
  320 /*
  321  * find the keyboard specified by a driver name and a unit number
  322  * starting at given index
  323  */
  324 int
  325 kbd_find_keyboard2(char *driver, int unit, int index)
  326 {
  327         int i;
  328 
  329         if ((index < 0) || (index >= keyboards))
  330                 return (-1);
  331 
  332         for (i = index; i < keyboards; ++i) {
  333                 if (keyboard[i] == NULL)
  334                         continue;
  335                 if (!KBD_IS_VALID(keyboard[i]))
  336                         continue;
  337                 if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver))
  338                         continue;
  339                 if ((unit != -1) && (keyboard[i]->kb_unit != unit))
  340                         continue;
  341                 return (i);
  342         }
  343 
  344         return (-1);
  345 }
  346 
  347 /* find the keyboard specified by a driver name and a unit number */
  348 int
  349 kbd_find_keyboard(char *driver, int unit)
  350 {
  351         return (kbd_find_keyboard2(driver, unit, 0));
  352 }
  353 
  354 /* allocate a keyboard */
  355 int
  356 kbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func,
  357              void *arg)
  358 {
  359         int index;
  360         int s;
  361 
  362         if (func == NULL)
  363                 return (-1);
  364 
  365         s = spltty();
  366         index = kbd_find_keyboard(driver, unit);
  367         if (index >= 0) {
  368                 if (KBD_IS_BUSY(keyboard[index])) {
  369                         splx(s);
  370                         return (-1);
  371                 }
  372                 keyboard[index]->kb_token = id;
  373                 KBD_BUSY(keyboard[index]);
  374                 keyboard[index]->kb_callback.kc_func = func;
  375                 keyboard[index]->kb_callback.kc_arg = arg;
  376                 kbdd_clear_state(keyboard[index]);
  377         }
  378         splx(s);
  379         return (index);
  380 }
  381 
  382 int
  383 kbd_release(keyboard_t *kbd, void *id)
  384 {
  385         int error;
  386         int s;
  387 
  388         s = spltty();
  389         if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
  390                 error = EINVAL;
  391         } else if (kbd->kb_token != id) {
  392                 error = EPERM;
  393         } else {
  394                 kbd->kb_token = NULL;
  395                 KBD_UNBUSY(kbd);
  396                 kbd->kb_callback.kc_func = NULL;
  397                 kbd->kb_callback.kc_arg = NULL;
  398                 kbdd_clear_state(kbd);
  399                 error = 0;
  400         }
  401         splx(s);
  402         return (error);
  403 }
  404 
  405 int
  406 kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func,
  407                     void *arg)
  408 {
  409         int error;
  410         int s;
  411 
  412         s = spltty();
  413         if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
  414                 error = EINVAL;
  415         } else if (kbd->kb_token != id) {
  416                 error = EPERM;
  417         } else if (func == NULL) {
  418                 error = EINVAL;
  419         } else {
  420                 kbd->kb_callback.kc_func = func;
  421                 kbd->kb_callback.kc_arg = arg;
  422                 error = 0;
  423         }
  424         splx(s);
  425         return (error);
  426 }
  427 
  428 /* get a keyboard structure */
  429 keyboard_t *
  430 kbd_get_keyboard(int index)
  431 {
  432         if ((index < 0) || (index >= keyboards))
  433                 return (NULL);
  434         if (keyboard[index] == NULL)
  435                 return (NULL);
  436         if (!KBD_IS_VALID(keyboard[index]))
  437                 return (NULL);
  438         return (keyboard[index]);
  439 }
  440 
  441 /*
  442  * The back door for the console driver; configure keyboards
  443  * This function is for the kernel console to initialize keyboards
  444  * at very early stage.
  445  */
  446 
  447 int
  448 kbd_configure(int flags)
  449 {
  450         const keyboard_driver_t **list;
  451         const keyboard_driver_t *p;
  452 
  453         SLIST_FOREACH(p, &keyboard_drivers, link) {
  454                 if (p->configure != NULL)
  455                         (*p->configure)(flags);
  456         }
  457         SET_FOREACH(list, kbddriver_set) {
  458                 p = *list;
  459                 if (p->configure != NULL)
  460                         (*p->configure)(flags);
  461         }
  462 
  463         return (0);
  464 }
  465 
  466 #ifdef KBD_INSTALL_CDEV
  467 
  468 /*
  469  * Virtual keyboard cdev driver functions
  470  * The virtual keyboard driver dispatches driver functions to
  471  * appropriate subdrivers.
  472  */
  473 
  474 #define KBD_UNIT(dev)   dev2unit(dev)
  475 
  476 static d_open_t         genkbdopen;
  477 static d_close_t        genkbdclose;
  478 static d_read_t         genkbdread;
  479 static d_write_t        genkbdwrite;
  480 static d_ioctl_t        genkbdioctl;
  481 static d_poll_t         genkbdpoll;
  482 
  483 
  484 static struct cdevsw kbd_cdevsw = {
  485         .d_version =    D_VERSION,
  486         .d_flags =      D_NEEDGIANT,
  487         .d_open =       genkbdopen,
  488         .d_close =      genkbdclose,
  489         .d_read =       genkbdread,
  490         .d_write =      genkbdwrite,
  491         .d_ioctl =      genkbdioctl,
  492         .d_poll =       genkbdpoll,
  493         .d_name =       "kbd",
  494 };
  495 
  496 int
  497 kbd_attach(keyboard_t *kbd)
  498 {
  499 
  500         if (kbd->kb_index >= keyboards)
  501                 return (EINVAL);
  502         if (keyboard[kbd->kb_index] != kbd)
  503                 return (EINVAL);
  504 
  505         kbd->kb_dev = make_dev(&kbd_cdevsw, kbd->kb_index, UID_ROOT, GID_WHEEL,
  506             0600, "%s%r", kbd->kb_name, kbd->kb_unit);
  507         make_dev_alias(kbd->kb_dev, "kbd%r", kbd->kb_index);
  508         kbd->kb_dev->si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
  509             M_WAITOK | M_ZERO);
  510         printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit);
  511         return (0);
  512 }
  513 
  514 int
  515 kbd_detach(keyboard_t *kbd)
  516 {
  517 
  518         if (kbd->kb_index >= keyboards)
  519                 return (EINVAL);
  520         if (keyboard[kbd->kb_index] != kbd)
  521                 return (EINVAL);
  522 
  523         free(kbd->kb_dev->si_drv1, M_DEVBUF);
  524         destroy_dev(kbd->kb_dev);
  525 
  526         return (0);
  527 }
  528 
  529 /*
  530  * Generic keyboard cdev driver functions
  531  * Keyboard subdrivers may call these functions to implement common
  532  * driver functions.
  533  */
  534 
  535 static void
  536 genkbd_putc(genkbd_softc_t *sc, char c)
  537 {
  538         unsigned int p;
  539 
  540         if (sc->gkb_q_length == KB_QSIZE)
  541                 return;
  542 
  543         p = (sc->gkb_q_start + sc->gkb_q_length) % KB_QSIZE;
  544         sc->gkb_q[p] = c;
  545         sc->gkb_q_length++;
  546 }
  547 
  548 static size_t
  549 genkbd_getc(genkbd_softc_t *sc, char *buf, size_t len)
  550 {
  551 
  552         /* Determine copy size. */
  553         if (sc->gkb_q_length == 0)
  554                 return (0);
  555         if (len >= sc->gkb_q_length)
  556                 len = sc->gkb_q_length;
  557         if (len >= KB_QSIZE - sc->gkb_q_start)
  558                 len = KB_QSIZE - sc->gkb_q_start;
  559 
  560         /* Copy out data and progress offset. */
  561         memcpy(buf, sc->gkb_q + sc->gkb_q_start, len);
  562         sc->gkb_q_start = (sc->gkb_q_start + len) % KB_QSIZE;
  563         sc->gkb_q_length -= len;
  564 
  565         return (len);
  566 }
  567 
  568 static kbd_callback_func_t genkbd_event;
  569 
  570 static int
  571 genkbdopen(struct cdev *dev, int mode, int flag, struct thread *td)
  572 {
  573         keyboard_t *kbd;
  574         genkbd_softc_t *sc;
  575         int s;
  576         int i;
  577 
  578         s = spltty();
  579         sc = dev->si_drv1;
  580         kbd = kbd_get_keyboard(KBD_INDEX(dev));
  581         if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
  582                 splx(s);
  583                 return (ENXIO);
  584         }
  585         i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc,
  586             genkbd_event, (void *)sc);
  587         if (i < 0) {
  588                 splx(s);
  589                 return (EBUSY);
  590         }
  591         /* assert(i == kbd->kb_index) */
  592         /* assert(kbd == kbd_get_keyboard(i)) */
  593 
  594         /*
  595          * NOTE: even when we have successfully claimed a keyboard,
  596          * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
  597          */
  598 
  599         sc->gkb_q_length = 0;
  600         splx(s);
  601 
  602         return (0);
  603 }
  604 
  605 static int
  606 genkbdclose(struct cdev *dev, int mode, int flag, struct thread *td)
  607 {
  608         keyboard_t *kbd;
  609         genkbd_softc_t *sc;
  610         int s;
  611 
  612         /*
  613          * NOTE: the device may have already become invalid.
  614          * kbd == NULL || !KBD_IS_VALID(kbd)
  615          */
  616         s = spltty();
  617         sc = dev->si_drv1;
  618         kbd = kbd_get_keyboard(KBD_INDEX(dev));
  619         if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
  620                 /* XXX: we shall be forgiving and don't report error... */
  621         } else {
  622                 kbd_release(kbd, (void *)sc);
  623         }
  624         splx(s);
  625         return (0);
  626 }
  627 
  628 static int
  629 genkbdread(struct cdev *dev, struct uio *uio, int flag)
  630 {
  631         keyboard_t *kbd;
  632         genkbd_softc_t *sc;
  633         u_char buffer[KB_BUFSIZE];
  634         int len;
  635         int error;
  636         int s;
  637 
  638         /* wait for input */
  639         s = spltty();
  640         sc = dev->si_drv1;
  641         kbd = kbd_get_keyboard(KBD_INDEX(dev));
  642         if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
  643                 splx(s);
  644                 return (ENXIO);
  645         }
  646         while (sc->gkb_q_length == 0) {
  647                 if (flag & O_NONBLOCK) {
  648                         splx(s);
  649                         return (EWOULDBLOCK);
  650                 }
  651                 sc->gkb_flags |= KB_ASLEEP;
  652                 error = tsleep(sc, PZERO | PCATCH, "kbdrea", 0);
  653                 kbd = kbd_get_keyboard(KBD_INDEX(dev));
  654                 if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
  655                         splx(s);
  656                         return (ENXIO); /* our keyboard has gone... */
  657                 }
  658                 if (error) {
  659                         sc->gkb_flags &= ~KB_ASLEEP;
  660                         splx(s);
  661                         return (error);
  662                 }
  663         }
  664         splx(s);
  665 
  666         /* copy as much input as possible */
  667         error = 0;
  668         while (uio->uio_resid > 0) {
  669                 len = imin(uio->uio_resid, sizeof(buffer));
  670                 len = genkbd_getc(sc, buffer, len);
  671                 if (len <= 0)
  672                         break;
  673                 error = uiomove(buffer, len, uio);
  674                 if (error)
  675                         break;
  676         }
  677 
  678         return (error);
  679 }
  680 
  681 static int
  682 genkbdwrite(struct cdev *dev, struct uio *uio, int flag)
  683 {
  684         keyboard_t *kbd;
  685 
  686         kbd = kbd_get_keyboard(KBD_INDEX(dev));
  687         if ((kbd == NULL) || !KBD_IS_VALID(kbd))
  688                 return (ENXIO);
  689         return (ENODEV);
  690 }
  691 
  692 static int
  693 genkbdioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
  694 {
  695         keyboard_t *kbd;
  696         int error;
  697 
  698         kbd = kbd_get_keyboard(KBD_INDEX(dev));
  699         if ((kbd == NULL) || !KBD_IS_VALID(kbd))
  700                 return (ENXIO);
  701         error = kbdd_ioctl(kbd, cmd, arg);
  702         if (error == ENOIOCTL)
  703                 error = ENODEV;
  704         return (error);
  705 }
  706 
  707 static int
  708 genkbdpoll(struct cdev *dev, int events, struct thread *td)
  709 {
  710         keyboard_t *kbd;
  711         genkbd_softc_t *sc;
  712         int revents;
  713         int s;
  714 
  715         revents = 0;
  716         s = spltty();
  717         sc = dev->si_drv1;
  718         kbd = kbd_get_keyboard(KBD_INDEX(dev));
  719         if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
  720                 revents =  POLLHUP;     /* the keyboard has gone */
  721         } else if (events & (POLLIN | POLLRDNORM)) {
  722                 if (sc->gkb_q_length > 0)
  723                         revents = events & (POLLIN | POLLRDNORM);
  724                 else
  725                         selrecord(td, &sc->gkb_rsel);
  726         }
  727         splx(s);
  728         return (revents);
  729 }
  730 
  731 static int
  732 genkbd_event(keyboard_t *kbd, int event, void *arg)
  733 {
  734         genkbd_softc_t *sc;
  735         size_t len;
  736         u_char *cp;
  737         int mode;
  738         u_int c;
  739 
  740         /* assert(KBD_IS_VALID(kbd)) */
  741         sc = (genkbd_softc_t *)arg;
  742 
  743         switch (event) {
  744         case KBDIO_KEYINPUT:
  745                 break;
  746         case KBDIO_UNLOADING:
  747                 /* the keyboard is going... */
  748                 kbd_release(kbd, (void *)sc);
  749                 if (sc->gkb_flags & KB_ASLEEP) {
  750                         sc->gkb_flags &= ~KB_ASLEEP;
  751                         wakeup(sc);
  752                 }
  753                 selwakeuppri(&sc->gkb_rsel, PZERO);
  754                 return (0);
  755         default:
  756                 return (EINVAL);
  757         }
  758 
  759         /* obtain the current key input mode */
  760         if (kbdd_ioctl(kbd, KDGKBMODE, (caddr_t)&mode))
  761                 mode = K_XLATE;
  762 
  763         /* read all pending input */
  764         while (kbdd_check_char(kbd)) {
  765                 c = kbdd_read_char(kbd, FALSE);
  766                 if (c == NOKEY)
  767                         continue;
  768                 if (c == ERRKEY)        /* XXX: ring bell? */
  769                         continue;
  770                 if (!KBD_IS_BUSY(kbd))
  771                         /* the device is not open, discard the input */
  772                         continue;
  773 
  774                 /* store the byte as is for K_RAW and K_CODE modes */
  775                 if (mode != K_XLATE) {
  776                         genkbd_putc(sc, KEYCHAR(c));
  777                         continue;
  778                 }
  779 
  780                 /* K_XLATE */
  781                 if (c & RELKEY) /* key release is ignored */
  782                         continue;
  783 
  784                 /* process special keys; most of them are just ignored... */
  785                 if (c & SPCLKEY) {
  786                         switch (KEYCHAR(c)) {
  787                         default:
  788                                 /* ignore them... */
  789                                 continue;
  790                         case BTAB:      /* a backtab: ESC [ Z */
  791                                 genkbd_putc(sc, 0x1b);
  792                                 genkbd_putc(sc, '[');
  793                                 genkbd_putc(sc, 'Z');
  794                                 continue;
  795                         }
  796                 }
  797 
  798                 /* normal chars, normal chars with the META, function keys */
  799                 switch (KEYFLAGS(c)) {
  800                 case 0:                 /* a normal char */
  801                         genkbd_putc(sc, KEYCHAR(c));
  802                         break;
  803                 case MKEY:              /* the META flag: prepend ESC */
  804                         genkbd_putc(sc, 0x1b);
  805                         genkbd_putc(sc, KEYCHAR(c));
  806                         break;
  807                 case FKEY | SPCLKEY:    /* a function key, return string */
  808                         cp = kbdd_get_fkeystr(kbd, KEYCHAR(c), &len);
  809                         if (cp != NULL) {
  810                                 while (len-- >  0)
  811                                         genkbd_putc(sc, *cp++);
  812                         }
  813                         break;
  814                 }
  815         }
  816 
  817         /* wake up sleeping/polling processes */
  818         if (sc->gkb_q_length > 0) {
  819                 if (sc->gkb_flags & KB_ASLEEP) {
  820                         sc->gkb_flags &= ~KB_ASLEEP;
  821                         wakeup(sc);
  822                 }
  823                 selwakeuppri(&sc->gkb_rsel, PZERO);
  824         }
  825 
  826         return (0);
  827 }
  828 
  829 #endif /* KBD_INSTALL_CDEV */
  830 
  831 /*
  832  * Generic low-level keyboard functions
  833  * The low-level functions in the keyboard subdriver may use these
  834  * functions.
  835  */
  836 
  837 #ifndef KBD_DISABLE_KEYMAP_LOAD
  838 static int key_change_ok(struct keyent_t *, struct keyent_t *, struct thread *);
  839 static int keymap_change_ok(keymap_t *, keymap_t *, struct thread *);
  840 static int accent_change_ok(accentmap_t *, accentmap_t *, struct thread *);
  841 static int fkey_change_ok(fkeytab_t *, fkeyarg_t *, struct thread *);
  842 #endif
  843 
  844 int
  845 genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
  846 {
  847         keymap_t *mapp;
  848         okeymap_t *omapp;
  849         keyarg_t *keyp;
  850         fkeyarg_t *fkeyp;
  851         int s;
  852         int i, j;
  853         int error;
  854 
  855         s = spltty();
  856         switch (cmd) {
  857 
  858         case KDGKBINFO:         /* get keyboard information */
  859                 ((keyboard_info_t *)arg)->kb_index = kbd->kb_index;
  860                 i = imin(strlen(kbd->kb_name) + 1,
  861                     sizeof(((keyboard_info_t *)arg)->kb_name));
  862                 bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i);
  863                 ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit;
  864                 ((keyboard_info_t *)arg)->kb_type = kbd->kb_type;
  865                 ((keyboard_info_t *)arg)->kb_config = kbd->kb_config;
  866                 ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags;
  867                 break;
  868 
  869         case KDGKBTYPE:         /* get keyboard type */
  870                 *(int *)arg = kbd->kb_type;
  871                 break;
  872 
  873         case KDGETREPEAT:       /* get keyboard repeat rate */
  874                 ((int *)arg)[0] = kbd->kb_delay1;
  875                 ((int *)arg)[1] = kbd->kb_delay2;
  876                 break;
  877 
  878         case GIO_KEYMAP:        /* get keyboard translation table */
  879                 error = copyout(kbd->kb_keymap, *(void **)arg,
  880                     sizeof(keymap_t));
  881                 splx(s);
  882                 return (error);
  883         case OGIO_KEYMAP:       /* get keyboard translation table (compat) */
  884                 mapp = kbd->kb_keymap;
  885                 omapp = (okeymap_t *)arg;
  886                 omapp->n_keys = mapp->n_keys;
  887                 for (i = 0; i < NUM_KEYS; i++) {
  888                         for (j = 0; j < NUM_STATES; j++)
  889                                 omapp->key[i].map[j] =
  890                                     mapp->key[i].map[j];
  891                         omapp->key[i].spcl = mapp->key[i].spcl;
  892                         omapp->key[i].flgs = mapp->key[i].flgs;
  893                 }
  894                 break;
  895         case PIO_KEYMAP:        /* set keyboard translation table */
  896         case OPIO_KEYMAP:       /* set keyboard translation table (compat) */
  897 #ifndef KBD_DISABLE_KEYMAP_LOAD
  898                 mapp = malloc(sizeof *mapp, M_TEMP, M_WAITOK);
  899                 if (cmd == OPIO_KEYMAP) {
  900                         omapp = (okeymap_t *)arg;
  901                         mapp->n_keys = omapp->n_keys;
  902                         for (i = 0; i < NUM_KEYS; i++) {
  903                                 for (j = 0; j < NUM_STATES; j++)
  904                                         mapp->key[i].map[j] =
  905                                             omapp->key[i].map[j];
  906                                 mapp->key[i].spcl = omapp->key[i].spcl;
  907                                 mapp->key[i].flgs = omapp->key[i].flgs;
  908                         }
  909                 } else {
  910                         error = copyin(*(void **)arg, mapp, sizeof *mapp);
  911                         if (error != 0) {
  912                                 splx(s);
  913                                 free(mapp, M_TEMP);
  914                                 return (error);
  915                         }
  916                 }
  917 
  918                 error = keymap_change_ok(kbd->kb_keymap, mapp, curthread);
  919                 if (error != 0) {
  920                         splx(s);
  921                         free(mapp, M_TEMP);
  922                         return (error);
  923                 }
  924                 bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
  925                 bcopy(mapp, kbd->kb_keymap, sizeof(*kbd->kb_keymap));
  926                 free(mapp, M_TEMP);
  927                 break;
  928 #else
  929                 splx(s);
  930                 return (ENODEV);
  931 #endif
  932 
  933         case GIO_KEYMAPENT:     /* get keyboard translation table entry */
  934                 keyp = (keyarg_t *)arg;
  935                 if (keyp->keynum >= sizeof(kbd->kb_keymap->key) /
  936                     sizeof(kbd->kb_keymap->key[0])) {
  937                         splx(s);
  938                         return (EINVAL);
  939                 }
  940                 bcopy(&kbd->kb_keymap->key[keyp->keynum], &keyp->key,
  941                     sizeof(keyp->key));
  942                 break;
  943         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
  944 #ifndef KBD_DISABLE_KEYMAP_LOAD
  945                 keyp = (keyarg_t *)arg;
  946                 if (keyp->keynum >= sizeof(kbd->kb_keymap->key) /
  947                     sizeof(kbd->kb_keymap->key[0])) {
  948                         splx(s);
  949                         return (EINVAL);
  950                 }
  951                 error = key_change_ok(&kbd->kb_keymap->key[keyp->keynum],
  952                     &keyp->key, curthread);
  953                 if (error != 0) {
  954                         splx(s);
  955                         return (error);
  956                 }
  957                 bcopy(&keyp->key, &kbd->kb_keymap->key[keyp->keynum],
  958                     sizeof(keyp->key));
  959                 break;
  960 #else
  961                 splx(s);
  962                 return (ENODEV);
  963 #endif
  964 
  965         case GIO_DEADKEYMAP:    /* get accent key translation table */
  966                 bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap));
  967                 break;
  968         case PIO_DEADKEYMAP:    /* set accent key translation table */
  969 #ifndef KBD_DISABLE_KEYMAP_LOAD
  970                 error = accent_change_ok(kbd->kb_accentmap,
  971                     (accentmap_t *)arg, curthread);
  972                 if (error != 0) {
  973                         splx(s);
  974                         return (error);
  975                 }
  976                 bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
  977                 break;
  978 #else
  979                 splx(s);
  980                 return (ENODEV);
  981 #endif
  982 
  983         case GETFKEY:           /* get functionkey string */
  984                 fkeyp = (fkeyarg_t *)arg;
  985                 if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
  986                         splx(s);
  987                         return (EINVAL);
  988                 }
  989                 bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef,
  990                     kbd->kb_fkeytab[fkeyp->keynum].len);
  991                 fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len;
  992                 break;
  993         case SETFKEY:           /* set functionkey string */
  994 #ifndef KBD_DISABLE_KEYMAP_LOAD
  995                 fkeyp = (fkeyarg_t *)arg;
  996                 if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
  997                         splx(s);
  998                         return (EINVAL);
  999                 }
 1000                 error = fkey_change_ok(&kbd->kb_fkeytab[fkeyp->keynum],
 1001                     fkeyp, curthread);
 1002                 if (error != 0) {
 1003                         splx(s);
 1004                         return (error);
 1005                 }
 1006                 kbd->kb_fkeytab[fkeyp->keynum].len = min(fkeyp->flen, MAXFK);
 1007                 bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str,
 1008                     kbd->kb_fkeytab[fkeyp->keynum].len);
 1009                 break;
 1010 #else
 1011                 splx(s);
 1012                 return (ENODEV);
 1013 #endif
 1014 
 1015         default:
 1016                 splx(s);
 1017                 return (ENOIOCTL);
 1018         }
 1019 
 1020         splx(s);
 1021         return (0);
 1022 }
 1023 
 1024 #ifndef KBD_DISABLE_KEYMAP_LOAD
 1025 #define RESTRICTED_KEY(key, i) \
 1026         ((key->spcl & (0x80 >> i)) && \
 1027                 (key->map[i] == RBT || key->map[i] == SUSP || \
 1028                  key->map[i] == STBY || key->map[i] == DBG || \
 1029                  key->map[i] == PNC || key->map[i] == HALT || \
 1030                  key->map[i] == PDWN))
 1031 
 1032 static int
 1033 key_change_ok(struct keyent_t *oldkey, struct keyent_t *newkey, struct thread *td)
 1034 {
 1035         int i;
 1036 
 1037         /* Low keymap_restrict_change means any changes are OK. */
 1038         if (keymap_restrict_change <= 0)
 1039                 return (0);
 1040 
 1041         /* High keymap_restrict_change means only root can change the keymap. */
 1042         if (keymap_restrict_change >= 2) {
 1043                 for (i = 0; i < NUM_STATES; i++)
 1044                         if (oldkey->map[i] != newkey->map[i])
 1045                                 return priv_check(td, PRIV_KEYBOARD);
 1046                 if (oldkey->spcl != newkey->spcl)
 1047                         return priv_check(td, PRIV_KEYBOARD);
 1048                 if (oldkey->flgs != newkey->flgs)
 1049                         return priv_check(td, PRIV_KEYBOARD);
 1050                 return (0);
 1051         }
 1052 
 1053         /* Otherwise we have to see if any special keys are being changed. */
 1054         for (i = 0; i < NUM_STATES; i++) {
 1055                 /*
 1056                  * If either the oldkey or the newkey action is restricted
 1057                  * then we must make sure that the action doesn't change.
 1058                  */
 1059                 if (!RESTRICTED_KEY(oldkey, i) && !RESTRICTED_KEY(newkey, i))
 1060                         continue;
 1061                 if ((oldkey->spcl & (0x80 >> i)) == (newkey->spcl & (0x80 >> i))
 1062                     && oldkey->map[i] == newkey->map[i])
 1063                         continue;
 1064                 return priv_check(td, PRIV_KEYBOARD);
 1065         }
 1066 
 1067         return (0);
 1068 }
 1069 
 1070 static int
 1071 keymap_change_ok(keymap_t *oldmap, keymap_t *newmap, struct thread *td)
 1072 {
 1073         int keycode, error;
 1074 
 1075         for (keycode = 0; keycode < NUM_KEYS; keycode++) {
 1076                 if ((error = key_change_ok(&oldmap->key[keycode],
 1077                     &newmap->key[keycode], td)) != 0)
 1078                         return (error);
 1079         }
 1080         return (0);
 1081 }
 1082 
 1083 static int
 1084 accent_change_ok(accentmap_t *oldmap, accentmap_t *newmap, struct thread *td)
 1085 {
 1086         struct acc_t *oldacc, *newacc;
 1087         int accent, i;
 1088 
 1089         if (keymap_restrict_change <= 2)
 1090                 return (0);
 1091 
 1092         if (oldmap->n_accs != newmap->n_accs)
 1093                 return priv_check(td, PRIV_KEYBOARD);
 1094 
 1095         for (accent = 0; accent < oldmap->n_accs; accent++) {
 1096                 oldacc = &oldmap->acc[accent];
 1097                 newacc = &newmap->acc[accent];
 1098                 if (oldacc->accchar != newacc->accchar)
 1099                         return priv_check(td, PRIV_KEYBOARD);
 1100                 for (i = 0; i < NUM_ACCENTCHARS; ++i) {
 1101                         if (oldacc->map[i][0] != newacc->map[i][0])
 1102                                 return priv_check(td, PRIV_KEYBOARD);
 1103                         if (oldacc->map[i][0] == 0)     /* end of table */
 1104                                 break;
 1105                         if (oldacc->map[i][1] != newacc->map[i][1])
 1106                                 return priv_check(td, PRIV_KEYBOARD);
 1107                 }
 1108         }
 1109 
 1110         return (0);
 1111 }
 1112 
 1113 static int
 1114 fkey_change_ok(fkeytab_t *oldkey, fkeyarg_t *newkey, struct thread *td)
 1115 {
 1116         if (keymap_restrict_change <= 3)
 1117                 return (0);
 1118 
 1119         if (oldkey->len != newkey->flen ||
 1120             bcmp(oldkey->str, newkey->keydef, oldkey->len) != 0)
 1121                 return priv_check(td, PRIV_KEYBOARD);
 1122 
 1123         return (0);
 1124 }
 1125 #endif
 1126 
 1127 /* get a pointer to the string associated with the given function key */
 1128 u_char *
 1129 genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len)
 1130 {
 1131         if (kbd == NULL)
 1132                 return (NULL);
 1133         fkey -= F_FN;
 1134         if (fkey > kbd->kb_fkeytab_size)
 1135                 return (NULL);
 1136         *len = kbd->kb_fkeytab[fkey].len;
 1137         return (kbd->kb_fkeytab[fkey].str);
 1138 }
 1139 
 1140 /* diagnostic dump */
 1141 static char *
 1142 get_kbd_type_name(int type)
 1143 {
 1144         static struct {
 1145                 int type;
 1146                 char *name;
 1147         } name_table[] = {
 1148                 { KB_84,        "AT 84" },
 1149                 { KB_101,       "AT 101/102" },
 1150                 { KB_OTHER,     "generic" },
 1151         };
 1152         int i;
 1153 
 1154         for (i = 0; i < nitems(name_table); ++i) {
 1155                 if (type == name_table[i].type)
 1156                         return (name_table[i].name);
 1157         }
 1158         return ("unknown");
 1159 }
 1160 
 1161 void
 1162 genkbd_diag(keyboard_t *kbd, int level)
 1163 {
 1164         if (level > 0) {
 1165                 printf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x",
 1166                     kbd->kb_index, kbd->kb_name, kbd->kb_unit,
 1167                     get_kbd_type_name(kbd->kb_type), kbd->kb_type,
 1168                     kbd->kb_config, kbd->kb_flags);
 1169                 if (kbd->kb_io_base > 0)
 1170                         printf(", port:0x%x-0x%x", kbd->kb_io_base,
 1171                             kbd->kb_io_base + kbd->kb_io_size - 1);
 1172                 printf("\n");
 1173         }
 1174 }
 1175 
 1176 #define set_lockkey_state(k, s, l)                              \
 1177         if (!((s) & l ## DOWN)) {                               \
 1178                 int i;                                          \
 1179                 (s) |= l ## DOWN;                               \
 1180                 (s) ^= l ## ED;                                 \
 1181                 i = (s) & LOCK_MASK;                            \
 1182                 (void)kbdd_ioctl((k), KDSETLED, (caddr_t)&i);   \
 1183         }
 1184 
 1185 static u_int
 1186 save_accent_key(keyboard_t *kbd, u_int key, int *accents)
 1187 {
 1188         int i;
 1189 
 1190         /* make an index into the accent map */
 1191         i = key - F_ACC + 1;
 1192         if ((i > kbd->kb_accentmap->n_accs)
 1193             || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) {
 1194                 /* the index is out of range or pointing to an empty entry */
 1195                 *accents = 0;
 1196                 return (ERRKEY);
 1197         }
 1198 
 1199         /*
 1200          * If the same accent key has been hit twice, produce the accent
 1201          * char itself.
 1202          */
 1203         if (i == *accents) {
 1204                 key = kbd->kb_accentmap->acc[i - 1].accchar;
 1205                 *accents = 0;
 1206                 return (key);
 1207         }
 1208 
 1209         /* remember the index and wait for the next key  */
 1210         *accents = i;
 1211         return (NOKEY);
 1212 }
 1213 
 1214 static u_int
 1215 make_accent_char(keyboard_t *kbd, u_int ch, int *accents)
 1216 {
 1217         struct acc_t *acc;
 1218         int i;
 1219 
 1220         acc = &kbd->kb_accentmap->acc[*accents - 1];
 1221         *accents = 0;
 1222 
 1223         /*
 1224          * If the accent key is followed by the space key,
 1225          * produce the accent char itself.
 1226          */
 1227         if (ch == ' ')
 1228                 return (acc->accchar);
 1229 
 1230         /* scan the accent map */
 1231         for (i = 0; i < NUM_ACCENTCHARS; ++i) {
 1232                 if (acc->map[i][0] == 0)        /* end of table */
 1233                         break;
 1234                 if (acc->map[i][0] == ch)
 1235                         return (acc->map[i][1]);
 1236         }
 1237         /* this char cannot be accented... */
 1238         return (ERRKEY);
 1239 }
 1240 
 1241 int
 1242 genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
 1243                  int *accents)
 1244 {
 1245         struct keyent_t *key;
 1246         int state = *shiftstate;
 1247         int action;
 1248         int f;
 1249         int i;
 1250 
 1251         i = keycode;
 1252         f = state & (AGRS | ALKED);
 1253         if ((f == AGRS1) || (f == AGRS2) || (f == ALKED))
 1254                 i += ALTGR_OFFSET;
 1255         key = &kbd->kb_keymap->key[i];
 1256         i = ((state & SHIFTS) ? 1 : 0)
 1257             | ((state & CTLS) ? 2 : 0)
 1258             | ((state & ALTS) ? 4 : 0);
 1259         if (((key->flgs & FLAG_LOCK_C) && (state & CLKED))
 1260                 || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) )
 1261                 i ^= 1;
 1262 
 1263         if (up) {       /* break: key released */
 1264                 action = kbd->kb_lastact[keycode];
 1265                 kbd->kb_lastact[keycode] = NOP;
 1266                 switch (action) {
 1267                 case LSHA:
 1268                         if (state & SHIFTAON) {
 1269                                 set_lockkey_state(kbd, state, ALK);
 1270                                 state &= ~ALKDOWN;
 1271                         }
 1272                         action = LSH;
 1273                         /* FALL THROUGH */
 1274                 case LSH:
 1275                         state &= ~SHIFTS1;
 1276                         break;
 1277                 case RSHA:
 1278                         if (state & SHIFTAON) {
 1279                                 set_lockkey_state(kbd, state, ALK);
 1280                                 state &= ~ALKDOWN;
 1281                         }
 1282                         action = RSH;
 1283                         /* FALL THROUGH */
 1284                 case RSH:
 1285                         state &= ~SHIFTS2;
 1286                         break;
 1287                 case LCTRA:
 1288                         if (state & SHIFTAON) {
 1289                                 set_lockkey_state(kbd, state, ALK);
 1290                                 state &= ~ALKDOWN;
 1291                         }
 1292                         action = LCTR;
 1293                         /* FALL THROUGH */
 1294                 case LCTR:
 1295                         state &= ~CTLS1;
 1296                         break;
 1297                 case RCTRA:
 1298                         if (state & SHIFTAON) {
 1299                                 set_lockkey_state(kbd, state, ALK);
 1300                                 state &= ~ALKDOWN;
 1301                         }
 1302                         action = RCTR;
 1303                         /* FALL THROUGH */
 1304                 case RCTR:
 1305                         state &= ~CTLS2;
 1306                         break;
 1307                 case LALTA:
 1308                         if (state & SHIFTAON) {
 1309                                 set_lockkey_state(kbd, state, ALK);
 1310                                 state &= ~ALKDOWN;
 1311                         }
 1312                         action = LALT;
 1313                         /* FALL THROUGH */
 1314                 case LALT:
 1315                         state &= ~ALTS1;
 1316                         break;
 1317                 case RALTA:
 1318                         if (state & SHIFTAON) {
 1319                                 set_lockkey_state(kbd, state, ALK);
 1320                                 state &= ~ALKDOWN;
 1321                         }
 1322                         action = RALT;
 1323                         /* FALL THROUGH */
 1324                 case RALT:
 1325                         state &= ~ALTS2;
 1326                         break;
 1327                 case ASH:
 1328                         state &= ~AGRS1;
 1329                         break;
 1330                 case META:
 1331                         state &= ~METAS1;
 1332                         break;
 1333                 case NLK:
 1334                         state &= ~NLKDOWN;
 1335                         break;
 1336                 case CLK:
 1337                         state &= ~CLKDOWN;
 1338                         break;
 1339                 case SLK:
 1340                         state &= ~SLKDOWN;
 1341                         break;
 1342                 case ALK:
 1343                         state &= ~ALKDOWN;
 1344                         break;
 1345                 case NOP:
 1346                         /* release events of regular keys are not reported */
 1347                         *shiftstate &= ~SHIFTAON;
 1348                         return (NOKEY);
 1349                 }
 1350                 *shiftstate = state & ~SHIFTAON;
 1351                 return (SPCLKEY | RELKEY | action);
 1352         } else {        /* make: key pressed */
 1353                 action = key->map[i];
 1354                 state &= ~SHIFTAON;
 1355                 if (key->spcl & (0x80 >> i)) {
 1356                         /* special keys */
 1357                         if (kbd->kb_lastact[keycode] == NOP)
 1358                                 kbd->kb_lastact[keycode] = action;
 1359                         if (kbd->kb_lastact[keycode] != action)
 1360                                 action = NOP;
 1361                         switch (action) {
 1362                         /* LOCKING KEYS */
 1363                         case NLK:
 1364                                 set_lockkey_state(kbd, state, NLK);
 1365                                 break;
 1366                         case CLK:
 1367                                 set_lockkey_state(kbd, state, CLK);
 1368                                 break;
 1369                         case SLK:
 1370                                 set_lockkey_state(kbd, state, SLK);
 1371                                 break;
 1372                         case ALK:
 1373                                 set_lockkey_state(kbd, state, ALK);
 1374                                 break;
 1375                         /* NON-LOCKING KEYS */
 1376                         case SPSC: case RBT:  case SUSP: case STBY:
 1377                         case DBG:  case NEXT: case PREV: case PNC:
 1378                         case HALT: case PDWN:
 1379                                 *accents = 0;
 1380                                 break;
 1381                         case BTAB:
 1382                                 *accents = 0;
 1383                                 action |= BKEY;
 1384                                 break;
 1385                         case LSHA:
 1386                                 state |= SHIFTAON;
 1387                                 action = LSH;
 1388                                 /* FALL THROUGH */
 1389                         case LSH:
 1390                                 state |= SHIFTS1;
 1391                                 break;
 1392                         case RSHA:
 1393                                 state |= SHIFTAON;
 1394                                 action = RSH;
 1395                                 /* FALL THROUGH */
 1396                         case RSH:
 1397                                 state |= SHIFTS2;
 1398                                 break;
 1399                         case LCTRA:
 1400                                 state |= SHIFTAON;
 1401                                 action = LCTR;
 1402                                 /* FALL THROUGH */
 1403                         case LCTR:
 1404                                 state |= CTLS1;
 1405                                 break;
 1406                         case RCTRA:
 1407                                 state |= SHIFTAON;
 1408                                 action = RCTR;
 1409                                 /* FALL THROUGH */
 1410                         case RCTR:
 1411                                 state |= CTLS2;
 1412                                 break;
 1413                         case LALTA:
 1414                                 state |= SHIFTAON;
 1415                                 action = LALT;
 1416                                 /* FALL THROUGH */
 1417                         case LALT:
 1418                                 state |= ALTS1;
 1419                                 break;
 1420                         case RALTA:
 1421                                 state |= SHIFTAON;
 1422                                 action = RALT;
 1423                                 /* FALL THROUGH */
 1424                         case RALT:
 1425                                 state |= ALTS2;
 1426                                 break;
 1427                         case ASH:
 1428                                 state |= AGRS1;
 1429                                 break;
 1430                         case META:
 1431                                 state |= METAS1;
 1432                                 break;
 1433                         case NOP:
 1434                                 *shiftstate = state;
 1435                                 return (NOKEY);
 1436                         default:
 1437                                 /* is this an accent (dead) key? */
 1438                                 *shiftstate = state;
 1439                                 if (action >= F_ACC && action <= L_ACC) {
 1440                                         action = save_accent_key(kbd, action,
 1441                                                                  accents);
 1442                                         switch (action) {
 1443                                         case NOKEY:
 1444                                         case ERRKEY:
 1445                                                 return (action);
 1446                                         default:
 1447                                                 if (state & METAS)
 1448                                                         return (action | MKEY);
 1449                                                 else
 1450                                                         return (action);
 1451                                         }
 1452                                         /* NOT REACHED */
 1453                                 }
 1454                                 /* other special keys */
 1455                                 if (*accents > 0) {
 1456                                         *accents = 0;
 1457                                         return (ERRKEY);
 1458                                 }
 1459                                 if (action >= F_FN && action <= L_FN)
 1460                                         action |= FKEY;
 1461                                 /* XXX: return fkey string for the FKEY? */
 1462                                 return (SPCLKEY | action);
 1463                         }
 1464                         *shiftstate = state;
 1465                         return (SPCLKEY | action);
 1466                 } else {
 1467                         /* regular keys */
 1468                         kbd->kb_lastact[keycode] = NOP;
 1469                         *shiftstate = state;
 1470                         if (*accents > 0) {
 1471                                 /* make an accented char */
 1472                                 action = make_accent_char(kbd, action, accents);
 1473                                 if (action == ERRKEY)
 1474                                         return (action);
 1475                         }
 1476                         if (state & METAS)
 1477                                 action |= MKEY;
 1478                         return (action);
 1479                 }
 1480         }
 1481         /* NOT REACHED */
 1482 }
 1483 
 1484 void
 1485 kbd_ev_event(keyboard_t *kbd, uint16_t type, uint16_t code, int32_t value)
 1486 {
 1487         int delay[2], led = 0, leds, oleds;
 1488 
 1489         if (type == EV_LED) {
 1490                 leds = oleds = KBD_LED_VAL(kbd);
 1491                 switch (code) {
 1492                 case LED_CAPSL:
 1493                         led = CLKED;
 1494                         break;
 1495                 case LED_NUML:
 1496                         led = NLKED;
 1497                         break;
 1498                 case LED_SCROLLL:
 1499                         led = SLKED;
 1500                         break;
 1501                 }
 1502 
 1503                 if (value)
 1504                         leds |= led;
 1505                 else
 1506                         leds &= ~led;
 1507 
 1508                 if (leds != oleds)
 1509                         kbdd_ioctl(kbd, KDSETLED, (caddr_t)&leds);
 1510 
 1511         } else if (type == EV_REP && code == REP_DELAY) {
 1512                 delay[0] = value;
 1513                 delay[1] = kbd->kb_delay2;
 1514                 kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
 1515         } else if (type == EV_REP && code == REP_PERIOD) {
 1516                 delay[0] = kbd->kb_delay1;
 1517                 delay[1] = value;
 1518                 kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
 1519         }
 1520 }
 1521 
 1522 static void
 1523 kbd_drv_init(void)
 1524 {
 1525         const keyboard_driver_t **list;
 1526         const keyboard_driver_t *p;
 1527 
 1528         SET_FOREACH(list, kbddriver_set) {
 1529                 p = *list;
 1530                 if (p->kbdsw->get_fkeystr == NULL)
 1531                         p->kbdsw->get_fkeystr = genkbd_get_fkeystr;
 1532                 if (p->kbdsw->diag == NULL)
 1533                         p->kbdsw->diag = genkbd_diag;
 1534         }
 1535 }
 1536 
 1537 SYSINIT(kbd_drv_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, kbd_drv_init, NULL);

Cache object: 1f7888f43a66636600b99396a9b70da1


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