// Copyright 2020 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include #include #include #include #include #include #include #include "json-c/json.h" #include "dbus_signal.h" #include "IPCProtocol.h" static DBusConnection *dbusconn = 0; int need_loop = 1; GMainLoop *main_loop = NULL; struct DbusSignal { char *interface; char *signal; dbus_signal_func_t cb; struct DbusSignal *next; }; static struct DbusSignal *dbus_signal_list = NULL; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static void *loop_thread(void *arg) { main_loop = g_main_loop_new(NULL, FALSE); //g_timeout_add(100, time_cb, NULL); g_main_loop_run(main_loop); if (main_loop) g_main_loop_unref(main_loop); main_loop = NULL; return 0; } static DBusHandlerResult dbus_monitor_changed( DBusConnection *connection, DBusMessage *message, void *user_data) { DBusMessageIter iter; DBusHandlerResult handled; handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; pthread_mutex_lock(&mutex); struct DbusSignal *tmp = dbus_signal_list; while(tmp) { if (dbus_message_is_signal(message, tmp->interface, tmp->signal)) { char *json_str; handled = DBUS_HANDLER_RESULT_HANDLED; dbus_message_iter_init(message, &iter); dbus_message_iter_get_basic(&iter, &json_str); if (tmp->cb) tmp->cb(json_str); } tmp = tmp->next; } pthread_mutex_unlock(&mutex); return handled; } static struct DbusSignal *check_dbus_signel(char *interface, char *signal, dbus_signal_func_t cb) { struct DbusSignal *tmp = dbus_signal_list; while(tmp) { if ((cb == tmp->cb) && g_str_equal(interface, tmp->interface) && (g_str_equal(signal, tmp->signal))) break; tmp = tmp->next; } return tmp; } static void add_dbus_sigal(struct DbusSignal *dbus_signal) { struct DbusSignal *tmp = dbus_signal_list; if (tmp == NULL) { dbus_signal_list = dbus_signal; } else { while(tmp->next) tmp = tmp->next; tmp->next = dbus_signal; } } void dbus_monitor_signal_registered(char *interface, char *signal, dbus_signal_func_t cb) { DBusError err; char *tmp; if (need_loop && main_loop == NULL) { pthread_t tid; pthread_create(&tid, NULL, loop_thread, NULL); } dbus_error_init(&err); if (dbusconn == NULL) { pthread_mutex_init(&mutex, NULL); dbusconn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &err); dbus_connection_add_filter(dbusconn, dbus_monitor_changed, NULL, NULL); } if (check_dbus_signel(interface, signal, cb) == NULL) { struct DbusSignal *dbus_signal = (struct DbusSignal *)malloc(sizeof(struct DbusSignal)); dbus_signal->interface = g_strdup(interface); dbus_signal->signal = g_strdup(signal); dbus_signal->cb = cb; dbus_signal->next = NULL; add_dbus_sigal(dbus_signal); tmp = g_strdup_printf("type='signal',interface='%s'", interface); dbus_bus_add_match(dbusconn, tmp, &err); g_free(tmp); } } void dbus_monitor_signal_unregistered(char *interface, char *signal, dbus_signal_func_t cb) { struct DbusSignal *tmp = dbus_signal_list; if (tmp == NULL) return; pthread_mutex_lock(&mutex); if ((cb == tmp->cb) && g_str_equal(interface, tmp->interface) && (g_str_equal(signal, tmp->signal))) { g_free(tmp->interface); g_free(tmp->signal); dbus_signal_list = tmp->next; free(tmp); } else { struct DbusSignal *tmp_pre = tmp; tmp = tmp->next; while(tmp) { if ((cb == tmp->cb) && g_str_equal(interface, tmp->interface) && (g_str_equal(signal, tmp->signal))) { g_free(tmp->interface); g_free(tmp->signal); tmp_pre = tmp->next; free(tmp); break; } tmp_pre = tmp; tmp = tmp->next; } } pthread_mutex_unlock(&mutex); } void disable_loop(void) { need_loop = 0; }