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