From cd7ffd3cb19661bf7dc183c4ffe92d4501b12a70 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Tue, 20 Jan 2026 23:33:41 +0100 Subject: [PATCH] WIP --- .../devicetree-compiler/source/generator.py | 101 +++++---- .../Source/bindings/tlora_pager.h | 15 ++ .../Source/drivers/TloraPager.cpp | 26 +++ .../Source/drivers/TloraPager.h | 11 + .../Source/drivers/tlora_pager.c | 18 -- .../Source/drivers/tlora_pager.h | 22 -- .../lilygo-tlora-pager/lilygo,tlora_pager.dts | 6 +- Devices/simulator/simulator.dts | 3 +- .../include/Tactility/bindings/esp32_gpio.h | 14 ++ .../include/Tactility/bindings/esp32_i2c.h | 14 ++ .../include/Tactility/drivers/Esp32Gpio.h | 15 ++ .../include/Tactility/drivers/Esp32I2c.h | 19 ++ .../include/tactility/drivers/esp32_gpio.h | 22 -- .../include/tactility/drivers/esp32_i2c.h | 28 --- .../source/{esp32_gpio.c => Esp32Gpio.cpp} | 55 +++-- Drivers/drivers-esp/source/Esp32I2c.cpp | 90 ++++++++ Drivers/drivers-esp/source/esp32_i2c.c | 47 ---- Firmware/Source/Main.cpp | 15 +- Tactility/Include/Tactility/Tactility.h | 4 +- Tactility/Source/Tactility.cpp | 7 +- core/include/Tactility/Bus.h | 49 +++++ core/include/Tactility/Device.h | 163 ++++++++++++++ core/include/Tactility/Driver.h | 40 ++++ core/include/Tactility/Error.h | 10 + .../FreeRTOS/FreeRTOS.h} | 0 .../freertos => Tactility/FreeRTOS}/README.md | 0 .../FreeRTOS}/event_groups.h | 0 .../freertos => Tactility/FreeRTOS}/port.h | 2 +- .../freertos => Tactility/FreeRTOS}/queue.h | 0 core/include/Tactility/FreeRTOS/semphr.h | 9 + .../freertos => Tactility/FreeRTOS}/task.h | 0 .../freertos => Tactility/FreeRTOS}/timers.h | 0 .../{tactility/log.h => Tactility/Log.h} | 22 +- core/include/Tactility/bindings/bindings.h | 8 + core/include/Tactility/bindings/gpio.h | 3 + core/include/Tactility/bindings/root.h | 7 + core/include/Tactility/concurrent/Mutex.h | 48 +++++ .../Tactility/concurrent/RecursiveMutex.h | 46 ++++ .../gpio.h => Tactility/drivers/Gpio.h} | 22 +- .../Tactility/drivers/GpioController.h | 28 +++ .../include/Tactility/drivers/I2cController.h | 26 +++ .../root.h => Tactility/drivers/Root.h} | 8 +- core/include/tactility/device.h | 111 ---------- .../tactility/drivers/gpio_controller.h | 28 --- .../tactility/drivers/i2c_controller.h | 26 --- core/include/tactility/freertos/semaphore.h | 19 -- core/source/Bus.cpp | 116 ++++++++++ core/source/Device.cpp | 202 ++++++++++++++++++ core/source/Driver.cpp | 146 +++++++++++++ core/source/{log.c => Log.cpp} | 4 +- core/source/device.c | 129 ----------- core/source/drivers/GpioController.cpp | 28 +++ core/source/drivers/I2cController.cpp | 23 ++ core/source/drivers/Root.cpp | 15 ++ core/source/drivers/gpio_controller.c | 19 -- core/source/drivers/i2c_controller.c | 15 -- core/source/drivers/root.c | 3 - 57 files changed, 1309 insertions(+), 598 deletions(-) create mode 100644 Devices/lilygo-tlora-pager/Source/bindings/tlora_pager.h create mode 100644 Devices/lilygo-tlora-pager/Source/drivers/TloraPager.cpp create mode 100644 Devices/lilygo-tlora-pager/Source/drivers/TloraPager.h delete mode 100644 Devices/lilygo-tlora-pager/Source/drivers/tlora_pager.c delete mode 100644 Devices/lilygo-tlora-pager/Source/drivers/tlora_pager.h create mode 100644 Drivers/drivers-esp/include/Tactility/bindings/esp32_gpio.h create mode 100644 Drivers/drivers-esp/include/Tactility/bindings/esp32_i2c.h create mode 100644 Drivers/drivers-esp/include/Tactility/drivers/Esp32Gpio.h create mode 100644 Drivers/drivers-esp/include/Tactility/drivers/Esp32I2c.h delete mode 100644 Drivers/drivers-esp/include/tactility/drivers/esp32_gpio.h delete mode 100644 Drivers/drivers-esp/include/tactility/drivers/esp32_i2c.h rename Drivers/drivers-esp/source/{esp32_gpio.c => Esp32Gpio.cpp} (59%) create mode 100644 Drivers/drivers-esp/source/Esp32I2c.cpp delete mode 100644 Drivers/drivers-esp/source/esp32_i2c.c create mode 100644 core/include/Tactility/Bus.h create mode 100644 core/include/Tactility/Device.h create mode 100644 core/include/Tactility/Driver.h create mode 100644 core/include/Tactility/Error.h rename core/include/{tactility/freertos/freertos.h => Tactility/FreeRTOS/FreeRTOS.h} (100%) rename core/include/{tactility/freertos => Tactility/FreeRTOS}/README.md (100%) rename core/include/{tactility/freertos => Tactility/FreeRTOS}/event_groups.h (100%) rename core/include/{tactility/freertos => Tactility/FreeRTOS}/port.h (78%) rename core/include/{tactility/freertos => Tactility/FreeRTOS}/queue.h (100%) create mode 100644 core/include/Tactility/FreeRTOS/semphr.h rename core/include/{tactility/freertos => Tactility/FreeRTOS}/task.h (100%) rename core/include/{tactility/freertos => Tactility/FreeRTOS}/timers.h (100%) rename core/include/{tactility/log.h => Tactility/Log.h} (51%) create mode 100644 core/include/Tactility/bindings/bindings.h create mode 100644 core/include/Tactility/bindings/gpio.h create mode 100644 core/include/Tactility/bindings/root.h create mode 100644 core/include/Tactility/concurrent/Mutex.h create mode 100644 core/include/Tactility/concurrent/RecursiveMutex.h rename core/include/{tactility/drivers/gpio.h => Tactility/drivers/Gpio.h} (80%) create mode 100644 core/include/Tactility/drivers/GpioController.h create mode 100644 core/include/Tactility/drivers/I2cController.h rename core/include/{tactility/drivers/root.h => Tactility/drivers/Root.h} (52%) delete mode 100644 core/include/tactility/device.h delete mode 100644 core/include/tactility/drivers/gpio_controller.h delete mode 100644 core/include/tactility/drivers/i2c_controller.h delete mode 100644 core/include/tactility/freertos/semaphore.h create mode 100644 core/source/Bus.cpp create mode 100644 core/source/Device.cpp create mode 100644 core/source/Driver.cpp rename core/source/{log.c => Log.cpp} (97%) delete mode 100644 core/source/device.c create mode 100644 core/source/drivers/GpioController.cpp create mode 100644 core/source/drivers/I2cController.cpp create mode 100644 core/source/drivers/Root.cpp delete mode 100644 core/source/drivers/gpio_controller.c delete mode 100644 core/source/drivers/i2c_controller.c delete mode 100644 core/source/drivers/root.c diff --git a/Buildscripts/devicetree-compiler/source/generator.py b/Buildscripts/devicetree-compiler/source/generator.py index c1cfbdc9..b88986e0 100644 --- a/Buildscripts/devicetree-compiler/source/generator.py +++ b/Buildscripts/devicetree-compiler/source/generator.py @@ -88,7 +88,9 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding]) -> def write_config(file, device: Device, bindings: list[Binding], type_name: str): device_identifier = get_device_identifier_safe(device) - file.write(f"const static struct {type_name}_config {device_identifier}_config_instance" " = {\n") + config_type = f"{type_name}_config_dt" + config_variable_name = f"{device_identifier}_config" + file.write(f"static const {config_type} {config_variable_name}" " = {\n") config_params = resolve_parameters_from_bindings(device, bindings) # Indent all params for index, config_param in enumerate(config_params): @@ -99,49 +101,57 @@ def write_config(file, device: Device, bindings: list[Binding], type_name: str): file.write(f"{config_params_joined}\n") file.write("};\n\n") -def write_device(file, device: Device, bindings: list[Binding], verbose: bool): +def write_device_structs(file, device: Device, bindings: list[Binding], verbose: bool): if verbose: - print(f"Processing device '{device.identifier}'") + print(f"Writing device struct for '{device.identifier}'") # Assemble some pre-requisites type_name = get_device_type_name(device, bindings) compatible_property = find_binding_property(device, "compatible") if compatible_property is None: raise Exception(f"Cannot find 'compatible' property for {device.identifier}") identifier = get_device_identifier_safe(device) - device_binding = find_binding(compatible_property.value, bindings) + config_variable_name = f"{identifier}_config" # Write config struct write_config(file, device, bindings, type_name) - # Type & instance names - api_type_name = f"{type_name}_api" - api_instance_name = f"{type_name}_api_instance" - init_function_name = f"{type_name}_init" - deinit_function_name = f"{type_name}_deinit" - config_instance_name = f"{identifier}_config_instance" # Write device struct - file.write(f"extern const struct {api_type_name} {api_instance_name};\n\n") - file.write("static struct device " f"{identifier}" " = {\n") - file.write("\t.name = \"" f"{identifier}" "\",\n") - file.write(f"\t.config = &{config_instance_name},\n") - file.write(f"\t.api = &{api_instance_name},\n") - file.write("\t.state = { .init_result = 0, .initialized = false },\n") - file.write("\t.data = NULL,\n") - file.write("\t.operations = { ") - file.write(f".init = {init_function_name}, ") - file.write(f".deinit = {deinit_function_name}") - file.write("},\n") - file.write("\t.metadata = {\n") - node_label_count = len(device_binding.includes) + 1 - file.write(f"\t\t.compatible_count = {node_label_count},\n") - file.write("\t\t.compatible = (const char*[]) {\n") - file.write(f"\t\t\t\"{device_binding.compatible}\",\n") - for include in device_binding.includes: - include_compatible = include.removesuffix(".yaml") - file.write(f"\t\t\t\"{include_compatible}\",\n") - file.write("\t\t}\n") - file.write("\t}\n") + file.write(f"static struct Device {identifier}" " = {\n") + file.write(f"\t.name = \"{identifier}\",\n") + file.write(f"\t.config = (void*)&{config_variable_name},\n") file.write("};\n\n") + # Child devices for child_device in device.devices: - write_device(file, child_device, bindings, verbose) + write_device_structs(file, child_device, bindings, verbose) + +def write_device_init(file, device: Device, parent_device: Device, bindings: list[Binding], verbose: bool): + if verbose: + print(f"Processing device init code for '{device.identifier}'") + # Assemble some pre-requisites + type_name = get_device_type_name(device, bindings) + compatible_property = find_binding_property(device, "compatible") + if compatible_property is None: + raise Exception(f"Cannot find 'compatible' property for {device.identifier}") + # Type & instance names + identifier = get_device_identifier_safe(device) + device_variable = identifier + driver_variable = f"{type_name}_driver" + config_instance_name = f"{identifier}_config_instance" + if parent_device is not None: + parent_identifier = get_device_identifier_safe(parent_device) + parent_value = f"&{parent_identifier}" + else: + parent_value = "NULL" + # Write device struct + file.write(f"\tdevice_construct(&{device_variable});\n") + file.write(f"\tdevice_add(&{device_variable});\n") + file.write(f"\tstruct Driver* {driver_variable} = driver_find(\"{compatible_property.value}\");\n") + file.write(f"\tif ({driver_variable} == NULL) return -1;\n") + file.write(f"\tdevice_set_driver(&{device_variable}, {driver_variable});\n") + file.write(f"\tdevice_set_parent(&{device_variable}, {parent_value});\n") + file.write(f"\tif (device_start(&{device_variable}) != 0) return -1;\n") + file.write("\n"); + # Write children + for child_device in device.devices: + write_device_init(file, child_device, device, bindings, verbose) def write_device_list_entry(file, device: Device): compatible_property = find_binding_property(device, "compatible") @@ -162,38 +172,37 @@ def write_device_list(file, devices: list[Device]): def generate_devicetree_c(filename: str, items: list[object], bindings: list[Binding], verbose: bool): with open(filename, "w") as file: + file.write("#include \n") + file.write("#include \n") # Write all headers first for item in items: if type(item) is IncludeC: write_include(file, item, verbose) file.write("\n") # Then write all devices - devices = [] for item in items: if type(item) is Device: - devices.append(item) - write_device(file, item, bindings, verbose) - write_device_list(file, devices) - file.write(dedent('''\ - struct device** devices_builtin_get() { - return devices_builtin; - } - ''')) + write_device_structs(file, item, bindings, verbose) + # Init function body start + file.write("int devices_builtin_init() {\n") + # Init function body logic + for item in items: + if type(item) is Device: + write_device_init(file, item, None, bindings, verbose) + file.write("\treturn 0;\n") + # Init function body end + file.write("}\n") def generate_devicetree_h(filename: str): with open(filename, "w") as file: file.write(dedent('''\ #pragma once - #include #ifdef __cplusplus extern "C" { #endif - /** - * @return an array of device* where the last item in the array is NULL - */ - struct device** devices_builtin_get(); + extern int devices_builtin_init(); #ifdef __cplusplus } diff --git a/Devices/lilygo-tlora-pager/Source/bindings/tlora_pager.h b/Devices/lilygo-tlora-pager/Source/bindings/tlora_pager.h new file mode 100644 index 00000000..b550f1d9 --- /dev/null +++ b/Devices/lilygo-tlora-pager/Source/bindings/tlora_pager.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +DEFINE_DEVICETREE(tlora_pager, struct RootConfig) + +#ifdef __cplusplus +} +#endif diff --git a/Devices/lilygo-tlora-pager/Source/drivers/TloraPager.cpp b/Devices/lilygo-tlora-pager/Source/drivers/TloraPager.cpp new file mode 100644 index 00000000..f9dfbf3a --- /dev/null +++ b/Devices/lilygo-tlora-pager/Source/drivers/TloraPager.cpp @@ -0,0 +1,26 @@ +#include "TloraPager.h" + +#include + +#include + +extern "C" { + +static int start(Device* device) { + return 0; +} + +static int stop(Device* device) { + return 0; +} + +Driver tlora_pager_driver = { + .name = "T-Lora Pager", + .compatible = (const char*[]) { "lilygo,tlora-pager", nullptr }, + .start_device = start, + .stop_device = stop, + .api = nullptr, + .internal = { 0 } +}; + +} diff --git a/Devices/lilygo-tlora-pager/Source/drivers/TloraPager.h b/Devices/lilygo-tlora-pager/Source/drivers/TloraPager.h new file mode 100644 index 00000000..07a90010 --- /dev/null +++ b/Devices/lilygo-tlora-pager/Source/drivers/TloraPager.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +} +#endif diff --git a/Devices/lilygo-tlora-pager/Source/drivers/tlora_pager.c b/Devices/lilygo-tlora-pager/Source/drivers/tlora_pager.c deleted file mode 100644 index b4b341d5..00000000 --- a/Devices/lilygo-tlora-pager/Source/drivers/tlora_pager.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "tlora_pager.h" -#include -#include - -#define TAG "tlora_pager" - -const struct tlora_pager_api tlora_pager_api_instance = { -}; - -int tlora_pager_init(const struct device* device) { - ESP_LOGI(TAG, "init %s", device->name); - return 0; -} - -int tlora_pager_deinit(const struct device* device) { - ESP_LOGI(TAG, "deinit %s", device->name); - return 0; -} diff --git a/Devices/lilygo-tlora-pager/Source/drivers/tlora_pager.h b/Devices/lilygo-tlora-pager/Source/drivers/tlora_pager.h deleted file mode 100644 index bb21b975..00000000 --- a/Devices/lilygo-tlora-pager/Source/drivers/tlora_pager.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -// Inherit base config -#define tlora_pager_config root_config - -// Inherit base API -#define tlora_pager_api root_api - -int tlora_pager_init(const struct device* device); - -int tlora_pager_deinit(const struct device* device); - -#ifdef __cplusplus -} -#endif diff --git a/Devices/lilygo-tlora-pager/lilygo,tlora_pager.dts b/Devices/lilygo-tlora-pager/lilygo,tlora_pager.dts index bd067892..bdd0f9b1 100644 --- a/Devices/lilygo-tlora-pager/lilygo,tlora_pager.dts +++ b/Devices/lilygo-tlora-pager/lilygo,tlora_pager.dts @@ -1,8 +1,8 @@ /dts-v1/; -#include -#include -#include +#include +#include +#include / { compatible = "lilygo,tlora-pager"; diff --git a/Devices/simulator/simulator.dts b/Devices/simulator/simulator.dts index c9e6ac8a..ce2f44c2 100644 --- a/Devices/simulator/simulator.dts +++ b/Devices/simulator/simulator.dts @@ -1,7 +1,6 @@ /dts-v1/; -#include -#include +#include / { model = "Simulator"; diff --git a/Drivers/drivers-esp/include/Tactility/bindings/esp32_gpio.h b/Drivers/drivers-esp/include/Tactility/bindings/esp32_gpio.h new file mode 100644 index 00000000..30102715 --- /dev/null +++ b/Drivers/drivers-esp/include/Tactility/bindings/esp32_gpio.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +DEFINE_DEVICETREE(esp32_gpio, struct Esp32GpioConfig) + +#ifdef __cplusplus +} +#endif diff --git a/Drivers/drivers-esp/include/Tactility/bindings/esp32_i2c.h b/Drivers/drivers-esp/include/Tactility/bindings/esp32_i2c.h new file mode 100644 index 00000000..e2826b74 --- /dev/null +++ b/Drivers/drivers-esp/include/Tactility/bindings/esp32_i2c.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +DEFINE_DEVICETREE(esp32_i2c, struct Esp32I2cConfig) + +#ifdef __cplusplus +} +#endif diff --git a/Drivers/drivers-esp/include/Tactility/drivers/Esp32Gpio.h b/Drivers/drivers-esp/include/Tactility/drivers/Esp32Gpio.h new file mode 100644 index 00000000..04245c68 --- /dev/null +++ b/Drivers/drivers-esp/include/Tactility/drivers/Esp32Gpio.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct Esp32GpioConfig { + uint8_t gpio_count; +}; + +#ifdef __cplusplus +} +#endif diff --git a/Drivers/drivers-esp/include/Tactility/drivers/Esp32I2c.h b/Drivers/drivers-esp/include/Tactility/drivers/Esp32I2c.h new file mode 100644 index 00000000..55b07b14 --- /dev/null +++ b/Drivers/drivers-esp/include/Tactility/drivers/Esp32I2c.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct Esp32I2cConfig { + uint32_t clock_frequency; + struct GpioPinConfig pin_sda; + struct GpioPinConfig pin_scl; + const i2c_port_t port; +}; + +#ifdef __cplusplus +} +#endif diff --git a/Drivers/drivers-esp/include/tactility/drivers/esp32_gpio.h b/Drivers/drivers-esp/include/tactility/drivers/esp32_gpio.h deleted file mode 100644 index 3c9deee5..00000000 --- a/Drivers/drivers-esp/include/tactility/drivers/esp32_gpio.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -struct esp32_gpio_config { - uint8_t gpio_count; -}; - -#define esp32_gpio_api gpio_controller_api - -int esp32_gpio_init(const struct device* device); - -int esp32_gpio_deinit(const struct device* device); - -#ifdef __cplusplus -} -#endif diff --git a/Drivers/drivers-esp/include/tactility/drivers/esp32_i2c.h b/Drivers/drivers-esp/include/tactility/drivers/esp32_i2c.h deleted file mode 100644 index bebd1dfe..00000000 --- a/Drivers/drivers-esp/include/tactility/drivers/esp32_i2c.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -struct esp32_i2c_config { - uint32_t clock_frequency; - struct gpio_pin_config pin_sda; - struct gpio_pin_config pin_scl; - const i2c_port_t port; -}; - -// Inherit base API -#define esp32_i2c_api i2c_controller_api - -int esp32_i2c_init(const struct device* device); - -int esp32_i2c_deinit(const struct device* device); - -#ifdef __cplusplus -} -#endif diff --git a/Drivers/drivers-esp/source/esp32_gpio.c b/Drivers/drivers-esp/source/Esp32Gpio.cpp similarity index 59% rename from Drivers/drivers-esp/source/esp32_gpio.c rename to Drivers/drivers-esp/source/Esp32Gpio.cpp index 53729561..db2dd33b 100644 --- a/Drivers/drivers-esp/source/esp32_gpio.c +++ b/Drivers/drivers-esp/source/Esp32Gpio.cpp @@ -1,24 +1,28 @@ -#include -#include - #include #include +#include +#include +#include +#include + #define TAG "esp32_gpio" -#define GET_CONFIG(dev) ((struct esp32_gpio_config*)dev->config) +#define GET_CONFIG(device) ((struct Esp32GpioConfig*)device->internal.driver_data) -static bool set_level(const struct device* dev, gpio_pin_t pin, bool high) { - return gpio_set_level(pin, high) == ESP_OK; +extern "C" { + +static bool set_level(Device* device, gpio_pin_t pin, bool high) { + return gpio_set_level(static_cast(pin), high) == ESP_OK; } -static bool get_level(const struct device* dev, gpio_pin_t pin, bool* high) { - *high = gpio_get_level(pin) != 0; +static bool get_level(Device* device, gpio_pin_t pin, bool* high) { + *high = gpio_get_level(static_cast(pin)) != 0; return true; } -static bool set_options(const struct device* dev, gpio_pin_t pin, gpio_flags_t options) { - const struct esp32_gpio_config* config = GET_CONFIG(dev); +static bool set_options(Device* device, gpio_pin_t pin, gpio_flags_t options) { + const Esp32GpioConfig* config = GET_CONFIG(device); if (pin >= config->gpio_count) { return false; @@ -49,7 +53,7 @@ static bool set_options(const struct device* dev, gpio_pin_t pin, gpio_flags_t o return gpio_config(&esp_config) == ESP_OK; } -static bool get_options(const struct device* dev, gpio_pin_t pin, gpio_flags_t* options) { +static bool get_options(Device* device, gpio_pin_t pin, gpio_flags_t* options) { gpio_io_config_t esp_config; if (gpio_get_io_config((gpio_num_t)pin, &esp_config) != ESP_OK) { return false; @@ -85,19 +89,30 @@ static bool get_options(const struct device* dev, gpio_pin_t pin, gpio_flags_t* return true; } -const struct esp32_gpio_api esp32_gpio_api_instance = { +static int start(Device* device) { + ESP_LOGI(TAG, "start %s", device->name); + return 0; +} + +static int stop(Device* device) { + ESP_LOGI(TAG, "stop %s", device->name); + return 0; +} + +const static GpioControllerApi esp32_gpio_api = { .set_level = set_level, .get_level = get_level, .set_options = set_options, .get_options = get_options }; -int esp32_gpio_init(const struct device* device) { - ESP_LOGI(TAG, "init %s", device->name); - return 0; -} +Driver esp32_gpio_driver = { + .name = "esp32_gpio", + .compatible = (const char*[]) { "espressif,esp32-gpio", nullptr }, + .start_device = start, + .stop_device = stop, + .api = (void*)&esp32_gpio_api, + .internal = { 0 } +}; -int esp32_gpio_deinit(const struct device* device) { - ESP_LOGI(TAG, "deinit %s", device->name); - return 0; -} +} // extern "C" diff --git a/Drivers/drivers-esp/source/Esp32I2c.cpp b/Drivers/drivers-esp/source/Esp32I2c.cpp new file mode 100644 index 00000000..b742e780 --- /dev/null +++ b/Drivers/drivers-esp/source/Esp32I2c.cpp @@ -0,0 +1,90 @@ +#include +#include + +#include +#include +#include + +#define TAG "esp32_i2c" + +struct InternalData { + Mutex mutex {}; + + InternalData() { + mutex_construct(&mutex); + } + + ~InternalData() { + mutex_destruct(&mutex); + } +}; + +#define GET_CONFIG(device) ((Esp32I2cConfig*)device->internal.driver_data) +#define GET_DATA(device) ((InternalData*)device->internal.driver_data) + +#define lock(data) mutex_lock(&data->mutex); +#define unlock(data) mutex_unlock(&data->mutex); + +extern "C" { + +static bool read(Device* device, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout) { + vPortAssertIfInISR(); + auto* driver_data = GET_DATA(device); + lock(driver_data); + const esp_err_t result = i2c_master_read_from_device(GET_CONFIG(device)->port, address, data, dataSize, timeout); + unlock(driver_data); + ESP_ERROR_CHECK_WITHOUT_ABORT(result); + return result == ESP_OK; +} + +static bool write(Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { + vPortAssertIfInISR(); + auto* driver_data = GET_DATA(device); + lock(driver_data); + const esp_err_t result = i2c_master_write_to_device(GET_CONFIG(device)->port, address, data, dataSize, timeout); + unlock(driver_data); + ESP_ERROR_CHECK_WITHOUT_ABORT(result); + return result == ESP_OK; +} + +static bool write_read(Device* device, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout) { + vPortAssertIfInISR(); + auto* driver_data = GET_DATA(device); + lock(driver_data); + const esp_err_t result = i2c_master_write_read_device(GET_CONFIG(device)->port, address, write_data, write_data_size, read_data, read_data_size, timeout); + unlock(driver_data) + ESP_ERROR_CHECK_WITHOUT_ABORT(result); + return result == ESP_OK; +} + +static int start(Device* device) { + ESP_LOGI(TAG, "start %s", device->name); + auto* data = new InternalData(); + device_set_driver_data(device, data); + return 0; +} + +static int stop(Device* device) { + ESP_LOGI(TAG, "stop %s", device->name); + auto* driver_data = static_cast(device_get_driver_data(device)); + device_set_driver_data(device, nullptr); + delete driver_data; + return 0; +} + +const I2cControllerApi esp32_i2c_api = { + .read = read, + .write = write, + .write_read = write_read +}; + +Driver esp32_i2c_driver = { + .name = "esp32_i2c", + .compatible = (const char*[]) { "espressif,esp32-i2c", nullptr }, + .start_device = start, + .stop_device = stop, + .api = (void*)&esp32_i2c_api, + .internal = { 0 } +}; + +} // extern "C" diff --git a/Drivers/drivers-esp/source/esp32_i2c.c b/Drivers/drivers-esp/source/esp32_i2c.c deleted file mode 100644 index e462974c..00000000 --- a/Drivers/drivers-esp/source/esp32_i2c.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "tactility/drivers/esp32_i2c.h" - -#include "driver/i2c.h" - -#include -#include - -#define TAG "esp32_i2c" - -#define GET_CONFIG(dev) ((struct esp32_i2c_config*)dev->config) - -static bool read(struct device* dev, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout) { - // TODO: mutex - esp_err_t result = i2c_master_read_from_device(GET_CONFIG(dev)->port, address, data, dataSize, timeout); - ESP_ERROR_CHECK_WITHOUT_ABORT(result); - return result == ESP_OK; -} - -static bool write(struct device* dev, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { - // TODO: mutex - esp_err_t result = i2c_master_write_to_device(GET_CONFIG(dev)->port, address, data, dataSize, timeout); - ESP_ERROR_CHECK_WITHOUT_ABORT(result); - return result == ESP_OK; -} - -static bool write_read(struct device* dev, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout) { - // TODO: mutex - esp_err_t result = i2c_master_write_read_device(GET_CONFIG(dev)->port, address, write_data, write_data_size, read_data, read_data_size, timeout); - ESP_ERROR_CHECK_WITHOUT_ABORT(result); - return result == ESP_OK; -} - -const struct esp32_i2c_api esp32_i2c_api_instance = { - .read = read, - .write = write, - .write_read = write_read -}; - -int esp32_i2c_init(const struct device* device) { - ESP_LOGI(TAG, "init %s", device->name); - return 0; -} - -int esp32_i2c_deinit(const struct device* device) { - ESP_LOGI(TAG, "deinit %s", device->name); - return 0; -} diff --git a/Firmware/Source/Main.cpp b/Firmware/Source/Main.cpp index c6dc7db1..cd0e690f 100644 --- a/Firmware/Source/Main.cpp +++ b/Firmware/Source/Main.cpp @@ -1,4 +1,6 @@ #include + +#include #include #ifdef ESP_PLATFORM @@ -25,8 +27,17 @@ void app_main() { tt_init_tactility_c(); // ELF bindings for side-loading on ESP32 #endif - auto devices = devices_builtin_get(); - tt::run(config, devices); + extern Driver root_driver; + extern Driver tlora_pager_driver; + extern Driver esp32_gpio_driver; + extern Driver esp32_i2c_driver; + driver_construct(&root_driver); + driver_construct(&tlora_pager_driver); + driver_construct(&esp32_gpio_driver); + driver_construct(&esp32_i2c_driver); + + devices_builtin_init(); + tt::run(config); } } // extern \ No newline at end of file diff --git a/Tactility/Include/Tactility/Tactility.h b/Tactility/Include/Tactility/Tactility.h index e88e0ec2..b0fc801e 100644 --- a/Tactility/Include/Tactility/Tactility.h +++ b/Tactility/Include/Tactility/Tactility.h @@ -5,8 +5,6 @@ #include #include -#include - namespace tt { /** @brief The configuration for the operating system @@ -21,7 +19,7 @@ struct Configuration { * Attempts to initialize Tactility and all configured hardware. * @param[in] config */ -void run(const Configuration& config, device** devices); +void run(const Configuration& config); /** * While technically nullable, this instance is always set if tt_init() succeeds. diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp index a90deaf7..4f4cd4ed 100644 --- a/Tactility/Source/Tactility.cpp +++ b/Tactility/Source/Tactility.cpp @@ -306,7 +306,7 @@ void registerApps() { registerInstalledAppsFromSdCards(); } -void run(const Configuration& config, device** devices) { +void run(const Configuration& config) { LOGGER.info("Tactility v{} on {} ({})", TT_VERSION, CONFIG_TT_DEVICE_NAME, CONFIG_TT_DEVICE_ID); assert(config.hardware); @@ -315,11 +315,6 @@ void run(const Configuration& config, device** devices) { // Assign early so starting services can use it config_instance = &config; - if (devices != nullptr) { - device_add_all(devices); - device_init_all(devices); - } - #ifdef ESP_PLATFORM initEsp(); #endif diff --git a/core/include/Tactility/Bus.h b/core/include/Tactility/Bus.h new file mode 100644 index 00000000..be49b9c5 --- /dev/null +++ b/core/include/Tactility/Bus.h @@ -0,0 +1,49 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +struct Device; + +/** + * A bus contains a group of devices owned by a parent device. + * It is used to make a group of devices discoverable. + * + * Example usage: + * The "i2c0" bus is created by the i2c_controller driver when a device is started by a driver. + * The postfix "0" means that it was the first device instance (at index 0). + */ +struct Bus { + /** The name of the bus (e.g. "i2c0" or "spi1"). Valid characters: a-z a-Z 0-9 - _ . */ + const char* name; + /** Internal data */ + struct { + /** The device this bus belongs to */ + struct Device* parent_device; + /** The bus' private data */ + void* data; + } internal; +}; + +// region Bus management + +int bus_construct(struct Bus* bus); + +int bus_destruct(struct Bus* bus); + +struct Bus* bus_find(const char* name); + +// endregion + +// region Bus device management + +int bus_add_device(struct Bus*, struct Device* dev); + +void bus_remove_device(struct Bus*, struct Device* dev); + +// endregion + +#ifdef __cplusplus +} +#endif diff --git a/core/include/Tactility/Device.h b/core/include/Tactility/Device.h new file mode 100644 index 00000000..edeaed59 --- /dev/null +++ b/core/include/Tactility/Device.h @@ -0,0 +1,163 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include +#include + +struct Driver; + +/** Represents a piece of hardware */ +struct Device { + /** The name of the device. Valid characters: a-z a-Z 0-9 - _ . */ + const char* name; + /** The configuration data for the device's driver */ + void* config; + /** Internal data */ + struct { + /** The parent device that this device belongs to. Can be NULL, but only the root device should have a NULL parent. */ + struct Device* parent; + /** Address of the API exposed by the device instance. */ + struct Driver* driver; + /** The driver data for this device (e.g. a mutex) */ + void* driver_data; + /** The bus that is owned by this device. This bus can contain child devices to make them discoverable. Can be NULL. */ + struct Bus* bus; + /** The mutex for device operations */ + struct Mutex mutex; + /** The device state */ + struct { + uint8_t start_result; + bool started : 1; + bool added : 1; + } state; + /** Private data */ + void* data; + } internal; +}; + +/** + * Initialize the properties of a device. + * + * @param[in] dev a device with all non-internal properties set + */ +void device_construct(struct Device* device); + +/** + * Deinitialize the properties of a device. + * This fails when a device is busy or has children. + * + * @param[in] dev + * @return the result code (0 for success) + */ +int device_destruct(struct Device* device); + +/** + * Indicates whether the device is in a state where its API is available + * + * @param[in] dev 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 + */ +void 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 + * @return true when the device was found and deregistered + */ +bool device_remove(struct Device* device); + +/** + * Attach the driver. + * + * @warning must call device_construct() and device_add() first + * @param device + * @return ERROR_INVALID_STATE or otherwise the value of the driver binding result (0 on success) + */ +int device_start(struct Device* device); + +/** + * Detach the driver. + * + * @param device + * @return ERROR_INVALID_STATE or otherwise the value of the driver unbinding result (0 on success) + */ +int device_stop(struct Device* device); + +/** + * Set or unset a parent. + * @warning must call before device_add() + * @param device non-NULL device + * @param parent nullable parent device + */ +void device_set_parent(struct Device* device, struct Device* parent); + +static inline void device_set_driver(struct Device* device, struct Driver* driver) { + device->internal.driver = driver; +} + +static inline struct Driver* device_get_driver(struct Device* device) { + return device->internal.driver; +} + +static inline void device_set_driver_data(struct Device* device, void* driver_data) { + device->internal.driver_data = driver_data; +} + +static inline void* device_get_driver_data(struct Device* device) { + return device->internal.driver_data; +} + +static inline bool device_is_added(const struct Device* device) { + return device->internal.state.added; +} + +static inline struct Bus* device_get_bus(const struct Device* device) { + return device->internal.bus; +} + +static inline void device_set_bus(struct Device* device, struct Bus* bus) { + device->internal.bus = bus; +} + +static inline const char* device_get_bus_name(const struct Device* device) { + return device->internal.bus ? device->internal.bus->name : ""; +} + +static inline void device_lock(struct Device* device) { + mutex_lock(&device->internal.mutex); +} + +static inline int device_try_lock(struct Device* device) { + return mutex_try_lock(&device->internal.mutex); +} + +static inline void device_unlock(struct Device* device) { + mutex_unlock(&device->internal.mutex); +} + +#ifdef __cplusplus +} +#endif diff --git a/core/include/Tactility/Driver.h b/core/include/Tactility/Driver.h new file mode 100644 index 00000000..eacc5e80 --- /dev/null +++ b/core/include/Tactility/Driver.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct Driver { + /** The driver name */ + const char* name; + /** Array of const char*, terminated by NULL */ + const char** compatible; + /** Function to initialize the driver for a device */ + int (*start_device)(struct Device* dev); + /** Function to deinitialize the driver for a device */ + int (*stop_device)(struct Device* dev); + /** Contains the driver's functions */ + const void* api; + /** Internal data */ + struct { + /** Contains private data */ + void* data; + } internal; +}; + +int driver_construct(struct Driver* drv); + +int driver_destruct(struct Driver* drv); + +struct Driver* driver_find(const char* name); + +int driver_bind(struct Driver* drv, struct Device* dev); + +int driver_unbind(struct Driver* drv, struct Device* dev); + +#ifdef __cplusplus +} +#endif diff --git a/core/include/Tactility/Error.h b/core/include/Tactility/Error.h new file mode 100644 index 00000000..97edfdc8 --- /dev/null +++ b/core/include/Tactility/Error.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +#define CUSTOM_ERROR_CODE(x) (-__ELASTERROR - x) + +#define ERROR_UNDEFINED CUSTOM_ERROR_CODE(1) +#define ERROR_INVALID_STATE CUSTOM_ERROR_CODE(2) +#define ERROR_INVALID_PARAMETER CUSTOM_ERROR_CODE(3) +#define ERROR_MISSING_PARAMETER CUSTOM_ERROR_CODE(4) diff --git a/core/include/tactility/freertos/freertos.h b/core/include/Tactility/FreeRTOS/FreeRTOS.h similarity index 100% rename from core/include/tactility/freertos/freertos.h rename to core/include/Tactility/FreeRTOS/FreeRTOS.h diff --git a/core/include/tactility/freertos/README.md b/core/include/Tactility/FreeRTOS/README.md similarity index 100% rename from core/include/tactility/freertos/README.md rename to core/include/Tactility/FreeRTOS/README.md diff --git a/core/include/tactility/freertos/event_groups.h b/core/include/Tactility/FreeRTOS/event_groups.h similarity index 100% rename from core/include/tactility/freertos/event_groups.h rename to core/include/Tactility/FreeRTOS/event_groups.h diff --git a/core/include/tactility/freertos/port.h b/core/include/Tactility/FreeRTOS/port.h similarity index 78% rename from core/include/tactility/freertos/port.h rename to core/include/Tactility/FreeRTOS/port.h index 226f5126..cddbf9ff 100644 --- a/core/include/tactility/freertos/port.h +++ b/core/include/Tactility/FreeRTOS/port.h @@ -1,6 +1,6 @@ #pragma once -#include "freertos.h" +#include "FreeRTOS.h" #ifndef ESP_PLATFORM #define xPortInIsrContext(x) (false) diff --git a/core/include/tactility/freertos/queue.h b/core/include/Tactility/FreeRTOS/queue.h similarity index 100% rename from core/include/tactility/freertos/queue.h rename to core/include/Tactility/FreeRTOS/queue.h diff --git a/core/include/Tactility/FreeRTOS/semphr.h b/core/include/Tactility/FreeRTOS/semphr.h new file mode 100644 index 00000000..a6a16237 --- /dev/null +++ b/core/include/Tactility/FreeRTOS/semphr.h @@ -0,0 +1,9 @@ +#pragma once + +#ifdef ESP_PLATFORM +#include +#include +#else +#include +#include +#endif \ No newline at end of file diff --git a/core/include/tactility/freertos/task.h b/core/include/Tactility/FreeRTOS/task.h similarity index 100% rename from core/include/tactility/freertos/task.h rename to core/include/Tactility/FreeRTOS/task.h diff --git a/core/include/tactility/freertos/timers.h b/core/include/Tactility/FreeRTOS/timers.h similarity index 100% rename from core/include/tactility/freertos/timers.h rename to core/include/Tactility/FreeRTOS/timers.h diff --git a/core/include/tactility/log.h b/core/include/Tactility/Log.h similarity index 51% rename from core/include/tactility/log.h rename to core/include/Tactility/Log.h index c1b76b44..c930f749 100644 --- a/core/include/tactility/log.h +++ b/core/include/Tactility/Log.h @@ -4,15 +4,21 @@ #include #endif +#ifdef __cplusplus +extern "C" { +#endif + +#define LOG_TAG(x) "\033[37m"#x"\033[0m" + #ifndef ESP_PLATFORM void log_generic(const char* tag, const char* format, ...); -#define LOG_E(x, ...) log(x, ##__VA_ARGS__) -#define LOG_W(x, ...) log(x, ##__VA_ARGS__) -#define LOG_I(x, ...) log(x, ##__VA_ARGS__) -#define LOG_D(x, ...) log(x, ##__VA_ARGS__) -#define LOG_V(x, ...) log(x, ##__VA_ARGS__) +#define LOG_E(x, ...) log_generic(x, ##__VA_ARGS__) +#define LOG_W(x, ...) log_generic(x, ##__VA_ARGS__) +#define LOG_I(x, ...) log_generic(x, ##__VA_ARGS__) +#define LOG_D(x, ...) log_generic(x, ##__VA_ARGS__) +#define LOG_V(x, ...) log_generic(x, ##__VA_ARGS__) #else @@ -22,4 +28,8 @@ void log_generic(const char* tag, const char* format, ...); #define LOG_D(x, ...) ESP_LOGD(x, ##__VA_ARGS__) #define LOG_V(x, ...) ESP_LOGV(x, ##__VA_ARGS__) -#endif \ No newline at end of file +#endif + +#ifdef __cplusplus +} +#endif diff --git a/core/include/Tactility/bindings/bindings.h b/core/include/Tactility/bindings/bindings.h new file mode 100644 index 00000000..8d46255a --- /dev/null +++ b/core/include/Tactility/bindings/bindings.h @@ -0,0 +1,8 @@ +#pragma once + +/** + * Creates required aliases for the devicetree generation. + * @param compatible_name the "compatible" value for the related driver + * @param config_type the internal configuration type for a device + */ +#define DEFINE_DEVICETREE(compatible_name, config_type) typedef config_type compatible_name##_config_dt; diff --git a/core/include/Tactility/bindings/gpio.h b/core/include/Tactility/bindings/gpio.h new file mode 100644 index 00000000..836daf73 --- /dev/null +++ b/core/include/Tactility/bindings/gpio.h @@ -0,0 +1,3 @@ +#pragma once + +#include diff --git a/core/include/Tactility/bindings/root.h b/core/include/Tactility/bindings/root.h new file mode 100644 index 00000000..f345b5c7 --- /dev/null +++ b/core/include/Tactility/bindings/root.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include + +DEFINE_DEVICETREE(root, struct RootConfig) + diff --git a/core/include/Tactility/concurrent/Mutex.h b/core/include/Tactility/concurrent/Mutex.h new file mode 100644 index 00000000..a6eede61 --- /dev/null +++ b/core/include/Tactility/concurrent/Mutex.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct Mutex { + QueueHandle_t handle; +}; + +inline static void mutex_construct(struct Mutex* mutex) { + mutex->handle = xSemaphoreCreateMutex(); +} + +inline static void mutex_destruct(struct Mutex* mutex) { + assert(mutex != NULL); + assert(mutex->handle != NULL); + vPortAssertIfInISR(); + vSemaphoreDelete(mutex->handle); + mutex->handle = NULL; +} + +inline static void mutex_lock(struct Mutex* mutex) { + assert(mutex->handle != NULL); + xSemaphoreTake(mutex->handle, portMAX_DELAY); +} + +inline static bool mutex_try_lock(struct Mutex* mutex) { + assert(mutex->handle != NULL); + return xSemaphoreTake(mutex->handle, 0) == pdTRUE; +} + +inline static bool mutex_is_locked(struct Mutex* mutex) { + assert(mutex->handle != NULL); + return xSemaphoreGetMutexHolder(mutex->handle) != NULL; +} + +inline static void mutex_unlock(struct Mutex* mutex) { + assert(mutex->handle != NULL); + xSemaphoreGive(mutex->handle); +} + +#ifdef __cplusplus +} +#endif diff --git a/core/include/Tactility/concurrent/RecursiveMutex.h b/core/include/Tactility/concurrent/RecursiveMutex.h new file mode 100644 index 00000000..50887cec --- /dev/null +++ b/core/include/Tactility/concurrent/RecursiveMutex.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct RecursiveMutex { + QueueHandle_t handle; +}; + +inline static void recursive_mutex_construct(struct RecursiveMutex* mutex) { + mutex->handle = xSemaphoreCreateRecursiveMutex(); +} + +inline static void recursive_mutex_destruct(struct RecursiveMutex* mutex) { + assert(mutex != NULL); + assert(mutex->handle != NULL); + vSemaphoreDelete(mutex->handle); + mutex->handle = NULL; +} + +inline static void recursive_mutex_lock(struct RecursiveMutex* mutex) { + assert(mutex->handle != NULL); + xSemaphoreTake(mutex->handle, portMAX_DELAY); +} + +inline static bool recursive_mutex_is_locked(struct RecursiveMutex* mutex) { + assert(mutex->handle != NULL); + return xSemaphoreGetMutexHolder(mutex->handle) != NULL; +} + +inline static bool recursive_mutex_try_lock(struct RecursiveMutex* mutex) { + assert(mutex->handle != NULL); + return xSemaphoreTake(mutex->handle, 0) == pdTRUE; +} + +inline static void recursive_mutex_unlock(struct RecursiveMutex* mutex) { + assert(mutex->handle != NULL); + xSemaphoreGive(mutex->handle); +} + +#ifdef __cplusplus +} +#endif diff --git a/core/include/tactility/drivers/gpio.h b/core/include/Tactility/drivers/Gpio.h similarity index 80% rename from core/include/tactility/drivers/gpio.h rename to core/include/Tactility/drivers/Gpio.h index b3ab4202..0e90f1df 100644 --- a/core/include/tactility/drivers/gpio.h +++ b/core/include/Tactility/drivers/Gpio.h @@ -4,7 +4,7 @@ extern "C" { #endif -#include +#include #define GPIO_OPTIONS_MASK 0x1f @@ -19,7 +19,7 @@ extern "C" { #define GPIO_PULL_DOWN (1 << 4) #define GPIO_INTERRUPT_BITMASK (0b111 << 5) // 3 bits to hold the values [0, 5] -#define GPIO_INTERRUPT_FROM_OPTIONS(options) (gpio_interrupt_type_t)((options & GPIO_INTERRUPT_BITMASK) >> 5) +#define GPIO_INTERRUPT_FROM_OPTIONS(options) (gpio_int_type_t)((options & GPIO_INTERRUPT_BITMASK) >> 5) #define GPIO_INTERRUPT_TO_OPTIONS(options, interrupt) (options | (interrupt << 5)) typedef enum { @@ -30,7 +30,7 @@ typedef enum { GPIO_INTERRUPT_LOW_LEVEL = 4, GPIO_INTERRUPT_HIGH_LEVEL = 5, GPIO__MAX, -} gpio_interrupt_type_t; +} GpioInterruptType; /** * @brief Provides a type to hold a GPIO pin index. @@ -67,25 +67,21 @@ typedef uint16_t gpio_flags_t; * controlled by that device, and the subset of pin configuration * flags which may be given in devicetree. */ -struct gpio_pin_config { +struct GpioPinConfig { /** GPIO device controlling the pin */ - const struct device* port; + const struct Device* port; /** The pin's number on the device */ gpio_pin_t pin; /** The pin's configuration flags as specified in devicetree */ gpio_flags_t dt_flags; }; - /** - * @brief Validate that GPIO port is ready. - * - * @param spec GPIO specification from devicetree - * - * @retval true if the GPIO spec is ready for use. - * @retval false if the GPIO spec is not ready for use. + * Check if the pin is ready to be used. + * @param pin_config the specifications of the pin + * @return true if the pin is ready to be used */ -inline bool gpio_is_ready(const struct gpio_pin_config* pin_config) { +static inline bool gpio_is_ready(const struct GpioPinConfig* pin_config) { return device_is_ready(pin_config->port); } diff --git a/core/include/Tactility/drivers/GpioController.h b/core/include/Tactility/drivers/GpioController.h new file mode 100644 index 00000000..3d70923d --- /dev/null +++ b/core/include/Tactility/drivers/GpioController.h @@ -0,0 +1,28 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Gpio.h" +#include + +struct GpioControllerApi { + bool (*set_level)(struct Device* device, gpio_pin_t pin, bool high); + bool (*get_level)(struct Device* device, gpio_pin_t pin, bool* high); + bool (*set_options)(struct Device* device, gpio_pin_t pin, gpio_flags_t options); + bool (*get_options)(struct Device* device, gpio_pin_t pin, gpio_flags_t* options); +}; + +bool gpio_controller_set_level(struct Device* device, gpio_pin_t pin, bool high); +bool gpio_controller_get_level(struct Device* device, gpio_pin_t pin, bool* high); +bool gpio_controller_set_options(struct Device* device, gpio_pin_t pin, gpio_flags_t options); +bool gpio_controller_get_options(struct Device* device, gpio_pin_t pin, gpio_flags_t* options); + +inline bool gpio_set_options_config(struct Device* device, struct GpioPinConfig* config) { + return gpio_controller_set_options(device, config->pin, config->dt_flags); +} + +#ifdef __cplusplus +} +#endif diff --git a/core/include/Tactility/drivers/I2cController.h b/core/include/Tactility/drivers/I2cController.h new file mode 100644 index 00000000..dcf7d176 --- /dev/null +++ b/core/include/Tactility/drivers/I2cController.h @@ -0,0 +1,26 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Gpio.h" +#include +#include +#include + +struct I2cControllerApi { + bool (*read)(struct Device* device, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout); + bool (*write)(struct Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); + bool (*write_read)(struct Device* device, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout); +}; + +bool i2c_controller_read(struct Device* device, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout); + +bool i2c_controller_write(struct Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); + +bool i2c_controller_write_read(struct Device* device, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout); + +#ifdef __cplusplus +} +#endif diff --git a/core/include/tactility/drivers/root.h b/core/include/Tactility/drivers/Root.h similarity index 52% rename from core/include/tactility/drivers/root.h rename to core/include/Tactility/drivers/Root.h index 73a35152..00120801 100644 --- a/core/include/tactility/drivers/root.h +++ b/core/include/Tactility/drivers/Root.h @@ -4,16 +4,10 @@ extern "C" { #endif -struct root_config { +struct RootConfig { const char* model; }; -struct root_api { -}; - -#define root_init nullptr -#define root_deinit nullptr - #ifdef __cplusplus } #endif diff --git a/core/include/tactility/device.h b/core/include/tactility/device.h deleted file mode 100644 index 387badb2..00000000 --- a/core/include/tactility/device.h +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -struct device; - -struct device_operations { - /** Initialization function */ - int (*init)(const struct device* device); - /** De-initialization function */ - int (*deinit)(const struct device* device); -}; - -struct device_state { - uint8_t init_result; - bool initialized : 1; -}; - -struct device_metadata { - /** @brief number of elements in the compatible array */ - size_t compatible_count; - /** @brief array of strings containing the compatible device names */ - const char** compatible; -}; - -struct device { - /** Name of the device as defined in the dts file */ - const char* name; - /** Address of device instance configuration. This relates to the parameters that are specified in the dts file*/ - const void* config; - /** Address of the API exposed by the device instance */ - const void* api; - /** The device state */ - struct device_state state; - /** Address of the device's private data */ - void* data; - /** Device operations: used for initializing and deinitializing */ - struct device_operations operations; - /** Device metadata */ - struct device_metadata metadata; -}; - -/** - * Initialize a device. - * @param[in] dev - * @return the return code of the device's init function - */ -uint8_t device_init(struct device* dev); - -/** - * Initialize an array of devices. - * @param[in] device_array a null-terminated array of devices - * @retval true if all devices initialized successfully - * @retval false if any device failed to initialize - */ -bool device_init_all(struct device** device_array); - -/** - * Deinitialize a device. - * @param[in] dev - * @return the return code of the device's deinit function - */ -uint8_t device_deinit(struct device* dev); - -/** - * Indicated whether the device is in a state where its API is available - * - * @param[in] dev non-null device pointer - * @return true if the device is ready for use - */ -bool device_is_ready(const struct device* dev); - -/** - * Register a single device. - * - * @param[in] dev non-null device pointer - */ -void device_add(const struct device* dev); - -/** - * Register all devices in the specified array. - * The array must be null-terminated. - * - * @param[in] device_array non-null array of devices - */ -void device_add_all(struct device** device_array); - -/** - * Deregister a device - * @param[in] dev non-null device pointer - * @return true when the device was found and deregistered - */ -bool device_remove(const struct device* dev); - -/** - * Iterate the devicetree. Find the next with the specified label. - * @param[in] identifier the identifier of the device, such as "root" or "i2c-controller" - * @param[inout] dev a pointer to a device pointer in the tree, or nullptr to start searching for the first device - * @return true if a device was found - */ -bool device_find_next_by_compatible(const char* identifier, const struct device** dev); - -#ifdef __cplusplus -} -#endif diff --git a/core/include/tactility/drivers/gpio_controller.h b/core/include/tactility/drivers/gpio_controller.h deleted file mode 100644 index 973e6b8e..00000000 --- a/core/include/tactility/drivers/gpio_controller.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "gpio.h" - -struct gpio_controller_api { - bool (*set_level)(const struct device*, gpio_pin_t pin, bool high); - bool (*get_level)(const struct device*, gpio_pin_t pin, bool* high); - bool (*set_options)(const struct device*, gpio_pin_t pin, gpio_flags_t options); - bool (*get_options)(const struct device*, gpio_pin_t pin, gpio_flags_t* options); -}; - -bool gpio_controller_set_level(const struct device* dev, gpio_pin_t pin, bool high); -bool gpio_controller_get_level(const struct device* dev, gpio_pin_t pin, bool* high); -bool gpio_controller_set_options(const struct device* dev, gpio_pin_t pin, gpio_flags_t options); -bool gpio_controller_get_options(const struct device* dev, gpio_pin_t pin, gpio_flags_t* options); - -inline bool gpio_set_options_config(const struct gpio_pin_config* config) { - return gpio_controller_set_options(config->port, config->pin, config->dt_flags); -} - -#ifdef __cplusplus -} -#endif diff --git a/core/include/tactility/drivers/i2c_controller.h b/core/include/tactility/drivers/i2c_controller.h deleted file mode 100644 index 8a511e2d..00000000 --- a/core/include/tactility/drivers/i2c_controller.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include "gpio.h" - -struct i2c_controller_api { - bool (*read)(struct device* dev, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout); - bool (*write)(struct device* dev, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); - bool (*write_read)(struct device* dev, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout); -}; - -bool i2c_controller_read(struct device* dev, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout); - -bool i2c_controller_write(struct device* dev, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); - -bool i2c_controller_write_read(struct device* dev, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout); - -#ifdef __cplusplus -} -#endif diff --git a/core/include/tactility/freertos/semaphore.h b/core/include/tactility/freertos/semaphore.h deleted file mode 100644 index 9a9a78a4..00000000 --- a/core/include/tactility/freertos/semaphore.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#ifdef ESP_PLATFORM -#include -#include -#else -#include -#include -#endif - -#include - -struct SemaphoreHandleDeleter { - static void operator()(QueueHandle_t handleToDelete) { - assert(xPortInIsrContext() == pdFALSE); - vSemaphoreDelete(handleToDelete); - } -}; - diff --git a/core/source/Bus.cpp b/core/source/Bus.cpp new file mode 100644 index 00000000..a6f04321 --- /dev/null +++ b/core/source/Bus.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +/** Keeps track of all existing buses */ +struct BusLedger { + std::vector buses = {}; + Mutex mutex {}; + + BusLedger() { + mutex_construct(&mutex); + } + + ~BusLedger() { + mutex_destruct(&mutex); + } +}; + +/* Internal data for a Bus */ +struct BusData { + std::vector devices = {}; + std::vector drivers = {}; + Mutex mutex {}; + + BusData() { + mutex_construct(&mutex); + } + + ~BusData() { + mutex_destruct(&mutex); + } +}; + +static BusLedger ledger; + +#define ledger_lock() mutex_lock(&ledger.mutex); +#define ledger_unlock() mutex_unlock(&ledger.mutex); + +#define bus_lock(bus_data) mutex_lock(&bus_data->mutex); +#define bus_unlock(bus_data) mutex_unlock(&bus_data->mutex); + +#define BUS_INSTANCE_DATA(bus) ((struct BusData*)bus->internal.data) + +extern "C" { + +// region Bus management + +static int bus_add(Bus* bus) { + ledger_lock(); + ledger.buses.push_back(bus); + ledger_unlock(); + return 0; +} + +static void bus_remove(Bus* bus) { + ledger_lock(); + const auto iterator = std::ranges::find(ledger.buses, bus); + if (iterator != ledger.buses.end()) { + ledger.buses.erase(iterator); + } + ledger_unlock(); +} + +int bus_construct(Bus* bus) { + bus->internal.data = new BusData(); + bus_add(bus); + return 0; +} + +int bus_destruct(Bus* bus) { + delete BUS_INSTANCE_DATA(bus); + bus_remove(bus); + return 0; +} + +// endregion + +// region Bus device management + +Bus* bus_find(const char* name) { + ledger_lock(); + const auto it = std::ranges::find_if(ledger.buses, [name](Bus* bus) { + return strcmp(name, bus->name) == 0; + }); + Bus* result = (it != ledger.buses.end()) ? *it : nullptr; + ledger_unlock(); + return result; +} + +int bus_add_device(Bus* bus, Device* dev) { + auto* bus_data = BUS_INSTANCE_DATA(bus); + bus_lock(bus_data); + bus_data->devices.push_back(dev); + bus_unlock(bus_data); + return 0; +} + +void bus_remove_device(Bus* bus, Device* dev) { + auto* bus_data = BUS_INSTANCE_DATA(bus); + bus_lock(bus_data); + const auto iterator = std::ranges::find(bus_data->devices, dev); + if (iterator != bus_data->devices.end()) { + bus_data->devices.erase(iterator); + } + bus_unlock(bus_data); +} + +// endregion + +} // extern "C" diff --git a/core/source/Device.cpp b/core/source/Device.cpp new file mode 100644 index 00000000..73bbca50 --- /dev/null +++ b/core/source/Device.cpp @@ -0,0 +1,202 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define TAG LOG_TAG(device) + +struct DeviceData { + std::vector children; +}; + +struct DeviceLedger { + std::vector devices; + Mutex mutex {}; + + DeviceLedger() { + mutex_construct(&mutex); + } + + ~DeviceLedger() { + mutex_destruct(&mutex); + } +}; + +static DeviceLedger ledger; + +extern "C" { + +#define ledger_lock() mutex_lock(&ledger.mutex); +#define ledger_unlock() mutex_unlock(&ledger.mutex); + +#define get_device_data(device) static_cast(device->internal.data) + +void device_construct(Device* device) { + LOG_I(TAG, "construct %s", device->name); + device->internal.data = new DeviceData(); + mutex_construct(&device->internal.mutex); +} + +int device_destruct(Device* device) { + LOG_I(TAG, "destruct %s", device->name); + mutex_destruct(&device->internal.mutex); + delete get_device_data(device); + device->internal.data = nullptr; + return 0; +} + +/** Add a child to the list of children */ +static void device_add_child(struct Device* device, struct Device* child) { + device_lock(device); + get_device_data(device)->children.push_back(device); + device_unlock(device); +} + +/** Remove a child from the list of children */ +static void device_remove_child(struct Device* device, struct Device* child) { + device_lock(device); + auto* parent_data = get_device_data(device); + const auto iterator = std::ranges::find(parent_data->children, device); + if (iterator != parent_data->children.end()) { + parent_data->children.erase(iterator); + } + device_unlock(device); +} + +void device_add(Device* device) { + LOG_I(TAG, "add %s", device->name); + + assert(!device->internal.state.started); + + // Already added + if (device->internal.state.added) { + return; + } + + // Add to ledger + ledger_lock(); + ledger.devices.push_back(device); + ledger_unlock(); + + // Add self to parent's children list + auto* parent = device->internal.parent; + if (parent != nullptr) { + device_add_child(parent, device); + } + + auto* bus = device->internal.bus; + if (bus != nullptr) { + bus_add_device(bus, device); + } + + device->internal.state.added = true; +} + +bool device_remove(Device* device) { + LOG_I(TAG, "remove %s", device->name); + + assert(!device->internal.state.started); + + // Already removed + if (!device->internal.state.added) { + return true; + } + + auto* bus = device->internal.bus; + if (bus != nullptr) { + bus_remove_device(bus, device); + } + + // Remove self from parent's children list + auto* parent = device->internal.parent; + if (parent != nullptr) { + device_remove_child(parent, device); + } + + ledger_lock(); + const auto iterator = std::ranges::find(ledger.devices, device); + if (iterator == ledger.devices.end()) { + ledger_unlock(); + goto failed_ledger_lookup; + } + ledger.devices.erase(iterator); + ledger_unlock(); + + device->internal.state.added = false; + return true; + +failed_ledger_lookup: + + // Re-add to parent + if (parent != nullptr) { + device_add_child(parent, device); + } + + // Re-add to bus + if (bus != nullptr) { + bus_add_device(bus, device); + } + + return false; +} + +int device_start(Device* device) { + if (!device->internal.state.added) { + return ERROR_INVALID_STATE; + } + + // Already started + if (device->internal.state.started) { + return 0; + } + + if (device->internal.driver == nullptr) { + LOG_E(TAG, "start error: no driver for %s", device->name); + return ERROR_INVALID_STATE; + } + + int result = driver_bind(device->internal.driver, device); + if (result != 0) { + device->internal.state.started = true; + device->internal.state.start_result = result; + } + + return 0; +} + +int device_stop(struct Device* device) { + if (!device->internal.state.added) { + return ERROR_INVALID_STATE; + } + + // Already stopped + if (!device->internal.state.started) { + return 0; + } + + int result = driver_unbind(device->internal.driver, device); + if (result != 0) { + // Re-add to bus + if (device->internal.bus != nullptr) { + bus_add_device(device->internal.bus, device); + } + return result; + } + + device->internal.state.started = false; + device->internal.state.start_result = 0; + return 0; +} + +void device_set_parent(Device* device, Device* parent) { + assert(!device->internal.state.started); + device->internal.parent = parent; +} + +} // extern "C" diff --git a/core/source/Driver.cpp b/core/source/Driver.cpp new file mode 100644 index 00000000..8e852faa --- /dev/null +++ b/core/source/Driver.cpp @@ -0,0 +1,146 @@ +#include +#include + +#include +#include +#include +#include + +struct DriverInternalData { + Mutex mutex; + int use_count = 0; +}; + +struct DriverLedger { + std::vector drivers = {}; + Mutex mutex {}; + + DriverLedger() { + mutex_construct(&mutex); + } + + ~DriverLedger() { + mutex_destruct(&mutex); + } +}; + +static DriverLedger ledger; + +#define TAG "driver" + +#define ledger_lock() mutex_lock(&ledger.mutex); +#define ledger_unlock() mutex_unlock(&ledger.mutex); + +#define driver_internal_data(driver) static_cast(driver->internal.data) +#define driver_lock(driver) mutex_lock(&driver_internal_data(driver)->mutex); +#define driver_unlock(driver) mutex_unlock(&driver_internal_data(driver)->mutex); + + +static void driver_add(Driver* dev) { + LOG_I(TAG, "add %s", dev->name); + ledger_lock(); + ledger.drivers.push_back(dev); + ledger_unlock(); +} + +static bool driver_remove(Driver* dev) { + LOG_I(TAG, "remove %s", dev->name); + + ledger_lock(); + const auto iterator = std::ranges::find(ledger.drivers, dev); + // check that there actually is a 3 in our vector + if (iterator == ledger.drivers.end()) { + return false; + } + ledger.drivers.erase(iterator); + ledger_unlock(); + + return true; +} + +extern "C" { + +int driver_construct(Driver* driver) { + driver->internal.data = new DriverInternalData(); + driver_add(driver); + return 0; +} + +int driver_destruct(Driver* driver) { + // Check if in use + if (driver_internal_data(driver)->use_count == 0) { + return ERROR_INVALID_STATE; + } + + driver_remove(driver); + delete driver_internal_data(driver); + return 0; +} + +Driver* driver_find(const char* name) { + ledger_lock(); + const auto it = std::ranges::find_if(ledger.drivers, [name](Driver* driver) { + return strcmp(name, driver->name) == 0; + }); + auto* driver = (it != ledger.drivers.end()) ? *it : nullptr; + ledger_unlock(); + return driver; +} + +int driver_bind(Driver* driver, Device* device) { + driver_lock(driver); + + int err = 0; + if (!device_is_added(device)) { + err = -ENODEV; + goto error; + } + + device_set_driver(device, driver); + + if (driver->start_device != nullptr) { + err = driver->start_device(device); + if (err != 0) { + goto error; + } + } + + driver_internal_data(driver)->use_count++; + driver_unlock(driver); + + LOG_I(TAG, "bound %s to %s", driver->name, device->name); + return 0; + +error: + + driver_unlock(driver); + return err; +} + +int driver_unbind(Driver* driver, Device* device) { + driver_lock(driver); + + if (driver->stop_device == nullptr) { + return 0; + } + + int err = driver->stop_device(device); + if (err != 0) { + goto error; + } + + device_set_driver(device, nullptr); + driver_internal_data(driver)->use_count--; + driver_unlock(driver); + + LOG_I(TAG, "unbound %s to %s", driver->name, device->name); + + return 0; + +error: + + driver_unlock(driver); + return err; +} + +} // extern "C" diff --git a/core/source/log.c b/core/source/Log.cpp similarity index 97% rename from core/source/log.c rename to core/source/Log.cpp index 867d8597..6fe18ca6 100644 --- a/core/source/log.c +++ b/core/source/Log.cpp @@ -1,7 +1,7 @@ -#include - #ifndef ESP_PLATFORM +#include + #include #include diff --git a/core/source/device.c b/core/source/device.c deleted file mode 100644 index cd3cd8e2..00000000 --- a/core/source/device.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -#include -#include -#include - -#define CONFIG_DEVICE_INDEX_SIZE 64 -#define TAG "device" - -// TODO: Automatically increase allocated size -static const struct device* device_index[CONFIG_DEVICE_INDEX_SIZE ] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -uint8_t device_init(struct device* const dev) { - assert(dev != NULL); - LOG_I(TAG, "init %s", dev->name); - - if (!dev->state.initialized) { - if (dev->operations.init == NULL) { - dev->state.initialized = true; - dev->state.init_result = 0U; - } else { - dev->state.init_result = dev->operations.init(dev); - dev->state.initialized = dev->state.init_result == 0U; - } - } - - return dev->state.init_result; -} - -bool device_init_all(struct device** const device_array) { - assert(device_array != NULL); - struct device** current_device = device_array; - bool all_succeeded = true; - while (*current_device != NULL) { - struct device* device = *current_device; - if (device_init(device) != 0U) { - all_succeeded = false; - } - current_device++; - } - return all_succeeded; -} - -uint8_t device_deinit(struct device* const dev) { - assert(dev != NULL); - LOG_I(TAG, "deinit %s", dev->name); - - if (dev->state.initialized) { - if (dev->operations.deinit != NULL) { - dev->state.init_result = dev->operations.deinit(dev); - if (dev->state.init_result == 0U) { - dev->state.initialized = false; - } - } else { - dev->state.initialized = false; - } - } - - return !dev->state.init_result; -} - -bool device_is_ready(const struct device* const dev) { - assert(dev != NULL); - return dev->state.initialized && (dev->state.init_result == 0U); -} - - -void device_add(const struct device* dev) { - assert(dev != NULL); - LOG_I(TAG, "add %s", dev->name); - for (int i = 0; i < CONFIG_DEVICE_INDEX_SIZE; i++) { - if (device_index[i] == NULL) { - device_index[i] = dev; - return; - } - } - assert(false); // out of space -} - -void device_add_all(struct device** const device_array) { - assert(device_array != NULL); - struct device** current_device = device_array; - while (*current_device != NULL) { - struct device* device = *current_device; - device_add(device); - current_device++; - } -} - -bool device_remove(const struct device* dev) { - assert(dev != NULL); - LOG_I(TAG, "remove %s", dev->name); - for (int i = 0; i < CONFIG_DEVICE_INDEX_SIZE; i++) { - if (device_index[i] == dev) { - device_index[i] = NULL; - return true; - } - } - return false; -} - -bool device_find_next_by_compatible(const char* identifier, const struct device** dev) { - bool found_first = (*dev == NULL); - for (int device_idx = 0; device_idx < CONFIG_DEVICE_INDEX_SIZE; device_idx++) { - const struct device* indexed_device = device_index[device_idx]; - if (indexed_device != NULL) { - if (!found_first) { - if (indexed_device == *dev) { - found_first = true; - } - } else { - for (int label_idx = 0; label_idx< indexed_device->metadata.compatible_count; ++label_idx) { - const char* indexed_device_label = indexed_device->metadata.compatible[label_idx]; - if (strcmp(indexed_device_label, identifier) == 0) { - *dev = indexed_device; - return true; - } - } - } - } - } - return false; -} diff --git a/core/source/drivers/GpioController.cpp b/core/source/drivers/GpioController.cpp new file mode 100644 index 00000000..cd4e4971 --- /dev/null +++ b/core/source/drivers/GpioController.cpp @@ -0,0 +1,28 @@ +#include +#include + +#define GPIO_DRIVER_API(driver) ((struct GpioControllerApi*)driver->api) + +extern "C" { + +bool gpio_controller_set_level(Device* device, gpio_pin_t pin, bool high) { + const auto* driver = device_get_driver(device); + return GPIO_DRIVER_API(driver)->set_level(device, pin, high); +} + +bool gpio_controller_get_level(Device* device, gpio_pin_t pin, bool* high) { + const auto* driver = device_get_driver(device); + return GPIO_DRIVER_API(driver)->get_level(device, pin, high); +} + +bool gpio_controller_set_options(Device* device, gpio_pin_t pin, gpio_flags_t options) { + const auto* driver = device_get_driver(device); + return GPIO_DRIVER_API(driver)->set_options(device, pin, options); +} + +bool gpio_controller_get_options(Device* device, gpio_pin_t pin, gpio_flags_t* options) { + const auto* driver = device_get_driver(device); + return GPIO_DRIVER_API(driver)->get_options(device, pin, options); +} + +} diff --git a/core/source/drivers/I2cController.cpp b/core/source/drivers/I2cController.cpp new file mode 100644 index 00000000..3592c82b --- /dev/null +++ b/core/source/drivers/I2cController.cpp @@ -0,0 +1,23 @@ +#include +#include + +#define I2C_DRIVER_API(driver) ((struct I2cControllerApi*)driver->api) + +extern "C" { + +bool i2c_controller_read(Device* device, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout) { + const auto* driver = device_get_driver(device); + return I2C_DRIVER_API(driver)->read(device, address, data, dataSize, timeout); +} + +bool i2c_controller_write(Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { + const auto* driver = device_get_driver(device); + return I2C_DRIVER_API(driver)->write(device, address, data, dataSize, timeout); +} + +bool i2c_controller_write_read(Device* device, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout) { + const auto* driver = device_get_driver(device); + return I2C_DRIVER_API(driver)->write_read(device, address, write_data, write_data_size, read_data, read_data_size, timeout); +} + +} diff --git a/core/source/drivers/Root.cpp b/core/source/drivers/Root.cpp new file mode 100644 index 00000000..02980e04 --- /dev/null +++ b/core/source/drivers/Root.cpp @@ -0,0 +1,15 @@ +#include +#include + +extern "C" { + +Driver root_driver = { + .name = "root", + .compatible = (const char*[]) { "root", nullptr }, + .start_device = nullptr, + .stop_device = nullptr, + .api = nullptr, + .internal = { 0 } +}; + +} diff --git a/core/source/drivers/gpio_controller.c b/core/source/drivers/gpio_controller.c deleted file mode 100644 index 61dcbdf0..00000000 --- a/core/source/drivers/gpio_controller.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -#define GPIO_API(dev) ((struct gpio_controller_api*)dev->api) - -bool gpio_controller_set_level(const struct device* dev, gpio_pin_t pin, bool high) { - return GPIO_API(dev)->set_level(dev, pin, high); -} - -bool gpio_controller_get_level(const struct device* dev, gpio_pin_t pin, bool* high) { - return GPIO_API(dev)->get_level(dev, pin, high); -} - -bool gpio_controller_set_options(const struct device* dev, gpio_pin_t pin, gpio_flags_t options) { - return GPIO_API(dev)->set_options(dev, pin, options); -} - -bool gpio_controller_get_options(const struct device* dev, gpio_pin_t pin, gpio_flags_t* options) { - return GPIO_API(dev)->get_options(dev, pin, options); -} diff --git a/core/source/drivers/i2c_controller.c b/core/source/drivers/i2c_controller.c deleted file mode 100644 index c04364bd..00000000 --- a/core/source/drivers/i2c_controller.c +++ /dev/null @@ -1,15 +0,0 @@ -#include - -#define GPIO_API(dev) ((struct i2c_controller_api*)dev->api) - -bool i2c_controller_read(struct device* dev, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout) { - return GPIO_API(dev)->read(dev, address, data, dataSize, timeout); -} - -bool i2c_controller_write(struct device* dev, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { - return GPIO_API(dev)->write(dev, address, data, dataSize, timeout); -} - -bool i2c_controller_write_read(struct device* dev, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout) { - return GPIO_API(dev)->write_read(dev, address, write_data, write_data_size, read_data, read_data_size, timeout); -} diff --git a/core/source/drivers/root.c b/core/source/drivers/root.c deleted file mode 100644 index eb304419..00000000 --- a/core/source/drivers/root.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "tactility/drivers/root.h" - -const struct root_api root_api_instance = {};