mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-08-21 09:25:06 +00:00
Compare commits
No commits in common. "335492435986989cd37dbf4555420dd5eb424a71" and "b98a813f3cfd65ed95d8ff8f4ef745b66b1770c5" have entirely different histories.
3354924359
...
b98a813f3c
@ -350,7 +350,7 @@ def generate_devicetree_c(filename: str, items: list[object], bindings: list[Bin
|
||||
for item in items:
|
||||
if type(item) is Device:
|
||||
write_device_structs(file, item, None, bindings, devices, verbose)
|
||||
file.write("const struct DtsDevice dts_devices[] = {\n")
|
||||
file.write("struct DtsDevice dts_devices[] = {\n")
|
||||
for item in items:
|
||||
if type(item) is Device:
|
||||
write_device_list_entry(file, item, bindings, verbose)
|
||||
@ -379,7 +379,7 @@ def generate_devicetree_c(filename: str, items: list[object], bindings: list[Bin
|
||||
file.write(f"extern struct Module {symbol};\n")
|
||||
file.write("\n")
|
||||
# Create array of symbol variables
|
||||
file.write("struct Module* const dts_modules[] = {\n")
|
||||
file.write("struct Module* dts_modules[] = {\n")
|
||||
for symbol in module_symbol_names:
|
||||
file.write(f"\t&{symbol},\n")
|
||||
file.write("\tNULL\n")
|
||||
@ -397,10 +397,10 @@ def generate_devicetree_h(filename: str):
|
||||
#endif
|
||||
|
||||
// Array of device tree modules terminated with DTS_MODULE_TERMINATOR
|
||||
extern const struct DtsDevice dts_devices[];
|
||||
extern struct DtsDevice dts_devices[];
|
||||
|
||||
// Array of module symbols terminated with NULL
|
||||
extern struct Module* const dts_modules[];
|
||||
extern struct Module* dts_modules[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ static struct Device bool_test_device = {
|
||||
.internal = NULL
|
||||
};
|
||||
|
||||
const struct DtsDevice dts_devices[] = {
|
||||
struct DtsDevice dts_devices[] = {
|
||||
{ &root, "test,root", DTS_DEVICE_STATUS_OKAY },
|
||||
{ &test_device, "test,generic-device", DTS_DEVICE_STATUS_OKAY },
|
||||
{ &bool_test_device, "test,bool-device", DTS_DEVICE_STATUS_OKAY },
|
||||
@ -59,7 +59,7 @@ const struct DtsDevice dts_devices[] = {
|
||||
|
||||
extern struct Module data_module;
|
||||
|
||||
struct Module* const dts_modules[] = {
|
||||
struct Module* dts_modules[] = {
|
||||
&data_module,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -7,10 +7,10 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// Array of device tree modules terminated with DTS_MODULE_TERMINATOR
|
||||
extern const struct DtsDevice dts_devices[];
|
||||
extern struct DtsDevice dts_devices[];
|
||||
|
||||
// Array of module symbols terminated with NULL
|
||||
extern struct Module* const dts_modules[];
|
||||
extern struct Module* dts_modules[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ idf_component_register(
|
||||
"Libraries/TactilityKernel/include"
|
||||
"Libraries/TactilityFreeRtos/include"
|
||||
"Libraries/lvgl/include"
|
||||
"Libraries/minmea/include"
|
||||
"Modules/lvgl-module/include"
|
||||
# DRIVER_INCLUDE_DIRS_PLACEHOLDER
|
||||
REQUIRES esp_timer
|
||||
@ -14,9 +13,7 @@ idf_component_register(
|
||||
add_prebuilt_library(TactilityC Libraries/TactilityC/binary/libTactilityC.a)
|
||||
add_prebuilt_library(TactilityKernel Libraries/TactilityKernel/binary/libTactilityKernel.a)
|
||||
add_prebuilt_library(lvgl Libraries/lvgl/binary/liblvgl.a)
|
||||
add_prebuilt_library(minmea Libraries/minmea/binary/libminmea.a)
|
||||
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE TactilityC)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE TactilityKernel)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE lvgl)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE minmea)
|
||||
|
||||
@ -185,13 +185,6 @@ def main():
|
||||
# elf_loader
|
||||
{'src': 'Libraries/elf_loader/elf_loader.cmake', 'dst': 'Libraries/elf_loader/'},
|
||||
{'src': 'Libraries/elf_loader/license.txt', 'dst': 'Libraries/elf_loader/'},
|
||||
# minmea
|
||||
{'src': 'build/esp-idf/minmea/libminmea.a', 'dst': 'Libraries/minmea/binary/'},
|
||||
{'src': 'Libraries/minmea/Include/**', 'dst': 'Libraries/minmea/include/'},
|
||||
{'src': 'Libraries/minmea/CMakeLists.txt', 'dst': 'Libraries/minmea/'},
|
||||
{'src': 'Libraries/minmea/README.md', 'dst': 'Libraries/minmea/'},
|
||||
{'src': 'Libraries/minmea/LICENSE*.*', 'dst': 'Libraries/minmea/'},
|
||||
{'src': 'Libraries/minmea/COPYING', 'dst': 'Libraries/minmea/'},
|
||||
]
|
||||
|
||||
map_copy(mappings, target_path)
|
||||
@ -199,7 +192,6 @@ def main():
|
||||
# Modules
|
||||
add_module(target_path, "lvgl-module")
|
||||
add_module(target_path, "crypt-module")
|
||||
add_module(target_path, "gps-module")
|
||||
|
||||
# Drivers - only ones actually built for this target (chip-restricted drivers like
|
||||
# sc2356-module won't have a .a outside ESP32-P4)
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
#include <tactility/module.h>
|
||||
|
||||
#include <tactility/error.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <Tactility/SystemEvents.h>
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/kernel/Kernel.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/settings/TrackballSettings.h>
|
||||
|
||||
#include <lilygo/drivers/trackball.h>
|
||||
|
||||
@ -4,9 +4,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Official LVGL library header
|
||||
#include <lvgl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@ -111,7 +111,7 @@ void lvgl_devices_detach() {
|
||||
|
||||
lv_disp_t* display = lv_disp_get_next(NULL);
|
||||
while (display != NULL) {
|
||||
lvgl_display_remove(display);
|
||||
lv_display_delete(display);
|
||||
display = lv_disp_get_next(NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ private:
|
||||
* @param dtsModules List of modules from devicetree, null-terminated, non-null parameter
|
||||
* @param dtsDevices Array that is terminated with DTS_DEVICE_TERMINATOR
|
||||
*/
|
||||
void run(Module* const dtsModules[], const DtsDevice dtsDevices[]);
|
||||
void run(Module* dtsModules[], DtsDevice dtsDevices[]);
|
||||
|
||||
/** Provides access to the dispatcher that runs on the main task.
|
||||
* @warning This dispatcher is used for WiFi and might block for some time during WiFi connection.
|
||||
|
||||
24
Tactility/Include/Tactility/lvgl/LvglSync.h
Normal file
24
Tactility/Include/Tactility/lvgl/LvglSync.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/Lock.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace tt::lvgl {
|
||||
|
||||
constexpr TickType_t defaultLockTime = 500 / portTICK_PERIOD_MS;
|
||||
|
||||
/**
|
||||
* LVGL locking function
|
||||
* @param[in] timeout as ticks
|
||||
* @warning when passing zero, we wait forever, as this is the default behaviour for esp_lvgl_port, and we want it to remain consistent
|
||||
* @deprecated Use lvgl_lock() or lvgl_try_lock() from lvgl-module instead.
|
||||
*/
|
||||
bool lock(TickType_t timeout = portMAX_DELAY) __attribute__((deprecated("Use lvgl_lock() from lvgl-module")));
|
||||
|
||||
/** @deprecated Use lvgl_unlock() from lvgl-module instead. */
|
||||
void unlock() __attribute__((deprecated("Use lvgl_unlock() from lvgl-module")));
|
||||
|
||||
std::shared_ptr<Lock> getSyncLock() __attribute__((deprecated("Use lvgl locking functions from lvgl-module")));
|
||||
|
||||
} // namespace
|
||||
@ -3,6 +3,7 @@
|
||||
#include <Tactility/MessageQueue.h>
|
||||
#include <Tactility/PubSub.h>
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/service/Service.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
|
||||
@ -10,6 +11,7 @@
|
||||
|
||||
#include <tactility/concurrent/dispatcher.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <lvgl.h>
|
||||
|
||||
namespace tt::service::gui {
|
||||
|
||||
@ -6,33 +6,26 @@
|
||||
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/TactilityConfig.h>
|
||||
#include <Tactility/bluetooth/Bluetooth.h>
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/CpuAffinity.h>
|
||||
#include <Tactility/MountPoints.h>
|
||||
#include <Tactility/app/AppManifestParsing.h>
|
||||
#include <Tactility/app/AppRegistration.h>
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/file/FileLock.h>
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/hal/SdCard.h>
|
||||
#include <Tactility/network/NtpPrivate.h>
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
#include <Tactility/service/ServiceRegistration.h>
|
||||
#include <Tactility/service/audio/Audio.h>
|
||||
#include <Tactility/settings/TimePrivate.h>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <Tactility/InitEsp.h>
|
||||
#endif
|
||||
|
||||
#include <gps/module.h>
|
||||
#include <gps_generic/gps_generic_module.h>
|
||||
|
||||
#include <crypt/module.h>
|
||||
#include <lvgl/module.h>
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
|
||||
#include <tactility/concurrent/thread.h>
|
||||
#include <tactility/drivers/audio_stream.h>
|
||||
#include <tactility/drivers/display.h>
|
||||
@ -43,7 +36,15 @@
|
||||
#include <tactility/filesystem/file_system.h>
|
||||
#include <tactility/kernel_init.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/memory.h>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <Tactility/InitEsp.h>
|
||||
#endif
|
||||
|
||||
#include "Tactility/Paths.h"
|
||||
#include "Tactility/hal/SdCard.h"
|
||||
|
||||
#include <Tactility/bluetooth/Bluetooth.h>
|
||||
|
||||
namespace tt {
|
||||
|
||||
@ -370,8 +371,6 @@ static void onLvglStarted() {
|
||||
#if TT_FEATURE_SCREENSHOT_ENABLED
|
||||
addService(service::screenshot::manifest);
|
||||
#endif
|
||||
|
||||
memory_print_stats();
|
||||
}
|
||||
|
||||
static void onLvglStopped() {
|
||||
@ -387,11 +386,9 @@ static void onLvglStopped() {
|
||||
check(service::removeService(service::memorychecker::manifest.id));
|
||||
check(service::removeService(service::statusbar::manifest.id));
|
||||
check(service::removeService(service::gui::manifest.id));
|
||||
|
||||
memory_print_stats();
|
||||
}
|
||||
|
||||
void run(Module* const dtsModules[], const DtsDevice dtsDevices[]) {
|
||||
void run(Module* dtsModules[], DtsDevice dtsDevices[]) {
|
||||
LOG_I(TAG, "Tactility v%s on %s (%s)", TT_VERSION, CONFIG_TT_DEVICE_NAME, CONFIG_TT_DEVICE_ID);
|
||||
|
||||
LOG_I(TAG, "Initializing kernel");
|
||||
|
||||
@ -95,7 +95,6 @@ private:
|
||||
// Note: the result code maps to values from cstdlib's errno.h
|
||||
lastError = getErrorCodeString(-relocate_result);
|
||||
LOG_E(TAG, "Application failed to load: %s", lastError.c_str());
|
||||
esp_elf_deinit(&elf);
|
||||
elfFileData = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
#include "Tactility/lvgl/LvglSync.h"
|
||||
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/alertdialog/AlertDialog.h>
|
||||
#include <Tactility/lvgl/Style.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
#include <Tactility/file/File.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <Tactility/lvgl/Style.h>
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <format>
|
||||
#include <Tactility/StringUtils.h>
|
||||
#include <Tactility/file/File.h>
|
||||
|
||||
namespace tt::app::appdetails {
|
||||
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/app/apphub/AppHub.h>
|
||||
#include <Tactility/app/apphub/AppHubEntry.h>
|
||||
#include <Tactility/app/apphubdetails/AppHubDetailsApp.h>
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <lvgl/widgets/spinner.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/network/Http.h>
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/widgets/spinner.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
#include <lvgl.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
namespace tt::app::apphub {
|
||||
|
||||
@ -59,16 +58,20 @@ class AppHubApp final : public App {
|
||||
|
||||
void onRefreshSuccess() {
|
||||
LOG_I(TAG, "Request success");
|
||||
lvgl_lock();
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
showApps();
|
||||
lvgl_unlock();
|
||||
}
|
||||
|
||||
void onRefreshError(const char* error) {
|
||||
LOG_E(TAG, "Request failed: %s", error);
|
||||
lvgl_lock();
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
showRefreshFailedError("Cannot reach server");
|
||||
lvgl_unlock();
|
||||
}
|
||||
|
||||
static void createAppWidget(const std::shared_ptr<AppManifest>& manifest, lv_obj_t* list) {
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
#include <Tactility/app/AppRegistration.h>
|
||||
#include <Tactility/app/alertdialog/AlertDialog.h>
|
||||
#include <Tactility/app/apphub/AppHub.h>
|
||||
#include <Tactility/app/apphub/AppHubEntry.h>
|
||||
#include <Tactility/app/AppRegistration.h>
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/network/Http.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
#include <Tactility/network/Http.h>
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <format>
|
||||
|
||||
namespace tt::app::apphubdetails {
|
||||
@ -88,15 +87,15 @@ class AppHubDetailsApp final : public App {
|
||||
void uninstallApp() {
|
||||
LOG_I(TAG, "Uninstall");
|
||||
|
||||
lvgl_lock();
|
||||
lvgl::getSyncLock()->lock();
|
||||
lv_obj_remove_flag(spinner, LV_OBJ_FLAG_HIDDEN);
|
||||
lvgl_unlock();
|
||||
lvgl::getSyncLock()->unlock();
|
||||
|
||||
uninstall(entry.appId);
|
||||
|
||||
lvgl_lock();
|
||||
lvgl::getSyncLock()->lock();
|
||||
updateViews();
|
||||
lvgl_unlock();
|
||||
lvgl::getSyncLock()->unlock();
|
||||
}
|
||||
|
||||
void doInstall() {
|
||||
@ -116,9 +115,9 @@ class AppHubDetailsApp final : public App {
|
||||
LOG_I(TAG, "Deleted temporary file %s", temp_file_path.c_str());
|
||||
}
|
||||
|
||||
lvgl_lock();
|
||||
lvgl::getSyncLock()->lock();
|
||||
updateViews();
|
||||
lvgl_unlock();
|
||||
lvgl::getSyncLock()->unlock();
|
||||
},
|
||||
[temp_file_path](const char* errorMessage) {
|
||||
LOG_E(TAG, "Download failed: %s", errorMessage);
|
||||
@ -134,9 +133,9 @@ class AppHubDetailsApp final : public App {
|
||||
void installApp() {
|
||||
LOG_I(TAG, "Install");
|
||||
|
||||
lvgl_lock();
|
||||
lvgl::getSyncLock()->lock();
|
||||
lv_obj_remove_flag(spinner, LV_OBJ_FLAG_HIDDEN);
|
||||
lvgl_unlock();
|
||||
lvgl::getSyncLock()->unlock();
|
||||
|
||||
doInstall();
|
||||
}
|
||||
@ -144,9 +143,9 @@ class AppHubDetailsApp final : public App {
|
||||
void updateApp() {
|
||||
LOG_I(TAG, "Update");
|
||||
|
||||
lvgl_lock();
|
||||
lvgl::getSyncLock()->lock();
|
||||
lv_obj_remove_flag(spinner, LV_OBJ_FLAG_HIDDEN);
|
||||
lvgl_unlock();
|
||||
lvgl::getSyncLock()->unlock();
|
||||
|
||||
LOG_I(TAG, "Removing previous version");
|
||||
uninstall(entry.appId);
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/PubSub.h>
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/audio/Audio.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <Tactility/PubSub.h>
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/audio/Audio.h>
|
||||
#include <lvgl/widgets/sliderbox.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
namespace tt::app::audiosettings {
|
||||
|
||||
class AudioSettingsApp final : public App {
|
||||
@ -157,9 +161,10 @@ public:
|
||||
refresh();
|
||||
|
||||
audioSubscription = service::audio::getPubsub()->subscribe([this](auto) {
|
||||
lvgl_lock();
|
||||
refresh();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(lvgl::defaultLockTime)) {
|
||||
refresh();
|
||||
lvgl::unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <Tactility/app/btmanage/BtManagePrivate.h>
|
||||
#include <Tactility/app/btmanage/View.h>
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <tactility/log.h>
|
||||
@ -79,9 +79,12 @@ void BtManage::unlock() {
|
||||
void BtManage::requestViewUpdate() {
|
||||
lock();
|
||||
if (isViewEnabled) {
|
||||
lvgl_lock();
|
||||
view.update();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(1000)) {
|
||||
view.update();
|
||||
lvgl::unlock();
|
||||
} else {
|
||||
LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "LVGL");
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
@ -1,21 +1,23 @@
|
||||
#include <Tactility/app/btpeersettings/BtPeerSettings.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
#include "tactility/device.h"
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/alertdialog/AlertDialog.h>
|
||||
#include <Tactility/bluetooth/Bluetooth.h>
|
||||
#include <Tactility/bluetooth/BluetoothPairedDevice.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Style.h>
|
||||
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/bluetooth.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
namespace tt::app::btpeersettings {
|
||||
|
||||
constexpr auto* TAG = "BtPeerSettings";
|
||||
@ -82,9 +84,12 @@ class BtPeerSettings : public App {
|
||||
|
||||
void requestViewUpdate() const {
|
||||
if (viewEnabled) {
|
||||
lvgl_lock();
|
||||
updateViews();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(1000)) {
|
||||
updateViews();
|
||||
lvgl::unlock();
|
||||
} else {
|
||||
LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "LVGL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,16 +6,15 @@
|
||||
|
||||
#include <Tactility/app/chat/ChatAppPrivate.h>
|
||||
#include <Tactility/app/chat/ChatProtocol.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <tactility/log.h>
|
||||
#include <vector>
|
||||
|
||||
namespace tt::app::chat {
|
||||
@ -84,9 +83,12 @@ void ChatApp::onReceive(const esp_now_recv_info_t* receiveInfo, const uint8_t* d
|
||||
|
||||
state.addMessage(msg);
|
||||
|
||||
lvgl_lock();
|
||||
view.displayMessage(msg);
|
||||
lvgl_unlock();
|
||||
{
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
lock.lock();
|
||||
view.displayMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatApp::sendMessage(const std::string& text) {
|
||||
@ -113,9 +115,12 @@ void ChatApp::sendMessage(const std::string& text) {
|
||||
|
||||
state.addMessage(msg);
|
||||
|
||||
lvgl_lock();
|
||||
view.displayMessage(msg);
|
||||
lvgl_unlock();
|
||||
{
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
lock.lock();
|
||||
view.displayMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatApp::applySettings(const std::string& nickname, const std::string& keyHex) {
|
||||
@ -168,9 +173,12 @@ void ChatApp::switchChannel(const std::string& chatChannel) {
|
||||
settings.chatChannel = trimmedChannel;
|
||||
saveSettings(settings);
|
||||
|
||||
lvgl_lock();
|
||||
view.refreshMessageList();
|
||||
lvgl_unlock();
|
||||
{
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
lock.lock();
|
||||
view.refreshMessageList();
|
||||
}
|
||||
}
|
||||
|
||||
extern const AppManifest manifest = {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Style.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/development/DevelopmentService.h>
|
||||
@ -10,12 +11,12 @@
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <lvgl.h>
|
||||
|
||||
namespace tt::app::development {
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include <Tactility/app/files/SupportedFiles.h>
|
||||
#include <Tactility/app/files/View.h>
|
||||
|
||||
#include <Tactility/Platform.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
@ -8,15 +9,14 @@
|
||||
#include <Tactility/app/inputdialog/InputDialog.h>
|
||||
#include <Tactility/app/notes/Notes.h>
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/usb_host_msc.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@ -450,7 +450,9 @@ void View::onEjectPressed() {
|
||||
void View::update(size_t start_index) {
|
||||
const bool is_root = (state->getCurrentPath() == "/");
|
||||
|
||||
if (!lvgl_try_lock(500 / portTICK_PERIOD_MS)) {
|
||||
auto sync_lockable = lvgl::getSyncLock();
|
||||
auto scoped_lockable = sync_lockable->asScopedLock();
|
||||
if (!scoped_lockable.lock(lvgl::defaultLockTime)) {
|
||||
LOG_E(TAG, "Mutex acquisition timeout (%s)", "lvgl");
|
||||
return;
|
||||
}
|
||||
@ -514,8 +516,6 @@ void View::update(size_t start_index) {
|
||||
} else {
|
||||
lv_obj_add_flag(lv_obj_get_parent(paste_button), LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
lvgl_unlock();
|
||||
}
|
||||
|
||||
void View::init(const AppContext& appContext, lv_obj_t* parent) {
|
||||
@ -551,16 +551,18 @@ void View::init(const AppContext& appContext, lv_obj_t* parent) {
|
||||
}
|
||||
|
||||
void View::onDirEntryListScrollBegin() {
|
||||
if (lvgl_try_lock(500 / portTICK_PERIOD_MS)) {
|
||||
auto sync_lockable = lvgl::getSyncLock();
|
||||
auto scoped_lockable = sync_lockable->asScopedLock();
|
||||
if (scoped_lockable.lock(lvgl::defaultLockTime)) {
|
||||
lv_obj_add_flag(action_list, LV_OBJ_FLAG_HIDDEN);
|
||||
lvgl_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void View::onNavigate() {
|
||||
if (lvgl_try_lock(500 / portTICK_PERIOD_MS)) {
|
||||
auto sync_lockable = lvgl::getSyncLock();
|
||||
auto scoped_lockable = sync_lockable->asScopedLock();
|
||||
if (scoped_lockable.lock(lvgl::defaultLockTime)) {
|
||||
lv_obj_add_flag(action_list, LV_OBJ_FLAG_HIDDEN);
|
||||
lvgl_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
#include <Tactility/app/fileselection/View.h>
|
||||
#include <Tactility/Platform.h>
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/app/alertdialog/AlertDialog.h>
|
||||
#include <Tactility/file/File.h>
|
||||
|
||||
#include <Tactility/Platform.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -155,27 +155,26 @@ void View::onNavigateUpPressed() {
|
||||
}
|
||||
|
||||
void View::update() {
|
||||
if (!lvgl_try_lock(500 / portTICK_PERIOD_MS)) {
|
||||
LOG_E(TAG, "Mutex acquisition timeout (%s)", "lvgl");
|
||||
return;
|
||||
}
|
||||
auto sync_lockable = lvgl::getSyncLock();
|
||||
auto scoped_lockable = sync_lockable->asScopedLock();
|
||||
if (scoped_lockable.lock(lvgl::defaultLockTime)) {
|
||||
lv_obj_clean(dir_entry_list);
|
||||
|
||||
lv_obj_clean(dir_entry_list);
|
||||
state->withEntries([this](const std::vector<dirent>& entries) {
|
||||
for (auto entry : entries) {
|
||||
LOG_D(TAG, "Entry: %s %d", entry.d_name, (int)entry.d_type);
|
||||
createDirEntryWidget(dir_entry_list, entry);
|
||||
}
|
||||
});
|
||||
|
||||
state->withEntries([this](const std::vector<dirent>& entries) {
|
||||
for (auto entry : entries) {
|
||||
LOG_D(TAG, "Entry: %s %d", entry.d_name, (int)entry.d_type);
|
||||
createDirEntryWidget(dir_entry_list, entry);
|
||||
if (state->getCurrentPath() == "/") {
|
||||
lv_obj_add_flag(navigate_up_button, LV_OBJ_FLAG_HIDDEN);
|
||||
} else {
|
||||
lv_obj_remove_flag(navigate_up_button, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
});
|
||||
|
||||
if (state->getCurrentPath() == "/") {
|
||||
lv_obj_add_flag(navigate_up_button, LV_OBJ_FLAG_HIDDEN);
|
||||
} else {
|
||||
lv_obj_remove_flag(navigate_up_button, LV_OBJ_FLAG_HIDDEN);
|
||||
LOG_E(TAG, "Mutex acquisition timeout (%s)", "lvgl");
|
||||
}
|
||||
|
||||
lvgl_unlock();
|
||||
}
|
||||
|
||||
void View::init(lv_obj_t* parent, Mode mode) {
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
#include <Tactility/app/i2cscanner/I2cHelpers.h>
|
||||
#include <Tactility/app/i2cscanner/I2cScannerPrivate.h>
|
||||
#include <Tactility/app/i2cscanner/I2cHelpers.h>
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/Preferences.h>
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <format>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
namespace tt::app::i2cscanner {
|
||||
|
||||
@ -367,9 +367,12 @@ void I2cScannerApp::updateViews() {
|
||||
}
|
||||
|
||||
void I2cScannerApp::updateViewsSafely() {
|
||||
lvgl_lock();
|
||||
updateViews();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(200 / portTICK_PERIOD_MS)) {
|
||||
updateViews();
|
||||
lvgl::unlock();
|
||||
} else {
|
||||
LOG_W(TAG, "Mutex acquisition timeout (%s)", "updateViewsSafely");
|
||||
}
|
||||
}
|
||||
|
||||
void I2cScannerApp::onScanTimerFinished() {
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
#include "lvgl/lvgl.h"
|
||||
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/fileselection/FileSelection.h>
|
||||
#include <Tactility/file/FileLock.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/Assets.h>
|
||||
|
||||
#include <Tactility/file/File.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
@ -41,16 +42,16 @@ class NotesApp final : public App {
|
||||
break;
|
||||
case 1: // Save
|
||||
if (!filePath.empty()) {
|
||||
lvgl_lock();
|
||||
lvgl::getSyncLock()->lock();
|
||||
saveBuffer = lv_textarea_get_text(uiNoteText);
|
||||
lvgl_unlock();
|
||||
lvgl::getSyncLock()->unlock();
|
||||
saveFile(filePath);
|
||||
}
|
||||
break;
|
||||
case 2: // Save as...
|
||||
lvgl_lock();
|
||||
lvgl::getSyncLock()->lock();
|
||||
saveBuffer = lv_textarea_get_text(uiNoteText);
|
||||
lvgl_unlock();
|
||||
lvgl::getSyncLock()->unlock();
|
||||
saveFileLaunchId = fileselection::startForExistingOrNewFile();
|
||||
LOG_I(TAG, "launched with id %u", saveFileLaunchId);
|
||||
break;
|
||||
@ -86,12 +87,13 @@ class NotesApp final : public App {
|
||||
file::getLock(path)->withLock([this, path] {
|
||||
auto data = file::readString(path);
|
||||
if (data != nullptr) {
|
||||
lvgl_lock();
|
||||
lv_textarea_set_text(uiNoteText, reinterpret_cast<const char*>(data.get()));
|
||||
lv_label_set_text(uiCurrentFileName, path.c_str());
|
||||
lvgl_unlock();
|
||||
filePath = path;
|
||||
LOG_I(TAG, "Loaded from %s", path.c_str());
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
lock.lock();
|
||||
lv_textarea_set_text(uiNoteText, reinterpret_cast<const char*>(data.get()));
|
||||
lv_label_set_text(uiCurrentFileName, path.c_str());
|
||||
filePath = path;
|
||||
LOG_I(TAG, "Loaded from %s", path.c_str());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Style.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
|
||||
#include <Tactility/Timer.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/power_supply.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -134,7 +136,7 @@ class PowerApp : public App {
|
||||
return;
|
||||
}
|
||||
|
||||
lvgl_lock();
|
||||
lvgl::lock(kernel::millisToTicks(1000));
|
||||
|
||||
for (auto& entry : entries) {
|
||||
if (entry.enableSwitch != nullptr) {
|
||||
@ -153,7 +155,7 @@ class PowerApp : public App {
|
||||
}
|
||||
}
|
||||
|
||||
lvgl_unlock();
|
||||
lvgl::unlock();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@ -7,15 +7,15 @@
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/lvgl/Lvgl.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/screenshot/Screenshot.h>
|
||||
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/Timer.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
namespace tt::app::screenshot {
|
||||
|
||||
@ -87,9 +87,10 @@ ScreenshotApp::~ScreenshotApp() {
|
||||
}
|
||||
|
||||
void ScreenshotApp::onTimerTick() {
|
||||
if (lvgl_try_lock(500 / portTICK_PERIOD_MS)) {
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
if (lock.lock(lvgl::defaultLockTime)) {
|
||||
updateScreenshotMode();
|
||||
lvgl_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,10 +4,12 @@
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/setup/Setup.h>
|
||||
|
||||
#include <Tactility/Preferences.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
#include <Tactility/app/timezone/TimeZone.h>
|
||||
#include <Tactility/app/wifimanage/WifiManage.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
#include <Tactility/TactilityConfig.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/Paths.h>
|
||||
|
||||
#include <Tactility/Paths.h>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <format>
|
||||
#include <lvgl.h>
|
||||
#include <utility>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
@ -245,18 +247,20 @@ class SystemInfoApp final : public App {
|
||||
Timer memoryTimer = Timer(Timer::Type::Periodic, kernel::millisToTicks(10000), [] {
|
||||
auto app = optApp();
|
||||
if (app) {
|
||||
lvgl_lock();
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
lock.lock();
|
||||
app->updateMemory();
|
||||
lvgl_unlock();
|
||||
}
|
||||
});
|
||||
|
||||
Timer tasksTimer = Timer(Timer::Type::Periodic, kernel::millisToTicks(15000), [] {
|
||||
auto app = optApp();
|
||||
if (app) {
|
||||
lvgl_lock();
|
||||
auto lockable = lvgl::getSyncLock();
|
||||
auto lock = lockable->asScopedLock();
|
||||
lock.lock();
|
||||
app->updateTasks();
|
||||
lvgl_unlock();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/timezone/TimeZone.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
#include <Tactility/settings/SystemSettings.h>
|
||||
#include <Tactility/settings/Time.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
#include <lvgl.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
namespace tt::app::timedatesettings {
|
||||
|
||||
|
||||
@ -1,20 +1,21 @@
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl/fonts.h>
|
||||
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/timezone/TimeZone.h>
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/MountPoints.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
#include <Tactility/settings/Time.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl/fonts.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <memory>
|
||||
|
||||
namespace tt::app::timezone {
|
||||
@ -165,16 +166,16 @@ class TimeZoneApp final : public App {
|
||||
}
|
||||
|
||||
void updateList() {
|
||||
if (lvgl_try_lock(200 / portTICK_PERIOD_MS)) {
|
||||
if (lvgl::lock(200 / portTICK_PERIOD_MS)) {
|
||||
std::string filter = string::lowercase(std::string(lv_textarea_get_text(filterTextareaWidget)));
|
||||
lvgl_unlock();
|
||||
lvgl::unlock();
|
||||
readTimeZones(filter);
|
||||
} else {
|
||||
LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "TimeZone LVGL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (lvgl_try_lock(200 / portTICK_PERIOD_MS)) {
|
||||
if (lvgl::lock(200 / portTICK_PERIOD_MS)) {
|
||||
if (mutex.lock(100 / portTICK_PERIOD_MS)) {
|
||||
lv_obj_clean(listWidget);
|
||||
|
||||
@ -187,7 +188,7 @@ class TimeZoneApp final : public App {
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
lvgl_unlock();
|
||||
lvgl::unlock();
|
||||
} else {
|
||||
LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "TimeZone LVGL");
|
||||
}
|
||||
|
||||
@ -2,17 +2,22 @@
|
||||
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/settings/WebServerSettings.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/service/webserver/WebServerService.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
#include <Tactility/service/wifi/WifiApSettings.h>
|
||||
#include <Tactility/service/webserver/AssetVersion.h>
|
||||
#include <Tactility/service/webserver/WebServerService.h>
|
||||
#include <Tactility/Assets.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <esp_netif.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/timers.h>
|
||||
|
||||
namespace tt::app::webserversettings {
|
||||
|
||||
@ -42,9 +47,10 @@ class WebServerSettingsApp final : public App {
|
||||
app->wsSettings.wifiMode = static_cast<settings::webserver::WiFiMode>(index);
|
||||
app->updated = true;
|
||||
app->wifiSettingsChanged = true;
|
||||
lvgl_lock();
|
||||
app->updateUrlDisplay();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(100)) {
|
||||
app->updateUrlDisplay();
|
||||
lvgl::unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -54,9 +60,10 @@ class WebServerSettingsApp final : public App {
|
||||
getMainDispatcher().dispatch([app, enabled] {
|
||||
app->wsSettings.webServerEnabled = enabled;
|
||||
app->updated = true;
|
||||
lvgl_lock();
|
||||
app->updateUrlDisplay();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(100)) {
|
||||
app->updateUrlDisplay();
|
||||
lvgl::unlock();
|
||||
}
|
||||
|
||||
// Apply immediately instead of waiting for app exit
|
||||
const auto copy = app->wsSettings;
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
#include "Tactility/lvgl/LvglSync.h"
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/alertdialog/AlertDialog.h>
|
||||
#include <Tactility/lvgl/Style.h>
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
#include <Tactility/service/wifi/WifiApSettings.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/widgets/toolbar.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
namespace tt::app::wifiapsettings {
|
||||
|
||||
constexpr auto* TAG = "WifiApSettings";
|
||||
@ -85,9 +88,12 @@ class WifiApSettings : public App {
|
||||
|
||||
void requestViewUpdate() const {
|
||||
if (viewEnabled) {
|
||||
lvgl_lock();
|
||||
updateViews();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(1000)) {
|
||||
updateViews();
|
||||
lvgl::unlock();
|
||||
} else {
|
||||
LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "LVGL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
#include <Tactility/app/wificonnect/WifiConnect.h>
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
namespace tt::app::wificonnect {
|
||||
|
||||
@ -66,9 +68,12 @@ void WifiConnect::unlock() {
|
||||
void WifiConnect::requestViewUpdate() {
|
||||
lock();
|
||||
if (viewEnabled) {
|
||||
lvgl_lock();
|
||||
view.update();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(1000)) {
|
||||
view.update();
|
||||
lvgl::unlock();
|
||||
} else {
|
||||
LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "LVGL");
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
#include <Tactility/app/wifimanage/View.h>
|
||||
#include <Tactility/app/wifimanage/WifiManagePrivate.h>
|
||||
#include <Tactility/app/wifimanage/View.h>
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/app/AppContext.h>
|
||||
#include <Tactility/app/wifiapsettings/WifiApSettings.h>
|
||||
#include <Tactility/app/wificonnect/WifiConnect.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/icons/shared.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
namespace tt::app::wifimanage {
|
||||
|
||||
@ -65,9 +65,12 @@ void WifiManage::unlock() {
|
||||
void WifiManage::requestViewUpdate() {
|
||||
lock();
|
||||
if (isViewEnabled) {
|
||||
lvgl_lock();
|
||||
view.update();
|
||||
lvgl_unlock();
|
||||
if (lvgl::lock(1000)) {
|
||||
view.update();
|
||||
lvgl::unlock();
|
||||
} else {
|
||||
LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "LVGL");
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
@ -11,8 +11,7 @@
|
||||
#include <Tactility/Assets.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/lvgl/Keyboard.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
|
||||
#include <host/ble_gap.h>
|
||||
#include <host/ble_gatt.h>
|
||||
@ -21,8 +20,8 @@
|
||||
#include <esp_timer.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@ -227,7 +226,7 @@ static void hidHostHandleMouseReport(const uint8_t* data, uint16_t len) {
|
||||
if (hid_host_ctx && hid_host_ctx->mouseIndev == nullptr) {
|
||||
getMainDispatcher().dispatch([] {
|
||||
if (!hid_host_ctx || hid_host_ctx->mouseIndev != nullptr) return;
|
||||
if (!lvgl_try_lock(1000)) { LOG_W(TAG, "LVGL lock failed for mouse indev"); return; }
|
||||
if (!tt::lvgl::lock(1000)) { LOG_W(TAG, "LVGL lock failed for mouse indev"); return; }
|
||||
auto* ms = lv_indev_create();
|
||||
lv_indev_set_type(ms, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(ms, hidHostMouseReadCb);
|
||||
@ -238,7 +237,7 @@ static void hidHostHandleMouseReport(const uint8_t* data, uint16_t len) {
|
||||
lv_indev_set_cursor(ms, cur);
|
||||
hid_host_ctx->mouseIndev = ms;
|
||||
hid_host_ctx->mouseCursor = cur;
|
||||
lvgl_unlock();
|
||||
tt::lvgl::unlock();
|
||||
LOG_I(TAG, "Mouse indev registered");
|
||||
});
|
||||
}
|
||||
@ -469,13 +468,13 @@ static void hidHostSubscribeNext(HidHostCtx& ctx) {
|
||||
}
|
||||
getMainDispatcher().dispatch([] {
|
||||
if (!hid_host_ctx || hid_host_ctx->kbIndev != nullptr) return;
|
||||
if (!lvgl_try_lock(1000)) { LOG_W(TAG, "LVGL lock failed for kb indev"); return; }
|
||||
if (!tt::lvgl::lock(1000)) { LOG_W(TAG, "LVGL lock failed for kb indev"); return; }
|
||||
auto* kb = lv_indev_create();
|
||||
lv_indev_set_type(kb, LV_INDEV_TYPE_KEYPAD);
|
||||
lv_indev_set_read_cb(kb, hidHostKeyboardReadCb);
|
||||
hid_host_ctx->kbIndev = kb;
|
||||
lvgl::hardware_keyboard_set_indev(kb);
|
||||
lvgl_unlock();
|
||||
tt::lvgl::hardware_keyboard_set_indev(kb);
|
||||
tt::lvgl::unlock();
|
||||
LOG_I(TAG, "Keyboard indev registered");
|
||||
});
|
||||
|
||||
@ -695,18 +694,18 @@ static int hidHostGapCb(struct ble_gap_event* event, void* /*arg*/) {
|
||||
}
|
||||
|
||||
getMainDispatcher().dispatch([saved_kb, saved_mouse, saved_cursor, saved_queue] {
|
||||
if (!lvgl_try_lock(1000)) {
|
||||
if (!tt::lvgl::lock(1000)) {
|
||||
LOG_W(TAG, "Failed to acquire LVGL lock for indev cleanup");
|
||||
if (saved_queue) vQueueDelete(saved_queue);
|
||||
return;
|
||||
}
|
||||
if (saved_kb) {
|
||||
lvgl::hardware_keyboard_set_indev(nullptr);
|
||||
tt::lvgl::hardware_keyboard_set_indev(nullptr);
|
||||
lv_indev_delete(saved_kb);
|
||||
}
|
||||
if (saved_mouse) lv_indev_delete(saved_mouse);
|
||||
if (saved_cursor) lv_obj_delete(saved_cursor);
|
||||
lvgl_unlock();
|
||||
tt::lvgl::unlock();
|
||||
if (saved_queue) vQueueDelete(saved_queue);
|
||||
});
|
||||
break;
|
||||
|
||||
35
Tactility/Source/lvgl/LvglSync.cpp
Normal file
35
Tactility/Source/lvgl/LvglSync.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "Tactility/lvgl/LvglSync.h"
|
||||
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
namespace tt::lvgl {
|
||||
|
||||
bool lock(TickType_t timeout) {
|
||||
return lvgl_try_lock(timeout);
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
lvgl_unlock();
|
||||
}
|
||||
|
||||
class LvglSync : public Lock {
|
||||
public:
|
||||
~LvglSync() override = default;
|
||||
|
||||
bool lock(TickType_t timeoutTicks) const override {
|
||||
return lvgl_try_lock(timeoutTicks);
|
||||
}
|
||||
|
||||
void unlock() const override {
|
||||
lvgl_unlock();
|
||||
}
|
||||
};
|
||||
|
||||
static std::shared_ptr<Lock> lvglSync = std::make_shared<LvglSync>();
|
||||
|
||||
std::shared_ptr<Lock> getSyncLock() {
|
||||
return lvglSync;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -5,16 +5,17 @@
|
||||
#include <Tactility/RecursiveMutex.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Statusbar.h>
|
||||
#include <Tactility/lvgl/Style.h>
|
||||
#include <Tactility/settings/Time.h>
|
||||
|
||||
#include <lvgl/fonts.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/fonts.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <memory>
|
||||
|
||||
namespace tt::lvgl {
|
||||
@ -105,10 +106,10 @@ static lv_obj_class_t statusbar_class = {
|
||||
|
||||
static void statusbar_pubsub_event(Statusbar* statusbar) {
|
||||
LOG_D(TAG, "Update event");
|
||||
if (lvgl_try_lock(500 / portTICK_PERIOD_MS)) {
|
||||
if (lock(defaultLockTime)) {
|
||||
update_main(statusbar);
|
||||
lv_obj_invalidate(&statusbar->obj);
|
||||
lvgl_unlock();
|
||||
unlock();
|
||||
} else {
|
||||
LOG_W(TAG, "Mutex acquisition timeout (%s)", "Statusbar");
|
||||
}
|
||||
|
||||
@ -2,8 +2,10 @@
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include <atomic>
|
||||
#include <Tactility/Assets.h>
|
||||
#include <Tactility/lvgl/Keyboard.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/usb_host_hid.h>
|
||||
@ -14,9 +16,7 @@
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <lvgl.h>
|
||||
|
||||
namespace tt::lvgl {
|
||||
|
||||
@ -148,31 +148,33 @@ static void usbHidInputTask(void* arg) {
|
||||
auto* ctx = static_cast<UsbHidInputCtx*>(arg);
|
||||
LOG_I(TAG, "started");
|
||||
|
||||
// TODO: Implement time-out
|
||||
while (!lv_is_initialized()) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
|
||||
lvgl_lock();
|
||||
if (lock()) {
|
||||
ctx->mouse_cursor = lv_image_create(lv_layer_sys());
|
||||
lv_obj_remove_flag(ctx->mouse_cursor, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_image_set_src(ctx->mouse_cursor, TT_ASSETS_UI_CURSOR);
|
||||
lv_obj_add_flag(ctx->mouse_cursor, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
ctx->mouse_cursor = lv_image_create(lv_layer_sys());
|
||||
lv_obj_remove_flag(ctx->mouse_cursor, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_image_set_src(ctx->mouse_cursor, TT_ASSETS_UI_CURSOR);
|
||||
lv_obj_add_flag(ctx->mouse_cursor, LV_OBJ_FLAG_HIDDEN);
|
||||
ctx->mouse_indev = lv_indev_create();
|
||||
lv_indev_set_type(ctx->mouse_indev, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(ctx->mouse_indev, mouse_read_cb);
|
||||
lv_indev_set_user_data(ctx->mouse_indev, ctx);
|
||||
lv_indev_set_cursor(ctx->mouse_indev, ctx->mouse_cursor);
|
||||
|
||||
ctx->mouse_indev = lv_indev_create();
|
||||
lv_indev_set_type(ctx->mouse_indev, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(ctx->mouse_indev, mouse_read_cb);
|
||||
lv_indev_set_user_data(ctx->mouse_indev, ctx);
|
||||
lv_indev_set_cursor(ctx->mouse_indev, ctx->mouse_cursor);
|
||||
ctx->kb_indev = lv_indev_create();
|
||||
lv_indev_set_type(ctx->kb_indev, LV_INDEV_TYPE_KEYPAD);
|
||||
lv_indev_set_read_cb(ctx->kb_indev, keyboard_read_cb);
|
||||
lv_indev_set_user_data(ctx->kb_indev, ctx);
|
||||
lv_indev_set_group(ctx->kb_indev, lv_group_get_default());
|
||||
|
||||
ctx->kb_indev = lv_indev_create();
|
||||
lv_indev_set_type(ctx->kb_indev, LV_INDEV_TYPE_KEYPAD);
|
||||
lv_indev_set_read_cb(ctx->kb_indev, keyboard_read_cb);
|
||||
lv_indev_set_user_data(ctx->kb_indev, ctx);
|
||||
lv_indev_set_group(ctx->kb_indev, lv_group_get_default());
|
||||
|
||||
lvgl_unlock();
|
||||
unlock();
|
||||
LOG_I(TAG, "LVGL input devices registered");
|
||||
} else {
|
||||
LOG_W(TAG, "could not acquire LVGL lock for indev registration");
|
||||
}
|
||||
|
||||
// Drain the HID event queue and route events to the appropriate destinations
|
||||
while (ctx->running) {
|
||||
@ -226,29 +228,29 @@ static void usbHidInputTask(void* arg) {
|
||||
break;
|
||||
}
|
||||
case USB_HID_EVENT_KEYBOARD_CONNECTED:
|
||||
if (ctx->kb_indev && lvgl_try_lock(pdMS_TO_TICKS(200))) {
|
||||
if (ctx->kb_indev && lock(pdMS_TO_TICKS(200))) {
|
||||
hardware_keyboard_set_indev(ctx->kb_indev);
|
||||
lvgl_unlock();
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
case USB_HID_EVENT_KEYBOARD_DISCONNECTED:
|
||||
if (lvgl_try_lock(pdMS_TO_TICKS(200))) {
|
||||
if (lock(pdMS_TO_TICKS(200))) {
|
||||
hardware_keyboard_set_indev(nullptr);
|
||||
lvgl_unlock();
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
case USB_HID_EVENT_MOUSE_CONNECTED:
|
||||
ctx->mouse_connected = true;
|
||||
if (ctx->mouse_cursor && lvgl_try_lock(pdMS_TO_TICKS(200))) {
|
||||
if (ctx->mouse_cursor && lock(pdMS_TO_TICKS(200))) {
|
||||
lv_obj_remove_flag(ctx->mouse_cursor, LV_OBJ_FLAG_HIDDEN);
|
||||
lvgl_unlock();
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
case USB_HID_EVENT_MOUSE_DISCONNECTED:
|
||||
ctx->mouse_connected = false;
|
||||
if (ctx->mouse_cursor && lvgl_try_lock(pdMS_TO_TICKS(200))) {
|
||||
if (ctx->mouse_cursor && lock(pdMS_TO_TICKS(200))) {
|
||||
lv_obj_add_flag(ctx->mouse_cursor, LV_OBJ_FLAG_HIDDEN);
|
||||
lvgl_unlock();
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -256,15 +258,16 @@ static void usbHidInputTask(void* arg) {
|
||||
}
|
||||
}
|
||||
|
||||
lvgl_lock();
|
||||
if (ctx->mouse_indev) { lv_indev_delete(ctx->mouse_indev); ctx->mouse_indev = nullptr; }
|
||||
if (ctx->mouse_cursor) { lv_obj_delete(ctx->mouse_cursor); ctx->mouse_cursor = nullptr; }
|
||||
if (ctx->kb_indev) {
|
||||
hardware_keyboard_set_indev(nullptr);
|
||||
lv_indev_delete(ctx->kb_indev);
|
||||
ctx->kb_indev = nullptr;
|
||||
if (lock()) {
|
||||
if (ctx->mouse_indev) { lv_indev_delete(ctx->mouse_indev); ctx->mouse_indev = nullptr; }
|
||||
if (ctx->mouse_cursor) { lv_obj_delete(ctx->mouse_cursor); ctx->mouse_cursor = nullptr; }
|
||||
if (ctx->kb_indev) {
|
||||
hardware_keyboard_set_indev(nullptr);
|
||||
lv_indev_delete(ctx->kb_indev);
|
||||
ctx->kb_indev = nullptr;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
lvgl_unlock();
|
||||
|
||||
LOG_I(TAG, "stopped");
|
||||
xSemaphoreGive(ctx->task_done);
|
||||
@ -331,7 +334,7 @@ void stopUsbHidInput() {
|
||||
vTaskDelete(ctx->task);
|
||||
// Task was killed before it could clean up LVGL objects; do it here to
|
||||
// prevent mouse_read_cb / keyboard_read_cb from running with a freed ctx.
|
||||
if (lvgl_try_lock(pdMS_TO_TICKS(200))) {
|
||||
if (lock(pdMS_TO_TICKS(200))) {
|
||||
if (ctx->mouse_indev) { lv_indev_delete(ctx->mouse_indev); ctx->mouse_indev = nullptr; }
|
||||
if (ctx->mouse_cursor) { lv_obj_delete(ctx->mouse_cursor); ctx->mouse_cursor = nullptr; }
|
||||
if (ctx->kb_indev) {
|
||||
@ -339,7 +342,7 @@ void stopUsbHidInput() {
|
||||
lv_indev_delete(ctx->kb_indev);
|
||||
ctx->kb_indev = nullptr;
|
||||
}
|
||||
lvgl_unlock();
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
ctx->task = nullptr;
|
||||
|
||||
@ -200,10 +200,10 @@ size_t receiveFile(httpd_req_t* request, size_t length, const std::string& fileP
|
||||
auto expected_chunk_size = std::min<size_t>(BUFFER_SIZE, length - bytes_received);
|
||||
size_t receive_chunk_size = httpd_req_recv(request, buffer, expected_chunk_size);
|
||||
if (receive_chunk_size <= 0) {
|
||||
LOG_E(TAG, "Receive failed, got 0 bytes but expected %zu more", length - bytes_received);
|
||||
LOG_E(TAG, "Receive failed");
|
||||
break;
|
||||
}
|
||||
if (fwrite(buffer, 1, receive_chunk_size, file) != receive_chunk_size) {
|
||||
if (fwrite(buffer, 1, receive_chunk_size, file) != (size_t)receive_chunk_size) {
|
||||
LOG_E(TAG, "Failed to write all bytes");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include <Tactility/service/ServiceRegistration.h>
|
||||
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/service/ServiceContext.h>
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
|
||||
@ -10,35 +9,11 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace tt::service {
|
||||
|
||||
constexpr auto* TAG = "ServiceRegistration";
|
||||
|
||||
namespace {
|
||||
|
||||
// Tracks the heap allocations addService() makes per registered id, so removeService()
|
||||
// can free them once the kernel confirms the manifest is unregistered. The kernel only
|
||||
// ever stores the raw pointer it's handed (see service_manager_add/_remove) - it never
|
||||
// takes ownership - so the registering side (us) is responsible for the lifetime.
|
||||
struct AllocatedManifest {
|
||||
std::shared_ptr<const ServiceManifest>* persistentManifest;
|
||||
::ServiceManifest* cManifest;
|
||||
};
|
||||
|
||||
Mutex& allocatedManifestsMutex() {
|
||||
static Mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, AllocatedManifest>& allocatedManifests() {
|
||||
static std::unordered_map<std::string, AllocatedManifest> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Bridges the kernel's C ServiceManifest/Service callbacks to the C++ Service
|
||||
// instances they wrap. Declared extern "C" to match the linkage of the C
|
||||
// function-pointer types they're assigned to (see e.g. gpio_controller.cpp).
|
||||
@ -73,8 +48,9 @@ void addService(std::shared_ptr<const ServiceManifest> manifest, bool autoStart)
|
||||
return;
|
||||
}
|
||||
|
||||
// Freed by removeService() once the kernel confirms the manifest is unregistered.
|
||||
// Keeps id's backing string alive for cManifest.id below in the meantime.
|
||||
// Intentionally never freed: removeService() only unregisters the manifest
|
||||
// from the kernel, it doesn't own this allocation. Keeps id's backing
|
||||
// string alive for cManifest.id below.
|
||||
auto* persistentManifest = new std::shared_ptr(manifest);
|
||||
auto* cManifest = new ::ServiceManifest {
|
||||
.id = (*persistentManifest)->id.c_str(),
|
||||
@ -84,12 +60,6 @@ void addService(std::shared_ptr<const ServiceManifest> manifest, bool autoStart)
|
||||
.on_stop = cppOnStopTrampoline,
|
||||
};
|
||||
|
||||
{
|
||||
auto lock = allocatedManifestsMutex().asScopedLock();
|
||||
lock.lock();
|
||||
allocatedManifests()[id] = AllocatedManifest { persistentManifest, cManifest };
|
||||
}
|
||||
|
||||
error_t error = service_manager_add(cManifest, autoStart);
|
||||
if (error != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to add service %s: %s", id.c_str(), error_to_string(error));
|
||||
@ -115,20 +85,6 @@ bool removeService(const std::string& id) {
|
||||
LOG_E(TAG, "Failed to remove service %s: %s", id.c_str(), error_to_string(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
// The kernel has confirmed the manifest is unregistered, so id (which points into
|
||||
// persistentManifest's string) is no longer needed by anything - safe to free now.
|
||||
{
|
||||
auto lock = allocatedManifestsMutex().asScopedLock();
|
||||
lock.lock();
|
||||
auto iterator = allocatedManifests().find(id);
|
||||
if (iterator != allocatedManifests().end()) {
|
||||
delete iterator->second.cManifest;
|
||||
delete iterator->second.persistentManifest;
|
||||
allocatedManifests().erase(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(TAG, "Removed %s", id.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -157,20 +157,13 @@ esp_err_t DevelopmentService::handleAppInstall(httpd_req_t* request) {
|
||||
// Create tmp directory
|
||||
const std::string tmp_path = getTempPath();
|
||||
if (!file::findOrCreateDirectory(tmp_path, 0777)) {
|
||||
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create temp path");
|
||||
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to save file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
std::string safe_name = file::getLastPathSegment(filename_entry->second);
|
||||
if (safe_name.empty() || safe_name.find("..") != std::string::npos ||
|
||||
safe_name.find('/') != std::string::npos || safe_name.find('\\') != std::string::npos) {
|
||||
httpd_resp_send_err(request, HTTPD_400_BAD_REQUEST, "invalid filename");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
auto file_path = std::format("{}/{}", tmp_path, safe_name);
|
||||
auto file_path = std::format("{}/{}", tmp_path, filename_entry->second);
|
||||
if (network::receiveFile(request, file_size, file_path) != file_size) {
|
||||
file::deleteFile(file_path);
|
||||
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
|
||||
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to save file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
#include <Tactility/service/gui/GuiService.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/app/AppInstance.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Statusbar.h>
|
||||
#include <Tactility/lvgl/UsbHidInput.h>
|
||||
#include <Tactility/service/ServiceRegistration.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace tt::service::gui {
|
||||
|
||||
extern const ServiceManifest manifest;
|
||||
@ -199,13 +200,6 @@ void GuiService::redraw() {
|
||||
// Create a default group which adds all objects automatically,
|
||||
// and assign all indevs to it.
|
||||
// This enables navigation with limited input, such as encoder wheels.
|
||||
// The previous default group (if any) is no longer referenced by anything
|
||||
// after lv_obj_clean() above, so it must be freed here or it leaks.
|
||||
auto* previous_group = lv_group_get_default();
|
||||
if (previous_group != nullptr) {
|
||||
lv_group_delete(previous_group);
|
||||
}
|
||||
|
||||
lv_group_t* group = lv_group_create();
|
||||
auto* indev = lv_indev_get_next(nullptr);
|
||||
while (indev) {
|
||||
@ -285,17 +279,6 @@ void GuiService::onStop(ServiceContext& service) {
|
||||
lv_group_delete(keyboardGroup);
|
||||
keyboardGroup = nullptr;
|
||||
}
|
||||
|
||||
auto* default_group = lv_group_get_default();
|
||||
if (default_group != nullptr) {
|
||||
lv_group_delete(default_group);
|
||||
lv_group_set_default(nullptr);
|
||||
}
|
||||
|
||||
auto* screen_root = lv_screen_active();
|
||||
if (screen_root != nullptr) {
|
||||
lv_obj_clean(screen_root);
|
||||
}
|
||||
lvgl_unlock();
|
||||
|
||||
delete thread;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
#include <Tactility/lvgl/Keyboard.h>
|
||||
#include <Tactility/service/gui/GuiService.h>
|
||||
#include <Tactility/TactilityConfig.h>
|
||||
#include <Tactility/service/espnow/EspNowService.h>
|
||||
#include "Tactility/lvgl/Keyboard.h"
|
||||
#include "Tactility/lvgl/LvglSync.h"
|
||||
#include "Tactility/service/gui/GuiService.h"
|
||||
|
||||
#include <tactility/check.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <Tactility/TactilityConfig.h>
|
||||
#include <Tactility/service/espnow/EspNowService.h>
|
||||
|
||||
namespace tt::service::gui {
|
||||
|
||||
@ -54,7 +53,7 @@ void GuiService::keyboardAddTextArea(lv_obj_t* textarea) {
|
||||
lock();
|
||||
|
||||
if (isStarted) {
|
||||
check(lvgl_try_lock(0), "lvgl should already be locked before calling this method");
|
||||
check(lvgl::lock(0), "lvgl should already be locked before calling this method");
|
||||
|
||||
if (softwareKeyboardIsEnabled()) {
|
||||
lv_obj_add_event_cb(textarea, show_keyboard, LV_EVENT_FOCUSED, nullptr);
|
||||
@ -67,7 +66,7 @@ void GuiService::keyboardAddTextArea(lv_obj_t* textarea) {
|
||||
lvgl::software_keyboard_activate(keyboardGroup);
|
||||
}
|
||||
|
||||
lvgl_unlock();
|
||||
lvgl::unlock();
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
@ -10,8 +10,12 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <esp_heap_caps.h>
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/memory.h>
|
||||
|
||||
namespace tt::service::loader {
|
||||
|
||||
@ -68,8 +72,6 @@ void LoaderService::onStartAppMessage(const std::string& id, app::LaunchId launc
|
||||
appStack.push_back(new_app);
|
||||
transitionAppToState(new_app, app::State::Created);
|
||||
transitionAppToState(new_app, app::State::Showing);
|
||||
|
||||
memory_print_stats();
|
||||
}
|
||||
|
||||
void LoaderService::onStopTopAppMessage(const std::string& id) {
|
||||
@ -123,6 +125,10 @@ void LoaderService::onStopTopAppMessage(const std::string& id) {
|
||||
LOG_W(TAG, "Memory leak: Stopped %s, but use count is %d", app_to_stop->getManifest().appId.c_str(), (int)(app_to_stop->getApp().use_count() - 2));
|
||||
}
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
LOG_I(TAG, "Free heap: %d", (int)heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
#endif
|
||||
|
||||
std::shared_ptr<app::AppInstance> instance_to_resume;
|
||||
// If there's a previous app, resume it
|
||||
if (!appStack.empty()) {
|
||||
@ -161,8 +167,6 @@ void LoaderService::onStopTopAppMessage(const std::string& id) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
memory_print_stats();
|
||||
}
|
||||
|
||||
int LoaderService::findAppInStack(const std::string& id) const {
|
||||
|
||||
@ -5,17 +5,16 @@
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/CpuAffinity.h>
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/service/loader/Loader.h>
|
||||
#include <Tactility/service/screenshot/ScreenshotTask.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include <lv_screenshot.h>
|
||||
|
||||
#include <format>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
namespace tt::service::screenshot {
|
||||
|
||||
constexpr auto* TAG = "ScreenshotTask";
|
||||
@ -51,13 +50,13 @@ void ScreenshotTask::setFinished() {
|
||||
}
|
||||
|
||||
static void makeScreenshot(const std::string& filename) {
|
||||
if (lvgl_try_lock(50 / portTICK_PERIOD_MS)) {
|
||||
if (lvgl::lock(50 / portTICK_PERIOD_MS)) {
|
||||
if (lv_screenshot_create(lv_scr_act(), LV_100ASK_SCREENSHOT_SV_PNG, filename.c_str())) {
|
||||
LOG_I(TAG, "Screenshot saved to %s", filename.c_str());
|
||||
} else {
|
||||
LOG_E(TAG, "Screenshot not saved to %s", filename.c_str());
|
||||
}
|
||||
lvgl_unlock();
|
||||
lvgl::unlock();
|
||||
} else {
|
||||
LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "LVGL");
|
||||
}
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/bluetooth/Bluetooth.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/service/ServiceContext.h>
|
||||
#include <Tactility/service/ServicePaths.h>
|
||||
#include <Tactility/service/ServiceRegistration.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/bluetooth.h>
|
||||
@ -18,6 +18,7 @@
|
||||
#include <tactility/drivers/usb_host_midi.h>
|
||||
#include <tactility/drivers/usb_host_msc.h>
|
||||
#include <tactility/filesystem/file_system.h>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/icons/statusbar.h>
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include <tactility/check.h>
|
||||
#include <Tactility/service/webserver/WebServerService.h>
|
||||
#include <Tactility/service/webserver/AssetVersion.h>
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
#include <Tactility/settings/WebServerSettings.h>
|
||||
#include <Tactility/MountPoints.h>
|
||||
@ -8,29 +10,28 @@
|
||||
#include <Tactility/lvgl/Statusbar.h>
|
||||
#include <Tactility/Mutex.h>
|
||||
|
||||
#include <tactility/check.h>
|
||||
|
||||
#include <Tactility/TactilityConfig.h>
|
||||
#include <Tactility/app/AppRegistration.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
#include <esp_wifi_default.h>
|
||||
#include <Tactility/network/HttpdReq.h>
|
||||
#include <Tactility/network/Url.h>
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/lvgl/Lvgl.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
|
||||
#include <ranges>
|
||||
#include <tactility/filesystem/file_system.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <lvgl/icons/statusbar.h>
|
||||
|
||||
#if TT_FEATURE_SCREENSHOT_ENABLED
|
||||
#include <lv_screenshot.h>
|
||||
#endif
|
||||
|
||||
#include <lvgl/icons/statusbar.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
@ -41,16 +42,16 @@
|
||||
#include <esp_netif.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_vfs_fat.h>
|
||||
#include <esp_wifi_default.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <iomanip>
|
||||
#include <lwip/ip4_addr.h>
|
||||
#include <mbedtls/base64.h>
|
||||
#include <ranges>
|
||||
#include <sstream>
|
||||
|
||||
#include <tactility/log.h>
|
||||
|
||||
namespace tt::service::webserver {
|
||||
|
||||
constexpr auto* TAG = "WebServerService";
|
||||
@ -1476,9 +1477,9 @@ esp_err_t WebServerService::handleApiScreenshot(httpd_req_t* request) {
|
||||
std::string lvgl_screenshot_path = lvgl::PATH_PREFIX + screenshot_path;
|
||||
|
||||
// Capture screenshot using LVGL
|
||||
if (lvgl_try_lock(pdMS_TO_TICKS(100))) {
|
||||
if (lvgl::lock(pdMS_TO_TICKS(100))) {
|
||||
bool success = lv_screenshot_create(lv_scr_act(), LV_100ASK_SCREENSHOT_SV_PNG, lvgl_screenshot_path.c_str());
|
||||
lvgl_unlock();
|
||||
lvgl::unlock();
|
||||
|
||||
if (!success) {
|
||||
LOG_E(TAG, "lv_screenshot_create failed for path: %s", lvgl_screenshot_path.c_str());
|
||||
|
||||
@ -14,7 +14,7 @@ extern "C" {
|
||||
* @param dts_devices The list of generated devices from the devicetree. The array must be terminated with DTS_DEVICE_TERMINATOR. Non-null parameter.
|
||||
* @return ERROR_NONE on success, otherwise an error code
|
||||
*/
|
||||
error_t kernel_init(struct Module* const dts_modules[], const struct DtsDevice dts_devices[]);
|
||||
error_t kernel_init(struct Module* dts_modules[], struct DtsDevice dts_devices[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Capability flags that describe what a memory allocation needs or prefers. */
|
||||
enum MemoryCapability {
|
||||
/** Internal memory (non-external/non-PSRAM) memory. */
|
||||
MEMORY_CAPABILITY_INTERNAL = 1u << 0,
|
||||
/** External memory (e.g. PSRAM/SPIRAM). */
|
||||
MEMORY_CAPABILITY_EXTERNAL = 1u << 1,
|
||||
/** Usable for code execution. */
|
||||
MEMORY_CAPABILITY_EXECUTABLE = 1u << 2,
|
||||
/** Usable as a DMA source/destination. */
|
||||
MEMORY_CAPABILITY_DMA = 1u << 3,
|
||||
/** Usable for SIMD instructions. */
|
||||
MEMORY_CAPABILITY_SIMD = 1u << 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Describes the constraints an allocation must (or should) satisfy.
|
||||
*
|
||||
* `required` capabilities must all be satisfied or the allocation fails. `desired`
|
||||
* capabilities are attempted alongside `required`, but implementations fall back to
|
||||
* `required`-only if `required | desired` together can't be satisfied.
|
||||
*/
|
||||
struct MemoryPolicy {
|
||||
/** A bitset of MemoryCapability flags that are required during allocation. */
|
||||
uint16_t required;
|
||||
/** A bitset of MemoryCapability flags that are preferable (but optional) during allocation. */
|
||||
uint16_t desired;
|
||||
/** Alignment (in bytes) of the returned pointer, or 0 for the platform default. Must be a power of 2. */
|
||||
size_t alignment;
|
||||
};
|
||||
|
||||
/** The default policy: no required/desired capabilities, no alignment requirement. */
|
||||
extern const struct MemoryPolicy MEMORY_POLICY_DEFAULT;
|
||||
|
||||
/**
|
||||
* @brief Logs current heap usage (internal and external, when applicable).
|
||||
* No-op on platforms without heap capability tracking.
|
||||
*/
|
||||
void memory_print_stats();
|
||||
|
||||
/**
|
||||
* @brief Allocates memory that satisfies the given policy.
|
||||
* @param[in] size number of bytes to allocate
|
||||
* @param[in] policy the allocation constraints
|
||||
* @return the allocated memory, or NULL on failure
|
||||
*/
|
||||
void* memory_alloc_with_policy(size_t size, const struct MemoryPolicy* policy);
|
||||
|
||||
/**
|
||||
* @brief Resizes a previous allocation, preserving its contents up to the smaller of the old and new size.
|
||||
* @warning policy->alignment is not guaranteed to be preserved across a realloc - it is only
|
||||
* honored on fresh allocations (memory_alloc_with_policy()/memory_calloc_with_policy()).
|
||||
* @param[in] ptr memory previously returned by memory_alloc_with_policy(), memory_calloc_with_policy(),
|
||||
* or memory_realloc_with_policy(), or NULL to allocate a new block
|
||||
* @param[in] size new memory size in bytes
|
||||
* @param[in] policy the policy for the new allocation
|
||||
* @return the (possibly moved) allocated memory, or NULL on failure - in which case ptr is left untouched
|
||||
*/
|
||||
void* memory_realloc_with_policy(void* ptr, size_t size, const struct MemoryPolicy* policy);
|
||||
|
||||
/**
|
||||
* @brief Allocates zero-initialized memory that satisfies the given policy.
|
||||
* @param[in] count number of elements
|
||||
* @param[in] size size of each element in bytes
|
||||
* @param[in] policy the allocation constraints
|
||||
* @return the allocated memory, or NULL on failure
|
||||
*/
|
||||
void* memory_calloc_with_policy(size_t count, size_t size, const struct MemoryPolicy* policy);
|
||||
|
||||
/**
|
||||
* @brief Allocates memory using MEMORY_POLICY_DEFAULT.
|
||||
* @param[in] size number of bytes to allocate
|
||||
* @return the allocated memory, or NULL on failure
|
||||
*/
|
||||
inline void* memory_alloc(size_t size) {
|
||||
return memory_alloc_with_policy(size, &MEMORY_POLICY_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates zero-initialized memory using MEMORY_POLICY_DEFAULT.
|
||||
* @param[in] count number of elements
|
||||
* @param[in] size size of each element in bytes
|
||||
* @return the allocated memory, or NULL on failure
|
||||
*/
|
||||
inline void* memory_calloc(size_t count, size_t size) {
|
||||
return memory_calloc_with_policy(count, size, &MEMORY_POLICY_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resizes a previous allocation using MEMORY_POLICY_DEFAULT. See memory_realloc_with_policy().
|
||||
* @param[in] ptr memory previously returned by one of the memory_* allocation functions, or NULL
|
||||
* @param[in] size new memory size in bytes
|
||||
* @return the (possibly moved) allocated memory, or NULL on failure - in which case ptr is left untouched
|
||||
*/
|
||||
inline void* memory_realloc(void* ptr, size_t size) {
|
||||
return memory_realloc_with_policy(ptr, size, &MEMORY_POLICY_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Frees memory previously returned by one of the memory_* allocation functions.
|
||||
* @param[in] ptr the memory to free, or NULL (a no-op)
|
||||
*/
|
||||
void memory_free(void* ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -43,7 +43,7 @@ Module root_module = {
|
||||
.internal = nullptr
|
||||
};
|
||||
|
||||
error_t kernel_init(Module* const dts_modules[], const DtsDevice dts_devices[]) {
|
||||
error_t kernel_init(Module* dts_modules[], DtsDevice dts_devices[]) {
|
||||
LOG_I(TAG, "init");
|
||||
|
||||
if (module_construct_add_start(&root_module) != ERROR_NONE) {
|
||||
@ -51,7 +51,7 @@ error_t kernel_init(Module* const dts_modules[], const DtsDevice dts_devices[])
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
Module* const* dts_module = dts_modules;
|
||||
Module** dts_module = dts_modules;
|
||||
while (*dts_module != nullptr) {
|
||||
if (module_construct_add_start(*dts_module) != ERROR_NONE) {
|
||||
LOG_E(TAG, "dts module init failed: %s", (*dts_module)->name);
|
||||
@ -60,7 +60,7 @@ error_t kernel_init(Module* const dts_modules[], const DtsDevice dts_devices[])
|
||||
dts_module++;
|
||||
}
|
||||
|
||||
const DtsDevice* dts_device = dts_devices;
|
||||
DtsDevice* dts_device = dts_devices;
|
||||
while (dts_device->device != nullptr) {
|
||||
if (dts_device->status == DTS_DEVICE_STATUS_OKAY) {
|
||||
if (device_construct_add_start(dts_device->device, dts_device->compatible) != ERROR_NONE) {
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/memory.h>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include <esp_heap_caps.h>
|
||||
#endif
|
||||
|
||||
constexpr auto* TAG = "memory";
|
||||
|
||||
extern "C" {
|
||||
|
||||
const struct MemoryPolicy MEMORY_POLICY_DEFAULT = {
|
||||
.required = 0,
|
||||
.desired = 0,
|
||||
.alignment = 0,
|
||||
};
|
||||
|
||||
void memory_print_stats() {
|
||||
#ifdef ESP_PLATFORM
|
||||
size_t heap_free = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
size_t heap_total = heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
|
||||
LOG_I(TAG, "Heap: %zu / %zu available", heap_free, heap_total);
|
||||
size_t ext_free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||
size_t ext_total = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
|
||||
LOG_I(TAG, "External: %zu / %zu available", ext_free, ext_total);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include <tactility/memory.h>
|
||||
|
||||
#include <esp_heap_caps.h>
|
||||
|
||||
namespace {
|
||||
|
||||
uint32_t toHeapCaps(uint16_t capabilityFlags) {
|
||||
uint32_t caps = 0;
|
||||
if (capabilityFlags & MEMORY_CAPABILITY_INTERNAL) caps |= MALLOC_CAP_INTERNAL;
|
||||
if (capabilityFlags & MEMORY_CAPABILITY_EXTERNAL) caps |= MALLOC_CAP_SPIRAM;
|
||||
if (capabilityFlags & MEMORY_CAPABILITY_EXECUTABLE) caps |= MALLOC_CAP_EXEC;
|
||||
if (capabilityFlags & MEMORY_CAPABILITY_DMA) caps |= MALLOC_CAP_DMA;
|
||||
if (capabilityFlags & MEMORY_CAPABILITY_SIMD) caps |= MALLOC_CAP_SIMD;
|
||||
return caps;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
void* memory_alloc_with_policy(size_t size, const struct MemoryPolicy* policy) {
|
||||
uint32_t required_caps = toHeapCaps(policy->required);
|
||||
uint32_t desired_caps = toHeapCaps(policy->desired);
|
||||
|
||||
void* ptr;
|
||||
if (policy->alignment > 0) {
|
||||
ptr = heap_caps_aligned_alloc(policy->alignment, size, required_caps | desired_caps);
|
||||
if (ptr == nullptr && desired_caps != 0) {
|
||||
// Desired caps couldn't be satisfied alongside the required ones - retry with
|
||||
// required only, since desired is explicitly optional.
|
||||
ptr = heap_caps_aligned_alloc(policy->alignment, size, required_caps);
|
||||
}
|
||||
} else {
|
||||
ptr = heap_caps_malloc(size, required_caps | desired_caps);
|
||||
if (ptr == nullptr && desired_caps != 0) {
|
||||
ptr = heap_caps_malloc(size, required_caps);
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* memory_realloc_with_policy(void* ptr, size_t size, const struct MemoryPolicy* policy) {
|
||||
uint32_t required_caps = toHeapCaps(policy->required);
|
||||
uint32_t desired_caps = toHeapCaps(policy->desired);
|
||||
|
||||
// No aligned-realloc counterpart in the heap_caps API - policy->alignment is only honored
|
||||
// on fresh allocations (memory_alloc_with_policy/memory_calloc_with_policy).
|
||||
void* result = heap_caps_realloc(ptr, size, required_caps | desired_caps);
|
||||
if (result == nullptr && desired_caps != 0) {
|
||||
result = heap_caps_realloc(ptr, size, required_caps);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void* memory_calloc_with_policy(size_t count, size_t size, const struct MemoryPolicy* policy) {
|
||||
uint32_t required_caps = toHeapCaps(policy->required);
|
||||
uint32_t desired_caps = toHeapCaps(policy->desired);
|
||||
|
||||
void* ptr;
|
||||
if (policy->alignment > 0) {
|
||||
ptr = heap_caps_aligned_calloc(policy->alignment, count, size, required_caps | desired_caps);
|
||||
if (ptr == nullptr && desired_caps != 0) {
|
||||
ptr = heap_caps_aligned_calloc(policy->alignment, count, size, required_caps);
|
||||
}
|
||||
} else {
|
||||
ptr = heap_caps_calloc(count, size, required_caps | desired_caps);
|
||||
if (ptr == nullptr && desired_caps != 0) {
|
||||
ptr = heap_caps_calloc(count, size, required_caps);
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void memory_free(void* ptr) {
|
||||
heap_caps_free(ptr);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // ESP_PLATFORM
|
||||
@ -1,68 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include <tactility/memory.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
|
||||
// posix_memalign requires a power-of-2 alignment that's at least sizeof(void*).
|
||||
size_t normalizeAlignment(uint8_t alignment) {
|
||||
size_t result = alignment;
|
||||
if (result < sizeof(void*)) {
|
||||
result = sizeof(void*);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
// MEMORY_CAP_* flags are meaningless on the desktop simulator (no capability-restricted memory regions)
|
||||
// policy->required/desired are intentionally ignored here.
|
||||
void* memory_alloc_with_policy(size_t size, const struct MemoryPolicy* policy) {
|
||||
if (policy->alignment > 0) {
|
||||
void* ptr = nullptr;
|
||||
if (posix_memalign(&ptr, normalizeAlignment(policy->alignment), size) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void* memory_realloc_with_policy(void* ptr, size_t size, const struct MemoryPolicy* policy) {
|
||||
// Alignment can't be preserved across a POSIX realloc; only honored on fresh allocations
|
||||
// (memory_alloc_with_policy/memory_calloc_with_policy).
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
void* memory_calloc_with_policy(size_t count, size_t size, const struct MemoryPolicy* policy) {
|
||||
if (policy->alignment > 0) {
|
||||
size_t total_size = count * size;
|
||||
if (count != 0 && total_size / count != size) {
|
||||
// count * size overflowed - reject rather than under-allocating.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* ptr = nullptr;
|
||||
if (posix_memalign(&ptr, normalizeAlignment(policy->alignment), total_size) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
memset(ptr, 0, total_size);
|
||||
return ptr;
|
||||
}
|
||||
return calloc(count, size);
|
||||
}
|
||||
|
||||
void memory_free(void* ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // !ESP_PLATFORM
|
||||
@ -37,7 +37,6 @@
|
||||
#include <tactility/error.h>
|
||||
#include <tactility/filesystem/file_system.h>
|
||||
#include <tactility/filesystem/file_mutex.h>
|
||||
#include <tactility/memory.h>
|
||||
#include <tactility/module.h>
|
||||
#include <tactility/wifi_auto_scan.h>
|
||||
#include <tactility/service/service_instance.h>
|
||||
@ -176,13 +175,6 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = {
|
||||
DEFINE_MODULE_SYMBOL(file_system_unmount),
|
||||
DEFINE_MODULE_SYMBOL(file_system_is_mounted),
|
||||
DEFINE_MODULE_SYMBOL(file_system_get_path),
|
||||
// memory
|
||||
DEFINE_MODULE_SYMBOL(MEMORY_POLICY_DEFAULT),
|
||||
DEFINE_MODULE_SYMBOL(memory_print_stats),
|
||||
DEFINE_MODULE_SYMBOL(memory_alloc_with_policy),
|
||||
DEFINE_MODULE_SYMBOL(memory_realloc_with_policy),
|
||||
DEFINE_MODULE_SYMBOL(memory_calloc_with_policy),
|
||||
DEFINE_MODULE_SYMBOL(memory_free),
|
||||
// drivers/gpio_controller
|
||||
DEFINE_MODULE_SYMBOL(gpio_descriptor_acquire),
|
||||
DEFINE_MODULE_SYMBOL(gpio_descriptor_release),
|
||||
|
||||
@ -1,83 +0,0 @@
|
||||
#include "doctest.h"
|
||||
#include <tactility/memory.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
TEST_CASE("MEMORY_POLICY_DEFAULT should have no requirements") {
|
||||
CHECK_EQ(MEMORY_POLICY_DEFAULT.required, 0);
|
||||
CHECK_EQ(MEMORY_POLICY_DEFAULT.desired, 0);
|
||||
CHECK_EQ(MEMORY_POLICY_DEFAULT.alignment, 0);
|
||||
}
|
||||
|
||||
TEST_CASE("memory_alloc should return usable memory") {
|
||||
void* ptr = memory_alloc(64);
|
||||
REQUIRE_NE(ptr, nullptr);
|
||||
memset(ptr, 0xAB, 64);
|
||||
CHECK_EQ(static_cast<uint8_t*>(ptr)[0], 0xAB);
|
||||
CHECK_EQ(static_cast<uint8_t*>(ptr)[63], 0xAB);
|
||||
memory_free(ptr);
|
||||
}
|
||||
|
||||
TEST_CASE("memory_calloc should zero-initialize memory") {
|
||||
auto* ptr = static_cast<uint8_t*>(memory_calloc(16, sizeof(uint8_t)));
|
||||
REQUIRE_NE(ptr, nullptr);
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
CHECK_EQ(ptr[i], 0);
|
||||
}
|
||||
memory_free(ptr);
|
||||
}
|
||||
|
||||
TEST_CASE("memory_realloc should preserve contents when growing") {
|
||||
auto* ptr = static_cast<uint8_t*>(memory_alloc(8));
|
||||
REQUIRE_NE(ptr, nullptr);
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
ptr[i] = i;
|
||||
}
|
||||
|
||||
auto* grown = static_cast<uint8_t*>(memory_realloc(ptr, 32));
|
||||
REQUIRE_NE(grown, nullptr);
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
CHECK_EQ(grown[i], i);
|
||||
}
|
||||
|
||||
memory_free(grown);
|
||||
}
|
||||
|
||||
TEST_CASE("memory_realloc with a NULL pointer should behave like an allocation") {
|
||||
void* ptr = memory_realloc(nullptr, 32);
|
||||
REQUIRE_NE(ptr, nullptr);
|
||||
memset(ptr, 0, 32);
|
||||
memory_free(ptr);
|
||||
}
|
||||
|
||||
TEST_CASE("memory_free with a NULL pointer should be a no-op") {
|
||||
memory_free(nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("memory_alloc_with_policy should honor a power-of-2 alignment") {
|
||||
MemoryPolicy policy = MEMORY_POLICY_DEFAULT;
|
||||
policy.alignment = 64;
|
||||
|
||||
void* ptr = memory_alloc_with_policy(128, &policy);
|
||||
REQUIRE_NE(ptr, nullptr);
|
||||
CHECK_EQ(reinterpret_cast<uintptr_t>(ptr) % 64, 0);
|
||||
memory_free(ptr);
|
||||
}
|
||||
|
||||
TEST_CASE("memory_calloc_with_policy should honor alignment and zero-initialize") {
|
||||
MemoryPolicy policy = MEMORY_POLICY_DEFAULT;
|
||||
policy.alignment = 32;
|
||||
|
||||
auto* ptr = static_cast<uint8_t*>(memory_calloc_with_policy(8, sizeof(uint32_t), &policy));
|
||||
REQUIRE_NE(ptr, nullptr);
|
||||
CHECK_EQ(reinterpret_cast<uintptr_t>(ptr) % 32, 0);
|
||||
for (size_t i = 0; i < 8 * sizeof(uint32_t); i++) {
|
||||
CHECK_EQ(ptr[i], 0);
|
||||
}
|
||||
memory_free(ptr);
|
||||
}
|
||||
|
||||
TEST_CASE("memory_print_stats should not crash") {
|
||||
memory_print_stats();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user