From 700c3322191aed14a587b48aed97df0eb9d25c96 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Fri, 21 Aug 2026 21:18:20 +0200 Subject: [PATCH] Fix for USB keyboard --- .../lvgl-module/include/lvgl/devices/keyboard.h | 8 ++++++++ Modules/lvgl-module/source/devices/keyboard.cpp | 14 ++++++++++++++ Tactility/Source/lvgl/KeyboardDeviceListener.cpp | 16 ++++++++++------ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/Modules/lvgl-module/include/lvgl/devices/keyboard.h b/Modules/lvgl-module/include/lvgl/devices/keyboard.h index d0c0af61e..66e62dc71 100644 --- a/Modules/lvgl-module/include/lvgl/devices/keyboard.h +++ b/Modules/lvgl-module/include/lvgl/devices/keyboard.h @@ -36,6 +36,14 @@ error_t lvgl_keyboard_add(struct Device* device, lv_display_t* display, lv_indev */ void lvgl_keyboard_remove(lv_indev_t* indev); +/** + * @brief Finds the indev previously created with lvgl_keyboard_add() for the given device, if any. + * @warning Caller must hold the LVGL lock. + * @param[in] device a device of type KEYBOARD_TYPE + * @return the bound indev, or NULL if none is bound to this device + */ +lv_indev_t* lvgl_keyboard_find_by_device(struct Device* device); + /** * @brief Assigns the indev to the shared keyboard input group, so it can drive focus * navigation and input for focused widgets. diff --git a/Modules/lvgl-module/source/devices/keyboard.cpp b/Modules/lvgl-module/source/devices/keyboard.cpp index 02bee3d89..a0b725295 100644 --- a/Modules/lvgl-module/source/devices/keyboard.cpp +++ b/Modules/lvgl-module/source/devices/keyboard.cpp @@ -100,6 +100,20 @@ void lvgl_keyboard_remove(lv_indev_t* indev) { delete wrapper; } +lv_indev_t* lvgl_keyboard_find_by_device(Device* device) { + lv_indev_t* indev = lv_indev_get_next(nullptr); + while (indev != nullptr) { + if (lv_indev_get_type(indev) == LV_INDEV_TYPE_KEYPAD) { + auto* wrapper = static_cast(lv_indev_get_driver_data(indev)); + if (wrapper != nullptr && wrapper->device == device) { + return indev; + } + } + indev = lv_indev_get_next(indev); + } + return nullptr; +} + void lvgl_keyboard_enable(lv_indev_t* indev) { check(keyboard_group != nullptr); lv_indev_set_group(indev, keyboard_group); diff --git a/Tactility/Source/lvgl/KeyboardDeviceListener.cpp b/Tactility/Source/lvgl/KeyboardDeviceListener.cpp index f017a366d..c237f7431 100644 --- a/Tactility/Source/lvgl/KeyboardDeviceListener.cpp +++ b/Tactility/Source/lvgl/KeyboardDeviceListener.cpp @@ -63,21 +63,25 @@ void onKeyboardDeviceStarted(Device* device) { void onKeyboardDeviceStopped(Device* device) { auto lock = bindingsMutex().asScopedLock(); lock.lock(); - lv_indev_t* indev = nullptr; auto& list = bindings(); for (auto it = list.begin(); it != list.end(); ++it) { if (it->device == device) { - indev = it->indev; list.erase(it); break; } } - if (indev == nullptr) { - return; - } + // Not every indev bound to a keyboard device goes through onKeyboardDeviceStarted() and + // bindings() above. lvgl_devices_attach() also binds whatever KEYBOARD_TYPE devices are + // already started at LVGL startup, before this listener is even registered (see + // startKeyboardDeviceListener()'s call site). Look the indev up directly so that path's + // devices still get detached before the kernel device is destructed, instead of leaving a + // dangling indev that reads a freed device on the next LVGL tick. lvgl_lock(); - lvgl_keyboard_remove(indev); + lv_indev_t* indev = lvgl_keyboard_find_by_device(device); + if (indev != nullptr) { + lvgl_keyboard_remove(indev); + } lvgl_unlock(); }