[RFC v2 libinput 2/2] buttonset: implement buttonset handling for Wacom tablet pads
Peter Hutterer
peter.hutterer at who-t.net
Mon Apr 6 20:26:26 PDT 2015
On Fri, Mar 27, 2015 at 02:52:15PM -0700, Jason Gerecke wrote:
> 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.
fixed, thanks.
> >+ 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.
added, thanks.
Cheers,
Peter
>
> >+ 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