Kernel and TactilitySDK improvements (#479)

* **New Features**
  * Expanded public device and driver APIs (accessors, sync, lifecycle, binding) and a module construct+start helper.
  * Added kernel symbol registry and new exported symbols (lvgl, C++ nothrow, I2S APIs, additional math funcs).

* **Refactor**
  * Renamed device traversal APIs for consistency (device_for_each*).
  * Moved inline helpers to explicit public declarations.

* **Chores**
  * Replaced several shell release scripts with Python-based SDK release tooling.
* **Style**
  * Header naming consistency fixes.
This commit is contained in:
Ken Van Hoeylandt
2026-02-03 23:24:37 +01:00
committed by GitHub
parent 9cc96fd32b
commit 9a672a30ff
29 changed files with 684 additions and 217 deletions
+138 -77
View File
@@ -3,18 +3,18 @@
#pragma once
#include "driver.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "error.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "error.h"
#include <tactility/concurrent/mutex.h>
#ifdef __cplusplus
extern "C" {
#endif
struct Driver;
struct DevicePrivate;
@@ -64,9 +64,9 @@ struct CompatibleDevice {
/**
* Initialize the properties of a device.
*
* @param[in] device a device with all non-internal properties set
* @retval ERROR_OUT_OF_MEMORY
* @retval ERROR_NONE
* @param[in,out] device a device with all non-internal properties set
* @retval ERROR_OUT_OF_MEMORY if internal data allocation failed
* @retval ERROR_NONE on success
*/
error_t device_construct(struct Device* device);
@@ -74,31 +74,20 @@ error_t device_construct(struct Device* device);
* Deinitialize the properties of a device.
* This fails when a device is busy or has children.
*
* @param[in] device
* @retval ERROR_INVALID_STATE
* @retval ERROR_NONE
* @param[in,out] device non-null device pointer
* @retval ERROR_INVALID_STATE if the device is busy or has children
* @retval ERROR_NONE on success
*/
error_t device_destruct(struct Device* device);
/**
* Indicates whether the device is in a state where its API is available
*
* @param[in] device non-null device pointer
* @return true if the device is ready for use
*/
static inline bool device_is_ready(const struct Device* device) {
return device->internal.state.started;
}
/**
* Register a device to all relevant systems:
* - the global ledger
* - its parent (if any)
* - a bus (if any)
*
* @param[in] device non-null device pointer
* @retval ERROR_INVALID_STATE
* @retval ERROR_NONE
* @param[in,out] device non-null device pointer
* @retval ERROR_INVALID_STATE if the device is already added
* @retval ERROR_NONE on success
*/
error_t device_add(struct Device* device);
@@ -106,12 +95,11 @@ error_t device_add(struct Device* device);
* Deregister a device. Remove it from all relevant systems:
* - the global ledger
* - its parent (if any)
* - a bus (if any)
*
* @param[in] device non-null device pointer
* @retval ERROR_INVALID_STATE
* @retval ERROR_NOT_FOUND
* @retval ERROR_NONE
* @param[in,out] device non-null device pointer
* @retval ERROR_INVALID_STATE if the device is still started
* @retval ERROR_NOT_FOUND if the device was not found in the system
* @retval ERROR_NONE on success
*/
error_t device_remove(struct Device* device);
@@ -119,91 +107,164 @@ error_t device_remove(struct Device* device);
* Attach the driver.
*
* @warning must call device_construct() and device_add() first
* @param device
* @retval ERROR_INVALID_STATE
* @param[in,out] device non-null device pointer
* @retval ERROR_INVALID_STATE if the device is already started or not added
* @retval ERROR_RESOURCE when driver binding fails
* @retval ERROR_NONE
* @retval ERROR_NONE on success
*/
error_t device_start(struct Device* device);
/**
* Detach the driver.
*
* @param device
* @retval ERROR_INVALID_STATE
* @param[in,out] device non-null device pointer
* @retval ERROR_INVALID_STATE if the device is not started
* @retval ERROR_RESOURCE when driver unbinding fails
* @retval ERROR_NONE
* @retval ERROR_NONE on success
*/
error_t device_stop(struct Device* device);
/**
* Construct and add a device with the given compatible string.
*
* @param[in,out] device non-NULL device
* @param[in] compatible compatible string
* @retval ERROR_NONE on success
* @retval error_t error code on failure
*/
error_t device_construct_add_start(struct Device* device, const char* compatible);
/**
* Construct and add a device with the given compatible string.
*
* @param[in,out] device non-NULL device
* @param[in] compatible compatible string
* @retval ERROR_NONE on success
* @retval error_t error code on failure
*/
error_t device_construct_add(struct Device* device, const char* compatible);
/**
* Set or unset a parent.
*
* @warning must call before device_add()
* @param device non-NULL device
* @param parent nullable parent device
* @param[in,out] device non-NULL device
* @param[in] parent nullable parent device
*/
void device_set_parent(struct Device* device, struct Device* parent);
error_t device_construct_add(struct Device* device, const char* compatible);
/**
* Set the driver for a device.
*
* @warning must call before device_add()
* @param[in,out] device non-NULL device
* @param[in] driver nullable driver
*/
void device_set_driver(struct Device* device, struct Driver* driver);
error_t device_construct_add_start(struct Device* device, const char* compatible);
/**
* Get the driver for a device.
*
* @param[in] device non-null device pointer
* @return the driver, or NULL if the device has no driver
*/
struct Driver* device_get_driver(struct Device* device);
static inline void device_set_driver(struct Device* device, struct Driver* driver) {
device->internal.driver = driver;
}
/**
* Get the parent device of a device.
*
* @param[in] device non-null device pointer
* @return the parent device, or NULL if the device has no parent
*/
struct Device* device_get_parent(struct Device* device);
static inline struct Driver* device_get_driver(struct Device* device) {
return device->internal.driver;
}
/**
* Indicates whether the device is in a state where its API is available
*
* @param[in] device non-null device pointer
* @return true if the device is ready for use
*/
bool device_is_ready(const struct Device* device);
static inline void device_set_driver_data(struct Device* device, void* driver_data) {
device->internal.driver_data = driver_data;
}
/**
* Set the driver data for a device.
*
* @param[in,out] device non-null device pointer
* @param[in] driver_data the driver data
*/
void device_set_driver_data(struct Device* device, void* driver_data);
static inline void* device_get_driver_data(struct Device* device) {
return device->internal.driver_data;
}
/**
* Get the driver data for a device.
*
* @param[in] device non-null device pointer
* @return the driver data
*/
void* device_get_driver_data(struct Device* device);
static inline bool device_is_added(const struct Device* device) {
return device->internal.state.added;
}
/**
* Indicates whether the device has been added to the system.
*
* @param[in] device non-null device pointer
* @return true if the device has been added
*/
bool device_is_added(const struct Device* device);
static inline void device_lock(struct Device* device) {
mutex_lock(&device->internal.mutex);
}
/**
* Lock the device for exclusive access.
*
* @param[in,out] device non-null device pointer
*/
void device_lock(struct Device* device);
static inline bool device_try_lock(struct Device* device) {
return mutex_try_lock(&device->internal.mutex);
}
/**
* Try to lock the device for exclusive access.
*
* @param[in,out] device non-null device pointer
* @return true if the device was locked successfully
*/
bool device_try_lock(struct Device* device);
static inline void device_unlock(struct Device* device) {
mutex_unlock(&device->internal.mutex);
}
/**
* Unlock the device.
*
* @param[in,out] device non-null device pointer
*/
void device_unlock(struct Device* device);
/**
* Get the type of a device.
*
* @param[in] device non-null device pointer
* @return the device type
*/
const struct DeviceType* device_get_type(struct Device* device);
static inline const struct DeviceType* device_get_type(struct Device* device) {
return device->internal.driver ? device->internal.driver->device_type : NULL;
}
/**
* Iterate through all the known devices
* @param callback_context the parameter to pass to the callback. NULL is valid.
* @param on_device the function to call for each filtered device. return true to continue iterating or false to stop.
*
* @param[in] callback_context the parameter to pass to the callback. NULL is valid.
* @param[in] on_device the function to call for each filtered device. return true to continue iterating or false to stop.
*/
void for_each_device(void* callback_context, bool(*on_device)(struct Device* device, void* context));
void device_for_each(void* callback_context, bool(*on_device)(struct Device* device, void* context));
/**
* Iterate through all the child devices of the specified device
* @param callbackContext the parameter to pass to the callback. NULL is valid.
* @param on_device the function to call for each filtered device. return true to continue iterating or false to stop.
*
* @param[in] device non-null device pointer
* @param[in] callback_context the parameter to pass to the callback. NULL is valid.
* @param[in] on_device the function to call for each filtered device. return true to continue iterating or false to stop.
*/
void for_each_device_child(struct Device* device, void* callbackContext, bool(*on_device)(struct Device* device, void* context));
void device_for_each_child(struct Device* device, void* callback_context, bool(*on_device)(struct Device* device, void* context));
/**
* Iterate through all the known devices of a specific type
* @param type the type to filter
* @param callbackContext the parameter to pass to the callback. NULL is valid.
* @param on_device the function to call for each filtered device. return true to continue iterating or false to stop.
*
* @param[in] type the type to filter
* @param[in] callback_context the parameter to pass to the callback. NULL is valid.
* @param[in] on_device the function to call for each filtered device. return true to continue iterating or false to stop.
*/
void for_each_device_of_type(const struct DeviceType* type, void* callbackContext, bool(*on_device)(struct Device* device, void* context));
void device_for_each_of_type(const struct DeviceType* type, void* callback_context, bool(*on_device)(struct Device* device, void* context));
#ifdef __cplusplus
}
+82 -3
View File
@@ -33,29 +33,108 @@ struct Driver {
struct DriverPrivate* driver_private;
};
/**
* @brief Construct a driver.
*
* This initializes the internal state of the driver.
*
* @param driver The driver to construct.
* @return ERROR_NONE if successful, or an error code otherwise.
*/
error_t driver_construct(struct Driver* driver);
/**
* @brief Destruct a driver.
*
* This cleans up the internal state of the driver.
*
* @param driver The driver to destruct.
* @return ERROR_NONE if successful, or an error code otherwise.
*/
error_t driver_destruct(struct Driver* driver);
/**
* @brief Add a driver to the system.
*
* This registers the driver so it can be used to bind to devices.
*
* @param driver The driver to add.
* @return ERROR_NONE if successful, or an error code otherwise.
*/
error_t driver_add(struct Driver* driver);
/**
* @brief Remove a driver from the system.
*
* This unregisters the driver.
*
* @param driver The driver to remove.
* @return ERROR_NONE if successful, or an error code otherwise.
*/
error_t driver_remove(struct Driver* driver);
/**
* @brief Construct and add a driver to the system.
*
* @param driver The driver to construct and add.
* @return ERROR_NONE if successful, or an error code otherwise.
*/
error_t driver_construct_add(struct Driver* driver);
/**
* @brief Remove and destruct a driver.
*
* @param driver The driver to remove and destruct.
* @return ERROR_NONE if successful, or an error code otherwise.
*/
error_t driver_remove_destruct(struct Driver* driver);
/**
* @brief Bind a driver to a device.
*
* This calls the driver's start_device function and increments the driver's use count.
*
* @param driver The driver to bind.
* @param device The device to bind to.
* @return ERROR_NONE if successful, or an error code otherwise.
*/
error_t driver_bind(struct Driver* driver, struct Device* device);
/**
* @brief Unbind a driver from a device.
*
* This calls the driver's stop_device function and decrements the driver's use count.
*
* @param driver The driver to unbind.
* @param device The device to unbind from.
* @return ERROR_NONE if successful, or an error code otherwise.
*/
error_t driver_unbind(struct Driver* driver, struct Device* device);
/**
* @brief Check if a driver is compatible with a given string.
*
* @param driver The driver to check.
* @param compatible The compatibility string to check.
* @return true if compatible, false otherwise.
*/
bool driver_is_compatible(struct Driver* driver, const char* compatible);
/**
* @brief Find a driver compatible with a given string.
*
* @param compatible The compatibility string to find.
* @return The compatible driver, or NULL if not found.
*/
struct Driver* driver_find_compatible(const char* compatible);
static inline const struct DeviceType* driver_get_device_type(struct Driver* driver) {
return driver->device_type;
}
/**
* @brief Get the device type of a driver.
*
* @param driver The driver to get the device type from.
* @return The device type of the driver.
*/
const struct DeviceType* driver_get_device_type(struct Driver* driver);
#ifdef __cplusplus
}
+14 -8
View File
@@ -59,7 +59,6 @@ struct Module {
*/
const struct ModuleSymbol* symbols;
struct {
bool started;
} internal;
@@ -101,13 +100,6 @@ error_t module_remove(struct Module* module);
*/
error_t module_start(struct Module* module);
/**
* @brief Check if the module is started.
* @param module module to check
* @return true if the module is started, false otherwise
*/
bool module_is_started(struct Module* module);
/**
* @brief Stop the module.
* @param module module
@@ -115,6 +107,20 @@ bool module_is_started(struct Module* module);
*/
error_t module_stop(struct Module* module);
/**
* @brief Construct, add and start a module.
* @param module module
* @return ERROR_NONE if successful
*/
error_t module_construct_add_start(struct Module* module);
/**
* @brief Check if the module is started.
* @param module module to check
* @return true if the module is started, false otherwise
*/
bool module_is_started(struct Module* module);
/**
* @brief Resolve a symbol from the module.
* @details The module must be started for symbol resolution to succeed.