[PATCH 09/15] Add four new motion filters

Daniel Stone daniel at fooishbar.org
Thu Jun 9 12:57:30 PDT 2011


From: Derek Foreman <derek.foreman at collabora.co.uk>

Attempt to decrease the possibility of errant motion as much as possible
by adding three new configurable filters, disabled by default:
    - Synaptics Max Jerk: maximum change in acceleration before the
      packet is declared errant (xorg.conf MaxJerk)
    - Synaptics Max Accel: maximum acceleration the pointer can have
      before being declared errant (xorg.conf MaxAccel)
    - Synaptics Max Error: maximum error from a best-fit prediction of
      the next position before being declared errant (xorg.conf MaxError)
    - Synaptics Max Distance: maximum distance a finger can move in a
      single report before being declared errant (xorg.conf MaxDistance)

Signed-off-by: Derek Foreman <derek.foreman at collabora.co.uk>
Reviewed-by: Daniel Stone <daniel at fooishbar.org>
---
 include/synaptics-properties.h |   12 ++++++++++
 man/synaptics.man              |   23 ++++++++++++++++++++
 src/properties.c               |   46 +++++++++++++++++++++++++++++++++++++++-
 src/synaptics.c                |   44 ++++++++++++++++++++++++++++++++++++++
 src/synapticsstr.h             |    6 +++++
 5 files changed, 130 insertions(+), 1 deletions(-)

diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h
index 77a1806..3e54fbb 100644
--- a/include/synaptics-properties.h
+++ b/include/synaptics-properties.h
@@ -158,4 +158,16 @@
 /* 32 Bit Integer, 2 values, horizontal hysteresis, vertical hysteresis */
 #define SYNAPTICS_PROP_NOISE_CANCELLATION "Synaptics Noise Cancellation"
 
+/* FLOAT */
+#define SYNAPTICS_PROP_MAX_DISTANCE "Synaptics Max Distance"
+
+/* FLOAT */
+#define SYNAPTICS_PROP_MAX_JERK "Synaptics Max Jerk"
+
+/* FLOAT */
+#define SYNAPTICS_PROP_MAX_ACCEL "Synaptics Max Accel"
+
+/* FLOAT */
+#define SYNAPTICS_PROP_MAX_ERROR "Synaptics Max Error"
+
 #endif /* _SYNAPTICS_PROPERTIES_H_ */
diff --git a/man/synaptics.man b/man/synaptics.man
index cb5f4c6..5b365e6 100644
--- a/man/synaptics.man
+++ b/man/synaptics.man
@@ -510,6 +510,29 @@ AreaBottomEdge option to any integer value other than zero. If supported by the
 server (version 1.9 and later), the edge may be specified in percent of
 the total height of the touchpad. Property: "Synaptics Area"
 .
+.TP
+.BI "Option \*qMaxAccel\*q \*q" integer \*q
+If acceleration increases beyond the specified value, ignore the packet that
+provoked it, assuming that it is erroneous. Property: "Synaptics Max Accel"
+.
+.TP
+.BI "Option \*qMaxDistance\*q \*q" integer \*q
+Ignore any single packet containing movement greater than the specified value
+in pixels, assuming that it is erroneous. Property: "Synaptics Max Distance"
+.
+.TP
+.BI "Option \*qMaxError\*q \*q" integer \*q
+Ignore any single packet containing movement where the error from a best-fit
+line determining the expected pointer position from historical values is larger
+than the specified value, assuming that it is erroneous.
+Property: "Synaptics Max Error"
+.
+.TP
+.BI "Option \*qMaxJerk\*q \*q" integer \*q
+If the derivative of acceleration increases beyond the specified value, ignore
+the packet that provoked it, assuming that it is erroneous.
+Property: "Synaptics Max Jerk"
+.
 
 .SH CONFIGURATION DETAILS
 .SS Area handling
diff --git a/src/properties.c b/src/properties.c
index 8370c0b..ad4c026 100644
--- a/src/properties.c
+++ b/src/properties.c
@@ -94,6 +94,10 @@ Atom prop_area                  = 0;
 Atom prop_noise_cancellation    = 0;
 Atom prop_product_id            = 0;
 Atom prop_device_node           = 0;
+Atom prop_max_distance          = 0;
+Atom prop_max_jerk              = 0;
+Atom prop_max_accel             = 0;
+Atom prop_max_error             = 0;
 
 static Atom
 InitAtom(DeviceIntPtr dev, char *name, int format, int nvalues, int *values)
@@ -313,6 +317,17 @@ InitDeviceProperties(InputInfoPtr pInfo)
         XISetDevicePropertyDeletable(pInfo->dev, prop_device_node, FALSE);
     }
 
+    fvalues[0] = para->max_distance;
+    prop_max_distance = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_MAX_DISTANCE, 1, fvalues);
+
+    fvalues[0] = para->max_jerk;
+    prop_max_jerk = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_MAX_JERK, 1, fvalues);
+
+    fvalues[0] = para->max_accel;
+    prop_max_accel = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_MAX_ACCEL, 1, fvalues);
+
+    fvalues[0] = para->max_error;
+    prop_max_error = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_MAX_ERROR, 1, fvalues);
 }
 
 int
