mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 10:53:17 +00:00
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:
parent
9cc96fd32b
commit
9a672a30ff
2
.github/actions/build-sdk/action.yml
vendored
2
.github/actions/build-sdk/action.yml
vendored
@ -29,7 +29,7 @@ runs:
|
|||||||
env:
|
env:
|
||||||
# NOTE: Update with ESP-IDF!
|
# NOTE: Update with ESP-IDF!
|
||||||
ESP_IDF_VERSION: '5.5'
|
ESP_IDF_VERSION: '5.5'
|
||||||
run: Buildscripts/release-sdk.sh release/TactilitySDK
|
run: python Buildscripts/release-sdk.py release/TactilitySDK
|
||||||
- name: 'Upload Artifact'
|
- name: 'Upload Artifact'
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
idf_component_register(
|
|
||||||
INCLUDE_DIRS "Libraries/TactilityC/Include" "Libraries/lvgl/Include" "Libraries/TactilityFreeRtos/Include"
|
|
||||||
REQUIRES esp_timer
|
|
||||||
)
|
|
||||||
|
|
||||||
add_prebuilt_library(TactilityC Libraries/TactilityC/Binary/libTactilityC.a)
|
|
||||||
add_prebuilt_library(lvgl Libraries/lvgl/Binary/liblvgl.a)
|
|
||||||
|
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE TactilityC)
|
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE lvgl)
|
|
||||||
19
Buildscripts/TactilitySDK/CMakeLists.txt
Normal file
19
Buildscripts/TactilitySDK/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
idf_component_register(
|
||||||
|
INCLUDE_DIRS
|
||||||
|
"Libraries/TactilityC/Include"
|
||||||
|
"Libraries/TactilityKernel/Include"
|
||||||
|
"Libraries/TactilityFreeRtos/Include"
|
||||||
|
"Libraries/lvgl/Include"
|
||||||
|
"Libraries/lvgl-module/Include"
|
||||||
|
REQUIRES esp_timer
|
||||||
|
)
|
||||||
|
|
||||||
|
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(lvgl-module Libraries/lvgl-module/Binary/liblvgl-module.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 lvgl-module)
|
||||||
BIN
Buildscripts/__pycache__/release-sdk.cpython-314.pyc
Normal file
BIN
Buildscripts/__pycache__/release-sdk.cpython-314.pyc
Normal file
Binary file not shown.
@ -1,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
config_idf_target=`cat sdkconfig | grep CONFIG_IDF_TARGET=`
|
|
||||||
echo ${config_idf_target:19:-1}
|
|
||||||
58
Buildscripts/release-sdk-current.py
Executable file
58
Buildscripts/release-sdk-current.py
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def get_idf_target():
|
||||||
|
try:
|
||||||
|
with open("sdkconfig", "r") as f:
|
||||||
|
for line in f:
|
||||||
|
if line.startswith("CONFIG_IDF_TARGET="):
|
||||||
|
# CONFIG_IDF_TARGET="esp32s3" -> esp32s3
|
||||||
|
return line.split('=')[1].strip().strip('"')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("sdkconfig not found")
|
||||||
|
return None
|
||||||
|
return None
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# 1. Get idf_target
|
||||||
|
idf_target = get_idf_target()
|
||||||
|
if not idf_target:
|
||||||
|
print("Could not determine IDF target from sdkconfig")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# 2. Get version
|
||||||
|
try:
|
||||||
|
with open("version.txt", "r") as f:
|
||||||
|
version = f.read().strip()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("version.txt not found")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# 3. Construct sdk_path
|
||||||
|
# release/TactilitySDK/${version}-${idf_target}/TactilitySDK
|
||||||
|
sdk_path = os.path.join("release", "TactilitySDK", f"{version}-{idf_target}", "TactilitySDK")
|
||||||
|
|
||||||
|
# 4. Cleanup sdk_path
|
||||||
|
if os.path.exists(sdk_path):
|
||||||
|
print(f"Cleaning up {sdk_path}")
|
||||||
|
shutil.rmtree(sdk_path)
|
||||||
|
|
||||||
|
os.makedirs(sdk_path, exist_ok=True)
|
||||||
|
|
||||||
|
# 5. Call release-sdk.py
|
||||||
|
# Note: Using sys.executable to ensure we use the same python interpreter
|
||||||
|
script_path = os.path.join("Buildscripts", "release-sdk.py")
|
||||||
|
print(f"Running {script_path} {sdk_path}")
|
||||||
|
|
||||||
|
result = subprocess.run([sys.executable, script_path, sdk_path])
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f"Error: {script_path} failed with return code {result.returncode}")
|
||||||
|
sys.exit(result.returncode)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@ -1,14 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#
|
|
||||||
# Description: Releases the current build files as an SDK in release/TactilitySDK-[platform]
|
|
||||||
# This deployment is used when compiling new SDK features for apps.
|
|
||||||
#
|
|
||||||
|
|
||||||
idf_target=`Buildscripts/get-idf-target.sh`
|
|
||||||
version=`cat version.txt`
|
|
||||||
sdk_path="release/TactilitySDK/${version}-${idf_target}/TactilitySDK"
|
|
||||||
mkdir -p ${sdk_path}
|
|
||||||
echo Cleaning up ${sdk_path}
|
|
||||||
rm -rf ${sdk_path}
|
|
||||||
./Buildscripts/release-sdk.sh ${sdk_path}
|
|
||||||
117
Buildscripts/release-sdk.py
Normal file
117
Buildscripts/release-sdk.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import glob
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def map_copy(mappings, target_base):
|
||||||
|
"""
|
||||||
|
Helper function to map input files/directories to output files/directories.
|
||||||
|
mappings: list of dicts with 'src' (glob pattern) and 'dst' (relative to target_base or absolute)
|
||||||
|
'src' can be a single file or a directory (if it ends with /).
|
||||||
|
"""
|
||||||
|
for mapping in mappings:
|
||||||
|
src_pattern = mapping['src']
|
||||||
|
dst_rel = mapping['dst']
|
||||||
|
dst_path = os.path.join(target_base, dst_rel)
|
||||||
|
|
||||||
|
# To preserve directory structure, we need to know where the wildcard starts
|
||||||
|
# or have a way to determine the "base" of the search.
|
||||||
|
# We'll split the pattern into a fixed base and a pattern part.
|
||||||
|
|
||||||
|
# Simple heuristic: find the first occurrence of '*' or '?'
|
||||||
|
wildcard_idx = -1
|
||||||
|
for i, char in enumerate(src_pattern):
|
||||||
|
if char in '*?':
|
||||||
|
wildcard_idx = i
|
||||||
|
break
|
||||||
|
|
||||||
|
if wildcard_idx != -1:
|
||||||
|
# Found a wildcard. The base is the directory containing it.
|
||||||
|
pattern_base = os.path.dirname(src_pattern[:wildcard_idx])
|
||||||
|
else:
|
||||||
|
# No wildcard. If it's a directory, we might want to preserve its name?
|
||||||
|
# For now, let's treat no-wildcard as no relative structure needed.
|
||||||
|
pattern_base = None
|
||||||
|
|
||||||
|
src_files = glob.glob(src_pattern, recursive=True)
|
||||||
|
if not src_files:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for src in src_files:
|
||||||
|
if os.path.isdir(src):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if pattern_base and src.startswith(pattern_base):
|
||||||
|
# Calculate relative path from the base of the glob pattern
|
||||||
|
rel_src = os.path.relpath(src, pattern_base)
|
||||||
|
# If dst_rel ends with /, it's a target directory
|
||||||
|
if dst_rel.endswith('/') or os.path.isdir(dst_path):
|
||||||
|
final_dst = os.path.join(dst_path, rel_src)
|
||||||
|
else:
|
||||||
|
# If dst_rel is a file, we can't really preserve structure
|
||||||
|
# unless we join it. But usually it's a dir if structure is preserved.
|
||||||
|
final_dst = dst_path
|
||||||
|
else:
|
||||||
|
final_dst = dst_path if not (dst_rel.endswith('/') or os.path.isdir(dst_path)) else os.path.join(dst_path, os.path.basename(src))
|
||||||
|
|
||||||
|
os.makedirs(os.path.dirname(final_dst), exist_ok=True)
|
||||||
|
shutil.copy2(src, final_dst)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: release-sdk.py [target_path]")
|
||||||
|
print("Example: release-sdk.py release/TactilitySDK")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
target_path = os.path.abspath(sys.argv[1])
|
||||||
|
os.makedirs(target_path, exist_ok=True)
|
||||||
|
|
||||||
|
# Mapping logic
|
||||||
|
mappings = [
|
||||||
|
{'src': 'version.txt', 'dst': ''},
|
||||||
|
# TactilityC
|
||||||
|
{'src': 'build/esp-idf/TactilityC/libTactilityC.a', 'dst': 'Libraries/TactilityC/Binary/'},
|
||||||
|
{'src': 'TactilityC/Include/*', 'dst': 'Libraries/TactilityC/Include/'},
|
||||||
|
{'src': 'TactilityC/CMakeLists.txt', 'dst': 'Libraries/TactilityC/'},
|
||||||
|
{'src': 'TactilityC/LICENSE*.*', 'dst': 'Libraries/TactilityC/'},
|
||||||
|
# TactilityFreeRtos
|
||||||
|
{'src': 'TactilityFreeRtos/Include/**', 'dst': 'Libraries/TactilityFreeRtos/Include/'},
|
||||||
|
{'src': 'TactilityFreeRtos/CMakeLists.txt', 'dst': 'Libraries/TactilityFreeRtos/'},
|
||||||
|
{'src': 'TactilityFreeRtos/LICENSE*.*', 'dst': 'Libraries/TactilityFreeRtos/'},
|
||||||
|
# TactilityKernel
|
||||||
|
{'src': 'build/esp-idf/TactilityKernel/libTactilityKernel.a', 'dst': 'Libraries/TactilityKernel/Binary/'},
|
||||||
|
{'src': 'TactilityKernel/Include/**', 'dst': 'Libraries/TactilityKernel/Include/'},
|
||||||
|
{'src': 'TactilityKernel/CMakeLists.txt', 'dst': 'Libraries/TactilityKernel/'},
|
||||||
|
{'src': 'TactilityKernel/LICENSE*.*', 'dst': 'Libraries/TactilityKernel/'},
|
||||||
|
# lvgl-module
|
||||||
|
{'src': 'build/esp-idf/lvgl-module/liblvgl-module.a', 'dst': 'Libraries/lvgl-module/Binary/'},
|
||||||
|
{'src': 'Modules/lvgl-module/Include/**', 'dst': 'Libraries/lvgl-module/Include/'},
|
||||||
|
{'src': 'Modules/lvgl-module/CMakeLists.txt', 'dst': 'Libraries/lvgl-module/'},
|
||||||
|
{'src': 'Modules/lvgl-module/LICENSE*.*', 'dst': 'Libraries/lvgl-module/'},
|
||||||
|
# lvgl (basics)
|
||||||
|
{'src': 'build/esp-idf/lvgl/liblvgl.a', 'dst': 'Libraries/lvgl/Binary/'},
|
||||||
|
{'src': 'Libraries/lvgl/lvgl.h', 'dst': 'Libraries/lvgl/Include/'},
|
||||||
|
{'src': 'Libraries/lvgl/lv_version.h', 'dst': 'Libraries/lvgl/Include/'},
|
||||||
|
{'src': 'Libraries/lvgl/LICENCE.txt', 'dst': 'Libraries/lvgl/LICENSE.txt'},
|
||||||
|
{'src': 'Libraries/lvgl/src/lv_conf_kconfig.h', 'dst': 'Libraries/lvgl/Include/lv_conf.h'},
|
||||||
|
{'src': 'Libraries/lvgl/src/**/*.h', 'dst': 'Libraries/lvgl/Include/src/'},
|
||||||
|
# elf_loader
|
||||||
|
{'src': 'Libraries/elf_loader/elf_loader.cmake', 'dst': 'Libraries/elf_loader/'},
|
||||||
|
{'src': 'Libraries/elf_loader/license.txt', 'dst': 'Libraries/elf_loader/'},
|
||||||
|
# Final scripts
|
||||||
|
{'src': 'Buildscripts/TactilitySDK/TactilitySDK.cmake', 'dst': ''},
|
||||||
|
{'src': 'Buildscripts/TactilitySDK/CMakeLists.txt', 'dst': ''},
|
||||||
|
]
|
||||||
|
|
||||||
|
map_copy(mappings, target_path)
|
||||||
|
|
||||||
|
# Output ESP-IDF SDK version to file
|
||||||
|
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
|
||||||
|
with open(os.path.join(target_path, "idf-version.txt"), "a") as f:
|
||||||
|
f.write(esp_idf_version)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@ -1,58 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#
|
|
||||||
# Usage: release-sdk.sh [target_path]
|
|
||||||
# Example: release.sh release/TactilitySDK
|
|
||||||
# Description: Releases the current build files as an SDK in the specified folder.
|
|
||||||
#
|
|
||||||
|
|
||||||
target_path=$1
|
|
||||||
|
|
||||||
mkdir -p $target_path
|
|
||||||
|
|
||||||
build_dir=`pwd`
|
|
||||||
library_path=$target_path/Libraries
|
|
||||||
|
|
||||||
cp version.txt $target_path
|
|
||||||
|
|
||||||
# TactilityC
|
|
||||||
tactility_library_path=$library_path/TactilityC
|
|
||||||
mkdir -p $tactility_library_path/Binary
|
|
||||||
cp build/esp-idf/TactilityC/libTactilityC.a $tactility_library_path/Binary/
|
|
||||||
mkdir -p $tactility_library_path/Include
|
|
||||||
find_target_dir="$build_dir/$tactility_library_path"
|
|
||||||
cp TactilityC/Include/* "$find_target_dir/Include"
|
|
||||||
cp TactilityC/*.txt "$find_target_dir"
|
|
||||||
cp TactilityC/*.md "$find_target_dir"
|
|
||||||
|
|
||||||
# TactilityFreeRtos
|
|
||||||
tactilityfreertos_library_path=$library_path/TactilityFreeRtos
|
|
||||||
mkdir -p "$tactilityfreertos_library_path/Include"
|
|
||||||
find_target_dir="$build_dir/$tactilityfreertos_library_path"
|
|
||||||
cp -r TactilityFreeRtos/Include/* "$find_target_dir/Include"
|
|
||||||
cp TactilityFreeRtos/*.txt "$find_target_dir"
|
|
||||||
cp TactilityFreeRtos/*.md "$find_target_dir"
|
|
||||||
|
|
||||||
# lvgl
|
|
||||||
lvgl_library_path=$library_path/lvgl
|
|
||||||
mkdir -p "$lvgl_library_path/Binary"
|
|
||||||
mkdir -p "$lvgl_library_path/Include"
|
|
||||||
cp build/esp-idf/lvgl/liblvgl.a "$lvgl_library_path/Binary/"
|
|
||||||
find_target_dir="$build_dir/$lvgl_library_path"
|
|
||||||
cd Libraries/lvgl
|
|
||||||
find src/ -name '*.h' | cpio -pdm "$find_target_dir/Include"
|
|
||||||
cd -
|
|
||||||
cp Libraries/lvgl/lvgl.h "$find_target_dir/Include"
|
|
||||||
cp Libraries/lvgl/lv_version.h "$find_target_dir/Include"
|
|
||||||
cp Libraries/lvgl/LICENCE.txt "$lvgl_library_path/LICENSE.txt"
|
|
||||||
cp Libraries/lvgl/src/lv_conf_kconfig.h "$lvgl_library_path/Include/lv_conf.h"
|
|
||||||
|
|
||||||
# elf_loader
|
|
||||||
elf_loader_library_path="$library_path/elf_loader"
|
|
||||||
mkdir -p "$elf_loader_library_path"
|
|
||||||
cp Libraries/elf_loader/elf_loader.cmake "$elf_loader_library_path/"
|
|
||||||
cp Libraries/elf_loader/license.txt "$elf_loader_library_path/"
|
|
||||||
|
|
||||||
cp Buildscripts/CMake/TactilitySDK.cmake "$target_path/"
|
|
||||||
cp Buildscripts/CMake/CMakeLists.txt "$target_path/"
|
|
||||||
printf '%s' "$ESP_IDF_VERSION" >> "$target_path/idf-version.txt"
|
|
||||||
@ -62,7 +62,7 @@ void hal_device_for_each_of_type(HalDeviceType type, void* context, bool(*onDevi
|
|||||||
.onDeviceParam = onDevice
|
.onDeviceParam = onDevice
|
||||||
};
|
};
|
||||||
|
|
||||||
for_each_device_of_type(&HAL_DEVICE_TYPE, &internal_context, [](Device* device, void* context){
|
device_for_each_of_type(&HAL_DEVICE_TYPE, &internal_context, [](Device* device, void* context){
|
||||||
auto* hal_device_private = GET_DATA(device);
|
auto* hal_device_private = GET_DATA(device);
|
||||||
auto* internal_context = static_cast<InternalContext*>(context);
|
auto* internal_context = static_cast<InternalContext*>(context);
|
||||||
auto hal_device_type = getHalDeviceType(hal_device_private->halDevice->getType());
|
auto hal_device_type = getHalDeviceType(hal_device_private->halDevice->getType());
|
||||||
|
|||||||
@ -122,7 +122,7 @@ std::vector<std::shared_ptr<Device>> findDevices(Device::Type type) {
|
|||||||
|
|
||||||
std::vector<std::shared_ptr<Device>> getDevices() {
|
std::vector<std::shared_ptr<Device>> getDevices() {
|
||||||
std::vector<std::shared_ptr<Device>> devices;
|
std::vector<std::shared_ptr<Device>> devices;
|
||||||
for_each_device_of_type(&HAL_DEVICE_TYPE, &devices ,[](auto* kernelDevice, auto* context) {
|
device_for_each_of_type(&HAL_DEVICE_TYPE, &devices ,[](auto* kernelDevice, auto* context) {
|
||||||
auto devices_ptr = static_cast<std::vector<std::shared_ptr<Device>>*>(context);
|
auto devices_ptr = static_cast<std::vector<std::shared_ptr<Device>>*>(context);
|
||||||
auto hal_device = hal_device_get_device(kernelDevice);
|
auto hal_device = hal_device_get_device(kernelDevice);
|
||||||
(*devices_ptr).push_back(hal_device);
|
(*devices_ptr).push_back(hal_device);
|
||||||
|
|||||||
@ -162,7 +162,9 @@ const struct ModuleSymbol lvgl_module_symbols[] = {
|
|||||||
DEFINE_MODULE_SYMBOL(lv_buttonmatrix_set_selected_button),
|
DEFINE_MODULE_SYMBOL(lv_buttonmatrix_set_selected_button),
|
||||||
// lv_canvas
|
// lv_canvas
|
||||||
DEFINE_MODULE_SYMBOL(lv_canvas_create),
|
DEFINE_MODULE_SYMBOL(lv_canvas_create),
|
||||||
|
DEFINE_MODULE_SYMBOL(lv_canvas_fill_bg),
|
||||||
DEFINE_MODULE_SYMBOL(lv_canvas_set_draw_buf),
|
DEFINE_MODULE_SYMBOL(lv_canvas_set_draw_buf),
|
||||||
|
DEFINE_MODULE_SYMBOL(lv_canvas_set_buffer),
|
||||||
DEFINE_MODULE_SYMBOL(lv_canvas_set_px),
|
DEFINE_MODULE_SYMBOL(lv_canvas_set_px),
|
||||||
// lv_label
|
// lv_label
|
||||||
DEFINE_MODULE_SYMBOL(lv_label_create),
|
DEFINE_MODULE_SYMBOL(lv_label_create),
|
||||||
@ -314,6 +316,8 @@ const struct ModuleSymbol lvgl_module_symbols[] = {
|
|||||||
DEFINE_MODULE_SYMBOL(lv_line_create),
|
DEFINE_MODULE_SYMBOL(lv_line_create),
|
||||||
DEFINE_MODULE_SYMBOL(lv_line_set_points),
|
DEFINE_MODULE_SYMBOL(lv_line_set_points),
|
||||||
DEFINE_MODULE_SYMBOL(lv_line_set_points_mutable),
|
DEFINE_MODULE_SYMBOL(lv_line_set_points_mutable),
|
||||||
|
DEFINE_MODULE_SYMBOL(lv_tick_get),
|
||||||
|
DEFINE_MODULE_SYMBOL(lv_tick_elaps),
|
||||||
// lv_slider
|
// lv_slider
|
||||||
DEFINE_MODULE_SYMBOL(lv_slider_create),
|
DEFINE_MODULE_SYMBOL(lv_slider_create),
|
||||||
DEFINE_MODULE_SYMBOL(lv_slider_get_value),
|
DEFINE_MODULE_SYMBOL(lv_slider_get_value),
|
||||||
|
|||||||
@ -32,7 +32,7 @@ Device* findDevice(i2c_port_t port) {
|
|||||||
.device = nullptr
|
.device = nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
for_each_device_of_type(&I2C_CONTROLLER_TYPE, ¶ms, [](auto* device, auto* context) {
|
device_for_each_of_type(&I2C_CONTROLLER_TYPE, ¶ms, [](auto* device, auto* context) {
|
||||||
auto* params_ptr = (Params*)context;
|
auto* params_ptr = (Params*)context;
|
||||||
auto* driver = device_get_driver(device);
|
auto* driver = device_get_driver(device);
|
||||||
if (driver == nullptr) return true;
|
if (driver == nullptr) return true;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include <private/elf_symbol.h>
|
#include <private/elf_symbol.h>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include <symbols/cplusplus.h>
|
#include <symbols/cplusplus.h>
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ extern "C" {
|
|||||||
const esp_elfsym cplusplus_symbols[] = {
|
const esp_elfsym cplusplus_symbols[] = {
|
||||||
ESP_ELFSYM_EXPORT(_Znwj), // operator new(unsigned int)
|
ESP_ELFSYM_EXPORT(_Znwj), // operator new(unsigned int)
|
||||||
ESP_ELFSYM_EXPORT(_ZdlPvj), // operator delete(void*, unsigned int)
|
ESP_ELFSYM_EXPORT(_ZdlPvj), // operator delete(void*, unsigned int)
|
||||||
|
{ "_ZSt7nothrow", (void*)&std::nothrow },
|
||||||
// cxx_guards
|
// cxx_guards
|
||||||
ESP_ELFSYM_EXPORT(__cxa_pure_virtual), // class-related, see https://arobenko.github.io/bare_metal_cpp/
|
ESP_ELFSYM_EXPORT(__cxa_pure_virtual), // class-related, see https://arobenko.github.io/bare_metal_cpp/
|
||||||
ESP_ELFSYM_EXPORT(__cxa_guard_acquire),
|
ESP_ELFSYM_EXPORT(__cxa_guard_acquire),
|
||||||
|
|||||||
@ -9,7 +9,7 @@ using namespace tt::hal;
|
|||||||
|
|
||||||
static Device* find_first_gpio_controller() {
|
static Device* find_first_gpio_controller() {
|
||||||
Device* device_result = nullptr;
|
Device* device_result = nullptr;
|
||||||
for_each_device_of_type(&GPIO_CONTROLLER_TYPE, &device_result, [](Device* device, void* context) {
|
device_for_each_of_type(&GPIO_CONTROLLER_TYPE, &device_result, [](Device* device, void* context) {
|
||||||
if (device_is_ready(device)) {
|
if (device_is_ready(device)) {
|
||||||
auto** device_result_ptr = static_cast<Device**>(context);
|
auto** device_result_ptr = static_cast<Device**>(context);
|
||||||
*device_result_ptr = device;
|
*device_result_ptr = device;
|
||||||
|
|||||||
@ -51,6 +51,9 @@
|
|||||||
|
|
||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
|
|
||||||
|
#include <driver/i2s_common.h>
|
||||||
|
#include <driver/i2s_std.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
extern double __floatsidf(int x);
|
extern double __floatsidf(int x);
|
||||||
@ -97,19 +100,32 @@ const esp_elfsym main_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(ceil),
|
ESP_ELFSYM_EXPORT(ceil),
|
||||||
ESP_ELFSYM_EXPORT(fabs),
|
ESP_ELFSYM_EXPORT(fabs),
|
||||||
ESP_ELFSYM_EXPORT(floor),
|
ESP_ELFSYM_EXPORT(floor),
|
||||||
|
ESP_ELFSYM_EXPORT(sinf),
|
||||||
|
ESP_ELFSYM_EXPORT(cosf),
|
||||||
|
ESP_ELFSYM_EXPORT(fabsf),
|
||||||
#ifndef _REENT_ONLY
|
#ifndef _REENT_ONLY
|
||||||
ESP_ELFSYM_EXPORT(acos),
|
ESP_ELFSYM_EXPORT(acos),
|
||||||
|
ESP_ELFSYM_EXPORT(acosf),
|
||||||
ESP_ELFSYM_EXPORT(asin),
|
ESP_ELFSYM_EXPORT(asin),
|
||||||
|
ESP_ELFSYM_EXPORT(asinf),
|
||||||
ESP_ELFSYM_EXPORT(atan2),
|
ESP_ELFSYM_EXPORT(atan2),
|
||||||
ESP_ELFSYM_EXPORT(cos),
|
ESP_ELFSYM_EXPORT(atan2f),
|
||||||
ESP_ELFSYM_EXPORT(sinh),
|
ESP_ELFSYM_EXPORT(sinh),
|
||||||
|
ESP_ELFSYM_EXPORT(sinhf),
|
||||||
ESP_ELFSYM_EXPORT(exp),
|
ESP_ELFSYM_EXPORT(exp),
|
||||||
|
ESP_ELFSYM_EXPORT(expf),
|
||||||
ESP_ELFSYM_EXPORT(ldexp),
|
ESP_ELFSYM_EXPORT(ldexp),
|
||||||
|
ESP_ELFSYM_EXPORT(ldexpf),
|
||||||
ESP_ELFSYM_EXPORT(log),
|
ESP_ELFSYM_EXPORT(log),
|
||||||
|
ESP_ELFSYM_EXPORT(logf),
|
||||||
ESP_ELFSYM_EXPORT(log10),
|
ESP_ELFSYM_EXPORT(log10),
|
||||||
|
ESP_ELFSYM_EXPORT(log10f),
|
||||||
ESP_ELFSYM_EXPORT(pow),
|
ESP_ELFSYM_EXPORT(pow),
|
||||||
|
ESP_ELFSYM_EXPORT(powf),
|
||||||
ESP_ELFSYM_EXPORT(sqrt),
|
ESP_ELFSYM_EXPORT(sqrt),
|
||||||
|
ESP_ELFSYM_EXPORT(sqrtf),
|
||||||
ESP_ELFSYM_EXPORT(fmod),
|
ESP_ELFSYM_EXPORT(fmod),
|
||||||
|
ESP_ELFSYM_EXPORT(fmodf),
|
||||||
#endif
|
#endif
|
||||||
// sys/errno.h
|
// sys/errno.h
|
||||||
ESP_ELFSYM_EXPORT(__errno),
|
ESP_ELFSYM_EXPORT(__errno),
|
||||||
@ -339,6 +355,22 @@ const esp_elfsym main_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(esp_netif_get_handle_from_ifkey),
|
ESP_ELFSYM_EXPORT(esp_netif_get_handle_from_ifkey),
|
||||||
// Locale
|
// Locale
|
||||||
ESP_ELFSYM_EXPORT(localeconv),
|
ESP_ELFSYM_EXPORT(localeconv),
|
||||||
|
//i2s_common.h
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_new_channel),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_del_channel),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_enable),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_disable),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_write),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_get_info),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_read),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_register_event_callback),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_preload_data),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_tune_rate),
|
||||||
|
//i2s_std.h
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_init_std_mode),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_reconfig_std_clock),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_reconfig_std_slot),
|
||||||
|
ESP_ELFSYM_EXPORT(i2s_channel_reconfig_std_gpio),
|
||||||
// delimiter
|
// delimiter
|
||||||
ESP_ELFSYM_END
|
ESP_ELFSYM_END
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,18 +3,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
#include "error.h"
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "error.h"
|
|
||||||
#include <tactility/concurrent/mutex.h>
|
#include <tactility/concurrent/mutex.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
struct Driver;
|
struct Driver;
|
||||||
struct DevicePrivate;
|
struct DevicePrivate;
|
||||||
|
|
||||||
@ -64,9 +64,9 @@ struct CompatibleDevice {
|
|||||||
/**
|
/**
|
||||||
* Initialize the properties of a device.
|
* Initialize the properties of a device.
|
||||||
*
|
*
|
||||||
* @param[in] device a device with all non-internal properties set
|
* @param[in,out] device a device with all non-internal properties set
|
||||||
* @retval ERROR_OUT_OF_MEMORY
|
* @retval ERROR_OUT_OF_MEMORY if internal data allocation failed
|
||||||
* @retval ERROR_NONE
|
* @retval ERROR_NONE on success
|
||||||
*/
|
*/
|
||||||
error_t device_construct(struct Device* device);
|
error_t device_construct(struct Device* device);
|
||||||
|
|
||||||
@ -74,31 +74,20 @@ error_t device_construct(struct Device* device);
|
|||||||
* Deinitialize the properties of a device.
|
* Deinitialize the properties of a device.
|
||||||
* This fails when a device is busy or has children.
|
* This fails when a device is busy or has children.
|
||||||
*
|
*
|
||||||
* @param[in] device
|
* @param[in,out] device non-null device pointer
|
||||||
* @retval ERROR_INVALID_STATE
|
* @retval ERROR_INVALID_STATE if the device is busy or has children
|
||||||
* @retval ERROR_NONE
|
* @retval ERROR_NONE on success
|
||||||
*/
|
*/
|
||||||
error_t device_destruct(struct Device* device);
|
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:
|
* Register a device to all relevant systems:
|
||||||
* - the global ledger
|
* - the global ledger
|
||||||
* - its parent (if any)
|
* - its parent (if any)
|
||||||
* - a bus (if any)
|
|
||||||
*
|
*
|
||||||
* @param[in] device non-null device pointer
|
* @param[in,out] device non-null device pointer
|
||||||
* @retval ERROR_INVALID_STATE
|
* @retval ERROR_INVALID_STATE if the device is already added
|
||||||
* @retval ERROR_NONE
|
* @retval ERROR_NONE on success
|
||||||
*/
|
*/
|
||||||
error_t device_add(struct Device* device);
|
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:
|
* Deregister a device. Remove it from all relevant systems:
|
||||||
* - the global ledger
|
* - the global ledger
|
||||||
* - its parent (if any)
|
* - its parent (if any)
|
||||||
* - a bus (if any)
|
|
||||||
*
|
*
|
||||||
* @param[in] device non-null device pointer
|
* @param[in,out] device non-null device pointer
|
||||||
* @retval ERROR_INVALID_STATE
|
* @retval ERROR_INVALID_STATE if the device is still started
|
||||||
* @retval ERROR_NOT_FOUND
|
* @retval ERROR_NOT_FOUND if the device was not found in the system
|
||||||
* @retval ERROR_NONE
|
* @retval ERROR_NONE on success
|
||||||
*/
|
*/
|
||||||
error_t device_remove(struct Device* device);
|
error_t device_remove(struct Device* device);
|
||||||
|
|
||||||
@ -119,91 +107,164 @@ error_t device_remove(struct Device* device);
|
|||||||
* Attach the driver.
|
* Attach the driver.
|
||||||
*
|
*
|
||||||
* @warning must call device_construct() and device_add() first
|
* @warning must call device_construct() and device_add() first
|
||||||
* @param device
|
* @param[in,out] device non-null device pointer
|
||||||
* @retval ERROR_INVALID_STATE
|
* @retval ERROR_INVALID_STATE if the device is already started or not added
|
||||||
* @retval ERROR_RESOURCE when driver binding fails
|
* @retval ERROR_RESOURCE when driver binding fails
|
||||||
* @retval ERROR_NONE
|
* @retval ERROR_NONE on success
|
||||||
*/
|
*/
|
||||||
error_t device_start(struct Device* device);
|
error_t device_start(struct Device* device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach the driver.
|
* Detach the driver.
|
||||||
*
|
*
|
||||||
* @param device
|
* @param[in,out] device non-null device pointer
|
||||||
* @retval ERROR_INVALID_STATE
|
* @retval ERROR_INVALID_STATE if the device is not started
|
||||||
* @retval ERROR_RESOURCE when driver unbinding fails
|
* @retval ERROR_RESOURCE when driver unbinding fails
|
||||||
* @retval ERROR_NONE
|
* @retval ERROR_NONE on success
|
||||||
*/
|
*/
|
||||||
error_t device_stop(struct Device* device);
|
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.
|
* Set or unset a parent.
|
||||||
|
*
|
||||||
* @warning must call before device_add()
|
* @warning must call before device_add()
|
||||||
* @param device non-NULL device
|
* @param[in,out] device non-NULL device
|
||||||
* @param parent nullable parent device
|
* @param[in] parent nullable parent device
|
||||||
*/
|
*/
|
||||||
void device_set_parent(struct Device* device, struct Device* parent);
|
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
|
* 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
|
* 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
|
* 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[in] type the type to filter
|
||||||
* @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_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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,29 +33,108 @@ struct Driver {
|
|||||||
struct DriverPrivate* driver_private;
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,7 +59,6 @@ struct Module {
|
|||||||
*/
|
*/
|
||||||
const struct ModuleSymbol* symbols;
|
const struct ModuleSymbol* symbols;
|
||||||
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool started;
|
bool started;
|
||||||
} internal;
|
} internal;
|
||||||
@ -101,13 +100,6 @@ error_t module_remove(struct Module* module);
|
|||||||
*/
|
*/
|
||||||
error_t module_start(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.
|
* @brief Stop the module.
|
||||||
* @param module module
|
* @param module module
|
||||||
@ -115,6 +107,20 @@ bool module_is_started(struct Module* module);
|
|||||||
*/
|
*/
|
||||||
error_t module_stop(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.
|
* @brief Resolve a symbol from the module.
|
||||||
* @details The module must be started for symbol resolution to succeed.
|
* @details The module must be started for symbol resolution to succeed.
|
||||||
|
|||||||
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
#include "tactility/error.h"
|
#include "tactility/error.h"
|
||||||
|
|
||||||
#include <tactility/concurrent/eventgroup.h>
|
#include <atomic>
|
||||||
|
#include <tactility/concurrent/event_group.h>
|
||||||
#include <tactility/concurrent/mutex.h>
|
#include <tactility/concurrent/mutex.h>
|
||||||
#include <tactility/log.h>
|
#include <tactility/log.h>
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#define TAG "Dispatcher"
|
#define TAG "Dispatcher"
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include <tactility/concurrent/eventgroup.h>
|
#include <tactility/concurrent/event_group.h>
|
||||||
#include <tactility/error.h>
|
#include <tactility/error.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@ -240,7 +240,51 @@ void device_set_parent(Device* device, Device* parent) {
|
|||||||
device->parent = parent;
|
device->parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void for_each_device(void* callback_context, bool(*on_device)(Device* device, void* context)) {
|
Device* device_get_parent(struct Device* device) {
|
||||||
|
return device->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void device_set_driver(struct Device* device, struct Driver* driver) {
|
||||||
|
device->internal.driver = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Driver* device_get_driver(struct Device* device) {
|
||||||
|
return device->internal.driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool device_is_ready(const struct Device* device) {
|
||||||
|
return device->internal.state.started;
|
||||||
|
}
|
||||||
|
|
||||||
|
void device_set_driver_data(struct Device* device, void* driver_data) {
|
||||||
|
device->internal.driver_data = driver_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* device_get_driver_data(struct Device* device) {
|
||||||
|
return device->internal.driver_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool device_is_added(const struct Device* device) {
|
||||||
|
return device->internal.state.added;
|
||||||
|
}
|
||||||
|
|
||||||
|
void device_lock(struct Device* device) {
|
||||||
|
mutex_lock(&device->internal.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool device_try_lock(struct Device* device) {
|
||||||
|
return mutex_try_lock(&device->internal.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void device_unlock(struct Device* device) {
|
||||||
|
mutex_unlock(&device->internal.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct DeviceType* device_get_type(struct Device* device) {
|
||||||
|
return device->internal.driver ? device->internal.driver->device_type : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void device_for_each(void* callback_context, bool(*on_device)(Device* device, void* context)) {
|
||||||
ledger_lock();
|
ledger_lock();
|
||||||
for (auto* device : ledger.devices) {
|
for (auto* device : ledger.devices) {
|
||||||
if (!on_device(device, callback_context)) {
|
if (!on_device(device, callback_context)) {
|
||||||
@ -250,7 +294,7 @@ void for_each_device(void* callback_context, bool(*on_device)(Device* device, vo
|
|||||||
ledger_unlock();
|
ledger_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void for_each_device_child(Device* device, void* callbackContext, bool(*on_device)(struct Device* device, void* context)) {
|
void device_for_each_child(Device* device, void* callbackContext, bool(*on_device)(struct Device* device, void* context)) {
|
||||||
auto* data = get_device_private(device);
|
auto* data = get_device_private(device);
|
||||||
for (auto* child_device : data->children) {
|
for (auto* child_device : data->children) {
|
||||||
if (!on_device(child_device, callbackContext)) {
|
if (!on_device(child_device, callbackContext)) {
|
||||||
@ -259,7 +303,7 @@ void for_each_device_child(Device* device, void* callbackContext, bool(*on_devic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void for_each_device_of_type(const DeviceType* type, void* callbackContext, bool(*on_device)(Device* device, void* context)) {
|
void device_for_each_of_type(const DeviceType* type, void* callbackContext, bool(*on_device)(Device* device, void* context)) {
|
||||||
ledger_lock();
|
ledger_lock();
|
||||||
for (auto* device : ledger.devices) {
|
for (auto* device : ledger.devices) {
|
||||||
auto* driver = device->internal.driver;
|
auto* driver = device->internal.driver;
|
||||||
|
|||||||
@ -199,4 +199,8 @@ error:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct DeviceType* driver_get_device_type(struct Driver* driver) {
|
||||||
|
return driver->device_type;
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@ -7,48 +7,41 @@ extern "C" {
|
|||||||
|
|
||||||
#define TAG "kernel"
|
#define TAG "kernel"
|
||||||
|
|
||||||
static error_t init_kernel_drivers() {
|
extern const struct ModuleSymbol KERNEL_SYMBOLS[];
|
||||||
|
|
||||||
|
static error_t start() {
|
||||||
extern Driver root_driver;
|
extern Driver root_driver;
|
||||||
if (driver_construct_add(&root_driver) != ERROR_NONE) return ERROR_RESOURCE;
|
if (driver_construct_add(&root_driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static error_t stop() {
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Module root_module = {
|
||||||
|
.name = "kernel",
|
||||||
|
.start = start,
|
||||||
|
.stop = stop,
|
||||||
|
.symbols = (const struct ModuleSymbol*)KERNEL_SYMBOLS
|
||||||
|
};
|
||||||
|
|
||||||
error_t kernel_init(struct Module* platform_module, struct Module* device_module, struct CompatibleDevice devicetree_devices[]) {
|
error_t kernel_init(struct Module* platform_module, struct Module* device_module, struct CompatibleDevice devicetree_devices[]) {
|
||||||
LOG_I(TAG, "init");
|
LOG_I(TAG, "init");
|
||||||
|
|
||||||
if (init_kernel_drivers() != ERROR_NONE) {
|
if (module_construct_add_start(&root_module) != ERROR_NONE) {
|
||||||
LOG_E(TAG, "init failed to init kernel drivers");
|
LOG_E(TAG, "root module init failed");
|
||||||
return ERROR_RESOURCE;
|
return ERROR_RESOURCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (module_construct(platform_module) != ERROR_NONE) {
|
if (module_construct_add_start(platform_module) != ERROR_NONE) {
|
||||||
LOG_E(TAG, "init failed to construct platform module");
|
LOG_E(TAG, "platform module init failed");
|
||||||
return ERROR_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module_add(platform_module) != ERROR_NONE) {
|
|
||||||
LOG_E(TAG, "init failed to add platform module");
|
|
||||||
return ERROR_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module_start(platform_module) != ERROR_NONE) {
|
|
||||||
LOG_E(TAG, "init failed to start platform module");
|
|
||||||
return ERROR_RESOURCE;
|
return ERROR_RESOURCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_module != nullptr) {
|
if (device_module != nullptr) {
|
||||||
if (module_construct(device_module) != ERROR_NONE) {
|
if (module_construct_add_start(device_module) != ERROR_NONE) {
|
||||||
LOG_E(TAG, "init failed to construct device module");
|
LOG_E(TAG, "device module init failed");
|
||||||
return ERROR_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module_add(device_module) != ERROR_NONE) {
|
|
||||||
LOG_E(TAG, "init failed to add device module");
|
|
||||||
return ERROR_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module_start(device_module) != ERROR_NONE) {
|
|
||||||
LOG_E(TAG, "init failed to start device module");
|
|
||||||
return ERROR_RESOURCE;
|
return ERROR_RESOURCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
126
TactilityKernel/Source/kernel_symbols.c
Normal file
126
TactilityKernel/Source/kernel_symbols.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#include <tactility/device.h>
|
||||||
|
#include <tactility/driver.h>
|
||||||
|
#include <tactility/drivers/i2c_controller.h>
|
||||||
|
#include <tactility/drivers/gpio_controller.h>
|
||||||
|
#include <tactility/concurrent/dispatcher.h>
|
||||||
|
#include <tactility/concurrent/event_group.h>
|
||||||
|
#include <tactility/concurrent/thread.h>
|
||||||
|
#include <tactility/concurrent/timer.h>
|
||||||
|
#include <tactility/error.h>
|
||||||
|
#include <tactility/log.h>
|
||||||
|
#include <tactility/module.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is a C file instead of C++, so we can import all headers as C code.
|
||||||
|
* The intent is to catch errors that only show up when compiling as C and not as C++.
|
||||||
|
* For example: wrong header includes.
|
||||||
|
*/
|
||||||
|
const struct ModuleSymbol KERNEL_SYMBOLS[] = {
|
||||||
|
// device
|
||||||
|
DEFINE_MODULE_SYMBOL(device_construct),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_destruct),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_add),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_remove),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_start),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_stop),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_construct_add),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_construct_add_start),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_set_parent),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_get_parent),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_set_driver),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_get_driver),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_set_driver_data),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_get_driver_data),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_is_added),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_is_ready),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_lock),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_try_lock),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_unlock),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_get_type),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_for_each),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_for_each_child),
|
||||||
|
DEFINE_MODULE_SYMBOL(device_for_each_of_type),
|
||||||
|
// driver
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_construct),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_destruct),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_add),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_remove),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_construct_add),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_remove_destruct),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_bind),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_unbind),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_is_compatible),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_find_compatible),
|
||||||
|
DEFINE_MODULE_SYMBOL(driver_get_device_type),
|
||||||
|
// drivers/gpio_controller
|
||||||
|
DEFINE_MODULE_SYMBOL(gpio_controller_set_level),
|
||||||
|
DEFINE_MODULE_SYMBOL(gpio_controller_get_level),
|
||||||
|
DEFINE_MODULE_SYMBOL(gpio_controller_set_options),
|
||||||
|
DEFINE_MODULE_SYMBOL(gpio_controller_get_options),
|
||||||
|
DEFINE_MODULE_SYMBOL(gpio_controller_get_pin_count),
|
||||||
|
// drivers/i2c_controller
|
||||||
|
DEFINE_MODULE_SYMBOL(i2c_controller_read),
|
||||||
|
DEFINE_MODULE_SYMBOL(i2c_controller_write),
|
||||||
|
DEFINE_MODULE_SYMBOL(i2c_controller_write_read),
|
||||||
|
DEFINE_MODULE_SYMBOL(i2c_controller_read_register),
|
||||||
|
DEFINE_MODULE_SYMBOL(i2c_controller_write_register),
|
||||||
|
DEFINE_MODULE_SYMBOL(i2c_controller_write_register_array),
|
||||||
|
DEFINE_MODULE_SYMBOL(i2c_controller_has_device_at_address),
|
||||||
|
// concurrent/dispatcher
|
||||||
|
DEFINE_MODULE_SYMBOL(dispatcher_alloc),
|
||||||
|
DEFINE_MODULE_SYMBOL(dispatcher_free),
|
||||||
|
DEFINE_MODULE_SYMBOL(dispatcher_dispatch_timed),
|
||||||
|
DEFINE_MODULE_SYMBOL(dispatcher_consume_timed),
|
||||||
|
// concurrent/event_group
|
||||||
|
DEFINE_MODULE_SYMBOL(event_group_set),
|
||||||
|
DEFINE_MODULE_SYMBOL(event_group_clear),
|
||||||
|
DEFINE_MODULE_SYMBOL(event_group_get),
|
||||||
|
DEFINE_MODULE_SYMBOL(event_group_wait),
|
||||||
|
// concurrent/thread
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_alloc),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_alloc_full),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_free),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_set_name),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_set_stack_size),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_set_affinity),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_set_main_function),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_set_priority),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_set_state_callback),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_get_state),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_start),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_join),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_get_task_handle),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_get_return_code),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_get_stack_space),
|
||||||
|
DEFINE_MODULE_SYMBOL(thread_get_current),
|
||||||
|
// concurrent/timer
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_alloc),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_free),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_start),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_stop),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_reset_with_interval),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_reset),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_is_running),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_get_expiry_time),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_set_pending_callback),
|
||||||
|
DEFINE_MODULE_SYMBOL(timer_set_callback_priority),
|
||||||
|
// error
|
||||||
|
DEFINE_MODULE_SYMBOL(error_to_string),
|
||||||
|
// log
|
||||||
|
#ifndef ESP_PLATFORM
|
||||||
|
DEFINE_MODULE_SYMBOL(log_generic),
|
||||||
|
#endif
|
||||||
|
// module
|
||||||
|
DEFINE_MODULE_SYMBOL(module_construct),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_destruct),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_add),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_remove),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_construct_add_start),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_start),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_stop),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_is_started),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_resolve_symbol),
|
||||||
|
DEFINE_MODULE_SYMBOL(module_resolve_symbol_global),
|
||||||
|
// terminator
|
||||||
|
MODULE_SYMBOL_TERMINATOR
|
||||||
|
};
|
||||||
@ -69,6 +69,14 @@ error_t module_stop(struct Module* module) {
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error_t module_construct_add_start(struct Module* module) {
|
||||||
|
error_t error = module_construct(module);
|
||||||
|
if (error != ERROR_NONE) return error;
|
||||||
|
error = module_add(module);
|
||||||
|
if (error != ERROR_NONE) return error;
|
||||||
|
return module_start(module);
|
||||||
|
}
|
||||||
|
|
||||||
bool module_resolve_symbol(Module* module, const char* symbol_name, uintptr_t* symbol_address) {
|
bool module_resolve_symbol(Module* module, const char* symbol_name, uintptr_t* symbol_address) {
|
||||||
if (!module_is_started(module)) return false;
|
if (!module_is_started(module)) return false;
|
||||||
auto* symbol_ptr = module->symbols;
|
auto* symbol_ptr = module->symbols;
|
||||||
|
|||||||
@ -41,7 +41,7 @@ TEST_CASE("device_add should add the device to the list of all devices") {
|
|||||||
|
|
||||||
// Gather all devices
|
// Gather all devices
|
||||||
std::vector<Device*> devices;
|
std::vector<Device*> devices;
|
||||||
for_each_device(&devices, [](auto* device, auto* context) {
|
device_for_each(&devices, [](auto* device, auto* context) {
|
||||||
auto* devices_ptr = static_cast<std::vector<Device*>*>(context);
|
auto* devices_ptr = static_cast<std::vector<Device*>*>(context);
|
||||||
devices_ptr->push_back(device);
|
devices_ptr->push_back(device);
|
||||||
return true;
|
return true;
|
||||||
@ -71,7 +71,7 @@ TEST_CASE("device_add should add the device to its parent") {
|
|||||||
|
|
||||||
// Gather all child devices
|
// Gather all child devices
|
||||||
std::vector<Device*> children;
|
std::vector<Device*> children;
|
||||||
for_each_device_child(&parent, &children, [](auto* child_device, auto* context) {
|
device_for_each_child(&parent, &children, [](auto* child_device, auto* context) {
|
||||||
auto* children_ptr = (std::vector<Device*>*)context;
|
auto* children_ptr = (std::vector<Device*>*)context;
|
||||||
children_ptr->push_back(child_device);
|
children_ptr->push_back(child_device);
|
||||||
return true;
|
return true;
|
||||||
@ -107,7 +107,7 @@ TEST_CASE("device_remove should remove it from the list of all devices") {
|
|||||||
|
|
||||||
// Gather all devices
|
// Gather all devices
|
||||||
std::vector<Device*> devices;
|
std::vector<Device*> devices;
|
||||||
for_each_device(&devices, [](auto* device, auto* context) {
|
device_for_each(&devices, [](auto* device, auto* context) {
|
||||||
auto* devices_ptr = (std::vector<Device*>*)context;
|
auto* devices_ptr = (std::vector<Device*>*)context;
|
||||||
devices_ptr->push_back(device);
|
devices_ptr->push_back(device);
|
||||||
return true;
|
return true;
|
||||||
@ -136,7 +136,7 @@ TEST_CASE("device_remove should remove the device from its parent") {
|
|||||||
|
|
||||||
// Gather all child devices
|
// Gather all child devices
|
||||||
std::vector<Device*> children;
|
std::vector<Device*> children;
|
||||||
for_each_device_child(&parent, &children, [](auto* child_device, auto* context) {
|
device_for_each_child(&parent, &children, [](auto* child_device, auto* context) {
|
||||||
auto* children_ptr = (std::vector<Device*>*)context;
|
auto* children_ptr = (std::vector<Device*>*)context;
|
||||||
children_ptr->push_back(child_device);
|
children_ptr->push_back(child_device);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user