Fix NULL dereferencing
[platform/core/connectivity/net-config.git] / src / wifi-state.c
index 237e2e0..1472718 100755 (executable)
 #include "log.h"
 #include "util.h"
 #include "netdbus.h"
+#include "setting.h"
 #include "wifi-state.h"
 #include "wifi-power.h"
+#include "wifi-scan.h"
 #include "netsupplicant.h"
 #include "network-state.h"
 #include "wifi-indicator.h"
 #include "network-statistics.h"
 #include "wifi-background-scan.h"
 
+#define NETCONFIG_UPDATE_DEVICE_LIST_COUNT             3
+#define NETCONFIG_UPDATE_DEVICE_LIST_TIMEOUT   1 * 1000
 #define NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT 15 * 1000
 
 static gboolean new_bss_found = FALSE;
-static guint network_noti_timer_id = 0;
 
-static wifi_service_state_e g_service_state = NETCONFIG_WIFI_UNKNOWN;
-static wifi_tech_state_e g_tech_state = NETCONFIG_WIFI_TECH_UNKNOWN;
+static guint network_update_timer_cnt = 0;
+static guint network_update_timer_id = 0;
+static guint network_noti_timer_id = 0;
 
-static GSList *notifier_list = NULL;
+static GSList *g_device_list = NULL;
+static GSList *g_notifier_list = NULL;
 
 static guint network_connected_popup_timer_id = 0;
 static gboolean block_network_connected_popup = FALSE;
 
+static void __device_free_data(gpointer data)
+{
+       wifi_device_data_s *device_data = data;
+
+       g_free(device_data->interface_name);
+       g_free(device_data->mac_address);
+       g_free(device_data);
+
+}
+
+static wifi_device_data_s *__device_get_data(const char *interface_name)
+{
+       GSList *list = NULL;
+
+       for (list = g_device_list; list; list = list->next) {
+               wifi_device_data_s *device_data = list->data;
+               if (g_strcmp0(device_data->interface_name, interface_name) == 0)
+                       return device_data;
+       }
+
+       return NULL;
+}
+
+static wifi_device_data_s *__device_get_data_by_macaddr(const char *macaddr)
+{
+       GSList *list = NULL;
+
+       for (list = g_device_list; list; list = list->next) {
+               wifi_device_data_s *device_data = list->data;
+               if (g_ascii_strncasecmp(device_data->mac_address,
+                               macaddr, MAC_ADDRESS_MAX_LEN) == 0)
+                       return device_data;
+       }
+
+       return NULL;
+}
+
 char *_convert_wifi_service_state_to_string(wifi_service_state_e wifi_service_state_type)
 {
        switch (wifi_service_state_type) {
@@ -80,8 +122,6 @@ char *_convert_wifi_technology_state_to_string(wifi_tech_state_e wifi_tech_state
                return "powered";
        case NETCONFIG_WIFI_TECH_CONNECTED:
                return "connected";
-       case NETCONFIG_WIFI_TECH_TETHERED:
-               return "tethered";
        default:
                ERR("Invalid wifi_tech_state_e parameter");
                break;
@@ -101,8 +141,9 @@ static void __set_wifi_connected_essid(void)
 {
        const char *essid_name = NULL;
        const char *wifi_profile = netconfig_get_default_profile();
+       const char *wifi_ifname = netconfig_get_default_ifname();
 
-       if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED)
+       if (wifi_state_get_service_state(wifi_ifname) != NETCONFIG_WIFI_CONNECTED)
                return;
 
        if (wifi_profile == NULL ||
@@ -117,7 +158,7 @@ static void __set_wifi_connected_essid(void)
                return;
        }
 
-       netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, essid_name);
+       netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, essid_name, TRUE);
 
        /* Block Network Connected popup for 3sec
         * to avoid multiple popup's due to ready signals */
@@ -131,19 +172,18 @@ static void __set_wifi_connected_essid(void)
 
 static void __unset_wifi_connected_essid(void)
 {
-       netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, "");
+       netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, "", TRUE);
 }
 
 static const char *__get_wifi_connected_essid(void)
 {
        const char *essid_name = NULL;
-       const char *wifi_profile = NULL;
+       const char *wifi_profile = netconfig_get_default_profile();
+       const char *wifi_ifname = netconfig_get_default_ifname();
 
-       if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED)
+       if (wifi_state_get_service_state(wifi_ifname) != NETCONFIG_WIFI_CONNECTED)
                return NULL;
 
