1 /* $NetBSD: dzms.c,v 1.21 2009/05/12 14:18:16 cegger 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.21 2009/05/12 14:18:16 cegger 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 device_t sc_wsmousedev; 83 }; 84 85 static int dzms_match(device_t, cfdata_t, void *); 86 static void dzms_attach(device_t, device_t, 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(device_t parent, cfdata_t cf, void *aux) 104 { 105 struct dzkm_attach_args *daa = aux; 106 107 /* Exact match is better than wildcard. */ 108 if (cf->cf_loc[DZCF_LINE] == daa->daa_line) 109 return 2; 110 111 /* This driver accepts wildcard. */ 112 if (cf->cf_loc[DZCF_LINE] == DZCF_LINE_DEFAULT) 113 return 1; 114 115 return 0; 116 } 117 118 static void 119 dzms_attach(device_t parent, device_t self, void *aux) 120 { 121 struct dz_softc *dz = device_private(parent); 122 struct dzms_softc *dzms = device_private(self); 123 struct dzkm_attach_args *daa = aux; 124 struct dz_linestate *ls; 125 struct wsmousedev_attach_args a; 126 127 dz->sc_dz[daa->daa_line].dz_catch = dzms_input; 128 dz->sc_dz[daa->daa_line].dz_private = dzms; 129 ls = &dz->sc_dz[daa->daa_line]; 130 dzms->dzms_ls = ls; 131 132 printf("\n"); 133 134 a.accessops = &dzms_accessops; 135 a.accesscookie = dzms; 136 137 dzms->sc_enabled = 0; 138 dzms->sc_selftest = 0; 139 dzms->sc_wsmousedev = config_found(self, &a, wsmousedevprint); 140 } 141 142 static int 143 dzms_enable(void *v) 144 { 145 struct dzms_softc *sc = v; 146 147 if (sc->sc_enabled) 148 return EBUSY; 149 150 sc->sc_selftest = 4; /* wait for 4 byte reply upto 1/2 sec */ 151 dzputc(sc->dzms_ls, MOUSE_SELF_TEST); 152 (void)tsleep(dzms_enable, TTIPRI, "dzmsopen", hz / 2); 153 if (sc->sc_selftest != 0) { 154 sc->sc_selftest = 0; 155 return ENXIO; 156 } 157 DELAY(150); 158 dzputc(sc->dzms_ls, MOUSE_INCREMENTAL); 159 sc->sc_enabled = 1; 160 sc->inputstate = 0; 161 return 0; 162 } 163 164 static void 165 dzms_disable(void *v) 166 { 167 struct dzms_softc *sc = v; 168 169 sc->sc_enabled = 0; 170 } 171 172 static int 173 dzms_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 174 { 175 if (cmd == WSMOUSEIO_GTYPE) { 176 *(u_int *)data = WSMOUSE_TYPE_VSXXX; 177 return 0; 178 } 179 return EPASSTHROUGH; 180 } 181 182 static int 183 dzms_input(void *vsc, int data) 184 { 185 struct dzms_softc *sc = vsc; 186 187 if (sc->sc_enabled == 0) { 188 if (sc->sc_selftest > 0) { 189 sc->sc_selftest -= 1; 190 if (sc->sc_selftest == 0) 191 wakeup(dzms_enable); 192 } 193 return (1); 194 } 195 196 #define WSMS_BUTTON1 0x01 197 #define WSMS_BUTTON2 0x02 198 #define WSMS_BUTTON3 0x04 199 200 if ((data & MOUSE_START_FRAME) != 0) 201 sc->inputstate = 1; 202 else 203 sc->inputstate++; 204 205 if (sc->inputstate == 1) { 206 sc->buttons = 0; 207 if ((data & LEFT_BUTTON) != 0) 208 sc->buttons |= WSMS_BUTTON1; 209 if ((data & MIDDLE_BUTTON) != 0) 210 sc->buttons |= WSMS_BUTTON2; 211 if ((data & RIGHT_BUTTON) != 0) 212 sc->buttons |= WSMS_BUTTON3; 213 214 sc->dx = data & MOUSE_X_SIGN; 215 sc->dy = data & MOUSE_Y_SIGN; 216 } else if (sc->inputstate == 2) { 217 if (sc->dx == 0) 218 sc->dx = -data; 219 else 220 sc->dx = data; 221 } else if (sc->inputstate == 3) { 222 sc->inputstate = 0; 223 if (sc->dy == 0) 224 sc->dy = -data; 225 else 226 sc->dy = data; 227 wsmouse_input(sc->sc_wsmousedev, 228 sc->buttons, 229 sc->dx, sc->dy, 0, 0, 230 WSMOUSE_INPUT_DELTA); 231 } 232 233 return(1); 234 } 235 236