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