-       wifi_profile = netconfig_get_default_profile();
-
        if (wifi_profile == NULL || netconfig_is_wifi_profile(wifi_profile) != TRUE) {
                ERR("Can't get Wi-Fi profile");
                return NULL;
@@ -217,15 +257,25 @@ static void _wifi_state_connected_activation(void)
        /* Add activation of services when Wi-Fi is connected */
 }
 
-static void _wifi_state_changed(wifi_service_state_e state)
+static void _wifi_state_changed(const char *interface_name,
+               wifi_service_state_e state)
 {
        GSList *list;
+       const char *ifname;
 
-       for (list = notifier_list; list; list = list->next) {
-               wifi_state_notifier *notifier = list->data;
+       for (list = g_notifier_list; list; ) {
+               wifi_state_notifier_s *notifier = list->data;
+               list = list->next;
+
+               if (notifier->service) {
+                       ifname = netconfig_get_ifname(notifier->service);
+                       if (g_strcmp0(ifname, interface_name) != 0)
+                               continue;
+               }
 
                if (notifier->wifi_state_changed != NULL)
-                       notifier->wifi_state_changed(state, notifier->user_data);
+                       notifier->wifi_state_changed(notifier->notifier,
+                               notifier->service, state, notifier->user_data);
        }
 }
 
@@ -242,14 +292,15 @@ static gboolean _check_network_notification(gpointer data)
 
        wifi_tech_state_e tech_state;
        wifi_service_state_e service_state;
+       char *interface_name = data;
 
-       tech_state = wifi_state_get_technology_state();
+       tech_state = wifi_state_get_technology_state(interface_name);
        if (tech_state < NETCONFIG_WIFI_TECH_POWERED) {
                DBG("Wi-Fi off or WPS only supported[%d]", tech_state);
                goto cleanup;
        }
 
-       service_state = wifi_state_get_service_state();
+       service_state = wifi_state_get_service_state(interface_name);
        if (service_state == NETCONFIG_WIFI_CONNECTED) {
                DBG("Service state is connected");
                goto cleanup;
@@ -405,24 +456,49 @@ static void _set_power_lock(gboolean power_lock)
        return;
 }
 
-void wifi_state_emit_power_completed(gboolean power_on)
+void wifi_state_emit_power_completed(const char *interface_name, gboolean power_on)
 {
        if (power_on)
-               wifi_emit_power_on_completed((Wifi *)get_wifi_object());
+               wifi_emit_power_on_completed((Wifi *)get_wifi_object(), interface_name);
        else
-               wifi_emit_power_off_completed((Wifi *)get_wifi_object());
+               wifi_emit_power_off_completed((Wifi *)get_wifi_object(), interface_name);
+
+       DBG("Successfully sent signal [%s %s]",
+               interface_name, (power_on) ? "powerOn" : "powerOff");
+}
+
+void wifi_state_emit_power_failed(const char *interface_name)
+{
+       wifi_emit_power_operation_failed((Wifi *)get_wifi_object(), interface_name);
 
-       DBG("Successfully sent signal [%s]", (power_on) ? "powerOn" : "powerOff");
+       DBG("Successfully sent signal [%s PowerOperationFailed]", interface_name);
 }
 
-void wifi_state_emit_power_failed(void)
+static void __update_wifi_state(void)
 {
-       wifi_emit_power_operation_failed((Wifi *)get_wifi_object());
+       int wifi_state = VCONFKEY_WIFI_OFF;
+       int network_wifi_state = VCONFKEY_NETWORK_WIFI_OFF;
+       GSList *list = NULL;
+
+       for (list = g_device_list; list; list = list->next) {
+               wifi_device_data_s *device_data = list->data;
+               if (device_data->powered) {
+                       if (wifi_state < VCONFKEY_WIFI_UNCONNECTED)
+                               wifi_state = VCONFKEY_WIFI_UNCONNECTED;
+                       if (network_wifi_state < VCONFKEY_NETWORK_WIFI_NOT_CONNECTED)
+                               network_wifi_state = VCONFKEY_NETWORK_WIFI_NOT_CONNECTED;
+               }
+               if (device_data->connected) {
+                       wifi_state = VCONFKEY_WIFI_CONNECTED;
+                       network_wifi_state = VCONFKEY_NETWORK_WIFI_CONNECTED;
+               }
+       }
 
-       DBG("Successfully sent signal [PowerOperationFailed]");
+       netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, wifi_state, TRUE);
+       netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, network_wifi_state, TRUE);
 }
 
