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