mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 19:03:16 +00:00
SDK improvements (#352)
TactilityC additions for: - C randomization functions - Tactility app paths - Tactility locks
This commit is contained in:
parent
6dc4f698c9
commit
c7621b5e4c
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
## Lower Priority
|
## Lower Priority
|
||||||
|
|
||||||
|
- Rename `Lock::lock()` and `Lock::unlock()` to `Lock::acquire()` and `Lock::release()`?
|
||||||
- elf_loader: make main() entry-point optional (so we can build libraries, or have the `manifest` as a global symbol)
|
- elf_loader: make main() entry-point optional (so we can build libraries, or have the `manifest` as a global symbol)
|
||||||
- Implement system suspend that turns off the screen
|
- Implement system suspend that turns off the screen
|
||||||
- The boot button on some devices can be used as GPIO_NUM_0 at runtime
|
- The boot button on some devices can be used as GPIO_NUM_0 at runtime
|
||||||
|
|||||||
@ -34,7 +34,7 @@ public:
|
|||||||
* The path will not end with a "/".
|
* The path will not end with a "/".
|
||||||
* This is mainly used for core apps (system/boot/settings type).
|
* This is mainly used for core apps (system/boot/settings type).
|
||||||
*/
|
*/
|
||||||
std::string getAssetsDirectory() const;
|
std::string getAssetsPath() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You should not store configuration data here.
|
* You should not store configuration data here.
|
||||||
|
|||||||
@ -28,7 +28,7 @@ std::string AppPaths::getUserDataPath(const std::string& childPath) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string AppPaths::getAssetsDirectory() const {
|
std::string AppPaths::getAssetsPath() const {
|
||||||
if (manifest.appLocation.isInternal()) {
|
if (manifest.appLocation.isInternal()) {
|
||||||
return std::format("{}{}/app/{}/assets", PARTITION_PREFIX, file::SYSTEM_PARTITION_NAME, manifest.appId);
|
return std::format("{}{}/app/{}/assets", PARTITION_PREFIX, file::SYSTEM_PARTITION_NAME, manifest.appId);
|
||||||
} else {
|
} else {
|
||||||
@ -38,7 +38,7 @@ std::string AppPaths::getAssetsDirectory() const {
|
|||||||
|
|
||||||
std::string AppPaths::getAssetsPath(const std::string& childPath) const {
|
std::string AppPaths::getAssetsPath(const std::string& childPath) const {
|
||||||
assert(!childPath.starts_with('/'));
|
assert(!childPath.starts_with('/'));
|
||||||
return std::format("{}/{}", getAssetsDirectory(), childPath);
|
return std::format("{}/{}", getAssetsPath(), childPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include "tt_app_manifest.h"
|
#include "tt_app_manifest.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -7,7 +9,6 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void* AppHandle;
|
typedef void* AppHandle;
|
||||||
typedef void* AppPathsHandle;
|
|
||||||
|
|
||||||
/** @return the bundle that belongs to this application, or null if it wasn't started with parameters. */
|
/** @return the bundle that belongs to this application, or null if it wasn't started with parameters. */
|
||||||
BundleHandle _Nullable tt_app_get_parameters(AppHandle handle);
|
BundleHandle _Nullable tt_app_get_parameters(AppHandle handle);
|
||||||
@ -24,12 +25,39 @@ void tt_app_set_result(AppHandle handle, AppResult result, BundleHandle _Nullabl
|
|||||||
/** @return true if a result was set for this app context */
|
/** @return true if a result was set for this app context */
|
||||||
bool tt_app_has_result(AppHandle handle);
|
bool tt_app_has_result(AppHandle handle);
|
||||||
|
|
||||||
/** Get the path to the data directory of this app.
|
/** Get the path to the user data directory for this app.
|
||||||
|
* The app can store user-specific (mutable) data in there such as app settings.
|
||||||
* @param[in] handle the app handle
|
* @param[in] handle the app handle
|
||||||
* @param[out] buffer the output buffer (recommended size is 256 bytes)
|
* @param[out] buffer the output buffer (recommended size is 256 bytes)
|
||||||
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
|
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
|
||||||
*/
|
*/
|
||||||
void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t* size);
|
void tt_app_get_user_data_path(AppHandle handle, char* buffer, size_t* size);
|
||||||
|
|
||||||
|
/** Resolve a child path in the user directory of this app.
|
||||||
|
* The app can store user-specific (mutable) data in there such as app settings.
|
||||||
|
* @param[in] handle the app handle
|
||||||
|
* @param[in] childPath the child path to resolve
|
||||||
|
* @param[out] buffer the output buffer (recommended size is 256 bytes)
|
||||||
|
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
|
||||||
|
*/
|
||||||
|
void tt_app_get_user_data_child_path(AppHandle handle, const char* childPath, char* buffer, size_t* size);
|
||||||
|
|
||||||
|
/** Get the path to the assets directory of this app.
|
||||||
|
* The content in this path should be treated as read-only.
|
||||||
|
* @param[in] handle the app handle
|
||||||
|
* @param[out] buffer the output buffer (recommended size is 256 bytes)
|
||||||
|
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
|
||||||
|
*/
|
||||||
|
void tt_app_get_assets_path(AppHandle handle, char* buffer, size_t* size);
|
||||||
|
|
||||||
|
/** Resolve a child path in the assets directory of this app.
|
||||||
|
* The content in this path should be treated as read-only.
|
||||||
|
* @param[in] handle the app handle
|
||||||
|
* @param[in] childPath the child path to resolve
|
||||||
|
* @param[out] buffer the output buffer (recommended size is 256 bytes)
|
||||||
|
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
|
||||||
|
*/
|
||||||
|
void tt_app_get_assets_child_path(AppHandle handle, const char* childPath, char* buffer, size_t* size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an app by id.
|
* Start an app by id.
|
||||||
|
|||||||
13
TactilityC/Include/tt_file.h
Normal file
13
TactilityC/Include/tt_file.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tt_lock.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LockHandle tt_lock_alloc_for_file(const char* path);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
34
TactilityC/Include/tt_lock.h
Normal file
34
TactilityC/Include/tt_lock.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tt_kernel.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** A handle that represents a lock instance. A lock could be a Mutex or similar construct */
|
||||||
|
typedef void* LockHandle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to lock the lock.
|
||||||
|
* @param[in] handle the handle that represents the mutex instance
|
||||||
|
* @param[in] timeout the maximum amount of ticks to wait when trying to lock
|
||||||
|
* @return true when the lock was acquired
|
||||||
|
*/
|
||||||
|
bool tt_lock_acquire(LockHandle handle, TickType timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to unlock the lock.
|
||||||
|
* @param[in] handle the handle that represents the mutex instance
|
||||||
|
* @return true when the lock was unlocked
|
||||||
|
*/
|
||||||
|
bool tt_lock_release(LockHandle handle);
|
||||||
|
|
||||||
|
/** Free the memory for this lock
|
||||||
|
* @param[in] handle the handle that represents the mutex instance
|
||||||
|
*/
|
||||||
|
void tt_lock_free(LockHandle handle);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <freertos/FreeRTOS.h>
|
#include "tt_kernel.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -33,7 +33,7 @@ void tt_mutex_free(MutexHandle handle);
|
|||||||
* @param[in] timeout the maximum amount of ticks to wait when trying to lock
|
* @param[in] timeout the maximum amount of ticks to wait when trying to lock
|
||||||
* @return true when the lock was acquired
|
* @return true when the lock was acquired
|
||||||
*/
|
*/
|
||||||
bool tt_mutex_lock(MutexHandle handle, TickType_t timeout);
|
bool tt_mutex_lock(MutexHandle handle, TickType timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to unlock a mutex.
|
* Attempt to unlock a mutex.
|
||||||
|
|||||||
8
TactilityC/Private/tt_lock_private.h
Normal file
8
TactilityC/Private/tt_lock_private.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <Tactility/Lock.h>
|
||||||
|
|
||||||
|
struct LockHolder {
|
||||||
|
std::shared_ptr<tt::Lock> lock;
|
||||||
|
};
|
||||||
@ -2,6 +2,7 @@
|
|||||||
#include <Tactility/app/App.h>
|
#include <Tactility/app/App.h>
|
||||||
#include <Tactility/app/AppPaths.h>
|
#include <Tactility/app/AppPaths.h>
|
||||||
#include <Tactility/app/AppContext.h>
|
#include <Tactility/app/AppContext.h>
|
||||||
|
#include <Tactility/file/FileLock.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
@ -34,13 +35,13 @@ void tt_app_stop() {
|
|||||||
tt::app::stop();
|
tt::app::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t* size) {
|
void tt_app_get_user_data_path(AppHandle handle, char* buffer, size_t* size) {
|
||||||
assert(buffer != nullptr);
|
assert(buffer != nullptr);
|
||||||
assert(size != nullptr);
|
assert(size != nullptr);
|
||||||
assert(*size > 0);
|
assert(*size > 0);
|
||||||
auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
|
const auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
|
||||||
auto data_path = paths->getUserDataPath();
|
const auto data_path = paths->getUserDataPath();
|
||||||
auto expected_length = data_path.length() + 1;
|
const auto expected_length = data_path.length() + 1;
|
||||||
if (*size < expected_length) {
|
if (*size < expected_length) {
|
||||||
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", *size, expected_length);
|
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", *size, expected_length);
|
||||||
*size = 0;
|
*size = 0;
|
||||||
@ -52,4 +53,59 @@ void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t* size
|
|||||||
*size = data_path.length();
|
*size = data_path.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tt_app_get_user_data_child_path(AppHandle handle, const char* childPath, char* buffer, size_t* size) {
|
||||||
|
assert(buffer != nullptr);
|
||||||
|
assert(size != nullptr);
|
||||||
|
assert(*size > 0);
|
||||||
|
const auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
|
||||||
|
const auto resolved_path = paths->getUserDataPath(childPath);
|
||||||
|
const auto resolved_path_length = resolved_path.length();
|
||||||
|
if (*size < (resolved_path_length + 1)) {
|
||||||
|
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", *size, (resolved_path_length + 1));
|
||||||
|
*size = 0;
|
||||||
|
buffer[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(buffer, resolved_path.c_str());
|
||||||
|
*size = resolved_path_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tt_app_get_assets_path(AppHandle handle, char* buffer, size_t* size) {
|
||||||
|
assert(buffer != nullptr);
|
||||||
|
assert(size != nullptr);
|
||||||
|
assert(*size > 0);
|
||||||
|
const auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
|
||||||
|
const auto assets_path = paths->getAssetsPath();
|
||||||
|
const auto expected_length = assets_path.length() + 1;
|
||||||
|
if (*size < expected_length) {
|
||||||
|
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", *size, expected_length);
|
||||||
|
*size = 0;
|
||||||
|
buffer[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(buffer, assets_path.c_str());
|
||||||
|
*size = assets_path.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tt_app_get_assets_child_path(AppHandle handle, const char* childPath, char* buffer, size_t* size) {
|
||||||
|
assert(buffer != nullptr);
|
||||||
|
assert(size != nullptr);
|
||||||
|
assert(*size > 0);
|
||||||
|
const auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
|
||||||
|
const auto resolved_path = paths->getAssetsPath(childPath);
|
||||||
|
const auto resolved_path_length = resolved_path.length();
|
||||||
|
if (*size < (resolved_path_length + 1)) {
|
||||||
|
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", *size, (resolved_path_length + 1));
|
||||||
|
*size = 0;
|
||||||
|
buffer[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(buffer, resolved_path.c_str());
|
||||||
|
*size = resolved_path_length;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
13
TactilityC/Source/tt_file.cpp
Normal file
13
TactilityC/Source/tt_file.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <tt_file.h>
|
||||||
|
#include <tt_lock_private.h>
|
||||||
|
#include <Tactility/file/FileLock.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
LockHandle tt_lock_alloc_for_file(const char* path) {
|
||||||
|
auto lock = tt::file::getLock(path);
|
||||||
|
auto holder = new LockHolder(lock);
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -38,6 +38,7 @@
|
|||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
#include <tt_file.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
@ -54,6 +55,9 @@ const esp_elfsym elf_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(calloc),
|
ESP_ELFSYM_EXPORT(calloc),
|
||||||
ESP_ELFSYM_EXPORT(realloc),
|
ESP_ELFSYM_EXPORT(realloc),
|
||||||
ESP_ELFSYM_EXPORT(free),
|
ESP_ELFSYM_EXPORT(free),
|
||||||
|
ESP_ELFSYM_EXPORT(rand),
|
||||||
|
ESP_ELFSYM_EXPORT(srand),
|
||||||
|
ESP_ELFSYM_EXPORT(rand_r),
|
||||||
// unistd.h
|
// unistd.h
|
||||||
ESP_ELFSYM_EXPORT(usleep),
|
ESP_ELFSYM_EXPORT(usleep),
|
||||||
ESP_ELFSYM_EXPORT(sleep),
|
ESP_ELFSYM_EXPORT(sleep),
|
||||||
@ -116,6 +120,7 @@ const esp_elfsym elf_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(snprintf),
|
ESP_ELFSYM_EXPORT(snprintf),
|
||||||
ESP_ELFSYM_EXPORT(sprintf),
|
ESP_ELFSYM_EXPORT(sprintf),
|
||||||
ESP_ELFSYM_EXPORT(vsprintf),
|
ESP_ELFSYM_EXPORT(vsprintf),
|
||||||
|
ESP_ELFSYM_EXPORT(vsnprintf),
|
||||||
// cstring
|
// cstring
|
||||||
ESP_ELFSYM_EXPORT(strlen),
|
ESP_ELFSYM_EXPORT(strlen),
|
||||||
ESP_ELFSYM_EXPORT(strcmp),
|
ESP_ELFSYM_EXPORT(strcmp),
|
||||||
@ -225,7 +230,14 @@ const esp_elfsym elf_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(tt_app_selectiondialog_get_result_index),
|
ESP_ELFSYM_EXPORT(tt_app_selectiondialog_get_result_index),
|
||||||
ESP_ELFSYM_EXPORT(tt_app_alertdialog_start),
|
ESP_ELFSYM_EXPORT(tt_app_alertdialog_start),
|
||||||
ESP_ELFSYM_EXPORT(tt_app_alertdialog_get_result_index),
|
ESP_ELFSYM_EXPORT(tt_app_alertdialog_get_result_index),
|
||||||
ESP_ELFSYM_EXPORT(tt_app_get_data_directory),
|
ESP_ELFSYM_EXPORT(tt_app_get_user_data_path),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_app_get_user_data_child_path),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_app_get_assets_path),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_app_get_assets_child_path),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_lock_alloc_for_file),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_lock_acquire),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_lock_release),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_lock_free),
|
||||||
ESP_ELFSYM_EXPORT(tt_bundle_alloc),
|
ESP_ELFSYM_EXPORT(tt_bundle_alloc),
|
||||||
ESP_ELFSYM_EXPORT(tt_bundle_free),
|
ESP_ELFSYM_EXPORT(tt_bundle_free),
|
||||||
ESP_ELFSYM_EXPORT(tt_bundle_opt_bool),
|
ESP_ELFSYM_EXPORT(tt_bundle_opt_bool),
|
||||||
|
|||||||
21
TactilityC/Source/tt_lock.cpp
Normal file
21
TactilityC/Source/tt_lock.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <tt_lock.h>
|
||||||
|
#include <tt_lock_private.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
bool tt_lock_acquire(LockHandle handle, TickType timeout) {
|
||||||
|
auto holder = static_cast<LockHolder*>(handle);
|
||||||
|
return holder->lock->lock(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tt_lock_release(LockHandle handle) {
|
||||||
|
auto holder = static_cast<LockHolder*>(handle);
|
||||||
|
return holder->lock->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tt_lock_free(LockHandle handle) {
|
||||||
|
auto holder = static_cast<LockHolder*>(handle);
|
||||||
|
delete holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,11 +5,11 @@ extern "C" {
|
|||||||
|
|
||||||
#define HANDLE_AS_MUTEX(handle) ((tt::Mutex*)(handle))
|
#define HANDLE_AS_MUTEX(handle) ((tt::Mutex*)(handle))
|
||||||
|
|
||||||
MutexHandle tt_mutex_alloc(enum TtMutexType type) {
|
MutexHandle tt_mutex_alloc(TtMutexType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TtMutexType::MUTEX_TYPE_NORMAL:
|
case MUTEX_TYPE_NORMAL:
|
||||||
return new tt::Mutex(tt::Mutex::Type::Normal);
|
return new tt::Mutex(tt::Mutex::Type::Normal);
|
||||||
case TtMutexType::MUTEX_TYPE_RECURSIVE:
|
case MUTEX_TYPE_RECURSIVE:
|
||||||
return new tt::Mutex(tt::Mutex::Type::Recursive);
|
return new tt::Mutex(tt::Mutex::Type::Recursive);
|
||||||
default:
|
default:
|
||||||
tt_crash("Type not supported");
|
tt_crash("Type not supported");
|
||||||
@ -20,8 +20,8 @@ void tt_mutex_free(MutexHandle handle) {
|
|||||||
delete HANDLE_AS_MUTEX(handle);
|
delete HANDLE_AS_MUTEX(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tt_mutex_lock(MutexHandle handle, TickType_t timeout) {
|
bool tt_mutex_lock(MutexHandle handle, TickType timeout) {
|
||||||
return HANDLE_AS_MUTEX(handle)->lock((TickType_t)timeout);
|
return HANDLE_AS_MUTEX(handle)->lock(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tt_mutex_unlock(MutexHandle handle) {
|
bool tt_mutex_unlock(MutexHandle handle) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user