-void wifi_state_update_power_state(gboolean powered)
+void wifi_state_update_power_state(const char *interface_name, gboolean powered)
 {
        wifi_tech_state_e tech_state;
 
@@ -430,50 +506,61 @@ void wifi_state_update_power_state(gboolean powered)
         * DO NOT update manually
         * It includes Wi-Fi state configuration
         */
-       tech_state = wifi_state_get_technology_state();
+       tech_state = wifi_state_get_technology_state(interface_name);
+       if (tech_state == NETCONFIG_WIFI_TECH_UNKNOWN)
+               wifi_state_update_device_list();
 
        if (powered == TRUE) {
                if (tech_state < NETCONFIG_WIFI_TECH_POWERED && netconfig_is_wifi_tethering_on() != TRUE) {
                        DBG("Wi-Fi turned on or waken up from power-save mode");
+                       gchar *mac_addr = vconf_get_str(VCONFKEY_WIFI_BSSID_ADDRESS);
+
+                       if (mac_addr != NULL) {
+                               if (strlen(mac_addr) == 0)
+                                       netconfig_set_mac_address_from_file();
+                               g_free(mac_addr);
+                       }
 
-                       wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_POWERED);
+                       wifi_state_set_powered(interface_name, TRUE);
+                       wifi_state_set_technology_state(interface_name, NETCONFIG_WIFI_TECH_POWERED);
 
-                       wifi_state_emit_power_completed(TRUE);
+                       wifi_state_emit_power_completed(interface_name, TRUE);
+                       netconfig_battery_start_wifi();
 
                        netconfig_wifi_device_picker_service_start();
 
-                       netconfig_set_vconf_int(VCONF_WIFI_LAST_POWER_STATE, VCONFKEY_WIFI_UNCONNECTED);
-                       netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_UNCONNECTED);
-                       netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, VCONFKEY_NETWORK_WIFI_NOT_CONNECTED);
+                       __update_wifi_state();
 
                        netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_ON);
 
-                       netconfig_wifi_bgscan_stop();
-                       netconfig_wifi_bgscan_set_interval(SCAN_EXPONENTIAL_MIN);
-                       netconfig_wifi_bgscan_start(TRUE);
+                       netconfig_wifi_bgscan_stop(interface_name);
+                       netconfig_wifi_bgscan_set_exp_interval(interface_name, SCAN_EXPONENTIAL_MIN);
+                       netconfig_wifi_bgscan_start(interface_name, TRUE);
 
                        /* Add callback to track change in notification setting */
                        _register_network_notification();
+
+                       netconfig_setting_update_interface_for_last_powered(interface_name, TRUE);
                }
        } else if (tech_state > NETCONFIG_WIFI_TECH_OFF) {
                DBG("Wi-Fi turned off or in power-save mode");
 
-               wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_WPS_ONLY);
+               wifi_state_set_powered(interface_name, FALSE);
+               wifi_state_set_technology_state(interface_name, NETCONFIG_WIFI_TECH_WPS_ONLY);
 
                netconfig_wifi_device_picker_service_stop();
 
-               wifi_power_disable_technology_state_by_only_connman_signal();
-               wifi_power_driver_and_supplicant(FALSE);
+               wifi_power_driver_and_supplicant(interface_name, FALSE);
 
-               wifi_state_emit_power_completed(FALSE);
+               wifi_state_emit_power_completed(interface_name, FALSE);
+               netconfig_battery_end_wifi();
 
-               netconfig_set_vconf_int(VCONF_WIFI_LAST_POWER_STATE, VCONFKEY_WIFI_OFF);
-               netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_OFF);
-               netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, VCONFKEY_NETWORK_WIFI_OFF);
+               __update_wifi_state();
 
                netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_OFF);
 
-               netconfig_wifi_bgscan_stop();
+               netconfig_wifi_bgscan_stop(interface_name);
+               netconfig_wifi_scan_set_scanning(interface_name, FALSE);
 
                _set_bss_found(FALSE);
 
