[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

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