[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