[PATCH libinput 2/3] evdev: use a different filter for low resolution touchpad on the Lenovo X230

Benjamin Tissoires benjamin.tissoires at gmail.com
Thu Apr 9 10:30:38 PDT 2015


Those touchpads presents an actual lower resolution that what is
advertised.

We see some jumps from the cursor due to the big steps in X and Y
when we are receiving data.

For instance, we receive:

E: 13.471932 0003 0000 16366	# EV_ABS / ABS_X                16366
E: 13.471932 0003 0001 9591	# EV_ABS / ABS_Y                9591
E: 13.471932 0000 0000 0000	# ------------ SYN_REPORT (0) ----------
E: 13.479924 0003 0000 16316	# EV_ABS / ABS_X                16316
E: 13.479924 0003 0001 9491	# EV_ABS / ABS_Y                9491
E: 13.479924 0000 0000 0000	# ------------ SYN_REPORT (0) ----------
E: 13.487939 0003 0000 16271	# EV_ABS / ABS_X                16271
E: 13.487939 0003 0001 9403	# EV_ABS / ABS_Y                9403
E: 13.487939 0000 0000 0000	# ------------ SYN_REPORT (0) ----------

-> jumps of ~50 in X in each report, and ~100 for Y.

Apply a factor to minimize those jumps at low speed and try keeping
the same feeling as regular touchpads at high speed. It still feels
slower but it is usable at least

Signed-off-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>
---
 doc/device-configuration-via-udev.dox |    9 +++++++++
 src/evdev-mt-touchpad.c               |    4 +++-
 src/evdev.c                           |    8 ++++++++
 src/evdev.h                           |    2 ++
 src/filter.c                          |   33 +++++++++++++++++++++++++++++++++
 src/filter.h                          |    5 +++++
 6 files changed, 60 insertions(+), 1 deletions(-)

diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox
index fc1c0af..c570913 100644
--- a/doc/device-configuration-via-udev.dox
+++ b/doc/device-configuration-via-udev.dox
@@ -57,6 +57,15 @@ See @ref motion_normalization for details.
 <dd>The angle in degrees for each click on a mouse wheel. See
 libinput_pointer_get_axis_source() for details.
 </dd>
+<dt>LIBINPUT_MODEL_LENOVO_X230</dt>
+<dd><b>Do not use for anything except a Lenovo X230 series</b> (you have been
+warned).
+This flag allows libinput to apply a different acceleration profile for the
+touchpads of this series of laptops to counter a hardware deficiency. It may
+also be use to tune other parts of the inputs of these laptops, so the effects
+of this property may change anytime and will be only tested against the
+mentioned laptop series.
+</dd>
 </dl>
 
 Below is an example udev rule to assign "seat1" to a device from vendor
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 68070c2..e04bea2 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -998,7 +998,9 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
 
 	if (evdev_device_init_pointer_acceleration(
                                        tp->device,
-                                       touchpad_accel_profile_linear) == -1)
+                                       tp->device->model_lenovo_x230 ?
+                                               touchpad_lenovo_x230_accel_profile :
+                                               touchpad_accel_profile_linear) == -1)
 		return -1;
 
 	return 0;
diff --git a/src/evdev.c b/src/evdev.c
index 243cd22..88d9169 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1343,6 +1343,13 @@ evdev_read_dpi_prop(struct evdev_device *device)
 	return dpi;
 }
 
+static inline int
+evdev_read_model_lenovo_x230_prop(struct evdev_device *device)
+{
+	return !!udev_device_get_property_value(device->udev_device,
+						"LIBINPUT_MODEL_LENOVO_X230");
+}
+
 /* Return 1 if the given resolutions have been set, or 0 otherwise */
 inline int
 evdev_fix_abs_resolution(struct evdev_device *device,
@@ -1853,6 +1860,7 @@ evdev_device_create(struct libinput_seat *seat,
 	device->scroll.wheel_click_angle =
 		evdev_read_wheel_click_prop(device);
 	device->dpi = evdev_read_dpi_prop(device);
+	device->model_lenovo_x230 = evdev_read_model_lenovo_x230_prop(device);
 	/* at most 5 SYN_DROPPED log-messages per 30s */
 	ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5);
 
diff --git a/src/evdev.h b/src/evdev.h
index af09baa..690f825 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -160,6 +160,8 @@ struct evdev_device {
 
 	int dpi; /* HW resolution */
 	struct ratelimit syn_drop_limit; /* ratelimit for SYN_DROPPED logging */
+
+	int model_lenovo_x230; /* Specific tuning for the X230 */
 };
 
 #define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
diff --git a/src/filter.c b/src/filter.c
index 92e6802..9a0f637 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -353,3 +353,36 @@ touchpad_accel_profile_linear(struct motion_filter *filter,
 
 	return speed_out * TP_MAGIC_SLOWDOWN;
 }
+
+double
+touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
+				      void *data,
+				      double speed_in,
+				      uint64_t time)
+{
+	/* Keep the magic factor from touchpad_accel_profile_linear.  */
+	const double TP_MAGIC_SLOWDOWN = 0.4;
+
+	/* Those touchpads presents an actual lower resolution that what is
+	 * advertised. We see some jumps from the cursor due to the big steps
+	 * in X and Y when we are receiving data.
+	 * Apply a factor to minimize those jumps at low speed, and try
+	 * keeping the same feeling as regular touchpads at high speed.
+	 * It still feels slower but it is usable at least */
+	const double TP_MAGIC_LOW_RES_FACTOR = 4.0;
+	double speed_out;
+	struct pointer_accelerator *accel_filter =
+		(struct pointer_accelerator *)filter;
+
+	const double max_accel = accel_filter->accel *
+				  TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */
+	const double threshold = accel_filter->threshold /
+				  TP_MAGIC_LOW_RES_FACTOR; /* units/ms */
+	const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
+
+	speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
+
+	speed_out = accel_profile_linear(speed_in, max_accel, threshold, incline);
+
+	return speed_out * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
+}
diff --git a/src/filter.h b/src/filter.h
index 70363a6..a053860 100644
--- a/src/filter.h
+++ b/src/filter.h
@@ -67,4 +67,9 @@ touchpad_accel_profile_linear(struct motion_filter *filter,
 			      void *data,
 			      double speed_in,
 			      uint64_t time);
+double
+touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
+				      void *data,
+				      double speed_in,
+				      uint64_t time);
 #endif /* FILTER_H */
-- 
1.7.1



More information about the wayland-devel mailing list