c0236c7aa61f328751ce1c546ca9c597d13f9345
[platform/core/connectivity/net-config.git] / src / wifi-power.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 <errno.h>
21 #include <vconf.h>
22 #include <vconf-keys.h>
23 #include <ITapiSim.h>
24 #include <TapiUtility.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <tzplatform_config.h>
28
29 #if defined TIZEN_P2P_ENABLE && !defined WLAN_CONCURRENT_MODE
30 #include <wifi-direct.h>
31 #endif
32
33 #include "log.h"
34 #include "util.h"
35 #include "netdbus.h"
36 #include "neterror.h"
37 #include "wifi-wps.h"
38 #include "wifi-power.h"
39 #include "wifi-state.h"
40 #include "wifi-tel-intf.h"
41 #include "netsupplicant.h"
42 #include "network-state.h"
43 #include "network-dpm.h"
44 #include "wifi-firmware.h"
45 #include "wifi-background-scan.h"
46
47
48 #define WLAN_SUPPLICANT_SCRIPT          "/usr/sbin/wpa_supp.sh"
49 #define P2P_SUPPLICANT_SCRIPT           "/usr/sbin/p2p_supp.sh"
50
51 #define VCONF_WIFI_OFF_STATE_BY_AIRPLANE        "file/private/wifi/wifi_off_by_airplane"
52 #define VCONF_WIFI_OFF_STATE_BY_RESTRICTED      "file/private/wifi/wifi_off_by_restricted"
53 #define VCONF_WIFI_OFF_STATE_BY_EMERGENCY       "file/private/wifi/wifi_off_by_emergency"
54 #if defined TIZEN_WEARABLE
55 #define VCONF_WIFI_WEARABLE_WIFI_USE                    "db/private/wifi/wearable_wifi_use"
56 #endif
57 #if !defined TIZEN_WEARABLE
58 #define VCONFKEY_SETAPPL_NETWORK_PERMIT_WITH_LCD_OFF_LIMIT      "db/setting/network_with_lcd_off_limit"
59 #endif
60
61 #define WLAN_MAC_INFO               tzplatform_mkpath(TZ_SYS_ETC, "/.mac.info")
62 #define WLAN_MAC_ADDRESS_FILEPATH   "/sys/class/net/wlan0/address"
63 #define WLAN_MAC_ADDR_MAX           20
64 #define VCONF_WIFI_BSSID_ADDRESS        "db/wifi/bssid_address"
65
66 #define ETH_MAC_ADDR_SIZE 6
67 #define VCONF_ETH_MAC_ADDRESS  "db/dnet/mac_address"
68 #define NET_EXEC_PATH "/sbin/ifconfig"
69 #define OS_RANDOM_FILE "/dev/urandom"
70
71 static gboolean connman_wifi_technology_state = FALSE;
72 static gboolean wifi_firmware_recovery_mode = FALSE;
73 static int airplane_mode = 0;
74
75 #if defined TIZEN_WEARABLE
76 static int psmode_wifi_use = 1;
77 #endif
78
79 static gboolean __is_wifi_restricted(void)
80 {
81 #if defined TIZEN_WEARABLE
82         return FALSE;
83 #endif
84         int restricted_mode = 0;
85
86         netconfig_vconf_get_bool(VCONFKEY_SETAPPL_NETWORK_RESTRICT_MODE, &restricted_mode);
87         if (restricted_mode != 0) {
88                 DBG("network restricted mode[%d]", restricted_mode);
89                 return TRUE;
90         }
91
92         return FALSE;
93 }
94
95 static void __technology_reply(GObject *source_object, GAsyncResult *res, gpointer user_data)
96 {
97         GVariant *reply;
98         GDBusConnection *conn = NULL;
99         GError *error = NULL;
100
101         conn = G_DBUS_CONNECTION(source_object);
102         reply = g_dbus_connection_call_finish(conn, res, &error);
103
104         if (reply == NULL) {
105                 if (error != NULL) {
106                         if (g_strstr_len(error->message, strlen(error->message),
107                                         CONNMAN_ERROR_INTERFACE ".AlreadyEnabled") != NULL) {
108                                 wifi_state_update_power_state(TRUE);
109                         } else if (g_strstr_len(error->message, strlen(error->message),
110                                         CONNMAN_ERROR_INTERFACE ".AlreadyDisabled") != NULL) {
111                                 wifi_state_update_power_state(FALSE);
112                         } else {
113                                 ERR("Fail to request status [%d: %s]", error->code, error->message);
114                                 wifi_state_update_power_state(FALSE);
115                         }
116                         g_error_free(error);
117                 } else {
118                         ERR("Fail to request status");
119                         wifi_state_update_power_state(FALSE);
120                 }
121         } else {
122                 DBG("Successfully requested");
123         }
124
125         g_variant_unref(reply);
126         netconfig_gdbus_pending_call_unref();
127 }
128
129 static int __execute_supplicant(gboolean enable)
130 {
131         int rv = 0;
132         const char *path = WLAN_SUPPLICANT_SCRIPT;
133         char *const args_enable[] = { "/usr/sbin/wpa_supp.sh", "start", NULL };
134         char *const args_disable[] = { "/usr/sbin/wpa_supp.sh", "stop", NULL };
135         char *const envs[] = { NULL };
136         static gboolean enabled = FALSE;
137
138         if (enabled == enable)
139                 return -EALREADY;
140
141         if (enable == TRUE)
142                 rv = netconfig_execute_file(path, args_enable, envs);
143         else
144                 rv = netconfig_execute_file(path, args_disable, envs);
145         if (rv < 0)
146                 return -EIO;
147
148         DBG("wpa_supplicant %s", enable == TRUE ? "started" : "stopped");
149
150         enabled = enable;
151
152         return 0;
153 }
154
155 #if defined TIZEN_P2P_ENABLE && defined WLAN_CONCURRENT_MODE
156 static int __netconfig_p2p_supplicant(gboolean enable)
157 {
158         int rv = 0;
159         const char *path = P2P_SUPPLICANT_SCRIPT;
160         char *const args_enable[] = { P2P_SUPPLICANT_SCRIPT, "start", NULL };
161         char *const args_disable[] = { P2P_SUPPLICANT_SCRIPT, "stop", NULL };
162         char *const envs[] = { NULL };
163
164         if (enable == TRUE)
165                 rv = netconfig_execute_file(path, args_enable, envs);
166         else
167                 rv = netconfig_execute_file(path, args_disable, envs);
168         if (rv < 0)
169                 return -EIO;
170
171         DBG("p2p_supplicant %s", enable == TRUE ? "started" : "stopped");
172
173         return 0;
174 }
175 #endif
176
177 void netconfig_wifi_recover_firmware(void)
178 {
179         wifi_firmware_recovery_mode = TRUE;
180
181         netconfig_wifi_bgscan_stop();
182
183         wifi_power_off();
184 }
185
186 #if defined TIZEN_P2P_ENABLE && !defined WLAN_CONCURRENT_MODE
187 static void __netconfig_wifi_direct_state_cb(int error_code, wifi_direct_device_state_e device_state, void *user_data)
188 {
189         int err;
190
191         wifi_direct_unset_device_state_changed_cb();
192         wifi_direct_deinitialize();
193
194         if (device_state == WIFI_DIRECT_DEVICE_STATE_DEACTIVATED) {
195                 err = wifi_power_on();
196                 if (err < 0) {
197                         if (err == -EALREADY)
198                                 wifi_state_update_power_state(TRUE);
199                         else
200                                 wifi_state_emit_power_failed();
201                 }
202         }
203 }
204
205 static gboolean __netconfig_wifi_direct_power_off(void)
206 {
207         DBG("Wi-Fi direct is turning off");
208
209         if (wifi_direct_initialize() < 0)
210                 return FALSE;
211
212         if (wifi_direct_set_device_state_changed_cb(__netconfig_wifi_direct_state_cb, NULL) < 0)
213                 return FALSE;
214
215         if (wifi_direct_deactivate() < 0)
216                 return FALSE;
217
218         return TRUE;
219 }
220 #endif
221
222 static int _load_driver_and_supplicant(void)
223 {
224         int err = 0;
225         wifi_tech_state_e tech_state;
226
227         tech_state = wifi_state_get_technology_state();
228         if (tech_state > NETCONFIG_WIFI_TECH_OFF)
229                 return -EALREADY;
230
231         err = __execute_supplicant(TRUE);
232         if (err < 0 && err != -EALREADY)
233                 return err;
234
235         err = netconfig_wifi_firmware(NETCONFIG_WIFI_STA, TRUE);
236         if (err < 0 && err != -EALREADY) {
237                 __execute_supplicant(FALSE);
238                 return err;
239         }
240
241         wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_WPS_ONLY);
242
243         return 0;
244 }
245
246 static int _remove_driver_and_supplicant(void)
247 {
248         int err = 0;
249
250         INFO("remove driver and supplicant");
251         if (wifi_firmware_recovery_mode != TRUE &&
252                                         netconfig_wifi_is_wps_enabled() == TRUE) {
253                 DBG("Wi-Fi WPS mode");
254                 return 0;
255         }
256
257         err = netconfig_wifi_firmware(NETCONFIG_WIFI_STA, FALSE);
258         if (err < 0 && err != -EALREADY)
259                 return err;
260
261         err = __execute_supplicant(FALSE);
262         if (err < 0 && err != -EALREADY)
263                 return err;
264
265         wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_OFF);
266
267         // reset service state
268         wifi_state_set_service_state(NETCONFIG_WIFI_IDLE);
269
270         if (wifi_firmware_recovery_mode == TRUE) {
271                 if (wifi_power_on() < 0)
272                         ERR("Failed to recover Wi-Fi firmware");
273
274                 wifi_firmware_recovery_mode = FALSE;
275         }
276
277         return 0;
278 }
279
280 static int _set_connman_technology_power(gboolean enable)
281 {
282         gboolean reply = FALSE;
283         GVariant *param0 = NULL;
284         GVariant *params = NULL;
285         char key[] = "Powered";
286         gboolean value_enable = TRUE;
287         gboolean value_disable = FALSE;
288
289         if (connman_wifi_technology_state == enable)
290                 return -EALREADY;
291
292         if (enable == TRUE)
293                 param0 = g_variant_new_boolean(value_enable);
294         else
295                 param0 = g_variant_new_boolean(value_disable);
296
297         params = g_variant_new("(sv)", key, param0);
298
299         reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
300                                         CONNMAN_WIFI_TECHNOLOGY_PREFIX, CONNMAN_TECHNOLOGY_INTERFACE,
301                                         "SetProperty", params, __technology_reply);
302
303         if (reply != TRUE) {
304                 ERR("Fail to set technology %s", enable == TRUE ? "enable" : "disable");
305                 return -ESRCH;
306         }
307
308         /* If Wi-Fi powered off,
309          * Do not remove Wi-Fi driver until ConnMan technology state updated
310          */
311         if (enable == TRUE)
312                 connman_wifi_technology_state = enable;
313
314         /* To be keep safe, early disable Wi-Fi tech state */
315         if (enable != TRUE)
316                 wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_WPS_ONLY);
317
318         return 0;
319 }
320
321 static void __netconfig_set_wifi_bssid(void)
322 {
323         int rv = 0;
324         char bssid[WLAN_MAC_ADDR_MAX];
325
326         FILE *fp = fopen(WLAN_MAC_INFO, "r");
327
328         if (fp == NULL) {
329                 ERR("Fail to open %s", WLAN_MAC_INFO);
330                 fp = fopen(WLAN_MAC_ADDRESS_FILEPATH, "r");
331                 if (fp == NULL) {
332                         ERR("Fail to open %s", WLAN_MAC_ADDRESS_FILEPATH);
333                         return;
334                 }
335         }
336
337         fseek(fp, 0L, SEEK_SET);
338         rv = fscanf(fp, "%17s", bssid);
339
340         if (rv < 0)
341                 ERR("Fail to read bssid");
342
343         netconfig_set_vconf_str(VCONF_WIFI_BSSID_ADDRESS, bssid);
344
345         fclose(fp);
346 }
347
348 void netconfig_wifi_disable_technology_state_by_only_connman_signal(void)
349 {
350         /* Important: it's only done by ConnMan technology signal update */
351         connman_wifi_technology_state = FALSE;
352 }
353
354 #if defined TIZEN_WEARABLE
355 int netconfig_wifi_on_wearable(gboolean device_picker_test)
356 {
357         int err = 0;
358         int wifi_use;
359         int ps_mode;
360
361         if (netconfig_vconf_get_int(VCONF_WIFI_WEARABLE_WIFI_USE, &wifi_use) < 0) {
362                 ERR("Fail to get VCONF_WIFI_WEARABLE_WIFI_USE");
363                 return -EIO;
364         }
365
366         if (wifi_use > 0) {
367                 if (netconfig_vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &ps_mode) < 0) {
368                         ERR("Fail to get VCONFKEY_SETAPPL_PSMODE");
369                         return -EIO;
370                 }
371
372                 if (ps_mode > SETTING_PSMODE_NORMAL) {
373                         WARN("ps mode is on(%d), Not turn on Wi-Fi", ps_mode);
374                         return -EPERM;
375                 }
376         } else {
377                 WARN("Not permitted Wi-Fi on");
378                 return -EPERM;
379         }
380
381         err = wifi_power_driver_and_supplicant(TRUE);
382         if (err < 0 && err != -EALREADY)
383                 return err;
384
385         err = _set_connman_technology_power(TRUE);
386
387         if (device_picker_test == TRUE)
388                 netconfig_wifi_enable_device_picker_test();
389
390         return err;
391 }
392
393 static void __wearable_wifi_use_changed_cb(keynode_t* node, void* user_data)
394 {
395         int wifi_state;
396         int wifi_use = 1;
397
398         if (netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state) < 0) {
399                 ERR("Fail to get VCONFKEY_WIFI_STATE");
400                 return;
401         }
402
403         if (node != NULL)
404                 wifi_use = vconf_keynode_get_int(node);
405         else
406                 netconfig_vconf_get_int(VCONF_WIFI_WEARABLE_WIFI_USE, &wifi_use);
407
408         if (wifi_use > 0) {
409                 DBG("wifi use on");
410                 if (wifi_state > VCONFKEY_WIFI_OFF) {
411                         WARN("Wi-Fi is already turned on");
412                         return;
413                 }
414                 wifi_power_on_wearable(TRUE);
415         } else {
416                 ERR("## wifi use [OFF]");
417                 if (wifi_state == VCONFKEY_WIFI_OFF) {
418                         WARN("Wi-Fi is already turned off");
419                         return;
420                 }
421
422                 wifi_power_off();
423         }
424 }
425 #else
426 static void __netconfig_wifi_restrict_mode(keynode_t *node, void *user_data)
427 {
428         int wifi_state = 0, restricted = 0;
429         int wifi_off_by_restricted = 0;
430
431         netconfig_vconf_get_int(VCONF_WIFI_OFF_STATE_BY_RESTRICTED, &wifi_off_by_restricted);
432
433         netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
434
435         if (node != NULL)
436                 restricted = vconf_keynode_get_bool(node);
437         else
438                 netconfig_vconf_get_bool(VCONFKEY_SETAPPL_NETWORK_RESTRICT_MODE, &restricted);
439
440         DBG("network restricted mode %s", restricted > 0 ? "ON" : "OFF");
441         DBG("Wi-Fi state %d, Wi-Fi was off by restricted mode %s", wifi_state,
442                         wifi_off_by_restricted ? "Yes" : "No");
443
444         if (restricted > 0) {
445                 /* network restricted on */
446                 if (wifi_state == VCONFKEY_WIFI_OFF)
447                         return;
448
449                 wifi_power_off();
450
451                 netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_RESTRICTED, 1);
452         } else {
453                 /* network restricted off */
454                 if (!wifi_off_by_restricted)
455                         return;
456
457                 netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_RESTRICTED, 0);
458
459                 if (wifi_state > VCONFKEY_WIFI_OFF)
460                         return;
461
462                 wifi_power_on();
463         }
464 }
465 #endif
466
467 static void __netconfig_wifi_airplane_mode(keynode_t *node, void *user_data)
468 {
469         int wifi_state = 0, airplane_state = 0;
470         int wifi_off_by_airplane = 0;
471
472         netconfig_vconf_get_int(VCONF_WIFI_OFF_STATE_BY_AIRPLANE, &wifi_off_by_airplane);
473
474 #if defined TIZEN_WEARABLE
475         netconfig_vconf_get_int(VCONF_WIFI_WEARABLE_WIFI_USE, &wifi_state)
476 #else
477         netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
478 #endif
479
480         if (node != NULL)
481                 airplane_state = vconf_keynode_get_bool(node);
482         else
483                 netconfig_vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &airplane_state);
484
485         DBG("airplane mode %s (prev:%d)", airplane_state > 0 ? "ON" : "OFF", airplane_mode);
486         DBG("Wi-Fi state(or use) %d, Wi-Fi was off by flight mode %s", wifi_state,
487                         wifi_off_by_airplane ? "Yes" : "No");
488
489         if (airplane_mode == airplane_state)
490                 return ;
491
492         airplane_mode = airplane_state;
493
494         if (airplane_state > 0) {
495                 /* airplane mode on */
496                 if (wifi_state == VCONFKEY_WIFI_OFF)
497                         return;
498
499                 wifi_power_off();
500
501                 netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_AIRPLANE, 1);
502 #if defined TIZEN_WEARABLE
503                 netconfig_set_vconf_int(VCONF_WIFI_WEARABLE_WIFI_USE, 0);
504 #endif
505         } else {
506                 /* airplane mode off */
507                 if (!wifi_off_by_airplane)
508                         return;
509
510                 netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_AIRPLANE, 0);
511 #if defined TIZEN_WEARABLE
512                 netconfig_set_vconf_int(VCONF_WIFI_WEARABLE_WIFI_USE, 1);
513 #else
514                 if (wifi_state > VCONFKEY_WIFI_OFF)
515                         return;
516
517                 wifi_power_on();
518 #endif
519         }
520 }
521
522 static void __emergency_mode_changed_cb(keynode_t *node, void *user_data)
523 {
524         int wifi_state = 0, emergency = 0;
525         int wifi_off_by_emergency = 0;
526 #if !defined TIZEN_WEARABLE
527         int emergency_by_fmm = 0;
528 #endif
529 #if defined TIZEN_WEARABLE
530         int wifi_use = 1;
531 #endif
532
533         netconfig_vconf_get_int(VCONF_WIFI_OFF_STATE_BY_EMERGENCY, &wifi_off_by_emergency);
534         netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
535
536 #if !defined TIZEN_WEARABLE
537         netconfig_vconf_get_bool(VCONFKEY_SETAPPL_NETWORK_PERMIT_WITH_LCD_OFF_LIMIT, &emergency_by_fmm);
538         DBG("emergency mode by Find My Mobile (%d)", emergency_by_fmm);
539         if (emergency_by_fmm == 1)
540                 return;
541 #endif
542
543         if (node != NULL)
544                 emergency = vconf_keynode_get_int(node);
545         else
546                 netconfig_vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &emergency);
547
548         DBG("emergency mode %s", emergency > SETTING_PSMODE_POWERFUL ? "ON" : "OFF");
549         DBG("Wi-Fi state %d, Wi-Fi was off by emergency mode %s", wifi_state, wifi_off_by_emergency ? "Yes" : "No");
550
551 #if defined TIZEN_WEARABLE
552         if (emergency == SETTING_PSMODE_WEARABLE) {
553                 /* basic power saving mode on */
554         } else if (emergency == SETTING_PSMODE_WEARABLE_ENHANCED) {
555                 /* enhanced power saving mode on */
556                 netconfig_vconf_get_int(VCONF_WIFI_WEARABLE_WIFI_USE, &wifi_use);
557                 psmode_wifi_use = wifi_use;
558                 if (wifi_use != 0)
559                         netconfig_set_vconf_int(VCONF_WIFI_WEARABLE_WIFI_USE, 0);
560
561                 if (wifi_state == VCONFKEY_WIFI_OFF)
562                         return;
563
564                 wifi_power_off();
565                 netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_EMERGENCY, 1);
566         } else {
567                 /* power saving mode off */
568                 netconfig_set_vconf_int(VCONF_WIFI_WEARABLE_WIFI_USE, psmode_wifi_use);
569                 if (!wifi_off_by_emergency)
570                         return;
571
572                 netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_EMERGENCY, 0);
573                 if (wifi_state > VCONFKEY_WIFI_OFF)
574                         return;
575
576                 wifi_power_on_wearable(TRUE);
577         }
578 #else
579         if (emergency > SETTING_PSMODE_POWERFUL) {
580                 /* emergency mode on */
581                 if (wifi_state == VCONFKEY_WIFI_OFF)
582                         return;
583
584                 wifi_power_off();
585
586                 netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_EMERGENCY, 1);
587         } else {
588                 /* emergency mode off */
589                 if (!wifi_off_by_emergency)
590                         return;
591
592                 netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_EMERGENCY, 0);
593
594                 if (wifi_state > VCONFKEY_WIFI_OFF)
595                         return;
596
597                 wifi_power_on();
598         }
599 #endif
600
601 }
602
603 static void __pm_state_changed_cb(keynode_t* node, void* user_data)
604 {
605         int new_state = -1;
606         int wifi_state = 0;
607         static int prev_state = VCONFKEY_PM_STATE_NORMAL;
608
609         if (netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state) < 0) {
610                 ERR("Fail to get VCONFKEY_WIFI_STATE");
611                 return;
612         }
613
614         /* PM state
615          *      VCONFKEY_PM_STATE_NORMAL = 1,
616          *      VCONFKEY_PM_STATE_LCDDIM,
617          *      VCONFKEY_PM_STATE_LCDOFF,
618          *      VCONFKEY_PM_STATE_SLEEP
619          */
620         if (node != NULL)
621                 new_state = vconf_keynode_get_int(node);
622         else
623                 netconfig_vconf_get_int(VCONFKEY_PM_STATE, &new_state);
624
625         DBG("wifi state: %d (0 off / 1 on / 2 connected)", wifi_state);
626         DBG("Old PM state: %d, current: %d", prev_state, new_state);
627
628         if ((new_state == VCONFKEY_PM_STATE_NORMAL) && (prev_state >= VCONFKEY_PM_STATE_LCDOFF)) {
629                 netconfig_wifi_bgscan_stop();
630                 netconfig_wifi_bgscan_start(TRUE);
631         }
632
633         prev_state = new_state;
634 }
635
636 static void _tapi_noti_sim_status_cb(TapiHandle *handle, const char *noti_id,
637                                                                                 void *data, void *user_data)
638 {
639         TelSimCardStatus_t *status = data;
640
641         if (*status == TAPI_SIM_STATUS_SIM_INIT_COMPLETED) {
642                 DBG("Turn Wi-Fi on automatically");
643 #if defined TIZEN_WEARABLE
644                 wifi_power_on_wearable(TRUE);
645 #else
646                 wifi_power_on();
647 #endif
648                 netconfig_tel_deinit();
649         }
650 }
651
652 static gboolean netconfig_tapi_check_sim_state(void)
653 {
654         int ret, card_changed;
655         TelSimCardStatus_t status = TAPI_SIM_STATUS_UNKNOWN;
656         TapiHandle *tapi_handle = NULL;
657
658         tapi_handle = (TapiHandle *)netconfig_tel_init();
659         if (tapi_handle == NULL) {
660                 ERR("Failed to tapi init");
661                 return FALSE;
662         }
663
664         ret = tel_get_sim_init_info(tapi_handle, &status, &card_changed);
665         if (ret != TAPI_API_SUCCESS) {
666                 ERR("tel_get_sim_init_info() Failed : [%d]", ret);
667                 netconfig_tel_deinit();
668                 return FALSE;
669         }
670
671         switch (status) {
672         case TAPI_SIM_STATUS_UNKNOWN:
673         case TAPI_SIM_STATUS_CARD_ERROR:
674         case TAPI_SIM_STATUS_CARD_NOT_PRESENT:
675         case TAPI_SIM_STATUS_CARD_BLOCKED:
676         case TAPI_SIM_STATUS_SIM_INIT_COMPLETED:
677                 break;
678         case TAPI_SIM_STATUS_SIM_PIN_REQUIRED:
679         case TAPI_SIM_STATUS_SIM_INITIALIZING:
680         case TAPI_SIM_STATUS_SIM_PUK_REQUIRED:
681         case TAPI_SIM_STATUS_SIM_LOCK_REQUIRED:
682         case TAPI_SIM_STATUS_SIM_NCK_REQUIRED:
683         case TAPI_SIM_STATUS_SIM_NSCK_REQUIRED:
684         case TAPI_SIM_STATUS_SIM_SPCK_REQUIRED:
685         case TAPI_SIM_STATUS_SIM_CCK_REQUIRED:
686                 tel_register_noti_event(tapi_handle, TAPI_NOTI_SIM_STATUS,
687                                 _tapi_noti_sim_status_cb, NULL);
688                 return FALSE;
689         default:
690                 ERR("not defined status(%d)", status);
691                 break;
692         }
693
694         netconfig_tel_deinit();
695
696         return TRUE;
697 }
698
699 static void __netconfig_telephony_ready_changed_cb(keynode_t * node, void *data)
700 {
701         int telephony_ready = 0;
702
703         if (node != NULL)
704                 telephony_ready = vconf_keynode_get_bool(node);
705         else
706                 netconfig_vconf_get_bool(VCONFKEY_TELEPHONY_READY, &telephony_ready);
707
708         if (telephony_ready != 0) {
709                 if (netconfig_tapi_check_sim_state() == FALSE) {
710                         DBG("Sim is not initialized yet.");
711
712                         goto done;
713                 }
714         } else
715                 return;
716
717         DBG("Turn Wi-Fi on automatically");
718
719 #if defined TIZEN_WEARABLE
720         wifi_power_on_wearable(TRUE);
721 #else
722         wifi_power_on();
723 #endif
724
725 done:
726         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_READY, __netconfig_telephony_ready_changed_cb);
727 }
728
729 int wifi_power_driver_and_supplicant(gboolean enable)
730 {
731         /* There are 3 thumb rules for Wi-Fi power management
732          *   1. Do not make exposed API to control wpa_supplicant and driver directly.
733          *      It probably breaks ConnMan technology operation.
734          *
735          *   2. Do not remove driver and wpa_supplicant if ConnMan already enabled.
736          *      It breaks ConnMan technology operation.
737          *
738          *   3. Final the best rule: make it as simple as possible.
739          *      Simple code enables easy maintenance and reduces logical errors.
740          */
741         if (enable == TRUE) {
742                 return _load_driver_and_supplicant();
743         } else {
744                 if (connman_wifi_technology_state == TRUE)
745                         return -ENOSYS;
746
747                 return _remove_driver_and_supplicant();
748         }
749 }
750
751 void wifi_power_disable_technology_state_by_only_connman_signal(void)
752 {
753         /* Important: it's only done by ConnMan technology signal update */
754         connman_wifi_technology_state = FALSE;
755 }
756
757 void wifi_power_recover_firmware(void)
758 {
759         wifi_firmware_recovery_mode = TRUE;
760
761         netconfig_wifi_bgscan_stop();
762
763         wifi_power_off();
764 }
765
766 int wifi_power_on(void)
767 {
768         int err = 0;
769         wifi_tech_state_e tech_state;
770
771         tech_state = wifi_state_get_technology_state();
772         if (tech_state >= NETCONFIG_WIFI_TECH_POWERED) {
773                 /* There can be a scenario where wifi is automatically *
774                  * activated by connman if wifi was powered in last boot. *
775                  * So we should update connman_wifi_technology_state variable *
776                  * if it is found that wifi_tech_state variable is *
777                  * NETCONFIG_WIFI_TECH_POWERED and connman_wifi_technology_state *
778                  * variable is FALSE. Earlier connman_wifi_technology_state *
779                  * variable was only updated when wifi was Powered on from *
780                  * net-config resulting in variable not getting updated. *
781                  * This caused wifi to not get deactivated after reboot if *
782                  * last power state was activated */
783                 ERR("Net-Config WiFi connman technology state %d",
784                                 connman_wifi_technology_state);
785                 if (connman_wifi_technology_state == FALSE)
786                         connman_wifi_technology_state = TRUE;
787                 return -EALREADY;
788         }
789
790         if (__is_wifi_restricted() == TRUE)
791                 return -EPERM;
792
793         if (netconfig_is_wifi_tethering_on() == TRUE) {
794                 /* TODO: Wi-Fi tethering turns off here */
795                 /* return TRUE; */
796                 ERR("Failed to turn tethering off");
797                 return -EBUSY;
798         }
799
800 #if defined TIZEN_P2P_ENABLE && !defined WLAN_CONCURRENT_MODE
801         if (netconfig_is_wifi_direct_on() == TRUE) {
802                 if (__netconfig_wifi_direct_power_off() == TRUE)
803                         return -EINPROGRESS;
804                 else {
805                         ERR("Failed to turn Wi-Fi direct off");
806                         return -EBUSY;
807                 }
808         }
809 #endif
810
811         err = wifi_power_driver_and_supplicant(TRUE);
812         if (err < 0 && err != -EALREADY)
813                 return err;
814
815         err = _set_connman_technology_power(TRUE);
816
817         return err;
818 }
819
820 int wifi_power_off(void)
821 {
822         int err;
823
824         err = _set_connman_technology_power(FALSE);
825         if (err == -EALREADY)
826                 wifi_state_update_power_state(FALSE);
827
828         return 0;
829 }
830
831 #if defined TIZEN_WEARABLE
832 int wifi_power_on_wearable(gboolean device_picker_test)
833 {
834         int err = 0;
835         int wifi_use = 1;
836         wifi_tech_state_e tech_state;
837
838         tech_state = wifi_state_get_technology_state();
839         if (tech_state >= NETCONFIG_WIFI_TECH_POWERED)
840                 return -EALREADY;
841
842         if (netconfig_vconf_get_int(VCONF_WIFI_WEARABLE_WIFI_USE, &wifi_use) < 0) {
843                 ERR("Fail to get VCONF_WIFI_WEARABLE_WIFI_USE");
844                 return -EIO;
845         }
846
847         if (wifi_use == 0) {
848                 WARN("VCONF_WIFI_WEARABLE_WIFI_USE is OFF");
849                 return -EPERM;
850         }
851
852         err = wifi_power_driver_and_supplicant(TRUE);
853         if (err < 0 && err != -EALREADY)
854                 return err;
855
856         err = _set_connman_technology_power(TRUE);
857
858         if (device_picker_test == TRUE)
859                 netconfig_wifi_enable_device_picker_test();
860
861         return err;
862 }
863 #endif
864
865 void wifi_power_initialize(void)
866 {
867         int wifi_last_power_state = 0;
868
869         /* Initialize Airplane mode */
870         netconfig_vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &airplane_mode);
871         DBG("Airplane[%s]", airplane_mode > 0 ? "ON" : "OFF");
872
873         /* Update the last Wi-Fi power state */
874         netconfig_vconf_get_int(VCONF_WIFI_LAST_POWER_STATE, &wifi_last_power_state);
875         if (wifi_last_power_state > VCONFKEY_WIFI_OFF) {
876                 if (TIZEN_TELEPHONY_ENABLE) {
877                         int telephony_ready = 0;
878                         netconfig_vconf_get_bool(VCONFKEY_TELEPHONY_READY, &telephony_ready);
879                         if (telephony_ready == 0) {
880                                 DBG("Telephony API is not initialized yet");
881                                 vconf_notify_key_changed(VCONFKEY_TELEPHONY_READY,
882                                                 __netconfig_telephony_ready_changed_cb, NULL);
883                         } else {
884                                 if (netconfig_tapi_check_sim_state() == FALSE)
885                                         DBG("SIM is not initialized yet");
886                         }
887                 }
888                 DBG("Turn Wi-Fi on automatically");
889 #if defined TIZEN_WEARABLE
890                 wifi_power_on_wearable(TRUE);
891 #else
892                 wifi_power_on();
893 #endif
894         }
895
896 #if defined TIZEN_WEARABLE
897         vconf_notify_key_changed(VCONF_WIFI_WEARABLE_WIFI_USE, __wearable_wifi_use_changed_cb, NULL);
898
899         vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
900                         __netconfig_wifi_airplane_mode, NULL);
901 #else
902         vconf_notify_key_changed(VCONFKEY_SETAPPL_NETWORK_RESTRICT_MODE,
903                         __netconfig_wifi_restrict_mode, NULL);
904         vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE,
905                         __netconfig_wifi_airplane_mode, NULL);
906 #endif
907
908         vconf_notify_key_changed(VCONFKEY_SETAPPL_PSMODE, __emergency_mode_changed_cb, NULL);
909         vconf_notify_key_changed(VCONFKEY_PM_STATE, __pm_state_changed_cb, NULL);
910 }
911
912 void wifi_power_deinitialize(void)
913 {
914 }
915
916 gboolean handle_load_driver(Wifi *wifi,
917                 GDBusMethodInvocation *context, gboolean device_picker_test)
918 {
919         int err;
920
921         DBG("Wi-Fi power on requested");
922
923         g_return_val_if_fail(wifi != NULL, FALSE);
924
925         if (!netconfig_dpm_update_from_wifi()) {
926                 DBG("DPM policy restricts Wi-Fi");
927                 netconfig_error_permission_denied(context);
928                 return TRUE;
929         }
930
931         if (TIZEN_WLAN_BOARD_SPRD)
932                 wifi_firmware_download();
933
934 #if defined TIZEN_WEARABLE
935         err = wifi_power_on_wearable(device_picker_test);
936 #else
937         err = wifi_power_on();
938
939         if (device_picker_test == TRUE)
940                 netconfig_wifi_enable_device_picker_test();
941 #endif
942         if (err < 0) {
943                 if (err == -EINPROGRESS)
944                         netconfig_error_inprogress(context);
945                 else if (err == -EALREADY)
946                         netconfig_error_already_exists(context);
947                 else if (err == -EPERM)
948                         netconfig_error_permission_denied(context);
949                 else
950                         netconfig_error_wifi_driver_failed(context);
951
952                 return TRUE;
953         }
954
955
956         netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_AIRPLANE, 0);
957         __netconfig_set_wifi_bssid();
958
959         wifi_complete_load_driver(wifi, context);
960         return TRUE;
961 }
962
963 gboolean handle_remove_driver(Wifi *wifi, GDBusMethodInvocation *context)
964 {
965         int err;
966
967         DBG("Wi-Fi power off requested");
968
969         g_return_val_if_fail(wifi != NULL, FALSE);
970
971         err = wifi_power_off();
972         if (err < 0) {
973                 if (err == -EINPROGRESS)
974                         netconfig_error_inprogress(context);
975                 else if (err == -EALREADY)
976                         netconfig_error_already_exists(context);
977                 else if (err == -EPERM)
978                         netconfig_error_permission_denied(context);
979                 else
980                         netconfig_error_wifi_driver_failed(context);
981                 return TRUE;
982         }
983
984         netconfig_set_vconf_int(VCONF_WIFI_OFF_STATE_BY_AIRPLANE, 0);
985
986         wifi_complete_remove_driver(wifi, context);
987         return TRUE;
988 }
989
990 gboolean handle_load_p2p_driver(Wifi *wifi, GDBusMethodInvocation *context)
991 {
992         ERR("Deprecated");
993
994         wifi_complete_load_p2p_driver(wifi, context);
995         return TRUE;
996 }
997
998 gboolean handle_remove_p2p_driver(Wifi *wifi, GDBusMethodInvocation *context)
999 {
1000         ERR("Deprecated");
1001
1002         wifi_complete_remove_p2p_driver(wifi, context);
1003         return TRUE;
1004 }
1005
1006 static int __netconfig_get_random_mac(unsigned char *mac_buf, int mac_len)
1007 {
1008         DBG("Generate Random Mac address of ethernet");
1009         FILE *fp;
1010         int rc;
1011
1012         fp = fopen(OS_RANDOM_FILE, "rb");
1013
1014         if (fp == NULL) {
1015                 ERR("Could not open /dev/urandom");
1016                 return -1;
1017         }
1018         rc = fread(mac_buf, 1, mac_len, fp);
1019         if (fp)
1020                 fclose(fp);
1021
1022         return rc != mac_len ? -1 : 0;
1023 }
1024
1025 void __netconfig_set_ether_macaddr()
1026 {
1027         DBG("Set wired Mac address ");
1028         char *mac_addr = NULL;
1029         char rand_addr[WLAN_MAC_ADDR_MAX];
1030         int rv = -1;
1031
1032         mac_addr = vconf_get_str(VCONF_ETH_MAC_ADDRESS);
1033         if (mac_addr == NULL) {
1034                 DBG("vconf_get_str Failed\n");
1035                 return;
1036         }
1037         /* Checking Invalid MAC Address */
1038         if ((strlen(mac_addr) == 0)) {
1039                 ERR("Failed to get valid MAC Address from vconf");
1040                 /*Generate the Random Mac address*/
1041                 unsigned char rand_mac_add[ETH_MAC_ADDR_SIZE+1];
1042
1043                 if (__netconfig_get_random_mac(rand_mac_add, ETH_MAC_ADDR_SIZE) == -1) {
1044
1045                         ERR("Could not generate the Random Mac address");
1046                         free(mac_addr);
1047                         return;
1048                 }
1049
1050                 rand_mac_add[0] &= 0xFE; /*Clear multicase bit*/
1051                 rand_mac_add[0] |= 0x02; /*set local assignment bit*/
1052
1053                 /*Set the Mac address in Vconf*/
1054                 snprintf(rand_addr, WLAN_MAC_ADDR_MAX, "%x:%x:%x:%x:%x:%x",
1055                                 rand_mac_add[0], rand_mac_add[1],
1056                                 rand_mac_add[2], rand_mac_add[3],
1057                                 rand_mac_add[4], rand_mac_add[5]);
1058
1059                 netconfig_set_vconf_str(VCONF_ETH_MAC_ADDRESS, rand_addr);
1060         } else { /* Valid MAC address */
1061                 strncpy(rand_addr, mac_addr, strlen(mac_addr));
1062                 rand_addr[strlen(mac_addr)] = '\0';
1063         }
1064
1065         DBG("MAC Address of eth0 [%s]", rand_addr);
1066         const char *path = NET_EXEC_PATH;
1067         char *const args[] = { "/sbin/ifconfig", "eth0", "hw",
1068                 "ether", rand_addr, "up", NULL};
1069         char *const envs[] = { NULL };
1070         rv = netconfig_execute_file(path, args, envs);
1071
1072         if (rv < 0)
1073                 ERR("Unable to execute system command");
1074         free(mac_addr);
1075
1076 }