1/* $NetBSD: qvms.c,v 1.3 2021/08/07 16:19:07 thorpej 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.3 2021/08/07 16:19:07 thorpej 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 73struct 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 87static int qvms_match(device_t, cfdata_t, void *); 88static void qvms_attach(device_t, device_t, void *); 89static int qvms_input(void *, int); 90 91CFATTACH_DECL_NEW(qvms, sizeof(struct qvms_softc), 92 qvms_match, qvms_attach, NULL, NULL); 93 94static int qvms_enable(void *); 95static int qvms_ioctl(void *, u_long, void *, int, struct lwp *); 96static void qvms_disable(void *); 97 98const struct wsmouse_accessops qvms_accessops = { 99 qvms_enable, 100 qvms_ioctl, 101 qvms_disable, 102}; 103 104static int 105qvms_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 120static void 121qvms_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 CFARGS_NONE); 143} 144 145static int 146qvms_enable(void *v) 147{ 148 struct qvms_softc *sc = v; 149 150 if (sc->sc_enabled) 151 return EBUSY; 152 153 sc->sc_selftest = 4; /* wait for 4 byte reply upto 1/2 sec */ 154 qvauxputc(sc->qvms_ls, MOUSE_SELF_TEST); 155 (void)tsleep(qvms_enable, TTIPRI, "qvmsopen", hz / 2); 156 if (sc->sc_selftest != 0) { 157 sc->sc_selftest = 0; 158 return ENXIO; 159 } 160 DELAY(150); 161 qvauxputc(sc->qvms_ls, MOUSE_INCREMENTAL); 162 sc->sc_enabled = 1; 163 sc->inputstate = 0; 164 return 0; 165} 166 167static void 168qvms_disable(void *v) 169{ 170 struct qvms_softc *sc = v; 171 172 sc->sc_enabled = 0; 173} 174 175static int 176qvms_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 177{ 178 if (cmd == WSMOUSEIO_GTYPE) { 179 *(u_int *)data = WSMOUSE_TYPE_VSXXX; 180 return 0; 181 } 182 return EPASSTHROUGH; 183} 184 185static int 186qvms_input(void *vsc, int data) 187{ 188 struct qvms_softc *sc = vsc; 189 190 if (sc->sc_enabled == 0) { 191 if (sc->sc_selftest > 0) { 192 sc->sc_selftest -= 1; 193 if (sc->sc_selftest == 0) 194 wakeup(qvms_enable); 195 } 196 return (1); 197 } 198 199#define WSMS_BUTTON1 0x01 200#define WSMS_BUTTON2 0x02 201#define WSMS_BUTTON3 0x04 202 203 if ((data & MOUSE_START_FRAME) != 0) 204 sc->inputstate = 1; 205 else 206 sc->inputstate++; 207 208 if (sc->inputstate == 1) { 209 sc->buttons = 0; 210 if ((data & LEFT_BUTTON) != 0) 211 sc->buttons |= WSMS_BUTTON1; 212 if ((data & MIDDLE_BUTTON) != 0) 213 sc->buttons |= WSMS_BUTTON2; 214 if ((data & RIGHT_BUTTON) != 0) 215 sc->buttons |= WSMS_BUTTON3; 216 217 sc->dx = data & MOUSE_X_SIGN; 218 sc->dy = data & MOUSE_Y_SIGN; 219 } else if (sc->inputstate == 2) { 220 if (sc->dx == 0) 221 sc->dx = -data; 222 else 223 sc->dx = data; 224 } else if (sc->inputstate == 3) { 225 sc->inputstate = 0; 226 if (sc->dy == 0) 227 sc->dy = -data; 228 else 229 sc->dy = data; 230 wsmouse_input(sc->sc_wsmousedev, 231 sc->buttons, 232 sc->dx, sc->dy, 0, 0, 233 WSMOUSE_INPUT_DELTA); 234 } 235 236 return(1); 237} 238 239