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

Cache object: 3f52d1e393a96db0a09eb0c7ee8fb5cd


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