Merge "Add a number of iteration for updating device list" into tizen
[platform/core/connectivity/net-config.git] / src / wifi-state.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <vconf.h>
21 #include <vconf-keys.h>
22
23 #include "log.h"
24 #include "util.h"
25 #include "netdbus.h"
26 #include "setting.h"
27 #include "wifi-state.h"
28 #include "wifi-power.h"
29 #include "wifi-scan.h"
30 #include "netsupplicant.h"
31 #include "network-state.h"
32 #include "wifi-indicator.h"
33 #include "network-statistics.h"
34 #include "wifi-background-scan.h"
35
36 #define NETCONFIG_UPDATE_DEVICE_LIST_COUNT              3
37 #define NETCONFIG_UPDATE_DEVICE_LIST_TIMEOUT    1 * 1000
38 #define NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT  15 * 1000
39
40 static gboolean new_bss_found = FALSE;
41
42 static guint network_update_timer_cnt = 0;
43 static guint network_update_timer_id = 0;
44 static guint network_noti_timer_id = 0;
45
46 static GSList *g_device_list = NULL;
47 static GSList *g_notifier_list = NULL;
48
49 static guint network_connected_popup_timer_id = 0;
50 static gboolean block_network_connected_popup = FALSE;
51
52 static void __device_free_data(gpointer data)
53 {
54         wifi_device_data_s *device_data = data;
55
56         g_free(device_data->interface_name);
57         g_free(device_data->mac_address);
58         g_free(device_data);
59
60 }
61
62 static wifi_device_data_s *__device_get_data(const char *interface_name)
63 {
64         GSList *list = NULL;
65
66         for (list = g_device_list; list; list = list->next) {
67                 wifi_device_data_s *device_data = list->data;
68                 if (g_strcmp0(device_data->interface_name, interface_name) == 0)
69                         return device_data;
70         }
71
72         return NULL;
73 }
74
75 static wifi_device_data_s *__device_get_data_by_macaddr(const char *macaddr)
76 {
77         GSList *list = NULL;
78
79         for (list = g_device_list; list; list = list->next) {
80                 wifi_device_data_s *device_data = list->data;
81                 if (g_ascii_strncasecmp(device_data->mac_address,
82                                 macaddr, MAC_ADDRESS_MAX_LEN) == 0)
83                         return device_data;
84         }
85
86         return NULL;
87 }
88
89 char *_convert_wifi_service_state_to_string(wifi_service_state_e wifi_service_state_type)
90 {
91         switch (wifi_service_state_type) {
92         case NETCONFIG_WIFI_UNKNOWN:
93                 return "unknown";
94         case NETCONFIG_WIFI_IDLE:
95                 return "idle";
96         case NETCONFIG_WIFI_ASSOCIATION:
97                 return "association";
98         case NETCONFIG_WIFI_CONFIGURATION:
99                 return "configuration";
100         case NETCONFIG_WIFI_CONNECTED:
101                 return "connected";
102         case NETCONFIG_WIFI_FAILURE:
103                 return "failure";
104         default:
105                 ERR("Invalid wifi_service_state_e parameter");
106                 break;
107         }
108
109         return "Invalid parameter";
110 }
111
112 char *_convert_wifi_technology_state_to_string(wifi_tech_state_e wifi_tech_state_type)
113 {
114         switch (wifi_tech_state_type) {
115         case NETCONFIG_WIFI_TECH_UNKNOWN:
116                 return "unknown";
117         case NETCONFIG_WIFI_TECH_OFF:
118                 return "off";
119         case NETCONFIG_WIFI_TECH_WPS_ONLY:
120                 return "wps only";
121         case NETCONFIG_WIFI_TECH_POWERED:
122                 return "powered";
123         case NETCONFIG_WIFI_TECH_CONNECTED:
124                 return "connected";
125         case NETCONFIG_WIFI_TECH_TETHERED:
126                 return "tethered";
127         default:
128                 ERR("Invalid wifi_tech_state_e parameter");
129                 break;
130         }
131
132         return "Invalid parameter";
133 }
134
135 static gboolean _block_network_connection_popup(gpointer data)
136 {
137         block_network_connected_popup = FALSE;
138         netconfig_stop_timer(&network_connected_popup_timer_id);
139         return FALSE;
140 }
141
142 static void __set_wifi_connected_essid(void)
143 {
144         const char *essid_name = NULL;
145         const char *wifi_profile = netconfig_get_default_profile();
146         const char *wifi_ifname = netconfig_get_default_ifname();
147
148         if (wifi_state_get_service_state(wifi_ifname) != NETCONFIG_WIFI_CONNECTED)
149                 return;
150
151         if (wifi_profile == NULL ||
152                         netconfig_is_wifi_profile(wifi_profile) != TRUE) {
153                 ERR("Can't get Wi-Fi profile");
154                 return;
155         }
156
157         essid_name = netconfig_wifi_get_connected_essid(wifi_profile);
158         if (essid_name == NULL) {
159                 ERR("Can't get Wi-Fi name");
160                 return;
161         }
162
163         netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, essid_name, TRUE);
164
165         /* Block Network Connected popup for 3sec
166          * to avoid multiple popup's due to ready signals */
167         if (block_network_connected_popup == FALSE) {
168                 block_network_connected_popup = TRUE;
169                 netconfig_start_timer(3000, _block_network_connection_popup,
170                                 NULL, &network_connected_popup_timer_id);
171                 __netconfig_pop_wifi_connected_poppup(essid_name);
172         }
173 }
174
175 static void __unset_wifi_connected_essid(void)
176 {
177         netconfig_set_vconf_str(VCONFKEY_WIFI_CONNECTED_AP_NAME, "", TRUE);
178 }
179
180 static const char *__get_wifi_connected_essid(void)
181 {
182         const char *essid_name = NULL;
183         const char *wifi_profile = netconfig_get_default_profile();
184         const char *wifi_ifname = netconfig_get_default_ifname();
185
186         if (wifi_state_get_service_state(wifi_ifname) != NETCONFIG_WIFI_CONNECTED)
187                 return NULL;
188
189         if (wifi_profile == NULL || netconfig_is_wifi_profile(wifi_profile) != TRUE) {
190                 ERR("Can't get Wi-Fi profile");
191                 return NULL;
192         }
193
194         essid_name = netconfig_wifi_get_connected_essid(wifi_profile);
195         if (essid_name == NULL) {
196                 ERR("Can't get Wi-Fi name");
197                 return NULL;
198         }
199
200         return essid_name;
201 }
202
203 static gboolean __is_wifi_profile_available(void)
204 {
205         GVariant *message = NULL;
206         GVariantIter *iter, *next;
207         gchar *obj;
208
209         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
210                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
211                         "GetServices", NULL);
212         if (message == NULL) {
213                 ERR("Failed to get service list");
214                 return FALSE;
215         }
216
217         g_variant_get(message, "(a(oa{sv}))", &iter);
218         while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
219                 if (obj == NULL || netconfig_is_wifi_profile((const gchar*)obj) == FALSE)
220                         continue;
221
222                 g_variant_iter_free(next);
223                 g_free(obj);
224                 break;
225         }
226
227         g_variant_unref(message);
228
229         g_variant_iter_free(iter);
230
231         return TRUE;
232 }
233
234 static gboolean __is_favorited(GVariantIter *array)
235 {
236         gboolean is_favorite = FALSE;
237         gchar *key;
238         GVariant *var;
239
240         while (g_variant_iter_loop(array, "{sv}", &key, &var)) {
241                 gboolean value;
242
243                 if (g_str_equal(key, "Favorite") != TRUE)
244                         continue;
245
246                 value = g_variant_get_boolean(var);
247                 if (value)
248                         is_favorite = TRUE;
249                 g_free(key);
250                 g_variant_unref(var);
251                 break;
252         }
253
254         return is_favorite;
255 }
256
257 static void _wifi_state_connected_activation(void)
258 {
259         /* Add activation of services when Wi-Fi is connected */
260 }
261
262 static void _wifi_state_changed(const char *interface_name,
263                 wifi_service_state_e state)
264 {
265         GSList *list;
266         const char *ifname;
267
268         for (list = g_notifier_list; list; ) {
269                 wifi_state_notifier_s *notifier = list->data;
270                 list = list->next;
271
272                 if (notifier->service) {
273                         ifname = netconfig_get_ifname(notifier->service);
274                         if (g_strcmp0(ifname, interface_name) != 0)
275                                 continue;
276                 }
277
278                 if (notifier->wifi_state_changed != NULL)
279                         notifier->wifi_state_changed(notifier->notifier,
280                                 notifier->service, state, notifier->user_data);
281         }
282 }
283
284 static void _set_bss_found(gboolean found)
285 {
286         if (found != new_bss_found)
287                 new_bss_found = found;
288 }
289
290 static gboolean _check_network_notification(gpointer data)
291 {
292         int qs_enable = 0, ug_state = 0;
293         static gboolean check_again = FALSE;
294
295         wifi_tech_state_e tech_state;
296         wifi_service_state_e service_state;
297         char *interface_name = data;
298
299         tech_state = wifi_state_get_technology_state(interface_name);
300         if (tech_state < NETCONFIG_WIFI_TECH_POWERED) {
301                 DBG("Wi-Fi off or WPS only supported[%d]", tech_state);
302                 goto cleanup;
303         }
304
305         service_state = wifi_state_get_service_state(interface_name);
306         if (service_state == NETCONFIG_WIFI_CONNECTED) {
307                 DBG("Service state is connected");
308                 goto cleanup;
309         } else if (service_state == NETCONFIG_WIFI_ASSOCIATION ||
310                 service_state == NETCONFIG_WIFI_CONFIGURATION) {
311                 DBG("Service state is connecting (check again : %d)", check_again);
312                 if (!check_again) {
313                         check_again = TRUE;
314                         return TRUE;
315                 } else
316                         check_again = FALSE;
317         }
318
319         if (__is_wifi_profile_available() == FALSE) {
320                 netconfig_send_notification_to_net_popup(
321                 NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
322                 goto cleanup;
323         }
324
325         netconfig_vconf_get_int(VCONFKEY_WIFI_ENABLE_QS, &qs_enable);
326         if (qs_enable != VCONFKEY_WIFI_QS_ENABLE) {
327                 DBG("qs_enable != VCONFKEY_WIFI_QS_ENABLE");
328                 goto cleanup;
329         }
330
331         netconfig_vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &ug_state);
332         if (ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
333                 goto cleanup;
334
335         netconfig_send_notification_to_net_popup(NETCONFIG_ADD_FOUND_AP_NOTI, NULL);
336
337         _set_bss_found(FALSE);
338
339 cleanup:
340         netconfig_stop_timer(&network_noti_timer_id);
341         return FALSE;
342 }
343
344 static char *_get_connman_favorite_service(void)
345 {
346         char *favorite_service = NULL;
347         GVariant *message = NULL;
348         gchar *obj;
349         GVariantIter *iter, *next;
350
351         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
352                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
353                         "GetServices", NULL);
354         if (message == NULL) {
355                 ERR("Failed to get service list");
356                 return NULL;
357         }
358
359         g_variant_get(message, "(a(oa{sv}))", &iter);
360         while (g_variant_iter_loop(iter, "(oa{sv})", &obj, &next)) {
361                 if (obj == NULL || netconfig_is_wifi_profile(obj) == FALSE)
362                         continue;
363
364                 if (__is_favorited(next) == TRUE) {
365                         favorite_service = g_strdup(obj);
366                         g_free(obj);
367                         g_variant_iter_free(next);
368                         break;
369                 }
370         }
371
372         g_variant_iter_free(iter);
373         g_variant_unref(message);
374
375         return favorite_service;
376 }
377
378 static void __notification_value_changed_cb(keynode_t *node, void *user_data)
379 {
380         int value = -1;
381
382         if (netconfig_vconf_get_int(VCONFKEY_WIFI_ENABLE_QS, &value) < 0)
383                 return;
384
385         if (value == VCONFKEY_WIFI_QS_DISABLE)
386                 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
387 }
388
389 static void _register_network_notification(void)
390 {
391 #if defined TIZEN_WEARABLE
392         return;
393 #endif
394         vconf_notify_key_changed(VCONFKEY_WIFI_ENABLE_QS, __notification_value_changed_cb, NULL);
395 }
396
397 static void _deregister_network_notification(void)
398 {
399 #if defined TIZEN_WEARABLE
400                 return;
401 #endif
402         vconf_ignore_key_changed(VCONFKEY_WIFI_ENABLE_QS, __notification_value_changed_cb);
403 }
404
405 static void _set_power_lock(gboolean power_lock)
406 {
407         gint32 ret = 0;
408         GVariant *reply;
409         GVariant *params;
410         char state[] = "lcdoff";
411         char flag[] = "staycurstate";
412         char standby[] = "NULL";
413         int timeout = 0;
414         char sleepmargin[] = "sleepmargin";
415
416         const char *lockstate = "lockstate";
417         const char *unlockstate = "unlockstate";
418         static gboolean old_state = FALSE;
419         const char *lock_method;
420
421         if (old_state == power_lock)
422                 return;
423
424         if (power_lock == TRUE) {
425                 /* deviced power lock enable */
426                 params = g_variant_new("(sssi)", state, flag, standby, timeout);
427
428                 lock_method = lockstate;
429         } else {
430                 /* deviced power lock disable */
431                 params = g_variant_new("(ss)", state, sleepmargin);
432
433                 lock_method = unlockstate;
434         }
435
436         reply = netconfig_invoke_dbus_method(
437                         "org.tizen.system.deviced",
438                         "/Org/Tizen/System/DeviceD/Display",
439                         "org.tizen.system.deviced.display",
440                         lock_method,
441                         params);
442         if (reply == NULL) {
443                 ERR("Failed to set_power_lock");
444                 return;
445         }
446
447         if (g_variant_is_of_type(reply, G_VARIANT_TYPE_INT32)) {
448                 ret = g_variant_get_int32(reply);
449                 if (ret < 0)
450                         ERR("Failed to set power lock %s with ret %d",
451                                 power_lock == TRUE ? "enable" : "disable", ret);
452                 else
453                         old_state = power_lock;
454         }
455
456         g_variant_unref(reply);
457
458         return;
459 }
460
461 void wifi_state_emit_power_completed(const char *interface_name, gboolean power_on)
462 {
463         if (power_on)
464                 wifi_emit_power_on_completed((Wifi *)get_wifi_object(), interface_name);
465         else
466                 wifi_emit_power_off_completed((Wifi *)get_wifi_object(), interface_name);
467
468         DBG("Successfully sent signal [%s %s]",
469                 interface_name, (power_on) ? "powerOn" : "powerOff");
470 }
471
472 void wifi_state_emit_power_failed(const char *interface_name)
473 {
474         wifi_emit_power_operation_failed((Wifi *)get_wifi_object(), interface_name);
475
476         DBG("Successfully sent signal [%s PowerOperationFailed]", interface_name);
477 }
478
479 static void __update_wifi_state(void)
480 {
481         int wifi_state = VCONFKEY_WIFI_OFF;
482         int network_wifi_state = VCONFKEY_NETWORK_WIFI_OFF;
483         GSList *list = NULL;
484
485         for (list = g_device_list; list; list = list->next) {
486                 wifi_device_data_s *device_data = list->data;
487                 if (device_data->powered) {
488                         if (wifi_state < VCONFKEY_WIFI_UNCONNECTED)
489                                 wifi_state = VCONFKEY_WIFI_UNCONNECTED;
490                         if (network_wifi_state < VCONFKEY_NETWORK_WIFI_NOT_CONNECTED)
491                                 network_wifi_state = VCONFKEY_NETWORK_WIFI_NOT_CONNECTED;
492                 }
493                 if (device_data->connected) {
494                         wifi_state = VCONFKEY_WIFI_CONNECTED;
495                         network_wifi_state = VCONFKEY_NETWORK_WIFI_CONNECTED;
496                 }
497         }
498
499         netconfig_set_vconf_int(VCONFKEY_WIFI_STATE, wifi_state, TRUE);
500         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_STATE, network_wifi_state, TRUE);
501 }
502
503 void wifi_state_update_power_state(const char *interface_name, gboolean powered)
504 {
505         wifi_tech_state_e tech_state;
506
507         /* It's automatically updated by signal-handler
508          * DO NOT update manually
509          * It includes Wi-Fi state configuration
510          */
511         tech_state = wifi_state_get_technology_state(interface_name);
512
513         if (powered == TRUE) {
514                 if (tech_state < NETCONFIG_WIFI_TECH_POWERED && netconfig_is_wifi_tethering_on() != TRUE) {
515                         DBG("Wi-Fi turned on or waken up from power-save mode");
516
517                         wifi_state_set_powered(interface_name, TRUE);
518                         wifi_state_set_technology_state(interface_name, NETCONFIG_WIFI_TECH_POWERED);
519
520                         wifi_state_emit_power_completed(interface_name, TRUE);
521                         netconfig_battery_start_wifi();
522
523                         netconfig_wifi_device_picker_service_start();
524
525                         __update_wifi_state();
526
527                         netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_ON);
528
529                         netconfig_wifi_bgscan_stop(interface_name);
530                         netconfig_wifi_bgscan_set_interval(interface_name, SCAN_EXPONENTIAL_MIN);
531                         netconfig_wifi_bgscan_start(interface_name, TRUE);
532
533                         /* Add callback to track change in notification setting */
534                         _register_network_notification();
535
536                         netconfig_setting_update_interface_for_last_powered(interface_name, TRUE);
537                 }
538         } else if (tech_state > NETCONFIG_WIFI_TECH_OFF) {
539                 DBG("Wi-Fi turned off or in power-save mode");
540
541                 wifi_state_set_powered(interface_name, FALSE);
542                 wifi_state_set_technology_state(interface_name, NETCONFIG_WIFI_TECH_WPS_ONLY);
543
544                 netconfig_wifi_device_picker_service_stop();
545
546                 wifi_power_driver_and_supplicant(interface_name, FALSE);
547
548                 wifi_state_emit_power_completed(interface_name, FALSE);
549                 netconfig_battery_end_wifi();
550
551                 __update_wifi_state();
552
553                 netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_OFF);
554
555                 netconfig_wifi_bgscan_stop(interface_name);
556                 netconfig_wifi_scan_set_scanning(interface_name, FALSE);
557
558                 _set_bss_found(FALSE);
559
560                 /* Inform net-popup to remove the wifi found notification */
561                 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
562                 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_PORTAL_NOTI, NULL);
563                 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_IP_CONFLICT_NOTI, NULL);
564
565                 _deregister_network_notification();
566
567                 netconfig_setting_update_interface_for_last_powered(interface_name, FALSE);
568         }
569 }
570
571 char *wifi_get_favorite_service(void)
572 {
573         return _get_connman_favorite_service();
574 }
575
576 void wifi_start_timer_network_notification(const char *interface_name)
577 {
578 #if defined TIZEN_WEARABLE
579                 /* In case of wearable device, no need to notify available Wi-Fi APs */
580                 return;
581 #endif
582         netconfig_start_timer(NETCONFIG_NETWORK_NOTIFICATION_TIMEOUT,
583                 _check_network_notification, g_strdup(interface_name), &network_noti_timer_id);
584 }
585
586 void wifi_state_notifier_register(wifi_state_notifier_s *notifier)
587 {
588         DBG("register notifier");
589
590         g_notifier_list = g_slist_append(g_notifier_list, notifier);
591 }
592
593 void wifi_state_notifier_unregister(wifi_state_notifier_s *notifier)
594 {
595         DBG("un-register notifier");
596
597         g_notifier_list = g_slist_remove_all(g_notifier_list, notifier);
598 }
599
600 void wifi_state_notifier_cleanup(void)
601 {
602         g_slist_free_full(g_notifier_list, NULL);
603 }
604
605 void wifi_state_set_bss_found(gboolean found)
606 {
607         _set_bss_found(found);
608 }
609
610 gboolean wifi_state_is_bss_found(void)
611 {
612         return new_bss_found;
613 }
614
615 void __copy_device_statistics(wifi_device_data_s *dst_data, GSList *device_list)
616 {
617         GSList *list;
618
619         for (list = device_list; list; list = list->next) {
620                 wifi_device_data_s *org_data = list->data;
621                 if (g_strcmp0(org_data->interface_name, dst_data->interface_name) == 0) {
622                         dst_data->tx = org_data->tx;
623                         dst_data->rx = org_data->rx;
624                         dst_data->tx_diff = org_data->tx_diff;
625                         dst_data->tx_diff = org_data->tx_diff;
626                         return;
627                 }
628         }
629 }
630
631 gboolean wifi_state_update_device_list(void)
632 {
633         GVariant *message = NULL, *variant;
634         GVariantIter *iter, *next;
635         GSList *device_list = NULL;
636         const char *path;
637         gchar *key;
638         gboolean updated = FALSE;
639
640         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
641                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
642                         "GetTechnologies", NULL);
643         if (message == NULL) {
644                 ERR("Failed to get technologies");
645                 return updated;
646         }
647
648         device_list = g_device_list;
649         g_device_list = NULL;
650
651         g_variant_get(message, "(a(oa{sv}))", &iter);
652         while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
653                 if (path == NULL || g_strcmp0(path, CONNMAN_WIFI_TECHNOLOGY_PREFIX) != 0)
654                         continue;
655
656                 while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
657                         if (g_strcmp0(key, "Device.List") == 0) {
658                                 GVariantIter *list_iter;
659                                 gchar *dev_key;
660                                 GVariant *dev_var;
661                                 const gchar *sdata;
662                                 wifi_device_data_s *device_data = NULL;
663
664                                 g_variant_get(variant, "a{sv}", &list_iter);
665                                 while(g_variant_iter_loop(list_iter, "{sv}", &dev_key, &dev_var)) {
666                                         if (g_variant_is_of_type(dev_var, G_VARIANT_TYPE_STRING)) {
667                                                 if (g_strcmp0(dev_key, "Ifname") == 0) {
668                                                         device_data = g_try_malloc0(sizeof(wifi_device_data_s));
669                                                         if (!device_data) {
670                                                                 g_variant_unref(dev_var);
671                                                                 break;
672                                                         }
673
674                                                         sdata = g_variant_get_string(dev_var, NULL);
675                                                         device_data->interface_name = g_strdup(sdata);
676                                                         g_device_list = g_slist_append(g_device_list, device_data);
677
678                                                         updated = TRUE;
679
680                                                         __copy_device_statistics(device_data, device_list);
681
682                                                 } else if (g_strcmp0(dev_key, "MAC.Address") == 0) {
683                                                         if (device_data) {
684                                                                 sdata = g_variant_get_string(dev_var, NULL);
685                                                                 device_data->mac_address = g_strdup(sdata);
686
687                                                                 DBG("Ifname[%s] MAC[%s] Powered[%d] Connected[%d]",
688                                                                         device_data->interface_name, device_data->mac_address,
689                                                                         device_data->powered, device_data->connected);
690                                                         }
691                                                 }
692                                         } else if (g_variant_is_of_type(dev_var, G_VARIANT_TYPE_BOOLEAN)) {
693                                                 if (g_strcmp0(dev_key, "Powered") == 0) {
694                                                         if (device_data) {
695                                                                 device_data->powered = g_variant_get_boolean(dev_var);
696                                                                 if (device_data->powered == TRUE)
697                                                                         device_data->tech_state = NETCONFIG_WIFI_TECH_POWERED;
698                                                                 else
699                                                                         device_data->tech_state = NETCONFIG_WIFI_TECH_OFF;
700                                                         }
701                                                 } else if (g_strcmp0(dev_key, "Connected") == 0) {
702                                                         if (device_data) {
703                                                                 device_data->connected = g_variant_get_boolean(dev_var);
704                                                                 if (device_data->connected == TRUE)
705                                                                         device_data->tech_state = NETCONFIG_WIFI_TECH_CONNECTED;
706                                                         }
707                                                 }
708                                         }
709                                 }
710
711                                 g_variant_iter_free(list_iter);
712                         }
713                 }
714         }
715
716         g_variant_unref(message);
717
718         g_variant_iter_free(iter);
719
720         g_slist_free_full(device_list, __device_free_data);
721
722         return updated;
723 }
724
725 GSList *wifi_state_get_device_list(void)
726 {
727         return g_device_list;
728 }
729
730 static gboolean __state_update_device_list(gpointer data)
731 {
732         if (wifi_state_update_device_list() == FALSE) {
733                 if (network_update_timer_cnt <
734                         NETCONFIG_UPDATE_DEVICE_LIST_COUNT) {
735                         network_update_timer_cnt++;
736                         return TRUE;
737                 }
738         }
739
740         netconfig_stop_timer(&network_update_timer_id);
741         return FALSE;
742 }
743
744 void wifi_state_set_service_state(const char *interface_name,
745                 const char *service, wifi_service_state_e new_state)
746 {
747         static gboolean dhcp_stage = FALSE;
748         wifi_device_data_s *device_data = NULL;
749         wifi_service_state_e old_state = NETCONFIG_WIFI_UNKNOWN;
750
751         device_data = __device_get_data(interface_name);
752         if (!device_data)
753                 return;
754
755         old_state = device_data->service_state;
756         if (old_state == new_state)
757                 return;
758
759         device_data->service_state = new_state;
760         DBG("Wi-Fi service state, old state[%s] ==> new state[%s]",
761                 _convert_wifi_service_state_to_string(old_state), _convert_wifi_service_state_to_string(new_state));
762
763         /* From association, temporarily disable Wi-Fi power saving */
764         if ((old_state < NETCONFIG_WIFI_ASSOCIATION || old_state == NETCONFIG_WIFI_FAILURE) && new_state == NETCONFIG_WIFI_ASSOCIATION) {
765                 _set_power_lock(TRUE);
766                 wifi_set_early_suspend(interface_name, FALSE);
767                 dhcp_stage = TRUE;
768         } else if (dhcp_stage == TRUE && new_state != NETCONFIG_WIFI_CONFIGURATION) {
769                 _set_power_lock(FALSE);
770                 wifi_set_early_suspend(interface_name, TRUE);
771                 dhcp_stage = FALSE;
772         }
773
774         if (new_state == NETCONFIG_WIFI_CONNECTED) {
775                 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_FOUND_AP_NOTI, NULL);
776
777                 __update_wifi_state();
778
779                 netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_CONNECTED);
780
781                 __set_wifi_connected_essid();
782
783                 netconfig_wifi_indicator_start(interface_name, service);
784         } else if (old_state == NETCONFIG_WIFI_CONNECTED) {
785                 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_PORTAL_NOTI, NULL);
786
787                 __unset_wifi_connected_essid();
788
789                 __update_wifi_state();
790
791                 netconfig_set_system_event(SYS_EVT_WIFI_STATE, EKEY_WIFI_STATE, EVAL_WIFI_ON);
792
793                 netconfig_wifi_indicator_stop(interface_name);
794
795                 netconfig_wifi_bgscan_stop(interface_name);
796                 netconfig_wifi_bgscan_set_interval(interface_name, SCAN_EXPONENTIAL_MIN);
797                 netconfig_wifi_bgscan_start(interface_name, TRUE);
798         } else if ((old_state > NETCONFIG_WIFI_IDLE && old_state < NETCONFIG_WIFI_CONNECTED) && new_state == NETCONFIG_WIFI_IDLE) {
799                 /* in ipv6 case disconnect/association -> association */
800                 DBG("reset the bg scan period");
801
802                 netconfig_wifi_bgscan_stop(interface_name);
803                 netconfig_wifi_bgscan_start(interface_name, TRUE);
804         }
805
806         _wifi_state_changed(interface_name, new_state);
807
808         if (new_state == NETCONFIG_WIFI_CONNECTED)
809                 _wifi_state_connected_activation();
810 }
811
812 wifi_service_state_e wifi_state_get_service_state(const char *interface_name)
813 {
814         wifi_device_data_s *device_data = __device_get_data(interface_name);
815         if (!device_data)
816                 return NETCONFIG_WIFI_UNKNOWN;
817
818         return device_data->service_state;
819 }
820
821 void wifi_state_set_technology_state(const char *interface_name, wifi_tech_state_e new_state)
822 {
823         wifi_device_data_s *device_data = NULL;
824
825         device_data = __device_get_data(interface_name);
826         if (device_data) {
827                 if (device_data->tech_state == new_state)
828                         return;
829
830                 DBG("Wi-Fi %s technology state, old state[%s] ==> new state[%s]", interface_name,
831                         _convert_wifi_technology_state_to_string(device_data->tech_state),
832                         _convert_wifi_technology_state_to_string(new_state));
833
834                 device_data->tech_state = new_state;
835         }
836 }
837
838 wifi_tech_state_e wifi_state_get_technology_state(const char *interface_name)
839 {
840         wifi_device_data_s *device_data = NULL;
841
842         device_data = __device_get_data(interface_name);
843         if (device_data) {
844                 DBG("Wi-Fi %s technology state [%s]", interface_name,
845                         _convert_wifi_technology_state_to_string(device_data->tech_state));
846
847                 return device_data->tech_state;
848         }
849
850         return NETCONFIG_WIFI_TECH_UNKNOWN;
851 }
852
853 void wifi_state_set_powered(const char *interface_name, gboolean powered)
854 {
855         wifi_device_data_s *device_data = __device_get_data(interface_name);
856
857         if (device_data) {
858                 device_data->powered = powered;
859                 DBG("Wi-Fi %s [%s]", interface_name, powered ? "enabled" : "disabled");
860         }
861 }
862
863 gboolean wifi_state_get_powered(const char *interface_name)
864 {
865         wifi_device_data_s *device_data = __device_get_data(interface_name);
866         if (!device_data)
867                 return FALSE;
868
869         return device_data->powered;
870 }
871
872 void wifi_state_set_connected(const char *interface_name, gboolean connected)
873 {
874         wifi_device_data_s *device_data = __device_get_data(interface_name);
875
876         if (device_data) {
877                 device_data->connected = connected;
878                 DBG("Wi-Fi %s [%s]", interface_name, connected ? "connected" : "disconnected");
879         }
880 }
881
882 gboolean wifi_state_get_connected(const char *interface_name)
883 {
884         wifi_device_data_s *device_data = __device_get_data(interface_name);
885         if (!device_data)
886                 return FALSE;
887
888         return device_data->connected;
889 }
890
891 gboolean wifi_state_is_existed(const char *interface_name)
892 {
893         wifi_device_data_s *device_data = __device_get_data(interface_name);
894         if (!device_data)
895                 return FALSE;
896
897         return TRUE;
898 }
899
900 const char *wifi_state_get_interface_name(const char *mac_address)
901 {
902         wifi_device_data_s *device_data = __device_get_data_by_macaddr(mac_address);
903         if (!device_data)
904                 return NULL;
905
906         return device_data->interface_name;
907 }
908
909 const char *wifi_state_get_mac_address(const char *interface_name)
910 {
911         wifi_device_data_s *device_data = __device_get_data(interface_name);
912         if (!device_data)
913                 return NULL;
914
915         return device_data->mac_address;
916 }
917
918 void wifi_state_set_connected_essid(void)
919 {
920         __set_wifi_connected_essid();
921 }
922
923 void wifi_state_get_connected_essid(gchar **essid)
924 {
925         *essid = g_strdup(__get_wifi_connected_essid());
926 }
927
928 void wifi_state_initialize(void)
929 {
930         if (wifi_state_update_device_list() == FALSE)
931                 netconfig_start_timer(NETCONFIG_UPDATE_DEVICE_LIST_TIMEOUT,
932                         __state_update_device_list, NULL, &network_update_timer_id);
933 }
934
935 void wifi_state_deinitialize(void)
936 {
937         g_slist_free_full(g_device_list, __device_free_data);
938 }