Annotation of sys/dev/pckbc/pms_intelli.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pms_intelli.c,v 1.1 2007/08/01 12:16:59 kettenis Exp $ */
! 2: /* $NetBSD: psm_intelli.c,v 1.8 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 pmsi_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, dy;
! 51:
! 52: struct device *sc_wsmousedev;
! 53: };
! 54:
! 55: int pmsiprobe(struct device *, void *, void *);
! 56: void pmsiattach(struct device *, struct device *, void *);
! 57: void pmsiinput(void *, int);
! 58:
! 59: struct cfattach pmsi_ca = {
! 60: sizeof(struct pmsi_softc), pmsiprobe, pmsiattach,
! 61: };
! 62:
! 63: int pmsi_enable(void *);
! 64: int pmsi_ioctl(void *, u_long, caddr_t, int, struct proc *);
! 65: void pmsi_disable(void *);
! 66:
! 67: const struct wsmouse_accessops pmsi_accessops = {
! 68: pmsi_enable,
! 69: pmsi_ioctl,
! 70: pmsi_disable,
! 71: };
! 72:
! 73: static int pmsi_setintellimode(pckbc_tag_t, pckbc_slot_t);
! 74:
! 75: static int
! 76: pmsi_setintellimode(tag, slot)
! 77: pckbc_tag_t tag;
! 78: pckbc_slot_t slot;
! 79: {
! 80: u_char cmd[2], resp[1];
! 81: int i, res;
! 82: static u_char rates[] = {200, 100, 80};
! 83:
! 84: cmd[0] = PMS_SET_SAMPLE;
! 85: for (i = 0; i < 3; i++) {
! 86: cmd[1] = rates[i];
! 87: res = pckbc_poll_cmd(tag, slot, cmd, 2, 0, 0, 0);
! 88: if (res)
! 89: return (res);
! 90: }
! 91:
! 92: cmd[0] = PMS_SEND_DEV_ID;
! 93: res = pckbc_poll_cmd(tag, slot, cmd, 1, 1, resp, 0);
! 94: if (res)
! 95: return (res);
! 96: if (resp[0] != 3)
! 97: return (ENXIO);
! 98:
! 99: return (0);
! 100: }
! 101:
! 102: int
! 103: pmsiprobe(parent, match, aux)
! 104: struct device *parent;
! 105: void *match;
! 106: void *aux;
! 107: {
! 108: struct pckbc_attach_args *pa = aux;
! 109: u_char cmd[1], resp[2];
! 110: int res;
! 111:
! 112: if (pa->pa_slot != PCKBC_AUX_SLOT)
! 113: return (0);
! 114:
! 115: /* Flush any garbage. */
! 116: pckbc_flush(pa->pa_tag, pa->pa_slot);
! 117:
! 118: /* reset the device */
! 119: cmd[0] = PMS_RESET;
! 120: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
! 121: if (res) {
! 122: #ifdef DEBUG
! 123: printf("pmsiprobe: reset error %d\n", res);
! 124: #endif
! 125: return (0);
! 126: }
! 127: if (resp[0] != PMS_RSTDONE) {
! 128: printf("pmsiprobe: reset response 0x%x\n", resp[0]);
! 129: return (0);
! 130: }
! 131:
! 132: /* get type number (0 = mouse) */
! 133: if (resp[1] != 0) {
! 134: #ifdef DEBUG
! 135: printf("pmsiprobe: type 0x%x\n", resp[1]);
! 136: #endif
! 137: return (0);
! 138: }
! 139:
! 140: if ((res = pmsi_setintellimode(pa->pa_tag, pa->pa_slot))) {
! 141: #ifdef DEBUG
! 142: printf("pmsiprobe: intellimode -> %d\n", res);
! 143: #endif
! 144: return (0);
! 145: }
! 146:
! 147: return (20);
! 148: }
! 149:
! 150: void
! 151: pmsiattach(parent, self, aux)
! 152: struct device *parent, *self;
! 153: void *aux;
! 154: {
! 155: struct pmsi_softc *sc = (void *)self;
! 156: struct pckbc_attach_args *pa = aux;
! 157: struct wsmousedev_attach_args a;
! 158: u_char cmd[1], resp[2];
! 159: int res;
! 160:
! 161: sc->sc_kbctag = pa->pa_tag;
! 162: sc->sc_kbcslot = pa->pa_slot;
! 163:
! 164: printf("\n");
! 165:
! 166: /* Flush any garbage. */
! 167: pckbc_flush(pa->pa_tag, pa->pa_slot);
! 168:
! 169: /* reset the device */
! 170: cmd[0] = PMS_RESET;
! 171: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
! 172: #ifdef DEBUG
! 173: if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
! 174: printf("pmsiattach: reset error\n");
! 175: return;
! 176: }
! 177: #endif
! 178: res = pmsi_setintellimode(pa->pa_tag, pa->pa_slot);
! 179: #ifdef DEBUG
! 180: if (res) {
! 181: printf("pmsiattach: error setting intelli mode\n");
! 182: return;
! 183: }
! 184: #endif
! 185:
! 186: /* Other initialization was done by pmsiprobe. */
! 187: sc->inputstate = 0;
! 188: sc->oldbuttons = 0;
! 189:
! 190: pckbc_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
! 191: pmsiinput, sc, sc->sc_dev.dv_xname);
! 192:
! 193: a.accessops = &pmsi_accessops;
! 194: a.accesscookie = sc;
! 195:
! 196: /*
! 197: * Attach the wsmouse, saving a handle to it.
! 198: * Note that we don't need to check this pointer against NULL
! 199: * here or in pmsintr, because if this fails pms_enable() will
! 200: * never be called, so pmsiinput() will never be called.
! 201: */
! 202: sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
! 203:
! 204: /* no interrupts until enabled */
! 205: cmd[0] = PMS_DEV_DISABLE;
! 206: res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
! 207: if (res)
! 208: printf("pmsiattach: disable error\n");
! 209: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
! 210: }
! 211:
! 212: int
! 213: pmsi_enable(v)
! 214: void *v;
! 215: {
! 216: struct pmsi_softc *sc = v;
! 217: u_char cmd[1];
! 218: int res;
! 219:
! 220: if (sc->sc_enabled)
! 221: return EBUSY;
! 222:
! 223: sc->sc_enabled = 1;
! 224: sc->inputstate = 0;
! 225: sc->oldbuttons = 0;
! 226:
! 227: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
! 228:
! 229: cmd[0] = PMS_DEV_ENABLE;
! 230: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
! 231: if (res)
! 232: printf("pmsi_enable: command error\n");
! 233:
! 234: return 0;
! 235: }
! 236:
! 237: void
! 238: pmsi_disable(v)
! 239: void *v;
! 240: {
! 241: struct pmsi_softc *sc = v;
! 242: u_char cmd[1];
! 243: int res;
! 244:
! 245: cmd[0] = PMS_DEV_DISABLE;
! 246: res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
! 247: if (res)
! 248: printf("pmsi_disable: command error\n");
! 249:
! 250: pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
! 251:
! 252: sc->sc_enabled = 0;
! 253: }
! 254:
! 255: int
! 256: pmsi_ioctl(v, cmd, data, flag, p)
! 257: void *v;
! 258: u_long cmd;
! 259: caddr_t data;
! 260: int flag;
! 261: struct proc *p;
! 262: {
! 263: struct pmsi_softc *sc = v;
! 264: u_char kbcmd[2];
! 265: int i;
! 266:
! 267: switch (cmd) {
! 268: case WSMOUSEIO_GTYPE:
! 269: *(u_int *)data = WSMOUSE_TYPE_PS2;
! 270: break;
! 271:
! 272: case WSMOUSEIO_SRES:
! 273: i = ((int) *(u_int *)data - 12) / 25;
! 274: /* valid values are {0,1,2,3} */
! 275: if (i < 0)
! 276: i = 0;
! 277: if (i > 3)
! 278: i = 3;
! 279:
! 280: kbcmd[0] = PMS_SET_RES;
! 281: kbcmd[1] = (unsigned char) i;
! 282: i = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd,
! 283: 2, 0, 1, 0);
! 284:
! 285: if (i)
! 286: printf("pms_ioctl: SET_RES command error\n");
! 287: break;
! 288:
! 289: default:
! 290: return (-1);
! 291: }
! 292: return (0);
! 293: }
! 294:
! 295: /* Masks for the first byte of a packet */
! 296: #define PS2LBUTMASK 0x01
! 297: #define PS2RBUTMASK 0x02
! 298: #define PS2MBUTMASK 0x04
! 299:
! 300: void pmsiinput(vsc, data)
! 301: void *vsc;
! 302: int data;
! 303: {
! 304: struct pmsi_softc *sc = vsc;
! 305: signed char dz;
! 306: u_int changed;
! 307:
! 308: if (!sc->sc_enabled) {
! 309: /* Interrupts are not expected. Discard the byte. */
! 310: return;
! 311: }
! 312:
! 313: switch (sc->inputstate) {
! 314:
! 315: case 0:
! 316: if ((data & 0xc0) == 0) { /* no ovfl, bit 3 == 1 too? */
! 317: sc->buttons = ((data & PS2LBUTMASK) ? 0x1 : 0) |
! 318: ((data & PS2MBUTMASK) ? 0x2 : 0) |
! 319: ((data & PS2RBUTMASK) ? 0x4 : 0);
! 320: ++sc->inputstate;
! 321: }
! 322: break;
! 323:
! 324: case 1:
! 325: sc->dx = data;
! 326: /* Bounding at -127 avoids a bug in XFree86. */
! 327: sc->dx = (sc->dx == -128) ? -127 : sc->dx;
! 328: ++sc->inputstate;
! 329: break;
! 330:
! 331: case 2:
! 332: sc->dy = data;
! 333: sc->dy = (sc->dy == -128) ? -127 : sc->dy;
! 334: ++sc->inputstate;
! 335: break;
! 336:
! 337: case 3:
! 338: dz = data;
! 339: dz = (dz == -128) ? -127 : dz;
! 340: sc->inputstate = 0;
! 341:
! 342: changed = (sc->buttons ^ sc->oldbuttons);
! 343: sc->oldbuttons = sc->buttons;
! 344:
! 345: if (sc->dx || sc->dy || dz || changed)
! 346: wsmouse_input(sc->sc_wsmousedev,
! 347: sc->buttons, sc->dx, sc->dy, dz, 0,
! 348: WSMOUSE_INPUT_DELTA);
! 349: break;
! 350: }
! 351:
! 352: return;
! 353: }
! 354:
! 355: struct cfdriver pmsi_cd = {
! 356: NULL, "pmsi", DV_DULL
! 357: };
CVSweb