-/* $OpenBSD: vsms_ws.c,v 1.2 2007/04/10 22:37:17 miod Exp $ */
+/* $OpenBSD: vsms_ws.c,v 1.3 2008/08/22 21:05:07 miod Exp $ */
/* $NetBSD: dzms.c,v 1.1 2000/12/02 17:03:55 ragge Exp $ */
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
+int lkms_handle_error(struct lkms_softc *, int);
+void lkms_input_disabled(struct lkms_softc *, int);
+void lkms_input_mouse(struct lkms_softc *, int);
+void lkms_input_tablet(struct lkms_softc *, int);
+
+#define WSMS_BUTTON(x) (1 << ((x) - 1))
+
struct cfdriver lkms_cd = {
NULL, "lkms", DV_DULL
};
+/*
+ * Report the device type and status on attachment, and return nonzero
+ * if it is not in working state.
+ */
+int
+lkms_handle_error(struct lkms_softc *sc, int mask)
+{
+ int error = sc->sc_error;
+
+#ifdef DEBUG
+ printf("%s: ", sc->dzms_dev.dv_xname);
+#endif
+
+ if (ISSET(sc->sc_flags, MS_TABLET)) {
+#ifdef DEBUG
+ printf("tablet, ");
+#endif
+ /*
+ * If we are a tablet, the stylet vs puck information
+ * is returned as a non-fatal status code. Handle
+ * it there so that this does not get in the way.
+ */
+ switch (error) {
+ case ERROR_TABLET_NO_POINTER:
+ /* i can has cheezpuck? */
+#ifdef DEBUG
+ printf("neither stylus nor puck connected\n");
+#else
+ printf("%s: neither stylus nor puck connected\n",
+ sc->dzms_dev.dv_xname);
+#endif
+ error = ERROR_OK;
+ break;
+ case ERROR_TABLET_STYLUS:
+#ifdef DEBUG
+ printf("stylus\n");
+#endif
+ SET(sc->sc_flags, MS_STYLUS);
+ error = ERROR_OK;
+ break;
+ default:
+#ifdef DEBUG
+ printf("puck\n");
+#endif
+ break;
+ }
+ } else {
+#ifdef DEBUG
+ printf("mouse\n");
+#endif
+ }
+
+ switch (error) {
+ case ERROR_MEMORY_CKSUM_ERROR:
+ printf("%s: memory checksum error\n",
+ sc->dzms_dev.dv_xname);
+ break;
+ case ERROR_BUTTON_ERROR:
+ {
+ int btn;
+
+ /*
+ * Print the list of defective parts
+ */
+ if (ISSET(sc->sc_flags, MS_TABLET)) {
+ if ((mask & FRAME_T_PR) != 0)
+ printf("%s: proximity sensor defective\n",
+ sc->dzms_dev.dv_xname);
+ } else
+ mask <<= 1;
+
+ for (btn = 1; btn < 4; btn++)
+ if ((mask & (1 << btn)) != 0)
+ printf("%s: button %d held down or defective\n",
+ sc->dzms_dev.dv_xname, btn);
+ }
+ break;
+ case ERROR_TABLET_LINK:
+ /* how vague this error is... */
+ printf("%s: analog or digital error\n",
+ sc->dzms_dev.dv_xname);
+ break;
+ default:
+ printf("%s: %sselftest error %02x\n", sc->dzms_dev.dv_xname,
+ error >= ERROR_FATAL ? "fatal " : "", error);
+ break;
+ case ERROR_OK:
+ break;
+ }
+
+ if (error >= ERROR_FATAL)
+ return ENXIO;
+
+ return 0;
+}
+
int
lkms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
{
-#if 0
struct lkms_softc *sc = v;
-#endif
+ struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(int *)data = WSMOUSE_TYPE_VSXXX;
return 0;
+
+ case WSMOUSEIO_GCALIBCOORDS:
+ if (ISSET(sc->sc_flags, MS_TABLET)) {
+ /*
+ * The tablet has a usable size of 11 inch on each
+ * axis, with a 200dpi resolution.
+ */
+ wsmc->minx = 0;
+ wsmc->maxx = 200 * 11;
+ wsmc->miny = 0;
+ wsmc->maxy = 200 * 11;
+ wsmc->swapxy = 0;
+ wsmc->resx = wsmc->maxx; /* anything better? */
+ wsmc->resy = wsmc->maxy; /* anything better? */
+ wsmc->samplelen = 0;
+ return 0;
+ } else
+ break;
}
return -1;
{
struct lkms_softc *sc = vsc;
- if (!sc->sc_enabled) {
- if (sc->sc_selftest > 0) {
- sc->sc_selftest--;
- if (sc->sc_selftest == 0)
- wakeup(&sc->sc_enabled);
+ if ((data & FRAME_MASK) != 0) {
+ sc->sc_frametype = data & FRAME_TYPE_MASK;
+ sc->sc_framepos = 0;
+ } else
+ sc->sc_framepos++;
+
+ if (ISSET(sc->sc_flags, MS_ENABLED) &&
+ !ISSET(sc->sc_flags, MS_SELFTEST)) {
+ switch (sc->sc_frametype) {
+ case FRAME_MOUSE:
+ lkms_input_mouse(sc, data);
+ break;
+ case FRAME_TABLET:
+ lkms_input_tablet(sc, data);
+ break;
}
- return (1);
- }
+ } else
+ lkms_input_disabled(sc, data);
+
+ return 1;
+}
+
+/*
+ * Input processing while the device is disabled. We only are
+ * interested in processing self test frames, so as to identify
+ * the device and report its state.
+ */
+void
+lkms_input_disabled(struct lkms_softc *sc, int data)
+{
+ if (!ISSET(sc->sc_flags, MS_SELFTEST))
+ return;
-#define WSMS_BUTTON1 0x01
-#define WSMS_BUTTON2 0x02
-#define WSMS_BUTTON3 0x04
+ if (sc->sc_frametype == FRAME_SELFTEST) {
+ switch (sc->sc_framepos) {
+ case 0:
+ break;
+ case 1:
+ data &= FRAME_ST_DEVICE_MASK;
+ if (data == FRAME_ST_DEVICE_TABLET)
+ SET(sc->sc_flags, MS_TABLET);
+ else if (data != FRAME_ST_DEVICE_MOUSE) {
+ printf("%s: unrecognized device type %02x\n",
+ sc->dzms_dev.dv_xname, data);
+ goto fail;
+ }
+ break;
+ case 2:
+ sc->sc_error = data;
+ break;
+ case 3:
+ if (lkms_handle_error(sc, data) != 0)
+ goto fail;
+
+ CLR(sc->sc_flags, MS_SELFTEST);
+ goto success;
+ break;
+ }
- if ((data & MOUSE_START_FRAME) != 0)
- sc->inputstate = 1;
- else
- sc->inputstate++;
+ return;
+ } /* else goto fail; */
+
+fail:
+ /*
+ * Our self test frame has been truncated, or we have received
+ * incorrect data (both could be a cable problem), or the
+ * selftest reported an error. The device is unusable.
+ */
+ CLR(sc->sc_flags, MS_TABLET | MS_STYLUS);
+
+success:
+ sc->sc_frametype = 0;
+ wakeup(&sc->sc_flags);
+}
- if (sc->inputstate == 1) {
+/*
+ * Input processing while the device is enabled, for mouse frames.
+ */
+void
+lkms_input_mouse(struct lkms_softc *sc, int data)
+{
+ switch (sc->sc_framepos) {
+ case 0:
sc->buttons = 0;
- if ((data & LEFT_BUTTON) != 0)
- sc->buttons |= WSMS_BUTTON1;
- if ((data & MIDDLE_BUTTON) != 0)
- sc->buttons |= WSMS_BUTTON2;
- if ((data & RIGHT_BUTTON) != 0)
- sc->buttons |= WSMS_BUTTON3;
-
- sc->dx = data & MOUSE_X_SIGN;
- sc->dy = data & MOUSE_Y_SIGN;
- } else if (sc->inputstate == 2) {
+ /* button order is inverted from wscons */
+ if ((data & FRAME_MS_B3) != 0)
+ sc->buttons |= WSMS_BUTTON(1);
+ if ((data & FRAME_MS_B2) != 0)
+ sc->buttons |= WSMS_BUTTON(2);
+ if ((data & FRAME_MS_B1) != 0)
+ sc->buttons |= WSMS_BUTTON(3);
+
+ sc->dx = data & FRAME_MS_X_SIGN;
+ sc->dy = data & FRAME_MS_Y_SIGN;
+ break;
+ case 1:
if (sc->dx == 0)
sc->dx = -data;
else
sc->dx = data;
- } else if (sc->inputstate == 3) {
- sc->inputstate = 0;
+ break;
+ case 2:
if (sc->dy == 0)
sc->dy = -data;
else
sc->dy = data;
wsmouse_input(sc->sc_wsmousedev, sc->buttons,
sc->dx, sc->dy, 0, 0, WSMOUSE_INPUT_DELTA);
+
+ sc->sc_frametype = 0;
+ break;
}
+}
+
+/*
+ * Input processing while the device is enabled, for tablet frames.
+ */
+void
+lkms_input_tablet(struct lkms_softc *sc, int data)
+{
+ switch (sc->sc_framepos) {
+ case 0:
+ /*
+ * Button information will depend on the type of positional
+ * device:
+ * - puck buttons get reported as is, as a 4 button mouse.
+ * Button order is opposite from mouse.
+ * - stylus barrel gets reported as left button, while tip
+ * gets reported as right button.
+ * Proximity sensor gets reported as a fictitious fifth
+ * button.
+ */
+ sc->buttons = 0;
+ if ((data & FRAME_T_B1) != 0)
+ sc->buttons |= WSMS_BUTTON(1);
+ if ((data & FRAME_T_B2) != 0) {
+ if (ISSET(sc->sc_flags, MS_STYLUS))
+ sc->buttons |= WSMS_BUTTON(3);
+ else
+ sc->buttons |= WSMS_BUTTON(2);
+ }
+ if ((data & FRAME_T_B3) != 0)
+ sc->buttons |= WSMS_BUTTON(3);
+ if ((data & FRAME_T_B4) != 0)
+ sc->buttons |= WSMS_BUTTON(4);
+ if ((data & FRAME_T_PR) != 0)
+ sc->buttons |= WSMS_BUTTON(5);
+ break;
+ case 1:
+ sc->dx = data & 0x3f;
+ break;
+ case 2:
+ sc->dx |= (data & 0x3f) << 6;
+ break;
+ case 3:
+ sc->dy = data & 0x3f;
+ break;
+ case 4:
+ sc->dy |= (data & 0x3f) << 6;
+ wsmouse_input(sc->sc_wsmousedev, sc->buttons,
+ sc->dx, sc->dy, 0, 0,
+ WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
- return (1);
+ sc->sc_frametype = 0;
+ break;
+ }
}
-/* $OpenBSD: vsmsvar.h,v 1.1 2006/08/27 16:52:15 miod Exp $ */
+/* $OpenBSD: vsmsvar.h,v 1.2 2008/08/22 21:05:07 miod Exp $ */
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*/
/*
- * Command characters for the mouse.
+ * Command characters
*/
-#define MOUSE_SELF_TEST 'T'
-#define MOUSE_INCREMENTAL 'R'
+#define VS_B9600 'B' /* T only: switch to 9600 bps */
+#define VS_REQUEST_POINT 'D' /* stop incremental position reports */
+#define VS_FREQ_55 'K' /* T only: 55Hz report rate */
+#define VS_FREQ_72 'L' /* T only: 72Hz report rate */
+#define VS_FREQ_120 'M' /* T only: 120Hz report rate, 9600bps */
+#define VS_REQUEST_POSITION 'P' /* request position (in point mode) */
+#define VS_INCREMENTAL 'R' /* incremental position reports */
+#define VS_SELF_TEST 'T' /* reset and self test */
/*
- * Mouse output bits.
- *
- * MOUSE_START_FRAME Start of report frame bit.
- * MOUSE_X_SIGN Sign bit for X.
- * MOUSE_Y_SIGN Sign bit for Y.
- * MOUSE_X_OFFSET X offset to start cursor at.
- * MOUSE_Y_OFFSET Y offset to start cursor at.
+ * Data frame types
+ */
+
+#define FRAME_MASK 0x80
+#define FRAME_TYPE_MASK 0xe0
+#define FRAME_MOUSE 0x80 /* 1 0 0 - mouse 3 byte packet */
+#define FRAME_SELFTEST 0xa0 /* 1 0 1 - selftest 4 byte packet */
+#define FRAME_TABLET 0xc0 /* 1 1 0 - tablet 5 byte packet */
+
+/*
+ * Selftest frame layout
+ * byte 0: frame type and device revision
+ * byte 1: manufacturing location code and device type
+ * byte 2: self test result
+ * byte 3: button mask (if result == button error)
+ */
+
+/* byte 0 */
+#define FRAME_ST_REV_MASK 0x0f /* device revision */
+
+/* byte 1 */
+#define FRAME_ST_LOCATION_MASK 0x70
+#define FRAME_ST_DEVICE_MASK 0x0f
+#define FRAME_ST_DEVICE_MOUSE 0x02
+#define FRAME_ST_DEVICE_TABLET 0x04
+
+/* status test error codes */
+#define ERROR_OK 0x00
+#define ERROR_TABLET_STYLUS 0x11 /* stylus only, no puck */
+#define ERROR_TABLET_NO_POINTER 0x13 /* neither stylus nor puck */
+#define ERROR_FATAL 0x20 /* fatal errors from here */
+#define ERROR_TABLET_LINK 0x3a /* tablet internal error */
+#define ERROR_BUTTON_ERROR 0x3d /* button malfunction */
+#define ERROR_MEMORY_CKSUM_ERROR 0x3e /* firmware malfunction */
+
+/*
+ * Mouse frame layout
+ * byte 0: frame type, delta signs, button mask
+ * byte 1: unsigned X delta
+ * byte 2: unsigned Y delta
*/
-#define MOUSE_START_FRAME 0x80
-#define MOUSE_X_SIGN 0x10
-#define MOUSE_Y_SIGN 0x08
+#define FRAME_MS_X_SIGN 0x10 /* set if positive */
+#define FRAME_MS_Y_SIGN 0x08 /* set if positive */
+#define FRAME_MS_B3 0x04 /* left button */
+#define FRAME_MS_B2 0x02 /* middle button */
+#define FRAME_MS_B1 0x01 /* right button */
/*
- * Definitions for mouse buttons
+ * Tablet frame layout
+ * byte 0: frame type, button and proximity sensor mask
+ * byte 1: low 6 bits of absolute X position
+ * byte 2: high 6 bits of absolute X position
+ * byte 3: low 6 bits of absolute Y position
+ * byte 4: high 6 bits of absolute Y position
*/
-#define RIGHT_BUTTON 0x01
-#define MIDDLE_BUTTON 0x02
-#define LEFT_BUTTON 0x04
+#define FRAME_T_B4 0x10 /* puck bottom button */
+#define FRAME_T_B3 0x08 /* puck right button */
+#define FRAME_T_B2 0x04 /* puck top / stylus tip */
+#define FRAME_T_B1 0x02 /* puck left / stylus barrel */
+#define FRAME_T_PR 0x01 /* stylus proximity (if zero) */
struct lkms_softc { /* driver status information */
struct device dzms_dev; /* required first: base device */
- int sc_enabled; /* input enabled? */
- int sc_selftest;
+ int sc_flags;
+#define MS_ENABLED 0x01 /* input enabled */
+#define MS_SELFTEST 0x02 /* selftest in progress */
+#define MS_TABLET 0x04 /* device is a tablet */
+#define MS_STYLUS 0x08 /* tablet has a stylus, not a puck */
+
+ int sc_frametype; /* frame type being processed */
+ u_int sc_framepos; /* position in the frame */
+ int sc_error; /* selftest error result */
- int inputstate;
- u_int buttons;
- int dx, dy;
+ u_int buttons;
+ int dx, dy;
struct device *sc_wsmousedev;
};