@@ -483,6 +570,8 @@ void wifi_state_update_power_state(gboolean powered)
                netconfig_send_notification_to_net_popup(NETCONFIG_DEL_IP_CONFLICT_NOTI, NULL);
 
                _deregister_network_notification();
+
+               netconfig_setting_update_interface_for_last_powered(interface_name, FALSE);
        }
 }
 
@@ -491,32 +580,33 @@ char *wifi_get_favorite_service(void)
        return _get_connman_favorite_service();
 }
 
-void wifi_start_timer_network_notification(void)
+void wifi_start_timer_network_notification(const char *interface_name)
 {
 #if defined TIZEN_WEARABLE
                /* In case of wearable device, no need to notify available Wi-Fi APs */
-               return ;
+               return;
 #endif
-       netconfig_start_timer(NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT, _check_network_notification, NULL, &network_noti_timer_id);
+       netconfig_start_timer(NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT,
+               _check_network_notification, g_strdup(interface_name), &network_noti_timer_id);
 }
 
-void wifi_state_notifier_register(wifi_state_notifier *notifier)
+void wifi_state_notifier_register(wifi_state_notifier_s *notifier)
 {
        DBG("register notifier");
 
-       notifier_list = g_slist_append(notifier_list, notifier);
+       g_notifier_list = g_slist_append(g_notifier_list, notifier);
 }
 
-void wifi_state_notifier_unregister(wifi_state_notifier *notifier)
+void wifi_state_notifier_unregister(wifi_state_notifier_s *notifier)
 {
        DBG("un-register notifier");
 
-       notifier_list = g_slist_remove_all(notifier_list, notifier);
+       g_notifier_list = g_slist_remove_all(g_notifier_list, notifier);
 }
 
 void wifi_state_notifier_cleanup(void)
 {
-       g_slist_free_full(notifier_list, NULL);
+       g_slist_free_full(g_notifier_list, NULL);
 }
 
 void wifi_state_set_bss_found(gboolean found)
@@ -529,176 +619,325 @@ gboolean wifi_state_is_bss_found(void)
        return new_bss_found;
 }
 
