summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@openbsd.org>2009-11-25 18:10:26 +0000
committerMatthieu Herrb <matthieu@openbsd.org>2009-11-25 18:10:26 +0000
commit8f301ca04fca91fcba4d8f6f70200b4f9a006d66 (patch)
tree02d837cbb1b7fd97952f92aff9850e56b291936e
parent4d60b61a606d333bc76b420ba80174be672d35c0 (diff)
Implement device properties for calibration data.
Setting the properties also write to the kernel table. The calibration code can now change the data without quitting X.
-rw-r--r--Makefile.am2
-rw-r--r--include/Makefile.am2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/ws.c130
4 files changed, 135 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 52b7eba..657885c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,4 +14,4 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
AUTOMAKE_OPTIONS= foreign
-SUBDIRS= src man
+SUBDIRS= src man include
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..15138e4
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,2 @@
+EXTRA_DIST = ws-properties.h
+sdk_HEADERS = ws-properties.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 50ece5d..1ed52fa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,4 +19,6 @@ AM_CFLAGS = $(XORG_CFLAGS)
@DRIVER_NAME@_drv_la_LDFLAGS= -module -avoid-version
@DRIVER_NAME@_drv_ladir= @inputdir@
+INCLUDES=-I$(top_srcdir)/include/
+
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c
diff --git a/src/ws.c b/src/ws.c
index d838244..f90482f 100644
--- a/src/ws.c
+++ b/src/ws.c
@@ -36,6 +36,16 @@
#include <mipointer.h>
#include <extinit.h>
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
+#define HAVE_PROPERTIES 1
+#endif
+
+#ifdef HAVE_PROPERTIES
+#include <X11/Xatom.h>
+#include "ws-properties.h"
+#endif
+
+
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
#include <X11/Xatom.h>
#include <xserver-properties.h>
@@ -81,6 +91,13 @@ static Bool wsOpen(InputInfoPtr);
static void wsClose(InputInfoPtr);
static void wsControlProc(DeviceIntPtr , PtrCtrl *);
+#ifdef HAVE_PROPERTIES
+static void wsInitProperty(DeviceIntPtr);
+static int wsSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
+
+static Atom prop_calibration = 0;
+static Atom prop_swap = 0;
+#endif
static XF86ModuleVersionInfo VersionRec = {
"ws",
@@ -471,6 +488,10 @@ wsDeviceInit(DeviceIntPtr pWS)
if (wsOpen(pInfo) != Success) {
return !Success;
}
+#ifdef HAVE_PROPERTIES
+ wsInitProperty(pWS);
+ XIRegisterPropertyHandler(pWS, wsSetProperty, NULL, NULL);
+#endif
return Success;
}
@@ -772,3 +793,112 @@ wsControlProc(DeviceIntPtr device, PtrCtrl *ctrl)
priv->den = ctrl->den;
priv->threshold = ctrl->threshold;
}
+
+#ifdef HAVE_PROPERTIES
+static void
+wsInitProperty(DeviceIntPtr device)
+{
+ InputInfoPtr pInfo = device->public.devicePrivate;
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ int rc;
+
+ DBG(1, ErrorF("wsInitProperty\n"));
+ if (priv->type != WSMOUSE_TYPE_TPANEL)
+ return;
+
+ prop_calibration = MakeAtom(WS_PROP_CALIBRATION,
+ strlen(WS_PROP_CALIBRATION), TRUE);
+ rc = XIChangeDeviceProperty(device, prop_calibration, XA_INTEGER, 32,
+ PropModeReplace, 4, &priv->min_x, FALSE);
+ if (rc != Success)
+ return;
+
+ XISetDevicePropertyDeletable(device, prop_calibration, FALSE);
+
+ prop_swap = MakeAtom(WS_PROP_SWAP_AXES,
+ strlen(WS_PROP_SWAP_AXES), TRUE);
+ rc = XIChangeDeviceProperty(device, prop_swap, XA_INTEGER, 8,
+ PropModeReplace, 1, &priv->swap_axes, FALSE);
+ if (rc != Success)
+ return;
+ return;
+}
+
+static int
+wsSetProperty(DeviceIntPtr device, Atom atom, XIPropertyValuePtr val,
+ BOOL checkonly)
+{
+ InputInfoPtr pInfo = device->public.devicePrivate;
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+ struct wsmouse_calibcoords coords;
+ int need_update = 0;
+
+ DBG(1, ErrorF("wsSetProperty\n"));
+
+ /* Ignore non panel devices */
+ if (priv->type != WSMOUSE_TYPE_TPANEL)
+ return Success;
+
+ if (atom == prop_calibration) {
+ if (val->format != 32 || val->type != XA_INTEGER)
+ return BadMatch;
+ if (val->size != 4 && val->size != 0)
+ return BadMatch;
+ if (!checkonly) {
+ if (val->size == 0) {
+ DBG(1, ErrorF(" uncalibrate\n"));
+ priv->min_x = 0;
+ priv->max_x = -1;
+ priv->min_y = 0;
+ priv->max_y = -1;
+ } else {
+ priv->min_x = ((int *)(val->data))[0];
+ priv->max_x = ((int *)(val->data))[1];
+ priv->min_y = ((int *)(val->data))[2];
+ priv->max_y = ((int *)(val->data))[3];
+ DBG(1, ErrorF(" calibrate %d %d %d %d\n",
+ priv->min_x, priv->max_x,
+ priv->min_y, priv->max_y));
+ need_update++;
+ }
+ /* Update axes descriptors */
+ InitValuatorAxisStruct(device, 0,
+ priv->min_x, priv->max_x, 1, 0, 1);
+ InitValuatorAxisStruct(device, 1,
+ priv->min_y, priv->max_y, 1, 0, 1);
+ }
+ } else if (atom == prop_swap) {
+ if (val->format != 8 || val->type != XA_INTEGER ||
+ val->size != 1)
+ return BadMatch;
+ if (!checkonly) {
+ priv->swap_axes = *((BOOL *)val->data);
+ DBG(1, ErrorF("swap_axes %d\n", priv->swap_axes));
+ need_update++;
+ }
+ } else {
+ return BadMatch;
+ }
+ if (need_update) {
+ /* Update the saved values to be restored on device off */
+ priv->coords.minx = priv->min_x;
+ priv->coords.maxx = priv->max_x;
+ priv->coords.miny = priv->min_y;
+ priv->coords.maxy = priv->max_y;
+ priv->coords.swapxy = priv->swap_axes;
+
+ /* Update the kernel calibration table */
+ coords.minx = priv->min_x;
+ coords.maxx = priv->max_x;
+ coords.miny = priv->min_y;
+ coords.maxy = priv->max_y;
+ coords.swapxy = priv->swap_axes;
+ coords.samplelen = priv->raw;
+ if (ioctl(pInfo->fd, WSMOUSEIO_SCALIBCOORDS, &coords) != 0) {
+ xf86Msg(X_ERROR, "SCALIBCOORDS failed %s\n",
+ strerror(errno));
+ }
+ }
+ return Success;
+}
+#endif