[PATCH evdev 2/3] Add the new valuators for multitouch (rev3)

Benjamin Tissoires tissoire at cena.fr
Wed Jun 2 08:51:31 PDT 2010



Le 02/06/2010 15:09, Henrik Rydberg a écrit :
>> +static int
>> +EvdevMTAddExtraValuators(EvdevPtr pEvdev, int total_num_axes)
>> +{
>> +    int num_axes = 0;
>> +    int mt_num_valuators = 0;
>> +
>> +    if (!(pEvdev->flags&  EVDEV_MULTITOUCH))
>> +        return total_num_axes;
>> +
>> +    mt_num_valuators = EvdevMTCountValuators(pEvdev);
>> +
>> +    /* substract the mt-valuators to total_num_axes
>> +     * to have only the non-mt valuators */
>> +    num_axes = total_num_axes - mt_num_valuators;
>> +
>> +    /* count the maximum number of touchpoints the device can support */
>> +    pEvdev->mt_max_touchpoints = (MAX_VALUATORS - num_axes)
>> +                                                / mt_num_valuators;
>> +
>> +    /* check if the device tells the number of touchpoints
>> +     * it can support. */
>> +    if (TestBit(ABS_MT_TRACKING_ID, pEvdev->abs_bitmask)) {
>> +        int max_id = pEvdev->absinfo[ABS_MT_TRACKING_ID].maximum;
>> +        if (max_id<  pEvdev->mt_max_touchpoints)
>> +            pEvdev->mt_max_touchpoints = max_id;
>> +    }
>
> There seems to be a misunderstanding here. The range of ABS_MT_TRACKING_ID
> should ideally be very large, much larger than the number of supported fingers.
> What you would want here is the maximum number of slots, according to the type B
> protocol. Until then, one should probably support as many fingers as the
> valuators can handle.

Well, I know that ABS_MT_TRACKING_ID shouldn't have anything to do with 
the number of touchpoints the device can support. However, currently, 
and for all devices that won't support protocol B (if there are any), 
this is the only one parameter I know to retrieve this max count. For 
instance, I thought some drivers of dual touchscreen sends Tracking_id 
between 1 and 2 (hid-egalax I think). But at least, if the max tracking 
id is 16, there is no point of creating 24 touches for example.

I had in mind these dual touch devices in order not polluting their 
valuators.

If you have any other suggestion (appart from slots, as this patch does 
not handle them at all, and a later one will come when it will be 
upstream), feel free to tell.

A solution would be to remove this test as dual touch devices could 
easily use slots I think.

>
>> +
>> +    num_axes += pEvdev->mt_max_touchpoints * mt_num_valuators;
>> +
>> +    return num_axes;
>> +}
>> +
>> +/**
>> + * As the first declared mt valuator is ABS_MT_TOUCH_MAJOR, it is then
>> + * the first mt-related valuator.
>
> Given that the order has been abstracted away with ABS_MT_FIRST/LAST_AXIS, the
> above comment should probably change, too.

How about this way:

"Given that the first defined mt event is not ABS_MT_POSITION_X, this 
event is not the first mt-related valuator."

Thanks for your comments,
Benjamin

>
>> + * This function puts ABS_MT_POSITION_X and ABS_MT_POSITION_Y at places
>> + * 0 and 1 in the set of multitouch valuators.
>> + */
>> +static void
>> +EvdevMTSortValuators(EvdevPtr pEvdev)
>> +{
>> +    int axis, tmp_axis_value;
>> +    int first_axis = 0;
>> +    int second_axis = 0;
>> +
>> +    if (!(pEvdev->flags&  EVDEV_MULTITOUCH))
>> +        return;
>> +
>> +    /* find the first and second mt axes */
>> +    for (axis = EVDEV_FIRST_MT_AXIS; axis<= EVDEV_LAST_MT_AXIS; axis++) {
>> +        if (pEvdev->axis_map[axis] == -1)
>> +            continue;
>> +
>> +        if (!first_axis)
>> +            first_axis = axis;
>> +        else if (!second_axis) {
>> +            second_axis = axis;
>> +            break;
>> +        }
>> +    }
>> +
>> +    /* do the actual swap */
>> +    tmp_axis_value = pEvdev->axis_map[first_axis];
>> +    pEvdev->axis_map[first_axis] = pEvdev->axis_map[ABS_MT_POSITION_X];
>> +    pEvdev->axis_map[ABS_MT_POSITION_X] = tmp_axis_value;
>> +
>> +    tmp_axis_value = pEvdev->axis_map[second_axis];
>> +    pEvdev->axis_map[second_axis] = pEvdev->axis_map[ABS_MT_POSITION_Y];
>> +    pEvdev->axis_map[ABS_MT_POSITION_Y] = tmp_axis_value;
>> +}
>> +
>> +/**
>> + * As multitouch devices contains extra axes to enable multitouch,
>> + * they are not initialized in the first init pass. This function
>> + * does the init for those extra valuators.
>> + */
>> +static void
>> +EvdevMTInitValuators(DeviceIntPtr device, Atom *atoms)
>> +{
>> +    InputInfoPtr pInfo;
>> +    EvdevPtr pEvdev;
>> +    int axis, j;
>> +
>> +    pInfo = device->public.devicePrivate;
>> +    pEvdev = pInfo->private;
>> +
>> +    if (!(pEvdev->flags&  EVDEV_MULTITOUCH))
>> +        return;
>> +
>> +    /* Here j starts at 1 as one set of mt-valuators has already been
>> +     * registered */
>> +    for (j = 1; j<  pEvdev->mt_max_touchpoints; j++) {
>> +        for (axis = EVDEV_FIRST_MT_AXIS; axis<= EVDEV_LAST_MT_AXIS; axis++) {
>> +            int axnum = pEvdev->axis_map[axis];
>> +            int real_axnum = axnum + j * pEvdev->mt_num_valuators;
>> +            int resolution = 10000;
>> +
>> +            if (axnum == -1)
>> +                continue;
>> +
>> +#if LINUX_VERSION_CODE>  KERNEL_VERSION(2, 6, 30)
>> +            /* Kernel provides units/mm, X wants units/m */
>> +            if (pEvdev->absinfo[axis].resolution)
>> +                resolution = pEvdev->absinfo[axis].resolution * 1000;
>> +#endif
>> +
>> +            xf86InitValuatorAxisStruct(device, real_axnum,
>> +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION)>= 7
>> +                                       atoms[axnum],
>> +#endif
>> +                                       pEvdev->absinfo[axis].minimum,
>> +                                       pEvdev->absinfo[axis].maximum,
>> +                                       resolution, 0, resolution);
>> +            xf86InitValuatorDefaults(device, real_axnum);
>> +            pEvdev->old_vals[real_axnum] = -1;
>> +        }
>> +    }
>> +}
>> +
>>   static int
>>   EvdevAddAbsClass(DeviceIntPtr device)
>>   {
>> @@ -1149,6 +1324,9 @@ EvdevAddAbsClass(DeviceIntPtr device)
>>       num_axes = CountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
>>       if (num_axes<  1)
>>           return !Success;
>> +
>> +    num_axes = EvdevMTAddExtraValuators(pEvdev, num_axes);
>> +
>>       pEvdev->num_vals = num_axes;
>>       memset(pEvdev->vals, 0, num_axes * sizeof(int));
>>       memset(pEvdev->old_vals, -1, num_axes * sizeof(int));
>> @@ -1162,6 +1340,8 @@ EvdevAddAbsClass(DeviceIntPtr device)
>>           i++;
>>       }
>>
>> +    EvdevMTSortValuators(pEvdev);
>> +
>>       EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
>>
>>       if (!InitValuatorClassDeviceStruct(device, num_axes,
>> @@ -1198,6 +1378,8 @@ EvdevAddAbsClass(DeviceIntPtr device)
>>           pEvdev->old_vals[axnum] = -1;
>>       }
>>
>> +    EvdevMTInitValuators(device, atoms);
>> +
>>       free(atoms);
>>
>>       if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
>> @@ -1503,7 +1685,7 @@ EvdevInit(DeviceIntPtr device)
>>
>>       if (pEvdev->flags&  (EVDEV_UNIGNORE_RELATIVE | EVDEV_UNIGNORE_ABSOLUTE))
>>           EvdevInitAnyClass(device, pEvdev);
>> -    else if (pEvdev->flags&  (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET))
>> +    else if (pEvdev->flags&  (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET | EVDEV_MULTITOUCH))
>>           EvdevInitTouchDevice(device, pEvdev);
>>       else if (pEvdev->flags&  EVDEV_RELATIVE_EVENTS)
>>           EvdevInitRelClass(device, pEvdev);
>> @@ -1875,6 +2057,15 @@ EvdevProbe(InputInfoPtr pInfo)
>>           xf86Msg(X_PROBED, "%s: Found absolute axes\n", pInfo->name);
>>           pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
>>
>> +        if ((TestBit(ABS_MT_POSITION_X, pEvdev->abs_bitmask)&&
>> +             TestBit(ABS_MT_POSITION_Y, pEvdev->abs_bitmask))) {
>> +            xf86Msg(X_INFO, "%s: Found absolute multitouch device.\n", pInfo->name);
>> +            pEvdev->flags |= EVDEV_MULTITOUCH;
>> +            if (!pEvdev->num_buttons) {
>> +                pEvdev->num_buttons = 7; /* LMR + scroll wheels */
>> +                pEvdev->flags |= EVDEV_BUTTON_EVENTS;
>> +            }
>> +        }
>>           if ((TestBit(ABS_X, pEvdev->abs_bitmask)&&
>>                TestBit(ABS_Y, pEvdev->abs_bitmask))) {
>>               xf86Msg(X_PROBED, "%s: Found x and y absolute axes\n", pInfo->name);
>> @@ -1947,6 +2138,9 @@ EvdevProbe(InputInfoPtr pInfo)
>>           } else if (pEvdev->flags&  EVDEV_TOUCHSCREEN) {
>>               xf86Msg(X_INFO, "%s: Configuring as touchscreen\n", pInfo->name);
>>               pInfo->type_name = XI_TOUCHSCREEN;
>> +	} else if (pEvdev->flags&  EVDEV_MULTITOUCH) {
>> +	    xf86Msg(X_INFO, "%s: Configuring as multitouch device\n", pInfo->name);
>> +	    pInfo->type_name = EVDEV_XI_MULTITOUCHDEVICE;
>>   	} else {
>>   	    xf86Msg(X_INFO, "%s: Configuring as mouse\n", pInfo->name);
>>   	    pInfo->type_name = XI_MOUSE;
>> diff --git a/src/evdev.h b/src/evdev.h
>> index 8c89f83..852f06c 100644
>> --- a/src/evdev.h
>> +++ b/src/evdev.h
>> @@ -71,6 +71,7 @@
>>   #define EVDEV_UNIGNORE_ABSOLUTE (1<<  9) /* explicitly unignore abs axes */
>>   #define EVDEV_UNIGNORE_RELATIVE (1<<  10) /* explicitly unignore rel axes */
>>   #define EVDEV_RELATIVE_MODE	(1<<  11) /* Force relative events for devices with absolute axes */
>> +#define EVDEV_MULTITOUCH	(1<<  12) /* device looks like a multi-touch screen? */
>>
>>   #if GET_ABI_MAJOR(ABI_XINPUT_VERSION)>= 3
>>   #define HAVE_PROPERTIES 1
>> @@ -80,7 +81,6 @@
>>   #define MAX_VALUATORS 36
>>   #endif
>>
>> -
>>   #if GET_ABI_MAJOR(ABI_XINPUT_VERSION)<  5
>>   typedef struct {
>>       char *rules;
>> @@ -193,6 +193,10 @@ typedef struct {
>>       /* Event queue used to defer keyboard/button events until EV_SYN time. */
>>       int                     num_queue;
>>       EventQueueRec           queue[EVDEV_MAXQUEUE];
>> +
>> +    unsigned int mt_num_valuators;
>> +    unsigned int mt_max_touchpoints; /* the number of simultaneous touchpoints
>> +                                      * the device can support */
>>   } EvdevRec, *EvdevPtr;
>>
>>   /* Event posting functions */
>


More information about the xorg-devel mailing list