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

Vasily Khoruzhick anarsoul at gmail.com
Thu Apr 16 12:07:30 PDT 2015


On Thu, Apr 16, 2015 at 9:41 PM, Benjamin Tissoires
<benjamin.tissoires at gmail.com> wrote:
> 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>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> Changes to v1:
> - a bit more generic than the original, makes adding new models more
> straightforward.
>
> Changes to v2:
> - changed the incline parameter to have a touchpad which feels like the other.
>   Not sure these are the final parameters but they make the touchpad much
>   better.
>
>  doc/device-configuration-via-udev.dox |    9 ++++++++
>  src/evdev-mt-touchpad.c               |   14 ++++++++++--
>  src/evdev.c                           |   23 ++++++++++++++++++++++
>  src/evdev.h                           |    7 ++++++
>  src/filter.c                          |   34 +++++++++++++++++++++++++++++++++
>  src/filter.h                          |    5 ++++
>  6 files changed, 89 insertions(+), 3 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 4e5a558..f88e906 100644
> --- a/src/evdev-mt-touchpad.c
> +++ b/src/evdev-mt-touchpad.c
> @@ -998,6 +998,7 @@ static int
>  tp_init_accel(struct tp_dispatch *tp, double diagonal)
>  {
>         int res_x, res_y;
> +       accel_profile_func_t profile;
>
>         res_x = tp->device->abs.absinfo_x->resolution;
>         res_y = tp->device->abs.absinfo_y->resolution;
> @@ -1021,9 +1022,16 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
>                 tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
>         }
>
> -       if (evdev_device_init_pointer_acceleration(
> -                                       tp->device,
> -                                       touchpad_accel_profile_linear) == -1)
> +       switch (tp->device->model) {
> +       case EVDEV_MODEL_LENOVO_X230:
> +               profile = touchpad_lenovo_x230_accel_profile;
> +               break;
> +       default:
> +               profile = touchpad_accel_profile_linear;
> +               break;
> +       }
> +
> +       if (evdev_device_init_pointer_acceleration(tp->device, profile) == -1)
>                 return -1;
>
>         return 0;
> diff --git a/src/evdev.c b/src/evdev.c
> index 5b4b2b6..0b705e4 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -1356,6 +1356,28 @@ evdev_read_dpi_prop(struct evdev_device *device)
>         return dpi;
>  }
>
> +static inline enum evdev_device_model
> +evdev_read_model(struct evdev_device *device)
> +{
> +       const struct model_map {
> +               const char *property;
> +               enum evdev_device_model model;
> +       } model_map[] = {
> +               { "LIBINPUT_MODEL_LENOVO_X230", EVDEV_MODEL_LENOVO_X230 },
> +               { NULL, EVDEV_MODEL_DEFAULT },
> +       };
> +       const struct model_map *m = model_map;
> +
> +       while (m->property) {
> +               if (!!udev_device_get_property_value(device->udev_device,
> +                                                    m->property))
> +                       break;
> +               m++;
> +       }
> +
> +       return m->model;
> +}
> +
>  /* Return 1 if the given resolutions have been set, or 0 otherwise */
>  inline int
>  evdev_fix_abs_resolution(struct evdev_device *device,
> @@ -1868,6 +1890,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 = evdev_read_model(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..c4bfb79 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -63,6 +63,11 @@ enum evdev_device_tags {
>         EVDEV_TAG_TOUCHPAD_TRACKPOINT = (1 << 3),
>  };
>
> +enum evdev_device_model {
> +       EVDEV_MODEL_DEFAULT,
> +       EVDEV_MODEL_LENOVO_X230,
> +};
> +
>  struct mt_slot {
>         int32_t seat_slot;
>         struct device_coords point;
> @@ -160,6 +165,8 @@ struct evdev_device {
>
>         int dpi; /* HW resolution */
>         struct ratelimit syn_drop_limit; /* ratelimit for SYN_DROPPED logging */
> +
> +       enum evdev_device_model model;
>  };
>
>  #define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
> diff --git a/src/filter.c b/src/filter.c
> index f7ff426..8c53f22 100644
> --- a/src/filter.c
> +++ b/src/filter.c
> @@ -355,3 +355,37 @@ 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 *
> +                                 TP_MAGIC_LOW_RES_FACTOR; /* twice the factor */

Not twice, square.

> +
> +       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
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list