From e750ec19190247d46803dead9a1c4b03dadc6d0f Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 20:14:34 +0100 Subject: [PATCH 01/11] Revert esp_lvgl_port upgrade --- Firmware/idf_component.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/idf_component.yml b/Firmware/idf_component.yml index 6d15beae6..0f1db8ffd 100644 --- a/Firmware/idf_component.yml +++ b/Firmware/idf_component.yml @@ -54,7 +54,7 @@ dependencies: version: "1.7.6~1" rules: - if: "target == esp32s3" - espressif/esp_lvgl_port: "2.7.0" + espressif/esp_lvgl_port: "2.5.0" lvgl/lvgl: "9.3.0" FastEPD: git: https://github.com/bitbank2/FastEPD.git From e017b7415f6096d2a478646779ad4505a31874e1 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 20:14:55 +0100 Subject: [PATCH 02/11] Fix for T-Deck apps not showing up and added new kernel functionality --- Tactility/Source/Tactility.cpp | 33 ++++++++++--------- TactilityKernel/Include/tactility/device.h | 8 +++++ .../Include/tactility/drivers/root.h | 10 ++++++ TactilityKernel/Include/tactility/error.h | 1 + TactilityKernel/Source/device.cpp | 5 +++ TactilityKernel/Source/drivers/root.cpp | 6 ++++ TactilityKernel/Source/kernel_symbols.c | 4 +++ 7 files changed, 51 insertions(+), 16 deletions(-) diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp index 5d83a1a81..942a9dcb6 100644 --- a/Tactility/Source/Tactility.cpp +++ b/Tactility/Source/Tactility.cpp @@ -32,6 +32,7 @@ #include #ifdef ESP_PLATFORM +#include "tactility/drivers/root.h" #include #endif @@ -61,8 +62,6 @@ namespace service { namespace statusbar { extern const ServiceManifest manifest; } #ifdef ESP_PLATFORM namespace displayidle { extern const ServiceManifest manifest; } -#endif -#if defined(ESP_PLATFORM) && defined(CONFIG_TT_DEVICE_LILYGO_TDECK) namespace keyboardidle { extern const ServiceManifest manifest; } #endif #if TT_FEATURE_SCREENSHOT_ENABLED @@ -112,11 +111,8 @@ namespace app { #ifdef ESP_PLATFORM namespace crashdiagnostics { extern const AppManifest manifest; } namespace webserversettings { extern const AppManifest manifest; } -#endif - -#if defined(ESP_PLATFORM) && defined(CONFIG_TT_DEVICE_LILYGO_TDECK) - namespace keyboardsettings { extern const AppManifest manifest; } - namespace trackballsettings { extern const AppManifest manifest; } + namespace keyboardsettings { extern const AppManifest manifest; } // T-Deck only for now + namespace trackballsettings { extern const AppManifest manifest; } // T-Deck only for now #endif #if TT_FEATURE_SCREENSHOT_ENABLED @@ -162,11 +158,13 @@ static void registerInternalApps() { addAppManifest(app::webserversettings::manifest); addAppManifest(app::crashdiagnostics::manifest); addAppManifest(app::development::manifest); -#endif - -#if defined(ESP_PLATFORM) && defined(CONFIG_TT_DEVICE_LILYGO_TDECK) - addAppManifest(app::keyboardsettings::manifest); - addAppManifest(app::trackballsettings::manifest); + // T-Deck only: + auto* root_device = device_find_by_name("/"); + check(root_device); + if (root_is_model(root_device, "LilyGO T-Deck")) { + addAppManifest(app::keyboardsettings::manifest); + addAppManifest(app::trackballsettings::manifest); + } #endif #if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED @@ -251,13 +249,16 @@ static void registerAndStartSecondaryServices() { addService(service::loader::manifest); addService(service::gui::manifest); addService(service::statusbar::manifest); + addService(service::memorychecker::manifest); #ifdef ESP_PLATFORM addService(service::displayidle::manifest); + // T-Deck only: + auto* root_device = device_find_by_name("/"); + check(root_device); + if (root_is_model(root_device, "LilyGO T-Deck")) { + addService(service::keyboardidle::manifest); + } #endif -#if defined(ESP_PLATFORM) && defined(CONFIG_TT_DEVICE_LILYGO_TDECK) - addService(service::keyboardidle::manifest); -#endif - addService(service::memorychecker::manifest); #if TT_FEATURE_SCREENSHOT_ENABLED addService(service::screenshot::manifest); #endif diff --git a/TactilityKernel/Include/tactility/device.h b/TactilityKernel/Include/tactility/device.h index 1be4b4984..af4595e5a 100644 --- a/TactilityKernel/Include/tactility/device.h +++ b/TactilityKernel/Include/tactility/device.h @@ -178,6 +178,14 @@ struct Device* device_get_parent(struct Device* device); */ bool device_is_ready(const struct Device* device); +/** + * Indicates whether the device is compatible with the given compatible string. + * @param[in] device non-null device pointer + * @param[in] compatible compatible string + * @return true if the device is compatible + */ +bool device_is_compatible(const struct Device* device, const char* compatible); + /** * Set the driver data for a device. * diff --git a/TactilityKernel/Include/tactility/drivers/root.h b/TactilityKernel/Include/tactility/drivers/root.h index e2797b937..f6fe8aa15 100644 --- a/TactilityKernel/Include/tactility/drivers/root.h +++ b/TactilityKernel/Include/tactility/drivers/root.h @@ -2,6 +2,8 @@ #pragma once +#include + #ifdef __cplusplus extern "C" { #endif @@ -10,6 +12,14 @@ struct RootConfig { const char* model; }; +/** + * Indicates whether the device's model matches the specified model. + * @param[in] device the device to check (non-null) + * @param[in] model the model to check against + * @return true if the device's model matches the specified model' + */ +bool root_is_model(const struct Device* device, const char* model); + #ifdef __cplusplus } #endif diff --git a/TactilityKernel/Include/tactility/error.h b/TactilityKernel/Include/tactility/error.h index f01ee259b..094a4c92f 100644 --- a/TactilityKernel/Include/tactility/error.h +++ b/TactilityKernel/Include/tactility/error.h @@ -23,6 +23,7 @@ typedef int error_t; #define ERROR_OUT_OF_MEMORY 9 #define ERROR_NOT_SUPPORTED 10 #define ERROR_NOT_ALLOWED 11 +#define ERROR_BUFFER_OVERFLOW 12 /** Convert an error_t to a human-readable text. Useful for logging. */ const char* error_to_string(error_t error); diff --git a/TactilityKernel/Source/device.cpp b/TactilityKernel/Source/device.cpp index 3e19b5b5c..b752faae5 100644 --- a/TactilityKernel/Source/device.cpp +++ b/TactilityKernel/Source/device.cpp @@ -277,6 +277,11 @@ bool device_is_ready(const struct Device* device) { return device->internal->state.started; } +bool device_is_compatible(const struct Device* device, const char* compatible) { + if (device->internal->driver == nullptr) return false; + return driver_is_compatible(device->internal->driver, compatible); +} + void device_set_driver_data(struct Device* device, void* driver_data) { device->internal->driver_data = driver_data; } diff --git a/TactilityKernel/Source/drivers/root.cpp b/TactilityKernel/Source/drivers/root.cpp index 0288e4c19..f1c04ccd5 100644 --- a/TactilityKernel/Source/drivers/root.cpp +++ b/TactilityKernel/Source/drivers/root.cpp @@ -1,10 +1,16 @@ // SPDX-License-Identifier: Apache-2.0 +#include #include #include extern "C" { +bool root_is_model(const struct Device* device, const char* buffer) { + auto* config = static_cast(device->config); + return strcmp(config->model, buffer) == 0; +} + Driver root_driver = { .name = "root", .compatible = (const char*[]) { "root", nullptr }, diff --git a/TactilityKernel/Source/kernel_symbols.c b/TactilityKernel/Source/kernel_symbols.c index e9686ea25..205383c57 100644 --- a/TactilityKernel/Source/kernel_symbols.c +++ b/TactilityKernel/Source/kernel_symbols.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = { DEFINE_MODULE_SYMBOL(device_get_driver_data), DEFINE_MODULE_SYMBOL(device_is_added), DEFINE_MODULE_SYMBOL(device_is_ready), + DEFINE_MODULE_SYMBOL(device_is_compatible), DEFINE_MODULE_SYMBOL(device_lock), DEFINE_MODULE_SYMBOL(device_try_lock), DEFINE_MODULE_SYMBOL(device_unlock), @@ -79,6 +81,8 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = { DEFINE_MODULE_SYMBOL(i2s_controller_get_config), DEFINE_MODULE_SYMBOL(i2s_controller_reset), DEFINE_MODULE_SYMBOL(I2S_CONTROLLER_TYPE), + // drivers/root + DEFINE_MODULE_SYMBOL(root_is_model), // drivers/spi_controller DEFINE_MODULE_SYMBOL(spi_controller_lock), DEFINE_MODULE_SYMBOL(spi_controller_try_lock), From 2edeb4f8053b9b1ac4e19320f66fad57005a2d90 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 20:15:31 +0100 Subject: [PATCH 03/11] Cleanup copy-pasted messages that were likely copied in error --- Devices/elecrow-crowpanel-advance-28/Source/devices/Display.cpp | 1 - Devices/elecrow-crowpanel-advance-35/Source/devices/Display.cpp | 1 - Devices/lilygo-tdeck/Source/devices/Display.cpp | 1 - Devices/m5stack-cores3/Source/devices/Display.cpp | 1 - Devices/waveshare-s3-touch-lcd-147/Source/devices/Display.cpp | 1 - 5 files changed, 5 deletions(-) diff --git a/Devices/elecrow-crowpanel-advance-28/Source/devices/Display.cpp b/Devices/elecrow-crowpanel-advance-28/Source/devices/Display.cpp index 1b79ebb04..3d1d12b29 100644 --- a/Devices/elecrow-crowpanel-advance-28/Source/devices/Display.cpp +++ b/Devices/elecrow-crowpanel-advance-28/Source/devices/Display.cpp @@ -5,7 +5,6 @@ #include static std::shared_ptr createTouch() { - // Note for future changes: Reset pin is 48 and interrupt pin is 47 auto configuration = std::make_unique( I2C_NUM_0, LCD_HORIZONTAL_RESOLUTION, diff --git a/Devices/elecrow-crowpanel-advance-35/Source/devices/Display.cpp b/Devices/elecrow-crowpanel-advance-35/Source/devices/Display.cpp index 6b5919f6b..3771b46ca 100644 --- a/Devices/elecrow-crowpanel-advance-35/Source/devices/Display.cpp +++ b/Devices/elecrow-crowpanel-advance-35/Source/devices/Display.cpp @@ -5,7 +5,6 @@ #include static std::shared_ptr createTouch() { - // Note for future changes: Reset pin is 48 and interrupt pin is 47 auto configuration = std::make_unique( I2C_NUM_0, 320, diff --git a/Devices/lilygo-tdeck/Source/devices/Display.cpp b/Devices/lilygo-tdeck/Source/devices/Display.cpp index 275654b05..82de3d710 100644 --- a/Devices/lilygo-tdeck/Source/devices/Display.cpp +++ b/Devices/lilygo-tdeck/Source/devices/Display.cpp @@ -5,7 +5,6 @@ #include static std::shared_ptr createTouch() { - // Note for future changes: Reset pin is 48 and interrupt pin is 47 auto configuration = std::make_unique( I2C_NUM_0, 240, diff --git a/Devices/m5stack-cores3/Source/devices/Display.cpp b/Devices/m5stack-cores3/Source/devices/Display.cpp index b7e716779..0409a1c17 100644 --- a/Devices/m5stack-cores3/Source/devices/Display.cpp +++ b/Devices/m5stack-cores3/Source/devices/Display.cpp @@ -17,7 +17,6 @@ static void setBacklightDuty(uint8_t backlightDuty) { } static std::shared_ptr createTouch() { - // Note for future changes: Reset pin is 48 and interrupt pin is 47 auto configuration = std::make_unique( I2C_NUM_0, LCD_HORIZONTAL_RESOLUTION, diff --git a/Devices/waveshare-s3-touch-lcd-147/Source/devices/Display.cpp b/Devices/waveshare-s3-touch-lcd-147/Source/devices/Display.cpp index f23e7fdde..5834a74be 100644 --- a/Devices/waveshare-s3-touch-lcd-147/Source/devices/Display.cpp +++ b/Devices/waveshare-s3-touch-lcd-147/Source/devices/Display.cpp @@ -12,7 +12,6 @@ constexpr auto LCD_VERTICAL_RESOLUTION = 320; void setBacklightDuty(uint8_t level); static std::shared_ptr createTouch() { - // Note for future changes: Reset pin is 48 and interrupt pin is 47 auto configuration = std::make_unique( I2C_NUM_0, 172, From a0d097b53c48fbbf4586d6c53ce954f01ecc87cd Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 20:15:42 +0100 Subject: [PATCH 04/11] Use interrupt-driven touch on T-Deck --- Devices/lilygo-tdeck/Source/devices/Display.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Devices/lilygo-tdeck/Source/devices/Display.cpp b/Devices/lilygo-tdeck/Source/devices/Display.cpp index 82de3d710..bb17a6d31 100644 --- a/Devices/lilygo-tdeck/Source/devices/Display.cpp +++ b/Devices/lilygo-tdeck/Source/devices/Display.cpp @@ -11,7 +11,9 @@ static std::shared_ptr createTouch() { 320, true, true, - false + false, + GPIO_NUM_NC, + GPIO_NUM_16 ); return std::make_shared(std::move(configuration)); From a7ee91725c4ad1da1d045cbae2cb5bd38daa3b84 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 20:17:01 +0100 Subject: [PATCH 05/11] Update checkout github action from v2 to v4 --- .github/actions/build-simulator/action.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/build-simulator/action.yml b/.github/actions/build-simulator/action.yml index b257b2c7e..8f759699f 100644 --- a/.github/actions/build-simulator/action.yml +++ b/.github/actions/build-simulator/action.yml @@ -15,7 +15,7 @@ runs: using: "composite" steps: - name: "Checkout repo" - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive - name: Install Linux Dependencies for SDL diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e129a72e1..96631892a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: "Checkout repo" - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive - name: "Configure Project" @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest steps: - name: "Checkout repo" - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive - name: "Install Python Dependencies" From 420fdfdd8842e805bbaa7f4ff320be71ebe9dfa7 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 20:27:06 +0100 Subject: [PATCH 06/11] Fix for PC target --- TactilityKernel/Source/drivers/root.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TactilityKernel/Source/drivers/root.cpp b/TactilityKernel/Source/drivers/root.cpp index f1c04ccd5..c6dc53498 100644 --- a/TactilityKernel/Source/drivers/root.cpp +++ b/TactilityKernel/Source/drivers/root.cpp @@ -3,6 +3,7 @@ #include #include #include +#include extern "C" { @@ -18,7 +19,8 @@ Driver root_driver = { .stop_device = nullptr, .api = nullptr, .device_type = nullptr, - .owner = nullptr + .owner = nullptr, + .internal = nullptr }; } From d3c6e52ce39051960d881c966abae4df872e7524 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 20:27:38 +0100 Subject: [PATCH 07/11] Fix for build --- TactilityKernel/Include/tactility/drivers/root.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TactilityKernel/Include/tactility/drivers/root.h b/TactilityKernel/Include/tactility/drivers/root.h index f6fe8aa15..62a2ae194 100644 --- a/TactilityKernel/Include/tactility/drivers/root.h +++ b/TactilityKernel/Include/tactility/drivers/root.h @@ -2,7 +2,7 @@ #pragma once -#include +#include #ifdef __cplusplus extern "C" { From 801eacee16bb46bf1315a05843a14558ff5102c9 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 20:29:30 +0100 Subject: [PATCH 08/11] Fixes --- TactilityKernel/Include/tactility/drivers/root.h | 2 +- TactilityKernel/Source/error.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/TactilityKernel/Include/tactility/drivers/root.h b/TactilityKernel/Include/tactility/drivers/root.h index 62a2ae194..7682262f2 100644 --- a/TactilityKernel/Include/tactility/drivers/root.h +++ b/TactilityKernel/Include/tactility/drivers/root.h @@ -16,7 +16,7 @@ struct RootConfig { * Indicates whether the device's model matches the specified model. * @param[in] device the device to check (non-null) * @param[in] model the model to check against - * @return true if the device's model matches the specified model' + * @return true if the device's model matches the specified model */ bool root_is_model(const struct Device* device, const char* model); diff --git a/TactilityKernel/Source/error.cpp b/TactilityKernel/Source/error.cpp index 7a6e144ec..408832508 100644 --- a/TactilityKernel/Source/error.cpp +++ b/TactilityKernel/Source/error.cpp @@ -29,6 +29,8 @@ const char* error_to_string(error_t error) { return "not supported"; case ERROR_NOT_ALLOWED: return "not allowed"; + case ERROR_BUFFER_OVERFLOW: + return "buffer overlow"; default: return "unknown"; } From a34e059c74c2d36e99ff5fa430a31701b14bf5f9 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 21:01:53 +0100 Subject: [PATCH 09/11] Typo fix --- TactilityKernel/Source/error.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TactilityKernel/Source/error.cpp b/TactilityKernel/Source/error.cpp index 408832508..e5e149da1 100644 --- a/TactilityKernel/Source/error.cpp +++ b/TactilityKernel/Source/error.cpp @@ -30,7 +30,7 @@ const char* error_to_string(error_t error) { case ERROR_NOT_ALLOWED: return "not allowed"; case ERROR_BUFFER_OVERFLOW: - return "buffer overlow"; + return "buffer overflow"; default: return "unknown"; } From adb23a0e665431c81eaa953031e3d612cea3e44c Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 21:40:03 +0100 Subject: [PATCH 10/11] Fix for build --- Firmware/Kconfig | 8 +++++++- Tactility/Source/Tactility.cpp | 20 ++++++++------------ device.py | 3 +++ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Firmware/Kconfig b/Firmware/Kconfig index 393e75e28..548887e86 100644 --- a/Firmware/Kconfig +++ b/Firmware/Kconfig @@ -6,7 +6,13 @@ menu "Tactility App" config TT_DEVICE_ID string "Device Identifier" default "" - config TT_SPLASH_DURATION + # T-Deck device-related code was directly referenced from Tactility in a pull request. + # This breaks other devices because the code does not exist in those implementations. + # Until we move it out into a proper driver, we have to have pre-processor definition for that. + config TT_TDECK_WORKAROUND + bool "Temporary work-around until we fix the T-Deck keyboard and trackball settings" + default n + config TT_SPLASH_DURATION int "Splash Duration (ms)" default 1000 range 0 3000 diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp index 942a9dcb6..976064c6f 100644 --- a/Tactility/Source/Tactility.cpp +++ b/Tactility/Source/Tactility.cpp @@ -111,9 +111,11 @@ namespace app { #ifdef ESP_PLATFORM namespace crashdiagnostics { extern const AppManifest manifest; } namespace webserversettings { extern const AppManifest manifest; } +#if CONFIG_TT_TDECK_WORKAROUND == 1 namespace keyboardsettings { extern const AppManifest manifest; } // T-Deck only for now namespace trackballsettings { extern const AppManifest manifest; } // T-Deck only for now #endif +#endif #if TT_FEATURE_SCREENSHOT_ENABLED namespace screenshot { extern const AppManifest manifest; } @@ -158,13 +160,10 @@ static void registerInternalApps() { addAppManifest(app::webserversettings::manifest); addAppManifest(app::crashdiagnostics::manifest); addAppManifest(app::development::manifest); - // T-Deck only: - auto* root_device = device_find_by_name("/"); - check(root_device); - if (root_is_model(root_device, "LilyGO T-Deck")) { +#if defined(CONFIG_TT_TDECK_WORKAROUND) addAppManifest(app::keyboardsettings::manifest); addAppManifest(app::trackballsettings::manifest); - } +#endif #endif #if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED @@ -250,14 +249,11 @@ static void registerAndStartSecondaryServices() { addService(service::gui::manifest); addService(service::statusbar::manifest); addService(service::memorychecker::manifest); -#ifdef ESP_PLATFORM +#if defined(ESP_PLATFORM) addService(service::displayidle::manifest); - // T-Deck only: - auto* root_device = device_find_by_name("/"); - check(root_device); - if (root_is_model(root_device, "LilyGO T-Deck")) { - addService(service::keyboardidle::manifest); - } +#if defined(CONFIG_TT_TDECK_WORKAROUND) + addService(service::keyboardidle::manifest); +#endif #endif #if TT_FEATURE_SCREENSHOT_ENABLED addService(service::screenshot::manifest); diff --git a/device.py b/device.py index 3048fcc0f..a68cbfede 100644 --- a/device.py +++ b/device.py @@ -105,6 +105,9 @@ def write_tactility_variables(output_file, device_properties: ConfigParser, devi else: output_file.write(f"CONFIG_TT_DEVICE_NAME=\"{board_vendor} {board_name}\"\n") output_file.write(f"CONFIG_TT_DEVICE_ID=\"{device_id}\"\n") + if device_id == "lilygo-tdeck": + output_file.write("CONFIG_TT_TDECK_WORKAROUND=y\n") + def write_core_variables(output_file, device_properties: ConfigParser): idf_target = get_property_or_exit(device_properties, "hardware", "target").lower() From 5605c3ce0a7994f52c0771c7867892e41e94a298 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Mon, 9 Feb 2026 23:05:08 +0100 Subject: [PATCH 11/11] GPIO ownership WIP --- .../Source/drivers/esp32_gpio.cpp | 37 +++--- Tactility/Source/Tactility.cpp | 1 - TactilityC/Include/tt_hal_gpio.h | 16 +-- TactilityC/Source/tt_hal_gpio.cpp | 25 +--- .../Include/tactility/drivers/gpio.h | 13 ++ .../tactility/drivers/gpio_controller.h | 111 ++++++++++------- .../tactility/drivers/gpio_descriptor.h | 20 +++ .../Source/drivers/gpio_controller.cpp | 115 +++++++++++++++--- TactilityKernel/Source/kernel_symbols.c | 10 +- 9 files changed, 233 insertions(+), 115 deletions(-) create mode 100644 TactilityKernel/Include/tactility/drivers/gpio_descriptor.h diff --git a/Platforms/PlatformEsp32/Source/drivers/esp32_gpio.cpp b/Platforms/PlatformEsp32/Source/drivers/esp32_gpio.cpp index 816800182..274d1d995 100644 --- a/Platforms/PlatformEsp32/Source/drivers/esp32_gpio.cpp +++ b/Platforms/PlatformEsp32/Source/drivers/esp32_gpio.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #define TAG "esp32_gpio" @@ -15,20 +16,20 @@ extern "C" { -static error_t set_level(Device* device, gpio_pin_t pin, bool high) { - auto esp_error = gpio_set_level(static_cast(pin), high); +static error_t set_level(GpioDescriptor* descriptor, bool high) { + auto esp_error = gpio_set_level(static_cast(descriptor->pin), high); return esp_err_to_error(esp_error); } -static error_t get_level(Device* device, gpio_pin_t pin, bool* high) { - *high = gpio_get_level(static_cast(pin)) != 0; +static error_t get_level(GpioDescriptor* descriptor, bool* high) { + *high = gpio_get_level(static_cast(descriptor->pin)) != 0; return ERROR_NONE; } -static error_t set_options(Device* device, gpio_pin_t pin, gpio_flags_t options) { - const Esp32GpioConfig* config = GET_CONFIG(device); +static error_t set_options(GpioDescriptor* descriptor, gpio_flags_t options) { + const Esp32GpioConfig* config = GET_CONFIG(descriptor->controller); - if (pin >= config->gpioCount) { + if (descriptor->pin >= config->gpioCount) { return ERROR_INVALID_ARGUMENT; } @@ -44,7 +45,7 @@ static error_t set_options(Device* device, gpio_pin_t pin, gpio_flags_t options) } const gpio_config_t esp_config = { - .pin_bit_mask = 1ULL << pin, + .pin_bit_mask = 1ULL << descriptor->pin, .mode = mode, .pull_up_en = (options & GPIO_PULL_UP) ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE, .pull_down_en = (options & GPIO_PULL_DOWN) ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE, @@ -58,9 +59,9 @@ static error_t set_options(Device* device, gpio_pin_t pin, gpio_flags_t options) return esp_err_to_error(esp_error); } -static int get_options(Device* device, gpio_pin_t pin, gpio_flags_t* options) { +static error_t get_options(GpioDescriptor* descriptor, gpio_flags_t* options) { gpio_io_config_t esp_config; - if (gpio_get_io_config(static_cast(pin), &esp_config) != ESP_OK) { + if (gpio_get_io_config(static_cast(descriptor->pin), &esp_config) != ESP_OK) { return ERROR_RESOURCE; } @@ -90,27 +91,31 @@ static int get_options(Device* device, gpio_pin_t pin, gpio_flags_t* options) { return ERROR_NONE; } -error_t get_pin_count(struct Device* device, uint32_t* count) { - *count = GET_CONFIG(device)->gpioCount; +static error_t get_pin_number(struct GpioDescriptor* descriptor, gpio_pin_t* pin) { + if (!descriptor) return ERROR_INVALID_ARGUMENT; + *pin = descriptor->pin; return ERROR_NONE; } static error_t start(Device* device) { ESP_LOGI(TAG, "start %s", device->name); - return ERROR_NONE; + auto pin_count = GET_CONFIG(device)->gpioCount; + return gpio_controller_init_descriptors(device, pin_count, nullptr); } static error_t stop(Device* device) { ESP_LOGI(TAG, "stop %s", device->name); - return ERROR_NONE; + return gpio_controller_deinit_descriptors(device); } const static GpioControllerApi esp32_gpio_api = { + .acquire_descriptor = acquire_descriptor, + .release_descriptor = release_descriptor, + .get_pin_number = get_pin_number, .set_level = set_level, .get_level = get_level, .set_options = set_options, - .get_options = get_options, - .get_pin_count = get_pin_count + .get_options = get_options }; extern struct Module platform_module; diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp index 976064c6f..ecfc83326 100644 --- a/Tactility/Source/Tactility.cpp +++ b/Tactility/Source/Tactility.cpp @@ -32,7 +32,6 @@ #include #ifdef ESP_PLATFORM -#include "tactility/drivers/root.h" #include #endif diff --git a/TactilityC/Include/tt_hal_gpio.h b/TactilityC/Include/tt_hal_gpio.h index 8776d3760..b80bd3ebb 100644 --- a/TactilityC/Include/tt_hal_gpio.h +++ b/TactilityC/Include/tt_hal_gpio.h @@ -7,22 +7,16 @@ extern "C" { #endif -/** Logical GPIO pin identifier used by the HAL. Typically maps to the SoC GPIO number. */ +/** @deprecated NON-FUNCTIONAL - WILL BE REMOVED SOON */ typedef unsigned int GpioPin; -/** Value indicating that no GPIO pin is used/applicable. */ + +/** @deprecated NON-FUNCTIONAL - WILL BE REMOVED SOON */ #define GPIO_NO_PIN -1 -/** Read the current logic level of a pin. - * The pin should be configured for input or input/output. - * @param[in] pin The pin to read. - * @return true if the level is high, false if low. If the pin is invalid, the - * behavior is implementation-defined and may return false. - */ +/** @deprecated NON-FUNCTIONAL - WILL BE REMOVED SOON */ bool tt_hal_gpio_get_level(GpioPin pin); -/** Get the number of GPIO pins available on this platform. - * @return The count of valid GPIO pins. - */ +/** @deprecated NON-FUNCTIONAL - WILL BE REMOVED SOON */ int tt_hal_gpio_get_pin_count(); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_hal_gpio.cpp b/TactilityC/Source/tt_hal_gpio.cpp index 5c533cc3c..114055a2b 100644 --- a/TactilityC/Source/tt_hal_gpio.cpp +++ b/TactilityC/Source/tt_hal_gpio.cpp @@ -7,33 +7,12 @@ extern "C" { using namespace tt::hal; -static Device* find_first_gpio_controller() { - Device* device_result = nullptr; - device_for_each_of_type(&GPIO_CONTROLLER_TYPE, &device_result, [](Device* device, void* context) { - if (device_is_ready(device)) { - auto** device_result_ptr = static_cast(context); - *device_result_ptr = device; - return false; - } - return true; - }); - return device_result; -} - bool tt_hal_gpio_get_level(GpioPin pin) { - Device* device_result = find_first_gpio_controller(); - if (device_result == nullptr) return false; - bool pin_state = false; - if (gpio_controller_get_level(device_result, pin, &pin_state) != ERROR_NONE) return false; - return pin_state; + return false; } int tt_hal_gpio_get_pin_count() { - Device* device_result = find_first_gpio_controller(); - if (device_result == nullptr) return 0; - uint32_t pin_count = 0; - if (gpio_controller_get_pin_count(device_result, &pin_count) != ERROR_NONE) return 0; - return (int)pin_count; + return 0; } } diff --git a/TactilityKernel/Include/tactility/drivers/gpio.h b/TactilityKernel/Include/tactility/drivers/gpio.h index b42301f11..8ac772f6a 100644 --- a/TactilityKernel/Include/tactility/drivers/gpio.h +++ b/TactilityKernel/Include/tactility/drivers/gpio.h @@ -38,12 +38,25 @@ typedef enum { GPIO__MAX, } GpioInterruptType; +enum GpioOwnerType { + /** @brief Pin is unclaimed/free */ + GPIO_OWNER_NONE, + /** @brief Pin is owned by a hog */ + GPIO_OWNER_HOG, + /** @brief Pin is claimed by a regular consumer */ + GPIO_OWNER_GPIO, + /** @brief Pin is owned by SPI. This is a special case because of CS pin transfer from hog to SPI controller. */ + GPIO_OWNER_SPI +}; + /** The index of a GPIO pin on a GPIO Controller */ typedef uint8_t gpio_pin_t; /** Specifies the configuration flags for a GPIO pin (or set of pins) */ typedef uint16_t gpio_flags_t; +typedef uint8_t gpio_level_t; + /** A configuration for a single GPIO pin */ struct GpioPinConfig { /** GPIO device controlling the pin */ diff --git a/TactilityKernel/Include/tactility/drivers/gpio_controller.h b/TactilityKernel/Include/tactility/drivers/gpio_controller.h index cd15fe30e..674eb323a 100644 --- a/TactilityKernel/Include/tactility/drivers/gpio_controller.h +++ b/TactilityKernel/Include/tactility/drivers/gpio_controller.h @@ -12,104 +12,127 @@ extern "C" { struct Device; struct GpioControllerApi { + struct GpioDescriptor* (*acquire_descriptor)( + struct Device* controller, + gpio_pin_t pin_number, + enum GpioOwnerType owner, + void* owner_context + ); + + error_t (*release_descriptor)(struct GpioDescriptor* descriptor); + + /** + * @brief Gets the pin number associated with a descriptor. + * @param[in] descriptor the pin descriptor + * @param[out] pin pointer to store the pin number + * @return ERROR_NONE if successful + */ + error_t (*get_pin_number)(struct GpioDescriptor* descriptor, gpio_pin_t* pin); + /** * @brief Sets the logical level of a GPIO pin. - * @param[in] device the GPIO controller device - * @param[in] pin the pin index + * @param[in,out] descriptor the pin descriptor * @param[in] high true to set the pin high, false to set it low * @return ERROR_NONE if successful */ - error_t (*set_level)(struct Device* device, gpio_pin_t pin, bool high); + error_t (*set_level)(struct GpioDescriptor* descriptor, bool high); /** * @brief Gets the logical level of a GPIO pin. - * @param[in] device the GPIO controller device - * @param[in] pin the pin index + * @param[in] descriptor the pin descriptor * @param[out] high pointer to store the pin level * @return ERROR_NONE if successful */ - error_t (*get_level)(struct Device* device, gpio_pin_t pin, bool* high); + error_t (*get_level)(struct GpioDescriptor* descriptor, bool* high); /** * @brief Configures the options for a GPIO pin. - * @param[in] device the GPIO controller device - * @param[in] pin the pin index + * @param[in,out] descriptor the pin descriptor * @param[in] options configuration flags (direction, pull-up/down, etc.) * @return ERROR_NONE if successful */ - error_t (*set_options)(struct Device* device, gpio_pin_t pin, gpio_flags_t options); + error_t (*set_options)(struct GpioDescriptor* descriptor, gpio_flags_t options); /** * @brief Gets the configuration options for a GPIO pin. - * @param[in] device the GPIO controller device - * @param[in] pin the pin index + * @param[in] descriptor the pin descriptor * @param[out] options pointer to store the configuration flags * @return ERROR_NONE if successful */ - error_t (*get_options)(struct Device* device, gpio_pin_t pin, gpio_flags_t* options); - - /** - * @brief Gets the number of pins supported by the controller. - * @param[in] device the GPIO controller device - * @param[out] count pointer to store the number of pins - * @return ERROR_NONE if successful - */ - error_t (*get_pin_count)(struct Device* device, uint32_t* count); + error_t (*get_options)(struct GpioDescriptor* descriptor, gpio_flags_t* options); }; +struct GpioDescriptor* acquire_descriptor( + struct Device* controller, + gpio_pin_t pin_number, + enum GpioOwnerType owner, + void* owner_context +); + +error_t release_descriptor(struct GpioDescriptor* descriptor); + /** - * @brief Sets the logical level of a GPIO pin. + * @brief Gets the number of pins supported by the controller. * @param[in] device the GPIO controller device - * @param[in] pin the pin index + * @param[out] count pointer to store the number of pins + * @return ERROR_NONE if successful + */ +error_t gpio_controller_get_pin_count(struct Device* device, uint32_t* count); + +/** + * @brief Gets the pin number associated with a descriptor. + * @param[in] descriptor the pin descriptor + * @param[out] pin pointer to store the pin number + * @return ERROR_NONE if successful + */ +error_t gpio_descriptor_pin_number(struct GpioDescriptor* descriptor, gpio_pin_t* pin); + +/** + * @brief Sets the logical level of a GPIO pin. + * @param[in] descriptor the pin descriptor * @param[in] high true to set the pin high, false to set it low * @return ERROR_NONE if successful */ -error_t gpio_controller_set_level(struct Device* device, gpio_pin_t pin, bool high); +error_t gpio_descriptor_set_level(struct GpioDescriptor* descriptor, bool high); /** * @brief Gets the logical level of a GPIO pin. - * @param[in] device the GPIO controller device - * @param[in] pin the pin index + * @param[in] descriptor the pin descriptor * @param[out] high pointer to store the pin level * @return ERROR_NONE if successful */ -error_t gpio_controller_get_level(struct Device* device, gpio_pin_t pin, bool* high); +error_t gpio_descriptor_get_level(struct GpioDescriptor* descriptor, bool* high); /** * @brief Configures the options for a GPIO pin. - * @param[in] device the GPIO controller device - * @param[in] pin the pin index + * @param[in] descriptor the pin descriptor * @param[in] options configuration flags (direction, pull-up/down, etc.) * @return ERROR_NONE if successful */ -error_t gpio_controller_set_options(struct Device* device, gpio_pin_t pin, gpio_flags_t options); +error_t gpio_descriptor_set_options(struct GpioDescriptor* descriptor, gpio_flags_t options); /** * @brief Gets the configuration options for a GPIO pin. - * @param[in] device the GPIO controller device - * @param[in] pin the pin index + * @param[in] descriptor the pin descriptor * @param[out] options pointer to store the configuration flags * @return ERROR_NONE if successful */ -error_t gpio_controller_get_options(struct Device* device, gpio_pin_t pin, gpio_flags_t* options); +error_t gpio_descriptor_get_options(struct GpioDescriptor* descriptor, gpio_flags_t* options); /** - * @brief Gets the number of pins supported by the controller. - * @param[in] device the GPIO controller device - * @param[out] count pointer to store the number of pins - * @return ERROR_NONE if successful - */ -error_t gpio_controller_get_pin_count(struct Device* device, uint32_t* count); + * @brief Initializes GPIO descriptors for a controller. + * @param[in,out] device the GPIO controller device + * @param[in] owner_data pointer to store in the descriptor's owner_data field + * @return ERROR_NONE if successful + */ +error_t gpio_controller_init_descriptors(struct Device* device, uint32_t pin_count, void* owner_data); /** - * @brief Configures the options for a GPIO pin using a pin configuration structure. - * @param[in] device the GPIO controller device - * @param[in] config the pin configuration structure + * @brief Deinitializes GPIO descriptors for a controller. + * @param[in,out] device the GPIO controller device * @return ERROR_NONE if successful */ -static inline error_t gpio_set_options_config(struct Device* device, const struct GpioPinConfig* config) { - return gpio_controller_set_options(device, config->pin, config->flags); -} +error_t gpio_controller_deinit_descriptors(struct Device* device); extern const struct DeviceType GPIO_CONTROLLER_TYPE; diff --git a/TactilityKernel/Include/tactility/drivers/gpio_descriptor.h b/TactilityKernel/Include/tactility/drivers/gpio_descriptor.h new file mode 100644 index 000000000..2f972c976 --- /dev/null +++ b/TactilityKernel/Include/tactility/drivers/gpio_descriptor.h @@ -0,0 +1,20 @@ +#pragma once + +#include "gpio.h" + +struct GpioDescriptor { + /** @brief The controller that owns this pin */ + struct Device* controller; + /** @brief Physical pin number */ + gpio_pin_t pin; + /** @brief Current owner */ + enum GpioOwnerType owner_type; + /** @brief Owner identity for validation */ + void* owner_context; + /** @brief Pin level */ + gpio_level_t level; + /** @brief Pin configuration flags */ + gpio_flags_t flags; + /** @brief Implementation-specific context (e.g. from esp32 controller internally) */ + void* controller_context; +}; diff --git a/TactilityKernel/Source/drivers/gpio_controller.cpp b/TactilityKernel/Source/drivers/gpio_controller.cpp index 376409bdb..9ddba628d 100644 --- a/TactilityKernel/Source/drivers/gpio_controller.cpp +++ b/TactilityKernel/Source/drivers/gpio_controller.cpp @@ -3,33 +3,116 @@ #include #include -#define GPIO_DRIVER_API(driver) ((struct GpioControllerApi*)driver->api) +#include +#include + +#define GPIO_INTERNAL_API(driver) ((struct GpioControllerApi*)driver->api) extern "C" { -error_t gpio_controller_set_level(Device* device, gpio_pin_t pin, bool high) { - const auto* driver = device_get_driver(device); - return GPIO_DRIVER_API(driver)->set_level(device, pin, high); +struct GpioControllerData { + struct Mutex mutex; + uint32_t pin_count; + struct GpioDescriptor* descriptors; +}; + +struct GpioDescriptor* acquire_descriptor( + struct Device* controller, + gpio_pin_t pin_number, + enum GpioOwnerType owner, + void* owner_context +) { + auto* data = (struct GpioControllerData*)device_get_driver_data(controller); + + mutex_lock(&data->mutex); + if (pin_number >= data->pin_count) { + mutex_unlock(&data->mutex); + return nullptr; + } + + struct GpioDescriptor* desc = &data->descriptors[pin_number]; + if (desc->owner_type != GPIO_OWNER_NONE) { + mutex_unlock(&data->mutex); + return nullptr; + } + + desc->owner_type = owner; + desc->owner_context = owner_context; + mutex_unlock(&data->mutex); + + return desc; } -error_t gpio_controller_get_level(Device* device, gpio_pin_t pin, bool* high) { - const auto* driver = device_get_driver(device); - return GPIO_DRIVER_API(driver)->get_level(device, pin, high); +error_t release_descriptor(struct GpioDescriptor* descriptor) { + descriptor->owner_type = GPIO_OWNER_NONE; + descriptor->owner_context = nullptr; + return ERROR_NONE; } -error_t gpio_controller_set_options(Device* device, gpio_pin_t pin, gpio_flags_t options) { - const auto* driver = device_get_driver(device); - return GPIO_DRIVER_API(driver)->set_options(device, pin, options); +error_t gpio_controller_get_pin_count(struct Device* device, uint32_t* count) { + auto* data = (struct GpioControllerData*)device_get_driver_data(device); + *count = data->pin_count; + return ERROR_NONE; } -error_t gpio_controller_get_options(Device* device, gpio_pin_t pin, gpio_flags_t* options) { - const auto* driver = device_get_driver(device); - return GPIO_DRIVER_API(driver)->get_options(device, pin, options); +error_t gpio_controller_init_descriptors(struct Device* device, uint32_t pin_count, void* controller_context) { + auto* data = (struct GpioControllerData*)malloc(sizeof(struct GpioControllerData)); + if (!data) return ERROR_OUT_OF_MEMORY; + + data->pin_count = pin_count; + data->descriptors = (struct GpioDescriptor*)calloc(pin_count, sizeof(struct GpioDescriptor)); + if (!data->descriptors) { + free(data); + return ERROR_OUT_OF_MEMORY; + } + + for (uint32_t i = 0; i < pin_count; ++i) { + data->descriptors[i].controller = device; + data->descriptors[i].pin = (gpio_pin_t)i; + data->descriptors[i].owner_type = GPIO_OWNER_NONE; + data->descriptors[i].controller_context = controller_context; + } + + mutex_construct(&data->mutex); + device_set_driver_data(device, data); + + return ERROR_NONE; } -error_t gpio_controller_get_pin_count(struct Device* device, uint32_t* count) { - const auto* driver = device_get_driver(device); - return GPIO_DRIVER_API(driver)->get_pin_count(device, count); +error_t gpio_controller_deinit_descriptors(struct Device* device) { + auto* data = (struct GpioControllerData*)device_get_driver_data(device); + + free(data->descriptors); + mutex_destruct(&data->mutex); + free(data); + device_set_driver_data(device, nullptr); + + return ERROR_NONE; +} + +error_t gpio_descriptor_set_level(struct GpioDescriptor* descriptor, bool high) { + const auto* driver = device_get_driver(descriptor->controller); + return GPIO_INTERNAL_API(driver)->set_level(descriptor, high); +} + +error_t gpio_descriptor_get_level(struct GpioDescriptor* descriptor, bool* high) { + const auto* driver = device_get_driver(descriptor->controller); + return GPIO_INTERNAL_API(driver)->get_level(descriptor, high); +} + +error_t gpio_descriptor_set_options(struct GpioDescriptor* descriptor, gpio_flags_t options) { + const auto* driver = device_get_driver(descriptor->controller); + return GPIO_INTERNAL_API(driver)->set_options(descriptor, options); +} + +error_t gpio_descriptor_get_options(struct GpioDescriptor* descriptor, gpio_flags_t* options) { + const auto* driver = device_get_driver(descriptor->controller); + return GPIO_INTERNAL_API(driver)->get_options(descriptor, options); +} + +error_t gpio_descriptor_get_pin_number(struct GpioDescriptor* descriptor, gpio_pin_t* pin) { + const auto* driver = device_get_driver(descriptor->controller); + return GPIO_INTERNAL_API(driver)->get_pin_number(descriptor, pin); } const struct DeviceType GPIO_CONTROLLER_TYPE { diff --git a/TactilityKernel/Source/kernel_symbols.c b/TactilityKernel/Source/kernel_symbols.c index 205383c57..8d1a1aec4 100644 --- a/TactilityKernel/Source/kernel_symbols.c +++ b/TactilityKernel/Source/kernel_symbols.c @@ -59,11 +59,13 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = { DEFINE_MODULE_SYMBOL(driver_find_compatible), DEFINE_MODULE_SYMBOL(driver_get_device_type), // drivers/gpio_controller - DEFINE_MODULE_SYMBOL(gpio_controller_set_level), - DEFINE_MODULE_SYMBOL(gpio_controller_get_level), - DEFINE_MODULE_SYMBOL(gpio_controller_set_options), - DEFINE_MODULE_SYMBOL(gpio_controller_get_options), + DEFINE_MODULE_SYMBOL(gpio_descriptor_set_level), + DEFINE_MODULE_SYMBOL(gpio_descriptor_get_level), + DEFINE_MODULE_SYMBOL(gpio_descriptor_set_options), + DEFINE_MODULE_SYMBOL(gpio_descriptor_get_options), DEFINE_MODULE_SYMBOL(gpio_controller_get_pin_count), + DEFINE_MODULE_SYMBOL(gpio_controller_init_descriptors), + DEFINE_MODULE_SYMBOL(gpio_controller_deinit_descriptors), DEFINE_MODULE_SYMBOL(GPIO_CONTROLLER_TYPE), // drivers/i2c_controller DEFINE_MODULE_SYMBOL(i2c_controller_read),