HinawaFwNode creates GSource for GLib MainContext. It's easy to GLib MainLoop as event dispatcher. This commit adds local application of GLib MainContext/MainLoop to dispatch events for HinawaFwNode. Signed-off-by: Takashi Sakamoto <o-takashi@xxxxxxxxxxxxx> --- efw-downloader/src/meson.build | 2 + efw-downloader/src/node-dispatcher.c | 86 ++++++++++++++++++++++++++++ efw-downloader/src/node-dispatcher.h | 21 +++++++ efw-downloader/src/subcmd-device.c | 10 ++++ 4 files changed, 119 insertions(+) create mode 100644 efw-downloader/src/node-dispatcher.c create mode 100644 efw-downloader/src/node-dispatcher.h diff --git a/efw-downloader/src/meson.build b/efw-downloader/src/meson.build index c006c8b..c43c332 100644 --- a/efw-downloader/src/meson.build +++ b/efw-downloader/src/meson.build @@ -15,12 +15,14 @@ sources = [ 'main.c', 'efw-proto.c', 'config-rom.c', + 'node-dispatcher.c', 'subcmd-device.c', ] headers = [ 'efw-proto.h', 'config-rom.h', + 'node-dispatcher.h', 'subcmds.h', ] diff --git a/efw-downloader/src/node-dispatcher.c b/efw-downloader/src/node-dispatcher.c new file mode 100644 index 0000000..8394600 --- /dev/null +++ b/efw-downloader/src/node-dispatcher.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2020 Takashi Sakamoto +#include "node-dispatcher.h" +#include <time.h> + +struct thread_arg { + GMainLoop *loop; + GCond cond; + GMutex mutex; +}; + +static gpointer run_node_dispatcher(gpointer data) +{ + struct thread_arg *args = (struct thread_arg *)data; + + g_mutex_lock(&args->mutex); + g_cond_signal(&args->cond); + g_mutex_unlock(&args->mutex); + + g_main_loop_run(args->loop); + + return NULL; +} + +void node_dispatcher_start(struct node_dispatcher *dispatcher, HinawaFwNode *node, GError **error) +{ + struct thread_arg args; + GSource *src; + + dispatcher->ctx = g_main_context_new(); + + hinawa_fw_node_create_source(node, &src, error); + if (*error != NULL) + return; + + g_source_attach(src, dispatcher->ctx); + g_source_unref(src); + + dispatcher->loop = g_main_loop_new(dispatcher->ctx, FALSE); + + args.loop = dispatcher->loop; + g_cond_init(&args.cond); + g_mutex_init(&args.mutex); + + dispatcher->th = g_thread_try_new("node-dispatcher", run_node_dispatcher, &args, error); + if (*error != NULL) { + g_main_loop_quit(dispatcher->loop); + g_main_loop_unref(dispatcher->loop); + dispatcher->loop = NULL; + + g_main_context_unref(dispatcher->ctx); + dispatcher->ctx = NULL; + + goto end; + } + + g_mutex_lock(&args.mutex); + while (!g_main_loop_is_running(dispatcher->loop)) + g_cond_wait(&args.cond, &args.mutex); + g_mutex_unlock(&args.mutex); +end: + g_cond_clear(&args.cond); + g_mutex_clear(&args.mutex); +} + +void node_dispatcher_stop(struct node_dispatcher *dispatcher) +{ + if (dispatcher->loop != NULL) + g_main_loop_quit(dispatcher->loop); + + if (dispatcher->th != NULL) { + g_thread_join(dispatcher->th); + g_thread_unref(dispatcher->th); + dispatcher->th = NULL; + } + + if (dispatcher->loop != NULL) { + g_main_loop_unref(dispatcher->loop); + dispatcher->loop = NULL; + } + + if (dispatcher->ctx != NULL) { + g_main_context_unref(dispatcher->ctx); + dispatcher->ctx = NULL; + } +} diff --git a/efw-downloader/src/node-dispatcher.h b/efw-downloader/src/node-dispatcher.h new file mode 100644 index 0000000..9e47e00 --- /dev/null +++ b/efw-downloader/src/node-dispatcher.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2020 Takashi Sakamoto +#ifndef __NODE_DISPATCHER_H__ +#define __NODE_DISPATCHER_H__ + +#include <glib.h> +#include <glib-object.h> + +#include <libhinawa/fw_node.h> +#include <libhinawa/fw_resp.h> + +struct node_dispatcher { + GMainContext *ctx; + GMainLoop *loop; + GThread *th; +}; + +void node_dispatcher_start(struct node_dispatcher *dispatcher, HinawaFwNode *node, GError **error); +void node_dispatcher_stop(struct node_dispatcher *dispatcher); + +#endif diff --git a/efw-downloader/src/subcmd-device.c b/efw-downloader/src/subcmd-device.c index 1bfa1f2..5ac0ac6 100644 --- a/efw-downloader/src/subcmd-device.c +++ b/efw-downloader/src/subcmd-device.c @@ -7,6 +7,7 @@ #include "efw-proto.h" #include "config-rom.h" +#include "node-dispatcher.h" #define report_error(error, msg) \ fprintf(stderr, "Fail to %s: %s %d %s\n", \ @@ -60,6 +61,7 @@ int subcmd_device(int argc, char **argv) gsize length; guint32 vendor_id, model_id; EfwProto *proto; + struct node_dispatcher dispatcher = {0}; int err; int i; @@ -116,8 +118,16 @@ int subcmd_device(int argc, char **argv) goto err_node; } + node_dispatcher_start(&dispatcher, node, &error); + if (error != NULL) { + report_error(error, "begin dispatcher"); + goto err_proto; + } + entry->op(argc, argv, proto, &error); + node_dispatcher_stop(&dispatcher); +err_proto: efw_proto_unbind(proto); g_object_unref(proto); err_node: -- 2.25.1