#define P2P_LISTEN_PERIOD 500
#define P2P_LISTEN_INTERVAL 2000
+ #define ASSOC_STATUS_AUTH_TIMEOUT 16
#define ASSOC_STATUS_NO_CLIENT 17
+#if defined TIZEN_EXT
+#define LOAD_SHAPING_MAX_RETRIES 7
+#else
#define LOAD_SHAPING_MAX_RETRIES 3
+#endif
+
+#if defined TIZEN_EXT
+#define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
+
+ /* Wi-Fi Signal Strength (for 2.4G (dB))
+ * Excellent : ~ -63
+ * Good : -64 ~ -74
+ * Weak : -75 ~ -82
+ * Very weak : -83 ~ -88
+ * No signal : -89 ~
+ *
+ * Wi-Fi Signal Strength (for 5G (dB))
+ * Excellent : ~ -67
+ * Good : -68 ~ -76
+ * Weak : -77 ~ -82
+ * Very weak : -83 ~ -88
+ * No signal : -89 ~
+ */
+#define RSSI_LEVEL_2_5G -77
+#define RSSI_LEVEL_2_24G -75
+#define RSSI_LEVEL_3_5G -68
+#define RSSI_LEVEL_3_24G -64
+#define WIFI_BSSID_STR_LEN 18
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#define ROAM_SCAN_INTERVAL 60 /* 60 seconds */
+#endif
static struct connman_technology *wifi_technology = NULL;
static struct connman_technology *p2p_technology = NULL;
bool p2p_connecting;
bool p2p_device;
int servicing;
+#if defined TIZEN_EXT
+ int assoc_retry_count;
+ struct connman_network *scan_pending_network;
+ bool allow_full_scan;
+ unsigned int automaxspeed_timeout;
+ GSupplicantScanParams *hidden_scan_params;
+ unsigned int mac_policy;
+ unsigned int preassoc_mac_policy;
+ unsigned int mac_lifetime;
+#endif
int disconnect_code;
int assoc_code;
+#if defined TIZEN_EXT_WIFI_MESH
+ bool mesh_interface;
+ struct wifi_mesh_info *mesh_info;
+#endif
};
-
+ struct disconnect_data {
+ struct wifi_data *wifi;
+ struct connman_network *network;
+ };
+
+#if defined TIZEN_EXT
+#include "connman.h"
+#include "dbus.h"
+
+#define TIZEN_ASSOC_RETRY_COUNT 4
+
+static gboolean wifi_first_scan = false;
+static gboolean found_with_first_scan = false;
+static gboolean is_wifi_notifier_registered = false;
+static GHashTable *failed_bssids = NULL;
+static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
+#endif
+
static GList *iface_list = NULL;
static GList *pending_wifi_device = NULL;
}
}
- return 0;
+ connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
+ connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
}
-static int peer_unregister_service(const unsigned char *specification,
- int specification_length,
- const unsigned char *query,
- int query_length, int version)
+static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
{
- GSupplicantP2PServiceParams *params;
- bool wfd = false;
- GList *list;
- int ret;
+ const char *peer_address;
- if (specification && !version && !query &&
- is_service_wfd(specification, specification_length)) {
- ret = peer_unregister_wfd_service();
- if (ret != 0 && ret != -EINPROGRESS)
- return ret;
- wfd = true;
- }
-
- for (list = iface_list; list; list = list->next) {
- struct wifi_data *wifi = list->data;
- GSupplicantInterface *iface = wifi->interface;
-
- if (wfd)
- goto stop_listening;
-
- if (!g_supplicant_interface_has_p2p(iface))
- continue;
-
- params = fill_in_peer_service_params(specification,
- specification_length, query,
- query_length, version);
- if (!params)
- continue;
+ peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
- ret = g_supplicant_interface_p2p_del_service(iface, params);
- if (ret != 0 && ret != -EINPROGRESS)
- free_peer_service_params(params);
-stop_listening:
- wifi->servicing--;
- if (!wifi->servicing || wifi->servicing < 0) {
- g_supplicant_interface_p2p_listen(iface, 0, 0);
- wifi->servicing = 0;
- }
- }
+ if (!peer_address)
+ return;
- return 0;
+ DBG("Peer %s connected", peer_address);
+ connman_mesh_add_connected_peer(peer_address);
}
-static struct connman_peer_driver peer_driver = {
- .connect = peer_connect,
- .disconnect = peer_disconnect,
- .register_service = peer_register_service,
- .unregister_service = peer_unregister_service,
-};
-
-static void handle_tethering(struct wifi_data *wifi)
+static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
{
- if (!wifi->tethering)
- return;
+ const char *peer_address;
+ int reason;
- if (!wifi->bridge)
- return;
+ peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
- if (wifi->bridged)
+ if (!peer_address)
return;
- DBG("index %d bridge %s", wifi->index, wifi->bridge);
-
- if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
- return;
+ reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
- wifi->bridged = true;
+ DBG("Peer %s disconnected with reason %d", peer_address, reason);
+ connman_mesh_remove_connected_peer(peer_address, reason);
}
+#endif
-static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
+static struct wifi_data *get_pending_wifi_data(const char *ifname)
{
- struct connman_device *device = user_data;
- struct wifi_data *wifi = connman_device_get_data(device);
-
- if (!wifi)
- return;
+ GList *list;
- DBG("index %d flags %d change %d", wifi->index, flags, change);
+ for (list = pending_wifi_device; list; list = list->next) {
+ struct wifi_data *wifi;
+ const char *dev_name;
- if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
- if (flags & IFF_UP)
- DBG("interface up");
- else
- DBG("interface down");
- }
+ wifi = list->data;
+ if (!wifi || !wifi->device)
+ continue;
- if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
- if (flags & IFF_LOWER_UP)
- DBG("carrier on");
- else
- DBG("carrier off");
+ dev_name = connman_device_get_string(wifi->device, "Interface");
+ if (!g_strcmp0(ifname, dev_name)) {
+ pending_wifi_device = g_list_delete_link(
+ pending_wifi_device, list);
+ return wifi;
+ }
}
- if (flags & IFF_LOWER_UP)
- handle_tethering(wifi);
-
- wifi->flags = flags;
+ return NULL;
}
-static int wifi_probe(struct connman_device *device)
+static void remove_pending_wifi_device(struct wifi_data *wifi)
{
- struct wifi_data *wifi;
-
- DBG("device %p", device);
-
- wifi = g_try_new0(struct wifi_data, 1);
- if (!wifi)
- return -ENOMEM;
-
- wifi->state = G_SUPPLICANT_STATE_INACTIVE;
- wifi->ap_supported = WIFI_AP_UNKNOWN;
- wifi->tethering_param = NULL;
-
- connman_device_set_data(device, wifi);
- wifi->device = connman_device_ref(device);
+ GList *link;
- wifi->index = connman_device_get_index(device);
- wifi->flags = 0;
+ link = g_list_find(pending_wifi_device, wifi);
- wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
- wifi_newlink, device);
- if (is_p2p_connecting())
- add_pending_wifi_device(wifi);
- else
- iface_list = g_list_append(iface_list, wifi);
+ if (!link)
+ return;
- return 0;
+ pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
}
-static void remove_networks(struct connman_device *device,
- struct wifi_data *wifi)
+static void peer_cancel_timeout(struct wifi_data *wifi)
{
- GSList *list;
+ if (wifi->p2p_connection_timeout > 0)
+ g_source_remove(wifi->p2p_connection_timeout);
- for (list = wifi->networks; list; list = list->next) {
- struct connman_network *network = list->data;
+ wifi->p2p_connection_timeout = 0;
+ wifi->p2p_connecting = false;
- connman_device_remove_network(device, network);
- connman_network_unref(network);
+ if (wifi->pending_peer) {
+ connman_peer_unref(wifi->pending_peer);
+ wifi->pending_peer = NULL;
}
-
- g_slist_free(wifi->networks);
- wifi->networks = NULL;
}
-static void remove_peers(struct wifi_data *wifi)
+static gboolean peer_connect_timeout(gpointer data)
{
- GSList *list;
+ struct wifi_data *wifi = data;
- for (list = wifi->peers; list; list = list->next) {
- struct connman_peer *peer = list->data;
+ DBG("");
- connman_peer_unregister(peer);
- connman_peer_unref(peer);
+ if (wifi->p2p_connecting) {
+ enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
+ GSupplicantPeer *gs_peer =
+ g_supplicant_interface_peer_lookup(wifi->interface,
+ connman_peer_get_identifier(wifi->pending_peer));
+
+ if (g_supplicant_peer_has_requested_connection(gs_peer))
+ state = CONNMAN_PEER_STATE_IDLE;
+
+ connman_peer_set_state(wifi->pending_peer, state);
}
- g_slist_free(wifi->peers);
- wifi->peers = NULL;
+ peer_cancel_timeout(wifi);
+
+ return FALSE;
}
-static void reset_autoscan(struct connman_device *device)
+static void peer_connect_callback(int result, GSupplicantInterface *interface,
+ void *user_data)
{
- struct wifi_data *wifi = connman_device_get_data(device);
- struct autoscan_params *autoscan;
+ struct wifi_data *wifi = user_data;
+ struct connman_peer *peer = wifi->pending_peer;
- DBG("");
+ DBG("peer %p - %d", peer, result);
- if (!wifi || !wifi->autoscan)
+ if (!peer)
return;
- autoscan = wifi->autoscan;
-
- autoscan->interval = 0;
-
- if (autoscan->timeout == 0)
+ if (result < 0) {
+ peer_connect_timeout(wifi);
return;
+ }
- g_source_remove(autoscan->timeout);
- autoscan->timeout = 0;
+ connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
- connman_device_unref(device);
+ wifi->p2p_connection_timeout = g_timeout_add_seconds(
+ P2P_CONNECTION_TIMEOUT,
+ peer_connect_timeout, wifi);
}
-static void stop_autoscan(struct connman_device *device)
+static int peer_connect(struct connman_peer *peer,
+ enum connman_peer_wps_method wps_method,
+ const char *wps_pin)
{
- const struct wifi_data *wifi = connman_device_get_data(device);
+ struct connman_device *device = connman_peer_get_device(peer);
+ GSupplicantPeerParams *peer_params;
+ GSupplicantPeer *gs_peer;
+ struct wifi_data *wifi;
+ bool pbc, pin;
+ int ret;
- if (!wifi || !wifi->autoscan)
- return;
+ DBG("peer %p", peer);
- reset_autoscan(device);
+ if (!device)
+ return -ENODEV;
- connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
-}
+ wifi = connman_device_get_data(device);
+ if (!wifi || !wifi->interface)
+ return -ENODEV;
-static void check_p2p_technology(void)
-{
- bool p2p_exists = false;
- GList *list;
+ if (wifi->p2p_connecting)
+ return -EBUSY;
- for (list = iface_list; list; list = list->next) {
- struct wifi_data *w = list->data;
+ gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
+ connman_peer_get_identifier(peer));
+ if (!gs_peer)
+ return -EINVAL;
- if (w->interface &&
- g_supplicant_interface_has_p2p(w->interface))
- p2p_exists = true;
- }
+ pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
+ pin = g_supplicant_peer_is_wps_pin(gs_peer);
- if (!p2p_exists) {
- connman_technology_driver_unregister(&p2p_tech_driver);
- connman_peer_driver_unregister(&peer_driver);
+ switch (wps_method) {
+ case CONNMAN_PEER_WPS_UNKNOWN:
+ if ((pbc && pin) || pin)
+ return -ENOKEY;
+ break;
+ case CONNMAN_PEER_WPS_PBC:
+ if (!pbc)
+ return -EINVAL;
+ wps_pin = NULL;
+ break;
+ case CONNMAN_PEER_WPS_PIN:
+ if (!pin || !wps_pin)
+ return -EINVAL;
+ break;
}
-}
-
-static void wifi_remove(struct connman_device *device)
-{
- struct wifi_data *wifi = connman_device_get_data(device);
- DBG("device %p wifi %p", device, wifi);
+ peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
+ if (!peer_params)
+ return -ENOMEM;
- if (!wifi)
+ peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
+ if (wps_pin)
+ peer_params->wps_pin = g_strdup(wps_pin);
+
+ peer_params->master = connman_peer_service_is_master();
+
+ ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
+ peer_connect_callback, wifi);
+ if (ret == -EINPROGRESS) {
+ wifi->pending_peer = connman_peer_ref(peer);
+ wifi->p2p_connecting = true;
+ } else if (ret < 0) {
+ g_free(peer_params->path);
+ g_free(peer_params->wps_pin);
+ g_free(peer_params);
+ }
+
+ return ret;
+}
+
+static int peer_disconnect(struct connman_peer *peer)
+{
+ struct connman_device *device = connman_peer_get_device(peer);
+ GSupplicantPeerParams peer_params = {};
+ GSupplicantPeer *gs_peer;
+ struct wifi_data *wifi;
+ int ret;
+
+ DBG("peer %p", peer);
+
+ if (!device)
+ return -ENODEV;
+
+ wifi = connman_device_get_data(device);
+ if (!wifi)
+ return -ENODEV;
+
+ gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
+ connman_peer_get_identifier(peer));
+ if (!gs_peer)
+ return -EINVAL;
+
+ peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
+
+ ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
+ &peer_params);
+ g_free(peer_params.path);
+
+ if (ret == -EINPROGRESS) {
+ peer_cancel_timeout(wifi);
+ wifi->p2p_device = false;
+ }
+
+ return ret;
+}
+
+struct peer_service_registration {
+ peer_service_registration_cb_t callback;
+ void *user_data;
+};
+
+static bool is_service_wfd(const unsigned char *specs, int length)
+{
+ if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
+ return false;
+
+ return true;
+}
+
+static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
+{
+ struct wifi_data *wifi = data;
+
+ if (!wifi->interface ||
+ !g_supplicant_interface_has_p2p(wifi->interface))
+ return;
+
+ if (!wifi->servicing) {
+ g_supplicant_interface_p2p_listen(wifi->interface,
+ P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
+ }
+
+ wifi->servicing++;
+}
+
+static void register_wfd_service_cb(int result,
+ GSupplicantInterface *iface, void *user_data)
+{
+ struct peer_service_registration *reg_data = user_data;
+
+ DBG("");
+
+ if (result == 0)
+ g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
+
+ if (reg_data && reg_data->callback) {
+ reg_data->callback(result, reg_data->user_data);
+ g_free(reg_data);
+ }
+}
+
+static GSupplicantP2PServiceParams *fill_in_peer_service_params(
+ const unsigned char *spec,
+ int spec_length, const unsigned char *query,
+ int query_length, int version)
+{
+ GSupplicantP2PServiceParams *params;
+
+ params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
+ if (!params)
+ return NULL;
+
+ if (version > 0) {
+ params->version = version;
- params->service = g_memdup(spec, spec_length);
++ if (spec_length > 0) {
++ params->service = g_malloc(spec_length);
++ memcpy(params->service, spec, spec_length);
++ }
+ } else if (query_length > 0 && spec_length > 0) {
- params->query = g_memdup(query, query_length);
++ params->query = g_malloc(query_length);
++ memcpy(params->query, query, query_length);
+ params->query_length = query_length;
+
- params->response = g_memdup(spec, spec_length);
++ params->response = g_malloc(spec_length);
++ memcpy(params->response, spec, spec_length);
+ params->response_length = spec_length;
+ } else {
- params->wfd_ies = g_memdup(spec, spec_length);
++ if (spec_length > 0) {
++ params->wfd_ies = g_malloc(spec_length);
++ memcpy(params->wfd_ies, spec, spec_length);
++ }
+ params->wfd_ies_length = spec_length;
+ }
+
+ return params;
+}
+
+static void free_peer_service_params(GSupplicantP2PServiceParams *params)
+{
+ if (!params)
+ return;
+
+ g_free(params->service);
+ g_free(params->query);
+ g_free(params->response);
+ g_free(params->wfd_ies);
+
+ g_free(params);
+}
+
+static int peer_register_wfd_service(const unsigned char *specification,
+ int specification_length,
+ peer_service_registration_cb_t callback,
+ void *user_data)
+{
+ struct peer_service_registration *reg_data = NULL;
+ static GSupplicantP2PServiceParams *params;
+ int ret;
+
+ DBG("");
+
+ if (wfd_service_registered)
+ return -EBUSY;
+
+ params = fill_in_peer_service_params(specification,
+ specification_length, NULL, 0, 0);
+ if (!params)
+ return -ENOMEM;
+
+ reg_data = g_try_malloc0(sizeof(*reg_data));
+ if (!reg_data) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ reg_data->callback = callback;
+ reg_data->user_data = user_data;
+
+ ret = g_supplicant_set_widi_ies(params,
+ register_wfd_service_cb, reg_data);
+ if (ret < 0 && ret != -EINPROGRESS)
+ goto error;
+
+ wfd_service_registered = true;
+
+ return ret;
+error:
+ free_peer_service_params(params);
+ g_free(reg_data);
+
+ return ret;
+}
+
+static void register_peer_service_cb(int result,
+ GSupplicantInterface *iface, void *user_data)
+{
+ struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
+ struct peer_service_registration *reg_data = user_data;
+
+#if defined TIZEN_EXT
+ if (!wifi)
return;
- if (flags & IFF_LOWER_UP) {
+#endif
+
+ DBG("");
+
+ if (result == 0)
+ apply_p2p_listen_on_iface(wifi, NULL);
+
+ if (reg_data->callback)
+ reg_data->callback(result, reg_data->user_data);
+
+ g_free(reg_data);
+}
+
+static int peer_register_service(const unsigned char *specification,
+ int specification_length,
+ const unsigned char *query,
+ int query_length, int version,
+ peer_service_registration_cb_t callback,
+ void *user_data)
+{
+ struct peer_service_registration *reg_data;
+ GSupplicantP2PServiceParams *params;
+ bool found = false;
+ int ret, ret_f;
+ GList *list;
+
+ DBG("");
+
+ if (specification && !version && !query &&
+ is_service_wfd(specification, specification_length)) {
+ return peer_register_wfd_service(specification,
+ specification_length, callback, user_data);
+ }
+
+ reg_data = g_try_malloc0(sizeof(*reg_data));
+ if (!reg_data)
+ return -ENOMEM;
+
+ reg_data->callback = callback;
+ reg_data->user_data = user_data;
+
+ ret_f = -EOPNOTSUPP;
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *wifi = list->data;
+ GSupplicantInterface *iface = wifi->interface;
+
+ if (!g_supplicant_interface_has_p2p(iface))
+ continue;
+
+ params = fill_in_peer_service_params(specification,
+ specification_length, query,
+ query_length, version);
+ if (!params)
+ continue;
+
+ if (!found) {
+ ret_f = g_supplicant_interface_p2p_add_service(iface,
+ register_peer_service_cb, params, reg_data);
+ if (ret_f == 0 || ret_f == -EINPROGRESS)
+ found = true;
+ ret = ret_f;
+ } else
+ ret = g_supplicant_interface_p2p_add_service(iface,
+ register_peer_service_cb, params, NULL);
+ if (ret != 0 && ret != -EINPROGRESS)
+ free_peer_service_params(params);
+ }
+
+ if (ret_f != 0 && ret_f != -EINPROGRESS)
+ g_free(reg_data);
+
+ return ret_f;
+}
+
+static int peer_unregister_wfd_service(void)
+{
+ GSupplicantP2PServiceParams *params;
+ GList *list;
+
+ if (!wfd_service_registered)
+ return -EALREADY;
+
+ params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
+ if (!params)
+ return -ENOMEM;
+
+ wfd_service_registered = false;
+
+ g_supplicant_set_widi_ies(params, NULL, NULL);
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *wifi = list->data;
+
+ if (!g_supplicant_interface_has_p2p(wifi->interface))
+ continue;
+
+ wifi->servicing--;
+ if (!wifi->servicing || wifi->servicing < 0) {
+ g_supplicant_interface_p2p_listen(wifi->interface,
+ 0, 0);
+ wifi->servicing = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int peer_unregister_service(const unsigned char *specification,
+ int specification_length,
+ const unsigned char *query,
+ int query_length, int version)
+{
+ GSupplicantP2PServiceParams *params;
+ bool wfd = false;
+ GList *list;
+ int ret;
+
+ if (specification && !version && !query &&
+ is_service_wfd(specification, specification_length)) {
+ ret = peer_unregister_wfd_service();
+ if (ret != 0 && ret != -EINPROGRESS)
+ return ret;
+ wfd = true;
+ }
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *wifi = list->data;
+ GSupplicantInterface *iface = wifi->interface;
+
+ if (wfd)
+ goto stop_listening;
+
+ if (!g_supplicant_interface_has_p2p(iface))
+ continue;
+
+ params = fill_in_peer_service_params(specification,
+ specification_length, query,
+ query_length, version);
+ if (!params)
+ continue;
+
+ ret = g_supplicant_interface_p2p_del_service(iface, params);
+ if (ret != 0 && ret != -EINPROGRESS)
+ free_peer_service_params(params);
+stop_listening:
+ wifi->servicing--;
+ if (!wifi->servicing || wifi->servicing < 0) {
+ g_supplicant_interface_p2p_listen(iface, 0, 0);
+ wifi->servicing = 0;
+ }
+ }
+
+ return 0;
+}
+
+static struct connman_peer_driver peer_driver = {
+ .connect = peer_connect,
+ .disconnect = peer_disconnect,
+ .register_service = peer_register_service,
+ .unregister_service = peer_unregister_service,
+};
+
+static void handle_tethering(struct wifi_data *wifi)
+{
+ if (!wifi->tethering)
+ return;
+
+ if (!wifi->bridge)
+ return;
+
+ if (wifi->bridged)
+ return;
+
+ DBG("index %d bridge %s", wifi->index, wifi->bridge);
+
+ if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
+ return;
+
+ wifi->bridged = true;
+}
+
+static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
+{
+ struct connman_device *device = user_data;
+ struct wifi_data *wifi = connman_device_get_data(device);
+
+ if (!wifi)
+ return;
+
+ DBG("index %d flags %d change %d", wifi->index, flags, change);
+
+ if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
+ if (flags & IFF_UP)
+ DBG("interface up");
+ else
+ DBG("interface down");
+ }
+
+ if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
-
- handle_tethering(wifi);
- } else
++ if (flags & IFF_LOWER_UP)
+ DBG("carrier on");
++ else
+ DBG("carrier off");
+ }
+
++ if (flags & IFF_LOWER_UP)
++ handle_tethering(wifi);
++
+ wifi->flags = flags;
+}
+
+static int wifi_probe(struct connman_device *device)
+{
+ struct wifi_data *wifi;
+
+ DBG("device %p", device);
+
+ wifi = g_try_new0(struct wifi_data, 1);
+ if (!wifi)
+ return -ENOMEM;
+
+ wifi->state = G_SUPPLICANT_STATE_INACTIVE;
+ wifi->ap_supported = WIFI_AP_UNKNOWN;
+ wifi->tethering_param = NULL;
+
+ connman_device_set_data(device, wifi);
+ wifi->device = connman_device_ref(device);
+
+ wifi->index = connman_device_get_index(device);
+ wifi->flags = 0;
+
+ wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
+ wifi_newlink, device);
+ if (is_p2p_connecting())
+ add_pending_wifi_device(wifi);
+ else
+ iface_list = g_list_append(iface_list, wifi);
+
+ return 0;
+}
+
+static void remove_networks(struct connman_device *device,
+ struct wifi_data *wifi)
+{
+ GSList *list;
+
+ for (list = wifi->networks; list; list = list->next) {
+ struct connman_network *network = list->data;
+
+ connman_device_remove_network(device, network);
+ connman_network_unref(network);
+ }
+
+ g_slist_free(wifi->networks);
+ wifi->networks = NULL;
+}
+
+static void remove_peers(struct wifi_data *wifi)
+{
+ GSList *list;
+
+ for (list = wifi->peers; list; list = list->next) {
+ struct connman_peer *peer = list->data;
+
+ connman_peer_unregister(peer);
+ connman_peer_unref(peer);
+ }
+
+ g_slist_free(wifi->peers);
+ wifi->peers = NULL;
+}
+
+static void reset_autoscan(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ struct autoscan_params *autoscan;
+
+ DBG("");
+
+ if (!wifi || !wifi->autoscan)
+ return;
+
+ autoscan = wifi->autoscan;
+
+ autoscan->interval = 0;
+
+ if (autoscan->timeout == 0)
+ return;
+
+ g_source_remove(autoscan->timeout);
+ autoscan->timeout = 0;
+
+ connman_device_unref(device);
+}
+
+static void stop_autoscan(struct connman_device *device)
+{
+ const struct wifi_data *wifi = connman_device_get_data(device);
+
+ if (!wifi || !wifi->autoscan)
+ return;
+
+ reset_autoscan(device);
+
+ connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
+}
+
+static void check_p2p_technology(void)
+{
+ bool p2p_exists = false;
+ GList *list;
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *w = list->data;
+
+ if (w->interface &&
+ g_supplicant_interface_has_p2p(w->interface))
+ p2p_exists = true;
+ }
+
+ if (!p2p_exists) {
+ connman_technology_driver_unregister(&p2p_tech_driver);
+ connman_peer_driver_unregister(&peer_driver);
+ }
+}
+
+struct last_connected {
+ GTimeVal modified;
+ gchar *ssid;
+ int freq;
+};
+
+static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ GTimeVal *aval = (GTimeVal *)a;
+ GTimeVal *bval = (GTimeVal *)b;
+
+ /* Note that the sort order is descending */
+ if (aval->tv_sec < bval->tv_sec)
+ return 1;
+
+ if (aval->tv_sec > bval->tv_sec)
+ return -1;
+
+ return 0;
+}
+
+static void free_entry(gpointer data)
+{
+ struct last_connected *entry = data;
+
+ g_free(entry->ssid);
+ g_free(entry);
+}
+
+static void wifi_remove(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+
+ DBG("device %p wifi %p", device, wifi);
+
+ if (!wifi)
+ return;
+
+ stop_autoscan(device);
+
+ if (wifi->p2p_device)
+ p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
+ else
+ iface_list = g_list_remove(iface_list, wifi);
+
+ check_p2p_technology();
+#if defined TIZEN_EXT_WIFI_MESH
+ check_mesh_technology();
+#endif
+
+ remove_pending_wifi_device(wifi);
+
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
+ g_source_remove(wifi->p2p_find_timeout);
+ connman_device_unref(wifi->device);
+ }
+
+ if (wifi->p2p_connection_timeout)
+ g_source_remove(wifi->p2p_connection_timeout);
+
+#if defined TIZEN_EXT
+ if (wifi->automaxspeed_timeout != 0) {
+ g_source_remove(wifi->automaxspeed_timeout);
+ wifi->automaxspeed_timeout = 0;
+ }
+#endif
+
+ remove_networks(device, wifi);
+ remove_peers(wifi);
+
+ connman_device_set_powered(device, false);
+ connman_device_set_data(device, NULL);
+ connman_device_unref(wifi->device);
+ connman_rtnl_remove_watch(wifi->watch);
+
+ g_supplicant_interface_set_data(wifi->interface, NULL);
+
+ g_supplicant_interface_cancel(wifi->interface);
+
+ if (wifi->scan_params)
+ g_supplicant_free_scan_params(wifi->scan_params);
+#if defined TIZEN_EXT
+ if (wifi->hidden_scan_params) {
+ while (wifi->hidden_scan_params->ssids) {
+ struct scan_ssid *ssid;
+ ssid = wifi->hidden_scan_params->ssids->data;
+ wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
+ }
+ g_supplicant_free_scan_params(wifi->hidden_scan_params);
+ }
+#endif
+
+ g_free(wifi->autoscan);
+ g_free(wifi->identifier);
+ g_free(wifi);
+}
+
+static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
+{
+ GSList *iter;
+
+ for (iter = list; iter; iter = g_slist_next(iter)) {
+ struct scan_ssid *scan_ssid = iter->data;
+
+ if (ssid_len == scan_ssid->ssid_len &&
+ memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
+ int freq, GSupplicantScanParams *scan_data,
+ int driver_max_scan_ssids, char *ssid_name)
+{
+ unsigned int i;
+ struct scan_ssid *scan_ssid;
+
+ if ((driver_max_scan_ssids == 0 ||
+ driver_max_scan_ssids > scan_data->num_ssids) &&
+ (hex_ssid || raw_ssid)) {
+ gchar *ssid;
+ unsigned int j = 0, hex;
+
+ if (hex_ssid) {
+ size_t hex_ssid_len = strlen(hex_ssid);
+
+ ssid = g_try_malloc0(hex_ssid_len / 2);
+ if (!ssid)
+ return -ENOMEM;
+
+ for (i = 0; i < hex_ssid_len; i += 2) {
+ sscanf(hex_ssid + i, "%02x", &hex);
+ ssid[j++] = hex;
+ }
+ } else {
+ ssid = raw_ssid;
+ j = ssid_len;
+ }
+
+ /*
+ * If we have already added hidden AP to the list,
+ * then do not do it again. This might happen if you have
+ * used or are using multiple wifi cards, so in that case
+ * you might have multiple service files for same AP.
+ */
+ if (is_duplicate(scan_data->ssids, ssid, j)) {
+ if (hex_ssid)
+ g_free(ssid);
+ return 0;
+ }
+
+ scan_ssid = g_try_new(struct scan_ssid, 1);
+ if (!scan_ssid) {
+ if (hex_ssid)
+ g_free(ssid);
+ return -ENOMEM;
+ }
+
+ memcpy(scan_ssid->ssid, ssid, j);
+ scan_ssid->ssid_len = j;
+ scan_data->ssids = g_slist_prepend(scan_data->ssids,
+ scan_ssid);
+
+ scan_data->num_ssids++;
+
+ DBG("SSID %s added to scanned list of %d entries", ssid_name,
+ scan_data->num_ssids);
+
+ if (hex_ssid)
+ g_free(ssid);
+ } else
+ return -EINVAL;
+
+ scan_data->ssids = g_slist_reverse(scan_data->ssids);
+
+ if (!scan_data->freqs) {
+ scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
+ if (!scan_data->freqs) {
+ g_slist_free_full(scan_data->ssids, g_free);
+ return -ENOMEM;
+ }
+
+ scan_data->num_freqs = 1;
+ scan_data->freqs[0] = freq;
+ } else {
+ bool duplicate = false;
+
+ /* Don't add duplicate entries */
+ for (i = 0; i < scan_data->num_freqs; i++) {
+ if (scan_data->freqs[i] == freq) {
+ duplicate = true;
+ break;
+ }
+ }
+
+ if (!duplicate) {
+ scan_data->num_freqs++;
+ scan_data->freqs = g_try_realloc(scan_data->freqs,
+ sizeof(uint16_t) * scan_data->num_freqs);
+ if (!scan_data->freqs) {
+ g_slist_free_full(scan_data->ssids, g_free);
+ return -ENOMEM;
+ }
+ scan_data->freqs[scan_data->num_freqs - 1] = freq;
+ }
+ }
+
+ return 1;
+}
+
+static int get_hidden_connections(GSupplicantScanParams *scan_data)
+{
+ struct connman_config_entry **entries;
+ GKeyFile *keyfile;
+#if defined TIZEN_EXT
+ gchar **services = NULL;
+#else
+ gchar **services;
+#endif /* defined TIZEN_EXT */
+ char *ssid, *name;
+ int i, ret;
+ bool value;
+ int num_ssids = 0, add_param_failed = 0;
+#if defined TIZEN_EXT
+ GSequenceIter *iter;
+ GSequence *latest_list;
+ struct last_connected *entry;
+ GTimeVal modified;
+
+ latest_list = g_sequence_new(free_entry);
+ if (!latest_list)
+ goto out;
+#endif
+ services = connman_storage_get_services();
+ for (i = 0; services && services[i]; i++) {
+ if (strncmp(services[i], "wifi_", 5) != 0)
+ continue;
+
+ keyfile = connman_storage_load_service(services[i]);
+ if (!keyfile)
+ continue;
+
+ value = g_key_file_get_boolean(keyfile,
+ services[i], "Hidden", NULL);
+ if (!value) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+
+ value = g_key_file_get_boolean(keyfile,
+ services[i], "Favorite", NULL);
+ if (!value) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+
+#if defined TIZEN_EXT
+ value = g_key_file_get_boolean(keyfile,
+ services[i], "AutoConnect", NULL);
+ if (!value) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+
+ gchar *str = g_key_file_get_string(keyfile,
+ services[i], "Modified", NULL);
+ if (!str) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+ g_time_val_from_iso8601(str, &modified);
+ g_free(str);
+#endif
+
+ ssid = g_key_file_get_string(keyfile,
+ services[i], "SSID", NULL);
+
+ name = g_key_file_get_string(keyfile, services[i], "Name",
+ NULL);
+
+#if defined TIZEN_EXT
+ entry = g_try_new(struct last_connected, 1);
+ if (!entry) {
+ g_sequence_free(latest_list);
+ g_free(ssid);
+ g_free(name);
+ g_key_file_free(keyfile);
+ goto out;
+ }
+
+ entry->modified = modified;
+ entry->ssid = ssid;
+
+ g_sequence_insert_sorted(latest_list, entry,
+ sort_entry, NULL);
+#else
+ ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
+ if (ret < 0)
+ add_param_failed++;
+ else if (ret > 0)
+ num_ssids++;
+
+ g_free(ssid);
+#endif
+ g_free(name);
+ g_key_file_free(keyfile);
+ }
+
+#if defined TIZEN_EXT
+ gint length = g_sequence_get_length(latest_list);
+ iter = g_sequence_get_begin_iter(latest_list);
+
+ for (i = 0; i < length; i++) {
+ entry = g_sequence_get(iter);
+
+ ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
+ if (ret < 0)
+ add_param_failed++;
+ else if (ret > 0)
+ num_ssids++;
+
+ iter = g_sequence_iter_next(iter);
+ }
+
+ g_sequence_free(latest_list);
+out:
+#endif
+ /*
+ * Check if there are any hidden AP that needs to be provisioned.
+ */
+ entries = connman_config_get_entries("wifi");
+ for (i = 0; entries && entries[i]; i++) {
+ int len;
+
+ if (!entries[i]->hidden)
+ continue;
+
+ if (!entries[i]->ssid) {
+ ssid = entries[i]->name;
+ len = strlen(ssid);
+ } else {
+ ssid = entries[i]->ssid;
+ len = entries[i]->ssid_len;
+ }
+
+ if (!ssid)
+ continue;
+
+ ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
+ if (ret < 0)
+ add_param_failed++;
+ else if (ret > 0)
+ num_ssids++;
+ }
- stop_autoscan(device);
+ connman_config_free_entries(entries);
- if (wifi->p2p_device)
- p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
- else
- iface_list = g_list_remove(iface_list, wifi);
+ if (add_param_failed > 0)
+ DBG("Unable to scan %d out of %d SSIDs",
+ add_param_failed, num_ssids);
- check_p2p_technology();
+ g_strfreev(services);
- remove_pending_wifi_device(wifi);
+ return num_ssids;
+}
- if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
- g_source_remove(wifi->p2p_find_timeout);
- connman_device_unref(wifi->device);
+static int get_hidden_connections_params(struct wifi_data *wifi,
+ GSupplicantScanParams *scan_params)
+{
+ int driver_max_ssids, i;
+ GSupplicantScanParams *orig_params;
+
+ /*
+ * Scan hidden networks so that we can autoconnect to them.
+ * We will assume 1 as a default number of ssid to scan.
+ */
+ driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
+ wifi->interface);
+ if (driver_max_ssids == 0)
+ driver_max_ssids = 1;
+
+ DBG("max ssids %d", driver_max_ssids);
+
+#if defined TIZEN_EXT
+ if (!wifi->hidden_scan_params) {
+ wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!wifi->hidden_scan_params)
+ return 0;
+
+ if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
+ g_supplicant_free_scan_params(wifi->hidden_scan_params);
+ wifi->hidden_scan_params = NULL;
+
+ return 0;
+ }
}
- if (wifi->p2p_connection_timeout)
- g_source_remove(wifi->p2p_connection_timeout);
+ orig_params = wifi->hidden_scan_params;
+#else
+ if (!wifi->scan_params) {
+ wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!wifi->scan_params)
+ return 0;
- remove_networks(device, wifi);
- remove_peers(wifi);
+ if (get_hidden_connections(wifi->scan_params) == 0) {
+ g_supplicant_free_scan_params(wifi->scan_params);
+ wifi->scan_params = NULL;
- connman_device_set_powered(device, false);
- connman_device_set_data(device, NULL);
- connman_device_unref(wifi->device);
- connman_rtnl_remove_watch(wifi->watch);
+ return 0;
+ }
+ }
- g_supplicant_interface_set_data(wifi->interface, NULL);
+ orig_params = wifi->scan_params;
+#endif
- g_supplicant_interface_cancel(wifi->interface);
+ /* Let's transfer driver_max_ssids params */
+ for (i = 0; i < driver_max_ssids; i++) {
+ struct scan_ssid *ssid;
- if (wifi->scan_params)
- g_supplicant_free_scan_params(wifi->scan_params);
+#if defined TIZEN_EXT
+ if (!wifi->hidden_scan_params->ssids)
+#else
+ if (!wifi->scan_params->ssids)
+#endif
+ break;
- g_free(wifi->autoscan);
- g_free(wifi->identifier);
- g_free(wifi);
+ ssid = orig_params->ssids->data;
+ orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
+ scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
+ }
+
+ if (i > 0) {
+ scan_params->num_ssids = i;
+ scan_params->ssids = g_slist_reverse(scan_params->ssids);
+
- scan_params->freqs = g_memdup(orig_params->freqs,
- sizeof(uint16_t) * orig_params->num_freqs);
- if (!scan_params->freqs)
++ if (orig_params->num_freqs <= 0)
+ goto err;
+
++ scan_params->freqs =
++ g_malloc(sizeof(uint16_t) * orig_params->num_freqs);
++ memcpy(scan_params->freqs, orig_params->freqs,
++ sizeof(uint16_t) *orig_params->num_freqs);
++
+ scan_params->num_freqs = orig_params->num_freqs;
+
+ } else
+ goto err;
+
+ orig_params->num_ssids -= scan_params->num_ssids;
+
+ return scan_params->num_ssids;
+
+err:
+ g_slist_free_full(scan_params->ssids, g_free);
+#if defined TIZEN_EXT
+ g_supplicant_free_scan_params(wifi->hidden_scan_params);
+ wifi->hidden_scan_params = NULL;
+#else
+ g_supplicant_free_scan_params(wifi->scan_params);
+ wifi->scan_params = NULL;
+#endif
+
+ return 0;
}
-static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
+static int throw_wifi_scan(struct connman_device *device,
+ GSupplicantInterfaceCallback callback)
{
- GSList *iter;
+ struct wifi_data *wifi = connman_device_get_data(device);
+ int ret;
- for (iter = list; iter; iter = g_slist_next(iter)) {
- struct scan_ssid *scan_ssid = iter->data;
+ if (!wifi)
+ return -ENODEV;
- if (ssid_len == scan_ssid->ssid_len &&
- memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
- return true;
+ DBG("device %p %p", device, wifi->interface);
+
+ if (wifi->tethering)
+ return -EBUSY;
+
+#if defined TIZEN_EXT
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)
+ && !wifi->allow_full_scan)
+#else
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
+#endif
+ return -EALREADY;
+
+ connman_device_ref(device);
+
+ ret = g_supplicant_interface_scan(wifi->interface, NULL,
+ callback, device);
+ if (ret == 0) {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, true);
+ } else
+ connman_device_unref(device);
+
+ return ret;
+}
+
+static void hidden_free(struct hidden_params *hidden)
+{
+ if (!hidden)
+ return;
+
+ if (hidden->scan_params)
+ g_supplicant_free_scan_params(hidden->scan_params);
+ g_free(hidden->identity);
+ g_free(hidden->passphrase);
+ g_free(hidden->security);
+ g_free(hidden);
+}
+
+#if defined TIZEN_EXT
+static void service_state_changed(struct connman_service *service,
+ enum connman_service_state state);
+
+static int network_connect(struct connman_network *network);
+
+static struct connman_notifier notifier = {
+ .name = "wifi",
+ .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
+ .service_state_changed = service_state_changed,
+};
+
+static void service_state_changed(struct connman_service *service,
+ enum connman_service_state state)
+{
+ enum connman_service_type type;
+
+ type = connman_service_get_type(service);
+ if (type != CONNMAN_SERVICE_TYPE_WIFI)
+ return;
+
+ DBG("service %p state %d", service, state);
+
+ switch (state) {
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ connman_notifier_unregister(¬ifier);
+ is_wifi_notifier_registered = FALSE;
+
+ __connman_device_request_scan(type);
+ break;
+
+ default:
+ break;
}
+}
- return false;
+static gboolean need_bss_transition(uint16_t freq, int snr, int strength)
+{
+ /*
+ * Since bssid->strength is a positive value,
+ * it need to be changed to its original value.
+ */
+ int signal = strength - 120;
+
+ /*
+ * If the currently connected AP matches the following conditions,
+ * scan for BSS transition is started.
+ * - SNR is less than 20 or RSSI level is less than 3
+ */
+ if (snr < 20 && snr != 0)
+ return TRUE;
+ else if (freq > 4900 && signal <= RSSI_LEVEL_2_5G)
+ return TRUE;
+ else if (freq <= 4900 && signal <= RSSI_LEVEL_2_24G)
+ return TRUE;
+
+ return FALSE;
}
-static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
- int freq, GSupplicantScanParams *scan_data,
- int driver_max_scan_ssids, char *ssid_name)
+static gboolean check_bss_condition(uint16_t freq, int snr, uint16_t strength)
{
- unsigned int i;
- struct scan_ssid *scan_ssid;
+ /*
+ * Since bssid->strength is a positive value,
+ * it need to be changed to its original value.
+ */
+ int signal = strength - 120;
- if ((driver_max_scan_ssids == 0 ||
- driver_max_scan_ssids > scan_data->num_ssids) &&
- (hex_ssid || raw_ssid)) {
- gchar *ssid;
- unsigned int j = 0, hex;
+ /*
+ * If the AP that matches the following conditions exists in the SCAN result,
+ * BSS transition is started.
+ * - SNR is 25 or more and RSSI level is greater than 3
+ */
+ if (snr < 25 && snr != 0)
+ return FALSE;
- if (hex_ssid) {
- size_t hex_ssid_len = strlen(hex_ssid);
+ if (freq > 4900 && signal > RSSI_LEVEL_3_5G)
+ return TRUE;
+ else if (freq <= 4900 && signal > RSSI_LEVEL_3_24G)
+ return TRUE;
- ssid = g_try_malloc0(hex_ssid_len / 2);
- if (!ssid)
- return -ENOMEM;
+ return FALSE;
+}
- for (i = 0; i < hex_ssid_len; i += 2) {
- sscanf(hex_ssid + i, "%02x", &hex);
- ssid[j++] = hex;
- }
- } else {
- ssid = raw_ssid;
- j = ssid_len;
- }
+static void scan_callback_hidden(int result,
+ GSupplicantInterface *interface, void *user_data);
- /*
- * If we have already added hidden AP to the list,
- * then do not do it again. This might happen if you have
- * used or are using multiple wifi cards, so in that case
- * you might have multiple service files for same AP.
- */
- if (is_duplicate(scan_data->ssids, ssid, j)) {
- if (hex_ssid)
- g_free(ssid);
- return 0;
- }
+static int network_disconnect(struct connman_network *network);
+#endif
- scan_ssid = g_try_new(struct scan_ssid, 1);
- if (!scan_ssid) {
- if (hex_ssid)
- g_free(ssid);
- return -ENOMEM;
+static void 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;
+#if defined TIZEN_EXT
+ bool roaming_needed = false;
+ bool roaming_ap_found = false;
+ GSList *list = NULL;
+ GSList *bssid_list = NULL;
+ bool favorite_exists = false;
+ struct connman_network *network = NULL;
+ struct connman_service *service = NULL;
+#endif
+
+ DBG("result %d wifi %p", result, wifi);
+
+ if (wifi) {
+ if (wifi->hidden && !wifi->postpone_hidden) {
+ connman_network_clear_hidden(wifi->hidden->user_data);
+ hidden_free(wifi->hidden);
+ wifi->hidden = NULL;
}
- memcpy(scan_ssid->ssid, ssid, j);
- scan_ssid->ssid_len = j;
- scan_data->ssids = g_slist_prepend(scan_data->ssids,
- scan_ssid);
+ if (wifi->scan_params) {
+ g_supplicant_free_scan_params(wifi->scan_params);
+ wifi->scan_params = NULL;
+ }
- scan_data->num_ssids++;
+#if defined TIZEN_EXT
+ if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
+ g_supplicant_free_scan_params(wifi->hidden_scan_params);
+ wifi->hidden_scan_params = NULL;
+ }
+#endif
+ }
- DBG("SSID %s added to scanned list of %d entries", ssid_name,
- scan_data->num_ssids);
+ if (result < 0)
+ connman_device_reset_scanning(device);
- if (hex_ssid)
- g_free(ssid);
- } else
- return -EINVAL;
+ /* User is connecting to a hidden AP, let's wait for finished event */
+ if (wifi && wifi->hidden && wifi->postpone_hidden) {
+ GSupplicantScanParams *scan_params;
+ int ret;
- scan_data->ssids = g_slist_reverse(scan_data->ssids);
+ wifi->postpone_hidden = false;
+ scan_params = wifi->hidden->scan_params;
+ wifi->hidden->scan_params = NULL;
- if (!scan_data->freqs) {
- scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
- if (!scan_data->freqs) {
- g_slist_free_full(scan_data->ssids, g_free);
- return -ENOMEM;
- }
+ reset_autoscan(device);
- scan_data->num_freqs = 1;
- scan_data->freqs[0] = freq;
- } else {
- bool duplicate = false;
+ ret = g_supplicant_interface_scan(wifi->interface, scan_params,
+ scan_callback, device);
+ if (ret == 0)
+ return;
- /* Don't add duplicate entries */
- for (i = 0; i < scan_data->num_freqs; i++) {
- if (scan_data->freqs[i] == freq) {
- duplicate = true;
+ /* On error, let's recall scan_callback, which will cleanup */
+ return scan_callback(ret, interface, user_data);
+ }
+
+#if defined TIZEN_EXT
+ if (wifi) {
+ for (list = wifi->networks; list; list = list->next) {
+ network = list->data;
+ service = connman_service_lookup_from_network(network);
+
+ if (service != NULL &&
+ (connman_service_get_favorite(service) == true) &&
+ (connman_service_get_autoconnect(service) == true)) {
+ DBG("Favorite service exists [%s]",
+ connman_network_get_string(network, "Name"));
+ favorite_exists = true;
break;
}
}
+ }
- if (!duplicate) {
- scan_data->num_freqs++;
- scan_data->freqs = g_try_realloc(scan_data->freqs,
- sizeof(uint16_t) * scan_data->num_freqs);
- if (!scan_data->freqs) {
- g_slist_free_full(scan_data->ssids, g_free);
- return -ENOMEM;
- }
- scan_data->freqs[scan_data->num_freqs - 1] = freq;
+ if (favorite_exists == false) {
+ if (wifi && wifi->allow_full_scan) {
+ int ret;
+ DBG("Trigger full channel scan");
+ wifi->allow_full_scan = false;
+
+ ret = g_supplicant_interface_scan(wifi->interface, NULL,
+ scan_callback_hidden, device);
+ if (ret == 0)
+ return;
+
+ /* On error, let's recall scan_callback, which will cleanup */
+ return scan_callback(ret, interface, user_data);
}
+ } else
+ wifi->allow_full_scan = false;
+#endif
+
+ scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
+
+ if (scanning) {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, false);
}
- return 1;
-}
+ if (result != -ENOLINK)
+#if defined TIZEN_EXT
+ if (result != -EIO)
+#endif
+ start_autoscan(device);
-static int get_hidden_connections(GSupplicantScanParams *scan_data)
-{
- struct connman_config_entry **entries;
- GKeyFile *keyfile;
- gchar **services;
- char *ssid, *name;
- int i, ret;
- bool value;
- int num_ssids = 0, add_param_failed = 0;
+ /*
+ * If we are here then we were scanning; however, if we are
+ * also mid-flight disabling the interface, then wifi_disable
+ * has already cleared the device scanning state and
+ * unreferenced the device, obviating the need to do it here.
+ */
- services = connman_storage_get_services();
- for (i = 0; services && services[i]; i++) {
- if (strncmp(services[i], "wifi_", 5) != 0)
- continue;
+ if (scanning)
+ connman_device_unref(device);
- keyfile = connman_storage_load_service(services[i]);
- if (!keyfile)
- continue;
+#if defined TIZEN_EXT
+ if (!wifi)
+ goto done;
- value = g_key_file_get_boolean(keyfile,
- services[i], "Hidden", NULL);
- if (!value) {
- g_key_file_free(keyfile);
- continue;
- }
+ if (wifi->scan_pending_network && result != -EIO) {
+ network_connect(wifi->scan_pending_network);
+ wifi->scan_pending_network = NULL;
+ connman_network_set_connecting(wifi->network);
+ } else if (connman_setting_get_bool("WifiRoaming") && wifi->network) {
+ bssid_list = connman_network_get_bssid_list(wifi->network);
- value = g_key_file_get_boolean(keyfile,
- services[i], "Favorite", NULL);
- if (!value) {
- g_key_file_free(keyfile);
- continue;
- }
+ if (g_slist_length(bssid_list) <= 1)
+ goto done;
- ssid = g_key_file_get_string(keyfile,
- services[i], "SSID", NULL);
+ if (!connman_network_get_connected(wifi->network))
+ goto done;
- name = g_key_file_get_string(keyfile, services[i], "Name",
- NULL);
+ if (connman_network_get_bool(wifi->network, "WiFi.Roaming"))
+ goto done;
- ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
- if (ret < 0)
- add_param_failed++;
- else if (ret > 0)
- num_ssids++;
+ if (!need_bss_transition(
+ connman_network_get_frequency(wifi->network),
+ connman_network_get_snr(wifi->network),
+ connman_network_get_strength(wifi->network)))
+ goto done;
- g_free(ssid);
- g_free(name);
- g_key_file_free(keyfile);
- }
+ for (bssid_list; bssid_list; bssid_list = bssid_list->next) {
+ struct g_connman_bssids *bssid = bssid_list->data;
- /*
- * Check if there are any hidden AP that needs to be provisioned.
- */
- entries = connman_config_get_entries("wifi");
- for (i = 0; entries && entries[i]; i++) {
- int len;
+ if (check_bss_condition(bssid->frequency,
+ bssid->score_snr, bssid->strength))
+ roaming_ap_found = true;
+ }
- if (!entries[i]->hidden)
- continue;
+ if (roaming_ap_found) {
+ char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
+ char *bssid_str = bssid_buff;
+ unsigned char *bssid;
- if (!entries[i]->ssid) {
- ssid = entries[i]->name;
- len = strlen(ssid);
- } else {
- ssid = entries[i]->ssid;
- len = entries[i]->ssid_len;
+ bssid = connman_network_get_bssid(wifi->network);
+ snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
+ connman_network_set_string(wifi->network,
+ "WiFi.RoamingCurBSSID", bssid_str);
+
+ network_disconnect(wifi->network);
+ wifi->pending_network = wifi->network;
+ connman_network_set_bool(wifi->network, "WiFi.Roaming", true);
}
+ }
- if (!ssid)
- continue;
+done:
+ if (is_wifi_notifier_registered != true &&
+ wifi_first_scan == true && found_with_first_scan == true) {
+ wifi_first_scan = false;
+ found_with_first_scan = false;
- ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
- if (ret < 0)
- add_param_failed++;
- else if (ret > 0)
- num_ssids++;
+ connman_notifier_register(¬ifier);
+ is_wifi_notifier_registered = true;
}
+#endif
+}
- connman_config_free_entries(entries);
+static void scan_callback_hidden(int result,
+ GSupplicantInterface *interface, void *user_data)
+{
+ struct connman_device *device = user_data;
+ struct wifi_data *wifi = connman_device_get_data(device);
+ GSupplicantScanParams *scan_params;
+ int ret;
- if (add_param_failed > 0)
- DBG("Unable to scan %d out of %d SSIDs",
- add_param_failed, num_ssids);
+ DBG("result %d wifi %p", result, wifi);
- g_strfreev(services);
+ if (!wifi)
+ goto out;
- return num_ssids;
+ /* User is trying to connect to a hidden AP */
+ if (wifi->hidden && wifi->postpone_hidden)
+ goto out;
+
+ scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!scan_params)
+ goto out;
+
+ if (get_hidden_connections_params(wifi, scan_params) > 0) {
+ ret = g_supplicant_interface_scan(wifi->interface,
+ scan_params,
+#if defined TIZEN_EXT
+ scan_callback,
+#else
+ scan_callback_hidden,
+#endif
+ device);
+ if (ret == 0)
+ return;
+ }
+
+ g_supplicant_free_scan_params(scan_params);
+
+out:
+ scan_callback(result, interface, user_data);
}
-static int get_hidden_connections_params(struct wifi_data *wifi,
- GSupplicantScanParams *scan_params)
+static gboolean autoscan_timeout(gpointer data)
{
- int driver_max_ssids, i;
- GSupplicantScanParams *orig_params;
+ struct connman_device *device = data;
+ struct wifi_data *wifi = connman_device_get_data(device);
+ struct autoscan_params *autoscan;
+ int interval;
- /*
- * Scan hidden networks so that we can autoconnect to them.
- * We will assume 1 as a default number of ssid to scan.
- */
- driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
- wifi->interface);
- if (driver_max_ssids == 0)
- driver_max_ssids = 1;
+ if (!wifi)
+ return FALSE;
- DBG("max ssids %d", driver_max_ssids);
+ autoscan = wifi->autoscan;
- if (!wifi->scan_params) {
- wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
- if (!wifi->scan_params)
- return 0;
+#if defined TIZEN_EXT
+ if (!autoscan)
+ return FALSE;
+#endif
- if (get_hidden_connections(wifi->scan_params) == 0) {
- g_supplicant_free_scan_params(wifi->scan_params);
- wifi->scan_params = NULL;
+ if (autoscan->interval <= 0) {
+ interval = autoscan->base;
+ goto set_interval;
+ } else
+ interval = autoscan->interval * autoscan->base;
- return 0;
- }
- }
+#if defined TIZEN_EXT
+ if (autoscan->interval >= autoscan->limit)
+#else
+ if (interval > autoscan->limit)
+#endif
+ interval = autoscan->limit;
- orig_params = wifi->scan_params;
+ throw_wifi_scan(wifi->device, scan_callback_hidden);
- /* Let's transfer driver_max_ssids params */
- for (i = 0; i < driver_max_ssids; i++) {
- struct scan_ssid *ssid;
+ /*
+ * In case BackgroundScanning is disabled, interval will reach the
+ * limit exactly after the very first passive scanning. It allows
+ * to ensure at most one passive scan is performed in such cases.
+ */
+ if (!connman_setting_get_bool("BackgroundScanning") &&
+ interval == autoscan->limit) {
+ g_source_remove(autoscan->timeout);
+ autoscan->timeout = 0;
- if (!wifi->scan_params->ssids)
- break;
+ connman_device_unref(device);
- ssid = orig_params->ssids->data;
- orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
- scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
+ return FALSE;
}
- if (i > 0) {
- scan_params->num_ssids = i;
- scan_params->ssids = g_slist_reverse(scan_params->ssids);
+set_interval:
+ DBG("interval %d", interval);
+
+ autoscan->interval = interval;
+
+ autoscan->timeout = g_timeout_add_seconds(interval,
+ autoscan_timeout, device);
+
+ return FALSE;
+}
+
+static void start_autoscan(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ struct autoscan_params *autoscan;
- if (orig_params->num_freqs <= 0)
- goto err;
+ DBG("");
- scan_params->freqs =
- g_malloc(sizeof(uint16_t) * orig_params->num_freqs);
- memcpy(scan_params->freqs, orig_params->freqs,
- sizeof(uint16_t) *orig_params->num_freqs);
+ if (!wifi)
+ return;
- scan_params->num_freqs = orig_params->num_freqs;
+ if (wifi->p2p_device)
+ return;
- } else
- goto err;
+ if (wifi->connected)
+ return;
- orig_params->num_ssids -= scan_params->num_ssids;
+ autoscan = wifi->autoscan;
+ if (!autoscan)
+ return;
- return scan_params->num_ssids;
+ if (autoscan->timeout > 0 || autoscan->interval > 0)
+ return;
-err:
- g_slist_free_full(scan_params->ssids, g_free);
- g_supplicant_free_scan_params(wifi->scan_params);
- wifi->scan_params = NULL;
+ connman_device_ref(device);
- return 0;
+ autoscan_timeout(device);
}
-static int throw_wifi_scan(struct connman_device *device,
- GSupplicantInterfaceCallback callback)
+static struct autoscan_params *parse_autoscan_params(const char *params)
{
- struct wifi_data *wifi = connman_device_get_data(device);
- int ret;
+ struct autoscan_params *autoscan;
+ char **list_params;
+ int limit;
+ int base;
- if (!wifi)
- return -ENODEV;
+ DBG("");
- DBG("device %p %p", device, wifi->interface);
+ list_params = g_strsplit(params, ":", 0);
+ if (list_params == 0)
+ return NULL;
- if (wifi->tethering)
- return -EBUSY;
+ if (!g_strcmp0(list_params[0], "exponential") &&
+ g_strv_length(list_params) == 3) {
+ base = atoi(list_params[1]);
+ limit = atoi(list_params[2]);
+ } else if (!g_strcmp0(list_params[0], "single") &&
+ g_strv_length(list_params) == 2)
+ base = limit = atoi(list_params[1]);
+ else {
+ g_strfreev(list_params);
+ return NULL;
+ }
- if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
- return -EALREADY;
+ DBG("Setup %s autoscanning", list_params[0]);
- connman_device_ref(device);
+ g_strfreev(list_params);
- ret = g_supplicant_interface_scan(wifi->interface, NULL,
- callback, device);
- if (ret == 0) {
- connman_device_set_scanning(device,
- CONNMAN_SERVICE_TYPE_WIFI, true);
- } else
- connman_device_unref(device);
+ autoscan = g_try_malloc0(sizeof(struct autoscan_params));
+ if (!autoscan) {
+ DBG("Could not allocate memory for autoscan");
+ return NULL;
+ }
- return ret;
+ DBG("base %d - limit %d", base, limit);
+ autoscan->base = base;
+ autoscan->limit = limit;
+
+ return autoscan;
}
-static void hidden_free(struct hidden_params *hidden)
+static void setup_autoscan(struct wifi_data *wifi)
{
- if (!hidden)
+ /*
+ * If BackgroundScanning is enabled, setup exponential
+ * autoscanning if it has not been previously done.
+ */
+ if (connman_setting_get_bool("BackgroundScanning")) {
+ wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
return;
+ }
+#if defined TIZEN_EXT
+ else {
+ if (wifi->autoscan) {
+ g_free(wifi->autoscan);
+ wifi->autoscan = NULL;
+ }
- if (hidden->scan_params)
- g_supplicant_free_scan_params(hidden->scan_params);
- g_free(hidden->identity);
- g_free(hidden->passphrase);
- g_free(hidden->security);
- g_free(hidden);
+ DBG("BackgroundScanning is disabled");
+
+ return;
+ }
+#else
+
+ /*
+ * On the contrary, if BackgroundScanning is disabled, update autoscan
+ * parameters based on the type of scanning that is being performed.
+ */
+ if (wifi->autoscan) {
+ g_free(wifi->autoscan);
+ wifi->autoscan = NULL;
+ }
+
+ switch (wifi->scanning_type) {
+ case WIFI_SCANNING_PASSIVE:
+ /* Do not setup autoscan. */
+ break;
+ case WIFI_SCANNING_ACTIVE:
+ /* Setup one single passive scan after active. */
+ wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
+ break;
+ case WIFI_SCANNING_UNKNOWN:
+ /* Setup autoscan in this case but we should never fall here. */
+ wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
+ break;
+ }
+#endif
}
-static void scan_callback(int result, GSupplicantInterface *interface,
- void *user_data)
+static void finalize_interface_creation(struct wifi_data *wifi)
{
- struct connman_device *device = user_data;
- struct wifi_data *wifi = connman_device_get_data(device);
- bool scanning;
+ DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
- DBG("result %d wifi %p", result, wifi);
+ if (!wifi->device) {
+ connman_error("WiFi device not set");
+ return;
+ }
- if (wifi) {
- if (wifi->hidden && !wifi->postpone_hidden) {
- connman_network_clear_hidden(wifi->hidden->user_data);
- hidden_free(wifi->hidden);
- wifi->hidden = NULL;
- }
+ connman_device_set_powered(wifi->device, true);
- if (wifi->scan_params) {
- g_supplicant_free_scan_params(wifi->scan_params);
- wifi->scan_params = NULL;
- }
- }
+ if (wifi->p2p_device)
+ return;
- if (result < 0)
- connman_device_reset_scanning(device);
+ if (!wifi->autoscan)
+ setup_autoscan(wifi);
- /* User is connecting to a hidden AP, let's wait for finished event */
- if (wifi && wifi->hidden && wifi->postpone_hidden) {
- GSupplicantScanParams *scan_params;
- int ret;
+ start_autoscan(wifi->device);
+}
- wifi->postpone_hidden = false;
- scan_params = wifi->hidden->scan_params;
- wifi->hidden->scan_params = NULL;
+static void interface_create_callback(int result,
+ GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct wifi_data *wifi = user_data;
++ char *bgscan_range_max;
++ long value;
- reset_autoscan(device);
+ DBG("result %d ifname %s, wifi %p", result,
+ g_supplicant_interface_get_ifname(interface),
+ wifi);
- ret = g_supplicant_interface_scan(wifi->interface, scan_params,
- scan_callback, device);
- if (ret == 0)
- return;
+ if (result < 0 || !wifi)
+ return;
- /* On error, let's recall scan_callback, which will cleanup */
- return scan_callback(ret, interface, user_data);
+ wifi->interface = interface;
+ g_supplicant_interface_set_data(interface, wifi);
+
+ if (g_supplicant_interface_get_ready(interface)) {
+ wifi->interface_ready = true;
+ finalize_interface_creation(wifi);
}
- scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
+
- if (scanning) {
- connman_device_set_scanning(device,
- CONNMAN_SERVICE_TYPE_WIFI, false);
++ /*
++ * Set the BSS expiration age to match the long scanning
++ * interval to avoid the loss of unconnected networks between
++ * two scans.
++ */
++ bgscan_range_max = strrchr(BGSCAN_DEFAULT, ':');
++ if (!bgscan_range_max || strlen(bgscan_range_max) < 1)
++ return;
+
++ value = strtol(bgscan_range_max + 1, NULL, 10);
++ if (value <= 0 || errno == ERANGE)
++ return;
++
++ if (g_supplicant_interface_set_bss_expiration_age(interface,
++ value + SCAN_MAX_DURATION) < 0) {
++ connman_warn("Failed to set bss expiration age");
+ }
+}
- if (result != -ENOLINK)
- start_autoscan(device);
+static int wifi_enable(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ int index;
+ char *interface;
- const char *driver = connman_option_get_string("wifi");
++ const char *driver = connman_setting_get_string("wifi");
+ int ret;
- /*
- * If we are here then we were scanning; however, if we are
- * also mid-flight disabling the interface, then wifi_disable
- * has already cleared the device scanning state and
- * unreferenced the device, obviating the need to do it here.
- */
+ DBG("device %p %p", device, wifi);
- if (scanning)
- connman_device_unref(device);
+ index = connman_device_get_index(device);
+ if (!wifi || index < 0)
+ return -ENODEV;
+
+ if (is_p2p_connecting())
+ return -EINPROGRESS;
+
+ interface = connman_inet_ifname(index);
+ ret = g_supplicant_interface_create(interface, driver, NULL,
+#ifdef TIZEN_EXT
+ connman_device_get_mac_policy(device),
+ connman_device_get_preassoc_mac_policy(device),
+ connman_device_get_random_mac_lifetime(device),
+#endif /* TIZEN_EXT */
+ interface_create_callback,
+ wifi);
+ g_free(interface);
+
+ if (ret < 0)
+ return ret;
+
+ return -EINPROGRESS;
}
-static void scan_callback_hidden(int result,
- GSupplicantInterface *interface, void *user_data)
+static int wifi_disable(struct connman_device *device)
{
- struct connman_device *device = user_data;
struct wifi_data *wifi = connman_device_get_data(device);
- GSupplicantScanParams *scan_params;
int ret;
- DBG("result %d wifi %p", result, wifi);
+ DBG("device %p wifi %p", device, wifi);
if (!wifi)
- goto out;
+ return -ENODEV;
- /* User is trying to connect to a hidden AP */
- if (wifi->hidden && wifi->postpone_hidden)
- goto out;
+ wifi->connected = false;
+ wifi->disconnecting = false;
- scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
- if (!scan_params)
- goto out;
+ if (wifi->pending_network)
+ wifi->pending_network = NULL;
- if (get_hidden_connections_params(wifi, scan_params) > 0) {
- ret = g_supplicant_interface_scan(wifi->interface,
- scan_params,
- scan_callback_hidden,
- device);
- if (ret == 0)
- return;
- }
+#if !defined TIZEN_EXT
+ stop_autoscan(device);
+#endif
- g_supplicant_free_scan_params(scan_params);
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
+ g_source_remove(wifi->p2p_find_timeout);
+ wifi->p2p_find_timeout = 0;
+ connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
+ connman_device_unref(wifi->device);
+ }
-out:
- scan_callback(result, interface, user_data);
-}
+#if defined TIZEN_EXT
+ if (wifi->automaxspeed_timeout != 0) {
+ g_source_remove(wifi->automaxspeed_timeout);
+ wifi->automaxspeed_timeout = 0;
+ }
+#endif
-static gboolean autoscan_timeout(gpointer data)
-{
- struct connman_device *device = data;
- struct wifi_data *wifi = connman_device_get_data(device);
- struct autoscan_params *autoscan;
- int interval;
+ /* In case of a user scan, device is still referenced */
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, false);
+ connman_device_unref(wifi->device);
+ }
- if (!wifi)
- return FALSE;
+#if defined TIZEN_EXT
+ stop_autoscan(device);
+#endif
- autoscan = wifi->autoscan;
+ remove_networks(device, wifi);
+ remove_peers(wifi);
- if (autoscan->interval <= 0) {
- interval = autoscan->base;
- goto set_interval;
- } else
- interval = autoscan->interval * autoscan->base;
+#if defined TIZEN_EXT
+ wifi->scan_pending_network = NULL;
- if (interval > autoscan->limit)
- interval = autoscan->limit;
+ if (is_wifi_notifier_registered == true) {
+ connman_notifier_unregister(¬ifier);
+ is_wifi_notifier_registered = false;
+ }
+#endif
- throw_wifi_scan(wifi->device, scan_callback_hidden);
+ ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
+ if (ret < 0)
+ return ret;
- /*
- * In case BackgroundScanning is disabled, interval will reach the
- * limit exactly after the very first passive scanning. It allows
- * to ensure at most one passive scan is performed in such cases.
- */
- if (!connman_setting_get_bool("BackgroundScanning") &&
- interval == autoscan->limit) {
- g_source_remove(autoscan->timeout);
- autoscan->timeout = 0;
+ return -EINPROGRESS;
+}
- connman_device_unref(device);
+static int get_latest_connections(int max_ssids,
+ GSupplicantScanParams *scan_data)
+{
+ GSequenceIter *iter;
+ GSequence *latest_list;
+ struct last_connected *entry;
+ GKeyFile *keyfile;
+ GTimeVal modified;
+ gchar **services;
+ gchar *str;
+ char *ssid;
+ int i, freq;
+ int num_ssids = 0;
- return FALSE;
- }
+ latest_list = g_sequence_new(free_entry);
+ if (!latest_list)
+ return -ENOMEM;
-set_interval:
- DBG("interval %d", interval);
+ services = connman_storage_get_services();
+ for (i = 0; services && services[i]; i++) {
+ if (strncmp(services[i], "wifi_", 5) != 0)
+ continue;
- autoscan->interval = interval;
+ keyfile = connman_storage_load_service(services[i]);
+ if (!keyfile)
+ continue;
- autoscan->timeout = g_timeout_add_seconds(interval,
- autoscan_timeout, device);
+ str = g_key_file_get_string(keyfile,
+ services[i], "Favorite", NULL);
+ if (!str || g_strcmp0(str, "true")) {
+ g_free(str);
+ g_key_file_free(keyfile);
+ continue;
+ }
+ g_free(str);
- return FALSE;
-}
+ str = g_key_file_get_string(keyfile,
+ services[i], "AutoConnect", NULL);
+ if (!str || g_strcmp0(str, "true")) {
+ g_free(str);
+ g_key_file_free(keyfile);
+ continue;
+ }
+ g_free(str);
-static void start_autoscan(struct connman_device *device)
-{
- struct wifi_data *wifi = connman_device_get_data(device);
- struct autoscan_params *autoscan;
+ str = g_key_file_get_string(keyfile,
+ services[i], "Modified", NULL);
+ if (!str) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+ util_iso8601_to_timeval(str, &modified);
+ g_free(str);
- DBG("");
+ ssid = g_key_file_get_string(keyfile,
+ services[i], "SSID", NULL);
- if (!wifi)
- return;
+ freq = g_key_file_get_integer(keyfile, services[i],
+ "Frequency", NULL);
+ if (freq) {
+ entry = g_try_new(struct last_connected, 1);
+ if (!entry) {
+ g_sequence_free(latest_list);
+ g_key_file_free(keyfile);
+ g_free(ssid);
+#if defined TIZEN_EXT
+ g_strfreev(services);
+#endif
+ return -ENOMEM;
+ }
- if (wifi->p2p_device)
- return;
+ entry->ssid = ssid;
+ entry->modified = modified;
+ entry->freq = freq;
- if (wifi->connected)
- return;
+ g_sequence_insert_sorted(latest_list, entry,
+ sort_entry, NULL);
+ num_ssids++;
+ } else
+ g_free(ssid);
- autoscan = wifi->autoscan;
- if (!autoscan)
- return;
+ g_key_file_free(keyfile);
+ }
- if (autoscan->timeout > 0 || autoscan->interval > 0)
- return;
+ g_strfreev(services);
- connman_device_ref(device);
+ num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
- autoscan_timeout(device);
-}
+ iter = g_sequence_get_begin_iter(latest_list);
-static struct autoscan_params *parse_autoscan_params(const char *params)
-{
- struct autoscan_params *autoscan;
- char **list_params;
- int limit;
- int base;
+ for (i = 0; i < num_ssids; i++) {
+ entry = g_sequence_get(iter);
- DBG("");
+ DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
+ entry->modified.tv_sec);
- list_params = g_strsplit(params, ":", 0);
- if (list_params == 0)
- return NULL;
+ add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
+ max_ssids, entry->ssid);
- if (!g_strcmp0(list_params[0], "exponential") &&
- g_strv_length(list_params) == 3) {
- base = atoi(list_params[1]);
- limit = atoi(list_params[2]);
- } else if (!g_strcmp0(list_params[0], "single") &&
- g_strv_length(list_params) == 2)
- base = limit = atoi(list_params[1]);
- else {
- g_strfreev(list_params);
- return NULL;
+ iter = g_sequence_iter_next(iter);
}
- DBG("Setup %s autoscanning", list_params[0]);
+ g_sequence_free(latest_list);
+ return num_ssids;
+}
- g_strfreev(list_params);
+static void wifi_update_scanner_type(struct wifi_data *wifi,
+ enum wifi_scanning_type new_type)
+{
+ DBG("");
- autoscan = g_try_malloc0(sizeof(struct autoscan_params));
- if (!autoscan) {
- DBG("Could not allocate memory for autoscan");
- return NULL;
- }
+ if (!wifi || wifi->scanning_type == new_type)
+ return;
- DBG("base %d - limit %d", base, limit);
- autoscan->base = base;
- autoscan->limit = limit;
+ wifi->scanning_type = new_type;
- return autoscan;
+ setup_autoscan(wifi);
}
-static void setup_autoscan(struct wifi_data *wifi)
+static int wifi_scan_simple(struct connman_device *device)
{
- /*
- * If BackgroundScanning is enabled, setup exponential
- * autoscanning if it has not been previously done.
- */
- if (connman_setting_get_bool("BackgroundScanning")) {
- wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
- return;
- }
+ struct wifi_data *wifi = connman_device_get_data(device);
- /*
- * On the contrary, if BackgroundScanning is disabled, update autoscan
- * parameters based on the type of scanning that is being performed.
- */
- if (wifi->autoscan) {
- g_free(wifi->autoscan);
- wifi->autoscan = NULL;
- }
+ reset_autoscan(device);
+
+ /* Distinguish between devices performing passive and active scanning */
+ if (wifi)
+ wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
- switch (wifi->scanning_type) {
- case WIFI_SCANNING_PASSIVE:
- /* Do not setup autoscan. */
- break;
- case WIFI_SCANNING_ACTIVE:
- /* Setup one single passive scan after active. */
- wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
- break;
- case WIFI_SCANNING_UNKNOWN:
- /* Setup autoscan in this case but we should never fall here. */
- wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
- break;
- }
+ return throw_wifi_scan(device, scan_callback_hidden);
}
-static void finalize_interface_creation(struct wifi_data *wifi)
+static gboolean p2p_find_stop(gpointer data)
{
- DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
+ struct connman_device *device = data;
+ struct wifi_data *wifi = connman_device_get_data(device);
- if (!wifi->device) {
- connman_error("WiFi device not set");
- return;
- }
+ DBG("");
- connman_device_set_powered(wifi->device, true);
+ if (wifi) {
+ wifi->p2p_find_timeout = 0;
- if (wifi->p2p_device)
- return;
+ g_supplicant_interface_p2p_stop_find(wifi->interface);
+ }
- if (!wifi->autoscan)
- setup_autoscan(wifi);
+ connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
- start_autoscan(wifi->device);
+ connman_device_unref(device);
+ start_autoscan(device);
+
+ return FALSE;
}
-static void interface_create_callback(int result,
- GSupplicantInterface *interface,
+static void p2p_find_callback(int result, GSupplicantInterface *interface,
void *user_data)
{
- struct wifi_data *wifi = user_data;
- char *bgscan_range_max;
- long value;
-
- DBG("result %d ifname %s, wifi %p", result,
- g_supplicant_interface_get_ifname(interface),
- wifi);
+ struct connman_device *device = user_data;
+ struct wifi_data *wifi = connman_device_get_data(device);
- if (result < 0 || !wifi)
- return;
+ DBG("result %d wifi %p", result, wifi);
- wifi->interface = interface;
- g_supplicant_interface_set_data(interface, wifi);
+ if (!wifi)
+ goto error;
- if (g_supplicant_interface_get_ready(interface)) {
- wifi->interface_ready = true;
- finalize_interface_creation(wifi);
+ if (wifi->p2p_find_timeout) {
+ g_source_remove(wifi->p2p_find_timeout);
+ wifi->p2p_find_timeout = 0;
}
- /*
- * Set the BSS expiration age to match the long scanning
- * interval to avoid the loss of unconnected networks between
- * two scans.
- */
- bgscan_range_max = strrchr(BGSCAN_DEFAULT, ':');
- if (!bgscan_range_max || strlen(bgscan_range_max) < 1)
- return;
+ if (result)
+ goto error;
- value = strtol(bgscan_range_max + 1, NULL, 10);
- if (value <= 0 || errno == ERANGE)
- return;
+ wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
+ p2p_find_stop, device);
+ if (!wifi->p2p_find_timeout)
+ goto error;
- if (g_supplicant_interface_set_bss_expiration_age(interface,
- value + SCAN_MAX_DURATION) < 0) {
- connman_warn("Failed to set bss expiration age");
- }
+ return;
+error:
+ p2p_find_stop(device);
}
-static int wifi_enable(struct connman_device *device)
+static int p2p_find(struct connman_device *device)
{
- struct wifi_data *wifi = connman_device_get_data(device);
- int index;
- char *interface;
- const char *driver = connman_setting_get_string("wifi");
+ struct wifi_data *wifi;
int ret;
- DBG("device %p %p", device, wifi);
+ DBG("");
- index = connman_device_get_index(device);
- if (!wifi || index < 0)
- return -ENODEV;
+ if (!p2p_technology)
+ return -ENOTSUP;
- if (is_p2p_connecting())
- return -EINPROGRESS;
+ wifi = connman_device_get_data(device);
- interface = connman_inet_ifname(index);
- ret = g_supplicant_interface_create(interface, driver, NULL,
- interface_create_callback,
- wifi);
- g_free(interface);
+ if (g_supplicant_interface_is_p2p_finding(wifi->interface))
+ return -EALREADY;
- if (ret < 0)
- return ret;
+ reset_autoscan(device);
+ connman_device_ref(device);
- return -EINPROGRESS;
+ ret = g_supplicant_interface_p2p_find(wifi->interface,
+ p2p_find_callback, device);
+ if (ret) {
+ connman_device_unref(device);
+ start_autoscan(device);
+ } else {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_P2P, true);
+ }
+
+ return ret;
}
-static int wifi_disable(struct connman_device *device)
+#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);
- int ret;
+ bool scanning;
- DBG("device %p wifi %p", device, wifi);
+ 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,
+ CONNMAN_SERVICE_TYPE_WIFI);
+ 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 = NULL;
+ bool scanning;
+ int ret;
+ int freq;
+ int count = 0;
if (!wifi)
return -ENODEV;
static void disconnect_callback(int result, GSupplicantInterface *interface,
void *user_data)
{
- struct wifi_data *wifi = dd->wifi;
+ struct disconnect_data *dd = user_data;
+ struct connman_network *network = dd->network;
- struct connman_network *network = user_data;
+#if defined TIZEN_EXT
+ GList *list;
+ struct wifi_data *wifi;
+
++ g_free(dd);
+ DBG("network %p result %d", network, result);
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->network == NULL && wifi->disconnecting == true)
+ wifi->disconnecting = false;
+
+ if (wifi->network == network)
+ goto found;
+ }
+
+ /* wifi_data may be invalid because wifi is already disabled */
+ return;
- struct wifi_data *wifi = user_data;
+found:
+#else
++ struct wifi_data *wifi = dd->wifi;
+ g_free(dd);
+#endif
- DBG("result %d supplicant interface %p wifi %p",
- result, interface, wifi);
+ DBG("result %d supplicant interface %p wifi %p networks: current %p "
+ "pending %p disconnected %p", result, interface, wifi,
+ wifi->network, wifi->pending_network, network);
if (result == -ECONNABORTED) {
DBG("wifi interface no longer available");
return;
}
- if (wifi->network && wifi->network != wifi->pending_network)
+#if defined TIZEN_EXT
+ if (wifi->network &&
+ (wifi->network != wifi->pending_network ||
+ connman_network_get_bool(wifi->network, "WiFi.Roaming")))
+#else
- connman_network_set_connected(wifi->network, false);
- wifi->network = NULL;
+ if (g_slist_find(wifi->networks, network))
+#endif
+ connman_network_set_connected(network, false);
wifi->disconnecting = false;
+
+ if (network != wifi->network) {
+ if (network == wifi->pending_network)
+ wifi->pending_network = NULL;
+ DBG("current wifi network has changed since disconnection");
+ return;
+ }
+
+ wifi->network = NULL;
+
wifi->connected = false;
if (wifi->pending_network) {
static int network_disconnect(struct connman_network *network)
{
struct connman_device *device = connman_network_get_device(network);
+ struct disconnect_data *dd;
struct wifi_data *wifi;
int err;
+#if defined TIZEN_EXT
+ struct connman_service *service;
+#endif
DBG("network %p", network);
if (!wps_ssid || wps_ssid_len != ssid_len ||
memcmp(ssid, wps_ssid, ssid_len) != 0) {
+ dd = g_malloc0(sizeof(*dd));
+ dd->wifi = wifi;
+ dd->network = network;
+
connman_network_set_associating(network, false);
- #if defined TIZEN_EXT
g_supplicant_interface_disconnect(wifi->interface,
- disconnect_callback, wifi->network);
-
+ disconnect_callback, dd);
++#if defined TIZEN_EXT
+ connman_network_set_bool(network, "WiFi.UseWPS", false);
+ connman_network_set_string(network, "WiFi.PinWPS", NULL);
- #else
- g_supplicant_interface_disconnect(wifi->interface,
- disconnect_callback, wifi);
+#endif
return false;
}
struct connman_network *network,
struct wifi_data *wifi)
{
- #if defined TIZEN_EXT
- const char *security;
struct connman_service *service;
- struct connman_service *service;
-
- if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
++#if defined TIZEN_EXT
++ const char *security;
+ if (wifi->connected)
+ return false;
+
+ security = connman_network_get_string(network, "WiFi.Security");
+
+ if (security && g_str_equal(security, "ieee8021x") == true &&
+ wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->retries = 0;
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
+
+ return false;
+ }
+
+ if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
+ return false;
+#else
+ if ((wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) &&
+ !((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING) &&
+ (wifi->assoc_code == ASSOC_STATUS_AUTH_TIMEOUT)))
return false;
if (wifi->connected)
/* See table 8-36 Reason codes in IEEE Std 802.11 */
switch (wifi->disconnect_code) {
-
++#if defined TIZEN_EXT
+ case 1: /* Unspecified reason */
+ /* Let's assume it's because we got blocked */
++#endif
case 6: /* Class 2 frame received from nonauthenticated STA */
connman_network_set_error(network,
CONNMAN_NETWORK_ERROR_BLOCKED);
return g_supplicant_set_country(alpha2, regdom_callback, NULL);
}
- string = connman_option_get_string("INSPreferredFreqBSSID");
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static void supp_ins_init(void)
+{
+ const char *string;
+ GSupplicantINSPreferredFreq preferred_freq;
+
++ string = connman_setting_get_string("INSPreferredFreqBSSID");
+ if (g_strcmp0(string, "5GHz") == 0)
+ preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ;
+ else if (g_strcmp0(string, "2.4GHz") == 0)
+ preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ;
+ else
+ preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN;
+
+ g_supplicant_set_ins_settings(preferred_freq,
+ connman_setting_get_bool("INSLastConnectedBSSID"),
+ connman_setting_get_bool("INSAssocReject"),
+ connman_setting_get_bool("INSSignalBSSID"),
+ connman_setting_get_uint("INSPreferredFreqBSSIDScore"),
+ connman_setting_get_uint("INSLastConnectedBSSIDScore"),
+ connman_setting_get_uint("INSAssocRejectScore"),
+ connman_setting_get_int("INSSignalLevel3_5GHz"),
+ connman_setting_get_int("INSSignalLevel3_24GHz")
+ );
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
static struct connman_technology_driver tech_driver = {
.name = "wifi",
.type = CONNMAN_SERVICE_TYPE_WIFI,
static unsigned int vpn_autoconnect_id = 0;
static struct connman_service *current_default = NULL;
static bool services_dirty = false;
+ static bool enable_online_to_ready_transition = false;
+ static unsigned int online_check_initial_interval = 0;
+ static unsigned int online_check_max_interval = 0;
+#if defined TIZEN_EXT
+static bool auto_connect_mode = TRUE;
+
+struct saved_profiles {
+ GTimeVal modified;
+ gchar *profile_name;
+};
+
+static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+enum connman_ins_preferred_freq {
+ CONNMAN_INS_PREFERRED_FREQ_UNKNOWN,
+ CONNMAN_INS_PREFERRED_FREQ_24GHZ,
+ CONNMAN_INS_PREFERRED_FREQ_5GHZ,
+};
+
+struct connman_ins_settings {
+ bool last_user_selection;
+ unsigned int last_user_selection_time;
+ unsigned int last_user_selection_score;
+ bool last_connected;
+ unsigned int last_connected_score;
+ enum connman_ins_preferred_freq preferred_freq;
+ unsigned int preferred_freq_score;
+ unsigned int security_priority[CONNMAN_SERVICE_SECURITY_MAX];
+ unsigned int security_priority_count;
+ unsigned int security_priority_score;
+ bool signal;
+ bool internet;
+ unsigned int internet_score;
+ int signal_level3_5ghz;
+ int signal_level3_24ghz;
+};
+
+static struct connman_ins_settings ins_settings;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
struct connman_stats {
bool valid;
bool enabled;
return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
}
- static void set_split_routing(struct connman_service *service, bool value)
+#ifdef TIZEN_EXT
+static const char *__connman_dnsconfig_method2string(enum connman_dnsconfig_method method)
+{
+ switch (method) {
+ case CONNMAN_DNSCONFIG_METHOD_UNKNOWN:
+ return "unknown";
+ case CONNMAN_DNSCONFIG_METHOD_MANUAL:
+ return "manual";
+ case CONNMAN_DNSCONFIG_METHOD_DHCP:
+ return "dhcp";
+ }
+
+ return NULL;
+}
+
+static enum connman_dnsconfig_method __connman_dnsconfig_string2method(
+ const char *method)
+{
+ if (g_strcmp0(method, "manual") == 0)
+ return CONNMAN_DNSCONFIG_METHOD_MANUAL;
+ else if (g_strcmp0(method, "dhcp") == 0)
+ return CONNMAN_DNSCONFIG_METHOD_DHCP;
+ else
+ return CONNMAN_DNSCONFIG_METHOD_UNKNOWN;
+}
+#endif
+
+ void __connman_service_split_routing_changed(struct connman_service *service)
+ {
+ dbus_bool_t split_routing;
+
+ if (!service->path)
+ return;
+
+ if (!allow_property_changed(service))
+ return;
+
+ split_routing = service->do_split_routing;
+ if (!connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "SplitRouting",
+ DBUS_TYPE_BOOLEAN, &split_routing))
+ connman_warn("cannot send SplitRouting property change on %s",
+ service->identifier);
+ }
+
+ void __connman_service_set_split_routing(struct connman_service *service,
+ bool value)
{
if (service->type != CONNMAN_SERVICE_TYPE_VPN)
return;
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
case CONNMAN_SERVICE_TYPE_VPN:
- set_split_routing(service, g_key_file_get_boolean(keyfile,
- service->identifier,
- "SplitRouting", NULL));
+ __connman_service_set_split_routing(service,
+ g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
/* fall through */
case CONNMAN_SERVICE_TYPE_WIFI:
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
case CONNMAN_SERVICE_TYPE_VPN:
- set_split_routing(service, g_key_file_get_boolean(keyfile,
- service->identifier,
- "SplitRouting", NULL));
+ __connman_service_set_split_routing(service,
+ g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
autoconnect = g_key_file_get_boolean(keyfile,
service->identifier, "AutoConnect", &error);
if (!i)
__connman_resolver_append_fallback_nameservers();
- const char *global_dns = connman_option_get_string("GlobalNameserver");
+#if defined TIZEN_EXT
++ const char *global_dns = connman_setting_get_string("GlobalNameserver");
+ if (global_dns)
+ nameserver_add(service, type, global_dns);
+#endif
+
searchdomain_add_all(service);
return 0;
i++;
}
- const char *global_dns = connman_option_get_string("GlobalNameserver");
+#if defined TIZEN_EXT
++ const char *global_dns = connman_setting_get_string("GlobalNameserver");
+ if (global_dns)
+ nameserver_remove(service, type, global_dns);
+#endif
searchdomain_remove_all(service);
return 0;
always_connect[always_connected_techs[i]] = 1;
}
++#if !defined TIZEN_EXT
static bool autoconnect_no_session_active(struct connman_service *service)
{
/*
return false;
}
++#endif
static bool autoconnect_already_connecting(struct connman_service *service,
bool autoconnecting)
continue;
}
+#if defined TIZEN_EXT
+ DBG("service %p %s %s %s, favorite(%d), ignore(%d), hidden(%d, %d)",
+ service, service->name,
+ state2string(service->state),
+ __connman_service_type2string(service->type),
+ service->favorite, is_ignore(service),
+ service->hidden, service->hidden_service);
+
+ /* Tizen takes Wi-Fi as the highest priority into consideration. */
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+ if (is_connecting(service->state) == TRUE || is_connected(service->state) == TRUE)
+ continue;
+#endif
+
+ if (service->connect_reason ==
+ CONNMAN_SERVICE_CONNECT_REASON_NATIVE) {
+ DBG("service %p uses native autonnect, skip", service);
+ continue;
+ }
+
if (service->pending ||
is_connecting(service->state) ||
is_connected(service->state)) {
for (list = service_list; list; list = list->next) {
struct connman_service *temp = list->data;
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ break;
+#endif
if (!is_connecting(temp->state) && !is_connected(temp->state))
- break;
+ continue;
if (service == temp)
continue;
service->wps = false;
service->wps_advertizing = false;
- #endif
- #if defined TIZEN_EXT
+#if defined TIZEN_EXT
+ memset(service->last_connected_bssid, 0, WIFI_BSSID_LEN_MAX);
+ service->is_internet_connection = false;
+ service->assoc_reject_count = 0;
++
+ service->disconnection_requested = false;
+ service->storage_reload = false;
+ /*
+ * Description: TIZEN implements system global connection management.
+ */
+ service->user_pdn_connection_refcount = 0;
+ __sync_synchronize();
+#endif
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ service->use_eapol = false;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
}
/**
g_hash_table_remove(service_hash, service->identifier);
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static int calculate_score_last_user_selection(struct connman_service *service)
+{
+ int score = 0;
+ struct connman_device *device;
+ const char *last_user_selection_ident;
+ time_t last_user_selection_time;
+ unsigned int frequency;
+ time_t curr_time;
+ time_t ref_time;
+ struct tm* ref_timeinfo;
+
+ device = connman_network_get_device(service->network);
+ if (!device)
+ return 0;
+
+ last_user_selection_time = connman_device_get_last_user_selection_time(device);
+ last_user_selection_ident = connman_device_get_last_user_selection_ident(device);
+ frequency = connman_network_get_frequency(service->network);
+
+ if (ins_settings.last_user_selection) {
+ if (g_strcmp0(last_user_selection_ident, service->identifier) == 0 &&
+ (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ service->strength >= ins_settings.signal_level3_24ghz) ||
+ ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ service->strength >= ins_settings.signal_level3_5ghz))) {
+
+ /* Only events that occur within 8 hours are counted. */
+ curr_time = time(NULL);
+ ref_timeinfo = localtime(&curr_time);
+ ref_timeinfo->tm_hour -= 8;
+ ref_time = mktime(ref_timeinfo);
+
+ if (last_user_selection_time > ref_time) {
+ int time_diff = (curr_time - last_user_selection_time) / 60;
+ int denominator = ins_settings.last_user_selection_time - time_diff;
+ int numerator = ins_settings.last_user_selection_time /
+ ins_settings.last_user_selection_score;
+ int last_user_score = denominator / numerator;
+
+ score += (last_user_score > ins_settings.last_user_selection_score ?
+ ins_settings.last_user_selection_score : last_user_score);
+ }
+ }
+ }
+
+ return score;
+}
+
+static int calculate_score_last_connected(struct connman_service *service)
+{
+ int score = 0;
+ struct connman_device *device;
+ const char *last_connected_ident;
+ unsigned int frequency;
+
+ device = connman_network_get_device(service->network);
+ if (!device)
+ return 0;
+
+ last_connected_ident = connman_device_get_last_connected_ident(device);
+ frequency = connman_network_get_frequency(service->network);
+
+ if (ins_settings.last_connected) {
+ if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
+ (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ service->strength >= ins_settings.signal_level3_24ghz) ||
+ ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ service->strength >= ins_settings.signal_level3_5ghz))) {
+ score += ins_settings.last_connected_score;
+ }
+ }
+
+ return score;
+}
+
+static int calculate_score_frequency(struct connman_service *service)
+{
+ int score = 0;
+ unsigned int frequency;
+
+ frequency = connman_network_get_frequency(service->network);
+
+ switch (ins_settings.preferred_freq) {
+ case CONNMAN_INS_PREFERRED_FREQ_24GHZ:
+ if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ (service->strength >= ins_settings.signal_level3_24ghz))
+ score += ins_settings.preferred_freq_score;
+
+ break;
+ case CONNMAN_INS_PREFERRED_FREQ_5GHZ:
+ if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ (service->strength >= ins_settings.signal_level3_5ghz))
+ score += ins_settings.preferred_freq_score;
+
+ break;
+ default:
+ break;
+ }
+
+ return score;
+}
+
+static int calculate_score_security_priority(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.security_priority_count)
+ score += ins_settings.security_priority[service->security];
+
+ return score;
+}
+
+static int calculate_score_internet_connection(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.internet) {
+ if (service->is_internet_connection)
+ score += ins_settings.internet_score;
+ }
+
+ return score;
+}
+
+static int calculate_score_strength(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.signal)
+ score += (((service->strength > 60) ? 60 : service->strength) - 35);
+
+ return score;
+}
+
+static int calculate_score(struct connman_service *service)
+{
+ int score_last_user_selection;
+ int score_last_connected;
+ int score_frequency;
+ int score_security_priority;
+ int score_internet_connection;
+ int score_strength;
+ int score = 0;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI) {
+ score += calculate_score_internet_connection(service);
+ service->ins_score = score;
+ return score;
+ }
+
+ score_last_user_selection = calculate_score_last_user_selection(service);
+ score_last_connected = calculate_score_last_connected(service);
+ score_frequency = calculate_score_frequency(service);
+ score_security_priority = calculate_score_security_priority(service);
+ score_internet_connection = calculate_score_internet_connection(service);
+ score_strength = calculate_score_strength(service);
+
+ score = score_last_user_selection + score_last_connected +
+ score_frequency + score_security_priority +
+ score_internet_connection + score_strength;
+
+ service->score_last_user_selection = score_last_user_selection;
+ service->score_last_connected = score_last_connected;
+ service->score_frequency = score_frequency;
+ service->score_security_priority = score_security_priority;
+ service->score_internet_connection = score_internet_connection;
+ service->score_strength = score_strength;
+
+ service->ins_score = score;
+ return score;
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
+ static gint service_compare(gconstpointer a, gconstpointer b);
+
+ static gint service_compare_vpn(struct connman_service *a,
+ struct connman_service *b)
+ {
+ struct connman_provider *provider;
+ struct connman_service *service;
+ struct connman_service *transport;
+ const char *ident;
+ bool reverse;
+
+ if (a->provider) {
+ provider = a->provider;
+ service = b;
+ reverse = false;
+ } else if (b->provider) {
+ provider = b->provider;
+ service = a;
+ reverse = true;
+ } else {
+ return 0;
+ }
+
+ ident = __connman_provider_get_transport_ident(provider);
+ transport = connman_service_lookup_from_identifier(ident);
+ if (!transport)
+ return 0;
+
+ if (reverse)
+ return service_compare(service, transport);
+
+ return service_compare(transport, service);
+ }
+
static gint service_compare(gconstpointer a, gconstpointer b)
{
struct connman_service *service_a = (void *) a;
a_connected = is_connected(state_a);
b_connected = is_connected(state_b);
- connman_option_get_string("DefaultWifiInterface");
+#if defined TIZEN_EXT
+ if ((a_connected && b_connected) &&
+ state_a == state_b &&
+ service_a->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service_b->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ const char *default_interface =
++ connman_setting_get_string("DefaultWifiInterface");
+ const char *ifname_a = connman_device_get_string(
+ connman_network_get_device(service_a->network), "Interface");
+ const char *ifname_b = connman_device_get_string(
+ connman_network_get_device(service_b->network), "Interface");
+
+ if (g_strcmp0(default_interface, ifname_a) == 0)
+ return -1;
+ else if (g_strcmp0(default_interface, ifname_b) == 0)
+ return 1;
+ }
+#endif
+
if (a_connected && b_connected) {
+ int rval;
+
+ /* Compare the VPN transport and the service */
+ if ((service_a->type == CONNMAN_SERVICE_TYPE_VPN ||
+ service_b->type == CONNMAN_SERVICE_TYPE_VPN) &&
+ service_b->type != service_a->type) {
+ rval = service_compare_vpn(service_a, service_b);
+ if (rval)
+ return rval;
+ }
+
if (service_a->order > service_b->order)
return -1;
/* It is not relevant to stay on Failure state
* when failing is due to wrong user input */
__connman_service_clear_error(service);
+#if defined TIZEN_EXT
+ /* Reseting the state back in case of failure state */
+ service->state_ipv4 = service->state_ipv6 =
+ CONNMAN_SERVICE_STATE_IDLE;
+ if (service->error != CONNMAN_SERVICE_ERROR_AUTH_FAILED &&
+ service->error != CONNMAN_SERVICE_ERROR_ASSOC_FAILED)
+ set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
+#endif
service_complete(service);
+ service_list_sort();
__connman_connection_update_gateway();
}
}
service_list_sort();
+#if defined TIZEN_EXT
+#if defined TIZEN_MAINTAIN_ONLINE
+ __connman_service_connect_default(service, old_state);
+#else
+ __connman_service_connect_default(service);
+#endif
+ /* Update Wi-Fi Roaming result */
+ if (connman_setting_get_bool("WifiRoaming") &&
+ connman_network_get_bool(service->network, "WiFi.Roaming")) {
+ const char *cur_bssid;
+ const char *dst_bssid;
+ const char *ifname;
+ struct connman_device *device;
+
+ device = connman_network_get_device(service->network);
+ if (device) {
+ ifname = connman_device_get_string(device, "Interface");
+ cur_bssid = connman_network_get_string(service->network,
+ "WiFi.RoamingCurBSSID");
+ dst_bssid = connman_network_get_string(service->network,
+ "WiFi.RoamingDstBSSID");
+ }
+
+ if (device && ifname && cur_bssid && dst_bssid) {
+ switch(new_state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ break;
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ __connman_technology_notify_roaming_state(ifname,
+ "success", cur_bssid, dst_bssid);
+ connman_network_set_bool(service->network,
+ "WiFi.Roaming", false);
+ connman_network_set_string(service->network,
+ "WiFi.RoamingCurBSSID", NULL);
+ connman_network_set_string(service->network,
+ "WiFi.RoamingDstBSSID", NULL);
+ break;
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ __connman_technology_notify_roaming_state(ifname,
+ "failure", cur_bssid, dst_bssid);
+ connman_network_set_bool(service->network,
+ "WiFi.Roaming", false);
+ connman_network_set_string(service->network,
+ "WiFi.RoamingCurBSSID", NULL);
+ connman_network_set_string(service->network,
+ "WiFi.RoamingDstBSSID", NULL);
+ break;
+ }
+ }
+ }
+#endif
+
__connman_connection_update_gateway();
+ notifier:
if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
new_state != CONNMAN_SERVICE_STATE_READY) ||
(old_state == CONNMAN_SERVICE_STATE_READY &&
if (service->phase2)
connman_network_set_string(service->network, "WiFi.Phase2",
service->phase2);
- #if defined TIZEN_EXT
+
+#if defined TIZEN_EXT
+ if (service->keymgmt_type)
+ connman_network_set_string(service->network, "WiFi.KeymgmtType",
+ service->keymgmt_type);
+
+ DBG("service->phase1 : %s", service->phase1);
+ if (service->phase1)
+ connman_network_set_string(service->network, "WiFi.Phase1",
+ service->phase1);
+#endif
+}
+
++#if defined TIZEN_EXT
+static bool has_valid_configuration_object(struct connman_service *service)
+{
+ return service->connector && service->c_sign_key && service->net_access_key;
}
+static void prepare_dpp(struct connman_service *service)
+{
+ DBG("prepare dpp");
+ if (service->connector)
+ connman_network_set_string(service->network, "WiFi.Connector",
+ service->connector);
+
+ if (service->c_sign_key)
+ connman_network_set_string(service->network, "WiFi.CSignKey",
+ service->c_sign_key);
+
+ if (service->net_access_key)
+ connman_network_set_string(service->network, "WiFi.NetAccessKey",
+ service->net_access_key);
+}
+#endif
+
static int service_connect(struct connman_service *service)
{
int err;
service_list_sort();
}
+ static void trigger_autoconnect(struct connman_service *service)
+ {
+ struct connman_device *device;
+ bool native;
+
+ if (!service->favorite)
+ return;
+
+ native = __connman_network_native_autoconnect(service->network);
+ if (native && service->autoconnect) {
+ DBG("trigger native autoconnect");
+ connman_network_set_autoconnect(service->network, true);
+ return;
+ }
+
+ device = connman_network_get_device(service->network);
+ if (device && connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_UNKNOWN))
+ return;
+
+ switch (service->type) {
+ case CONNMAN_SERVICE_TYPE_UNKNOWN:
+ case CONNMAN_SERVICE_TYPE_SYSTEM:
+ case CONNMAN_SERVICE_TYPE_P2P:
++#if defined TIZEN_EXT_WIFI_MESH
++ case CONNMAN_SERVICE_TYPE_MESH:
++#endif
+ break;
+
+ case CONNMAN_SERVICE_TYPE_GADGET:
+ case CONNMAN_SERVICE_TYPE_ETHERNET:
+ if (service->autoconnect) {
+ __connman_service_connect(service,
+ CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ break;
+ }
+
+ /* fall through */
+ case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ case CONNMAN_SERVICE_TYPE_GPS:
+ case CONNMAN_SERVICE_TYPE_VPN:
+ case CONNMAN_SERVICE_TYPE_WIFI:
+ case CONNMAN_SERVICE_TYPE_CELLULAR:
+ do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ break;
+ }
++
++#if defined TIZEN_EXT
++ /* TIZEN synchronizes below information when the service creates */
++ if (service->eap != NULL)
++ connman_network_set_string(service->network, "WiFi.EAP",
++ service->eap);
++ if (service->identity != NULL)
++ connman_network_set_string(service->network, "WiFi.Identity",
++ service->identity);
++ if (service->phase2 != NULL)
++ connman_network_set_string(service->network, "WiFi.Phase2",
++ service->phase2);
++ if (service->eap != NULL)
++ connman_network_set_string(service->network, "WiFi.Connector",
++ service->connector);
++ if (service->identity != NULL)
++ connman_network_set_string(service->network, "WiFi.CSignKey",
++ service->c_sign_key);
++ if (service->phase2 != NULL)
++ connman_network_set_string(service->network, "WiFi.NetAccessKey",
++ service->net_access_key);
++#endif
+ }
+
/**
* __connman_service_create_from_network:
* @network: network structure
.context_unref = agent_context_unref,
};
- string = connman_option_get_string("INSPreferredFreq");
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static void ins_setting_init(void)
+{
+ int i;
+ const char *string;
+ char **string_list;
+ unsigned int string_count;
+
+ ins_settings.last_user_selection = connman_setting_get_bool("INSLastUserSelection");
+ ins_settings.last_user_selection_time = connman_setting_get_uint("INSLastUserSelectionTime");
+ ins_settings.last_connected = connman_setting_get_bool("INSLastConnected");
+
++ string = connman_setting_get_string("INSPreferredFreq");
+ if (g_strcmp0(string, "5GHz") == 0)
+ ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_5GHZ;
+ else if (g_strcmp0(string, "2.4GHz") == 0)
+ ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_24GHZ;
+ else
+ ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_UNKNOWN;
+
+ ins_settings.security_priority_count = connman_setting_get_uint("INSSecurityPriorityCount");
+ ins_settings.security_priority_score = connman_setting_get_uint("INSSecurityPriorityScore");
+ string_count = ins_settings.security_priority_count;
+
+ memset(ins_settings.security_priority, 0, sizeof(ins_settings.security_priority));
+ string_list = connman_setting_get_string_list("INSSecurityPriority");
+ for (i = 0; string_list && string_list[i]; i++) {
+ unsigned int security_score = string_count * ins_settings.security_priority_score;
+
+ if (g_strcmp0(string_list[i], "WEP") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WEP] = security_score;
+ else if (g_strcmp0(string_list[i], "PSK") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_PSK] = security_score;
+ else if (g_strcmp0(string_list[i], "8021X") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_8021X] = security_score;
+ else if (g_strcmp0(string_list[i], "WPA") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WPA] = security_score;
+ else if (g_strcmp0(string_list[i], "RSN") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_RSN] = security_score;
+ else if (g_strcmp0(string_list[i], "SAE") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_SAE] = security_score;
+ else if (g_strcmp0(string_list[i], "OWE") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_OWE] = security_score;
+ else if (g_strcmp0(string_list[i], "DPP") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_DPP] = security_score;
+
+ string_count--;
+ }
+
+ ins_settings.signal = connman_setting_get_bool("INSSignal");
+ ins_settings.internet = connman_setting_get_bool("INSInternet");
+
+ ins_settings.last_user_selection_score = connman_setting_get_uint("INSLastUserSelectionScore");
+ ins_settings.last_connected_score = connman_setting_get_uint("INSLastConnectedScore");
+ ins_settings.preferred_freq_score = connman_setting_get_uint("INSPreferredFreqScore");
+ ins_settings.internet_score = connman_setting_get_uint("INSInternetScore");
+
+ /*
+ * In ConnMan, signal strength is used after being converted
+ * to positive value(signal strength + 120).
+ * So the value for comparison should also be converted to the same.
+ */
+ ins_settings.signal_level3_5ghz = connman_setting_get_int("INSSignalLevel3_5GHz") + 120;
+ ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_24GHz") + 120;
+
+ DBG("last_user_selection [%s]", ins_settings.last_user_selection ? "true" : "false");
+ DBG("last_user_selection_time [%d]", ins_settings.last_user_selection_time);
+ DBG("last_user_selection_score [%d]", ins_settings.last_user_selection_score);
+
+ DBG("last_connected [%s]", ins_settings.last_connected ? "true" : "false");
+ DBG("last_connected_score [%d]", ins_settings.last_connected_score);
+
+ DBG("preferred_freq [%s]", ins_settings.preferred_freq ? "true" : "false");
+ DBG("preferred_freq_score [%d]", ins_settings.preferred_freq_score);
+
+ DBG("security_priority_count [%d]", ins_settings.security_priority_count);
+ for (i = 0; i < CONNMAN_SERVICE_SECURITY_MAX; i++) {
+ if (ins_settings.security_priority[i])
+ DBG("security_priority %s [%d]", security2string(i),
+ ins_settings.security_priority[i]);
+ }
+ DBG("security_priority_score [%d]", ins_settings.security_priority_score);
+
+ DBG("signal [%s]", ins_settings.signal ? "true" : "false");
+
+ DBG("internet [%s]", ins_settings.internet ? "true" : "false");
+ DBG("internet_score [%d]", ins_settings.internet_score);
+
+ DBG("signal_level3_5ghz [%d]", ins_settings.signal_level3_5ghz);
+ DBG("signal_level3_24ghz [%d]", ins_settings.signal_level3_24ghz);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
int __connman_service_init(void)
{
int err;