[RFC v2 libinput 2/2] buttonset: implement buttonset handling for Wacom tablet pads
Jason Gerecke
killertofu at gmail.com
Fri Mar 27 14:52:15 PDT 2015
Did some practical testing of these patches and noticed two issues with
the touchstrips:
On 3/17/2015 11:58 PM, Peter Hutterer wrote:
> From: Benjamin Tissoires <benjamin.tissoires at gmail.com>
>
> Same approach as evdev-tablet (started as copy/paste), with axis and buttons
> adjusted. Wacom's handling of pad devices requires a lot of non-obvious
> handling, e.g. ABS_THROTTLE is the second ring, ABS_RX is the strip, etc.
>
> This is not generic buttonset code, if we start supporting other devices for
> buttonsets we'll factor out a couple of the functions.
>
> The wheel and strip events are a bit of a problem: Wacom sends a 0 event on the
> axis when the finger is released. We can detect this if there is an ABS_MISC 0
> present in the same event and suppress it. Won't work if any finger is down
> on any other wheel, strip or button but that's a kernel bug we'll fix once we
> figure out how.
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires at redhat.com>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> src/Makefile.am | 2 +
> src/evdev-buttonset-wacom.c | 533 ++++++++++++++++++++++++++++++++++++++++++++
> src/evdev-buttonset-wacom.h | 63 ++++++
> src/evdev.c | 18 +-
> src/evdev.h | 3 +
> src/libinput-private.h | 16 ++
> src/libinput.c | 65 ++++++
> 7 files changed, 691 insertions(+), 9 deletions(-)
> create mode 100644 src/evdev-buttonset-wacom.c
> create mode 100644 src/evdev-buttonset-wacom.h
>
> [...]
>
> +static inline double
> +normalize_strip(const struct input_absinfo *absinfo)
> +{
> + /* strip axes don't use a proper value, they just shift the bit left
> + * for each position. 0 isn't a real value either, it's only sent on
> + * finger release */
> + double min = 1,
Min should be set to 0 (i.e., log2(1)) here.
> + max = log2(absinfo->maximum);
> + double range = max - min;
> + double value = (log2(absinfo->value) - min) / range;
> +
> + return value;
> +}
> +
> +/* Detect ring wraparound, current and old are normalized to [0, 1[ */
> +static inline double
> +guess_ring_delta(double current, double old)
> +{
> + double d1, d2, d3;
> +
> + d1 = current - old;
> + d2 = (current + 1) - old;
> + d3 = current - (old + 1);
> +
> + if (fabs(d2) < fabs(d1))
> + d1 = d2;
> +
> + if (fabs(d3) < fabs(d1))
> + d1 = d3;
> +
> + return d1;
> +}
> +
> +static void
> +buttonset_check_notify_axes(struct buttonset_dispatch *buttonset,
> + struct evdev_device *device,
> + uint32_t time)
> +{
> + struct libinput_device *base = &device->base;
> + bool axis_update_needed = false;
> + double deltas[LIBINPUT_BUTTONSET_MAX_NUM_AXES] = {0};
> + double deltas_discrete[LIBINPUT_BUTTONSET_MAX_NUM_AXES] = {0};
> + unsigned int a;
> + unsigned int code;
> +
> + for (a = 0; a <= buttonset->naxes; a++) {
> + const struct input_absinfo *absinfo;
> +
> + if (!bit_is_set(buttonset->changed_axes, a))
> + continue;
> +
> + code = buttonset->axis_map[a];
> + assert(code != 0);
> + absinfo = libevdev_get_abs_info(device->evdev, code);
> + assert(absinfo);
> +
> + switch (buttonset->types[a]) {
> + case LIBINPUT_BUTTONSET_AXIS_RING:
> + buttonset->axes[a] = normalize_ring(absinfo);
> + deltas[a] = guess_ring_delta(buttonset->axes[a],
> + buttonset->axes_prev[a]);
> + deltas_discrete[a] = unnormalize_ring_value(absinfo,
> + deltas[a]);
> + break;
> + case LIBINPUT_BUTTONSET_AXIS_STRIP:
> + buttonset->axes[a] = normalize_strip(absinfo);
> + deltas[a] = buttonset->axes[a] - buttonset->axes_prev[a];
> + break;
When a touch goes up, normalize_strip will return a normalized value of
negative infinity. You should add suppression logic like for the
ABS_MISC case since it isn't a real value.
> + default:
> + log_bug_libinput(device->base.seat->libinput,
> + "Invalid axis update: %u\n", a);
> + break;
> + }
> +
> + if (buttonset->have_abs_misc_terminator) {
> + /* Suppress the reset to 0 on finger up. See the
> + comment in buttonset_process_absolute */
> + if (libevdev_get_event_value(device->evdev,
> + EV_ABS,
> + ABS_MISC) == 0) {
> + clear_bit(buttonset->changed_axes, a);
> + buttonset->axes[a] = buttonset->axes_prev[a];
> + continue;
> + /* on finger down, reset the delta to 0 */
> + } else {
> + deltas[a] = 0;
> + deltas_discrete[a] = 0;
> + }
> + }
> +
> + axis_update_needed = true;
> + }
> +
> + if (axis_update_needed)
> + buttonset_notify_axis(base,
> + time,
> + LIBINPUT_BUTTONSET_AXIS_SOURCE_UNKNOWN,
> + buttonset->changed_axes,
> + buttonset->axes,
> + deltas,
> + deltas_discrete);
> +
> + memset(buttonset->changed_axes, 0, sizeof(buttonset->changed_axes));
> + memcpy(buttonset->axes_prev,
> + buttonset->axes,
> + sizeof(buttonset->axes_prev));
> + buttonset->have_abs_misc_terminator = false;
> +}
> +
> [...]
>
--
Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....
More information about the wayland-devel
mailing list