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

Henrik Rydberg rydberg at euromail.se
Wed Jun 2 06:09:09 PDT 2010


> +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.

> +
> +    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.

> + * 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