diff --git a/meson.build b/meson.build index 64481a1a..3efa9293 100644 --- a/meson.build +++ b/meson.build @@ -379,6 +379,7 @@ src_libinput = src_libfilter + [ 'src/evdev.c', 'src/evdev-debounce.c', 'src/evdev-fallback.c', + 'src/evdev-plugin.c', 'src/evdev-totem.c', 'src/evdev-middle-button.c', 'src/evdev-mt-touchpad.c', diff --git a/src/evdev-plugin.c b/src/evdev-plugin.c new file mode 100644 index 00000000..a1949ee4 --- /dev/null +++ b/src/evdev-plugin.c @@ -0,0 +1,148 @@ +/* + * Copyright © 2025 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "util-mem.h" +#include + +#include "evdev.h" +#include "evdev-plugin.h" + +_unused_ +static inline void +evdev_print_event(struct evdev_device *device, + const struct evdev_event *e, + uint64_t time_in_us) +{ + static uint32_t offset = 0; + static uint32_t last_time = 0; + uint32_t time = us2ms(time_in_us); + + if (offset == 0) { + offset = time; + last_time = time - offset; + } + + time -= offset; + + switch (evdev_usage_enum(e->usage)) { + case EVDEV_SYN_REPORT: + evdev_log_debug(device, + "%u.%03u ----------------- EV_SYN ----------------- +%ums\n", + time / 1000, + time % 1000, + time - last_time); + + last_time = time; + break; + case EVDEV_MSC_SERIAL: + evdev_log_debug(device, + "%u.%03u %-16s %-16s %#010x\n", + time / 1000, + time % 1000, + evdev_event_get_type_name(e), + evdev_event_get_code_name(e), + e->value); + break; + default: + evdev_log_debug(device, + "%u.%03u %-16s %-20s %4d\n", + time / 1000, + time % 1000, + evdev_event_get_type_name(e), + evdev_event_get_code_name(e), + e->value); + break; + } +} + +static inline void +evdev_process_event(struct evdev_device *device, + struct evdev_event *e, + uint64_t time) +{ + struct evdev_dispatch *dispatch = device->dispatch; + +#if EVENT_DEBUGGING + evdev_print_event(device, e, time); +#endif + + libinput_timer_flush(evdev_libinput_context(device), time); + + dispatch->interface->process(dispatch, device, e, time); +} + +static inline void +evdev_device_dispatch_one(struct libinput_plugin *plugin, + struct libinput_device *libinput_device, + struct evdev_frame *frame) +{ + struct evdev_device *device = evdev_device(libinput_device); + uint64_t time = evdev_frame_get_time(frame); + + size_t nevents; + struct evdev_event *events = evdev_frame_get_events(frame, &nevents); + for (size_t i = 0; i < nevents; i++) { + struct evdev_event *ev = &events[i]; + if (!device->mtdev) { + evdev_process_event(device, ev, time); + } else { + struct input_event e = evdev_event_to_input_event(ev, time); + mtdev_put_event(device->mtdev, &e); + if (evdev_usage_eq(ev->usage, EVDEV_SYN_REPORT)) { + while (!mtdev_empty(device->mtdev)) { + struct input_event e; + + mtdev_get_event(device->mtdev, &e); + + uint64_t time; + struct evdev_event ev = evdev_event_from_input_event(&e, &time); + evdev_process_event(device, &ev, time); + } + } + } + } + + /* Discard event to make the plugin system aware we're done */ + evdev_frame_reset(frame); +} + +static const struct libinput_plugin_interface interface = { + .run = NULL, + .destroy = NULL, + .device_new = NULL, + .device_ignored = NULL, + .device_added = NULL, + .device_removed = NULL, + .evdev_frame = evdev_device_dispatch_one, +}; + +void +libinput_evdev_dispatch_plugin(struct libinput *libinput) +{ + _unref_(libinput_plugin) *p = libinput_plugin_new(libinput, + "evdev", + &interface, + NULL); +} diff --git a/src/evdev-plugin.h b/src/evdev-plugin.h new file mode 100644 index 00000000..43ddcd7d --- /dev/null +++ b/src/evdev-plugin.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2025 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "config.h" + +#include "libinput.h" +#include "libinput-plugin.h" + +void +libinput_evdev_dispatch_plugin(struct libinput *libinput); diff --git a/src/evdev.c b/src/evdev.c index 9b87a0d0..711c4596 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -43,6 +43,7 @@ #include "evdev-frame.h" #include "filter.h" #include "libinput-private.h" +#include "libinput-plugin.h" #include "quirks.h" #include "util-input-event.h" #include "util-udev.h" @@ -1032,108 +1033,14 @@ evdev_read_switch_reliability_prop(struct evdev_device *device) return r; } -_unused_ -static inline void -evdev_print_event(struct evdev_device *device, - const struct evdev_event *e, - uint64_t time_in_us) -{ - static uint32_t offset = 0; - static uint32_t last_time = 0; - uint32_t time = us2ms(time_in_us); - - if (offset == 0) { - offset = time; - last_time = time - offset; - } - - time -= offset; - - switch (evdev_usage_enum(e->usage)) { - case EVDEV_SYN_REPORT: - evdev_log_debug(device, - "%u.%03u ----------------- EV_SYN ----------------- +%ums\n", - time / 1000, - time % 1000, - time - last_time); - - last_time = time; - break; - case EVDEV_MSC_SERIAL: - evdev_log_debug(device, - "%u.%03u %-16s %-16s %#010x\n", - time / 1000, - time % 1000, - evdev_event_get_type_name(e), - evdev_event_get_code_name(e), - e->value); - break; - default: - evdev_log_debug(device, - "%u.%03u %-16s %-20s %4d\n", - time / 1000, - time % 1000, - evdev_event_get_type_name(e), - evdev_event_get_code_name(e), - e->value); - break; - } -} - -static inline void -evdev_process_event(struct evdev_device *device, - struct evdev_event *e, - uint64_t time) -{ - struct evdev_dispatch *dispatch = device->dispatch; - -#if EVENT_DEBUGGING - evdev_print_event(device, e, time); -#endif - - libinput_timer_flush(evdev_libinput_context(device), time); - - dispatch->interface->process(dispatch, device, e, time); -} - -static inline void -evdev_device_dispatch_one(struct evdev_device *device, - struct evdev_event *ev, - uint64_t time) -{ - if (!device->mtdev) { - evdev_process_event(device, ev, time); - } else { - struct input_event e = evdev_event_to_input_event(ev, time); - mtdev_put_event(device->mtdev, &e); - if (evdev_usage_eq(ev->usage, EVDEV_SYN_REPORT)) { - while (!mtdev_empty(device->mtdev)) { - struct input_event e; - mtdev_get_event(device->mtdev, &e); - - uint64_t time; - struct evdev_event ev = evdev_event_from_input_event(&e, &time); - evdev_process_event(device, &ev, time); - } - } - } -} - static inline void evdev_device_dispatch_frame(struct libinput *libinput, struct evdev_device *device, struct evdev_frame *frame) { - size_t nevents; - struct evdev_event *events = evdev_frame_get_events(frame, &nevents); - libinput_plugin_system_notify_evdev_frame(&libinput->plugin_system, &device->base, frame); - - for (size_t i = 0; i < nevents; i++) { - evdev_device_dispatch_one(device, &events[i], evdev_frame_get_time(frame)); - } } static inline void diff --git a/src/libinput-plugin-system.h b/src/libinput-plugin-system.h index b4b61d65..5927240e 100644 --- a/src/libinput-plugin-system.h +++ b/src/libinput-plugin-system.h @@ -47,6 +47,10 @@ struct libinput_plugin_system { void libinput_plugin_system_init(struct libinput_plugin_system *system); +void +libinput_plugin_system_load_internal_plugins(struct libinput *libinput, + struct libinput_plugin_system *system); + void libinput_plugin_system_destroy(struct libinput_plugin_system *system); diff --git a/src/libinput-plugin.c b/src/libinput-plugin.c index ba8167ae..493e821a 100644 --- a/src/libinput-plugin.c +++ b/src/libinput-plugin.c @@ -33,9 +33,12 @@ #include "libinput-plugin-system.h" #include "timer.h" + #include "libinput-util.h" #include "libinput-private.h" +#include "evdev-plugin.h" + struct libinput_plugin { struct libinput *libinput; char *name; @@ -352,6 +355,16 @@ libinput_plugin_system_init(struct libinput_plugin_system *system) list_init(&system->removed_plugins); } +void +libinput_plugin_system_load_internal_plugins(struct libinput *libinput, + struct libinput_plugin_system *system) +{ + /* Our own event dispatch is implemented as mini-plugin, + * guarantee this one to always be last (and after any + * other plugins have run so none of the devices are + * actually connected to anything yet */ + libinput_evdev_dispatch_plugin(libinput); +} void libinput_plugin_system_destroy(struct libinput_plugin_system *system) { diff --git a/src/path-seat.c b/src/path-seat.c index 9d08a66a..f98b4d0d 100644 --- a/src/path-seat.c +++ b/src/path-seat.c @@ -383,6 +383,9 @@ libinput_path_add_device(struct libinput *libinput, return NULL; } + libinput_plugin_system_load_internal_plugins(libinput, + &libinput->plugin_system); + /* We cannot do this during path_create_context because the log * handler isn't set up there but we really want to log to the right * place if the quirks run into parser errors. So we have to do it diff --git a/src/udev-seat.c b/src/udev-seat.c index 81557c63..1a397ca1 100644 --- a/src/udev-seat.c +++ b/src/udev-seat.c @@ -421,6 +421,9 @@ libinput_udev_assign_seat(struct libinput *libinput, if (input->seat_id != NULL) return -1; + libinput_plugin_system_load_internal_plugins(libinput, + &libinput->plugin_system); + /* We cannot do this during udev_create_context because the log * handler isn't set up there but we really want to log to the right * place if the quirks run into parser errors. So we have to do it