On 04/10/2016 09:15 PM, Peter Hutterer wrote: > Signed-off-by: Peter Hutterer <[email protected]> > --- > Adjustments for the new API in 2/5 > > src/Makefile.am | 1 + > src/evdev-tablet-pad.c | 614 > +++++++++++++++++++++++++++++++++++++++++++++++++ > src/evdev-tablet-pad.h | 69 ++++++ > src/evdev.c | 28 ++- > src/evdev.h | 13 ++ > src/libinput.c | 6 +- > 6 files changed, 716 insertions(+), 15 deletions(-) > create mode 100644 src/evdev-tablet-pad.c > create mode 100644 src/evdev-tablet-pad.h > > diff --git a/src/Makefile.am b/src/Makefile.am > index 343e75c..a3df6c8 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -20,6 +20,7 @@ libinput_la_SOURCES = \ > evdev-mt-touchpad-gestures.c \ > evdev-tablet.c \ > evdev-tablet.h \ > + evdev-tablet-pad.c \ > filter.c \ > filter.h \ > filter-private.h \ > diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c > new file mode 100644 > index 0000000..8c64830 > --- /dev/null > +++ b/src/evdev-tablet-pad.c > @@ -0,0 +1,614 @@ > +/* > + * Copyright © 2016 Red Hat, Inc. > + * > + * Permission to use, copy, modify, distribute, and sell this software and > + * its documentation for any purpose is hereby granted without fee, provided > + * that the above copyright notice appear in all copies and that both that > + * copyright notice and this permission notice appear in supporting > + * documentation, and that the name of the copyright holders not be used in > + * advertising or publicity pertaining to distribution of the software > + * without specific, written prior permission. The copyright holders make > + * no representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER > + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF > + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN > + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include "config.h" > +#include "evdev-tablet-pad.h" > + > +#include <assert.h> > +#include <stdbool.h> > +#include <string.h> > + > +#define pad_set_status(pad_,s_) (pad_)->status |= (s_) > +#define pad_unset_status(pad_,s_) (pad_)->status &= ~(s_) > +#define pad_has_status(pad_,s_) (!!((pad_)->status & (s_))) > + > +static void > +pad_get_buttons_pressed(struct pad_dispatch *pad, > + struct button_state *buttons) > +{ > + struct button_state *state = &pad->button_state; > + struct button_state *prev_state = &pad->prev_button_state; > + unsigned int i; > + > + for (i = 0; i < sizeof(buttons->bits); i++) > + buttons->bits[i] = state->bits[i] & ~(prev_state->bits[i]); > +} > + > +static void > +pad_get_buttons_released(struct pad_dispatch *pad, > + struct button_state *buttons) > +{ > + struct button_state *state = &pad->button_state; > + struct button_state *prev_state = &pad->prev_button_state; > + unsigned int i; > + > + for (i = 0; i < sizeof(buttons->bits); i++) > + buttons->bits[i] = prev_state->bits[i] & ~(state->bits[i]); > +} > + > +static inline bool > +pad_button_is_down(const struct pad_dispatch *pad, > + uint32_t button) > +{ > + return bit_is_set(pad->button_state.bits, button); > +} > + > +static inline bool > +pad_any_button_down(const struct pad_dispatch *pad) > +{ > + const struct button_state *state = &pad->button_state; > + unsigned int i; > + > + for (i = 0; i < sizeof(state->bits); i++) > + if (state->bits[i] != 0) > + return true; > + > + return false; > +} > + > +static inline void > +pad_button_set_down(struct pad_dispatch *pad, > + uint32_t button, > + bool is_down) > +{ > + struct button_state *state = &pad->button_state; > + > + if (is_down) { > + set_bit(state->bits, button); > + pad_set_status(pad, PAD_BUTTONS_PRESSED); > + } else { > + clear_bit(state->bits, button); > + pad_set_status(pad, PAD_BUTTONS_RELEASED); > + } > +} > + > +static void > +pad_process_absolute(struct pad_dispatch *pad, > + struct evdev_device *device, > + struct input_event *e, > + uint64_t time) > +{ > + switch (e->code) { > + case ABS_WHEEL: > + pad->changed_axes |= PAD_AXIS_RING1; > + pad_set_status(pad, PAD_AXES_UPDATED); > + break; > + case ABS_THROTTLE: > + pad->changed_axes |= PAD_AXIS_RING2; > + pad_set_status(pad, PAD_AXES_UPDATED); > + break; > + case ABS_RX: > + pad->changed_axes |= PAD_AXIS_STRIP1; > + pad_set_status(pad, PAD_AXES_UPDATED); > + break; > + case ABS_RY: > + pad->changed_axes |= PAD_AXIS_STRIP2; > + pad_set_status(pad, PAD_AXES_UPDATED); > + break; > + case ABS_MISC: > + /* The wacom driver always sends a 0 axis event on finger > + up, but we also get an ABS_MISC 15 on touch down and > + ABS_MISC 0 on touch up, on top of the actual event. This > + is kernel behavior for xf86-input-wacom backwards > + compatibility after the 3.17 wacom HID move. > + > + We use that event to tell when we truly went a full > + rotation around the wheel vs. a finger release. > + > + FIXME: On the Intuos5 and later the kernel merges all > + states into that event, so if any finger is down on any > + button, the wheel release won't trigger the ABS_MISC 0 > + but still send a 0 event. We can't currently detect this. > + */ > + pad->have_abs_misc_terminator = true; > + break; > + default: > + log_info(device->base.seat->libinput, > + "Unhandled EV_ABS event code %#x\n", e->code); > + break; > + } > +} > + > +static inline double > +normalize_ring(const struct input_absinfo *absinfo) > +{ > + /* libinput has 0 as the ring's northernmost point in the device's > + current logical rotation, increasing clockwise to 1. Wacom has > + 0 on the left-most wheel position. > + */ > + double range = absinfo->maximum - absinfo->minimum + 1; > + double value = (absinfo->value - absinfo->minimum) / range - 0.25; > + > + if (value < 0.0) > + value += 1.0; > + > + return value; > +} > + > +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 = 0, > + max = log2(absinfo->maximum); > + double range = max - min; > + double value = (log2(absinfo->value) - min) / range; > + > + return value; > +} > + > +static inline double > +pad_handle_ring(struct pad_dispatch *pad, > + struct evdev_device *device, > + unsigned int code) > +{ > + const struct input_absinfo *absinfo; > + double degrees; > + > + absinfo = libevdev_get_abs_info(device->evdev, code); > + assert(absinfo); > + > + degrees = normalize_ring(absinfo) * 360; > + > + if (device->left_handed.enabled) > + degrees = fmod(degrees + 180, 360); > + > + return degrees; > +} > + > +static inline double > +pad_handle_strip(struct pad_dispatch *pad, > + struct evdev_device *device, > + unsigned int code) > +{ > + const struct input_absinfo *absinfo; > + double pos; > + > + absinfo = libevdev_get_abs_info(device->evdev, code); > + assert(absinfo); > + > + if (absinfo->value == 0) > + return 0.0; > + > + pos = normalize_strip(absinfo); > + > + if (device->left_handed.enabled) > + pos = 1.0 - pos; > + > + return pos; > +} > + > +static void > +pad_check_notify_axes(struct pad_dispatch *pad, > + struct evdev_device *device, > + uint64_t time) > +{ > + struct libinput_device *base = &device->base; > + double value; > + bool send_finger_up = false; > + > + /* Suppress the reset to 0 on finger up. See the > + comment in pad_process_absolute */ > + if (pad->have_abs_misc_terminator && > + libevdev_get_event_value(device->evdev, EV_ABS, ABS_MISC) == 0) > + send_finger_up = true; > + > + if (pad->changed_axes & PAD_AXIS_RING1) { > + value = pad_handle_ring(pad, device, ABS_WHEEL); > + if (send_finger_up) > + value = -1.0; > + > + tablet_pad_notify_ring(base, > + time, > + 0, > + value, > + LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER); > + } > + > + if (pad->changed_axes & PAD_AXIS_RING2) { > + value = pad_handle_ring(pad, device, ABS_THROTTLE); > + if (send_finger_up) > + value = -1.0; > + > + tablet_pad_notify_ring(base, > + time, > + 1, > + value, > + LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER); > + } > + > + if (pad->changed_axes & PAD_AXIS_STRIP1) { > + value = pad_handle_strip(pad, device, ABS_RX); > + if (send_finger_up) > + value = -1.0; > + > + tablet_pad_notify_strip(base, > + time, > + 0, > + value, > + > LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER); > + } > + > + if (pad->changed_axes & PAD_AXIS_STRIP2) { > + value = pad_handle_strip(pad, device, ABS_RY); > + if (send_finger_up) > + value = -1.0; > + > + tablet_pad_notify_strip(base, > + time, > + 1, > + value, > + > LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER); > + } > + > + pad->changed_axes = PAD_AXIS_NONE; > + pad->have_abs_misc_terminator = false; > +} > + > +static void > +pad_process_key(struct pad_dispatch *pad, > + struct evdev_device *device, > + struct input_event *e, > + uint64_t time) > +{ > + uint32_t button = e->code; > + uint32_t is_press = e->value != 0; > + > + pad_button_set_down(pad, button, is_press); > +} > + > +static void > +pad_notify_button_mask(struct pad_dispatch *pad, > + struct evdev_device *device, > + uint64_t time, > + const struct button_state *buttons, > + enum libinput_button_state state) > +{ > + struct libinput_device *base = &device->base; > + int32_t code; > + unsigned int i; > + > + for (i = 0; i < sizeof(buttons->bits); i++) { > + unsigned char buttons_slice = buttons->bits[i]; > + > + code = i * 8; > + while (buttons_slice) { > + int enabled; > + char map; > + > + code++; > + enabled = (buttons_slice & 1); > + buttons_slice >>= 1; > + > + if (!enabled) > + continue; > + > + map = pad->button_map[code - 1]; > + if (map != -1) > + tablet_pad_notify_button(base, time, map, > state); > + } > + } > +} > + > +static void > +pad_notify_buttons(struct pad_dispatch *pad, > + struct evdev_device *device, > + uint64_t time, > + enum libinput_button_state state) > +{ > + struct button_state buttons; > + > + if (state == LIBINPUT_BUTTON_STATE_PRESSED) > + pad_get_buttons_pressed(pad, &buttons); > + else > + pad_get_buttons_released(pad, &buttons); > + > + pad_notify_button_mask(pad, device, time, &buttons, state); > +} > + > +static void > +pad_change_to_left_handed(struct evdev_device *device) > +{ > + struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch; > + > + if (device->left_handed.enabled == device->left_handed.want_enabled) > + return; > + > + if (pad_any_button_down(pad)) > + return; > + > + device->left_handed.enabled = device->left_handed.want_enabled; > +} > + > +static void > +pad_flush(struct pad_dispatch *pad, > + struct evdev_device *device, > + uint64_t time) > +{ > + if (pad_has_status(pad, PAD_AXES_UPDATED)) { > + pad_check_notify_axes(pad, device, time); > + pad_unset_status(pad, PAD_AXES_UPDATED); > + } > + > + if (pad_has_status(pad, PAD_BUTTONS_RELEASED)) { > + pad_notify_buttons(pad, > + device, > + time, > + LIBINPUT_BUTTON_STATE_RELEASED); > + pad_unset_status(pad, PAD_BUTTONS_RELEASED); > + > + pad_change_to_left_handed(device); > + } > + > + if (pad_has_status(pad, PAD_BUTTONS_PRESSED)) { > + pad_notify_buttons(pad, > + device, > + time, > + LIBINPUT_BUTTON_STATE_PRESSED); > + pad_unset_status(pad, PAD_BUTTONS_PRESSED); > + } > + > + /* Update state */ > + memcpy(&pad->prev_button_state, > + &pad->button_state, > + sizeof(pad->button_state)); > +} > + > +static void > +pad_process(struct evdev_dispatch *dispatch, > + struct evdev_device *device, > + struct input_event *e, > + uint64_t time) > +{ > + struct pad_dispatch *pad = (struct pad_dispatch *)dispatch; > + > + switch (e->type) { > + case EV_ABS: > + pad_process_absolute(pad, device, e, time); > + break; > + case EV_KEY: > + pad_process_key(pad, device, e, time); > + break; > + case EV_SYN: > + pad_flush(pad, device, time); > + break; > + default: > + log_error(device->base.seat->libinput, > + "Unexpected event type %s (%#x)\n", > + libevdev_event_type_get_name(e->type), > + e->type); > + break; > + } > +} > + > +static void > +pad_suspend(struct evdev_dispatch *dispatch, > + struct evdev_device *device) > +{ > + struct pad_dispatch *pad = (struct pad_dispatch *)dispatch; > + struct libinput *libinput = device->base.seat->libinput; > + unsigned int code; > + > + for (code = KEY_ESC; code < KEY_CNT; code++) { > + if (pad_button_is_down(pad, code)) > + pad_button_set_down(pad, code, false); > + } > + > + pad_flush(pad, device, libinput_now(libinput)); > +} > + > +static void > +pad_destroy(struct evdev_dispatch *dispatch) > +{ > + struct pad_dispatch *pad = (struct pad_dispatch*)dispatch; > + > + free(pad); > +} > + > +static struct evdev_dispatch_interface pad_interface = { > + pad_process, > + pad_suspend, /* suspend */ > + NULL, /* remove */ > + pad_destroy, > + NULL, /* device_added */ > + NULL, /* device_removed */ > + NULL, /* device_suspended */ > + NULL, /* device_resumed */ > + NULL, /* post_added */ > +}; > + > +static void > +pad_init_buttons(struct pad_dispatch *pad, > + struct evdev_device *device) > +{ > + unsigned int code; > + size_t i; > + int map = 0; > + > + for (i = 0; i < ARRAY_LENGTH(pad->button_map); i++) > + pad->button_map[i] = -1; > + > + for (code = BTN_0; code < BTN_MOUSE; code++) { > + if (libevdev_has_event_code(device->evdev, EV_KEY, code)) > + pad->button_map[code] = map++; > + } > + > + for (code = BTN_A; code < BTN_DIGI; code++) { > + if (libevdev_has_event_code(device->evdev, EV_KEY, code)) > + pad->button_map[code] = map++; > + } > + > + pad->nbuttons = map; > +} > +
For the sake of the compatibility with future devices, I'd recommend more strictly following the button ranges used by the kernel: http://lxr.free-electrons.com/source/drivers/hid/wacom_wac.c#L2712 Also, note that you're missing coverage of BTN_BASE and BTN_BASE2. 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.... > +static void > +pad_init_left_handed(struct evdev_device *device) > +{ > + if (evdev_tablet_has_left_handed(device)) > + evdev_init_left_handed(device, > + pad_change_to_left_handed); > +} > + > +static int > +pad_init(struct pad_dispatch *pad, struct evdev_device *device) > +{ > + pad->base.interface = &pad_interface; > + pad->device = device; > + pad->status = PAD_NONE; > + pad->changed_axes = PAD_AXIS_NONE; > + > + pad_init_buttons(pad, device); > + pad_init_left_handed(device); > + > + return 0; > +} > + > +static uint32_t > +pad_sendevents_get_modes(struct libinput_device *device) > +{ > + return LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; > +} > + > +static enum libinput_config_status > +pad_sendevents_set_mode(struct libinput_device *device, > + enum libinput_config_send_events_mode mode) > +{ > + struct evdev_device *evdev = (struct evdev_device*)device; > + struct pad_dispatch *pad = (struct pad_dispatch*)evdev->dispatch; > + > + if (mode == pad->sendevents.current_mode) > + return LIBINPUT_CONFIG_STATUS_SUCCESS; > + > + switch(mode) { > + case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED: > + break; > + case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED: > + pad_suspend(evdev->dispatch, evdev); > + break; > + default: > + return LIBINPUT_CONFIG_STATUS_UNSUPPORTED; > + } > + > + pad->sendevents.current_mode = mode; > + > + return LIBINPUT_CONFIG_STATUS_SUCCESS; > +} > + > +static enum libinput_config_send_events_mode > +pad_sendevents_get_mode(struct libinput_device *device) > +{ > + struct evdev_device *evdev = (struct evdev_device*)device; > + struct pad_dispatch *dispatch = (struct pad_dispatch*)evdev->dispatch; > + > + return dispatch->sendevents.current_mode; > +} > + > +static enum libinput_config_send_events_mode > +pad_sendevents_get_default_mode(struct libinput_device *device) > +{ > + return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; > +} > + > +struct evdev_dispatch * > +evdev_tablet_pad_create(struct evdev_device *device) > +{ > + struct pad_dispatch *pad; > + > + pad = zalloc(sizeof *pad); > + if (!pad) > + return NULL; > + > + if (pad_init(pad, device) != 0) { > + pad_destroy(&pad->base); > + return NULL; > + } > + > + device->base.config.sendevents = &pad->sendevents.config; > + pad->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; > + pad->sendevents.config.get_modes = pad_sendevents_get_modes; > + pad->sendevents.config.set_mode = pad_sendevents_set_mode; > + pad->sendevents.config.get_mode = pad_sendevents_get_mode; > + pad->sendevents.config.get_default_mode = > pad_sendevents_get_default_mode; > + > + return &pad->base; > +} > + > +int > +evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device) > +{ > + struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch; > + > + if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD)) > + return -1; > + > + return pad->nbuttons; > +} > + > +int > +evdev_device_tablet_pad_get_num_rings(struct evdev_device *device) > +{ > + int nrings = 0; > + > + if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD)) > + return -1; > + > + if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_WHEEL)) { > + nrings++; > + if (libevdev_has_event_code(device->evdev, > + EV_ABS, > + ABS_THROTTLE)) > + nrings++; > + } > + > + return nrings; > +} > + > +int > +evdev_device_tablet_pad_get_num_strips(struct evdev_device *device) > +{ > + int nstrips = 0; > + > + if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD)) > + return -1; > + > + if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_RX)) { > + nstrips++; > + if (libevdev_has_event_code(device->evdev, > + EV_ABS, > + ABS_RY)) > + nstrips++; > + } > + > + return nstrips; > +} > diff --git a/src/evdev-tablet-pad.h b/src/evdev-tablet-pad.h > new file mode 100644 > index 0000000..828ded8 > --- /dev/null > +++ b/src/evdev-tablet-pad.h > @@ -0,0 +1,69 @@ > +/* > + * Copyright © 2015 Red Hat, Inc. > + * > + * Permission to use, copy, modify, distribute, and sell this software and > + * its documentation for any purpose is hereby granted without fee, provided > + * that the above copyright notice appear in all copies and that both that > + * copyright notice and this permission notice appear in supporting > + * documentation, and that the name of the copyright holders not be used in > + * advertising or publicity pertaining to distribution of the software > + * without specific, written prior permission. The copyright holders make > + * no representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER > + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF > + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN > + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#ifndef EVDEV_BUTTONSET_WACOM_H > +#define EVDEV_BUTTONSET_WACOM_H > + > +#include "evdev.h" > + > +#define LIBINPUT_BUTTONSET_AXIS_NONE 0 > + > +enum pad_status { > + PAD_NONE = 0, > + PAD_AXES_UPDATED = 1 << 0, > + PAD_BUTTONS_PRESSED = 1 << 1, > + PAD_BUTTONS_RELEASED = 1 << 2, > +}; > + > +enum pad_axes { > + PAD_AXIS_NONE = 0, > + PAD_AXIS_RING1 = 1 << 0, > + PAD_AXIS_RING2 = 1 << 1, > + PAD_AXIS_STRIP1 = 1 << 2, > + PAD_AXIS_STRIP2 = 1 << 3, > +}; > + > +struct button_state { > + unsigned char bits[NCHARS(KEY_CNT)]; > +}; > + > +struct pad_dispatch { > + struct evdev_dispatch base; > + struct evdev_device *device; > + unsigned char status; > + uint32_t changed_axes; > + > + struct button_state button_state; > + struct button_state prev_button_state; > + > + char button_map[KEY_CNT]; > + unsigned int nbuttons; > + > + bool have_abs_misc_terminator; > + > + struct { > + struct libinput_device_config_send_events config; > + enum libinput_config_send_events_mode current_mode; > + } sendevents; > +}; > + > +#endif > diff --git a/src/evdev.c b/src/evdev.c > index a5511c5..0ec3823 100644 > --- a/src/evdev.c > +++ b/src/evdev.c > @@ -65,7 +65,7 @@ enum evdev_device_udev_tags { > EVDEV_UDEV_TAG_TABLET = (1 << 5), > EVDEV_UDEV_TAG_JOYSTICK = (1 << 6), > EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7), > - EVDEV_UDEV_TAG_BUTTONSET = (1 << 8), > + EVDEV_UDEV_TAG_TABLET_PAD = (1 << 8), > EVDEV_UDEV_TAG_POINTINGSTICK = (1 << 9), > }; > > @@ -82,7 +82,7 @@ static const struct evdev_udev_tag_match > evdev_udev_tag_matches[] = { > {"ID_INPUT_TOUCHPAD", EVDEV_UDEV_TAG_TOUCHPAD}, > {"ID_INPUT_TOUCHSCREEN", EVDEV_UDEV_TAG_TOUCHSCREEN}, > {"ID_INPUT_TABLET", EVDEV_UDEV_TAG_TABLET}, > - {"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_BUTTONSET}, > + {"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_TABLET_PAD}, > {"ID_INPUT_JOYSTICK", EVDEV_UDEV_TAG_JOYSTICK}, > {"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER}, > {"ID_INPUT_POINTINGSTICK", EVDEV_UDEV_TAG_POINTINGSTICK}, > @@ -2031,7 +2031,7 @@ evdev_configure_device(struct evdev_device *device) > udev_tags & EVDEV_UDEV_TAG_POINTINGSTICK ? " Pointingstick" : > "", > udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "", > udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : > "", > - udev_tags & EVDEV_UDEV_TAG_BUTTONSET ? " Buttonset" : ""); > + udev_tags & EVDEV_UDEV_TAG_TABLET_PAD ? " TabletPad" : ""); > > if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) { > log_info(libinput, > @@ -2049,14 +2049,6 @@ evdev_configure_device(struct evdev_device *device) > return -1; > } > > - /* libwacom assigns tablet _and_ tablet_pad to the pad devices */ > - if (udev_tags & EVDEV_UDEV_TAG_BUTTONSET) { > - log_info(libinput, > - "input device '%s', %s is a buttonset, ignoring\n", > - device->devname, devnode); > - return -1; > - } > - > if (evdev_reject_device(device) == -1) { > log_info(libinput, > "input device '%s', %s was rejected.\n", > @@ -2092,7 +2084,17 @@ evdev_configure_device(struct evdev_device *device) > tablet_tags = EVDEV_UDEV_TAG_TABLET | > EVDEV_UDEV_TAG_TOUCHPAD | > EVDEV_UDEV_TAG_TOUCHSCREEN; > - if ((udev_tags & tablet_tags) == EVDEV_UDEV_TAG_TABLET) { > + > + /* libwacom assigns tablet _and_ tablet_pad to the pad devices */ > + if (udev_tags & EVDEV_UDEV_TAG_TABLET_PAD) { > + device->dispatch = evdev_tablet_pad_create(device); > + device->seat_caps |= EVDEV_DEVICE_TABLET_PAD; > + log_info(libinput, > + "input device '%s', %s is a tablet pad\n", > + device->devname, devnode); > + return device->dispatch == NULL ? -1 : 0; > + > + } else if ((udev_tags & tablet_tags) == EVDEV_UDEV_TAG_TABLET) { > device->dispatch = evdev_tablet_create(device); > device->seat_caps |= EVDEV_DEVICE_TABLET; > log_info(libinput, > @@ -2521,6 +2523,8 @@ evdev_device_has_capability(struct evdev_device *device, > return !!(device->seat_caps & EVDEV_DEVICE_GESTURE); > case LIBINPUT_DEVICE_CAP_TABLET_TOOL: > return !!(device->seat_caps & EVDEV_DEVICE_TABLET); > + case LIBINPUT_DEVICE_CAP_TABLET_PAD: > + return !!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD); > default: > return 0; > } > diff --git a/src/evdev.h b/src/evdev.h > index f5e7bed..d76c3dd 100644 > --- a/src/evdev.h > +++ b/src/evdev.h > @@ -61,6 +61,7 @@ enum evdev_device_seat_capability { > EVDEV_DEVICE_KEYBOARD = (1 << 1), > EVDEV_DEVICE_TOUCH = (1 << 2), > EVDEV_DEVICE_TABLET = (1 << 3), > + EVDEV_DEVICE_TABLET_PAD = (1 << 4), > EVDEV_DEVICE_GESTURE = (1 << 5), > }; > > @@ -317,6 +318,9 @@ evdev_mt_touchpad_create(struct evdev_device *device); > struct evdev_dispatch * > evdev_tablet_create(struct evdev_device *device); > > +struct evdev_dispatch * > +evdev_tablet_pad_create(struct evdev_device *device); > + > void > evdev_tag_touchpad(struct evdev_device *device, > struct udev_device *udev_device); > @@ -367,6 +371,15 @@ evdev_device_has_button(struct evdev_device *device, > uint32_t code); > int > evdev_device_has_key(struct evdev_device *device, uint32_t code); > > +int > +evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device); > + > +int > +evdev_device_tablet_pad_get_num_rings(struct evdev_device *device); > + > +int > +evdev_device_tablet_pad_get_num_strips(struct evdev_device *device); > + > double > evdev_device_transform_x(struct evdev_device *device, > double x, > diff --git a/src/libinput.c b/src/libinput.c > index 53da963..22fef0a 100644 > --- a/src/libinput.c > +++ b/src/libinput.c > @@ -2794,19 +2794,19 @@ libinput_device_keyboard_has_key(struct > libinput_device *device, uint32_t code) > LIBINPUT_EXPORT int > libinput_device_tablet_pad_get_num_buttons(struct libinput_device *device) > { > - return 0; > + return evdev_device_tablet_pad_get_num_buttons((struct evdev_device > *)device); > } > > LIBINPUT_EXPORT int > libinput_device_tablet_pad_get_num_rings(struct libinput_device *device) > { > - return 0; > + return evdev_device_tablet_pad_get_num_rings((struct evdev_device > *)device); > } > > LIBINPUT_EXPORT int > libinput_device_tablet_pad_get_num_strips(struct libinput_device *device) > { > - return 0; > + return evdev_device_tablet_pad_get_num_strips((struct evdev_device > *)device); > } > > LIBINPUT_EXPORT struct libinput_event * > _______________________________________________ wayland-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/wayland-devel
