/* $NetBSD: qms.c,v 1.22 2022/09/27 06:36:42 skrll Exp $ */ /*- * Copyright (c) 2001 Reinoud Zandijk * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Reinoud Zandijk * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Quadrature mouse driver for the wscons as used in the IOMD */ #include __KERNEL_RCSID(0, "$NetBSD: qms.c,v 1.22 2022/09/27 06:36:42 skrll Exp $"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct qms_softc { device_t sc_dev; device_t sc_wsmousedev; bus_space_tag_t sc_iot; /* bus tag */ bus_space_handle_t sc_ioh; /* bus handle for XY */ bus_space_handle_t sc_butioh; /* bus handle for buttons */ struct callout sc_callout; uint16_t lastx; uint16_t lasty; int lastb; }; /* Offsets of hardware registers */ #define QMS_MOUSEX 0 /* 16 bits X register */ #define QMS_MOUSEY 1 /* 16 bits Y register */ #define QMS_BUTTONS 0 /* mouse buttons in bits 4,5,6 */ static int qms_match(device_t , cfdata_t , void *); static void qms_attach(device_t , device_t , void *); static int qms_enable(void *); static int qms_ioctl(void *, u_long, void *, int, struct lwp *); static void qms_disable(void *cookie); static void qms_intr(void *arg); CFATTACH_DECL_NEW(qms, sizeof(struct qms_softc), qms_match, qms_attach, NULL, NULL); static struct wsmouse_accessops qms_accessops = { qms_enable, qms_ioctl, qms_disable }; static int qms_match(device_t parent, cfdata_t cf, void *aux) { struct qms_attach_args *qa = aux; if (strcmp(qa->qa_name, "qms") == 0) return 1; return 0; } static void qms_attach(device_t parent, device_t self, void *aux) { struct qms_softc *sc = device_private(self); struct qms_attach_args *qa = aux; struct wsmousedev_attach_args wsmouseargs; sc->sc_dev = self; sc->sc_iot = qa->qa_iot; sc->sc_ioh = qa->qa_ioh; sc->sc_butioh = qa->qa_ioh_but; /* set up wsmouse attach arguments */ wsmouseargs.accessops = &qms_accessops; wsmouseargs.accesscookie = sc; aprint_normal("\n"); sc->sc_wsmousedev = config_found(sc->sc_dev, &wsmouseargs, wsmousedevprint, CFARGS_NONE); callout_init(&sc->sc_callout, 0); } static int qms_enable(void *cookie) { struct qms_softc *sc = cookie; int b; /* We don't want the mouse to warp on open. */ sc->lastx = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QMS_MOUSEX); sc->lasty = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QMS_MOUSEY); b = bus_space_read_1(sc->sc_iot, sc->sc_butioh, QMS_BUTTONS) & 0x70; /* patch up the buttons */ b >>= 4; sc->lastb = ~( ((b & 1)<<2) | (b & 2) | ((b & 4)>>2)); callout_reset(&sc->sc_callout, hz / 100, qms_intr, sc); return 0; } static void qms_disable(void *cookie) { struct qms_softc *sc = cookie; callout_stop(&sc->sc_callout); } static int qms_ioctl(void *cookie, u_long cmd, void *data, int flag, struct lwp *l) { switch (cmd) { case WSMOUSEIO_GTYPE: *(int *)data = WSMOUSE_TYPE_ARCHIMEDES; return 0; } return EPASSTHROUGH; } static void qms_intr(void *arg) { struct qms_softc *sc = arg; int b; uint16_t x, y; int16_t dx, dy; x = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QMS_MOUSEX); y = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QMS_MOUSEY); b = bus_space_read_1(sc->sc_iot, sc->sc_butioh, QMS_BUTTONS) & 0x70; /* patch up the buttons */ b >>= 4; b = ~( ((b & 1)<<2) | (b & 2) | ((b & 4)>>2)); if ((x != sc->lastx) || (y != sc->lasty) || (b != sc->lastb)) { /* This assumes that int16_t is two's complement. */ dx = x - sc->lastx; dy = y - sc->lasty; wsmouse_input(sc->sc_wsmousedev, b, dx, dy, 0, 0, WSMOUSE_INPUT_DELTA); /* save old values */ sc->lastx = x; sc->lasty = y; sc->lastb = b; } callout_reset(&sc->sc_callout, hz / 100, qms_intr, sc); } /* end of qms.c */