@@ -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',
]
new file mode 100644
@@ -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;
+ }
+}
new file mode 100644
@@ -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
@@ -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:
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@sakamocchi.jp> --- 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