From ace7fdcba81dc1fe26eda148acc149094260e451 Mon Sep 17 00:00:00 2001 From: Leena Gunda Date: Fri, 22 Oct 2010 11:53:39 +0200 Subject: [PATCH] gsupplicant: Get all BSSs when scan is done After a scan, all BSSs need to be refreshed and passed back to the device layer or else the WiFi device networks list is emptied. Fixes BMC#8324 Fixes BMC#8363 --- gsupplicant/dbus.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ gsupplicant/dbus.h | 5 +++ gsupplicant/supplicant.c | 60 +++++++++++++++++++++++++++++----- 3 files changed, 141 insertions(+), 8 deletions(-) diff --git a/gsupplicant/dbus.c b/gsupplicant/dbus.c index 23593f4..53c56ae 100644 --- a/gsupplicant/dbus.c +++ b/gsupplicant/dbus.c @@ -182,6 +182,90 @@ int supplicant_dbus_property_get_all(const char *path, const char *interface, return 0; } +static void property_get_reply(DBusPendingCall *call, void *user_data) +{ + struct property_get_data *data = user_data; + DBusMessage *reply; + DBusMessageIter iter; + + reply = dbus_pending_call_steal_reply(call); + + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) + goto done; + + if (dbus_message_iter_init(reply, &iter) == FALSE) + goto done; + + if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) { + DBusMessageIter variant; + + dbus_message_iter_recurse(&iter, &variant); + + if (data->function != NULL) + data->function(NULL, &variant, data->user_data); + } +done: + dbus_message_unref(reply); + + dbus_pending_call_unref(call); +} + +int supplicant_dbus_property_get(const char *path, const char *interface, + const char *method, + supplicant_dbus_property_function function, + void *user_data) +{ + struct property_get_data *data; + DBusMessage *message; + DBusPendingCall *call; + + if (connection == NULL) + return -EINVAL; + + if (path == NULL || interface == NULL || method == NULL) + return -EINVAL; + + data = dbus_malloc0(sizeof(*data)); + if (data == NULL) + return -ENOMEM; + + message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path, + DBUS_INTERFACE_PROPERTIES, "Get"); + + if (message == NULL) { + dbus_free(data); + return -ENOMEM; + } + + dbus_message_set_auto_start(message, FALSE); + + dbus_message_append_args(message, DBUS_TYPE_STRING, &interface, + DBUS_TYPE_STRING, &method, NULL); + + if (dbus_connection_send_with_reply(connection, message, + &call, TIMEOUT) == FALSE) { + dbus_message_unref(message); + dbus_free(data); + return -EIO; + } + + if (call == NULL) { + dbus_message_unref(message); + dbus_free(data); + return -EIO; + } + + data->function = function; + data->user_data = user_data; + + dbus_pending_call_set_notify(call, property_get_reply, + data, dbus_free); + + dbus_message_unref(message); + + return 0; +} + struct property_set_data { supplicant_dbus_result_function function; void *user_data; diff --git a/gsupplicant/dbus.h b/gsupplicant/dbus.h index 254b93e..642e8b1 100644 --- a/gsupplicant/dbus.h +++ b/gsupplicant/dbus.h @@ -51,6 +51,11 @@ int supplicant_dbus_property_get_all(const char *path, const char *interface, supplicant_dbus_property_function function, void *user_data); +int supplicant_dbus_property_get(const char *path, const char *interface, + const char *method, + supplicant_dbus_property_function function, + void *user_data); + int supplicant_dbus_property_set(const char *path, const char *interface, const char *key, const char *signature, supplicant_dbus_setup_function setup, diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index 2670c94..322b63d 100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -1300,6 +1300,45 @@ static void interface_property(const char *key, DBusMessageIter *iter, key, dbus_message_iter_get_arg_type(iter)); } +static void scan_network_update(DBusMessageIter *iter, void *user_data) +{ + GSupplicantInterface *interface = user_data; + GSupplicantNetwork *network; + char *path; + + if (iter == NULL) + return; + + dbus_message_iter_get_basic(iter, &path); + + if (path == NULL) + return; + + if (g_strcmp0(path, "/") == 0) + return; + + /* Update the network details based on scan BSS data */ + network = g_hash_table_lookup(interface->bss_mapping, path); + if (network != NULL) + callback_network_added(network); +} + +static void scan_bss_data(const char *key, DBusMessageIter *iter, + void *user_data) +{ + GSupplicantInterface *interface = user_data; + + if (iter) + supplicant_dbus_array_foreach(iter, scan_network_update, + interface); + + if (interface->scan_callback != NULL) + interface->scan_callback(0, interface, interface->scan_data); + + interface->scan_callback = NULL; + interface->scan_data = NULL; +} + static GSupplicantInterface *interface_alloc(const char *path) { GSupplicantInterface *interface; @@ -1511,18 +1550,23 @@ static void signal_scan_done(const char *path, DBusMessageIter *iter) dbus_message_iter_get_basic(iter, &success); - if (interface->scan_callback != NULL) { - int result = 0; + /* + * If scan is unsuccessful return -EIO else get the scanned BSSs + * and update the network details accordingly + */ + if (success == FALSE) { + if (interface->scan_callback != NULL) + interface->scan_callback(-EIO, interface, + interface->scan_data); - if (success == FALSE) - result = -EIO; + interface->scan_callback = NULL; + interface->scan_data = NULL; - interface->scan_callback(result, interface, - interface->scan_data); + return; } - interface->scan_callback = NULL; - interface->scan_data = NULL; + supplicant_dbus_property_get(path, SUPPLICANT_INTERFACE ".Interface", + "BSSs", scan_bss_data, interface); } static void signal_bss_added(const char *path, DBusMessageIter *iter) -- 2.7.4