@@ -694,8 +709,37 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
             return BadValue;
         para->hyst_x = hyst[0];
         para->hyst_y = hyst[1];
-    } else if (property == prop_product_id || property == prop_device_node)
+    } else if (property == prop_product_id || property == prop_device_node) {
         return BadValue; /* read-only */
+    } else if (property == prop_max_distance) {
+        float max_distance;
+        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
+            return BadMatch;
+
+        max_distance = *(float*)prop->data;
+        para->max_distance = max_distance;
+    } else if (property == prop_max_jerk) {
+        float max_jerk;
+        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
+            return BadMatch;
+
+        max_jerk = *(float*)prop->data;
+        para->max_jerk = max_jerk;
+    } else if (property == prop_max_accel) {
+        float max_accel;
+        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
+            return BadMatch;
+
+        max_accel = *(float*)prop->data;
+        para->max_accel = max_accel;
+    } else if (property == prop_max_error) {
+        float max_error;
+        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
+            return BadMatch;
+
+        max_error = *(float*)prop->data;
+        para->max_error = max_error;
+    }
 
     return Success;
 }
diff --git a/src/synaptics.c b/src/synaptics.c
index 560f166..4c408d9 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -573,6 +573,11 @@ static void set_default_parameters(InputInfoPtr pInfo)
     pars->resolution_horiz = xf86SetIntOption(opts, "HorizResolution", horizResolution);
     pars->resolution_vert = xf86SetIntOption(opts, "VertResolution", vertResolution);
 
+    pars->max_jerk = xf86SetRealOption(opts, "MaxJerk", 0.0);
+    pars->max_distance = xf86SetRealOption(opts, "MaxDistance", 0.0);
+    pars->max_accel = xf86SetRealOption(opts, "MaxAccel", 0.0);
+    pars->max_error = xf86SetRealOption(opts, "MaxError", 0.0);
+
     /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
     if (pars->top_edge > pars->bottom_edge) {
 	int tmp = pars->top_edge;
@@ -1801,6 +1806,33 @@ static void regress(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
     double yb1n = 0, xb1n = 0, b1d = 0, xb1, yb1;
     double dista, distb, distc, vela, velb, velc, acca, accb, jerk;
 
+    if (pars->max_distance &&
+        hypot(hw->x - HIST(0).x, hw->y - HIST(0).y) > pars->max_distance)
+        goto filtered;
+
+    if (pars->max_accel > 0 || pars->max_jerk > 0) {
+        if (priv->count_packet_finger < 3) {
+            *dx = 0;
+            *dy = 0;
+            return;
+        }
+
+        dista = hypot(HIST(0).x - hw->x, HIST(0).y - hw->y);
+        distb = hypot(HIST_DELTA(1, 0, x), HIST_DELTA(1, 0, y));
+        distc = hypot(HIST_DELTA(2, 1, x), HIST_DELTA(2, 1, y));
+        vela = dista / (HIST(0).millis - hw->millis);
+        velb = distb / HIST_DELTA(1, 0, millis);
+        velc = distc / HIST_DELTA(2, 1, millis);
+        acca = (vela - velb) / (HIST(1).millis - hw->millis);
+        if (pars->max_accel > 0 && fabs(acca) > pars->max_accel)
+            goto filtered;
+
+        accb = (velc - velb) / HIST_DELTA(2, 0, millis);
+        jerk = (acca - accb) / (HIST(2).millis - hw->millis);
+        if (pars->max_jerk > 0 && fabs(jerk) > pars->max_jerk)
+            goto filtered;
+    }
+
     if (priv->count_packet_finger == 1) {
         *dx = hw->x - HIST(0).x;
         *dy = hw->y - HIST(0).y;
@@ -1826,6 +1858,18 @@ static void regress(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
     xb1 = xb1n/b1d;
     yb1 = yb1n/b1d;
 
+    if (pars->max_error > 0) {
+        double X, Y, e, xb0, yb0;
+
+        xb0 = xm - xb1*tm;
+        yb0 = ym - yb1*tm;
+        X = xb1*(hw->millis - HIST(0).millis) + xb0;
+        Y = yb1*(hw->millis - HIST(0).millis) + yb0;
+        e = hypot(hw->x - X, hw->y - Y);
+        if (e > pars->max_error)
+            goto filtered;
+    }
+
     *dx = xb1 * (hw->millis - start_time);
     *dy = yb1 * (hw->millis - start_time);
     return;
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
index a496212..73893cf 100644
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -163,6 +163,12 @@ typedef struct _SynapticsParameters
     Bool tap_and_drag_gesture;		    /* Switches the tap-and-drag gesture on/off */
     unsigned int resolution_horiz;          /* horizontal resolution of touchpad in units/mm */
     unsigned int resolution_vert;           /* vertical resolution of touchpad in units/mm */
+
+    double max_distance;                    /* maximum distance in a single report for valid input */
+    double max_jerk;                        /* maximum jerk for valid input */
+    double max_accel;                       /* maximum acceleration for valid input */
+    double max_error;                       /* maximum deviation from estimated position for valid input */
+
     int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */
     int hyst_x, hyst_y;                     /* x and y width of hysteresis box */
 } SynapticsParameters;
-- 
1.7.5.3



More information about the xorg-devel mailing list