mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-19 03:13:14 +00:00
Remove Bus and add DeviceType
This commit is contained in:
parent
c85c4da300
commit
b4966c36f6
@ -20,6 +20,7 @@ Driver tlora_pager_driver = {
|
||||
.start_device = start,
|
||||
.stop_device = stop,
|
||||
.api = nullptr,
|
||||
.device_type = nullptr,
|
||||
.internal = { 0 }
|
||||
};
|
||||
|
||||
|
||||
@ -112,6 +112,7 @@ Driver esp32_gpio_driver = {
|
||||
.start_device = start,
|
||||
.stop_device = stop,
|
||||
.api = (void*)&esp32_gpio_api,
|
||||
.device_type = nullptr,
|
||||
.internal = { 0 }
|
||||
};
|
||||
|
||||
|
||||
@ -84,6 +84,7 @@ Driver esp32_i2c_driver = {
|
||||
.start_device = start,
|
||||
.stop_device = stop,
|
||||
.api = (void*)&esp32_i2c_api,
|
||||
.device_type = &I2C_CONTROLLER_TYPE,
|
||||
.internal = { 0 }
|
||||
};
|
||||
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
#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
|
||||
@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "Driver.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <Tactility/Bus.h>
|
||||
#include <Tactility/concurrent/Mutex.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
@ -13,6 +14,12 @@ extern "C" {
|
||||
|
||||
struct Driver;
|
||||
|
||||
/** Enables discovering devices of the same type */
|
||||
struct DeviceType {
|
||||
/* Placeholder because empty structs have a different size with C vs C++ compilers */
|
||||
uint8_t _;
|
||||
};
|
||||
|
||||
/** Represents a piece of hardware */
|
||||
struct Device {
|
||||
/** The name of the device. Valid characters: a-z a-Z 0-9 - _ . */
|
||||
@ -27,8 +34,6 @@ struct Device {
|
||||
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 */
|
||||
@ -134,18 +139,6 @@ 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);
|
||||
}
|
||||
@ -158,6 +151,18 @@ static inline void device_unlock(struct Device* device) {
|
||||
mutex_unlock(&device->internal.mutex);
|
||||
}
|
||||
|
||||
static inline const struct DeviceType* device_get_type(struct Device* device) {
|
||||
return device->internal.driver->device_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all the known devices of a specific type
|
||||
* @param type the type to filter
|
||||
* @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.
|
||||
*/
|
||||
void for_each_device_of_type(const struct DeviceType* type, void* callback_context, bool(*on_device)(struct Device* device, void* context));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/Bus.h>
|
||||
#include <Tactility/Device.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Device;
|
||||
struct DeviceType;
|
||||
|
||||
struct Driver {
|
||||
/** The driver name */
|
||||
const char* name;
|
||||
@ -18,6 +18,8 @@ struct Driver {
|
||||
int (*stop_device)(struct Device* dev);
|
||||
/** Contains the driver's functions */
|
||||
const void* api;
|
||||
/** Which type of devices this driver creates (can be NULL) */
|
||||
const struct DeviceType* device_type;
|
||||
/** Internal data */
|
||||
struct {
|
||||
/** Contains private data */
|
||||
@ -25,15 +27,19 @@ struct Driver {
|
||||
} internal;
|
||||
};
|
||||
|
||||
int driver_construct(struct Driver* drv);
|
||||
int driver_construct(struct Driver* driver);
|
||||
|
||||
int driver_destruct(struct Driver* drv);
|
||||
int driver_destruct(struct Driver* driver);
|
||||
|
||||
struct Driver* driver_find(const char* compatible);
|
||||
|
||||
int driver_bind(struct Driver* drv, struct Device* dev);
|
||||
int driver_bind(struct Driver* driver, struct Device* device);
|
||||
|
||||
int driver_unbind(struct Driver* drv, struct Device* dev);
|
||||
int driver_unbind(struct Driver* driver, struct Device* device);
|
||||
|
||||
static inline const struct DeviceType* driver_get_device_type(struct Driver* driver) {
|
||||
return driver->device_type;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ bool i2c_controller_write(struct Device* device, uint8_t address, const uint8_t*
|
||||
|
||||
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);
|
||||
|
||||
extern const struct DeviceType I2C_CONTROLLER_TYPE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include <Tactility/concurrent/Mutex.h>
|
||||
#include <Tactility/Bus.h>
|
||||
#include <Tactility/Device.h>
|
||||
#include <Tactility/Driver.h>
|
||||
|
||||
/** Keeps track of all existing buses */
|
||||
struct BusLedger {
|
||||
std::vector<Bus*> buses = {};
|
||||
Mutex mutex {};
|
||||
|
||||
BusLedger() {
|
||||
mutex_construct(&mutex);
|
||||
}
|
||||
|
||||
~BusLedger() {
|
||||
mutex_destruct(&mutex);
|
||||
}
|
||||
};
|
||||
|
||||
/* Internal data for a Bus */
|
||||
struct BusData {
|
||||
std::vector<Device*> devices = {};
|
||||
std::vector<Driver*> 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"
|
||||
@ -90,11 +90,6 @@ void device_add(Device* device) {
|
||||
device_add_child(parent, device);
|
||||
}
|
||||
|
||||
auto* bus = device->internal.bus;
|
||||
if (bus != nullptr) {
|
||||
bus_add_device(bus, device);
|
||||
}
|
||||
|
||||
device->internal.state.added = true;
|
||||
}
|
||||
|
||||
@ -108,11 +103,6 @@ bool device_remove(Device* device) {
|
||||
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->parent;
|
||||
if (parent != nullptr) {
|
||||
@ -138,11 +128,6 @@ failed_ledger_lookup:
|
||||
device_add_child(parent, device);
|
||||
}
|
||||
|
||||
// Re-add to bus
|
||||
if (bus != nullptr) {
|
||||
bus_add_device(bus, device);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -180,15 +165,6 @@ int device_stop(struct Device* device) {
|
||||
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;
|
||||
@ -199,4 +175,19 @@ void device_set_parent(Device* device, Device* parent) {
|
||||
device->parent = parent;
|
||||
}
|
||||
|
||||
void for_each_device_of_type(const DeviceType* type, void* callback_context, bool(*on_device)(Device* device, void* context)) {
|
||||
ledger_lock();
|
||||
for (auto* device : ledger.devices) {
|
||||
auto* driver = device->internal.driver;
|
||||
if (driver != nullptr) {
|
||||
if (driver->device_type == type) {
|
||||
if (!on_device(device, callback_context)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ledger_unlock()
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <Tactility/concurrent/Mutex.h>
|
||||
#include <Tactility/Device.h>
|
||||
#include <Tactility/Driver.h>
|
||||
#include <Tactility/Error.h>
|
||||
#include <Tactility/Log.h>
|
||||
|
||||
@ -20,4 +20,6 @@ bool i2c_controller_write_read(Device* device, uint8_t address, const uint8_t* w
|
||||
return I2C_DRIVER_API(driver)->write_read(device, address, write_data, write_data_size, read_data, read_data_size, timeout);
|
||||
}
|
||||
|
||||
const struct DeviceType I2C_CONTROLLER_TYPE { 0 };
|
||||
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ Driver root_driver = {
|
||||
.start_device = nullptr,
|
||||
.stop_device = nullptr,
|
||||
.api = nullptr,
|
||||
.device_type = nullptr,
|
||||
.internal = { 0 }
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user