tablet: centralize the libwacom handling
authorPeter Hutterer <peter.hutterer@who-t.net>
Mon, 28 Oct 2024 23:46:05 +0000 (09:46 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 31 Oct 2024 03:38:28 +0000 (13:38 +1000)
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: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1073>

src/evdev-tablet-pad-leds.c
src/evdev-tablet-pad.c
src/evdev-tablet-pad.h
src/evdev-tablet.c
src/evdev-tablet.h
src/evdev.c
src/evdev.h

index be309090b68d6a789cb27d552e1e22acae0a5d9b..e83a1970661be05f9916c83368354f0538007d0a 100644 (file)
@@ -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);
index 90614c5dae919c79182a0ac4df0d43b3f9c30be0..e9529250e61d1c7de68131a7b1c186f037748d30 100644 (file)
@@ -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
index fe7aa8b79ff05d3d44e4dfaeb1c7ecdc75e0b0a6..eeed7ee92305cd7293befb6eb7ecdadcb8ff3ad8 100644 (file)
 
 #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,
index c90168bc26f07e78d759a4ba80d24837a591876a..be91c9e65d318ae116d37822c961609e20bfba02 100644 (file)
@@ -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 *
index 48469a2be998368427efd3cc069407631bf6e1c3..e3490cd8c77182ff0bc49ef852534684c818d882 100644 (file)
 
 #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
index cd9206725ced7b5c6db7bc4cf19e5a4ca97245dc..15e338ac6e42e52107194915866090a7ab78b4e2 100644 (file)
@@ -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;
-}
index f954938c5c6b18183993ca9c34f2e8b85e825ca5..4971e4e9520879f87764903556cb235a78f355a9 100644 (file)
@@ -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)