diff options
author | Daniel Wagner <daniel.wagner@bmw-carit.de> | 2011-08-11 16:56:18 +0200 |
---|---|---|
committer | Daniel Wagner <daniel.wagner@bmw-carit.de> | 2011-08-11 17:40:53 +0200 |
commit | eadf27c4f3d2e872d390ebddbfc77725fd1d5167 (patch) | |
tree | 09fb5439a9328eedc53f5f6f63edc25b02b38d8d | |
parent | 94b80ba600d314127427b9948459a4c86a05015d (diff) | |
download | connman-eadf27c4f3d2e872d390ebddbfc77725fd1d5167.tar.gz connman-eadf27c4f3d2e872d390ebddbfc77725fd1d5167.tar.bz2 connman-eadf27c4f3d2e872d390ebddbfc77725fd1d5167.zip |
notify: Add state_idle()
-rw-r--r-- | include/notifier.h | 1 | ||||
-rw-r--r-- | src/notifier.c | 65 |
2 files changed, 66 insertions, 0 deletions
diff --git a/include/notifier.h b/include/notifier.h index c42f9bec..74c3d6bc 100644 --- a/include/notifier.h +++ b/include/notifier.h @@ -54,6 +54,7 @@ struct connman_notifier { enum connman_service_state state); void (*ipconfig_changed) (struct connman_service *service, struct connman_ipconfig *ipconfig); + void (*idle_state) (connman_bool_t idle); }; int connman_notifier_register(struct connman_notifier *notifier); diff --git a/src/notifier.c b/src/notifier.c index f6d9b00d..aa6611bf 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -30,6 +30,7 @@ static DBusConnection *connection = NULL; static GSList *notifier_list = NULL; +static GHashTable *service_hash = NULL; static gint compare_priority(gconstpointer a, gconstpointer b) { @@ -417,6 +418,17 @@ void __connman_notifier_service_remove(struct connman_service *service) { GSList *list; + if (g_hash_table_lookup(service_hash, service) != NULL) { + /* + * This is a tempory check for consistency. It can be + * removed when there are no reports for the following + * error message. + */ + connman_error("Service state machine inconsistency detected."); + + g_hash_table_remove(service_hash, service); + } + for (list = notifier_list; list; list = list->next) { struct connman_notifier *notifier = list->data; @@ -464,10 +476,26 @@ void __connman_notifier_offlinemode(connman_bool_t enabled) } } +static void notify_idle_state(connman_bool_t idle) +{ + GSList *list; + + DBG("idle %d", idle); + + for (list = notifier_list; list; list = list->next) { + struct connman_notifier *notifier = list->data; + + if (notifier->idle_state) + notifier->idle_state(idle); + } +} + void __connman_notifier_service_state_changed(struct connman_service *service, enum connman_service_state state) { GSList *list; + unsigned int old_size; + connman_bool_t found; for (list = notifier_list; list; list = list->next) { struct connman_notifier *notifier = list->data; @@ -475,6 +503,36 @@ void __connman_notifier_service_state_changed(struct connman_service *service, if (notifier->service_state_changed) notifier->service_state_changed(service, state); } + + old_size = g_hash_table_size(service_hash); + found = g_hash_table_lookup(service_hash, service) != NULL; + + switch (state) { + case CONNMAN_SERVICE_STATE_UNKNOWN: + case CONNMAN_SERVICE_STATE_DISCONNECT: + case CONNMAN_SERVICE_STATE_IDLE: + if (found == FALSE) + break; + + g_hash_table_remove(service_hash, service); + if (old_size == 1) + notify_idle_state(TRUE); + + break; + case CONNMAN_SERVICE_STATE_ASSOCIATION: + case CONNMAN_SERVICE_STATE_CONFIGURATION: + case CONNMAN_SERVICE_STATE_READY: + case CONNMAN_SERVICE_STATE_ONLINE: + case CONNMAN_SERVICE_STATE_FAILURE: + if (found == TRUE) + break; + + g_hash_table_insert(service_hash, service, service); + if (old_size == 0) + notify_idle_state(FALSE); + + break; + } } void __connman_notifier_ipconfig_changed(struct connman_service *service, @@ -542,6 +600,10 @@ int __connman_notifier_init(void) connection = connman_dbus_get_connection(); + service_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, NULL); + + return 0; } @@ -549,5 +611,8 @@ void __connman_notifier_cleanup(void) { DBG(""); + g_hash_table_destroy(service_hash); + service_hash = NULL; + dbus_connection_unref(connection); } |