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