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