This commit is contained in:
Ken Van Hoeylandt 2026-01-21 00:04:16 +01:00
parent cd7ffd3cb1
commit f50fbfe331
4 changed files with 54 additions and 17 deletions

View File

@ -115,7 +115,7 @@ def write_device_structs(file, device: Device, bindings: list[Binding], verbose:
write_config(file, device, bindings, type_name)
# Write device struct
file.write(f"static struct Device {identifier}" " = {\n")
file.write(f"\t.name = \"{identifier}\",\n")
file.write(f"\t.name = \"{device.identifier}\",\n") # Use original name
file.write(f"\t.config = (void*)&{config_variable_name},\n")
file.write("};\n\n")
# Child devices
@ -133,22 +133,13 @@ def write_device_init(file, device: Device, parent_device: Device, bindings: lis
# 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");
file.write(f"\tif (init_builtin_device(&{device_variable}, \"{compatible_property.value}\", {parent_value}) != 0) return -1;\n")
# Write children
for child_device in device.devices:
write_device_init(file, child_device, device, bindings, verbose)
@ -172,13 +163,43 @@ 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 <Tactility/Device.h>\n")
file.write("#include <Tactility/Driver.h>\n")
file.write(dedent('''\
// Generated includes
#include <Tactility/Device.h>
#include <Tactility/Driver.h>
#include <Tactility/Log.h>
// DTS includes
'''))
# Write all headers first
for item in items:
if type(item) is IncludeC:
write_include(file, item, verbose)
file.write("\n")
file.write(dedent('''\
#define TAG "devicetree"
static int init_builtin_device(struct Device* device, const char* compatible, struct Device* parent_device) {
struct Driver* driver = driver_find(compatible);
if (driver == NULL) {
LOG_E(TAG, "Can't find driver: %s", compatible);
return -1;
}
device_construct(device);
device_set_driver(device, driver);
device_set_parent(device, parent_device);
device_add(device);
const int err = device_start(device);
if (err != 0) {
LOG_E(TAG, "Failed to start device %s with driver %s: error code %d", device->name, compatible, err);
return -1;
}
return 0;
}
'''))
# Then write all devices
for item in items:
if type(item) is Device:

View File

@ -29,7 +29,7 @@ int driver_construct(struct Driver* drv);
int driver_destruct(struct Driver* drv);
struct Driver* driver_find(const char* name);
struct Driver* driver_find(const char* compatible);
int driver_bind(struct Driver* drv, struct Device* dev);

View File

@ -22,7 +22,7 @@ void log_generic(const char* tag, const char* format, ...);
#else
#define LOG_E(x, ...) ESP_LOGD(x, ##__VA_ARGS__)
#define LOG_E(x, ...) ESP_LOGE(x, ##__VA_ARGS__)
#define LOG_W(x, ...) ESP_LOGW(x, ##__VA_ARGS__)
#define LOG_I(x, ...) ESP_LOGI(x, ##__VA_ARGS__)
#define LOG_D(x, ...) ESP_LOGD(x, ##__VA_ARGS__)

View File

@ -7,8 +7,16 @@
#include <Tactility/Log.h>
struct DriverInternalData {
Mutex mutex;
Mutex mutex {};
int use_count = 0;
DriverInternalData() {
mutex_construct(&mutex);
}
~DriverInternalData() {
mutex_destruct(&mutex);
}
};
struct DriverLedger {
@ -80,7 +88,15 @@ int driver_destruct(Driver* driver) {
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;
const char** current_compatible = driver->compatible;
assert(current_compatible != nullptr);
while (*current_compatible != nullptr) {
if (strcmp(name, *current_compatible) == 0) {
return 0;
}
current_compatible++;
}
return -1;
});
auto* driver = (it != ledger.drivers.end()) ? *it : nullptr;
ledger_unlock();