From: Rafał Miłecki <ra...@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 <ra...@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 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel