From cf6aa0ecbb0b0fe5c06bd5fc87eaa58e2ab47573 Mon Sep 17 00:00:00 2001 From: Niraj Kumar Goit Date: Mon, 14 Aug 2017 19:45:43 +0530 Subject: [connman]Added DBus method for wifi Specific AP Scan. Change-Id: Ib8f446164242caeb7fbc29c2917eff4b8a5b8bf7 Signed-off-by: Niraj Kumar Goit --- include/device.h | 5 +++ plugins/wifi.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/connman.h | 4 ++ src/device.c | 67 ++++++++++++++++++++++++++++++ src/technology.c | 73 +++++++++++++++++++++++++++++++++ 5 files changed, 271 insertions(+) diff --git a/include/device.h b/include/device.h index 57b925c4..dafdca25 100755 --- a/include/device.h +++ b/include/device.h @@ -130,6 +130,11 @@ struct connman_device_driver { const char *security, void *user_data); int (*set_regdom) (struct connman_device *device, const char *alpha2); +#if defined TIZEN_EXT + int (*specific_scan) (enum connman_service_type type, + struct connman_device *device, int scan_type, + GSList *specific_scan_list, void *user_data); +#endif }; int connman_device_driver_register(struct connman_device_driver *driver); diff --git a/plugins/wifi.c b/plugins/wifi.c index 24711417..7f99ace5 100755 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -1831,6 +1831,125 @@ static int p2p_find(struct connman_device *device) return ret; } +#if defined TIZEN_EXT +static void specific_scan_callback(int result, GSupplicantInterface *interface, + void *user_data) +{ + struct connman_device *device = user_data; + struct wifi_data *wifi = connman_device_get_data(device); + bool scanning; + + DBG("result %d wifi %p", result, wifi); + + if (wifi && wifi->scan_params) { + g_supplicant_free_scan_params(wifi->scan_params); + wifi->scan_params = NULL; + } + + scanning = connman_device_get_scanning(device); + if (scanning) { + connman_device_set_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI, false); + connman_device_unref(device); + } +} + +static int wifi_specific_scan(enum connman_service_type type, + struct connman_device *device, int scan_type, + GSList *specific_scan_list, void *user_data) +{ + GSList *list = NULL; + char *ssid = NULL; + struct wifi_data *wifi = connman_device_get_data(device); + GSupplicantScanParams *scan_params = NULL; + struct scan_ssid *scan_ssid; + bool scanning; + int ret; + int freq; + int count = 0; + + if (!wifi) + return -ENODEV; + + if (wifi->p2p_device) + return 0; + + if (type == CONNMAN_SERVICE_TYPE_P2P) + return p2p_find(device); + + if (wifi->tethering) + return 0; + + scanning = connman_device_get_scanning(device); + if (scanning) + return -EALREADY; + + DBG("scan_type: %d", scan_type); + if (scan_type == 1) { /* ssid based scan */ + scan_params = g_try_malloc0(sizeof(GSupplicantScanParams)); + if (!scan_params) + return -ENOMEM; + + scan_ssid = g_try_new0(struct scan_ssid, 1); + if (!scan_ssid) { + g_free(scan_params); + return -ENOMEM; + } + for (list = specific_scan_list; list; list = list->next) { + ssid = (char *)list->data; + int ssid_len = strlen(ssid); + + memcpy(scan_ssid->ssid, ssid, (ssid_len + 1)); + DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); + scan_ssid->ssid_len = ssid_len; + scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid); + count++; + } + scan_params->num_ssids = count; + + } else if (scan_type == 2) { /* frequency based scan */ + + scan_params = g_try_malloc0(sizeof(GSupplicantScanParams)); + if (!scan_params) + return -ENOMEM; + + scan_params->freqs = g_try_new0(uint16_t, 1); + if (!scan_params->freqs) { + g_free(scan_params); + return -ENOMEM; + } + count = 0; + for (list = specific_scan_list; list; list = list->next) { + freq = (int)list->data; + DBG("freq: %d", freq); + scan_params->freqs[count] = freq; + count++; + } + scan_params->num_freqs = count; + + } else { + DBG("Invalid scan"); + return -EINVAL; + } + + reset_autoscan(device); + connman_device_ref(device); + + ret = g_supplicant_interface_scan(wifi->interface, scan_params, + specific_scan_callback, device); + + if (ret == 0) { + connman_device_set_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI, true); + } else { + g_supplicant_free_scan_params(scan_params); + connman_device_unref(device); + } + + return ret; +} +#endif + /* * Note that the hidden scan is only used when connecting to this specific * hidden AP first time. It is not used when system autoconnects to hidden AP. @@ -2009,6 +2128,9 @@ static struct connman_device_driver wifi_ng_driver = { .disable = wifi_disable, .scan = wifi_scan, .set_regdom = wifi_set_regdom, +#if defined TIZEN_EXT + .specific_scan = wifi_specific_scan, +#endif }; static void system_ready(void) diff --git a/src/connman.h b/src/connman.h index dcd8c7f9..5e257bf6 100755 --- a/src/connman.h +++ b/src/connman.h @@ -576,6 +576,10 @@ int __connman_device_request_hidden_scan(struct connman_device *device, const char *ssid, unsigned int ssid_len, const char *identity, const char *passphrase, const char *security, void *user_data); +#if defined TIZEN_EXT +int __connman_device_request_specific_scan(enum connman_service_type type, + int scan_type, GSList *specific_scan_list); +#endif bool __connman_device_isfiltered(const char *devname); diff --git a/src/device.c b/src/device.c index aff0fa93..acd68da4 100755 --- a/src/device.c +++ b/src/device.c @@ -1077,6 +1077,73 @@ void connman_device_regdom_notify(struct connman_device *device, __connman_technology_notify_regdom_by_device(device, result, alpha2); } +#if defined TIZEN_EXT +static int device_specific_scan(enum connman_service_type type, + struct connman_device *device, + int scan_type, GSList *specific_scan_list) +{ + if (!device->driver || !device->driver->specific_scan) + return -EOPNOTSUPP; + + if (!device->powered) + return -ENOLINK; + + return device->driver->specific_scan(type, device, scan_type, + specific_scan_list, NULL); +} + +int __connman_device_request_specific_scan(enum connman_service_type type, + int scan_type, GSList *specific_scan_list) +{ + bool success = false; + int last_err = -ENOSYS; + GSList *list; + int err; + + switch (type) { + case CONNMAN_SERVICE_TYPE_UNKNOWN: + case CONNMAN_SERVICE_TYPE_SYSTEM: + case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_BLUETOOTH: + case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_GPS: + case CONNMAN_SERVICE_TYPE_VPN: + case CONNMAN_SERVICE_TYPE_GADGET: + return -EOPNOTSUPP; + case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_P2P: + break; + } + + for (list = device_list; list; list = list->next) { + struct connman_device *device = list->data; + enum connman_service_type service_type = + __connman_device_get_service_type(device); + + if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) { + if (type == CONNMAN_SERVICE_TYPE_P2P) { + if (service_type != CONNMAN_SERVICE_TYPE_WIFI) + continue; + } else if (service_type != type) + continue; + } + + err = device_specific_scan(type, device, scan_type, specific_scan_list); + if (err == 0 || err == -EALREADY || err == -EINPROGRESS) { + success = true; + } else { + last_err = err; + DBG("device %p err %d", device, err); + } + } + + if (success) + return 0; + + return last_err; +} +#endif + int __connman_device_request_scan(enum connman_service_type type) { bool success = false; diff --git a/src/technology.c b/src/technology.c index 29707f92..fb39d34f 100755 --- a/src/technology.c +++ b/src/technology.c @@ -1173,6 +1173,77 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) } #if defined TIZEN_EXT +static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + GSList *specific_scan_list = NULL; + int scan_type = 0; + const char *name = NULL; + unsigned int freq = 0; + DBusMessageIter iter, dict; + int err; + + DBG("technology %p request from %s", technology, + dbus_message_get_sender(msg)); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&iter, &dict); + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&entry, &value2); + type = dbus_message_iter_get_arg_type(&value2); + if (g_str_equal(key, "SSID")) { + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + scan_type = 1; /* SSID based scan */ + dbus_message_iter_get_basic(&value2, &name); + DBG("name %s", name); + specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name)); + } else if (g_str_equal(key, "Frequency")) { + if (type != DBUS_TYPE_UINT16) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + scan_type = 2; /* Frequency based scan */ + dbus_message_iter_get_basic(&value2, &freq); + DBG("freq %d", freq); + specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(freq)); + } + dbus_message_iter_next(&dict); + } + + dbus_message_ref(msg); + technology->scan_pending = + g_slist_prepend(technology->scan_pending, msg); + + err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list); + if (err < 0) + reply_scan_pending(technology, err); + + g_slist_free_full(specific_scan_list, g_free); + return NULL; +} + static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; @@ -1216,6 +1287,8 @@ static const GDBusMethodTable technology_methods[] = { GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL, set_property) }, { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) }, + { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }), + NULL, specific_scan) }, #if defined TIZEN_EXT { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }), get_scan_state) }, -- cgit v1.2.3