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