[PATCH libinput 2/2] pad: use libwacom to get the evdev to button number mapping
Peter Hutterer
peter.hutterer at who-t.net
Thu Oct 26 05:24:07 UTC 2017
Some of wacom's tablets, notably the Bamboo series, have a non-predictable
scheme of mapping the buttons to numeric button numbers in libwacom. Since we
promise sequential button numbers, we need to have those identical to
libwacom, otherwise it's impossible to map the two together.
Most tablets have a predictable mapping, so this does not affect the majority
of devices.
For the old-style bamboos, this swaps the buttons around with the buttons
being ordered in a vertical order.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
meson.build | 9 +++
src/evdev-tablet-pad.c | 74 +++++++++++++++++++--
test/test-pad.c | 171 ++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 233 insertions(+), 21 deletions(-)
diff --git a/meson.build b/meson.build
index f93cde70..72bd90b0 100644
--- a/meson.build
+++ b/meson.build
@@ -66,6 +66,15 @@ if have_libwacom
name : 'libwacom_get_paired_device check',
dependencies : dep_libwacom)
config_h.set10('HAVE_LIBWACOM_GET_PAIRED_DEVICE', result)
+
+ code = '''
+ #include <libwacom/libwacom.h>
+ int main(void) { libwacom_get_button_evdev_code(NULL, 'A'); }
+ '''
+ result = cc.links(code,
+ name : 'libwacom_get_button_evdev_code check',
+ dependencies : dep_libwacom)
+ config_h.set10('HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE', result)
else
dep_libwacom = declare_dependency()
endif
diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c
index 82604d70..2e85f7ac 100644
--- a/src/evdev-tablet-pad.c
+++ b/src/evdev-tablet-pad.c
@@ -27,6 +27,10 @@
#include <stdbool.h>
#include <string.h>
+#if HAVE_LIBWACOM
+#include <libwacom/libwacom.h>
+#endif
+
#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_)))
@@ -517,17 +521,61 @@ static struct evdev_dispatch_interface pad_interface = {
.get_switch_state = NULL,
};
+static bool
+pad_init_buttons_from_libwacom(struct pad_dispatch *pad,
+ struct evdev_device *device)
+{
+ bool rc = false;
+#if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE
+ WacomDeviceDatabase *db = NULL;
+ WacomDevice *tablet = NULL;
+ int num_buttons;
+ int map = 0;
+
+ db = libwacom_database_new();
+ if (!db) {
+ evdev_log_info(device,
+ "Failed to initialize libwacom context.\n");
+ goto out;
+ }
+
+ tablet = libwacom_new_from_usbid(db,
+ evdev_device_get_id_vendor(device),
+ evdev_device_get_id_product(device),
+ NULL);
+ if (!tablet)
+ goto out;
+
+ num_buttons = libwacom_get_num_buttons(tablet);
+ for (int i = 0; i < num_buttons; i++) {
+ unsigned int code;
+
+ code = libwacom_get_button_evdev_code(tablet, 'A' + i);
+ if (code == 0)
+ continue;
+
+ pad->button_map[code] = map++;
+ }
+
+ pad->nbuttons = map;
+
+ rc = true;
+out:
+ if (tablet)
+ libwacom_destroy(tablet);
+ if (db)
+ libwacom_database_destroy(db);
+#endif
+ return rc;
+}
+
static void
-pad_init_buttons(struct pad_dispatch *pad,
- struct evdev_device *device)
+pad_init_buttons_from_kernel(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;
-
/* we match wacom_report_numbered_buttons() from the kernel */
for (code = BTN_0; code < BTN_0 + 10; code++) {
if (libevdev_has_event_code(device->evdev, EV_KEY, code))
@@ -553,6 +601,20 @@ pad_init_buttons(struct pad_dispatch *pad,
}
static void
+pad_init_buttons(struct pad_dispatch *pad,
+ struct evdev_device *device)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_LENGTH(pad->button_map); i++)
+ pad->button_map[i] = -1;
+
+ if (!pad_init_buttons_from_libwacom(pad, device))
+ pad_init_buttons_from_kernel(pad, device);
+
+}
+
+static void
pad_init_left_handed(struct evdev_device *device)
{
if (evdev_tablet_has_left_handed(device))
diff --git a/test/test-pad.c b/test/test-pad.c
index 085d6c58..3383c60f 100644
--- a/test/test-pad.c
+++ b/test/test-pad.c
@@ -29,6 +29,10 @@
#include <unistd.h>
#include <stdbool.h>
+#if HAVE_LIBWACOM
+#include <libwacom/libwacom.h>
+#endif
+
#include "libinput-util.h"
#include "litest.h"
@@ -119,6 +123,35 @@ START_TEST(pad_time)
}
END_TEST
+START_TEST(pad_num_buttons_libwacom)
+{
+#if HAVE_LIBWACOM
+ struct litest_device *dev = litest_current_device();
+ struct libinput_device *device = dev->libinput_device;
+ WacomDeviceDatabase *db = NULL;
+ WacomDevice *wacom = NULL;
+ unsigned int nb_lw, nb;
+
+ db = libwacom_database_new();
+ ck_assert_notnull(db);
+
+ wacom = libwacom_new_from_usbid(db,
+ libevdev_get_id_vendor(dev->evdev),
+ libevdev_get_id_product(dev->evdev),
+ NULL);
+ ck_assert_notnull(wacom);
+
+ nb_lw = libwacom_get_num_buttons(wacom);
+ nb = libinput_device_tablet_pad_get_num_buttons(device);
+
+ ck_assert_int_eq(nb, nb_lw);
+
+ libwacom_destroy(wacom);
+ libwacom_database_destroy(db);
+#endif
+}
+END_TEST
+
START_TEST(pad_num_buttons)
{
struct litest_device *dev = litest_current_device();
@@ -141,33 +174,42 @@ START_TEST(pad_num_buttons)
}
END_TEST
-START_TEST(pad_button)
+START_TEST(pad_button_intuos)
{
+#if !HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
unsigned int code;
unsigned int expected_number = 0;
struct libinput_event *ev;
struct libinput_event_tablet_pad *pev;
+ unsigned int count;
+
+ /* Intuos button mapping is sequential up from BTN_0 and continues
+ * with BTN_A */
+
+ if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_0))
+ return;
litest_drain_events(li);
- for (code = BTN_0; code < KEY_MAX; code++) {
- if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
+ for (code = BTN_0; code < BTN_DIGI; code++) {
+ /* SKip over the BTN_MOUSE and BTN_JOYSTICK range */
+ if (code >= BTN_MOUSE && code < BTN_A) {
+ ck_assert(!libevdev_has_event_code(dev->evdev,
+ EV_KEY, code));
continue;
-
- litest_button_click(dev, code, 1);
- litest_button_click(dev, code, 0);
- libinput_dispatch(li);
-
- switch (code) {
- case BTN_STYLUS:
- litest_assert_empty_queue(li);
- continue;
- default:
- break;
}
+ if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
+ return;
+
+ litest_button_click(dev, code, 1);
+ litest_button_click(dev, code, 0);
+ libinput_dispatch(li);
+
+ count++;
+
ev = libinput_get_event(li);
pev = litest_is_pad_button_event(ev,
expected_number,
@@ -186,6 +228,102 @@ START_TEST(pad_button)
}
litest_assert_empty_queue(li);
+
+ ck_assert_int_gt(count, 3);
+#endif
+}
+END_TEST
+
+START_TEST(pad_button_bamboo)
+{
+#if !HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ unsigned int code;
+ unsigned int expected_number = 0;
+ struct libinput_event *ev;
+ struct libinput_event_tablet_pad *pev;
+ unsigned int count;
+
+ if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_LEFT))
+ return;
+
+ litest_drain_events(li);
+
+ for (code = BTN_LEFT; code < BTN_JOYSTICK; code++) {
+ if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
+ return;
+
+ litest_button_click(dev, code, 1);
+ litest_button_click(dev, code, 0);
+ libinput_dispatch(li);
+
+ count++;
+
+ ev = libinput_get_event(li);
+ pev = litest_is_pad_button_event(ev,
+ expected_number,
+ LIBINPUT_BUTTON_STATE_PRESSED);
+ ev = libinput_event_tablet_pad_get_base_event(pev);
+ libinput_event_destroy(ev);
+
+ ev = libinput_get_event(li);
+ pev = litest_is_pad_button_event(ev,
+ expected_number,
+ LIBINPUT_BUTTON_STATE_RELEASED);
+ ev = libinput_event_tablet_pad_get_base_event(pev);
+ libinput_event_destroy(ev);
+
+ expected_number++;
+ }
+
+ litest_assert_empty_queue(li);
+
+ ck_assert_int_gt(count, 3);
+#endif
+}
+END_TEST
+
+START_TEST(pad_button_libwacom)
+{
+#if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ WacomDeviceDatabase *db = NULL;
+ WacomDevice *wacom = NULL;
+
+ db = libwacom_database_new();
+ assert(db);
+
+ wacom = libwacom_new_from_usbid(db,
+ libevdev_get_id_vendor(dev->evdev),
+ libevdev_get_id_product(dev->evdev),
+ NULL);
+ assert(wacom);
+
+ litest_drain_events(li);
+
+ for (int i = 0; i < libwacom_get_num_buttons(wacom); i++) {
+ unsigned int code;
+
+ code = libwacom_get_button_evdev_code(wacom, 'A' + i);
+
+ litest_button_click(dev, code, 1);
+ litest_button_click(dev, code, 0);
+ libinput_dispatch(li);
+
+ litest_assert_pad_button_event(li,
+ i,
+ LIBINPUT_BUTTON_STATE_PRESSED);
+ litest_assert_pad_button_event(li,
+ i,
+ LIBINPUT_BUTTON_STATE_RELEASED);
+ }
+
+
+ libwacom_destroy(wacom);
+ libwacom_database_destroy(db);
+#endif
}
END_TEST
@@ -788,7 +926,10 @@ litest_setup_tests_pad(void)
litest_add("pad:time", pad_time, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:button", pad_num_buttons, LITEST_TABLET_PAD, LITEST_ANY);
- litest_add("pad:button", pad_button, LITEST_TABLET_PAD, LITEST_ANY);
+ litest_add("pad:button", pad_num_buttons_libwacom, LITEST_TABLET_PAD, LITEST_ANY);
+ litest_add("pad:button", pad_button_intuos, LITEST_TABLET_PAD, LITEST_ANY);
+ litest_add("pad:button", pad_button_bamboo, LITEST_TABLET_PAD, LITEST_ANY);
+ litest_add("pad:button", pad_button_libwacom, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:button", pad_button_mode_groups, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:ring", pad_has_ring, LITEST_RING, LITEST_ANY);
--
2.13.6
More information about the wayland-devel
mailing list