-void wifi_state_set_service_state(wifi_service_state_e new_state)
+void __copy_device_statistics(wifi_device_data_s *dst_data, GSList *device_list)
+{
+       GSList *list;
+
+       for (list = device_list; list; list = list->next) {
+               wifi_device_data_s *org_data = list->data;
+               if (g_strcmp0(org_data->interface_name, dst_data->interface_name) == 0) {
+                       dst_data->tx = org_data->tx;
+                       dst_data->rx = org_data->rx;
+                       dst_data->tx_diff = org_data->tx_diff;
+                       dst_data->tx_diff = org_data->tx_diff;
+                       return;
+               }
+       }
+}
+
+gboolean wifi_state_update_device_list(void)
+{
+       GVariant *message = NULL, *variant;
+       GVariantIter *iter, *next;
+       GSList *device_list = NULL;
+       const char *path;
+       gchar *key;
+       gboolean updated = FALSE;
+
+       message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
+                       CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
+                       "GetTechnologies", NULL);
+       if (message == NULL) {
+               ERR("Failed to get technologies");
+               return updated;
+       }
+
+       DBG("Wi-Fi g_device_list: %p", g_device_list);
+
+       device_list = g_device_list;
+       g_device_list = NULL;
+
+       g_variant_get(message, "(a(oa{sv}))", &iter);
+       while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
+               if (path == NULL || g_strcmp0(path, CONNMAN_WIFI_TECHNOLOGY_PREFIX) != 0)
+                       continue;
+
+               while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
+                       if (g_strcmp0(key, "Device.List") == 0) {
+                               GVariantIter *list_iter;
+                               gchar *dev_key;
+                               GVariant *dev_var;
+                               const gchar *sdata;
+                               wifi_device_data_s *device_data = NULL;
+
+                               g_variant_get(variant, "a{sv}", &list_iter);
+                               while(g_variant_iter_loop(list_iter, "{sv}", &dev_key, &dev_var)) {
+                                       if (g_variant_is_of_type(dev_var, G_VARIANT_TYPE_STRING)) {
+                                               if (g_strcmp0(dev_key, "Ifname") == 0) {
+                                                       device_data = g_try_malloc0(sizeof(wifi_device_data_s));
+                                                       if (!device_data) {
+                                                               g_variant_unref(dev_var);
+                                                               break;
+                                                       }
+
+                                                       sdata = g_variant_get_string(dev_var, NULL);
+                                                       device_data->interface_name = g_strdup(sdata);
+                                                       g_device_list = g_slist_append(g_device_list, device_data);
+
+                                                       updated = TRUE;
+
+                                                       __copy_device_statistics(device_data, device_list);
+
+                                               } else if (g_strcmp0(dev_key, "MAC.Address") == 0) {
+                                                       if (device_data) {
+                                                               sdata = g_variant_get_string(dev_var, NULL);
+                                                               device_data->mac_address = g_strdup(sdata);
+
+                                                               DBG("Ifname[%s] MAC[%s] Powered[%d] Connected[%d]",
+                                                                       device_data->interface_name, device_data->mac_address,
+                                                                       device_data->powered, device_data->connected);
+                                                       }
+                                               }
+                                       } else if (g_variant_is_of_type(dev_var, G_VARIANT_TYPE_BOOLEAN)) {
+                                               if (g_strcmp0(dev_key, "Powered") == 0) {
+                                                       if (device_data) {
+                                                               device_data->powered = g_variant_get_boolean(dev_var);
+
+                                                               if (device_data->tech_state == NETCONFIG_WIFI_TECH_UNKNOWN)
+                                                                       device_data->tech_state = NETCONFIG_WIFI_TECH_OFF;
+
+                                                               if (device_data->interface_name)
+                                                                       wifi_state_update_power_state(
+                                                                                       device_data->interface_name, device_data->powered);
+
+                                                               if (device_data->powered == TRUE)
+                                                                       device_data->tech_state = NETCONFIG_WIFI_TECH_POWERED;
+                                                               else
+                                                                       device_data->tech_state = NETCONFIG_WIFI_TECH_OFF;
+                                                       }
+                                               } else if (g_strcmp0(dev_key, "Connected") == 0) {
+                                                       if (device_data) {
+                                                               device_data->connected = g_variant_get_boolean(dev_var);
+                                                               if (device_data->connected == TRUE)
+                                                                       device_data->tech_state = NETCONFIG_WIFI_TECH_CONNECTED;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               g_variant_iter_free(list_iter);
+                       }
+               }
+       }
+
+       g_variant_unref(message);
+
+       g_variant_iter_free(iter);
+
+       g_slist_free_full(device_list, __device_free_data);
+
+       if (network_update_timer_id && updated)
+               netconfig_stop_timer(&network_update_timer_id);
+
+       return updated;
+}
+
+GSList *wifi_state_get_device_list(void)
+{
+       return g_device_list;
+}
+
+static gboolean __state_update_device_list(gpointer data)
+{
+       if (wifi_state_update_device_list() == FALSE) {
+               if (network_update_timer_cnt <
+                       NETCONFIG_UPDATE_DEVICE_LIST_COUNT) {
+                       network_update_timer_cnt++;
+                       return TRUE;
+               }
+       }
+
+       netconfig_stop_timer(&network_update_timer_id);
+       return FALSE;
+}
+
+void wifi_state_set_service_state(const char *interface_name,
+               const char *service, wifi_service_state_e new_state)
 {
        static gboolean dhcp_stage = FALSE;
-       wifi_service_state_e old_state = g_service_state;
+       wifi_device_data_s *device_data = NULL;
+       wifi_service_state_e old_state = NETCONFIG_WIFI_UNKNOWN;
+
+       device_data = __device_get_data(interface_name);
+       if (!device_data)
+               return;
 
+       old_state = device_data->service_state;
        if (old_state == new_state)
                return;
 
-       g_service_state = new_state;
+       device_data->service_state = new_state;
        DBG("Wi-Fi service state, old state[%s] ==> new state[%s]",
                _convert_wifi_service_state_to_string(old_state), _convert_wifi_service_state_to_string(new_state));
 
        /* From association, temporarily disable Wi-Fi power saving */
        if ((old_state < NETCONFIG_WIFI_ASSOCIATION || old_state == NETCONFIG_WIFI_FAILURE) && new_state == NETCONFIG_WIFI_ASSOCIATION) {
                _set_power_lock(TRUE);
-               wifi_set_early_suspend(FALSE);
+               wifi_set_early_suspend(interface_name, FALSE);
                dhcp_stage = TRUE;
        } else if (dhcp_stage == TRUE && new_state != NETCONFIG_WIFI_CONFIGURATION) {
                _set_power_lock(FALSE);
-               wifi_set_early_suspend(TRUE);
+               wifi_set_early_suspend(interface_name, TRUE);
                dhcp_stage = FALSE;
        }
 
        if (new_state == NETCONFIG_WIFI_CONNECTED) {
                netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
 
-               netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_CONNECTED);
-               netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, VCONFKEY_NETWORK_WIFI_CONNECTED);
+               __update_wifi_state();
 
                netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_CONNECTED);
 
                __set_wifi_connected_essid();
 
-               netconfig_wifi_indicator_start();
+               netconfig_wifi_indicator_start(interface_name, service);
        } else if (old_state == NETCONFIG_WIFI_CONNECTED) {
                netconfig_send_notification_to_net_popup(NETCONFIG_DEL_PORTAL_NOTI, NULL);
 
                __unset_wifi_connected_essid();
 
-               netconfig_set_vconf_int (VCONFKEY_WIFI_STATE, VCONFKEY_WIFI_UNCONNECTED);
-               netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, VCONFKEY_NETWORK_WIFI_NOT_CONNECTED);
+               __update_wifi_state();
 
                netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_ON);
 
-               netconfig_wifi_indicator_stop();
+               netconfig_wifi_indicator_stop(interface_name);
 
-               netconfig_wifi_bgscan_stop();
-               netconfig_wifi_bgscan_set_interval(SCAN_EXPONENTIAL_MIN);
-               netconfig_wifi_bgscan_start(TRUE);
+               netconfig_wifi_bgscan_stop(interface_name);
+               netconfig_wifi_bgscan_set_exp_interval(interface_name, SCAN_EXPONENTIAL_MIN);
+               netconfig_wifi_bgscan_start(interface_name, TRUE);
        } else if ((old_state > NETCONFIG_WIFI_IDLE && old_state < NETCONFIG_WIFI_CONNECTED) && new_state == NETCONFIG_WIFI_IDLE) {
                /* in ipv6 case disconnect/association -> association */
                DBG("reset the bg scan period");
 
-               netconfig_wifi_bgscan_stop();
-               netconfig_wifi_bgscan_start(TRUE);
+               netconfig_wifi_bgscan_stop(interface_name);
+               netconfig_wifi_bgscan_start(interface_name, TRUE);
+       } else if (old_state == NETCONFIG_WIFI_FAILURE && new_state == NETCONFIG_WIFI_IDLE) {
+               DBG("reset the bg scan period, in failure case");
+               netconfig_wifi_bgscan_stop(interface_name);
+               netconfig_wifi_bgscan_set_exp_interval(interface_name, SCAN_EXPONENTIAL_MIN);
+               netconfig_wifi_bgscan_start(interface_name, FALSE);
        }
 
-       _wifi_state_changed(new_state);
+       _wifi_state_changed(interface_name, new_state);
 
        if (new_state == NETCONFIG_WIFI_CONNECTED)
                _wifi_state_connected_activation();
 }
 
-wifi_service_state_e wifi_state_get_service_state(void)
+wifi_service_state_e wifi_state_get_service_state(const char *interface_name)
 {
-       return g_service_state;
+       wifi_device_data_s *device_data = __device_get_data(interface_name);
+       if (!device_data)
+               return NETCONFIG_WIFI_UNKNOWN;
+
+       return device_data->service_state;
 }
 
-void wifi_state_set_tech_state(wifi_tech_state_e new_state)
+void wifi_state_set_technology_state(const char *interface_name, wifi_tech_state_e new_state)
 {
-       wifi_tech_state_e old_state = g_tech_state;
+       wifi_device_data_s *device_data = NULL;
 
-       if (old_state == new_state)
-               return;
+       device_data = __device_get_data(interface_name);
+       if (device_data) {
+               if (device_data->tech_state == new_state)
+                       return;
 
-       g_tech_state = new_state;
+               DBG("Wi-Fi %s technology state, old state[%s] ==> new state[%s]", interface_name,
+                       _convert_wifi_technology_state_to_string(device_data->tech_state),
+                       _convert_wifi_technology_state_to_string(new_state));
 
-       DBG("Wi-Fi technology state, old state[%s] ==> new state[%s]",
-               _convert_wifi_technology_state_to_string(old_state), _convert_wifi_technology_state_to_string(new_state));
+               device_data->tech_state = new_state;
+       }
 }
 
-wifi_tech_state_e wifi_state_get_technology_state(void)
+wifi_tech_state_e wifi_state_get_technology_state(const char *interface_name)
 {
-       GVariant *message = NULL, *variant;
-       GVariantIter *iter, *next;
-       wifi_tech_state_e ret = NETCONFIG_WIFI_TECH_OFF;
-       gboolean wifi_tech_powered = FALSE;
-       gboolean wifi_tech_connected = FALSE;
-       const char *path;
-       gchar *key;
+       wifi_device_data_s *device_data = NULL;
 
-       if (g_tech_state > NETCONFIG_WIFI_TECH_UNKNOWN)
-               return g_tech_state;
+       device_data = __device_get_data(interface_name);
+       if (device_data) {
+               DBG("Wi-Fi %s technology state [%s]", interface_name,
+                       _convert_wifi_technology_state_to_string(device_data->tech_state));
 
-       message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
-                       CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
-                       "GetTechnologies", NULL);
-       if (message == NULL) {
-               ERR("Failed to get_technology_state");
-               return NETCONFIG_WIFI_TECH_UNKNOWN;
+               return device_data->tech_state;
        }
 
-       g_variant_get(message, "(a(oa{sv}))", &iter);
-       while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
-               if (path == NULL || g_strcmp0(path, CONNMAN_WIFI_TECHNOLOGY_PREFIX) != 0)
-                       continue;
+       return NETCONFIG_WIFI_TECH_UNKNOWN;
+}
 
-               while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
-                       const gchar *sdata = NULL;
-                       gboolean data;
-
-                       if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) {
-                               data = g_variant_get_boolean(variant);
-                               DBG("key-[%s] - %s", key, data ? "True" : "False");
-
-                               if (strcmp(key, "Powered") == 0 && data)
-                                       wifi_tech_powered = TRUE;
-                               else if (strcmp(key, "Connected") == 0 && data)
-                                       wifi_tech_connected = TRUE;
-                               /* For further use
-                               else if (strcmp(key, "Tethering") == 0 && data) {
-                               } */
-                       } else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
-                               sdata = g_variant_get_string(variant, NULL);
-                               DBG("%s", sdata);
-                       }
-               }
+void wifi_state_set_powered(const char *interface_name, gboolean powered)
+{
+       wifi_device_data_s *device_data = __device_get_data(interface_name);
+
+       if (device_data) {
+               device_data->powered = powered;
+               DBG("Wi-Fi %s [%s]", interface_name, powered ? "enabled" : "disabled");
        }
+}
 
-       g_variant_unref(message);
+gboolean wifi_state_get_powered(const char *interface_name)
+{
+       wifi_device_data_s *device_data = __device_get_data(interface_name);
+       if (!device_data)
+               return FALSE;
 
-       g_variant_iter_free(iter);
+       return device_data->powered;
+}
 
-       if (wifi_tech_powered == TRUE)
-               ret = NETCONFIG_WIFI_TECH_POWERED;
+void wifi_state_set_connected(const char *interface_name, gboolean connected)
+{
+       wifi_device_data_s *device_data = __device_get_data(interface_name);
 
-       if (wifi_tech_connected == TRUE)
-               ret = NETCONFIG_WIFI_TECH_CONNECTED;
+       if (device_data) {
+               device_data->connected = connected;
+               DBG("Wi-Fi %s [%s]", interface_name, connected ? "connected" : "disconnected");
+       }
+}
 
-       g_tech_state = ret;
+gboolean wifi_state_get_connected(const char *interface_name)
+{
+       wifi_device_data_s *device_data = __device_get_data(interface_name);
+       if (!device_data)
+               return FALSE;
 
-       return g_tech_state;
+       return device_data->connected;
 }
 
-gboolean wifi_state_is_technology_available(void)
+gboolean wifi_state_is_existed(const char *interface_name)
 {
-       GVariant *message = NULL;
-       GVariantIter *iter, *next;
-       const char *path;
-       gboolean ret = FALSE;
-
-       message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
-                       CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
-                       "GetTechnologies", NULL);
-       if (message == NULL) {
-               ERR("Failed to get_technology_state");
+       wifi_device_data_s *device_data = __device_get_data(interface_name);
+       if (!device_data)
                return FALSE;
-       }
 
-       g_variant_get(message, "(a(oa{sv}))", &iter);
-       while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
-               if (path != NULL && g_strcmp0(path, CONNMAN_WIFI_TECHNOLOGY_PREFIX) == 0)
-                       ret = TRUE;
-       }
+       return TRUE;
+}
 
-       g_variant_unref(message);
-       g_variant_iter_free(iter);
+const char *wifi_state_get_interface_name(const char *mac_address)
+{
+       wifi_device_data_s *device_data = __device_get_data_by_macaddr(mac_address);
+       if (!device_data)
+               return NULL;
+
+       return device_data->interface_name;
+}
 
-       DBG("Wi-Fi technology is %s", ret ? "available" : "unavailable");
-       return ret;
+const char *wifi_state_get_mac_address(const char *interface_name)
+{
+       wifi_device_data_s *device_data = __device_get_data(interface_name);
+       if (!device_data)
+               return NULL;
+
+       return device_data->mac_address;
 }
 
 void wifi_state_set_connected_essid(void)
@@ -711,58 +950,14 @@ void wifi_state_get_connected_essid(gchar **essid)
        *essid = g_strdup(__get_wifi_connected_essid());
 }
 
-/*     wifi_connection_state_e in CAPI
- *
- *     WIFI_CONNECTION_STATE_FAILURE           = -1
- *     WIFI_CONNECTION_STATE_DISCONNECTED      = 0
- *     WIFI_CONNECTION_STATE_ASSOCIATION       = 1
- *     WIFI_CONNECTION_STATE_CONFIGURATION     = 2
- *     WIFI_CONNECTION_STATE_CONNECTED         = 3
- */
-/*     connection_wifi_state_e in CAPI
- *
- *     CONNECTION_WIFI_STATE_DEACTIVATED       = 0
- *     CONNECTION_WIFI_STATE_DISCONNECTED      = 1
- *     CONNECTION_WIFI_STATE_CONNECTED         = 2
- */
-gboolean handle_get_wifi_state(Wifi *wifi, GDBusMethodInvocation *context)
+void wifi_state_initialize(void)
 {
-       g_return_val_if_fail(wifi != NULL, TRUE);
-       GVariant *param = NULL;
-       wifi_tech_state_e tech_state = NETCONFIG_WIFI_TECH_UNKNOWN;
-       wifi_service_state_e service_state = NETCONFIG_WIFI_UNKNOWN;
-       tech_state = wifi_state_get_technology_state();
-       service_state = wifi_state_get_service_state();
-
-       if (tech_state == NETCONFIG_WIFI_TECH_UNKNOWN)
-               param = g_variant_new("(s)", "unknown");
-       else if (tech_state == NETCONFIG_WIFI_TECH_OFF ||
-               tech_state == NETCONFIG_WIFI_TECH_WPS_ONLY)
-               param = g_variant_new("(s)", "deactivated");
-       else if (tech_state == NETCONFIG_WIFI_TECH_CONNECTED)
-               param = g_variant_new("(s)", "connected");
-       else {
-               switch (service_state) {
-               case NETCONFIG_WIFI_FAILURE:
-                       param = g_variant_new("(s)", "failure");
-                       break;
-               case NETCONFIG_WIFI_ASSOCIATION:
-                       param = g_variant_new("(s)", "association");
-                       break;
-               case NETCONFIG_WIFI_CONFIGURATION:
-                       param = g_variant_new("(s)", "configuration");
-                       break;
-               case NETCONFIG_WIFI_CONNECTED:
-                       param = g_variant_new("(s)", "connected");
-                       break;
-               case NETCONFIG_WIFI_UNKNOWN:
-               case NETCONFIG_WIFI_IDLE:
-               default:
-                       param = g_variant_new("(s)", "disconnected");
-               }
-       }
-
-       g_dbus_method_invocation_return_value(context, param);
+       if (wifi_state_update_device_list() == FALSE)
+               netconfig_start_timer(NETCONFIG_UPDATE_DEVICE_LIST_TIMEOUT,
+                       __state_update_device_list, NULL, &network_update_timer_id);
+}
 
-       return TRUE;
+void wifi_state_deinitialize(void)
+{
+       g_slist_free_full(g_device_list, __device_free_data);
 }