From 2b2959fc8b2172c692e7f182c3cf7e90a6320e1a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 29 Oct 2024 09:46:05 +1000 Subject: [PATCH] tablet: centralize the libwacom handling Instead of re-creating the the libwacom device from the database every time we need it let's create it once during tablet|pad_init and pass it down to the functions. This allows us to have one point per tablet/pad where we can log an error if the device is not supported by libwacom - previously this was printed during the left-handed setup. Part-of: --- src/evdev-tablet-pad-leds.c | 26 ++------ src/evdev-tablet-pad.c | 119 ++++++++++++++++++++---------------- src/evdev-tablet-pad.h | 10 ++- src/evdev-tablet.c | 106 ++++++++++++++++++++------------ src/evdev-tablet.h | 4 ++ src/evdev.c | 47 -------------- src/evdev.h | 3 - 7 files changed, 152 insertions(+), 163 deletions(-) diff --git a/src/evdev-tablet-pad-leds.c b/src/evdev-tablet-pad-leds.c index be309090..e83a1970 100644 --- a/src/evdev-tablet-pad-leds.c +++ b/src/evdev-tablet-pad-leds.c @@ -404,23 +404,13 @@ pad_find_button_group(struct pad_dispatch *pad, static int pad_init_leds_from_libwacom(struct pad_dispatch *pad, - struct evdev_device *device) + struct evdev_device *device, + WacomDevice *wacom) { - struct libinput *li = pad_libinput_context(pad); - WacomDeviceDatabase *db = NULL; - WacomDevice *wacom = NULL; int rc = -EINVAL; - db = libinput_libwacom_ref(li); - if (!db) - goto out; - - wacom = libwacom_new_from_path(db, - udev_device_get_devnode(device->udev_device), - WFALLBACK_NONE, - NULL); if (!wacom) - goto out; + return -ENOENT; for (int b = 0; b < libwacom_get_num_buttons(wacom); b++) { char btn = 'A' + b; @@ -523,11 +513,6 @@ pad_init_leds_from_libwacom(struct pad_dispatch *pad, rc = 0; out: - if (wacom) - libwacom_destroy(wacom); - if (db) - libinput_libwacom_unref(li); - if (rc != 0) { if (rc == -ENOENT && is_litest_device(pad->device)) { evdev_log_error(pad->device, @@ -567,7 +552,8 @@ pad_init_fallback_group(struct pad_dispatch *pad) int pad_init_leds(struct pad_dispatch *pad, - struct evdev_device *device) + struct evdev_device *device, + WacomDevice *wacom) { int rc = 1; @@ -582,7 +568,7 @@ pad_init_leds(struct pad_dispatch *pad, /* If libwacom fails, we init one fallback group anyway */ #if HAVE_LIBWACOM - rc = pad_init_leds_from_libwacom(pad, device); + rc = pad_init_leds_from_libwacom(pad, device, wacom); #endif if (rc != 0) rc = pad_init_fallback_group(pad); diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c index 90614c5d..e9529250 100644 --- a/src/evdev-tablet-pad.c +++ b/src/evdev-tablet-pad.c @@ -642,58 +642,28 @@ static struct evdev_dispatch_interface pad_interface = { static bool pad_init_buttons_from_libwacom(struct pad_dispatch *pad, - struct evdev_device *device) + struct evdev_device *device, + WacomDevice *tablet) { bool rc = false; #if HAVE_LIBWACOM - struct libinput *li = pad_libinput_context(pad); - WacomDeviceDatabase *db = NULL; - WacomDevice *tablet = NULL; - int num_buttons; - int map = 0; - char event_path[64]; - - db = libinput_libwacom_ref(li); - if (!db) - goto out; - - snprintf(event_path, - sizeof(event_path), - "/dev/input/%s", - evdev_device_get_sysname(device)); - tablet = libwacom_new_from_path(db, - event_path, - WFALLBACK_NONE, - NULL); - if (!tablet) { - tablet = libwacom_new_from_usbid(db, - evdev_device_get_id_vendor(device), - evdev_device_get_id_product(device), - NULL); - } - if (!tablet) - goto out; + if (tablet) { + int num_buttons = libwacom_get_num_buttons(tablet); + int map = 0; + for (int i = 0; i < num_buttons; i++) { + unsigned int code; - 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; - code = libwacom_get_button_evdev_code(tablet, 'A' + i); - if (code == 0) - continue; + map_set_button_map(pad->button_map[code], map++); + } - map_set_button_map(pad->button_map[code], map++); + pad->nbuttons = map; + rc = true; } - - pad->nbuttons = map; - - rc = true; -out: - if (tablet) - libwacom_destroy(tablet); - if (db) - libinput_libwacom_unref(li); #endif return rc; } @@ -750,23 +720,30 @@ pad_init_keys(struct pad_dispatch *pad, struct evdev_device *device) static void pad_init_buttons(struct pad_dispatch *pad, - struct evdev_device *device) + struct evdev_device *device, + WacomDevice *wacom) { size_t i; for (i = 0; i < ARRAY_LENGTH(pad->button_map); i++) map_init(pad->button_map[i]); - if (!pad_init_buttons_from_libwacom(pad, device)) + if (!pad_init_buttons_from_libwacom(pad, device, wacom)) pad_init_buttons_from_kernel(pad, device); pad_init_keys(pad, device); } static void -pad_init_left_handed(struct evdev_device *device) +pad_init_left_handed(struct evdev_device *device, + WacomDevice *wacom) { - if (evdev_tablet_has_left_handed(device)) + bool has_left_handed = true; + +#if HAVE_LIBWACOM + has_left_handed = !wacom || libwacom_is_reversible(wacom); +#endif + if (has_left_handed) evdev_init_left_handed(device, pad_change_to_left_handed); } @@ -774,6 +751,34 @@ pad_init_left_handed(struct evdev_device *device) static int pad_init(struct pad_dispatch *pad, struct evdev_device *device) { + int rc = 1; + struct libinput *li = evdev_libinput_context(device); + WacomDevice *wacom = NULL; +#if HAVE_LIBWACOM + WacomDeviceDatabase *db = libinput_libwacom_ref(li); + if (db) { + char event_path[64]; + snprintf(event_path, + sizeof(event_path), + "/dev/input/%s", + evdev_device_get_sysname(device)); + wacom = libwacom_new_from_path(db, event_path, WFALLBACK_NONE, NULL); + if (!wacom) { + wacom = libwacom_new_from_usbid(db, + evdev_device_get_id_vendor(device), + evdev_device_get_id_product(device), + NULL); + } + if (!wacom) { + evdev_log_info(device, + "device \"%s\" (%04x:%04x) is not known to libwacom\n", + evdev_device_get_name(device), + evdev_device_get_id_vendor(device), + evdev_device_get_id_product(device)); + } + } +#endif + pad->base.dispatch_type = DISPATCH_TABLET_PAD; pad->base.interface = &pad_interface; pad->device = device; @@ -787,15 +792,21 @@ pad_init(struct pad_dispatch *pad, struct evdev_device *device) if (libevdev_has_event_code(device->evdev, EV_REL, REL_WHEEL) && libevdev_has_event_code(device->evdev, EV_REL, REL_DIAL)) { - log_bug_libinput(pad_libinput_context(pad), "Unsupported combination REL_DIAL and REL_WHEEL\n"); + log_bug_libinput(li, "Unsupported combination REL_DIAL and REL_WHEEL\n"); } - pad_init_buttons(pad, device); - pad_init_left_handed(device); - if (pad_init_leds(pad, device) != 0) - return 1; + pad_init_buttons(pad, device, wacom); + pad_init_left_handed(device, wacom); + + rc = pad_init_leds(pad, device, wacom); - return 0; +#if HAVE_LIBWACOM + if (wacom) + libwacom_destroy(wacom); + if (db) + libinput_libwacom_unref(li); +#endif + return rc; } static uint32_t diff --git a/src/evdev-tablet-pad.h b/src/evdev-tablet-pad.h index fe7aa8b7..eeed7ee9 100644 --- a/src/evdev-tablet-pad.h +++ b/src/evdev-tablet-pad.h @@ -26,6 +26,10 @@ #include "evdev.h" +#if !HAVE_LIBWACOM +typedef void * WacomDevice; +#endif + #define LIBINPUT_BUTTONSET_AXIS_NONE 0 enum pad_status { @@ -106,9 +110,13 @@ pad_libinput_context(const struct pad_dispatch *pad) } int -pad_init_leds(struct pad_dispatch *pad, struct evdev_device *device); +pad_init_leds(struct pad_dispatch *pad, + struct evdev_device *device, + WacomDevice *wacom); + void pad_destroy_leds(struct pad_dispatch *pad); + void pad_button_update_mode(struct libinput_tablet_pad_mode_group *g, unsigned int button_index, diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index c90168bc..be91c9e6 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -2577,56 +2577,53 @@ tablet_init_accel(struct tablet_dispatch *tablet, struct evdev_device *device) } static void -tablet_init_left_handed(struct evdev_device *device) +tablet_init_left_handed(struct evdev_device *device, + WacomDevice *wacom) { - if (evdev_tablet_has_left_handed(device)) + bool has_left_handed = true; + +#if HAVE_LIBWACOM + has_left_handed = !wacom || libwacom_is_reversible(wacom); +#endif + if (has_left_handed) evdev_init_left_handed(device, tablet_change_to_left_handed); } -static void -tablet_lookup_libwacom(struct evdev_device *device, - struct tablet_dispatch *tablet, - bool *is_aes, - bool *is_display_tablet) +static inline bool +tablet_is_display_tablet(WacomDevice *wacom) { #if HAVE_LIBWACOM - const char *devnode; - WacomDeviceDatabase *db; - WacomDevice *libwacom_device = NULL; - int vid = evdev_device_get_id_vendor(device); - - db = tablet_libinput_context(tablet)->libwacom.db; - if (!db) - return; - - devnode = udev_device_get_devnode(device->udev_device); - libwacom_device = libwacom_new_from_path(db, devnode, WFALLBACK_NONE, NULL); - if (!libwacom_device) - return; - - *is_display_tablet = !!(libwacom_get_integration_flags(libwacom_device) - & (WACOM_DEVICE_INTEGRATED_SYSTEM|WACOM_DEVICE_INTEGRATED_DISPLAY)); + return wacom && + !!(libwacom_get_integration_flags(wacom) & (WACOM_DEVICE_INTEGRATED_SYSTEM|WACOM_DEVICE_INTEGRATED_DISPLAY)); +#else + return false; +#endif +} +static inline bool +tablet_is_aes(struct evdev_device *device, WacomDevice *wacom) +{ +#if HAVE_LIBWACOM + int vid = evdev_device_get_id_vendor(device); /* Wacom-specific check for whether smoothing is required: * libwacom keeps all the AES pens in a single group, so any device * that supports AES pens will list all AES pens. 0x11 is one of the * lenovo pens so we use that as the flag of whether the tablet * is an AES tablet */ - if (vid == VENDOR_ID_WACOM) { + if (wacom && vid == VENDOR_ID_WACOM) { int nstyli; - const int *stylus_ids = libwacom_get_supported_styli(libwacom_device, &nstyli); + const int *stylus_ids = libwacom_get_supported_styli(wacom, &nstyli); for (int i = 0; i < nstyli; i++) { if (stylus_ids[i] == 0x11) { - *is_aes = true; - break; + return true; } } } - - libwacom_destroy(libwacom_device); #endif + + return false; } static void @@ -2737,9 +2734,35 @@ static int tablet_init(struct tablet_dispatch *tablet, struct evdev_device *device) { + struct libinput *li = evdev_libinput_context(device); struct libevdev *evdev = device->evdev; enum libinput_tablet_tool_axis axis; - int rc; + int rc = -1; + WacomDevice *wacom = NULL; +#if HAVE_LIBWACOM + WacomDeviceDatabase *db = libinput_libwacom_ref(li); + if (db) { + char event_path[64]; + snprintf(event_path, + sizeof(event_path), + "/dev/input/%s", + evdev_device_get_sysname(device)); + wacom = libwacom_new_from_path(db, event_path, WFALLBACK_NONE, NULL); + if (!wacom) { + wacom = libwacom_new_from_usbid(db, + evdev_device_get_id_vendor(device), + evdev_device_get_id_product(device), + NULL); + } + if (!wacom) { + evdev_log_info(device, + "device \"%s\" (%04x:%04x) is not known to libwacom\n", + evdev_device_get_name(device), + evdev_device_get_id_vendor(device), + evdev_device_get_id_product(device)); + } + } +#endif tablet->base.dispatch_type = DISPATCH_TABLET; tablet->base.interface = &tablet_interface; @@ -2749,11 +2772,10 @@ tablet_init(struct tablet_dispatch *tablet, list_init(&tablet->tool_list); if (tablet_reject_device(device)) - return -1; + goto out; - bool is_aes = false; - bool is_display_tablet = false; - tablet_lookup_libwacom(device, tablet, &is_aes, &is_display_tablet); + bool is_aes = tablet_is_aes(device, wacom); + bool is_display_tablet = tablet_is_display_tablet(wacom); if (!libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN)) { libevdev_enable_event_code(evdev, EV_KEY, BTN_TOOL_PEN, NULL); @@ -2772,10 +2794,10 @@ tablet_init(struct tablet_dispatch *tablet, tablet_init_proximity_threshold(tablet, device); rc = tablet_init_accel(tablet, device); if (rc != 0) - return rc; + goto out; evdev_init_sendevents(device, &tablet->base); - tablet_init_left_handed(device); + tablet_init_left_handed(device, wacom); tablet_init_smoothing(device, tablet, is_aes); for (axis = LIBINPUT_TABLET_TOOL_AXIS_X; @@ -2792,12 +2814,20 @@ tablet_init(struct tablet_dispatch *tablet, tablet->quirks.need_to_force_prox_out = true; libinput_timer_init(&tablet->quirks.prox_out_timer, - tablet_libinput_context(tablet), + li, "proxout", tablet_proximity_out_quirk_timer_func, tablet); - return 0; + rc = 0; +out: +#if HAVE_LIBWACOM + if (wacom) + libwacom_destroy(wacom); + if (db) + libinput_libwacom_unref(li); +#endif + return rc; } struct evdev_dispatch * diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index 48469a2b..e3490cd8 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -27,6 +27,10 @@ #include "evdev.h" +#if !HAVE_LIBWACOM +typedef void * WacomDevice; +#endif + #define LIBINPUT_TABLET_TOOL_AXIS_NONE 0 #define LIBINPUT_TOOL_NONE 0 #define LIBINPUT_TABLET_TOOL_TYPE_MAX LIBINPUT_TABLET_TOOL_TYPE_LENS diff --git a/src/evdev.c b/src/evdev.c index cd920672..15e338ac 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -3128,50 +3128,3 @@ evdev_device_destroy(struct evdev_device *device) udev_device_unref(device->udev_device); free(device); } - -bool -evdev_tablet_has_left_handed(struct evdev_device *device) -{ - bool has_left_handed = true; -#if HAVE_LIBWACOM - struct libinput *li = evdev_libinput_context(device); - WacomDeviceDatabase *db = NULL; - WacomDevice *d = NULL; - WacomError *error; - const char *devnode; - - db = libinput_libwacom_ref(li); - if (!db) - goto out; - - error = libwacom_error_new(); - devnode = udev_device_get_devnode(device->udev_device); - - d = libwacom_new_from_path(db, - devnode, - WFALLBACK_NONE, - error); - - if (d) { - has_left_handed = !!libwacom_is_reversible(d); - } else if (libwacom_error_get_code(error) == WERROR_UNKNOWN_MODEL) { - evdev_log_info(device, - "tablet '%s' unknown to libwacom\n", - device->devname); - } else { - evdev_log_error(device, - "libwacom error: %s\n", - libwacom_error_get_message(error)); - } - - if (error) - libwacom_error_free(&error); - if (d) - libwacom_destroy(d); - if (db) - libinput_libwacom_unref(li); - -out: -#endif - return has_left_handed; -} diff --git a/src/evdev.h b/src/evdev.h index f954938c..4971e4e9 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -671,9 +671,6 @@ void evdev_init_left_handed(struct evdev_device *device, void (*change_to_left_handed)(struct evdev_device *)); -bool -evdev_tablet_has_left_handed(struct evdev_device *device); - static inline uint32_t evdev_to_left_handed(struct evdev_device *device, uint32_t button) -- 2.34.1