LCOV - code coverage report
Current view: top level - dev/wscons - wskbd.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 736 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: wskbd.c,v 1.91 2018/04/18 10:24:32 mpi Exp $ */
       2             : /* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
       6             :  *
       7             :  * Keysym translator:
       8             :  * Contributed to The NetBSD Foundation by Juergen Hannken-Illjes.
       9             :  *
      10             :  * Redistribution and use in source and binary forms, with or without
      11             :  * modification, are permitted provided that the following conditions
      12             :  * are met:
      13             :  * 1. Redistributions of source code must retain the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer.
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  * 3. All advertising materials mentioning features or use of this software
      19             :  *    must display the following acknowledgement:
      20             :  *      This product includes software developed by Christopher G. Demetriou
      21             :  *      for the NetBSD Project.
      22             :  * 4. The name of the author may not be used to endorse or promote products
      23             :  *    derived from this software without specific prior written permission
      24             :  *
      25             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      26             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      27             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      28             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      29             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      30             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      31             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      32             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      33             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      34             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      35             :  */
      36             : 
      37             : /*
      38             :  * Copyright (c) 1992, 1993
      39             :  *      The Regents of the University of California.  All rights reserved.
      40             :  *
      41             :  * This software was developed by the Computer Systems Engineering group
      42             :  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
      43             :  * contributed to Berkeley.
      44             :  *
      45             :  * All advertising materials mentioning features or use of this software
      46             :  * must display the following acknowledgement:
      47             :  *      This product includes software developed by the University of
      48             :  *      California, Lawrence Berkeley Laboratory.
      49             :  *
      50             :  * Redistribution and use in source and binary forms, with or without
      51             :  * modification, are permitted provided that the following conditions
      52             :  * are met:
      53             :  * 1. Redistributions of source code must retain the above copyright
      54             :  *    notice, this list of conditions and the following disclaimer.
      55             :  * 2. Redistributions in binary form must reproduce the above copyright
      56             :  *    notice, this list of conditions and the following disclaimer in the
      57             :  *    documentation and/or other materials provided with the distribution.
      58             :  * 3. Neither the name of the University nor the names of its contributors
      59             :  *    may be used to endorse or promote products derived from this software
      60             :  *    without specific prior written permission.
      61             :  *
      62             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      63             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      64             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      65             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      66             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      67             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      68             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      69             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      70             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      71             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      72             :  * SUCH DAMAGE.
      73             :  *
      74             :  *      @(#)kbd.c       8.2 (Berkeley) 10/30/93
      75             :  */
      76             : 
      77             : /*
      78             :  * Keyboard driver (/dev/wskbd*).  Translates incoming bytes to ASCII or
      79             :  * to `wscons_events' and passes them up to the appropriate reader.
      80             :  */
      81             : 
      82             : #include <sys/param.h>
      83             : #include <sys/conf.h>
      84             : #include <sys/device.h>
      85             : #include <sys/ioctl.h>
      86             : #include <sys/kernel.h>
      87             : #include <sys/proc.h>
      88             : #include <sys/syslog.h>
      89             : #include <sys/systm.h>
      90             : #include <sys/timeout.h>
      91             : #include <sys/malloc.h>
      92             : #include <sys/tty.h>
      93             : #include <sys/signalvar.h>
      94             : #include <sys/errno.h>
      95             : #include <sys/fcntl.h>
      96             : #include <sys/vnode.h>
      97             : #include <sys/poll.h>
      98             : 
      99             : #include <ddb/db_var.h>
     100             : 
     101             : #include <dev/wscons/wscons_features.h>
     102             : #include <dev/wscons/wsconsio.h>
     103             : #include <dev/wscons/wskbdvar.h>
     104             : #include <dev/wscons/wsksymdef.h>
     105             : #include <dev/wscons/wsksymvar.h>
     106             : #include <dev/wscons/wsdisplayvar.h>
     107             : #include <dev/wscons/wseventvar.h>
     108             : #include <dev/wscons/wscons_callbacks.h>
     109             : 
     110             : #include "audio.h"            /* NAUDIO (mixer tuning) */
     111             : #include "wsdisplay.h"
     112             : #include "wskbd.h"
     113             : #include "wsmux.h"
     114             : 
     115             : #ifdef WSKBD_DEBUG
     116             : #define DPRINTF(x)      if (wskbddebug) printf x
     117             : int     wskbddebug = 0;
     118             : #else
     119             : #define DPRINTF(x)
     120             : #endif
     121             : 
     122             : #include <dev/wscons/wsmuxvar.h>
     123             : 
     124             : struct wskbd_internal {
     125             :         const struct wskbd_consops *t_consops;
     126             :         void    *t_consaccesscookie;
     127             : 
     128             :         int     t_modifiers;
     129             :         int     t_composelen;           /* remaining entries in t_composebuf */
     130             :         keysym_t t_composebuf[2];
     131             : 
     132             :         int     t_flags;
     133             : #define WSKFL_METAESC 1
     134             : 
     135             : #define MAXKEYSYMSPERKEY 2 /* ESC <key> at max */
     136             :         keysym_t t_symbols[MAXKEYSYMSPERKEY];
     137             : 
     138             :         struct wskbd_softc *t_sc;       /* back pointer */
     139             : 
     140             :         struct wskbd_mapdata t_keymap;  /* translation map table and
     141             :                                            current layout */
     142             : };
     143             : 
     144             : struct wskbd_softc {
     145             :         struct wsevsrc  sc_base;
     146             : 
     147             :         struct wskbd_internal *id;
     148             : 
     149             :         const struct wskbd_accessops *sc_accessops;
     150             :         void *sc_accesscookie;
     151             : 
     152             :         int     sc_ledstate;
     153             : 
     154             :         int     sc_isconsole;
     155             : 
     156             :         struct wskbd_bell_data sc_bell_data;
     157             :         struct wskbd_keyrepeat_data sc_keyrepeat_data;
     158             : 
     159             :         int     sc_repeating;           /* we've called timeout() */
     160             :         int     sc_repkey;
     161             :         struct timeout sc_repeat_ch;
     162             :         u_int   sc_repeat_type;
     163             :         int     sc_repeat_value;
     164             : 
     165             :         int     sc_translating;         /* xlate to chars for emulation */
     166             : 
     167             :         int     sc_maplen;              /* number of entries in sc_map */
     168             :         struct wscons_keymap *sc_map;   /* current translation map */
     169             : 
     170             :         int     sc_refcnt;
     171             :         u_char  sc_dying;               /* device is being detached */
     172             : };
     173             : 
     174             : #define MOD_SHIFT_L             (1 << 0)
     175             : #define MOD_SHIFT_R             (1 << 1)
     176             : #define MOD_SHIFTLOCK           (1 << 2)
     177             : #define MOD_CAPSLOCK            (1 << 3)
     178             : #define MOD_CONTROL_L           (1 << 4)
     179             : #define MOD_CONTROL_R           (1 << 5)
     180             : #define MOD_META_L              (1 << 6)
     181             : #define MOD_META_R              (1 << 7)
     182             : #define MOD_MODESHIFT           (1 << 8)
     183             : #define MOD_NUMLOCK             (1 << 9)
     184             : #define MOD_COMPOSE             (1 << 10)
     185             : #define MOD_HOLDSCREEN          (1 << 11)
     186             : #define MOD_COMMAND             (1 << 12)
     187             : #define MOD_COMMAND1            (1 << 13)
     188             : #define MOD_COMMAND2            (1 << 14)
     189             : #define MOD_MODELOCK            (1 << 15)
     190             : 
     191             : #define MOD_ANYSHIFT            (MOD_SHIFT_L | MOD_SHIFT_R | MOD_SHIFTLOCK)
     192             : #define MOD_ANYCONTROL          (MOD_CONTROL_L | MOD_CONTROL_R)
     193             : #define MOD_ANYMETA             (MOD_META_L | MOD_META_R)
     194             : #define MOD_ANYLED              (MOD_SHIFTLOCK | MOD_CAPSLOCK | MOD_NUMLOCK | \
     195             :                                  MOD_COMPOSE | MOD_HOLDSCREEN)
     196             : 
     197             : #define MOD_ONESET(id, mask)    (((id)->t_modifiers & (mask)) != 0)
     198             : #define MOD_ALLSET(id, mask)    (((id)->t_modifiers & (mask)) == (mask))
     199             : 
     200             : keysym_t ksym_upcase(keysym_t);
     201             : 
     202             : int     wskbd_match(struct device *, void *, void *);
     203             : void    wskbd_attach(struct device *, struct device *, void *);
     204             : int     wskbd_detach(struct device *, int);
     205             : int     wskbd_activate(struct device *, int);
     206             : 
     207             : int     wskbd_displayioctl(struct device *, u_long, caddr_t, int, struct proc *);
     208             : 
     209             : void    update_leds(struct wskbd_internal *);
     210             : void    update_modifier(struct wskbd_internal *, u_int, int, int);
     211             : int     internal_command(struct wskbd_softc *, u_int *, keysym_t, keysym_t);
     212             : int     wskbd_translate(struct wskbd_internal *, u_int, int);
     213             : int     wskbd_enable(struct wskbd_softc *, int);
     214             : void    wskbd_debugger(struct wskbd_softc *);
     215             : #if NWSDISPLAY > 0
     216             : void    change_displayparam(struct wskbd_softc *, int, int, int);
     217             : #endif
     218             : 
     219             : int     wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int,
     220             :             struct proc *);
     221             : void    wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value);
     222             : 
     223             : #if NWSMUX > 0
     224             : int     wskbd_mux_open(struct wsevsrc *, struct wseventvar *);
     225             : int     wskbd_mux_close(struct wsevsrc *);
     226             : #else
     227             : #define wskbd_mux_open NULL
     228             : #define wskbd_mux_close NULL
     229             : #endif
     230             : 
     231             : int     wskbd_do_open(struct wskbd_softc *, struct wseventvar *);
     232             : int     wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *);
     233             : 
     234             : int     (*wskbd_get_backlight)(struct wskbd_backlight *);
     235             : int     (*wskbd_set_backlight)(struct wskbd_backlight *);
     236             : 
     237             : struct cfdriver wskbd_cd = {
     238             :         NULL, "wskbd", DV_TTY
     239             : };
     240             : 
     241             : struct cfattach wskbd_ca = {
     242             :         sizeof (struct wskbd_softc), wskbd_match, wskbd_attach,
     243             :         wskbd_detach, wskbd_activate
     244             : };
     245             : 
     246             : #if defined(__i386__) || defined(__amd64__)
     247             : extern int kbd_reset;
     248             : #endif
     249             : 
     250             : #ifndef WSKBD_DEFAULT_BELL_PITCH
     251             : #define WSKBD_DEFAULT_BELL_PITCH        400     /* 400Hz */
     252             : #endif
     253             : #ifndef WSKBD_DEFAULT_BELL_PERIOD
     254             : #define WSKBD_DEFAULT_BELL_PERIOD       100     /* 100ms */
     255             : #endif
     256             : #ifndef WSKBD_DEFAULT_BELL_VOLUME
     257             : #define WSKBD_DEFAULT_BELL_VOLUME       50      /* 50% volume */
     258             : #endif
     259             : 
     260             : struct wskbd_bell_data wskbd_default_bell_data = {
     261             :         WSKBD_BELL_DOALL,
     262             :         WSKBD_DEFAULT_BELL_PITCH,
     263             :         WSKBD_DEFAULT_BELL_PERIOD,
     264             :         WSKBD_DEFAULT_BELL_VOLUME,
     265             : };
     266             : 
     267             : #ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1
     268             : #define WSKBD_DEFAULT_KEYREPEAT_DEL1    400     /* 400ms to start repeating */
     269             : #endif
     270             : #ifndef WSKBD_DEFAULT_KEYREPEAT_DELN
     271             : #define WSKBD_DEFAULT_KEYREPEAT_DELN    100     /* 100ms to between repeats */
     272             : #endif
     273             : 
     274             : struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = {
     275             :         WSKBD_KEYREPEAT_DOALL,
     276             :         WSKBD_DEFAULT_KEYREPEAT_DEL1,
     277             :         WSKBD_DEFAULT_KEYREPEAT_DELN,
     278             : };
     279             : 
     280             : #if NWSMUX > 0 || NWSDISPLAY > 0
     281             : struct wssrcops wskbd_srcops = {
     282             :         WSMUX_KBD,
     283             :         wskbd_mux_open, wskbd_mux_close, wskbd_do_ioctl,
     284             :         wskbd_displayioctl,
     285             : #if NWSDISPLAY > 0
     286             :         wskbd_set_display
     287             : #else
     288             :         NULL
     289             : #endif
     290             : };
     291             : #endif
     292             : 
     293             : #if NWSDISPLAY > 0
     294             : void wskbd_repeat(void *v);
     295             : #endif
     296             : 
     297             : static int wskbd_console_initted;
     298             : static struct wskbd_softc *wskbd_console_device;
     299             : static struct wskbd_internal wskbd_console_data;
     300             : 
     301             : void    wskbd_update_layout(struct wskbd_internal *, kbd_t);
     302             : 
     303             : #if NAUDIO > 0
     304             : extern int wskbd_set_mixervolume(long, long);
     305             : #endif
     306             : 
     307             : void
     308           0 : wskbd_update_layout(struct wskbd_internal *id, kbd_t enc)
     309             : {
     310           0 :         if (enc & KB_METAESC)
     311           0 :                 id->t_flags |= WSKFL_METAESC;
     312             :         else
     313           0 :                 id->t_flags &= ~WSKFL_METAESC;
     314             : 
     315           0 :         id->t_keymap.layout = enc;
     316           0 : }
     317             : 
     318             : /*
     319             :  * Print function (for parent devices).
     320             :  */
     321             : int
     322           0 : wskbddevprint(void *aux, const char *pnp)
     323             : {
     324             : #if 0
     325             :         struct wskbddev_attach_args *ap = aux;
     326             : #endif
     327             : 
     328           0 :         if (pnp)
     329           0 :                 printf("wskbd at %s", pnp);
     330             : #if 0
     331             :         printf(" console %d", ap->console);
     332             : #endif
     333             : 
     334           0 :         return (UNCONF);
     335             : }
     336             : 
     337             : int
     338           0 : wskbd_match(struct device *parent, void *match, void *aux)
     339             : {
     340           0 :         struct cfdata *cf = match;
     341           0 :         struct wskbddev_attach_args *ap = aux;
     342             : 
     343           0 :         if (cf->wskbddevcf_console != WSKBDDEVCF_CONSOLE_UNK) {
     344             :                 /*
     345             :                  * If console-ness of device specified, either match
     346             :                  * exactly (at high priority), or fail.
     347             :                  */
     348           0 :                 if (cf->wskbddevcf_console != 0 && ap->console != 0)
     349           0 :                         return (10);
     350             :                 else
     351           0 :                         return (0);
     352             :         }
     353             : 
     354             :         /* If console-ness unspecified, it wins. */
     355           0 :         return (1);
     356           0 : }
     357             : 
     358             : void
     359           0 : wskbd_attach(struct device *parent, struct device *self, void *aux)
     360             : {
     361           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)self;
     362           0 :         struct wskbddev_attach_args *ap = aux;
     363             :         kbd_t layout;
     364             : #if NWSMUX > 0
     365             :         struct wsmux_softc *wsmux_sc = NULL;
     366             :         int mux, error;
     367             : #endif
     368             : 
     369           0 :         sc->sc_isconsole = ap->console;
     370             : 
     371             : #if NWSMUX > 0 || NWSDISPLAY > 0
     372           0 :         sc->sc_base.me_ops = &wskbd_srcops;
     373             : #endif
     374             : #if NWSMUX > 0
     375           0 :         mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux;
     376           0 :         if (mux >= 0)
     377           0 :                 wsmux_sc = wsmux_getmux(mux);
     378             : #endif  /* NWSMUX > 0 */
     379             : 
     380           0 :         if (ap->console) {
     381           0 :                 sc->id = &wskbd_console_data;
     382           0 :         } else {
     383           0 :                 sc->id = malloc(sizeof(struct wskbd_internal),
     384             :                     M_DEVBUF, M_WAITOK | M_ZERO);
     385           0 :                 bcopy(ap->keymap, &sc->id->t_keymap, sizeof(sc->id->t_keymap));
     386             :         }
     387             : 
     388             : #if NWSDISPLAY > 0
     389           0 :         timeout_set(&sc->sc_repeat_ch, wskbd_repeat, sc);
     390             : #endif
     391             : 
     392           0 :         sc->id->t_sc = sc;
     393             : 
     394           0 :         sc->sc_accessops = ap->accessops;
     395           0 :         sc->sc_accesscookie = ap->accesscookie;
     396           0 :         sc->sc_repeating = 0;
     397           0 :         sc->sc_translating = 1;
     398           0 :         sc->sc_ledstate = -1; /* force update */
     399             : 
     400             :         /*
     401             :          * If this layout is the default choice of the driver (i.e. the
     402             :          * driver doesn't know better), pick the existing layout of the
     403             :          * current mux, if any.
     404             :          */
     405           0 :         layout = sc->id->t_keymap.layout;
     406             : #if NWSMUX > 0
     407           0 :         if (layout & KB_DEFAULT) {
     408           0 :                 if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE)
     409           0 :                         layout = wsmux_get_layout(wsmux_sc);
     410             :         }
     411             : #endif
     412           0 :         for (;;) {
     413           0 :                 if (wskbd_load_keymap(&sc->id->t_keymap, layout, &sc->sc_map,
     414           0 :                     &sc->sc_maplen) == 0)
     415             :                         break;
     416             : #if NWSMUX > 0
     417           0 :                 if (layout == sc->id->t_keymap.layout)
     418           0 :                         panic("cannot load keymap");
     419           0 :                 if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE) {
     420           0 :                         printf("\n%s: cannot load keymap, "
     421             :                             "falling back to default\n%s",
     422           0 :                             sc->sc_base.me_dv.dv_xname,
     423             :                             sc->sc_base.me_dv.dv_xname);
     424           0 :                         layout = wsmux_get_layout(wsmux_sc);
     425             :                 } else
     426             : #endif
     427           0 :                         panic("cannot load keymap");
     428             :         }
     429           0 :         wskbd_update_layout(sc->id, layout);
     430             : 
     431             :         /* set default bell and key repeat data */
     432           0 :         sc->sc_bell_data = wskbd_default_bell_data;
     433           0 :         sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data;
     434             : 
     435           0 :         if (ap->console) {
     436           0 :                 KASSERT(wskbd_console_initted); 
     437           0 :                 KASSERT(wskbd_console_device == NULL);
     438             : 
     439           0 :                 wskbd_console_device = sc;
     440             : 
     441           0 :                 printf(": console keyboard");
     442             : 
     443             : #if NWSDISPLAY > 0
     444           0 :                 wsdisplay_set_console_kbd(&sc->sc_base); /* sets sc_displaydv */
     445           0 :                 if (sc->sc_displaydv != NULL)
     446           0 :                         printf(", using %s", sc->sc_displaydv->dv_xname);
     447             : #endif
     448             :         }
     449             : 
     450             : #if NWSMUX > 0
     451             :         /* Ignore mux for console; it always goes to the console mux. */
     452           0 :         if (wsmux_sc != NULL && ap->console == 0) {
     453           0 :                 printf(" mux %d\n", mux);
     454           0 :                 error = wsmux_attach_sc(wsmux_sc, &sc->sc_base);
     455           0 :                 if (error)
     456           0 :                         printf("%s: attach error=%d\n",
     457           0 :                             sc->sc_base.me_dv.dv_xname, error);
     458             : 
     459             :                 /*
     460             :                  * Try and set this encoding as the mux default if it
     461             :                  * hasn't any yet, and if this is not a driver default
     462             :                  * layout (i.e. parent driver pretends to know better).
     463             :                  * Note that wsmux_set_layout() rejects layouts with
     464             :                  * KB_DEFAULT set.
     465             :                  */
     466           0 :                 if (wsmux_get_layout(wsmux_sc) == KB_NONE)
     467           0 :                         wsmux_set_layout(wsmux_sc, layout);
     468             :         } else
     469             : #endif
     470           0 :         printf("\n");
     471             : 
     472             : #if NWSDISPLAY > 0 && NWSMUX == 0
     473             :         if (ap->console == 0) {
     474             :                 /*
     475             :                  * In the non-wsmux world, always connect wskbd0 and wsdisplay0
     476             :                  * together.
     477             :                  */
     478             :                 extern struct cfdriver wsdisplay_cd;
     479             : 
     480             :                 if (wsdisplay_cd.cd_ndevs != 0 && self->dv_unit == 0) {
     481             :                         if (wskbd_set_display(self,
     482             :                             wsdisplay_cd.cd_devs[0]) == 0)
     483             :                                 wsdisplay_set_kbd(wsdisplay_cd.cd_devs[0],
     484             :                                     (struct wsevsrc *)sc);
     485             :                 }
     486             :         }
     487             : #endif
     488           0 : }
     489             : 
     490             : void    
     491           0 : wskbd_cnattach(const struct wskbd_consops *consops, void *conscookie,
     492             :     const struct wskbd_mapdata *mapdata)
     493             : {
     494             : 
     495           0 :         KASSERT(!wskbd_console_initted);
     496             : 
     497           0 :         bcopy(mapdata, &wskbd_console_data.t_keymap, sizeof(*mapdata));
     498           0 :         wskbd_update_layout(&wskbd_console_data, mapdata->layout);
     499             : 
     500           0 :         wskbd_console_data.t_consops = consops;
     501           0 :         wskbd_console_data.t_consaccesscookie = conscookie;
     502             : 
     503             : #if NWSDISPLAY > 0
     504           0 :         wsdisplay_set_cons_kbd(wskbd_cngetc, wskbd_cnpollc, wskbd_cnbell);
     505             : #endif
     506             : 
     507           0 :         wskbd_console_initted = 1;
     508           0 : }
     509             : 
     510             : void
     511           0 : wskbd_cndetach(void)
     512             : {
     513           0 :         KASSERT(wskbd_console_initted);
     514             : 
     515           0 :         wskbd_console_data.t_keymap.keydesc = NULL;
     516           0 :         wskbd_console_data.t_keymap.layout = KB_NONE;
     517             : 
     518           0 :         wskbd_console_data.t_consops = NULL;
     519           0 :         wskbd_console_data.t_consaccesscookie = NULL;
     520             : 
     521             : #if NWSDISPLAY > 0
     522           0 :         wsdisplay_unset_cons_kbd();
     523             : #endif
     524             : 
     525           0 :         wskbd_console_device = NULL;
     526           0 :         wskbd_console_initted = 0;
     527           0 : }
     528             : 
     529             : #if NWSDISPLAY > 0
     530             : void
     531           0 : wskbd_repeat(void *v)
     532             : {
     533           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)v;
     534           0 :         int s = spltty();
     535             : 
     536           0 :         if (sc->sc_repeating == 0) {
     537             :                 /*
     538             :                  * race condition: a "key up" event came in when wskbd_repeat()
     539             :                  * was already called but not yet spltty()'d
     540             :                  */
     541           0 :                 splx(s);
     542           0 :                 return;
     543             :         }
     544           0 :         if (sc->sc_translating) {
     545             :                 /* deliver keys */
     546           0 :                 if (sc->sc_displaydv != NULL)
     547           0 :                         wsdisplay_kbdinput(sc->sc_displaydv,
     548           0 :                             sc->id->t_keymap.layout,
     549           0 :                             sc->id->t_symbols, sc->sc_repeating);
     550             :         } else {
     551             :                 /* queue event */
     552           0 :                 wskbd_deliver_event(sc, sc->sc_repeat_type,
     553           0 :                     sc->sc_repeat_value);
     554             :         }
     555           0 :         if (sc->sc_keyrepeat_data.delN != 0)
     556           0 :                 timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.delN);
     557           0 :         splx(s);
     558           0 : }
     559             : #endif
     560             : 
     561             : int
     562           0 : wskbd_activate(struct device *self, int act)
     563             : {
     564           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)self;
     565             : 
     566           0 :         if (act == DVACT_DEACTIVATE)
     567           0 :                 sc->sc_dying = 1;
     568           0 :         return (0);
     569             : }
     570             : 
     571             : /*
     572             :  * Detach a keyboard.  To keep track of users of the softc we keep
     573             :  * a reference count that's incremented while inside, e.g., read.
     574             :  * If the keyboard is active and the reference count is > 0 (0 is the
     575             :  * normal state) we post an event and then wait for the process
     576             :  * that had the reference to wake us up again.  Then we blow away the
     577             :  * vnode and return (which will deallocate the softc).
     578             :  */
     579             : int
     580           0 : wskbd_detach(struct device  *self, int flags)
     581             : {
     582           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)self;
     583             :         struct wseventvar *evar;
     584             :         int maj, mn;
     585             :         int s;
     586             : 
     587             : #if NWSMUX > 0
     588             :         /* Tell parent mux we're leaving. */
     589           0 :         if (sc->sc_base.me_parent != NULL)
     590           0 :                 wsmux_detach_sc(&sc->sc_base);
     591             : #endif
     592             : 
     593             : #if NWSDISPLAY > 0
     594           0 :         if (sc->sc_repeating) {
     595           0 :                 sc->sc_repeating = 0;
     596           0 :                 timeout_del(&sc->sc_repeat_ch);
     597           0 :         }
     598             : #endif
     599             : 
     600           0 :         if (sc->sc_isconsole) {
     601           0 :                 KASSERT(wskbd_console_device == sc);
     602           0 :                 wskbd_cndetach();
     603           0 :         }
     604             : 
     605           0 :         evar = sc->sc_base.me_evp;
     606           0 :         if (evar != NULL && evar->io != NULL) {
     607           0 :                 s = spltty();
     608           0 :                 if (--sc->sc_refcnt >= 0) {
     609             :                         /* Wake everyone by generating a dummy event. */
     610           0 :                         if (++evar->put >= WSEVENT_QSIZE)
     611           0 :                                 evar->put = 0;
     612           0 :                         WSEVENT_WAKEUP(evar);
     613             :                         /* Wait for processes to go away. */
     614           0 :                         if (tsleep(sc, PZERO, "wskdet", hz * 60))
     615           0 :                                 printf("wskbd_detach: %s didn't detach\n",
     616           0 :                                        sc->sc_base.me_dv.dv_xname);
     617             :                 }
     618           0 :                 splx(s);
     619           0 :         }
     620             : 
     621           0 :         free(sc->sc_map, M_DEVBUF,
     622           0 :             sc->sc_maplen * sizeof(struct wscons_keymap));
     623             : 
     624             :         /* locate the major number */
     625           0 :         for (maj = 0; maj < nchrdev; maj++)
     626           0 :                 if (cdevsw[maj].d_open == wskbdopen)
     627             :                         break;
     628             : 
     629             :         /* Nuke the vnodes for any open instances. */
     630           0 :         mn = self->dv_unit;
     631           0 :         vdevgone(maj, mn, mn, VCHR);
     632             : 
     633           0 :         return (0);
     634             : }
     635             : 
     636             : void
     637           0 : wskbd_input(struct device *dev, u_int type, int value)
     638             : {
     639           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)dev; 
     640             : #if NWSDISPLAY > 0
     641             :         int num;
     642             : #endif
     643             : 
     644             : #if NWSDISPLAY > 0
     645           0 :         if (sc->sc_repeating) {
     646           0 :                 sc->sc_repeating = 0;
     647           0 :                 timeout_del(&sc->sc_repeat_ch);
     648           0 :         }
     649             : 
     650             :         /*
     651             :          * If /dev/wskbdN is not connected in event mode translate and
     652             :          * send upstream.
     653             :          */
     654           0 :         if (sc->sc_translating) {
     655             : #ifdef HAVE_BURNER_SUPPORT
     656           0 :                 if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_displaydv != NULL)
     657           0 :                         wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_KBD);
     658             : #endif
     659           0 :                 num = wskbd_translate(sc->id, type, value);
     660           0 :                 if (num > 0) {
     661           0 :                         if (sc->sc_displaydv != NULL) {
     662             : #ifdef HAVE_SCROLLBACK_SUPPORT
     663             :                                 /* XXX - Shift_R+PGUP(release) emits PrtSc */
     664           0 :                                 if (sc->id->t_symbols[0] != KS_Print_Screen) {
     665           0 :                                         wsscrollback(sc->sc_displaydv,
     666             :                                             WSDISPLAY_SCROLL_RESET);
     667           0 :                                 }
     668             : #endif
     669           0 :                                 wsdisplay_kbdinput(sc->sc_displaydv,
     670           0 :                                     sc->id->t_keymap.layout,
     671           0 :                                     sc->id->t_symbols, num);
     672           0 :                         }
     673             : 
     674           0 :                         if (sc->sc_keyrepeat_data.del1 != 0) {
     675           0 :                                 sc->sc_repeating = num;
     676           0 :                                 timeout_add_msec(&sc->sc_repeat_ch,
     677           0 :                                     sc->sc_keyrepeat_data.del1);
     678           0 :                         }
     679             :                 }
     680           0 :                 return;
     681             :         }
     682             : #endif
     683             : 
     684           0 :         wskbd_deliver_event(sc, type, value);
     685             : 
     686             : #if NWSDISPLAY > 0
     687             :         /* Repeat key presses if enabled. */
     688           0 :         if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_keyrepeat_data.del1 != 0) {
     689           0 :                 sc->sc_repeat_type = type;
     690           0 :                 sc->sc_repeat_value = value;
     691           0 :                 sc->sc_repeating = 1;
     692           0 :                 timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1);
     693           0 :         }
     694             : #endif
     695           0 : }
     696             : 
     697             : /*
     698             :  * Keyboard is generating events.  Turn this keystroke into an
     699             :  * event and put it in the queue.  If the queue is full, the
     700             :  * keystroke is lost (sorry!).
     701             :  */
     702             : void
     703           0 : wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value)
     704             : {
     705             :         struct wseventvar *evar;
     706             :         struct wscons_event *ev;
     707             :         int put;
     708             : 
     709           0 :         evar = sc->sc_base.me_evp;
     710             : 
     711           0 :         if (evar == NULL) {
     712             :                 DPRINTF(("wskbd_input: not open\n"));
     713           0 :                 return;
     714             :         }
     715             : 
     716             : #ifdef DIAGNOSTIC
     717           0 :         if (evar->q == NULL) {
     718           0 :                 printf("wskbd_input: evar->q=NULL\n");
     719           0 :                 return;
     720             :         }
     721             : #endif
     722             : 
     723           0 :         put = evar->put;
     724           0 :         ev = &evar->q[put];
     725           0 :         put = (put + 1) % WSEVENT_QSIZE;
     726           0 :         if (put == evar->get) {
     727           0 :                 log(LOG_WARNING, "%s: event queue overflow\n",
     728           0 :                     sc->sc_base.me_dv.dv_xname);
     729           0 :                 return;
     730             :         }
     731           0 :         ev->type = type;
     732           0 :         ev->value = value;
     733           0 :         nanotime(&ev->time);
     734           0 :         evar->put = put;
     735           0 :         WSEVENT_WAKEUP(evar);
     736           0 : }
     737             : 
     738             : #ifdef WSDISPLAY_COMPAT_RAWKBD
     739             : void
     740           0 : wskbd_rawinput(struct device *dev, u_char *buf, int len)
     741             : {
     742             : #if NWSDISPLAY > 0
     743           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)dev;
     744             : 
     745           0 :         if (sc->sc_displaydv != NULL)
     746           0 :                 wsdisplay_rawkbdinput(sc->sc_displaydv, buf, len);
     747             : #endif
     748           0 : }
     749             : #endif /* WSDISPLAY_COMPAT_RAWKBD */
     750             : 
     751             : int
     752           0 : wskbd_enable(struct wskbd_softc *sc, int on)
     753             : {
     754             :         int error;
     755             : 
     756             : #if NWSDISPLAY > 0
     757           0 :         if (sc->sc_displaydv != NULL)
     758           0 :                 return (0);
     759             : 
     760             :         /* Always cancel auto repeat when fiddling with the kbd. */
     761           0 :         if (sc->sc_repeating) {
     762           0 :                 sc->sc_repeating = 0;
     763           0 :                 timeout_del(&sc->sc_repeat_ch);
     764           0 :         }
     765             : #endif
     766             : 
     767           0 :         error = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on);
     768             :         DPRINTF(("wskbd_enable: sc=%p on=%d res=%d\n", sc, on, error));
     769           0 :         return (error);
     770           0 : }
     771             : 
     772             : #if NWSMUX > 0
     773             : int
     774           0 : wskbd_mux_open(struct wsevsrc *me, struct wseventvar *evp)
     775             : {
     776           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)me;
     777             : 
     778           0 :         if (sc->sc_dying)
     779           0 :                 return (EIO);
     780             : 
     781           0 :         if (sc->sc_base.me_evp != NULL)
     782           0 :                 return (EBUSY);
     783             : 
     784           0 :         return (wskbd_do_open(sc, evp));
     785           0 : }
     786             : #endif
     787             : 
     788             : int
     789           0 : wskbdopen(dev_t dev, int flags, int mode, struct proc *p)
     790             : {
     791             :         struct wskbd_softc *sc;
     792             :         struct wseventvar *evar;
     793             :         int unit, error;
     794             : 
     795           0 :         unit = minor(dev);
     796           0 :         if (unit >= wskbd_cd.cd_ndevs ||     /* make sure it was attached */
     797           0 :             (sc = wskbd_cd.cd_devs[unit]) == NULL)
     798           0 :                 return (ENXIO);
     799             : 
     800             : #if NWSMUX > 0
     801             :         DPRINTF(("wskbdopen: %s mux=%p p=%p\n", sc->sc_base.me_dv.dv_xname,
     802             :                  sc->sc_base.me_parent, p));
     803             : #endif
     804             : 
     805           0 :         if (sc->sc_dying)
     806           0 :                 return (EIO);
     807             : 
     808           0 :         if ((flags & (FREAD | FWRITE)) == FWRITE) {
     809             :                 /* Not opening for read, only ioctl is available. */
     810           0 :                 return (0);
     811             :         }
     812             : 
     813             : #if NWSMUX > 0
     814           0 :         if (sc->sc_base.me_parent != NULL) {
     815             :                 /* Grab the keyboard out of the greedy hands of the mux. */
     816             :                 DPRINTF(("wskbdopen: detach\n"));
     817           0 :                 wsmux_detach_sc(&sc->sc_base);
     818           0 :         }
     819             : #endif
     820             : 
     821           0 :         if (sc->sc_base.me_evp != NULL)
     822           0 :                 return (EBUSY);
     823             : 
     824           0 :         evar = &sc->sc_base.me_evar;
     825           0 :         wsevent_init(evar);
     826           0 :         evar->io = p->p_p;
     827             : 
     828           0 :         error = wskbd_do_open(sc, evar);
     829           0 :         if (error) {
     830             :                 DPRINTF(("wskbdopen: %s open failed\n",
     831             :                          sc->sc_base.me_dv.dv_xname));
     832           0 :                 sc->sc_base.me_evp = NULL;
     833           0 :                 wsevent_fini(evar);
     834           0 :         }
     835           0 :         return (error);
     836           0 : }
     837             : 
     838             : int
     839           0 : wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp)
     840             : {
     841           0 :         sc->sc_base.me_evp = evp;
     842           0 :         sc->sc_translating = 0;
     843             : 
     844           0 :         return (wskbd_enable(sc, 1));
     845             : }
     846             : 
     847             : int
     848           0 : wskbdclose(dev_t dev, int flags, int mode, struct proc *p)
     849             : {
     850             :         struct wskbd_softc *sc =
     851           0 :             (struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)];
     852           0 :         struct wseventvar *evar = sc->sc_base.me_evp;
     853             : 
     854           0 :         if (evar == NULL)
     855             :                 /* not open for read */
     856           0 :                 return (0);
     857             : 
     858           0 :         sc->sc_base.me_evp = NULL;
     859           0 :         sc->sc_translating = 1;
     860           0 :         (void)wskbd_enable(sc, 0);
     861           0 :         wsevent_fini(evar);
     862             : 
     863             : #if NWSMUX > 0
     864           0 :         if (sc->sc_base.me_parent == NULL) {
     865             :                 int mux, error;
     866             : 
     867             :                 DPRINTF(("wskbdclose: attach\n"));
     868           0 :                 mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux;
     869           0 :                 if (mux >= 0) {
     870           0 :                         error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base);
     871           0 :                         if (error)
     872           0 :                                 printf("%s: can't attach mux (error=%d)\n",
     873           0 :                                     sc->sc_base.me_dv.dv_xname, error);
     874             :                 }
     875           0 :         }
     876             : #endif
     877             : 
     878           0 :         return (0);
     879           0 : }
     880             : 
     881             : #if NWSMUX > 0
     882             : int
     883           0 : wskbd_mux_close(struct wsevsrc *me)
     884             : {
     885           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)me;
     886             : 
     887           0 :         sc->sc_base.me_evp = NULL;
     888           0 :         sc->sc_translating = 1;
     889           0 :         (void)wskbd_enable(sc, 0);
     890             : 
     891           0 :         return (0);
     892             : }
     893             : #endif
     894             : 
     895             : int
     896           0 : wskbdread(dev_t dev, struct uio *uio, int flags)
     897             : {
     898           0 :         struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
     899             :         int error;
     900             : 
     901           0 :         if (sc->sc_dying)
     902           0 :                 return (EIO);
     903             : 
     904             : #ifdef DIAGNOSTIC
     905           0 :         if (sc->sc_base.me_evp == NULL) {
     906           0 :                 printf("wskbdread: evp == NULL\n");
     907           0 :                 return (EINVAL);
     908             :         }
     909             : #endif
     910             : 
     911           0 :         sc->sc_refcnt++;
     912           0 :         error = wsevent_read(&sc->sc_base.me_evar, uio, flags);
     913           0 :         if (--sc->sc_refcnt < 0) {
     914           0 :                 wakeup(sc);
     915             :                 error = EIO;
     916           0 :         }
     917           0 :         return (error);
     918           0 : }
     919             : 
     920             : int
     921           0 : wskbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
     922             : {
     923           0 :         return (wskbd_do_ioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, flag,p));
     924             : }
     925             : 
     926             : /* A wrapper around the ioctl() workhorse to make reference counting easy. */
     927             : int
     928           0 : wskbd_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag,
     929             :     struct proc *p)
     930             : {
     931           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)dv;
     932             :         int error;
     933             : 
     934           0 :         sc->sc_refcnt++;
     935           0 :         error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p);
     936           0 :         if (--sc->sc_refcnt < 0)
     937           0 :                 wakeup(sc);
     938           0 :         return (error);
     939             : }
     940             : 
     941             : int
     942           0 : wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag,
     943             :      struct proc *p)
     944             : {
     945             :         int error;
     946             : 
     947             :         /*      
     948             :          * Try the generic ioctls that the wskbd interface supports.
     949             :          */
     950           0 :         switch (cmd) {
     951             :         case FIONBIO:           /* we will remove this someday (soon???) */
     952           0 :                 return (0);
     953             : 
     954             :         case FIOASYNC:
     955           0 :                 if (sc->sc_base.me_evp == NULL)
     956           0 :                         return (EINVAL);
     957           0 :                 sc->sc_base.me_evp->async = *(int *)data != 0;
     958           0 :                 return (0);
     959             : 
     960             :         case FIOSETOWN:
     961           0 :                 if (sc->sc_base.me_evp == NULL)
     962           0 :                         return (EINVAL);
     963           0 :                 if (-*(int *)data != sc->sc_base.me_evp->io->ps_pgid &&
     964           0 :                     *(int *)data != sc->sc_base.me_evp->io->ps_pid)
     965           0 :                         return (EPERM);
     966           0 :                 return (0);
     967             :                    
     968             :         case TIOCSPGRP:
     969           0 :                 if (sc->sc_base.me_evp == NULL)
     970           0 :                         return (EINVAL);
     971           0 :                 if (*(int *)data != sc->sc_base.me_evp->io->ps_pgid)
     972           0 :                         return (EPERM);
     973           0 :                 return (0);
     974             :         }
     975             : 
     976             :         /*
     977             :          * Try the keyboard driver for WSKBDIO ioctls.  It returns -1
     978             :          * if it didn't recognize the request.
     979             :          */
     980           0 :         error = wskbd_displayioctl(&sc->sc_base.me_dv, cmd, data, flag, p);
     981           0 :         return (error != -1 ? error : ENOTTY);
     982           0 : }
     983             : 
     984             : /*
     985             :  * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode.
     986             :  * Some of these have no real effect in raw mode, however.
     987             :  */
     988             : int
     989           0 : wskbd_displayioctl(struct device *dev, u_long cmd, caddr_t data, int flag,
     990             :     struct proc *p)
     991             : {
     992           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)dev;
     993             :         struct wskbd_bell_data *ubdp, *kbdp;
     994             :         struct wskbd_keyrepeat_data *ukdp, *kkdp;
     995             :         struct wskbd_map_data *umdp;
     996             :         struct wskbd_encoding_data *uedp;
     997             :         kbd_t enc;
     998             :         void *buf;
     999             :         int len, error;
    1000             :         int count, i;
    1001             : 
    1002           0 :         switch (cmd) {
    1003             :         case WSKBDIO_BELL:
    1004             :         case WSKBDIO_COMPLEXBELL:
    1005             :         case WSKBDIO_SETBELL:
    1006             :         case WSKBDIO_SETKEYREPEAT:
    1007             :         case WSKBDIO_SETDEFAULTKEYREPEAT:
    1008             :         case WSKBDIO_SETMAP:
    1009             :         case WSKBDIO_SETENCODING:
    1010             :         case WSKBDIO_SETBACKLIGHT:
    1011           0 :                 if ((flag & FWRITE) == 0)
    1012           0 :                         return (EACCES);
    1013             :         }
    1014             : 
    1015           0 :         switch (cmd) {
    1016             : #define SETBELL(dstp, srcp, dfltp)                                      \
    1017             :     do {                                                                \
    1018             :         (dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH) ?                \
    1019             :             (srcp)->pitch : (dfltp)->pitch;                               \
    1020             :         (dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD) ?      \
    1021             :             (srcp)->period : (dfltp)->period;                             \
    1022             :         (dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME) ?      \
    1023             :             (srcp)->volume : (dfltp)->volume;                             \
    1024             :         (dstp)->which = WSKBD_BELL_DOALL;                            \
    1025             :     } while (0)
    1026             : 
    1027             :         case WSKBDIO_BELL:
    1028           0 :                 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
    1029           0 :                     WSKBDIO_COMPLEXBELL, (caddr_t)&sc->sc_bell_data, flag, p));
    1030             : 
    1031             :         case WSKBDIO_COMPLEXBELL:
    1032           0 :                 ubdp = (struct wskbd_bell_data *)data;
    1033           0 :                 SETBELL(ubdp, ubdp, &sc->sc_bell_data);
    1034           0 :                 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
    1035             :                     WSKBDIO_COMPLEXBELL, (caddr_t)ubdp, flag, p));
    1036             : 
    1037             :         case WSKBDIO_SETBELL:
    1038           0 :                 kbdp = &sc->sc_bell_data;
    1039             : setbell:
    1040           0 :                 ubdp = (struct wskbd_bell_data *)data;
    1041           0 :                 SETBELL(kbdp, ubdp, kbdp);
    1042           0 :                 return (0);
    1043             : 
    1044             :         case WSKBDIO_GETBELL:
    1045           0 :                 kbdp = &sc->sc_bell_data;
    1046             : getbell:
    1047           0 :                 ubdp = (struct wskbd_bell_data *)data;
    1048           0 :                 SETBELL(ubdp, kbdp, kbdp);
    1049           0 :                 return (0);
    1050             : 
    1051             :         case WSKBDIO_SETDEFAULTBELL:
    1052           0 :                 if ((error = suser(p)) != 0)
    1053           0 :                         return (error);
    1054             :                 kbdp = &wskbd_default_bell_data;
    1055           0 :                 goto setbell;
    1056             : 
    1057             : 
    1058             :         case WSKBDIO_GETDEFAULTBELL:
    1059             :                 kbdp = &wskbd_default_bell_data;
    1060           0 :                 goto getbell;
    1061             : 
    1062             : #undef SETBELL
    1063             : 
    1064             : #define SETKEYREPEAT(dstp, srcp, dfltp)                                 \
    1065             :     do {                                                                \
    1066             :         (dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL1) ?     \
    1067             :             (srcp)->del1 : (dfltp)->del1;                         \
    1068             :         (dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN) ?     \
    1069             :             (srcp)->delN : (dfltp)->delN;                         \
    1070             :         (dstp)->which = WSKBD_KEYREPEAT_DOALL;                               \
    1071             :     } while (0)
    1072             : 
    1073             :         case WSKBDIO_SETKEYREPEAT:
    1074           0 :                 kkdp = &sc->sc_keyrepeat_data;
    1075             : setkeyrepeat:
    1076           0 :                 ukdp = (struct wskbd_keyrepeat_data *)data;
    1077           0 :                 SETKEYREPEAT(kkdp, ukdp, kkdp);
    1078           0 :                 return (0);
    1079             : 
    1080             :         case WSKBDIO_GETKEYREPEAT:
    1081           0 :                 kkdp = &sc->sc_keyrepeat_data;
    1082             : getkeyrepeat:
    1083           0 :                 ukdp = (struct wskbd_keyrepeat_data *)data;
    1084           0 :                 SETKEYREPEAT(ukdp, kkdp, kkdp);
    1085           0 :                 return (0);
    1086             : 
    1087             :         case WSKBDIO_SETDEFAULTKEYREPEAT:
    1088           0 :                 if ((error = suser(p)) != 0)
    1089           0 :                         return (error);
    1090             :                 kkdp = &wskbd_default_keyrepeat_data;
    1091           0 :                 goto setkeyrepeat;
    1092             : 
    1093             : 
    1094             :         case WSKBDIO_GETDEFAULTKEYREPEAT:
    1095             :                 kkdp = &wskbd_default_keyrepeat_data;
    1096           0 :                 goto getkeyrepeat;
    1097             : 
    1098             : #undef SETKEYREPEAT
    1099             : 
    1100             :         case WSKBDIO_SETMAP:
    1101           0 :                 umdp = (struct wskbd_map_data *)data;
    1102           0 :                 if (umdp->maplen > WSKBDIO_MAXMAPLEN)
    1103           0 :                         return (EINVAL);
    1104             : 
    1105           0 :                 buf = mallocarray(umdp->maplen, sizeof(struct wscons_keymap),
    1106             :                     M_TEMP, M_WAITOK);
    1107           0 :                 len = umdp->maplen * sizeof(struct wscons_keymap);
    1108             : 
    1109           0 :                 error = copyin(umdp->map, buf, len);
    1110           0 :                 if (error == 0) {
    1111           0 :                         wskbd_init_keymap(umdp->maplen,
    1112           0 :                                           &sc->sc_map, &sc->sc_maplen);
    1113           0 :                         memcpy(sc->sc_map, buf, len);
    1114             :                         /* drop the variant bits handled by the map */
    1115           0 :                         enc = KB_USER | (KB_VARIANT(sc->id->t_keymap.layout) &
    1116             :                             KB_HANDLEDBYWSKBD);
    1117           0 :                         wskbd_update_layout(sc->id, enc);
    1118           0 :                 }
    1119           0 :                 free(buf, M_TEMP, len);
    1120           0 :                 return(error);
    1121             : 
    1122             :         case WSKBDIO_GETMAP:
    1123           0 :                 umdp = (struct wskbd_map_data *)data;
    1124           0 :                 if (umdp->maplen > sc->sc_maplen)
    1125           0 :                         umdp->maplen = sc->sc_maplen;
    1126           0 :                 error = copyout(sc->sc_map, umdp->map,
    1127           0 :                                 umdp->maplen*sizeof(struct wscons_keymap));
    1128           0 :                 return(error);
    1129             : 
    1130             :         case WSKBDIO_GETENCODING:
    1131           0 :                 *((kbd_t *)data) = sc->id->t_keymap.layout & ~KB_DEFAULT;
    1132           0 :                 return(0);
    1133             : 
    1134             :         case WSKBDIO_SETENCODING:
    1135           0 :                 enc = *((kbd_t *)data);
    1136           0 :                 if (KB_ENCODING(enc) == KB_USER) {
    1137             :                         /* user map must already be loaded */
    1138           0 :                         if (KB_ENCODING(sc->id->t_keymap.layout) != KB_USER)
    1139           0 :                                 return (EINVAL);
    1140             :                         /* map variants make no sense */
    1141           0 :                         if (KB_VARIANT(enc) & ~KB_HANDLEDBYWSKBD)
    1142           0 :                                 return (EINVAL);
    1143             :                 } else {
    1144           0 :                         error = wskbd_load_keymap(&sc->id->t_keymap, enc,
    1145           0 :                             &sc->sc_map, &sc->sc_maplen);
    1146           0 :                         if (error)
    1147           0 :                                 return (error);
    1148             :                 }
    1149           0 :                 wskbd_update_layout(sc->id, enc);
    1150             : #if NWSMUX > 0
    1151             :                 /* Update mux default layout */
    1152           0 :                 if (sc->sc_base.me_parent != NULL)
    1153           0 :                         wsmux_set_layout(sc->sc_base.me_parent, enc);
    1154             : #endif
    1155           0 :                 return (0);
    1156             : 
    1157             :         case WSKBDIO_GETENCODINGS:
    1158           0 :                 uedp = (struct wskbd_encoding_data *)data;
    1159           0 :                 for (count = 0; sc->id->t_keymap.keydesc[count].name; count++)
    1160             :                         ;
    1161           0 :                 if (uedp->nencodings > count)
    1162           0 :                         uedp->nencodings = count;
    1163           0 :                 for (i = 0; i < uedp->nencodings; i++) {
    1164           0 :                         error = copyout(&sc->id->t_keymap.keydesc[i].name,
    1165           0 :                             &uedp->encodings[i], sizeof(kbd_t));
    1166           0 :                         if (error)
    1167           0 :                                 return (error);
    1168             :                 }
    1169           0 :                 return (0);
    1170             : 
    1171             :         case WSKBDIO_GETBACKLIGHT:
    1172           0 :                 if (wskbd_get_backlight != NULL)
    1173           0 :                         return (*wskbd_get_backlight)((struct wskbd_backlight *)data);
    1174             :                 error = ENOTTY;
    1175           0 :                 break;
    1176             : 
    1177             :         case WSKBDIO_SETBACKLIGHT:
    1178           0 :                 if (wskbd_set_backlight != NULL)
    1179           0 :                         return (*wskbd_set_backlight)((struct wskbd_backlight *)data);
    1180             :                 error = ENOTTY;
    1181           0 :                 break;
    1182             :         }
    1183             : 
    1184             :         /*
    1185             :          * Try the keyboard driver for WSKBDIO ioctls.  It returns -1
    1186             :          * if it didn't recognize the request, and in turn we return
    1187             :          * -1 if we didn't recognize the request.
    1188             :          */
    1189             : /* printf("kbdaccess\n"); */
    1190           0 :         error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data,
    1191             :                                            flag, p);
    1192             : #ifdef WSDISPLAY_COMPAT_RAWKBD
    1193           0 :         if (!error && cmd == WSKBDIO_SETMODE && *(int *)data == WSKBD_RAW) {
    1194           0 :                 int s = spltty();
    1195           0 :                 sc->id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R
    1196             :                                          | MOD_CONTROL_L | MOD_CONTROL_R
    1197             :                                          | MOD_META_L | MOD_META_R
    1198             :                                          | MOD_COMMAND
    1199             :                                          | MOD_COMMAND1 | MOD_COMMAND2);
    1200             : #if NWSDISPLAY > 0
    1201           0 :                 if (sc->sc_repeating) {
    1202           0 :                         sc->sc_repeating = 0;
    1203           0 :                         timeout_del(&sc->sc_repeat_ch);
    1204           0 :                 }
    1205             : #endif
    1206           0 :                 splx(s);
    1207           0 :         }
    1208             : #endif
    1209           0 :         return (error);
    1210           0 : }
    1211             : 
    1212             : int
    1213           0 : wskbdpoll(dev_t dev, int events, struct proc *p)
    1214             : {
    1215           0 :         struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
    1216             : 
    1217           0 :         if (sc->sc_base.me_evp == NULL)
    1218           0 :                 return (POLLERR);
    1219           0 :         return (wsevent_poll(sc->sc_base.me_evp, events, p));
    1220           0 : }
    1221             : 
    1222             : int
    1223           0 : wskbdkqfilter(dev_t dev, struct knote *kn)
    1224             : {
    1225           0 :         struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
    1226             : 
    1227           0 :         if (sc->sc_base.me_evp == NULL)
    1228           0 :                 return (ENXIO);
    1229           0 :         return (wsevent_kqfilter(sc->sc_base.me_evp, kn));
    1230           0 : }
    1231             : 
    1232             : #if NWSDISPLAY > 0
    1233             : 
    1234             : int
    1235           0 : wskbd_pickfree(void)
    1236             : {
    1237             :         int i;
    1238             :         struct wskbd_softc *sc;
    1239             : 
    1240           0 :         for (i = 0; i < wskbd_cd.cd_ndevs; i++) {
    1241           0 :                 if ((sc = wskbd_cd.cd_devs[i]) == NULL)
    1242             :                         continue;
    1243           0 :                 if (sc->sc_displaydv == NULL)
    1244           0 :                         return (i);
    1245             :         }
    1246           0 :         return (-1);
    1247           0 : }
    1248             : 
    1249             : struct wsevsrc *
    1250           0 : wskbd_set_console_display(struct device *displaydv, struct wsevsrc *me)
    1251             : {
    1252           0 :         struct wskbd_softc *sc = wskbd_console_device;
    1253             : 
    1254           0 :         if (sc == NULL)
    1255           0 :                 return (NULL);
    1256           0 :         sc->sc_displaydv = displaydv;
    1257             : #if NWSMUX > 0
    1258           0 :         (void)wsmux_attach_sc((struct wsmux_softc *)me, &sc->sc_base);
    1259             : #endif
    1260           0 :         return (&sc->sc_base);
    1261           0 : }
    1262             : 
    1263             : int
    1264           0 : wskbd_set_display(struct device *dv, struct device *displaydv)
    1265             : {
    1266           0 :         struct wskbd_softc *sc = (struct wskbd_softc *)dv;
    1267             :         struct device *odisplaydv;
    1268             :         int error;
    1269             : 
    1270             :         DPRINTF(("wskbd_set_display: %s odisp=%p disp=%p cons=%d\n",
    1271             :                  dv->dv_xname, sc->sc_displaydv, displaydv, 
    1272             :                  sc->sc_isconsole));
    1273             : 
    1274           0 :         if (sc->sc_isconsole)
    1275           0 :                 return (EBUSY);
    1276             : 
    1277           0 :         if (displaydv != NULL) {
    1278           0 :                 if (sc->sc_displaydv != NULL)
    1279           0 :                         return (EBUSY);
    1280             :         } else {
    1281           0 :                 if (sc->sc_displaydv == NULL)
    1282           0 :                         return (ENXIO);
    1283             :         }
    1284             : 
    1285           0 :         odisplaydv = sc->sc_displaydv;
    1286           0 :         sc->sc_displaydv = NULL;
    1287           0 :         error = wskbd_enable(sc, displaydv != NULL);
    1288           0 :         sc->sc_displaydv = displaydv;
    1289           0 :         if (error) {
    1290           0 :                 sc->sc_displaydv = odisplaydv;
    1291           0 :                 return (error);
    1292             :         }
    1293             : 
    1294           0 :         if (displaydv)
    1295           0 :                 printf("%s: connecting to %s\n",
    1296           0 :                        sc->sc_base.me_dv.dv_xname, displaydv->dv_xname);
    1297             :         else
    1298           0 :                 printf("%s: disconnecting from %s\n",
    1299           0 :                        sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname);
    1300             : 
    1301           0 :         return (0);
    1302           0 : }
    1303             : 
    1304             : #endif  /* NWSDISPLAY > 0 */
    1305             : 
    1306             : #if NWSMUX > 0
    1307             : int
    1308           0 : wskbd_add_mux(int unit, struct wsmux_softc *muxsc)
    1309             : {
    1310             :         struct wskbd_softc *sc;
    1311             : 
    1312           0 :         if (unit < 0 || unit >= wskbd_cd.cd_ndevs ||
    1313           0 :             (sc = wskbd_cd.cd_devs[unit]) == NULL)
    1314           0 :                 return (ENXIO);
    1315             : 
    1316           0 :         if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL)
    1317           0 :                 return (EBUSY);
    1318             : 
    1319           0 :         return (wsmux_attach_sc(muxsc, &sc->sc_base));
    1320           0 : }
    1321             : #endif
    1322             : 
    1323             : /*
    1324             :  * Console interface.
    1325             :  */
    1326             : int
    1327           0 : wskbd_cngetc(dev_t dev)
    1328             : {
    1329             :         static int num = 0;
    1330             :         static int pos;
    1331           0 :         u_int type;
    1332           0 :         int data;
    1333             :         keysym_t ks;
    1334             : 
    1335           0 :         if (!wskbd_console_initted)
    1336           0 :                 return 0;
    1337             : 
    1338           0 :         if (wskbd_console_device != NULL &&
    1339           0 :             !wskbd_console_device->sc_translating)
    1340           0 :                 return 0;
    1341             : 
    1342           0 :         for(;;) {
    1343           0 :                 if (num-- > 0) {
    1344           0 :                         ks = wskbd_console_data.t_symbols[pos++];
    1345           0 :                         if (KS_GROUP(ks) == KS_GROUP_Ascii)
    1346           0 :                                 return (KS_VALUE(ks));  
    1347             :                 } else {
    1348           0 :                         (*wskbd_console_data.t_consops->getc)
    1349           0 :                                 (wskbd_console_data.t_consaccesscookie,
    1350             :                                  &type, &data);
    1351           0 :                         num = wskbd_translate(&wskbd_console_data, type, data);
    1352           0 :                         pos = 0;
    1353             :                 }
    1354             :         }
    1355           0 : }
    1356             : 
    1357             : void
    1358           0 : wskbd_cnpollc(dev_t dev, int poll)
    1359             : {
    1360           0 :         if (!wskbd_console_initted)
    1361             :                 return;
    1362             : 
    1363           0 :         if (wskbd_console_device != NULL &&
    1364           0 :             !wskbd_console_device->sc_translating)
    1365             :                 return;
    1366             : 
    1367           0 :         (*wskbd_console_data.t_consops->pollc)
    1368           0 :             (wskbd_console_data.t_consaccesscookie, poll);
    1369           0 : }
    1370             : 
    1371             : void
    1372           0 : wskbd_cnbell(dev_t dev, u_int pitch, u_int period, u_int volume)
    1373             : {
    1374           0 :         if (!wskbd_console_initted)
    1375             :                 return;
    1376             : 
    1377           0 :         if (wskbd_console_data.t_consops->bell != NULL)
    1378           0 :                 (*wskbd_console_data.t_consops->bell)
    1379           0 :                     (wskbd_console_data.t_consaccesscookie, pitch, period,
    1380             :                         volume);
    1381           0 : }
    1382             : 
    1383             : void
    1384           0 : update_leds(struct wskbd_internal *id)
    1385             : {
    1386             :         int new_state;
    1387             : 
    1388             :         new_state = 0;
    1389           0 :         if (id->t_modifiers & (MOD_SHIFTLOCK | MOD_CAPSLOCK))
    1390           0 :                 new_state |= WSKBD_LED_CAPS;
    1391           0 :         if (id->t_modifiers & MOD_NUMLOCK)
    1392           0 :                 new_state |= WSKBD_LED_NUM;
    1393           0 :         if (id->t_modifiers & MOD_COMPOSE)
    1394           0 :                 new_state |= WSKBD_LED_COMPOSE;
    1395           0 :         if (id->t_modifiers & MOD_HOLDSCREEN)
    1396           0 :                 new_state |= WSKBD_LED_SCROLL;
    1397             : 
    1398           0 :         if (id->t_sc && new_state != id->t_sc->sc_ledstate) {
    1399           0 :                 (*id->t_sc->sc_accessops->set_leds)
    1400           0 :                     (id->t_sc->sc_accesscookie, new_state);
    1401           0 :                 id->t_sc->sc_ledstate = new_state;
    1402           0 :         }
    1403           0 : }
    1404             : 
    1405             : void
    1406           0 : update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask)
    1407             : {
    1408           0 :         if (toggle) {
    1409           0 :                 if (type == WSCONS_EVENT_KEY_DOWN)
    1410           0 :                         id->t_modifiers ^= mask;
    1411             :         } else {
    1412           0 :                 if (type == WSCONS_EVENT_KEY_DOWN)
    1413           0 :                         id->t_modifiers |= mask;
    1414             :                 else
    1415           0 :                         id->t_modifiers &= ~mask;
    1416             :         }
    1417           0 :         if (mask & MOD_ANYLED)
    1418           0 :                 update_leds(id);
    1419           0 : }
    1420             : 
    1421             : #if NWSDISPLAY > 0
    1422             : void
    1423           0 : change_displayparam(struct wskbd_softc *sc, int param, int updown,
    1424             :     int wraparound)
    1425             : {
    1426             :         int res;
    1427           0 :         struct wsdisplay_param dp;
    1428             : 
    1429           0 :         dp.param = param;
    1430           0 :         res = wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_GETPARAM, &dp);
    1431             : 
    1432           0 :         if (res == EINVAL)
    1433           0 :                 return; /* no such parameter */
    1434             : 
    1435           0 :         dp.curval += updown;
    1436           0 :         if (dp.max < dp.curval)
    1437           0 :                 dp.curval = wraparound ? dp.min : dp.max;
    1438             :         else
    1439           0 :         if (dp.curval < dp.min)
    1440           0 :                 dp.curval = wraparound ? dp.max : dp.min;
    1441           0 :         wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_SETPARAM, &dp);
    1442           0 : }
    1443             : #endif
    1444             : 
    1445             : int
    1446           0 : internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym,
    1447             :     keysym_t ksym2)
    1448             : {
    1449           0 :         switch (ksym) {
    1450             :         case KS_Cmd:
    1451           0 :                 update_modifier(sc->id, *type, 0, MOD_COMMAND);
    1452             :                 ksym = ksym2;
    1453           0 :                 break;
    1454             : 
    1455             :         case KS_Cmd1:
    1456           0 :                 update_modifier(sc->id, *type, 0, MOD_COMMAND1);
    1457           0 :                 break;
    1458             : 
    1459             :         case KS_Cmd2:
    1460           0 :                 update_modifier(sc->id, *type, 0, MOD_COMMAND2);
    1461           0 :                 break;
    1462             :         }
    1463             : 
    1464           0 :         if (*type != WSCONS_EVENT_KEY_DOWN)
    1465           0 :                 return (0);
    1466             : 
    1467             : #ifdef HAVE_SCROLLBACK_SUPPORT
    1468             : #if NWSDISPLAY > 0
    1469           0 :         switch (ksym) {
    1470             :         case KS_Cmd_ScrollBack:
    1471           0 :                 if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) {
    1472           0 :                         if (sc->sc_displaydv != NULL)
    1473           0 :                                 wsscrollback(sc->sc_displaydv,
    1474             :                                     WSDISPLAY_SCROLL_BACKWARD);
    1475           0 :                         return (1);
    1476             :                 }
    1477             :                 break;
    1478             : 
    1479             :         case KS_Cmd_ScrollFwd:
    1480           0 :                 if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) {
    1481           0 :                         if (sc->sc_displaydv != NULL)
    1482           0 :                                 wsscrollback(sc->sc_displaydv,
    1483             :                                     WSDISPLAY_SCROLL_FORWARD);
    1484           0 :                         return (1);
    1485             :                 }
    1486             :                 break;
    1487             :         }
    1488             : #endif
    1489             : #endif
    1490             : 
    1491           0 :         if (!MOD_ONESET(sc->id, MOD_COMMAND) &&
    1492           0 :             !MOD_ALLSET(sc->id, MOD_COMMAND1 | MOD_COMMAND2))
    1493           0 :                 return (0);
    1494             : 
    1495             : #ifdef DDB
    1496           0 :         if (ksym == KS_Cmd_Debugger) {
    1497           0 :                 wskbd_debugger(sc);
    1498             :                 /* discard this key (ddb discarded command modifiers) */
    1499           0 :                 *type = WSCONS_EVENT_KEY_UP;
    1500           0 :                 return (1);
    1501             :         }
    1502             : #endif
    1503             : 
    1504             : #if NWSDISPLAY > 0
    1505           0 :         if (sc->sc_displaydv == NULL)
    1506           0 :                 return (0);
    1507             : 
    1508           0 :         switch (ksym) {
    1509             :         case KS_Cmd_Screen0:
    1510             :         case KS_Cmd_Screen1:
    1511             :         case KS_Cmd_Screen2:
    1512             :         case KS_Cmd_Screen3:
    1513             :         case KS_Cmd_Screen4:
    1514             :         case KS_Cmd_Screen5:
    1515             :         case KS_Cmd_Screen6:
    1516             :         case KS_Cmd_Screen7:
    1517             :         case KS_Cmd_Screen8:
    1518             :         case KS_Cmd_Screen9:
    1519             :         case KS_Cmd_Screen10:
    1520             :         case KS_Cmd_Screen11:
    1521           0 :                 wsdisplay_switch(sc->sc_displaydv, ksym - KS_Cmd_Screen0, 0);
    1522           0 :                 return (1);
    1523             :         case KS_Cmd_ResetEmul:
    1524           0 :                 wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL);
    1525           0 :                 return (1);
    1526             :         case KS_Cmd_ResetClose:
    1527           0 :                 wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE);
    1528           0 :                 return (1);
    1529             : #if defined(__i386__) || defined(__amd64__)
    1530             :         case KS_Cmd_KbdReset:
    1531           0 :                 switch (kbd_reset) {
    1532             : #ifdef DDB
    1533             :                 case 2:
    1534           0 :                         wskbd_debugger(sc);
    1535             :                         /* discard this key (ddb discarded command modifiers) */
    1536           0 :                         *type = WSCONS_EVENT_KEY_UP;
    1537           0 :                         break;
    1538             : #endif
    1539             :                 case 1:
    1540           0 :                         kbd_reset = 0;
    1541           0 :                         prsignal(initprocess, SIGUSR1);
    1542           0 :                         break;
    1543             :                 default:
    1544             :                         break;
    1545             :                 }
    1546           0 :                 return (1);
    1547             : #endif
    1548             :         case KS_Cmd_BacklightOn:
    1549             :         case KS_Cmd_BacklightOff:
    1550             :         case KS_Cmd_BacklightToggle:
    1551           0 :                 change_displayparam(sc, WSDISPLAYIO_PARAM_BACKLIGHT,
    1552           0 :                     ksym == KS_Cmd_BacklightOff ? -1 : 1,
    1553           0 :                     ksym == KS_Cmd_BacklightToggle ? 1 : 0);
    1554           0 :                 return (1);
    1555             :         case KS_Cmd_BrightnessUp:
    1556             :         case KS_Cmd_BrightnessDown:
    1557             :         case KS_Cmd_BrightnessRotate:
    1558           0 :                 change_displayparam(sc, WSDISPLAYIO_PARAM_BRIGHTNESS,
    1559           0 :                     ksym == KS_Cmd_BrightnessDown ? -1 : 1,
    1560           0 :                     ksym == KS_Cmd_BrightnessRotate ? 1 : 0);
    1561           0 :                 return (1);
    1562             :         case KS_Cmd_ContrastUp:
    1563             :         case KS_Cmd_ContrastDown:
    1564             :         case KS_Cmd_ContrastRotate:
    1565           0 :                 change_displayparam(sc, WSDISPLAYIO_PARAM_CONTRAST,
    1566           0 :                     ksym == KS_Cmd_ContrastDown ? -1 : 1,
    1567           0 :                     ksym == KS_Cmd_ContrastRotate ? 1 : 0);
    1568           0 :                 return (1);
    1569             :         }
    1570             : #endif
    1571           0 :         return (0);
    1572           0 : }
    1573             : 
    1574             : int
    1575           0 : wskbd_translate(struct wskbd_internal *id, u_int type, int value)
    1576             : {
    1577           0 :         struct wskbd_softc *sc = id->t_sc;
    1578             :         keysym_t ksym, res, *group;
    1579           0 :         struct wscons_keymap kpbuf, *kp;
    1580             :         int gindex, iscommand = 0;
    1581             : 
    1582           0 :         if (type == WSCONS_EVENT_ALL_KEYS_UP) {
    1583             : #if NWSDISPLAY > 0
    1584           0 :                 if (sc != NULL && sc->sc_repeating) {
    1585           0 :                         sc->sc_repeating = 0;
    1586           0 :                         timeout_del(&sc->sc_repeat_ch);
    1587           0 :                 }
    1588             : #endif
    1589           0 :                 id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R |
    1590             :                     MOD_CONTROL_L | MOD_CONTROL_R |
    1591             :                     MOD_META_L | MOD_META_R |
    1592             :                     MOD_MODESHIFT | MOD_MODELOCK |
    1593             :                     MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2);
    1594           0 :                 return (0);
    1595             :         }
    1596             : 
    1597           0 :         if (sc != NULL) {
    1598           0 :                 if (value < 0 || value >= sc->sc_maplen) {
    1599             : #ifdef DEBUG
    1600             :                         printf("wskbd_translate: keycode %d out of range\n",
    1601             :                                value);
    1602             : #endif
    1603           0 :                         return (0);
    1604             :                 }
    1605           0 :                 kp = sc->sc_map + value;
    1606           0 :         } else {
    1607             :                 kp = &kpbuf;
    1608           0 :                 wskbd_get_mapentry(&id->t_keymap, value, kp);
    1609             :         }
    1610             : 
    1611             :         /* if this key has a command, process it first */
    1612           0 :         if (sc != NULL && kp->command != KS_voidSymbol)
    1613           0 :                 iscommand = internal_command(sc, &type, kp->command,
    1614           0 :                     kp->group1[0]);
    1615             : 
    1616             :         /* Now update modifiers */
    1617           0 :         switch (kp->group1[0]) {
    1618             :         case KS_Shift_L:
    1619           0 :                 update_modifier(id, type, 0, MOD_SHIFT_L);
    1620           0 :                 break;
    1621             : 
    1622             :         case KS_Shift_R:
    1623           0 :                 update_modifier(id, type, 0, MOD_SHIFT_R);
    1624           0 :                 break;
    1625             : 
    1626             :         case KS_Shift_Lock:
    1627           0 :                 update_modifier(id, type, 1, MOD_SHIFTLOCK);
    1628           0 :                 break;
    1629             : 
    1630             :         case KS_Caps_Lock:
    1631           0 :                 update_modifier(id, type, 1, MOD_CAPSLOCK);
    1632           0 :                 break;
    1633             : 
    1634             :         case KS_Control_L:
    1635           0 :                 update_modifier(id, type, 0, MOD_CONTROL_L);
    1636           0 :                 break;
    1637             : 
    1638             :         case KS_Control_R:
    1639           0 :                 update_modifier(id, type, 0, MOD_CONTROL_R);
    1640           0 :                 break;
    1641             : 
    1642             :         case KS_Alt_L:
    1643           0 :                 update_modifier(id, type, 0, MOD_META_L);
    1644           0 :                 break;
    1645             : 
    1646             :         case KS_Alt_R:
    1647           0 :                 update_modifier(id, type, 0, MOD_META_R);
    1648           0 :                 break;
    1649             : 
    1650             :         case KS_Mode_switch:
    1651           0 :                 update_modifier(id, type, 0, MOD_MODESHIFT);
    1652           0 :                 break;
    1653             : 
    1654             :         case KS_Mode_Lock:
    1655           0 :                 update_modifier(id, type, 1, MOD_MODELOCK);
    1656           0 :                 break;
    1657             : 
    1658             :         case KS_Num_Lock:
    1659           0 :                 update_modifier(id, type, 1, MOD_NUMLOCK);
    1660           0 :                 break;
    1661             : 
    1662             : #if NWSDISPLAY > 0
    1663             :         case KS_Hold_Screen:
    1664           0 :                 if (sc != NULL) {
    1665           0 :                         update_modifier(id, type, 1, MOD_HOLDSCREEN);
    1666           0 :                         if (sc->sc_displaydv != NULL)
    1667           0 :                                 wsdisplay_kbdholdscreen(sc->sc_displaydv,
    1668           0 :                                     id->t_modifiers & MOD_HOLDSCREEN);
    1669             :                 }
    1670             :                 break;
    1671             : 
    1672             :         default:
    1673           0 :                 if (sc != NULL && sc->sc_repeating &&
    1674           0 :                     ((type == WSCONS_EVENT_KEY_UP && value != sc->sc_repkey) ||
    1675           0 :                      (type == WSCONS_EVENT_KEY_DOWN && value == sc->sc_repkey)))
    1676           0 :                         return (0);
    1677             :                 break;
    1678             : #endif
    1679             :         }
    1680             : 
    1681             : #if NWSDISPLAY > 0
    1682           0 :         if (sc != NULL) {
    1683           0 :                 if (sc->sc_repeating) {
    1684           0 :                         sc->sc_repeating = 0;
    1685           0 :                         timeout_del(&sc->sc_repeat_ch);
    1686           0 :                 }
    1687           0 :                 sc->sc_repkey = value;
    1688           0 :         }
    1689             : #endif
    1690             : 
    1691             :         /* If this is a key release or we are in command mode, we are done */
    1692           0 :         if (type != WSCONS_EVENT_KEY_DOWN || iscommand)
    1693           0 :                 return (0);
    1694             : 
    1695             :         /* Get the keysym */
    1696           0 :         if (id->t_modifiers & (MOD_MODESHIFT|MOD_MODELOCK) &&
    1697           0 :             !MOD_ONESET(id, MOD_ANYCONTROL))
    1698           0 :                 group = & kp->group2[0];
    1699             :         else
    1700             :                 group = & kp->group1[0];
    1701             : 
    1702           0 :         if ((id->t_modifiers & MOD_NUMLOCK) &&
    1703           0 :             KS_GROUP(group[1]) == KS_GROUP_Keypad) {
    1704           0 :                 gindex = !MOD_ONESET(id, MOD_ANYSHIFT);
    1705           0 :                 ksym = group[gindex];
    1706           0 :         } else {
    1707             :                 /* CAPS alone should only affect letter keys */
    1708           0 :                 if ((id->t_modifiers & (MOD_CAPSLOCK | MOD_ANYSHIFT)) ==
    1709             :                     MOD_CAPSLOCK) {
    1710             :                         gindex = 0;
    1711           0 :                         ksym = ksym_upcase(group[0]);
    1712           0 :                 } else {
    1713           0 :                         gindex = MOD_ONESET(id, MOD_ANYSHIFT);
    1714           0 :                         ksym = group[gindex];
    1715             :                 }
    1716             :         }
    1717             : 
    1718             :         /* Submit Audio keys for hotkey processing */
    1719           0 :         if (KS_GROUP(ksym) == KS_GROUP_Function) {
    1720           0 :                 switch (ksym) {
    1721             : #if NAUDIO > 0
    1722             :                 case KS_AudioMute:
    1723           0 :                         wskbd_set_mixervolume(0, 1);
    1724           0 :                         return (0);
    1725             :                 case KS_AudioLower:
    1726           0 :                         wskbd_set_mixervolume(-1, 1);
    1727           0 :                         return (0);
    1728             :                 case KS_AudioRaise:
    1729           0 :                         wskbd_set_mixervolume(1, 1);
    1730           0 :                         return (0);
    1731             : #endif
    1732             :                 default:
    1733             :                         break;
    1734             :                 }
    1735             :         }
    1736             : 
    1737             :         /* Process compose sequence and dead accents */
    1738             :         res = KS_voidSymbol;
    1739             : 
    1740           0 :         switch (KS_GROUP(ksym)) {
    1741             :         case KS_GROUP_Ascii:
    1742             :         case KS_GROUP_Keypad:
    1743             :         case KS_GROUP_Function:
    1744             :                 res = ksym;
    1745           0 :                 break;
    1746             : 
    1747             :         case KS_GROUP_Mod:
    1748           0 :                 if (ksym == KS_Multi_key) {
    1749           0 :                         update_modifier(id, 1, 0, MOD_COMPOSE);
    1750           0 :                         id->t_composelen = 2;
    1751           0 :                 }
    1752             :                 break;
    1753             : 
    1754             :         case KS_GROUP_Dead:
    1755           0 :                 if (id->t_composelen == 0) {
    1756           0 :                         update_modifier(id, 1, 0, MOD_COMPOSE);
    1757           0 :                         id->t_composelen = 1;
    1758           0 :                         id->t_composebuf[0] = ksym;
    1759           0 :                 } else
    1760             :                         res = ksym;
    1761             :                 break;
    1762             :         }
    1763             : 
    1764           0 :         if (res == KS_voidSymbol)
    1765           0 :                 return (0);
    1766             : 
    1767           0 :         if (id->t_composelen > 0) {
    1768             :                 /*
    1769             :                  * If the compose key also serves as AltGr (i.e. set to both
    1770             :                  * KS_Multi_key and KS_Mode_switch), and would provide a valid,
    1771             :                  * distinct combination as AltGr, leave compose mode.
    1772             :                  */
    1773           0 :                 if (id->t_composelen == 2 && group == &kp->group2[0]) {
    1774           0 :                         if (kp->group1[gindex] != kp->group2[gindex])
    1775           0 :                                 id->t_composelen = 0;
    1776             :                 }
    1777             : 
    1778           0 :                 if (id->t_composelen != 0) {
    1779           0 :                         id->t_composebuf[2 - id->t_composelen] = res;
    1780           0 :                         if (--id->t_composelen == 0) {
    1781           0 :                                 res = wskbd_compose_value(id->t_composebuf);
    1782           0 :                                 update_modifier(id, 0, 0, MOD_COMPOSE);
    1783             :                         } else {
    1784           0 :                                 return (0);
    1785             :                         }
    1786           0 :                 }
    1787             :         }
    1788             : 
    1789             :         /* We are done, return the symbol */
    1790           0 :         if (KS_GROUP(res) == KS_GROUP_Ascii) {
    1791           0 :                 if (MOD_ONESET(id, MOD_ANYCONTROL)) {
    1792           0 :                         if ((res >= KS_at && res <= KS_z) || res == KS_space)
    1793           0 :                                 res = res & 0x1f;
    1794           0 :                         else if (res == KS_2)
    1795           0 :                                 res = 0x00;
    1796           0 :                         else if (res >= KS_3 && res <= KS_7)
    1797           0 :                                 res = KS_Escape + (res - KS_3);
    1798           0 :                         else if (res == KS_8)
    1799           0 :                                 res = KS_Delete;
    1800             :                 }
    1801           0 :                 if (MOD_ONESET(id, MOD_ANYMETA)) {
    1802           0 :                         if (id->t_flags & WSKFL_METAESC) {
    1803           0 :                                 id->t_symbols[0] = KS_Escape;
    1804           0 :                                 id->t_symbols[1] = res;
    1805           0 :                                 return (2);
    1806             :                         } else
    1807           0 :                                 res |= 0x80;
    1808           0 :                 }
    1809             :         }
    1810             : 
    1811           0 :         id->t_symbols[0] = res;
    1812           0 :         return (1);
    1813           0 : }
    1814             : 
    1815             : void
    1816           0 : wskbd_debugger(struct wskbd_softc *sc)
    1817             : {
    1818             : #ifdef DDB
    1819           0 :         if (sc->sc_isconsole && db_console) {
    1820           0 :                 if (sc->id->t_consops->debugger != NULL) {
    1821           0 :                         (*sc->id->t_consops->debugger)
    1822           0 :                                 (sc->id->t_consaccesscookie);
    1823           0 :                 } else
    1824           0 :                         db_enter();
    1825             :         }
    1826             : #endif
    1827           0 : }

Generated by: LCOV version 1.13