summaryrefslogtreecommitdiff
path: root/sys/dev/sun/sunms.c
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-05-20 18:22:34 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-05-20 18:22:34 +0000
commitae4392e18d464ca5c9974696dfc309c032c0830c (patch)
tree7b7ddb329ff1c5e9062099a6d93d1211543e3a3e /sys/dev/sun/sunms.c
parentc18b8a1b0101be40280a8fa45d190b4d7dfa3dba (diff)
Add code to attach sun mice on sparc and sparc64 as wsmouse devices. Since
not all Sun mice run at the canonical 1200 bps, hop between 1200, 4800 and 9600 bps by paying attention to breaks on the line. Attachement and engine code written 7 years ago for OpenBSD/sparc, except for sparc64 com(4) attachment. Speed hop idea borrowed from Opensolaris. This allows sparc and sparc64 users to run X11 without needing a configuration file anymore, as it was in the XFree86 3.x days. Multihead configurations will still need a minimal configuration file, though.
Diffstat (limited to 'sys/dev/sun/sunms.c')
-rw-r--r--sys/dev/sun/sunms.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/sys/dev/sun/sunms.c b/sys/dev/sun/sunms.c
new file mode 100644
index 00000000000..c0eb3a925f8
--- /dev/null
+++ b/sys/dev/sun/sunms.c
@@ -0,0 +1,241 @@
+/* $OpenBSD: sunms.c,v 1.1 2009/05/20 18:22:33 miod Exp $ */
+
+/*
+ * Copyright (c) 2002, 2009, Miodrag Vallat
+ * All rights reserved.
+ *
+ * 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 AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Common Sun mouse handling code.
+ *
+ * This code supports 3- and 5- byte Mouse Systems protocols, and speeds of
+ * 1200, 4800 and 9600 bps.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/timeout.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsmousevar.h>
+
+#include <dev/sun/sunmsvar.h>
+
+void
+sunms_attach(struct sunms_softc *sc, const struct wsmouse_accessops *ao)
+{
+ struct wsmousedev_attach_args a;
+
+ printf("\n");
+
+ /* Initialize state machine. */
+ sc->sc_state = STATE_PROBING;
+ sc->sc_bps = INIT_SPEED;
+ timeout_set(&sc->sc_abort_tmo, sunms_abort_input, sc);
+
+ /*
+ * Note that it doesn't matter if a long time elapses between this
+ * and the moment interrupts are enabled, as we either have the
+ * right speed, and will switch to decode state, or get a break
+ * or a framing error, causing an immediate speed change.
+ */
+ getmicrotime(&sc->sc_lastbpschange);
+
+ a.accessops = ao;
+ a.accesscookie = sc;
+ sc->sc_wsmousedev = config_found(&sc->sc_dev, &a, wsmousedevprint);
+}
+
+int
+sunms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+#if 0
+ struct sunms_softc *sc = v;
+#endif
+
+ switch (cmd) {
+ case WSMOUSEIO_GTYPE:
+ *(u_int *)data = WSMOUSE_TYPE_SUN;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Reinitialize the line to a different speed. Invoked at spltty().
+ */
+void
+sunms_speed_change(struct sunms_softc *sc)
+{
+ uint bps;
+
+ switch (sc->sc_bps) {
+ default:
+ case 9600:
+ bps = 4800;
+ break;
+ case 4800:
+ bps = 1200;
+ break;
+ case 1200:
+ bps = 9600;
+ break;
+ }
+
+#ifdef DEBUG
+ printf("%s: %d bps\n", sc->sc_dev.dv_xname, bps);
+#endif
+ microtime(&sc->sc_lastbpschange);
+
+ (*sc->sc_speed_change)(sc, bps);
+ sc->sc_state = STATE_PROBING;
+ sc->sc_bps = bps;
+ sc->sc_brk = 0;
+ timeout_del(&sc->sc_abort_tmo);
+}
+
+/*
+ * Process actual mouse data. Invoked at spltty().
+ */
+void
+sunms_input(struct sunms_softc *sc, int c)
+{
+ struct timeval curtime;
+
+ if (sc->sc_wsmousedev == NULL)
+ return; /* why bother */
+
+ if (sc->sc_state == STATE_RATE_CHANGE)
+ return; /* not ready yet */
+
+ /*
+ * If we have changed speed recently, ignore data for a few
+ * milliseconds to make sure that either we'll detect the speed
+ * is still not correct, or discard potential noise resulting
+ * from the speed change.
+ */
+ if (sc->sc_state == STATE_PROBING) {
+ microtime(&curtime);
+ timersub(&curtime, &sc->sc_lastbpschange, &curtime);
+ if (curtime.tv_sec != 0 ||
+ curtime.tv_usec >= 200 * 1000) {
+ sc->sc_state = STATE_DECODING;
+ sc->sc_byteno = -1;
+ } else
+ return;
+ }
+
+ /*
+ * The Sun mice use either 3 byte or 5 byte packets. The
+ * first byte of each packet has the topmost bit set;
+ * however motion parts of the packet may have the topmost
+ * bit set too; so we only check for a first byte pattern
+ * when we are not currently processing a packet.
+ */
+ if (sc->sc_byteno < 0) {
+ if (ISSET(c, 0x80) && !ISSET(c, 0x30))
+ sc->sc_byteno = 0;
+ else
+ return;
+ }
+
+ switch (sc->sc_byteno) {
+ case 0:
+ /*
+ * First packet has bit 7 set; bits 0-2 are button states,
+ * and bit 3 is set if it is a short (3 byte) packet.
+ * On the Tadpole SPARCbook, mice connected to the external
+ * connector will also have bit 6 set to allow it to be
+ * differenciated from the onboard pointer.
+ */
+ sc->sc_pktlen = ISSET(c, 0x08) ? 3 : 5;
+ sc->sc_mb = 0;
+ if (!ISSET(c, 1 << 2)) /* left button */
+ sc->sc_mb |= 1 << 0;
+ if (!ISSET(c, 1 << 1)) /* middle button */
+ sc->sc_mb |= 1 << 1;
+ if (!ISSET(c, 1 << 0)) /* right button */
+ sc->sc_mb |= 1 << 2;
+ sc->sc_byteno++;
+
+ /*
+ * In case we do not receive the whole packet, we need
+ * to be able to reset sc_byteno.
+ *
+ * At 1200bps 8N2, a five byte packet will span 50 bits
+ * and thus will transmit in 1/24 second, or about 42ms.
+ *
+ * A reset timeout of 100ms will be more than enough.
+ */
+ timeout_add_msec(&sc->sc_abort_tmo, 100);
+
+ break;
+ case 1:
+ case 3:
+ /*
+ * Following bytes contain signed 7 bit X, then Y deltas.
+ * Short packets only have one set of deltas (and are
+ * thus usually used on 4800 baud mice).
+ */
+ sc->sc_dx += (int8_t)c;
+ sc->sc_byteno++;
+ break;
+ case 2:
+ case 4:
+ sc->sc_dy += (int8_t)c;
+ sc->sc_byteno++;
+ break;
+ }
+
+ if (sc->sc_byteno == sc->sc_pktlen) {
+ timeout_del(&sc->sc_abort_tmo);
+ sc->sc_byteno = -1;
+ wsmouse_input(sc->sc_wsmousedev, sc->sc_mb,
+ sc->sc_dx, sc->sc_dy, 0, 0, WSMOUSE_INPUT_DELTA);
+ sc->sc_dx = sc->sc_dy = 0;
+ }
+}
+
+void
+sunms_abort_input(void *v)
+{
+ struct sunms_softc *sc = v;
+ int s;
+
+#ifdef DEBUG
+ printf("aborting incomplete packet\n");
+#endif
+ s = spltty();
+ sc->sc_byteno = -1;
+ splx(s);
+}