1 /* $NetBSD: dzms.c,v 1.17 2007/10/19 11:59:40 ad Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)ms.c 8.1 (Berkeley) 6/11/93 41 */ 42 43 /* 44 * VSXXX mice attached to line 1 of the DZ* 45 */ 46 47 #include <sys/cdefs.h> 48 __KERNEL_RCSID(0, "$NetBSD: dzms.c,v 1.17 2007/10/19 11:59:40 ad Exp $"); 49 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/device.h> 53 #include <sys/ioctl.h> 54 #include <sys/syslog.h> 55 #include <sys/kernel.h> 56 #include <sys/proc.h> 57 #include <sys/tty.h> 58 59 #include <sys/bus.h> 60 61 #include <dev/dec/dzreg.h> 62 #include <dev/dec/dzvar.h> 63 #include <dev/dec/dzkbdvar.h> 64 #include <dev/dec/lk201.h> 65 66 #include <dev/wscons/wsconsio.h> 67 #include <dev/wscons/wsmousevar.h> 68 69 #include "locators.h" 70 71 struct dzms_softc { /* driver status information */ 72 struct device dzms_dev; /* required first: base device */ 73 struct dz_linestate *dzms_ls; 74 75 int sc_enabled; /* input enabled? */ 76 int sc_selftest; 77 78 int inputstate; 79 u_int buttons; 80 int dx, dy; 81 82 struct device *sc_wsmousedev; 83 }; 84 85 static int dzms_match(struct device *, struct cfdata *, void *); 86 static void dzms_attach(struct device *, struct device *, void *); 87 static int dzms_input(void *, int); 88 89 CFATTACH_DECL(dzms, sizeof(struct dzms_softc), 90 dzms_match, dzms_attach, NULL, NULL); 91 92 static int dzms_enable(void *); 93 static int dzms_ioctl(void *, u_long, void *, int, struct lwp *); 94 static void dzms_disable(void *); 95 96 const struct wsmouse_accessops dzms_accessops = { 97 dzms_enable, 98 dzms_ioctl, 99 dzms_disable, 100 }; 101 102 static int 103 dzms_match(parent, cf, aux) 104 struct device *parent; 105 struct cfdata *cf; 106 void *aux; 107 { 108 struct dzkm_attach_args *daa = aux; 109 110 /* Exact match is better than wildcard. */ 111 if (cf->cf_loc[DZCF_LINE] == daa->daa_line) 112 return 2; 113 114 /* This driver accepts wildcard. */ 115 if (cf->cf_loc[DZCF_LINE] == DZCF_LINE_DEFAULT) 116 return 1; 117 118 return 0; 119 } 120 121 static void 122 dzms_attach(parent, self, aux) 123 struct device *parent, *self; 124 void *aux; 125 { 126 struct dz_softc *dz = device_private(parent); 127 struct dzms_softc *dzms = device_private(self); 128 struct dzkm_attach_args *daa = aux; 129 struct dz_linestate *ls; 130 struct wsmousedev_attach_args a; 131 132 dz->sc_dz[daa->daa_line].dz_catch = dzms_input; 133 dz->sc_dz[daa->daa_line].dz_private = dzms; 134 ls = &dz->sc_dz[daa->daa_line]; 135 dzms->dzms_ls = ls; 136 137 printf("\n"); 138 139 a.accessops = &dzms_accessops; 140 a.accesscookie = dzms; 141 142 dzms->sc_enabled = 0; 143 dzms->sc_selftest = 0; 144 dzms->sc_wsmousedev = config_found(self, &a, wsmousedevprint); 145 } 146 147 static int 148 dzms_enable(v) 149 void *v; 150 { 151 struct dzms_softc *sc = v; 152 153 if (sc->sc_enabled) 154 return EBUSY; 155 156 sc->sc_selftest = 4; /* wait for 4 byte reply upto 1/2 sec */ 157 dzputc(sc->dzms_ls, MOUSE_SELF_TEST); 158 (void)tsleep(dzms_enable, TTIPRI, "dzmsopen", hz / 2); 159 if (sc->sc_selftest != 0) { 160 sc->sc_selftest = 0; 161 return ENXIO; 162 } 163 DELAY(150); 164 dzputc(sc->dzms_ls, MOUSE_INCREMENTAL); 165 sc->sc_enabled = 1; 166 sc->inputstate = 0; 167 return 0; 168 } 169 170 static void 171 dzms_disable(v) 172 void *v; 173 { 174 struct dzms_softc *sc = v; 175 176 sc->sc_enabled = 0; 177 } 178 179 static int 180 dzms_ioctl(v, cmd, data, flag, l) 181 void *v; 182 u_long cmd; 183 void *data; 184 int flag; 185 struct lwp *l; 186 { 187 if (cmd == WSMOUSEIO_GTYPE) { 188 *(u_int *)data = WSMOUSE_TYPE_VSXXX; 189 return 0; 190 } 191 return EPASSTHROUGH; 192 } 193 194 static int 195 dzms_input(vsc, data) 196 void *vsc; 197 int data; 198 { 199 struct dzms_softc *sc = vsc; 200 201 if (sc->sc_enabled == 0) { 202 if (sc->sc_selftest > 0) { 203 sc->sc_selftest -= 1; 204 if (sc->sc_selftest == 0) 205 wakeup(dzms_enable); 206 } 207 return (1); 208 } 209 210 #define WSMS_BUTTON1 0x01 211 #define WSMS_BUTTON2 0x02 212 #define WSMS_BUTTON3 0x04 213 214 if ((data & MOUSE_START_FRAME) != 0) 215 sc->inputstate = 1; 216 else 217 sc->inputstate++; 218 219 if (sc->inputstate == 1) { 220 sc->buttons = 0; 221 if ((data & LEFT_BUTTON) != 0) 222 sc->buttons |= WSMS_BUTTON1; 223 if ((data & MIDDLE_BUTTON) != 0) 224 sc->buttons |= WSMS_BUTTON2; 225 if ((data & RIGHT_BUTTON) != 0) 226 sc->buttons |= WSMS_BUTTON3; 227 228 sc->dx = data & MOUSE_X_SIGN; 229 sc->dy = data & MOUSE_Y_SIGN; 230 } else if (sc->inputstate == 2) { 231 if (sc->dx == 0) 232 sc->dx = -data; 233 else 234 sc->dx = data; 235 } else if (sc->inputstate == 3) { 236 sc->inputstate = 0; 237 if (sc->dy == 0) 238 sc->dy = -data; 239 else 240 sc->dy = data; 241 wsmouse_input(sc->sc_wsmousedev, 242 sc->buttons, 243 sc->dx, sc->dy, 0, 0, 244 WSMOUSE_INPUT_DELTA); 245 } 246 247 return(1); 248 } 249 250