[BACK]Return to wskbd.c CVS log [TXT][DIR] Up to [local] / sys / dev / wscons

Annotation of sys/dev/wscons/wskbd.c, Revision 1.1

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

CVSweb