[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