evdev: workaround for missing ABS_X/Y on multitouch devices

Peter Hutterer peter.hutterer at who-t.net
Sun Dec 21 21:08:23 PST 2014


On Sat, Dec 20, 2014 at 10:57:12PM +0000, Colin Macdonald wrote:
> On 27/06/14 02:47, Peter Hutterer wrote:
> > right idea, but I think this is too fancy for what we need. Something like
> > this before the loop should be enough:
> > 
> > /* curse you, android! */
> > if (libevdev_has_event_code(EV_ABS, ABS_MT_POSITION_X) &&
> >     !libevdev_has_event_code(EV_ABS, ABS_X))
> > {
> >     const struct input_absinfo* abs;
> >     abs = libevdev_get_abs_info(pEvdev->dev, axis);
> >     libevdev_enable_event_code(pEvdev->dev, EV_ABS, ABS_X, abs);
> >     num_axes++;
> > }
> > 
> > repeat for ABS_Y
> 
> Hi Peter,
> 
> Sorry so long to get back to this, as I'm sure you've long forgotten.
> But please find patch attached.  I followed your advice and did this
> before the mapping loop.
> 
> However, I did the full mt_axis_mappings table, not just
> ABS_MT_POSITION_X and _Y.  I think this is the right thing to do here in
> case some driver has ABS_MT_PRESSURE or ABS_MT_DISTANCE.

It should be, but I don't think I've see a device that is lacking
pressure/distance but has the MT codes for it anyway.

> I've lightly tested on an Android device where it does make the
> touchscreen work.
> 
> It also seems ok (i.e., doesn't break) my touchscreen laptop (Fedora
> GNU/Linux).
> 
> Colin

> From baeb2b0a71387a9ed83737b5cf58c195882588df Mon Sep 17 00:00:00 2001
> From: "Colin B. Macdonald" <macdonald at maths.ox.ac.uk>
> Date: Thu, 26 Jun 2014 12:17:59 +0100
> Subject: [PATCH] Workaround lack of ABS_X, bug #80470
> 
> Often on Android, we have ABS_MT_POSITION_X without
> ABS_X (which is contrary to spec).  We add fake
> ABS_X axis in that case.  I also commented some of
> the surrouding code as I did this.
> ---
>  src/evdev.c | 35 ++++++++++++++++++++++++++++++++---
>  1 file changed, 32 insertions(+), 3 deletions(-)
> 
> diff --git a/src/evdev.c b/src/evdev.c
> index 9cfc982..f6834be 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -1211,7 +1211,8 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int num_scroll_axes)
>  {
>      InputInfoPtr pInfo;
>      EvdevPtr pEvdev;
> -    int num_axes = 0, axis, i = 0;
> +    int axis, i = 0;
> +    int num_axes = 0; /* number of non-MT axes */
>      int num_mt_axes = 0, /* number of MT-only axes */
>          num_mt_axes_total = 0; /* total number of MT axes, including
>                                    double-counted ones, excluding blacklisted */
> @@ -1224,6 +1225,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int num_scroll_axes)
>      if (!libevdev_has_event_type(pEvdev->dev, EV_ABS))
>          goto out;
>  
> +    /* Find number of absolute axis, including MT ones, will decrease later. */
>      for (i = 0; i < ABS_MAX; i++)
>          if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i))
>              num_axes++;
> @@ -1232,6 +1234,31 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int num_scroll_axes)
>          goto out;
>  
>  #ifdef MULTITOUCH
> +    /* Android drivers often have ABS_MT_POSITION_X but not ABS_X.
> +       Loop over the MT->legacy axis table and add fake axes. */
> +    for (i = 0; i < ArrayLength(mt_axis_mappings); i++)
> +    {
> +        int mt_code = mt_axis_mappings[i].mt_code;
> +        int code = mt_axis_mappings[i].code;
> +        if (libevdev_has_event_code(pEvdev->dev, EV_ABS, mt_code) &&
> +           !libevdev_has_event_code(pEvdev->dev, EV_ABS, code))

needs an extra space here for indentation

> +        {
> +            const struct input_absinfo* abs;
> +            abs = libevdev_get_abs_info(pEvdev->dev, mt_code);
> +            if (libevdev_enable_event_code(pEvdev->dev, EV_ABS, code, abs))
> +            {
> +                xf86IDrvMsg(pInfo, X_ERROR, "Failed to fake %s as a copy of %s\n",
> +                            abs_labels[code], abs_labels[mt_code]);

please use libevdev_event_code_get_name() here instead of the axis labels,
it's a bit easier to parse.

> +
> +                goto out;
> +            }
> +            xf86IDrvMsg(pInfo, X_WARNING, "Faking %s as a copy of axis %s\n",
> +                        abs_labels[code], abs_labels[mt_code]);

same here (and use X_INFO here). for both messages I think it's enough
to just say "faking %s", no need to print both axes, the code is
straightforward to deduce it.

> +            num_axes++;
> +        }
> +    }
> +
> +    /* Absolute multitouch axes: adjust mapping and axes counts. */
>      for (axis = ABS_MT_SLOT; axis < ABS_MAX; axis++)
>      {
>          if (libevdev_has_event_code(pEvdev->dev, EV_ABS, axis))
> @@ -1239,6 +1266,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int num_scroll_axes)
>              int j;
>              Bool skip = FALSE;
>  
> +            /* Setup mapping if axis is in MT->legacy axis table. */
>              for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
>              {
>                  if (mt_axis_mappings[j].mt_code == axis &&
> @@ -1258,9 +1286,10 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int num_scroll_axes)
>              num_axes--;
>          }
>      }
> +    xf86IDrvMsg(pInfo, X_INFO, "Have %d multitouch, %d non-multitouch axes\n",
> +		num_mt_axes, num_axes);

skip this one please

these are all just nitpicks, the approach looks correct. Send me an updated
version please and I'll run it against the test suites here.

Cheers,
   Peter

>  
> -    /* device only has mt-axes. the kernel should give us ABS_X etc for
> -       backwards compat but some devices don't have it. */
> +    /* Panic if, after faking ABS_X etc, we still only have mt-axes. */
>      if (num_axes == 0 && num_mt_axes > 0) {
>          xf86IDrvMsg(pInfo, X_ERROR,
>                      "found only multitouch-axes. That shouldn't happen.\n");
> -- 
> 2.1.0
> 




> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel



More information about the xorg-devel mailing list