tizen 2.3.1 release
[framework/connectivity/mobileap-agent.git] / src / mobileap_wifi.c
1 /*
2  * mobileap-agent
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <glib.h>
19 #include <dbus/dbus.h>
20 #include <dbus/dbus-glib.h>
21 #include <dbus/dbus-glib-lowlevel.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <wifi.h>
26 #include <wifi-direct.h>
27
28 #include "mobileap_softap.h"
29 #include "mobileap_common.h"
30 #include "mobileap_wifi.h"
31 #include "mobileap_handler.h"
32 #include "mobileap_notification.h"
33
34 #define WIFI_RECOVERY_GUARD_TIME        1000    /* ms */
35
36 static mobile_ap_error_code_e __update_softap_settings(softap_settings_t *st,
37         gchar *ssid, gchar *passphrase, int hide_mode, softap_security_type_e security_type);
38 static int __turn_off_wifi(TetheringObject *obj);
39
40 static DBusGMethodInvocation *g_context = NULL;
41 static guint wifi_recovery_timeout_id = 0;
42 static gboolean prev_wifi_on = FALSE;
43 static wifi_saved_settings wifi_settings = {0, NULL, NULL, 0};
44
45 static void _wifi_direct_state_cb(int error_code, wifi_direct_device_state_e state, void *user_data)
46 {
47         bool wifi_state = false;
48
49         DBG("+\n");
50
51         if (user_data == NULL) {
52                 ERR("The param is NULL\n");
53                 return;
54         }
55
56         TetheringObject *obj = (TetheringObject *)user_data;
57         int ret = 0;
58
59         if (state != WIFI_DIRECT_DEVICE_STATE_DEACTIVATED) {
60                 ERR("Unknown state : %d\n", state);
61                 return;
62         }
63
64         wifi_direct_unset_device_state_changed_cb();
65         wifi_direct_deinitialize();
66
67         if (error_code != 0) {
68                 ERR("wifi_direct_deactivate fail in cb : %d\n", error_code);
69                 ret = MOBILE_AP_ERROR_INTERNAL;
70                 goto DONE;
71         }
72         DBG("Wi-Fi direct is turned off\n");
73
74         wifi_is_activated(&wifi_state);
75         if (wifi_state) {
76                 DBG("Wi-Fi is turned on. Turn off Wi-Fi");
77                 if (__turn_off_wifi(obj) != MOBILE_AP_ERROR_NONE) {
78                         ERR("_turn_off_wifi is failed\n");
79                         ret = MOBILE_AP_ERROR_INTERNAL;
80                         goto DONE;
81                 }
82                 return;
83         }
84
85         ret = _enable_wifi_tethering(obj, wifi_settings.ssid, wifi_settings.key,
86                         wifi_settings.hide_mode, wifi_settings.security_type);
87         if (ret != MOBILE_AP_ERROR_NONE) {
88                 ERR("_enable_wifi_tethering is failed\n");
89         } else {
90                 _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
91         }
92
93 DONE:
94         dbus_g_method_return(g_context,
95                         MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
96         g_context = NULL;
97
98         g_free(wifi_settings.ssid);
99         g_free(wifi_settings.key);
100         memset(&wifi_settings, 0, sizeof(wifi_settings));
101
102         DBG("-\n");
103         return;
104 }
105
106 static void __wifi_activated_cb(wifi_error_e result, void *user_data)
107 {
108         DBG("Wi-Fi on is done\n");
109
110         return;
111 }
112
113 static void __wifi_deactivated_cb(wifi_error_e result, void *user_data)
114 {
115         DBG("+\n");
116
117         if (user_data == NULL) {
118                 ERR("The param is NULL\n");
119                 return;
120         }
121
122         TetheringObject *obj = (TetheringObject *)user_data;
123         int ret;
124
125         if (result != WIFI_ERROR_NONE) {
126                 ERR("__wifi_deactivated_cb error : %d\n", result);
127                 ret = MOBILE_AP_ERROR_INTERNAL;
128                 goto DONE;
129         }
130
131         DBG("Wi-Fi is turned off\n");
132
133         ret = _enable_wifi_tethering(obj, wifi_settings.ssid, wifi_settings.key,
134                         wifi_settings.hide_mode, wifi_settings.security_type);
135         if (ret != MOBILE_AP_ERROR_NONE) {
136                 ERR("_enable_wifi_tethering is failed\n");
137         } else {
138                 prev_wifi_on = TRUE;
139                 _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
140         }
141
142 DONE:
143         dbus_g_method_return(g_context,
144                         MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
145         g_context = NULL;
146
147         g_free(wifi_settings.ssid);
148         g_free(wifi_settings.key);
149         memset(&wifi_settings, 0, sizeof(wifi_settings));
150
151         DBG("-\n");
152         return;
153 }
154
155 static int __turn_off_wifi(TetheringObject *obj)
156 {
157         int ret;
158
159         ret = wifi_deactivate(__wifi_deactivated_cb, (void *)obj);
160         if (ret != WIFI_ERROR_NONE) {
161                 ERR("wifi_deactivate() is failed : %d\n", ret);
162                 return MOBILE_AP_ERROR_INTERNAL;
163         }
164
165         return MOBILE_AP_ERROR_NONE;
166 }
167
168 static gboolean __turn_on_wifi_timeout_cb(gpointer user_data)
169 {
170         int ret;
171         guint idle_id;
172
173         wifi_recovery_timeout_id = 0;
174
175         ret = wifi_activate(__wifi_activated_cb, NULL);
176         if (ret != WIFI_ERROR_NONE) {
177                 ERR("wifi_activate() is failed : %d\n", ret);
178         }
179
180         idle_id = g_idle_add(_terminate_mobileap_agent, NULL);
181         if (idle_id == 0) {
182                 ERR("g_idle_add is failed\n");
183         }
184
185         return FALSE;
186 }
187
188 static int __turn_on_wifi(void)
189 {
190         if (wifi_recovery_timeout_id > 0) {
191                 g_source_remove(wifi_recovery_timeout_id);
192                 wifi_recovery_timeout_id = 0;
193         }
194
195         wifi_recovery_timeout_id = g_timeout_add(WIFI_RECOVERY_GUARD_TIME,
196                         __turn_on_wifi_timeout_cb, NULL);
197         if (wifi_recovery_timeout_id == 0) {
198                 ERR("g_timeout_add is failed\n");
199                 return MOBILE_AP_ERROR_INTERNAL;
200         }
201
202         return MOBILE_AP_ERROR_NONE;
203 }
204
205 static gboolean __is_wifi_direct_on(void)
206 {
207         int wifi_direct_state = 0;
208         int ret;
209
210         ret = vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state);
211         if (ret < 0) {
212                 ERR("vconf_get_int() is failed : %d\n", ret);
213                 return FALSE;
214         }
215
216         return wifi_direct_state != 0 ? TRUE : FALSE;
217 }
218
219 static int __turn_off_wifi_direct(TetheringObject *obj)
220 {
221         int ret;
222
223         ret = wifi_direct_initialize();
224         if (ret < 0) {
225                 ERR("wifi_direct_initialize() is failed : %d\n", ret);
226                 return MOBILE_AP_ERROR_INTERNAL;
227         }
228
229         ret = wifi_direct_set_device_state_changed_cb(_wifi_direct_state_cb, (void *)obj);
230         if (ret < 0) {
231                 ERR("wifi_direct_set_device_state_changed_cb() is failed : %d\n", ret);
232                 ret = wifi_direct_deinitialize();
233                 DBG("wifi_direct_deinitialize() ret : %d\n", ret);
234                 return MOBILE_AP_ERROR_INTERNAL;
235         }
236
237         ret = wifi_direct_deactivate();
238         if (ret < 0) {
239                 ERR("wifi_direct_deactivate() is failed : %d\n", ret);
240                 ret = wifi_direct_unset_device_state_changed_cb();
241                 DBG("wifi_direct_unset_device_state_changed_cb() ret : %d\n", ret);
242                 ret = wifi_direct_deinitialize();
243                 DBG("wifi_direct_deinitialize() ret : %d\n", ret);
244                 return MOBILE_AP_ERROR_INTERNAL;
245         }
246
247         return MOBILE_AP_ERROR_NONE;
248 }
249
250 static mobile_ap_error_code_e __update_softap_settings(softap_settings_t *st,
251         gchar *ssid, gchar *passphrase, int hide_mode, softap_security_type_e security_type)
252 {
253         if (st == NULL) {
254                 ERR("Invalid param\n");
255                 return MOBILE_AP_ERROR_INVALID_PARAM;
256         }
257
258         g_strlcpy(st->ssid, ssid, sizeof(st->ssid));
259
260         if (security_type == SOFTAP_SECURITY_TYPE_WPA2_PSK) {
261                 g_strlcpy(st->security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR,
262                         sizeof(st->security_type));
263                 g_strlcpy(st->key, passphrase, sizeof(st->key));
264         } else if (security_type == SOFTAP_SECURITY_TYPE_OPEN) {
265                 g_strlcpy(st->security_type, SOFTAP_SECURITY_TYPE_OPEN_STR,
266                         sizeof(st->security_type));
267                 g_strlcpy(st->key, "00000000", sizeof(st->key));
268         } else {
269                 ERR("Unknown security type\n");
270                 return MOBILE_AP_ERROR_INTERNAL;
271         }
272
273         st->hide_mode = hide_mode;
274
275         SDBG("ssid : %s security type : %s hide mode : %d\n",
276                         st->ssid, st->security_type, st->hide_mode);
277
278         return MOBILE_AP_ERROR_NONE;
279 }
280
281 static gboolean __is_equal_softap_settings(softap_settings_t *a, softap_settings_t *b)
282 {
283         if (a->hide_mode != b->hide_mode)
284                 return FALSE;
285
286         if (strcmp(a->ssid, b->ssid) != 0)
287                 return FALSE;
288
289         if (strcmp(a->key, b->key) != 0)
290                 return FALSE;
291
292         if (strcmp(a->security_type, b->security_type) != 0)
293                 return FALSE;
294
295         return TRUE;
296 }
297
298 mobile_ap_error_code_e _reload_softap_settings(TetheringObject *obj,
299                 gchar *ssid, gchar *key, gint hide_mode, gint security_type)
300 {
301         gboolean backup_prev_wifi_on = prev_wifi_on;
302         mobile_ap_error_code_e ret;
303         softap_settings_t *old_settings = &obj->softap_settings;
304         softap_settings_t new_settings;
305
306         if (obj == NULL || ssid == NULL || !strlen(ssid)) {
307                 ERR("invalid parameters\n");
308                 return MOBILE_AP_ERROR_INVALID_PARAM;
309         }
310
311         if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
312                 return MOBILE_AP_ERROR_NONE;
313
314         ret = __update_softap_settings(&new_settings, ssid, key, hide_mode,
315                         (softap_security_type_e)security_type);
316         if (ret != MOBILE_AP_ERROR_NONE) {
317                 ERR("__update_softap_settings is failed\n");
318                 return ret;
319         }
320
321         if (__is_equal_softap_settings(&new_settings, old_settings) == TRUE) {
322                 DBG("No need to reload settings\n");
323                 return MOBILE_AP_ERROR_NONE;
324         }
325
326         prev_wifi_on = FALSE;
327         ret = _disable_wifi_tethering(obj);
328
329         prev_wifi_on = backup_prev_wifi_on;
330         if (ret != MOBILE_AP_ERROR_NONE) {
331                 ERR("_disable_wifi_tethering is failed : %d\n", ret);
332                 return ret;
333         }
334
335         ret = _enable_wifi_tethering(obj, ssid, key, hide_mode,
336                         (softap_security_type_e)security_type);
337         if (ret != MOBILE_AP_ERROR_NONE) {
338                 ERR("_enable_wifi_tethering is failed : %d\n", ret);
339                 return ret;
340         }
341         _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
342
343         return MOBILE_AP_ERROR_NONE;
344 }
345
346 mobile_ap_error_code_e _reload_softap_settings_for_ap(TetheringObject *obj,
347         gchar *ssid, gchar *key, gint hide_mode, gint security_type)
348 {
349         gboolean backup_prev_wifi_on = prev_wifi_on;
350         mobile_ap_error_code_e ret;
351         softap_settings_t *old_settings = &obj->softap_settings;
352         softap_settings_t new_settings;
353
354         if (obj == NULL || ssid == NULL || !strlen(ssid)) {
355                 ERR("invalid parameters\n");
356                 return MOBILE_AP_ERROR_INVALID_PARAM;
357         }
358
359         ret = __update_softap_settings(&new_settings, ssid, key, hide_mode,
360                         (softap_security_type_e)security_type);
361         if (ret != MOBILE_AP_ERROR_NONE) {
362                 ERR("__update_softap_settings is failed\n");
363                 return ret;
364         }
365
366         if (__is_equal_softap_settings(&new_settings, old_settings) == TRUE) {
367                 DBG("No need to reload settings\n");
368                 return MOBILE_AP_ERROR_NONE;
369         }
370
371         prev_wifi_on = FALSE;
372
373         ret = _disable_wifi_ap(obj);
374         prev_wifi_on = backup_prev_wifi_on;
375         if (ret != MOBILE_AP_ERROR_NONE) {
376                 ERR("_disable_wifi_ap is failed : %d\n", ret);
377                 return ret;
378         }
379
380         ret = _enable_wifi_ap(obj, ssid, key, hide_mode,
381                         (softap_security_type_e)security_type);
382         if (ret != MOBILE_AP_ERROR_NONE) {
383                 ERR("_enable_wifi_ap is failed : %d\n", ret);
384                 return ret;
385         }
386
387         return MOBILE_AP_ERROR_NONE;
388 }
389
390 int _get_wifi_name_from_lease_info(const char *mac, char **name_buf)
391 {
392         if (mac == NULL || name_buf == NULL) {
393                 return MOBILE_AP_ERROR_INVALID_PARAM;
394         }
395
396         GIOChannel *io = NULL;
397         char *line = NULL;
398         char *device_name = MOBILE_AP_NAME_UNKNOWN;
399         char ip_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
400         char mac_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
401         char name[MOBILE_AP_STR_HOSTNAME_LEN] = {0, };
402         char expire[MOBILE_AP_STR_INFO_LEN] = {0, };
403         char extra[MOBILE_AP_STR_INFO_LEN] = {0, };
404
405         io = g_io_channel_new_file(DNSMASQ_LEASES_FILE, "r", NULL);
406         if (io == NULL) {
407                 return MOBILE_AP_ERROR_RESOURCE;
408         }
409
410         while (g_io_channel_read_line(io, &line, NULL, NULL, NULL) ==
411                         G_IO_STATUS_NORMAL) {
412                 sscanf(line, "%19s %19s %19s %19s %19s",
413                                 expire, mac_addr, ip_addr, name, extra);
414                 g_free(line);
415
416                 if (g_ascii_strcasecmp(mac_addr, mac) == 0) {
417                         if (g_strcmp0(name, "*") != 0)
418                                 device_name = name;
419                         break;
420                 }
421         }
422         g_io_channel_unref(io);
423
424         *name_buf = g_strdup(device_name);
425
426         return MOBILE_AP_ERROR_NONE;
427 }
428
429 void _add_wifi_device_to_array(softap_device_info_t *di, GPtrArray *array)
430 {
431         int i = 0;
432         GIOChannel *io = NULL;
433         gchar *line = NULL;
434         gchar *device_name = NULL;
435         gchar ip_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
436         gchar mac_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
437         gchar name[MOBILE_AP_STR_HOSTNAME_LEN] = {0, };
438         gchar expire[MOBILE_AP_STR_INFO_LEN] = {0, };
439         gchar extra[MOBILE_AP_STR_INFO_LEN] = {0, };
440
441         int found = 0;
442
443         for (i = 0; i < di->number; i++)
444                 SDBG("bssid[%d]:%s\n", i, di->bssid[i]);
445
446         DBG("Number of connected device:%d\n", di->number);
447
448         io = g_io_channel_new_file(DNSMASQ_LEASES_FILE, "r", NULL);
449
450         while (g_io_channel_read_line(io, &line, NULL, NULL, NULL) ==
451                                                         G_IO_STATUS_NORMAL) {
452                 sscanf(line, "%19s %19s %19s %19s %19s", expire, mac_addr,
453                                                         ip_addr, name, extra);
454                 SDBG("mac_addr:%s ip_addr:%s name:%s expire:%s\n", mac_addr,
455                                                         ip_addr, name, expire);
456
457                 for (i = 0; i < di->number; i++) {
458                         if (g_ascii_strcasecmp(di->bssid[i], mac_addr) == 0) {
459                                 if (!strcmp(name, "*"))
460                                         device_name = MOBILE_AP_NAME_UNKNOWN;
461                                 else
462                                         device_name = name;
463
464                                 _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
465                                                                 device_name);
466
467                                 found++;
468
469                                 break;
470                         }
471                 }
472
473                 g_free(line);
474         }
475         g_io_channel_unref(io);
476
477         /* Set the name UNKNOWN unless we got the name. */
478         for (i = found; i < di->number; i++) {
479                 _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
480                                                         MOBILE_AP_NAME_UNKNOWN);
481         }
482 }
483
484 mobile_ap_error_code_e _enable_wifi_tethering(TetheringObject *obj, gchar *ssid,
485         gchar *passphrase, int hide_mode, softap_security_type_e security_type)
486 {
487         mobile_ap_error_code_e ret;
488
489         if (obj == NULL || ssid == NULL || !strlen(ssid)) {
490                 ERR("invalid parameters\n");
491                 return MOBILE_AP_ERROR_INVALID_PARAM;
492         }
493
494         if (security_type == SOFTAP_SECURITY_TYPE_WPA2_PSK && passphrase == NULL) {
495                 ERR("passphrase is null\n");
496                 return MOBILE_AP_ERROR_INVALID_PARAM;
497         }
498
499         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
500                 ERR("Wi-Fi AP is already enabled\n");
501                 ret = MOBILE_AP_ERROR_RESOURCE;
502                 return ret;
503         }
504
505         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
506                 ERR("Wi-Fi tethering is already enabled\n");
507                 ret = MOBILE_AP_ERROR_ALREADY_ENABLED;
508                 return ret;
509         }
510
511         /* Update global state */
512         if (!_mobileap_set_state(MOBILE_AP_STATE_WIFI)) {
513                 ret = MOBILE_AP_ERROR_RESOURCE;
514                 return ret;
515         }
516
517         /* Update Wi-Fi hotspot data to common object */
518         ret = __update_softap_settings(&obj->softap_settings, ssid, passphrase,
519                         hide_mode, security_type);
520         if (ret != MOBILE_AP_ERROR_NONE) {
521                 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
522                 return ret;
523         }
524
525         if (vconf_set_str(VCONFKEY_MOBILE_HOTSPOT_SSID,
526                                 obj->softap_settings.ssid) < 0) {
527                 ERR("vconf_set_str is failed\n");
528         }
529
530         /* Initialize tethering */
531         _block_device_sleep();
532         ret = _init_tethering(obj);
533         if (ret != MOBILE_AP_ERROR_NONE) {
534                 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
535                 goto DONE;
536         }
537
538         /* Upload driver */
539         ret = _mh_core_enable_softap(MOBILE_AP_TYPE_WIFI,
540                         obj->softap_settings.ssid,
541                         obj->softap_settings.security_type,
542                         obj->softap_settings.key,
543                         obj->softap_settings.hide_mode);
544         if (ret != MOBILE_AP_ERROR_NONE) {
545                 _deinit_tethering(obj);
546                 _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
547                 goto DONE;
548         }
549         _delete_timeout_noti();
550
551         _init_timeout_cb(MOBILE_AP_TYPE_WIFI, (void *)obj);
552         _start_timeout_cb(MOBILE_AP_TYPE_WIFI, time(NULL) + TETHERING_CONN_TIMEOUT);
553
554         _add_interface_routing(WIFI_IF, IP_ADDRESS_SOFTAP);
555         _add_routing_rule(WIFI_IF);
556
557 DONE:
558         _unblock_device_sleep();
559         return ret;
560 }
561
562 mobile_ap_error_code_e _enable_wifi_ap(TetheringObject *obj,
563                 gchar *ssid, gchar *passphrase, int hide_mode,
564                 softap_security_type_e security_type)
565 {
566         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
567
568         if (obj == NULL || ssid == NULL || !strlen(ssid)) {
569                 ERR("invalid parameters\n");
570                 return MOBILE_AP_ERROR_INVALID_PARAM;
571         }
572
573         if (security_type == SOFTAP_SECURITY_TYPE_WPA2_PSK &&
574                 (passphrase == NULL || strlen(passphrase) >= MOBILE_AP_WIFI_KEY_MAX_LEN)) {
575                 ERR("hex key length is not correct\n");
576                 return MOBILE_AP_ERROR_INVALID_PARAM;
577         }
578
579         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI | MOBILE_AP_STATE_BT
580                         | MOBILE_AP_STATE_USB)) {
581                 ERR("Tethering is already enabled\n");
582                 return MOBILE_AP_ERROR_RESOURCE;
583         }
584
585         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
586                 ERR("Wi-Fi AP is already enabled\n");
587                 return MOBILE_AP_ERROR_ALREADY_ENABLED;
588         }
589
590         if (!_mobileap_set_state(MOBILE_AP_STATE_WIFI_AP)) {
591                 return MOBILE_AP_ERROR_RESOURCE;
592         }
593
594         ret = __update_softap_settings(&obj->softap_settings, ssid, passphrase,
595                         hide_mode, security_type);
596         if (ret != MOBILE_AP_ERROR_NONE) {
597                 _mobileap_clear_state(MOBILE_AP_STATE_WIFI_AP);
598                 return ret;
599         }
600
601         _block_device_sleep();
602
603         if (_init_tethering(obj) != MOBILE_AP_ERROR_NONE) {
604                 _mobileap_clear_state(MOBILE_AP_STATE_WIFI_AP);
605                 ret = MOBILE_AP_ERROR_RESOURCE;
606                 goto DONE;
607         }
608
609         /* Upload driver */
610         ret = _mh_core_enable_softap(MOBILE_AP_TYPE_WIFI_AP,
611                         obj->softap_settings.ssid,
612                         obj->softap_settings.security_type,
613                         obj->softap_settings.key,
614                         obj->softap_settings.hide_mode);
615         if (ret != MOBILE_AP_ERROR_NONE) {
616                 _deinit_tethering(obj);
617                 _mobileap_clear_state(MOBILE_AP_STATE_WIFI_AP);
618                 goto DONE;
619         }
620
621         _delete_timeout_noti();
622         _init_timeout_cb(MOBILE_AP_TYPE_WIFI_AP, (void *)obj);
623         _start_timeout_cb(MOBILE_AP_TYPE_WIFI_AP, time(NULL) + WIFI_AP_CONN_TIMEOUT);
624         _add_interface_routing(WIFI_IF, IP_ADDRESS_SOFTAP);
625         _add_routing_rule(WIFI_IF);
626
627 DONE:
628         _unblock_device_sleep();
629         return ret;
630 }
631
632 mobile_ap_error_code_e _disable_wifi_tethering(TetheringObject *obj)
633 {
634         int ret;
635         int state;
636         mobile_ap_type_e type;
637
638         type = MOBILE_AP_TYPE_WIFI;
639         state = MOBILE_AP_STATE_WIFI;
640
641         if (!_mobileap_is_enabled(state)) {
642                 ERR("Wi-Fi tethering ap has not been activated\n");
643                 ret = MOBILE_AP_ERROR_NOT_ENABLED;
644                 return ret;
645         }
646
647         _block_device_sleep();
648         _del_routing_rule(WIFI_IF);
649         _del_interface_routing(WIFI_IF, IP_ADDRESS_SOFTAP);
650         _flush_ip_address(WIFI_IF);
651         _deinit_timeout_cb(type);
652
653         if (_remove_station_info_all(type) != MOBILE_AP_ERROR_NONE) {
654                 ERR("_remove_station_info_all is failed. Ignore it.\n");
655         }
656
657         ret = _mh_core_disable_softap();
658         if (ret != MOBILE_AP_ERROR_NONE) {
659                 ERR("_mh_core_disable_softap is failed : %d\n", ret);
660                 goto DONE;
661         }
662
663         _deinit_tethering(obj);
664         _mobileap_clear_state(state);
665
666         if (prev_wifi_on == TRUE) {
667                 DBG("Previous Wi-Fi was turned on. Recover it\n");
668                 if (__turn_on_wifi() != MOBILE_AP_ERROR_NONE) {
669                         ERR("__turn_on_wifi() is failed\n");
670                 }
671                 prev_wifi_on = FALSE;
672         }
673         DBG("_disable_wifi_tethering is done\n");
674
675 DONE:
676         _unblock_device_sleep();
677         return ret;
678 }
679
680 mobile_ap_error_code_e _disable_wifi_ap(TetheringObject *obj)
681 {
682         int ret;
683         int state;
684         mobile_ap_type_e type;
685
686         type = MOBILE_AP_TYPE_WIFI_AP;
687         state = MOBILE_AP_STATE_WIFI_AP;
688
689         if (!_mobileap_is_enabled(state)) {
690                 ERR("Wi-Fi ap tethering has not been activated\n");
691                 ret = MOBILE_AP_ERROR_NOT_ENABLED;
692                 return ret;
693         }
694
695         _block_device_sleep();
696         _del_routing_rule(WIFI_IF);
697         _del_interface_routing(WIFI_IF, IP_ADDRESS_SOFTAP);
698         _flush_ip_address(WIFI_IF);
699         _deinit_timeout_cb(type);
700
701         if (_remove_station_info_all(type) != MOBILE_AP_ERROR_NONE) {
702                 ERR("_remove_station_info_all is failed. Ignore it.\n");
703         }
704
705         ret = _mh_core_disable_softap();
706         if (ret != MOBILE_AP_ERROR_NONE) {
707                 ERR("_mh_core_disable_softap is failed : %d\n", ret);
708                 goto DONE;
709         }
710
711         _deinit_tethering(obj);
712         _mobileap_clear_state(state);
713
714         DBG("_disable_wifi_ap is done\n");
715
716 DONE:
717         _unblock_device_sleep();
718         return ret;
719 }
720
721 gboolean tethering_enable_wifi_tethering(TetheringObject *obj, gchar *ssid,
722                 gchar *key, gint visibility, gint security_type,
723                 DBusGMethodInvocation *context)
724 {
725         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
726         gboolean ret_val = FALSE;
727         bool wifi_state = false;
728
729         DBG("+\n");
730         g_assert(obj != NULL);
731         g_assert(context != NULL);
732
733         if (g_context) {
734                 DBG("It is turnning on\n");
735                 dbus_g_method_return(context,
736                                 MOBILE_AP_ENABLE_WIFI_TETHERING_CFM,
737                                 MOBILE_AP_ERROR_IN_PROGRESS);
738                 return FALSE;
739         }
740
741         g_context = context;
742
743         wifi_settings.ssid = g_strdup(ssid);
744         if (security_type == SOFTAP_SECURITY_TYPE_WPA2_PSK) {
745                 wifi_settings.key = g_strdup(key);
746                 wifi_settings.security_type = SOFTAP_SECURITY_TYPE_WPA2_PSK;
747         } else {
748                 wifi_settings.security_type = SOFTAP_SECURITY_TYPE_OPEN;
749         }
750         wifi_settings.hide_mode = (!visibility);
751
752         if (wifi_recovery_timeout_id) {
753                 DBG("Wi-Fi recovery is cancelled\n");
754                 g_source_remove(wifi_recovery_timeout_id);
755                 wifi_recovery_timeout_id = 0;
756                 prev_wifi_on = TRUE;
757         }
758
759         if (__is_wifi_direct_on() == TRUE) {
760                 DBG("Wi-Fi and Wi-Fi direct are turned on\n");
761                 if (__turn_off_wifi_direct(obj) != MOBILE_AP_ERROR_NONE) {
762                         ERR("_turn_off_wifi_direct is failed\n");
763                         ret = MOBILE_AP_ERROR_INTERNAL;
764                         goto DONE;
765                 }
766
767                 return TRUE;
768         }
769
770         wifi_is_activated(&wifi_state);
771         if (wifi_state == true) {
772                 DBG("Wi-Fi is turned on\n");
773                 if (__turn_off_wifi(obj) != MOBILE_AP_ERROR_NONE) {
774                         ERR("_turn_off_wifi is failed\n");
775                         ret = MOBILE_AP_ERROR_INTERNAL;
776                         goto DONE;
777                 }
778
779                 return TRUE;
780         }
781
782         ret = _enable_wifi_tethering(obj, ssid, key, !visibility,
783                         (softap_security_type_e)security_type);
784         if (ret != MOBILE_AP_ERROR_NONE) {
785                 ERR("_enable_wifi_tethering is failed\n");
786         } else {
787                 _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
788                 ret_val = TRUE;
789         }
790
791 DONE:
792         dbus_g_method_return(g_context,
793                         MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
794         g_context = NULL;
795
796         g_free(wifi_settings.ssid);
797         g_free(wifi_settings.key);
798         memset(&wifi_settings, 0, sizeof(wifi_settings));
799
800         return ret_val;
801 }
802
803 gboolean tethering_disable_wifi_tethering(TetheringObject *obj,
804                 DBusGMethodInvocation *context)
805 {
806         int ret = MOBILE_AP_ERROR_NONE;
807
808         DBG("+\n");
809         g_assert(obj != NULL);
810         g_assert(context != NULL);
811
812         ret = _disable_wifi_tethering(obj);
813
814         _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_OFF, NULL);
815         dbus_g_method_return(context, MOBILE_AP_DISABLE_WIFI_TETHERING_CFM, ret);
816
817         if (ret != MOBILE_AP_ERROR_NONE)
818                 return FALSE;
819
820         return TRUE;
821 }
822
823 gboolean tethering_enable_wifi_ap(TetheringObject *obj, gchar *ssid, gchar *key,
824         gint visibility, gint security_type, DBusGMethodInvocation *context)
825 {
826         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
827         gboolean ret_val = FALSE;
828
829         DBG("+\n");
830         g_assert(obj != NULL);
831         g_assert(context != NULL);
832
833         if (wifi_recovery_timeout_id) {
834                 DBG("Wi-Fi recovery is cancelled\n");
835                 g_source_remove(wifi_recovery_timeout_id);
836                 wifi_recovery_timeout_id = 0;
837         }
838
839         ret = _enable_wifi_ap(obj, ssid, key, !visibility,
840                         (softap_security_type_e)security_type);
841         if (ret != MOBILE_AP_ERROR_NONE) {
842                 ERR("_enable_wifi_tethering is failed\n");
843         } else {
844                 _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_AP_ON, NULL);
845                 ret_val = TRUE;
846         }
847
848         dbus_g_method_return(context, MOBILE_AP_ENABLE_WIFI_AP_CFM, ret);
849
850         return ret_val;
851 }
852
853 gboolean tethering_disable_wifi_ap(TetheringObject *obj,
854                 DBusGMethodInvocation *context)
855 {
856         int ret = MOBILE_AP_ERROR_NONE;
857
858         DBG("+\n");
859         g_assert(obj != NULL);
860         g_assert(context != NULL);
861
862         ret = _disable_wifi_ap(obj);
863
864         _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_AP_OFF, NULL);
865         dbus_g_method_return(context, MOBILE_AP_DISABLE_WIFI_AP_CFM, ret);
866
867         if (ret != MOBILE_AP_ERROR_NONE)
868                 return FALSE;
869
870         return TRUE;
871 }
872
873 gboolean tethering_reload_wifi_settings(TetheringObject *obj, gchar *ssid,
874                 gchar *key, gint visibility, gint security_type,
875                 DBusGMethodInvocation *context)
876 {
877         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
878         gboolean ret_val = TRUE;
879
880         DBG("+\n");
881         g_assert(obj != NULL);
882         g_assert(context != NULL);
883
884         ret = _reload_softap_settings(obj, ssid, key, !visibility, security_type);
885         if (ret != MOBILE_AP_ERROR_NONE) {
886                 ERR("_reload_softap_settings is failed\n");
887                 ret_val = FALSE;
888         }
889
890         dbus_g_method_return(context, ret);
891
892         return ret_val;
893 }
894
895 gboolean tethering_reload_wifi_ap_settings(TetheringObject *obj, gchar *ssid,
896         gchar *key, gint visibility, gint security, DBusGMethodInvocation *context)
897 {
898
899         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
900         gboolean ret_val = TRUE;
901
902         DBG("+\n");
903         g_assert(obj != NULL);
904         g_assert(context != NULL);
905
906         ret = _reload_softap_settings_for_ap(obj, ssid, key, !visibility, security);
907         if (ret != MOBILE_AP_ERROR_NONE) {
908                 ERR("_reload_softap_settings_for_ap is failed\n");
909                 ret_val = FALSE;
910         }
911
912         dbus_g_method_return(context, ret);
913         return ret_val;
914 }
915
916 gboolean _is_trying_wifi_operation(void)
917 {
918         return (g_context || wifi_recovery_timeout_id ? TRUE : FALSE);
919 }