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

Annotation of sys/dev/pckbc/pms.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: pms.c,v 1.1 2007/08/01 12:16:59 kettenis Exp $ */
                      2: /* $NetBSD: psm.c,v 1.11 2000/06/05 22:20:57 sommerfeld Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1994 Charles M. Hannum.
                      6:  * Copyright (c) 1992, 1993 Erik Forsberg.
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
                     16:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
                     18:  * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     19:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                     21:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
                     22:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                     23:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                     24:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  */
                     26:
                     27: #include <sys/param.h>
                     28: #include <sys/systm.h>
                     29: #include <sys/device.h>
                     30: #include <sys/ioctl.h>
                     31:
                     32: #include <machine/bus.h>
                     33:
                     34: #include <dev/ic/pckbcvar.h>
                     35:
                     36: #include <dev/pckbc/pmsreg.h>
                     37:
                     38: #include <dev/wscons/wsconsio.h>
                     39: #include <dev/wscons/wsmousevar.h>
                     40:
                     41: struct pms_softc {             /* driver status information */
                     42:        struct device sc_dev;
                     43:
                     44:        pckbc_tag_t sc_kbctag;
                     45:        int sc_kbcslot;
                     46:
                     47:        int sc_enabled;         /* input enabled? */
                     48:        int inputstate;
                     49:        u_int buttons, oldbuttons;      /* mouse button status */
                     50:        signed char dx;
                     51:
                     52:        struct device *sc_wsmousedev;
                     53: };
                     54:
                     55: int pmsprobe(struct device *, void *, void *);
                     56: void pmsattach(struct device *, struct device *, void *);
                     57: void pmsinput(void *, int);
                     58:
                     59: struct cfattach pms_ca = {
                     60:        sizeof(struct pms_softc), pmsprobe, pmsattach,
                     61: };
                     62:
                     63: int    pms_enable(void *);
                     64: int    pms_ioctl(void *, u_long, caddr_t, int, struct proc *);
                     65: void   pms_disable(void *);
                     66:
                     67: const struct wsmouse_accessops pms_accessops = {
                     68:        pms_enable,
                     69:        pms_ioctl,
                     70:        pms_disable,
                     71: };
                     72:
                     73: int
                     74: pmsprobe(parent, match, aux)
                     75:        struct device *parent;
                     76:        void *match;
                     77:        void *aux;
                     78: {
                     79:        struct pckbc_attach_args *pa = aux;
                     80:        u_char cmd[1], resp[2];
                     81:        int res;
                     82:
                     83:        if (pa->pa_slot != PCKBC_AUX_SLOT)
                     84:                return (0);
                     85:
                     86:        /* Flush any garbage. */
                     87:        pckbc_flush(pa->pa_tag, pa->pa_slot);
                     88:
                     89:        /* reset the device */
                     90:        cmd[0] = PMS_RESET;
                     91:        res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
                     92:        if (res) {
                     93: #ifdef DEBUG
                     94:                printf("pmsprobe: reset error %d\n", res);
                     95: #endif
                     96:                return (0);
                     97:        }
                     98:        if (resp[0] != PMS_RSTDONE) {
                     99:                printf("pmsprobe: reset response 0x%x\n", resp[0]);
                    100:                return (0);
                    101:        }
                    102:
                    103:        /* get type number (0 = mouse) */
                    104:        if (resp[1] != 0) {
                    105: #ifdef DEBUG
                    106:                printf("pmsprobe: type 0x%x\n", resp[1]);
                    107: #endif
                    108:                return (0);
                    109:        }
                    110:
                    111:        return (10);
                    112: }
                    113:
                    114: void
                    115: pmsattach(parent, self, aux)
                    116:        struct device *parent, *self;
                    117:        void *aux;
                    118: {
                    119:        struct pms_softc *sc = (void *)self;
                    120:        struct pckbc_attach_args *pa = aux;
                    121:        struct wsmousedev_attach_args a;
                    122:        u_char cmd[1], resp[2];
                    123:        int res;
                    124:
                    125:        sc->sc_kbctag = pa->pa_tag;
                    126:        sc->sc_kbcslot = pa->pa_slot;
                    127:
                    128:        printf("\n");
                    129:
                    130:        /* Flush any garbage. */
                    131:        pckbc_flush(pa->pa_tag, pa->pa_slot);
                    132:
                    133:        /* reset the device */
                    134:        cmd[0] = PMS_RESET;
                    135:        res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
                    136: #ifdef DEBUG
                    137:        if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
                    138:                printf("pmsattach: reset error\n");
                    139:                return;
                    140:        }
                    141: #endif
                    142:
                    143:        sc->inputstate = 0;
                    144:        sc->oldbuttons = 0;
                    145:
                    146:        pckbc_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
                    147:                               pmsinput, sc, sc->sc_dev.dv_xname);
                    148:
                    149:        a.accessops = &pms_accessops;
                    150:        a.accesscookie = sc;
                    151:
                    152:        /*
                    153:         * Attach the wsmouse, saving a handle to it.
                    154:         * Note that we don't need to check this pointer against NULL
                    155:         * here or in pmsintr, because if this fails pms_enable() will
                    156:         * never be called, so pmsinput() will never be called.
                    157:         */
                    158:        sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
                    159:
                    160:        /* no interrupts until enabled */
                    161:        cmd[0] = PMS_DEV_DISABLE;
                    162:        res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
                    163:        if (res)
                    164:                printf("pmsattach: disable error\n");
                    165:        pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
                    166: }
                    167:
                    168: int
                    169: pms_enable(v)
                    170:        void *v;
                    171: {
                    172:        struct pms_softc *sc = v;
                    173:        u_char cmd[1];
                    174:        int res;
                    175:
                    176:        if (sc->sc_enabled)
                    177:                return EBUSY;
                    178:
                    179:        sc->sc_enabled = 1;
                    180:        sc->inputstate = 0;
                    181:        sc->oldbuttons = 0;
                    182:
                    183:        pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
                    184:
                    185:        cmd[0] = PMS_DEV_ENABLE;
                    186:        res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
                    187:        if (res)
                    188:                printf("pms_enable: command error\n");
                    189: #if 0
                    190:        {
                    191:                u_char scmd[2];
                    192:
                    193:                scmd[0] = PMS_SET_RES;
                    194:                scmd[1] = 3; /* 8 counts/mm */
                    195:                res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
                    196:                                        2, 0, 1, 0);
                    197:                if (res)
                    198:                        printf("pms_enable: setup error1 (%d)\n", res);
                    199:
                    200:                scmd[0] = PMS_SET_SCALE21;
                    201:                res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
                    202:                                        1, 0, 1, 0);
                    203:                if (res)
                    204:                        printf("pms_enable: setup error2 (%d)\n", res);
                    205:
                    206:                scmd[0] = PMS_SET_SAMPLE;
                    207:                scmd[1] = 100; /* 100 samples/sec */
                    208:                res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, scmd,
                    209:                                        2, 0, 1, 0);
                    210:                if (res)
                    211:                        printf("pms_enable: setup error3 (%d)\n", res);
                    212:        }
                    213: #endif
                    214:
                    215:        return 0;
                    216: }
                    217:
                    218: void
                    219: pms_disable(v)
                    220:        void *v;
                    221: {
                    222:        struct pms_softc *sc = v;
                    223:        u_char cmd[1];
                    224:        int res;
                    225:
                    226:        cmd[0] = PMS_DEV_DISABLE;
                    227:        res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
                    228:        if (res)
                    229:                printf("pms_disable: command error\n");
                    230:
                    231:        pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
                    232:
                    233:        sc->sc_enabled = 0;
                    234: }
                    235:
                    236: int
                    237: pms_ioctl(v, cmd, data, flag, p)
                    238:        void *v;
                    239:        u_long cmd;
                    240:        caddr_t data;
                    241:        int flag;
                    242:        struct proc *p;
                    243: {
                    244:        struct pms_softc *sc = v;
                    245:        u_char kbcmd[2];
                    246:        int i;
                    247:
                    248:        switch (cmd) {
                    249:        case WSMOUSEIO_GTYPE:
                    250:                *(u_int *)data = WSMOUSE_TYPE_PS2;
                    251:                break;
                    252:
                    253:        case WSMOUSEIO_SRES:
                    254:                i = ((int) *(u_int *)data - 12) / 25;
                    255:                /* valid values are {0,1,2,3} */
                    256:                if (i < 0)
                    257:                        i = 0;
                    258:                if (i > 3)
                    259:                        i = 3;
                    260:
                    261:                kbcmd[0] = PMS_SET_RES;
                    262:                kbcmd[1] = (unsigned char) i;
                    263:                i = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd,
                    264:                    2, 0, 1, 0);
                    265:
                    266:                if (i)
                    267:                        printf("pms_ioctl: SET_RES command error\n");
                    268:                break;
                    269:
                    270:        default:
                    271:                return (-1);
                    272:        }
                    273:        return (0);
                    274: }
                    275:
                    276: /* Masks for the first byte of a packet */
                    277: #define PS2LBUTMASK 0x01
                    278: #define PS2RBUTMASK 0x02
                    279: #define PS2MBUTMASK 0x04
                    280:
                    281: void pmsinput(vsc, data)
                    282: void *vsc;
                    283: int data;
                    284: {
                    285:        struct pms_softc *sc = vsc;
                    286:        signed char dy;
                    287:        u_int changed;
                    288:
                    289:        if (!sc->sc_enabled) {
                    290:                /* Interrupts are not expected.  Discard the byte. */
                    291:                return;
                    292:        }
                    293:
                    294:        switch (sc->inputstate) {
                    295:
                    296:        case 0:
                    297:                if ((data & 0xc0) == 0) { /* no ovfl, bit 3 == 1 too? */
                    298:                        sc->buttons = ((data & PS2LBUTMASK) ? 0x1 : 0) |
                    299:                            ((data & PS2MBUTMASK) ? 0x2 : 0) |
                    300:                            ((data & PS2RBUTMASK) ? 0x4 : 0);
                    301:                        ++sc->inputstate;
                    302:                }
                    303:                break;
                    304:
                    305:        case 1:
                    306:                sc->dx = data;
                    307:                /* Bounding at -127 avoids a bug in XFree86. */
                    308:                sc->dx = (sc->dx == -128) ? -127 : sc->dx;
                    309:                ++sc->inputstate;
                    310:                break;
                    311:
                    312:        case 2:
                    313:                dy = data;
                    314:                dy = (dy == -128) ? -127 : dy;
                    315:                sc->inputstate = 0;
                    316:
                    317:                changed = (sc->buttons ^ sc->oldbuttons);
                    318:                sc->oldbuttons = sc->buttons;
                    319:
                    320:                if (sc->dx || dy || changed)
                    321:                        wsmouse_input(sc->sc_wsmousedev,
                    322:                                      sc->buttons, sc->dx, dy, 0, 0,
                    323:                                      WSMOUSE_INPUT_DELTA);
                    324:                break;
                    325:        }
                    326:
                    327:        return;
                    328: }
                    329:
                    330: struct cfdriver pms_cd = {
                    331:        NULL, "pms", DV_DULL
                    332: };

CVSweb