[PATCH] evdev: Add support for run-time calibration.

Peter Hutterer peter.hutterer at who-t.net
Wed Oct 29 23:31:55 PDT 2008


Some devices require run-time axis calibration. We can't change the min/max
ranges once we've initialised the valuator structs though, so in-driver
run-time calibration is required.

If the property is set, the driver scales from the calibrated range to the
values reported to the X server (which then may scale to screen coordinates).
If the property is not set (i.e. zero items) no scaling is performed.
---
 include/evdev-properties.h |    4 +++
 man/evdev.man              |    5 ++++
 src/evdev.c                |   50 ++++++++++++++++++++++++++++++++++++++++++++
 src/evdev.h                |    7 ++++++
 4 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/include/evdev-properties.h b/include/evdev-properties.h
index 89f25f1..be4307b 100644
--- a/include/evdev-properties.h
+++ b/include/evdev-properties.h
@@ -58,4 +58,8 @@
 /* CARD8 */
 #define EVDEV_PROP_REOPEN "Evdev Reopen Attempts"
 
+/* Run-time calibration */
+/* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */
+#define EVDEV_PROP_CALIBRATION "Evdev Axis Calibration"
+
 #endif
diff --git a/man/evdev.man b/man/evdev.man
index 9d336fc..fc8a96a 100644
--- a/man/evdev.man
+++ b/man/evdev.man
@@ -186,6 +186,11 @@ value.
 .TP 7
 .BI "Evdev Axis Inversion"
 2 boolean values (8 bit, 0 or 1), order X, Y. 1 inverts the axis.
+.BI "Evdev Axis Calibration"
+4 32-bit values, order min-x, max-x, min-y, max-y or 0 values to disable
+run-time axis calibration. This feature is required for devices that need to
+scale to a different coordinate system than originally reported to the X
+server, such as touchscreens that require run-time calibration.
 
 .SH AUTHORS
 Kristian Høgsberg.
diff --git a/src/evdev.c b/src/evdev.c
index 9ef2829..aa8a10d 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -76,6 +76,7 @@
 #define EVDEV_TOUCHPAD		(1 << 4)
 #define EVDEV_INITIALIZED	(1 << 5) /* WheelInit etc. called already? */
 #define EVDEV_TOUCHSCREEN	(1 << 6)
+#define EVDEV_CALIBRATED	(1 << 7) /* run-time calibrated? */
 
 #define MIN_KEYCODE 8
 #define GLYPHS_PER_KEY 2
@@ -107,6 +108,7 @@ static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
                             XIPropertyValuePtr val, BOOL checkonly);
 static Atom prop_invert = 0;
 static Atom prop_reopen = 0;
+static Atom prop_calibration = 0;
 #endif
 
 
@@ -387,6 +389,17 @@ EvdevReadInput(InputInfoPtr pInfo)
         int abs_x, abs_y;
         abs_x = pEvdev->abs_x;
         abs_y = pEvdev->abs_y;
+
+        if (pEvdev->flags & EVDEV_CALIBRATED)
+        {
+            abs_x = xf86ScaleAxis(abs_x,
+                    pEvdev->max_x, pEvdev->min_x,
+                    pEvdev->calibration.max_x, pEvdev->calibration.min_x);
+            abs_y = xf86ScaleAxis(abs_y,
+                    pEvdev->max_y, pEvdev->min_y,
+                    pEvdev->calibration.max_y, pEvdev->calibration.min_y);
+        }
+
         if (pEvdev->invert_x)
             abs_x = pEvdev->max_x - (abs_x - pEvdev->min_x);
         if (pEvdev->invert_y)
@@ -1542,6 +1555,16 @@ EvdevInitProperty(DeviceIntPtr dev)
         return;
 
     XISetDevicePropertyDeletable(dev, prop_reopen, FALSE);
+
+
+    prop_calibration = MakeAtom(EVDEV_PROP_CALIBRATION,
+                                strlen(EVDEV_PROP_CALIBRATION), TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER, 32,
+                                PropModeReplace, 0, NULL, FALSE);
+    if (rc != Success)
+        return;
+
+    XISetDevicePropertyDeletable(dev, prop_calibration, FALSE);
 }
 
 static int
@@ -1570,6 +1593,33 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
 
         if (!checkonly)
             pEvdev->reopen_attempts = *((CARD8*)val->data);
+    } else 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)
+            {
+                pEvdev->flags &= ~EVDEV_CALIBRATED;
+                pEvdev->calibration.min_x = 0;
+                pEvdev->calibration.max_x = 0;
+                pEvdev->calibration.min_y = 0;
+                pEvdev->calibration.max_y = 0;
+            } else if (val->size == 4)
+            {
+                CARD32 *vals = (CARD32*)val->data;
+
+                pEvdev->flags |= EVDEV_CALIBRATED;
+                pEvdev->calibration.min_x = vals[0];
+                pEvdev->calibration.max_x = vals[1];
+                pEvdev->calibration.min_y = vals[2];
+                pEvdev->calibration.max_y = vals[3];
+            }
+        }
     }
 
     return Success;
diff --git a/src/evdev.h b/src/evdev.h
index 5a97185..5696978 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -102,6 +102,13 @@ typedef struct {
         Time                expires;     /* time of expiry */
         Time                timeout;
     } emulateWheel;
+    /* run-time calibration */
+    struct {
+        int                 min_x;
+        int                 max_x;
+        int                 min_y;
+        int                 max_y;
+    } calibration;
 
     unsigned char btnmap[32];           /* config-file specified button mapping */
 
-- 
1.5.4.3

Cheers,
  Peter



More information about the xorg mailing list