From b98b8d1be2ce54488276502f98a0fa6e739230ab Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Thu, 28 Mar 2024 14:31:27 +0100 Subject: [PATCH] Move indev to shared component --- CHANGELOG.md | 2 +- buffyboard/README.md | 2 + buffyboard/indev.c | 84 -------------------------------------- buffyboard/indev.h | 20 --------- buffyboard/main.c | 7 ++-- buffyboard/meson.build | 6 ++- {unl0kr => shared}/indev.c | 36 ++++++++++------ {unl0kr => shared}/indev.h | 29 ++++++++----- unl0kr/main.c | 23 ++--------- unl0kr/meson.build | 2 +- 10 files changed, 58 insertions(+), 153 deletions(-) delete mode 100644 buffyboard/indev.c delete mode 100644 buffyboard/indev.h rename {unl0kr => shared}/indev.c (94%) rename {unl0kr => shared}/indev.h (56%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11c8e3e..6c5e4a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ If a change only affects particular applications, they are listed in parentheses ## Unreleased -Nothing at the moment +- feat(buffyboard): Handle input device connection/disconnection at runtime; adds new dependency libudev ## 3.0.0 (2024-03-22) diff --git a/buffyboard/README.md b/buffyboard/README.md index 4e7bdb4..a7adfc6 100644 --- a/buffyboard/README.md +++ b/buffyboard/README.md @@ -32,6 +32,7 @@ For a growing collection of demo videos, see the [wiki]. - [lvgl] (git submodule / linked statically) - [squeek2lvgl] (git submodule / linked statically) - [libinput] +- [libudev] - evdev kernel module - uinput kernel module @@ -129,6 +130,7 @@ The [FontAwesome] font is licensed under the Open Font License version 1.1. [arrow-alt-circle-up]: https://fontawesome.com/v5.15/icons/arrow-alt-circle-up?style=solid [fbkeyboard]: https://github.com/bakonyiferenc/fbkeyboard [libinput]: https://gitlab.freedesktop.org/libinput/libinput +[libudev]: https://github.com/systemd/systemd/tree/main/src/libudev [lv_port_linux_frame_buffer]: https://github.com/lvgl/lv_port_linux_frame_buffer [lv_sim_emscripten]: https://github.com/lvgl/lv_sim_emscripten/blob/master/mouse_cursor_icon.c [lvgl]: https://github.com/lvgl/lvgl diff --git a/buffyboard/indev.c b/buffyboard/indev.c deleted file mode 100644 index 1c4750f..0000000 --- a/buffyboard/indev.c +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright 2021 Johannes Marbach - * SPDX-License-Identifier: GPL-3.0-or-later - */ - - -#include "indev.h" - -#include "../shared/cursor/cursor.h" - -#include "lvgl/lvgl.h" - -#include - - -/** - * Defines - */ - -#define MAX_POINTER_DEVS 4 -#define MAX_TOUCHSCREEN_DEVS 1 - - -/** - * Static variables - */ - -static int num_pointer_devs = 0; -static char *pointer_devs[MAX_POINTER_DEVS]; -static lv_indev_t *pointer_indevs[MAX_POINTER_DEVS]; - -static int num_touchscreen_devs = 0; -static char *touchscreen_devs[MAX_TOUCHSCREEN_DEVS]; -static lv_indev_t *touchscreen_indevs[MAX_TOUCHSCREEN_DEVS]; - - -/** - * Static prototypes - */ - -/** - * Auto-connect available input devices having a specific capability. - * - * @param capability capability to filter devices by - * @param max_num_devs maximum number of devices to connect - * @param num_devs pointer for writing the actual number of connected devices into - * @param devs array for storing device paths - * @param indevs array for storing LVGL indevs - */ -static void auto_connect(lv_libinput_capability capability, int max_num_devs, int *num_devs, char *devs[], lv_indev_t *indevs[]); - - -/** - * Static functions - */ - -static void auto_connect(lv_libinput_capability capability, int max_num_devs, int *num_devs, char *devs[], lv_indev_t *indevs[]) { - lv_memset(devs, 0, max_num_devs * sizeof(char *)); - lv_memset(indevs, 0, max_num_devs * sizeof(lv_indev_t *)); - - *num_devs = lv_libinput_find_devs(capability, devs, max_num_devs, false); - - for (int i = 0; i < *num_devs; ++i) { - indevs[i] = lv_libinput_create(capability & LV_LIBINPUT_CAPABILITY_KEYBOARD ? LV_INDEV_TYPE_KEYPAD : LV_INDEV_TYPE_POINTER, devs[i]); - } -} - - -/** - * Public functions - */ - -void bb_indev_auto_connect() { - auto_connect(LV_LIBINPUT_CAPABILITY_POINTER, MAX_POINTER_DEVS, &num_pointer_devs, pointer_devs, pointer_indevs); - auto_connect(LV_LIBINPUT_CAPABILITY_TOUCH, MAX_TOUCHSCREEN_DEVS, &num_touchscreen_devs, touchscreen_devs, touchscreen_indevs); -} - -void bb_indev_set_up_mouse_cursor() { - lv_obj_t *cursor_obj = lv_img_create(lv_scr_act()); - lv_img_set_src(cursor_obj, &bb_cursor_img_dsc); - for (int i = 0; i < num_pointer_devs; ++i) { - lv_indev_set_cursor(pointer_indevs[i], cursor_obj); - } -} diff --git a/buffyboard/indev.h b/buffyboard/indev.h deleted file mode 100644 index 6d37f96..0000000 --- a/buffyboard/indev.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright 2021 Johannes Marbach - * SPDX-License-Identifier: GPL-3.0-or-later - */ - - -#ifndef BB_INDEV_H -#define BB_INDEV_H - -/** - * Auto-connect currently available keyboard, pointer and touchscreen input devices. - */ -void bb_indev_auto_connect(); - -/** - * Set up the mouse cursor image for currently connected pointer devices. - */ -void bb_indev_set_up_mouse_cursor(); - -#endif /* BB_INDEV_H */ diff --git a/buffyboard/main.c b/buffyboard/main.c index 4454e97..3321d3a 100644 --- a/buffyboard/main.c +++ b/buffyboard/main.c @@ -6,13 +6,13 @@ #include "buffyboard.h" #include "command_line.h" -#include "indev.h" #include "sq2lv_layouts.h" #include "terminal.h" #include "uinput_device.h" #include "lvgl/lvgl.h" +#include "../shared/indev.h" #include "../squeek2lvgl/sq2lv.h" #include @@ -279,9 +279,8 @@ int main(int argc, char *argv[]) { } } - /* Connect input devices */ - bb_indev_auto_connect(); - bb_indev_set_up_mouse_cursor(); + /* Start input device monitor and auto-connect available devices */ + bb_indev_start_monitor_and_autoconnect(false, true, true); /* Initialise theme and styles */ set_theme(true); diff --git a/buffyboard/meson.build b/buffyboard/meson.build index 60c870b..aeee739 100644 --- a/buffyboard/meson.build +++ b/buffyboard/meson.build @@ -15,7 +15,6 @@ add_project_arguments('-DBB_VERSION="@0@"'.format(meson.project_version()), lang buffyboard_sources = [ 'command_line.c', 'font_32.c', - 'indev.c', 'main.c', 'sq2lv_layouts.c', 'terminal.c', @@ -23,7 +22,9 @@ buffyboard_sources = [ ] shared_sources = [ - '../shared/cursor/cursor.c' + '../shared/cursor/cursor.c', + '../shared/indev.c', + '../shared/log.c', ] squeek2lvgl_sources = [ @@ -38,6 +39,7 @@ executable( include_directories: ['..'], dependencies: [ dependency('libinput'), + dependency('libudev'), meson.get_compiler('c').find_library('m', required: false), ], install: true diff --git a/unl0kr/indev.c b/shared/indev.c similarity index 94% rename from unl0kr/indev.c rename to shared/indev.c index e71ce35..692158f 100644 --- a/unl0kr/indev.c +++ b/shared/indev.c @@ -6,8 +6,8 @@ #include "indev.h" -#include "../shared/cursor/cursor.h" -#include "../shared/log.h" +#include "cursor/cursor.h" +#include "log.h" #include "lvgl/src/indev/lv_indev_private.h" @@ -361,12 +361,17 @@ static void set_mouse_cursor(struct input_device *device) { lv_indev_set_cursor(device->indev, cursor_obj); } +static void query_device_monitor(lv_timer_t *timer) { + LV_UNUSED(timer); + bb_indev_query_monitor(); +} + /** * Public functions */ -void ul_indev_set_allowed_device_capability(bool keyboard, bool pointer, bool touchscreen) { +void bb_indev_set_allowed_device_capability(bool keyboard, bool pointer, bool touchscreen) { allowed_capability = LV_LIBINPUT_CAPABILITY_NONE; if (keyboard) { allowed_capability |= LV_LIBINPUT_CAPABILITY_KEYBOARD; @@ -379,7 +384,7 @@ void ul_indev_set_allowed_device_capability(bool keyboard, bool pointer, bool to } } -void ul_indev_set_keyboard_input_group(lv_group_t *group) { +void bb_indev_set_keyboard_input_group(lv_group_t *group) { /* Store the group */ keyboard_input_group = group; @@ -391,7 +396,14 @@ void ul_indev_set_keyboard_input_group(lv_group_t *group) { } } -void ul_indev_auto_connect() { +void bb_indev_start_monitor_and_autoconnect(bool keyboard, bool pointer, bool touchscreen) { + bb_indev_set_allowed_device_capability(keyboard, pointer, touchscreen); + bb_indev_start_monitor(); + lv_timer_create(query_device_monitor, 1000, NULL); + bb_indev_auto_connect(); +} + +void bb_indev_auto_connect() { bb_log(BB_LOG_LEVEL_VERBOSE, "Auto-connecting supported input devices"); /* Make sure udev context is initialised */ @@ -434,7 +446,7 @@ void ul_indev_auto_connect() { udev_enumerate_unref(enumerate); } -void ul_indev_start_monitor() { +void bb_indev_start_monitor() { /* Make sure udev context is initialised */ if (!context) { context = udev_new(); @@ -454,7 +466,7 @@ void ul_indev_start_monitor() { monitor = udev_monitor_new_from_netlink(context, "udev"); if (!monitor) { bb_log(BB_LOG_LEVEL_WARNING, "Could not create udev monitor"); - ul_indev_stop_monitor(); + bb_indev_stop_monitor(); return; } @@ -466,19 +478,19 @@ void ul_indev_start_monitor() { /* Start monitor */ if (udev_monitor_enable_receiving(monitor) < 0) { bb_log(BB_LOG_LEVEL_WARNING, "Could not enable udev monitor"); - ul_indev_stop_monitor(); + bb_indev_stop_monitor(); return; } /* Obtain monitor file descriptor */ if ((monitor_fd = udev_monitor_get_fd(monitor)) < 0) { bb_log(BB_LOG_LEVEL_WARNING, "Could not acquire file descriptor for udev monitor"); - ul_indev_stop_monitor(); + bb_indev_stop_monitor(); return; } } -void ul_indev_stop_monitor() { +void bb_indev_stop_monitor() { /* Unreference monitor */ if (monitor) { udev_monitor_unref(monitor); @@ -497,7 +509,7 @@ void ul_indev_stop_monitor() { } } -void ul_indev_query_monitor() { +void bb_indev_query_monitor() { /* Make sure the monitor is running */ if (!monitor) { bb_log(BB_LOG_LEVEL_ERROR, "Cannot query udev monitor because it is not running"); @@ -535,7 +547,7 @@ void ul_indev_query_monitor() { } } -bool ul_indev_is_keyboard_connected() { +bool bb_indev_is_keyboard_connected() { for (int i = 0; i < num_connected_devices; ++i) { if (is_keyboard_device(devices[i])) { return true; diff --git a/unl0kr/indev.h b/shared/indev.h similarity index 56% rename from unl0kr/indev.h rename to shared/indev.h index b71ca9d..2733444 100644 --- a/unl0kr/indev.h +++ b/shared/indev.h @@ -4,8 +4,8 @@ */ -#ifndef UL_INDEV_H -#define UL_INDEV_H +#ifndef BB_INDEV_H +#define BB_INDEV_H #include "lvgl/lvgl.h" @@ -18,40 +18,49 @@ * @param pointer if true, allow connection of pointer devices * @param touchscreen if true, allow connection of touchscreen devices */ -void ul_indev_set_allowed_device_capability(bool keyboard, bool pointer, bool touchscreen); +void bb_indev_set_allowed_device_capability(bool keyboard, bool pointer, bool touchscreen); /** * Set the group for receiving input from keyboard devices. * * @param group group that should receive input */ -void ul_indev_set_keyboard_input_group(lv_group_t *group); +void bb_indev_set_keyboard_input_group(lv_group_t *group); + +/** + * Start the udev device monitor and auto-connect currently available devices. + * + * @param keyboard if true, allow connection of keyboard devices + * @param pointer if true, allow connection of pointer devices + * @param touchscreen if true, allow connection of touchscreen devices + */ +void bb_indev_start_monitor_and_autoconnect(bool keyboard, bool pointer, bool touchscreen); /** * Auto-connect currently available keyboard, pointer and touchscreen input devices. */ -void ul_indev_auto_connect(); +void bb_indev_auto_connect(); /** * Start the udev device monitor. */ -void ul_indev_start_monitor(); +void bb_indev_start_monitor(); /** * Stop the udev device monitor. */ -void ul_indev_stop_monitor(); +void bb_indev_stop_monitor(); /** * Query the udev device monitor and (dis)connect added or removed devices */ -void ul_indev_query_monitor(); +void bb_indev_query_monitor(); /** * Check if any keyboard devices are connected. * * @return true if at least one keyboard device is connected, false otherwise */ -bool ul_indev_is_keyboard_connected(); +bool bb_indev_is_keyboard_connected(); -#endif /* UL_INDEV_H */ +#endif /* BB_INDEV_H */ diff --git a/unl0kr/main.c b/unl0kr/main.c index 89a7b32..c586795 100644 --- a/unl0kr/main.c +++ b/unl0kr/main.c @@ -7,12 +7,12 @@ #include "backends.h" #include "command_line.h" #include "config.h" -#include "indev.h" #include "unl0kr.h" #include "terminal.h" #include "theme.h" #include "themes.h" +#include "../shared/indev.h" #include "../shared/log.h" #include "../squeek2lvgl/sq2lv.h" @@ -54,13 +54,6 @@ lv_obj_t *keyboard = NULL; */ static void *tick_thread (void *args); -/** - * Query the device monitor and handle updates. - * - * @param timer the timer object - */ -static void query_device_monitor(lv_timer_t *timer); - /** * Handle LV_EVENT_CLICKED events from the theme toggle button. * @@ -216,11 +209,6 @@ static void *tick_thread (void *args) { return NULL; } -static void query_device_monitor(lv_timer_t *timer) { - LV_UNUSED(timer); - ul_indev_query_monitor(); -} - static void toggle_theme_btn_clicked_cb(lv_event_t *event) { LV_UNUSED(event); toggle_theme(); @@ -442,16 +430,13 @@ int main(int argc, char *argv[]) { /* Prepare for routing physical keyboard input into the textarea */ lv_group_t *keyboard_input_group = lv_group_create(); - ul_indev_set_keyboard_input_group(keyboard_input_group); + bb_indev_set_keyboard_input_group(keyboard_input_group); /* Start input device monitor and auto-connect available devices */ - ul_indev_set_allowed_device_capability(conf_opts.input.keyboard, conf_opts.input.pointer, conf_opts.input.touchscreen); - ul_indev_start_monitor(); - lv_timer_create(query_device_monitor, 1000, NULL); - ul_indev_auto_connect(); + bb_indev_start_monitor_and_autoconnect(conf_opts.input.keyboard, conf_opts.input.pointer, conf_opts.input.touchscreen); /* Hide the on-screen keyboard by default if a physical keyboard is connected */ - if (conf_opts.keyboard.autohide && ul_indev_is_keyboard_connected()) { + if (conf_opts.keyboard.autohide && bb_indev_is_keyboard_connected()) { is_keyboard_hidden = true; } diff --git a/unl0kr/meson.build b/unl0kr/meson.build index 5ec430d..4e0de61 100644 --- a/unl0kr/meson.build +++ b/unl0kr/meson.build @@ -17,7 +17,6 @@ unl0kr_sources = [ 'command_line.c', 'config.c', 'font_32.c', - 'indev.c', 'main.c', 'sq2lv_layouts.c', 'terminal.c', @@ -27,6 +26,7 @@ unl0kr_sources = [ shared_sources = [ '../shared/cursor/cursor.c', + '../shared/indev.c', '../shared/log.c', ]