[PATCH DRAFT RFC] upoe: tiny daemon for PoE devices
Rafał Miłecki
zajec5 at gmail.com
Wed May 12 15:57:37 PDT 2021
From: Rafał Miłecki <rafal at milecki.pl>
This is a tiny app that reads list of PoE devices and initializes them
using built-in drivers. PoE status can be read using ubus.
Signed-off-by: Rafał Miłecki <rafal at milecki.pl>
---
This is a *** DRAFT *** for how we could handle PoE devices in OpenWrt.
Please feel free to comment if this EARLY & INCOMPLETE design looks sane
enough.
---
CMakeLists.txt | 9 ++++
dummy.c | 24 +++++++++
upoe.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++
upoe.h | 36 +++++++++++++
4 files changed, 213 insertions(+)
create mode 100644 CMakeLists.txt
create mode 100644 dummy.c
create mode 100644 upoe.c
create mode 100644 upoe.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..6474663
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.6)
+
+project(upoe)
+set(CMAKE_C_FLAGS "-std=c99 -D_GNU_SOURCE -Wall")
+
+add_executable(upoe upoe.c dummy.c)
+target_link_libraries(upoe ubox ubus uci)
+
+install(TARGETS upoe RUNTIME DESTINATION bin)
diff --git a/dummy.c b/dummy.c
new file mode 100644
index 0000000..de0abfb
--- /dev/null
+++ b/dummy.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "upoe.h"
+
+static int upoe_dummy_probe_device(struct upoe *upoe, struct uci_element *e)
+{
+ struct device *dev = calloc(1, sizeof(*dev));
+
+ dev->drv = &dummy;
+ upoe_device_register(upoe, dev);
+
+ return 0;
+}
+
+static int upoe_dummy_get_status(struct upoe *upoe, struct device *dev)
+{
+ return 0;
+}
+
+struct driver dummy = {
+ .type = "dummy",
+ .probe_device = upoe_dummy_probe_device,
+ .get_status = upoe_dummy_get_status,
+};
diff --git a/upoe.c b/upoe.c
new file mode 100644
index 0000000..3dfa834
--- /dev/null
+++ b/upoe.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "upoe.h"
+
+/**************************************************
+ * Device
+ **************************************************/
+
+static int upoe_device_status(struct ubus_context *ctx,
+ struct ubus_object *obj,
+ struct ubus_request_data *req,
+ const char *method,
+ struct blob_attr *msg)
+{
+ struct upoe *upoe = container_of(ctx, struct upoe, ubus);
+ struct device *dev = container_of(obj, struct device, ubus_obj);
+ struct blob_buf b = { };
+ //void *c;
+
+ blob_buf_init(&b, 0);
+
+ dev->drv->get_status(upoe, dev);
+ blobmsg_add_string(&b, "foo", "bar");
+
+ ubus_send_reply(ctx, req, b.head);
+
+ blob_buf_free(&b);
+
+ return 0;
+}
+
+static const struct ubus_method upoe_ubus_device_methods[] = {
+ UBUS_METHOD_NOARG("status", upoe_device_status),
+};
+
+static struct ubus_object_type upoe_ubus_device_object_type =
+ UBUS_OBJECT_TYPE("upoe-device", upoe_ubus_device_methods);
+
+int upoe_device_register(struct upoe *upoe, struct device *dev)
+{
+ struct ubus_object *obj = &dev->ubus_obj;
+ char *name = NULL;
+ int err;
+
+ if (asprintf(&name, "upoe.%s", "dummy0") == -1)
+ return -ENOMEM;
+
+ obj->name = name;
+ obj->type = &upoe_ubus_device_object_type;
+ obj->methods = upoe_ubus_device_methods;
+ obj->n_methods = ARRAY_SIZE(upoe_ubus_device_methods);
+
+ err = ubus_add_object(&upoe->ubus, obj);
+ if (err) {
+ fprintf(stderr, "Failed to add ubus object\n");
+ free(name);
+ }
+
+ return err;
+}
+
+/**************************************************
+ * main()
+ **************************************************/
+
+static struct driver *drivers[] = {
+ &dummy,
+};
+
+static int upoe_probe_devices(struct upoe *upoe) {
+ struct uci_package *p;
+ struct uci_element *e;
+
+ uci_load(upoe->uci, "upoe", &p);
+ if (!p) {
+ fprintf(stderr, "Failed to load upoe config\n");
+ return -ENOENT;
+ }
+
+ uci_foreach_element(&p->sections, e) {
+ struct uci_section *s;
+ const char *type;
+ int i;
+
+ s = uci_to_section(e);
+
+ if (strcmp(s->type, "device"))
+ continue;
+
+ type = uci_lookup_option_string(upoe->uci, s, "type");
+ if (!type)
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(drivers); i++) {
+ struct driver *drv = drivers[i];
+
+ if (!strcmp(drv->type, type)) {
+ drv->probe_device(upoe, e);
+ break;
+ }
+ }
+ }
+
+ uci_unload(upoe->uci, p);
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ struct upoe *upoe = calloc(1, sizeof(*upoe));
+ int err;
+
+ if (!upoe) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ upoe->uci = uci_alloc_context();
+ if (!upoe->uci) {
+ err = -ENOMEM;
+ goto err_free_upoe;
+ }
+
+ if (ubus_connect_ctx(&upoe->ubus, NULL)) {
+ fprintf(stderr, "Failed to connect to ubus\n");
+ err = -ENXIO;
+ goto err_uci_free;
+ }
+
+ upoe_probe_devices(upoe);
+
+ uloop_init();
+ ubus_add_uloop(&upoe->ubus);
+ uloop_run();
+ uloop_done();
+
+ ubus_shutdown(&upoe->ubus);
+err_uci_free:
+ uci_free_context(upoe->uci);
+err_free_upoe:
+ free(upoe);
+err_out:
+ return err;
+}
diff --git a/upoe.h b/upoe.h
new file mode 100644
index 0000000..c3fd18d
--- /dev/null
+++ b/upoe.h
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifndef UPOE_H_
+#define UPOE_H_
+
+#include <uci.h>
+#include <libubus.h>
+
+struct upoe;
+struct device;
+
+struct driver {
+ const char *type;
+ int (*probe_device)(struct upoe *upoe, struct uci_element *e);
+ int (*get_status)(struct upoe *upoe, struct device *dev);
+};
+
+struct device {
+ struct driver *drv;
+ struct ubus_object ubus_obj;
+ void (*get_status)(struct device *dev);
+
+ struct device *next;
+};
+
+struct upoe {
+ struct uci_context *uci;
+ struct ubus_context ubus;
+ struct device *devices;
+};
+
+int upoe_device_register(struct upoe *upoe, struct device *dev);
+
+struct driver dummy;
+
+#endif
--
2.26.2
More information about the openwrt-devel
mailing list