[PATCH 3/4] Implement MT Slots protocol support

Benjamin Tissoires tissoire at cena.fr
Wed Jun 23 08:25:57 PDT 2010



Le 23/06/2010 16:04, Chase Douglas a écrit :
> From: Benjamin Tissoires<tissoire at cena.fr>
>
> The MT Slots protocol sends only the ABS_MT_* values that have changed
> from a previous set of events. We use the ABS_MT_SLOT value as an index
> into an array of MT valuators.
> (see kernel_src/Documentation/input/multi-touch-protocol.txt)
>
> The "Abs Tracking ID" value can be used to figure out if a touch is down
> or not. If it is != -1, then the touch is down. Otherwise, the touch is
> up and the other values in the "slot" of valuators are invalid.
>
> Signed-off-by: Benjamin Tissoires<tissoire at cena.fr>
> Signed-off-by: Chase Douglas<chase.douglas at canonical.com>
> ---
>   src/evdev.c |   34 ++++++++++++++++++++++++++++++++--
>   src/evdev.h |    1 +
>   2 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/src/evdev.c b/src/evdev.c
> index 68d8946..777eebe 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -527,6 +527,12 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
>       }
>   }
>
> +static inline BOOL
> +EvdevIsMTEvent(struct input_event *ev)
> +{
> +    return ev->code>= EVDEV_FIRST_MT_AXIS&&  ev->code<= EVDEV_LAST_MT_AXIS;
> +}
> +
>   /**
>    * Take the absolute motion input event and process it accordingly.
>    */
> @@ -549,7 +555,18 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
>       if (EvdevWheelEmuFilterMotion(pInfo, ev))
>           return;
>
> -    pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
> +    if (!EvdevIsMTEvent(ev)&&  ev->code != ABS_MT_SLOT)
> +        pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
> +    else if (ev->code == ABS_MT_SLOT) {
> +        pEvdev->mt_current_touchpoint = value;
> +        return;
> +    }
> +    else if (pEvdev->mt_current_touchpoint<  pEvdev->mt_max_touchpoints) {
> +        pEvdev->vals[pEvdev->axis_map[ev->code] +
> +            pEvdev->mt_current_touchpoint * pEvdev->mt_num_valuators] = value;
> +    } else
> +        return; /* mt-event, but not enough place to store it */
> +
>       if (ev->code == ABS_X)
>           pEvdev->abs |= ABS_X_VALUE;
>       else if (ev->code == ABS_Y)
> @@ -1309,6 +1326,14 @@ EvdevMTInitValuators(DeviceIntPtr device, Atom *atoms)
>               pEvdev->old_vals[real_axnum] = -1;
>           }
>       }
> +
> +    /* TRACKING_ID != -1 means touch is down */
> +    for (j = 0; j<  pEvdev->mt_max_touchpoints; j++) {
> +        int axnum = pEvdev->axis_map[ABS_MT_TRACKING_ID];
> +        int real_axnum = axnum + j * pEvdev->mt_num_valuators;
> +
> +        pEvdev->vals[real_axnum] = -1;
> +    }

Ouch, I just saw that:
if the device reports its trackingID between 0 and 15 (for instance the 
magicmouse), you can not have -1 in the trackingID since the server 
clamps it at 0.

We need to call again xf86InitValuatorAxisStruct on each trackingID axis 
to set its min at -1.

the patch should be:
----------------------------------------------------------------------------
     /* TRACKING_ID != -1 means touch is down */
     for (j = 0; j < pEvdev->mt_max_touchpoints; j++) {
         int axnum = pEvdev->axis_map[ABS_MT_TRACKING_ID];
         int real_axnum = axnum + j * pEvdev->mt_num_valuators;

         int resolution = 10000;

#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30)
         /* Kernel provides units/mm, X wants units/m */
         if (pEvdev->absinfo[ABS_MT_TRACKING_ID].resolution)
             resolution = pEvdev->absinfo[ABS_MT_TRACKING_ID].resolution 
* 1000;
#endif

          /* We force the trackingID to have a min value of -1 */
         xf86InitValuatorAxisStruct(device, real_axnum,
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
                                        atoms[axnum],
#endif
                                    -1,
 
pEvdev->absinfo[ABS_MT_TRACKING_ID].maximum,
                                    resolution, 0, resolution);


         pEvdev->vals[real_axnum] = -1;
     }
----------------------------------------------------------------------------

>   }
>
>   static int
> @@ -1329,6 +1354,10 @@ EvdevAddAbsClass(DeviceIntPtr device)
>       if (num_axes<  1)
>           return !Success;
>
> +    /* We use slots internally to arrange touches into valuators */
> +    if (TestBit(ABS_MT_SLOT, pEvdev->abs_bitmask))
> +        num_axes--;
> +
>       num_axes = EvdevMTAddExtraValuators(pEvdev, num_axes);
>
>       pEvdev->num_vals = num_axes;
> @@ -1338,7 +1367,8 @@ EvdevAddAbsClass(DeviceIntPtr device)
>
>       for (axis = ABS_X; axis<= ABS_MAX; axis++) {
>           pEvdev->axis_map[axis] = -1;
> -        if (!TestBit(axis, pEvdev->abs_bitmask))
> +        /* We use slots internally to arrange touches into valuators */
> +        if (!TestBit(axis, pEvdev->abs_bitmask) || axis == ABS_MT_SLOT)
>               continue;
>           pEvdev->axis_map[axis] = i;
>           i++;
> diff --git a/src/evdev.h b/src/evdev.h
> index 7f9fc47..25c63a7 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -197,6 +197,7 @@ typedef struct {
>       unsigned int mt_num_valuators;
>       unsigned int mt_max_touchpoints; /* the number of simultaneous touchpoints
>                                         * the device can support */
> +    unsigned int mt_current_touchpoint;
>   } EvdevRec, *EvdevPtr;
>
>   /* Event posting functions */


More information about the xorg-devel mailing list