[BACK]Return to lk201_ws.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / dec

Annotation of sys/arch/vax/dec/lk201_ws.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: lk201_ws.c,v 1.10 2006/08/27 16:50:43 miod Exp $      */
        !             2: /* $NetBSD: lk201_ws.c,v 1.2 1998/10/22 17:55:20 drochner Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1998
        !             6:  *     Matthias Drochner.  All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed for the NetBSD Project
        !            19:  *     by Matthias Drochner.
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  *
        !            34:  */
        !            35:
        !            36: #include <sys/param.h>
        !            37: #include <sys/systm.h>
        !            38: #include <sys/kernel.h>
        !            39: #include <sys/proc.h>
        !            40: #include <sys/tty.h>
        !            41: #include <sys/timeout.h>
        !            42:
        !            43: #include <dev/wscons/wsconsio.h>
        !            44:
        !            45: #include <vax/dec/lk201reg.h>
        !            46: #include <vax/dec/lk201var.h>
        !            47: #include <vax/dec/wskbdmap_lk201.h> /* for {MIN,MAX}_LK201_KEY */
        !            48:
        !            49: struct cfdriver lkkbd_cd = {
        !            50:        NULL, "lkkbd", DV_DULL
        !            51: };
        !            52:
        !            53: void   lk201_identify(void *);
        !            54:
        !            55: static const char *lkkbd_descr[] = {
        !            56:        "no keyboard",
        !            57:        "LK-201 keyboard",
        !            58:        "LK-401 keyboard"
        !            59: };
        !            60:
        !            61: #define        send(lks, c) ((*((lks)->attmt.sendchar))((lks)->attmt.cookie, c))
        !            62:
        !            63: void
        !            64: lk201_init(struct lk201_state *lks)
        !            65: {
        !            66:        int i;
        !            67:
        !            68:        lks->waitack = 0;
        !            69:
        !            70:        send(lks, LK_LED_ENABLE);
        !            71:        send(lks, LK_LED_ALL);
        !            72:
        !            73:        /*
        !            74:         * set all keys to updown mode; autorepeat is
        !            75:         * done by wskbd software
        !            76:         */
        !            77:        for (i = 1; i <= 14; i++)
        !            78:                send(lks, LK_CMD_MODE(LK_UPDOWN, i));
        !            79:
        !            80:        send(lks, LK_CL_DISABLE);
        !            81:        lks->kcvol = 0;
        !            82:
        !            83:        lks->bellvol = -1; /* not yet set */
        !            84:
        !            85:        for (i = 0; i < LK_KLL; i++)
        !            86:                lks->down_keys_list[i] = -1;
        !            87:        send(lks, LK_KBD_ENABLE);
        !            88:
        !            89:        send(lks, LK_LED_DISABLE);
        !            90:        send(lks, LK_LED_ALL);
        !            91:        lks->leds_state = 0;
        !            92:
        !            93:        /*
        !            94:         * Note that, when attaching lkkbd initially, this timeout will
        !            95:         * be scheduled but will not run until interrupts are enabled.
        !            96:         * This is not a problem, since lk201_identify() relies upon
        !            97:         * interrupts being enabled.
        !            98:         */
        !            99:        timeout_set(&lks->probetmo, lk201_identify, lks);
        !           100:        timeout_add(&lks->probetmo, 0);
        !           101: }
        !           102:
        !           103: void
        !           104: lk201_identify(void *v)
        !           105: {
        !           106:        struct lk201_state *lks = v;
        !           107:        int i;
        !           108:
        !           109:        /*
        !           110:         * Swallow all the keyboard acknowledges from lk201_init().
        !           111:         * There should be 14 of them - one per LK_CMD_MODE command.
        !           112:         */
        !           113:        for(;;) {
        !           114:                lks->waitack = 1;
        !           115:                for (i = 100; i != 0; i--) {
        !           116:                        DELAY(1000);
        !           117:                        if (lks->waitack == 0)
        !           118:                                break;
        !           119:                }
        !           120:                if (i == 0)
        !           121:                        break;
        !           122:        }
        !           123:
        !           124:        /*
        !           125:         * Try to set the keyboard in LK-401 mode.
        !           126:         * If we receive an error, this is an LK-201 keyboard.
        !           127:         */
        !           128:        lks->waitack = 1;
        !           129:        send(lks, LK_ENABLE_401);
        !           130:        for (i = 100; i != 0; i--) {
        !           131:                DELAY(1000);
        !           132:                if (lks->waitack == 0)
        !           133:                        break;
        !           134:        }
        !           135:        if (lks->waitack != 0)
        !           136:                lks->kbdtype = KBD_NONE;
        !           137:        else {
        !           138:                if (lks->ackdata == LK_INPUT_ERROR)
        !           139:                        lks->kbdtype = KBD_LK201;
        !           140:                else
        !           141:                        lks->kbdtype = KBD_LK401;
        !           142:        }
        !           143:        lks->waitack = 0;
        !           144:
        !           145:        printf("%s: %s\n", lks->device->dv_xname, lkkbd_descr[lks->kbdtype]);
        !           146: }
        !           147:
        !           148: int
        !           149: lk201_decode(struct lk201_state *lks, int active, int wantmulti, int datain,
        !           150:     u_int *type, int *dataout)
        !           151: {
        !           152:        int i, freeslot;
        !           153:
        !           154:        if (lks->waitack != 0) {
        !           155:                lks->ackdata = datain;
        !           156:                lks->waitack = 0;
        !           157:                return (LKD_NODATA);
        !           158:        }
        !           159:
        !           160:        switch (datain) {
        !           161:        case LK_POWER_UP:
        !           162: #ifdef DEBUG
        !           163:                printf("lk201_decode: powerup detected\n");
        !           164: #endif
        !           165:                lk201_init(lks);
        !           166:                return (LKD_NODATA);
        !           167:        case LK_KDOWN_ERROR:
        !           168:        case LK_POWER_ERROR:
        !           169:        case LK_OUTPUT_ERROR:
        !           170:        case LK_INPUT_ERROR:
        !           171:                printf("lk201_decode: error %x\n", datain);
        !           172:                /* FALLTHROUGH */
        !           173:        case LK_KEY_REPEAT: /* autorepeat handled by wskbd */
        !           174:        case LK_MODE_CHANGE: /* ignore silently */
        !           175:                return (LKD_NODATA);
        !           176:        }
        !           177:
        !           178:        if (active == 0)
        !           179:                return (LKD_NODATA);    /* no need to decode */
        !           180:
        !           181:        if (datain == LK_KEY_UP) {
        !           182:                if (wantmulti) {
        !           183:                        for (i = 0; i < LK_KLL; i++)
        !           184:                                if (lks->down_keys_list[i] != -1) {
        !           185:                                        *type = WSCONS_EVENT_KEY_UP;
        !           186:                                        *dataout = lks->down_keys_list[i] -
        !           187:                                            MIN_LK201_KEY;
        !           188:                                        lks->down_keys_list[i] = -1;
        !           189:                                        return (LKD_MORE);
        !           190:                                }
        !           191:                        return (LKD_NODATA);
        !           192:                } else {
        !           193:                        for (i = 0; i < LK_KLL; i++)
        !           194:                                lks->down_keys_list[i] = -1;
        !           195:                        *type = WSCONS_EVENT_ALL_KEYS_UP;
        !           196:                        return (LKD_COMPLETE);
        !           197:                }
        !           198:        } else if (datain < MIN_LK201_KEY || datain > MAX_LK201_KEY) {
        !           199: #ifdef DEBUG
        !           200:                /* this can happen while hotplugging the keyboard */
        !           201:                printf("lk201_decode: %x\n", datain);
        !           202: #endif
        !           203:                return (LKD_NODATA);
        !           204:        }
        !           205:
        !           206:        /*
        !           207:         * The LK-201 keyboard has a compose key (to the left of the spacebar),
        !           208:         * but no alt/meta key at all. The LK-401 keyboard fixes this and has
        !           209:         * two compose keys and two alt keys.
        !           210:         *
        !           211:         * If the keyboard is an LK-201, translate the left compose key
        !           212:         * scancode to a specific key code, which will map as a left alt key,
        !           213:         * and compose key when shifted), so that the user can have both
        !           214:         * an alt and a compose key available.
        !           215:         */
        !           216:        if (lks->kbdtype == KBD_LK201 && datain == 177)
        !           217:                datain = 252;
        !           218:
        !           219:        *dataout = datain - MIN_LK201_KEY;
        !           220:
        !           221:        freeslot = -1;
        !           222:        for (i = 0; i < LK_KLL; i++) {
        !           223:                if (lks->down_keys_list[i] == datain) {
        !           224:                        *type = WSCONS_EVENT_KEY_UP;
        !           225:                        lks->down_keys_list[i] = -1;
        !           226:                        return (LKD_COMPLETE);
        !           227:                }
        !           228:                if (lks->down_keys_list[i] == -1 && freeslot == -1)
        !           229:                        freeslot = i;
        !           230:        }
        !           231:
        !           232:        if (freeslot == -1) {
        !           233:                printf("lk201_decode: down(%d) no free slot\n", datain);
        !           234:                return (LKD_NODATA);
        !           235:        }
        !           236:
        !           237:        *type = WSCONS_EVENT_KEY_DOWN;
        !           238:        lks->down_keys_list[freeslot] = datain;
        !           239:        return (LKD_COMPLETE);
        !           240: }
        !           241:
        !           242: void
        !           243: lk201_bell(struct lk201_state *lks, struct wskbd_bell_data *bell)
        !           244: {
        !           245:        unsigned int vol;
        !           246:
        !           247:        if (bell->which & WSKBD_BELL_DOVOLUME) {
        !           248:                vol = 8 - bell->volume * 8 / 100;
        !           249:                if (vol > 7)
        !           250:                        vol = 7;
        !           251:        } else
        !           252:                vol = 3;
        !           253:
        !           254:        if (vol != lks->bellvol) {
        !           255:                send(lks, LK_BELL_ENABLE);
        !           256:                send(lks, LK_PARAM_VOLUME(vol));
        !           257:                lks->bellvol = vol;
        !           258:        }
        !           259:        send(lks, LK_RING_BELL);
        !           260: }
        !           261:
        !           262: int
        !           263: lk201_get_leds(struct lk201_state *lks)
        !           264: {
        !           265:        return (lks->leds_state);
        !           266: }
        !           267:
        !           268: int
        !           269: lk201_get_type(struct lk201_state *lks)
        !           270: {
        !           271:        /*
        !           272:         * Note that we report LK201 even if no keyboard is
        !           273:         * plugged to avoid confusing wsconsctl.
        !           274:         */
        !           275:        if (lks->kbdtype == KBD_LK401)
        !           276:                return (WSKBD_TYPE_LK401);
        !           277:        else
        !           278:                return (WSKBD_TYPE_LK201);
        !           279: }
        !           280:
        !           281: void
        !           282: lk201_set_keyclick(struct lk201_state *lks, int vol)
        !           283: {
        !           284:        unsigned int newvol;
        !           285:
        !           286:        if (vol == 0)
        !           287:                send(lks, LK_CL_DISABLE);
        !           288:        else {
        !           289:                newvol = 8 - vol * 8 / 100;
        !           290:                if (newvol > 7)
        !           291:                        newvol = 7;
        !           292:
        !           293:                send(lks, LK_CL_ENABLE);
        !           294:                send(lks, LK_PARAM_VOLUME(newvol));
        !           295:        }
        !           296:
        !           297:        lks->kcvol = vol;
        !           298: }
        !           299:
        !           300: void
        !           301: lk201_set_leds(struct lk201_state *lks, int leds)
        !           302: {
        !           303:        int newleds;
        !           304:
        !           305:        newleds = 0;
        !           306:        if (leds & WSKBD_LED_SCROLL)
        !           307:                newleds |= LK_LED_WAIT;
        !           308:        if (leds & WSKBD_LED_CAPS)
        !           309:                newleds |= LK_LED_LOCK;
        !           310:
        !           311:        send(lks, LK_LED_DISABLE);
        !           312:        send(lks, (0x80 | (~newleds & 0x0f)));
        !           313:
        !           314:        send(lks, LK_LED_ENABLE);
        !           315:        send(lks, (0x80 | (newleds & 0x0f)));
        !           316:
        !           317:        lks->leds_state = leds;
        !           318: }

CVSweb