Remove flight mode implementation from core and add it to bt-service
[platform/core/connectivity/bluetooth-frwk.git] / bt-core / bt-core-adapter.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <vconf.h>
19 #include <vconf-keys.h>
20 #include <vconf-internal-radio-keys.h>
21 #include <bundle.h>
22 #include <eventsystem.h>
23 #include <stdio.h>
24 #ifdef TIZEN_FEATURE_ACTD
25 #include <actd/unit_control.h>
26 #endif
27
28 #include "bt-core-main.h"
29 #include "bt-core-adapter.h"
30 #include "bt-core-common.h"
31 #include "bt-core-dbus-handler.h"
32 #include "bt-core-noti-handler.h"
33
34 #include "bt-internal-types.h"
35
36 #define BT_CORE_IDLE_TERM_TIME 200 /* 200ms */
37 #define BT_CORE_CHECK_ADAPTER_OBJECT_PATH_MAX 50
38
39 #ifdef TIZEN_FEATURE_BT_OTP
40 #define BT_OTP_OBJECT_PATH      "/org/projectx/otp"
41 #define BT_OTP_INTERFACE_NAME   "org.projectx.otp_service"
42 #define BLE_DISABLED            "LeDisabled"
43 #endif
44
45 static bt_status_t adapter_status = BT_DEACTIVATED;
46 static bt_le_status_t adapter_le_status = BT_LE_DEACTIVATED;
47 static gboolean is_recovery_mode = FALSE;
48 static guint core_enable_timer_id;
49
50
51 static int bt_status_before[BT_MODE_MAX] = { VCONFKEY_BT_STATUS_OFF, };
52 static int bt_le_status_before[BT_MODE_MAX] = { VCONFKEY_BT_LE_STATUS_OFF, };
53
54 static int __bt_eventsystem_set_value(const char *event, const char *key, const char *value);
55
56 static void __bt_core_set_status(bt_status_t status)
57 {
58         adapter_status = status;
59 }
60
61 bt_status_t _bt_core_get_status(void)
62 {
63         return adapter_status;
64 }
65
66 static void __bt_core_set_le_status(bt_le_status_t status)
67 {
68         adapter_le_status = status;
69 }
70
71 bt_le_status_t _bt_core_get_le_status(void)
72 {
73         return adapter_le_status;
74 }
75
76 int _bt_core_get_bt_status(bt_mode_e mode)
77 {
78         return bt_status_before[mode];
79 }
80
81 int _bt_core_get_bt_le_status(bt_mode_e mode)
82 {
83         return bt_le_status_before[mode];
84 }
85
86 void _bt_core_set_bt_status(bt_mode_e mode, int status)
87 {
88         bt_status_before[mode] = status;
89 }
90
91 void _bt_core_set_bt_le_status(bt_mode_e mode, int status)
92 {
93         bt_le_status_before[mode] = status;
94 }
95
96 gboolean _bt_core_is_recovery_mode(void)
97 {
98         return is_recovery_mode;
99 }
100
101 static gboolean __bt_core_idle_terminate(gpointer data)
102 {
103         BT_DBG("+");
104         _bt_core_terminate();
105         return FALSE;
106 }
107
108 gboolean _bt_core_is_flight_mode_enabled(void)
109 {
110         int isFlightMode = 0;
111         int ret = -1;
112
113         if (TIZEN_FEATURE_FLIGHTMODE_ENABLED) {
114                 ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &isFlightMode);
115                 if (ret != 0)
116                         BT_ERR("vconf_get_bool failed");
117
118                 return isFlightMode;
119         } else {
120                 return FALSE;
121         }
122 }
123
124 #ifdef TIZEN_FEATURE_ACTD
125 static int __bt_call_systemact_service(const char *service_name)
126 {
127         int ret;
128
129         BT_DBG("Use System Activated : %s", service_name);
130
131         ret = actd_start_unit(UNIT_CONTROL_BUS_TYPE_SYSTEM, service_name, 5000);
132
133         if (ret != UNIT_CONTROL_OK) {
134                 BT_ERR("Failed to activate the %s: %d", service_name, ret);
135                 /* Return Success even if the activating result is fail */
136                 return 0;
137         }
138
139         return 0;
140 }
141 #else
142 static int __bt_call_systemact_service(const char *file_path)
143 {
144         BT_DBG("+");
145         FILE *fp;
146
147         if (!file_path) {
148                 BT_ERR("service file path is NULL");
149                 return -1;
150         }
151
152         if (!access(file_path, F_OK)) {
153                 remove(file_path);
154                 usleep(100);
155         }
156
157         fp = fopen(file_path, "w");
158         if (!fp) {
159                 BT_ERR("Failed to fopen service file");
160                 return -1;
161         }
162
163
164         fclose(fp);
165         BT_DBG("-");
166         return 0;
167
168 }
169 #endif
170
171 static int __execute_command(const char *cmd, char *const arg_list[])
172 {
173         int pid;
174         int pid2;
175         int status = 0;
176         BT_DBG("+");
177
178         pid = fork();
179         switch (pid) {
180         case -1:
181                 BT_ERR("fork failed");
182                 return -1;
183
184         case 0:
185                 pid2 = fork();
186                 if (pid2 == -1) {
187                         BT_ERR("fork failed");
188                 } else if (pid2 == 0) {
189                         if (arg_list != NULL) {
190                                 execv(cmd, arg_list);
191                         } else {
192                                 char *argv[] = { NULL };
193                                 execv(cmd, argv);
194                         }
195                         exit(256);
196                 }
197                 exit(0);
198                 break;
199
200         default:
201                 BT_DBG("parent : forked[%d]", pid);
202                 waitpid(pid, &status, 0);
203                 BT_DBG("child is terminated : %d", status);
204                 break;
205         }
206         BT_DBG("-");
207         return 0;
208 }
209
210 static int __bt_stack_up(void)
211 {
212         int ret;
213
214         /* activate HCI logger */
215         ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_LOGGER_START);
216         if (ret < 0) {
217                 BT_ERR("Failed to call systemact service");
218                 return -1;
219         }
220
221         /* activate Bluez */
222         ret = __bt_call_systemact_service(BT_SYSTEMACT_BLUEZ_START);
223         if (ret < 0) {
224                 BT_ERR("Failed to call systemact service");
225                 return -1;
226         }
227
228         /* activate bluetooth-share */
229         if (!TIZEN_PROFILE_WEARABLE) {
230                 ret = __bt_call_systemact_service(BT_SYSTEMACT_BLUETOOTH_SHARE_START);
231                 if (ret < 0) {
232                         BT_ERR("Failed to call systemact service");
233                         return -1;
234                 }
235         }
236
237         return 0;
238 }
239
240 int _bt_enable_adapter(void)
241 {
242         int ret;
243         bt_status_t status;
244 #if 0
245         bt_le_status_t le_status;
246 #endif
247         BT_INFO("");
248
249         status = _bt_core_get_status();
250         if (status != BT_DEACTIVATED) {
251                 BT_ERR("Invalid state %d", status);
252                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
253                 return -1;
254         }
255
256 #if 0 /* only the concept of private */
257         le_status = _bt_core_get_le_status();
258         if (le_status == BT_LE_ACTIVATED) {
259                 /* Turn on PSCAN, (ISCAN if needed) */
260                 /* Return with 0 for the Enabled response. */
261                 __bt_core_set_status(BT_ACTIVATED);
262                 BT_INFO("BR/EDR is enabled.");
263                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
264                 return 0;
265         }
266 #endif
267
268         __bt_core_set_status(BT_ACTIVATING);
269         if (TIZEN_FEATURE_BT_USB_DONGLE) {
270                 ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_UP);
271                 if (ret < 0)
272                         BT_ERR("Failed to call systemact service");
273         } else {
274                 ret = __bt_stack_up();
275         }
276         if (ret < 0) {
277                 BT_ERR("running script failed");
278                 if (TIZEN_FEATURE_BT_USB_DONGLE) {
279                         ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN);
280                         if (ret < 0)
281                                 BT_ERR("Failed to call systemact service");
282                 } else {
283                         ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh", NULL);
284                 }
285                 __bt_core_set_status(BT_DEACTIVATED);
286                 return -1;
287         }
288
289         return 0;
290 }
291
292 int _bt_disable_adapter(void)
293 {
294         bt_status_t status;
295 #if 0
296         bt_le_status_t le_status;
297 #endif
298
299         BT_INFO_C("Disable adapter");
300
301 #if 0 /* only the concept of private */
302         le_status = _bt_core_get_le_status();
303         BT_DBG("le_status : %d", le_status);
304         if (le_status == BT_LE_ACTIVATED) {
305                 /* Turn off PSCAN, (ISCAN if needed) */
306                 /* Return with 0 for the Disabled response. */
307                 __bt_core_set_status(BT_DEACTIVATED);
308                 BT_INFO("BR/EDR is disabled. now LE only mode");
309                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
310                 return 0;
311         }
312 #endif
313
314         status = _bt_core_get_status();
315         if (status == BT_ACTIVATING) {
316                 /* Forcely terminate */
317                 if (TIZEN_FEATURE_BT_USB_DONGLE) {
318                         if (__bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN) < 0)
319                                 BT_ERR("Failed to call systemact service");
320                 } else {
321 #ifdef TIZEN_FEATURE_RADIO
322                         int radio_status = VCONFKEY_RADIO_STATUS_OFF;
323
324                         /* Check if radio status on or off */
325                         if (vconf_get_int(VCONFKEY_RADIO_STATUS, &radio_status) < 0)
326                                 BT_ERR("Fail to get radio status");
327
328                         BT_DBG("Radio status: %d", radio_status);
329
330                         if (radio_status == VCONFKEY_RADIO_STATUS_ON) {
331                                 if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN_WITH_RADIO) < 0)
332                                         BT_ERR("running script failed");
333                         } else {
334                                 if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN) < 0)
335                                         BT_ERR("running script failed");
336                         }
337 #else
338                         if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN) < 0)
339                                 BT_ERR("running script failed");
340 #endif
341                 }
342                 _bt_core_terminate();
343                 return 0;
344         } else if (status != BT_ACTIVATED) {
345                 BT_ERR("Invalid state %d", status);
346                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
347         }
348
349         __bt_core_set_status(BT_DEACTIVATING);
350         if (TIZEN_FEATURE_BT_USB_DONGLE) {
351                 if (__bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN) < 0) {
352                         BT_ERR("Failed to call systemact service");
353                         __bt_core_set_status(BT_ACTIVATED);
354                         return -1;
355                 }
356                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
357         } else {
358 #ifdef TIZEN_FEATURE_RADIO
359                 int radio_status = VCONFKEY_RADIO_STATUS_OFF;
360
361                 /* Check if radio status on or off */
362                 if (vconf_get_int(VCONFKEY_RADIO_STATUS, &radio_status) < 0)
363                         BT_ERR("Fail to get radio status");
364
365                 BT_DBG("Radio status: %d", radio_status);
366
367                 if (radio_status == VCONFKEY_RADIO_STATUS_ON) {
368                         if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN_WITH_RADIO) < 0) {
369                                 BT_ERR("running script failed");
370                                 __bt_core_set_status(BT_ACTIVATED);
371                                 return -1;
372                         }
373                 } else {
374                         if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN) < 0) {
375                                 BT_ERR("running script failed");
376                                 __bt_core_set_status(BT_ACTIVATED);
377                                 return -1;
378                         }
379                 }
380 #else
381                 if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN) < 0) {
382                                 BT_ERR("running script failed");
383                                 __bt_core_set_status(BT_ACTIVATED);
384                                 return -1;
385                 }
386 #endif
387         }
388
389         return 0;
390 }
391
392 int _bt_enable_adapter_le(void)
393 {
394         BT_DBG("");
395
396         int ret;
397         bt_status_t status;
398         bt_le_status_t le_status;
399         le_status = _bt_core_get_le_status();
400         retv_if(le_status == BT_LE_ACTIVATED, 0);
401         retv_if(le_status != BT_LE_DEACTIVATED, -1);
402
403         status = _bt_core_get_status();
404         if (status == BT_DEACTIVATED) {
405                 __bt_core_set_le_status(BT_LE_ACTIVATING);
406                 BT_DBG("Activate BT");
407                 if (TIZEN_FEATURE_BT_USB_DONGLE) {
408                         ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_UP);
409                         if (ret < 0)
410                                 BT_ERR("Failed to call systemact service");
411                 } else {
412                         ret = __bt_stack_up();
413                 }
414                 if (ret < 0) {
415                         BT_ERR("running script failed");
416                         if (TIZEN_FEATURE_BT_USB_DONGLE) {
417                                 ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN);
418                                 if (ret < 0)
419                                         BT_ERR("Failed to call systemact service");
420                         } else {
421                                 ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh &", NULL);
422                         }
423                         __bt_core_set_status(BT_DEACTIVATED);
424                         __bt_core_set_le_status(BT_LE_DEACTIVATED);
425                         return -1;
426                 }
427         } else {
428                 __bt_core_set_le_status(BT_LE_ACTIVATED);
429                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
430         }
431 #ifdef TIZEN_FEATURE_BT_HPS
432         ret = _bt_core_start_httpproxy();
433         if (ret < 0)
434                 BT_ERR("_bt_core_start_httpproxy() failed");
435 #endif
436
437         return 0;
438 }
439
440 #ifdef TIZEN_FEATURE_BT_OTP
441 static void _bt_core_stop_otp()
442 {
443         GError *error = NULL;
444         GDBusMessage *msg = NULL;
445         GDBusConnection *conn = _bt_core_get_gdbus_connection();
446         msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, BLE_DISABLED);
447         if (!g_dbus_connection_send_message(conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
448                 if (error != NULL) {
449                         BT_ERR("Failed to send BLE_DISABLED signal to OTP : errCode[%x], \
450                                         message[%s]",
451                                         error->code, error->message);
452                         g_clear_error(&error);
453                 }
454         }
455 }
456 #endif
457
458 int _bt_disable_adapter_le(void)
459 {
460         BT_DBG("+");
461
462         bt_status_t status;
463         bt_le_status_t le_status;
464
465         le_status = _bt_core_get_le_status();
466         retv_if(le_status == BT_LE_DEACTIVATED, 0);
467         retv_if(le_status == BT_LE_DEACTIVATING, -1);
468
469 #ifdef TIZEN_FEATURE_BT_HPS
470         _bt_core_stop_httpproxy();
471 #endif
472
473 #ifdef TIZEN_FEATURE_BT_OTP
474         _bt_core_stop_otp();
475 #endif
476
477         status = _bt_core_get_status();
478         BT_DBG("status : %d", status);
479
480         if (status == BT_DEACTIVATED) {
481                 __bt_core_set_le_status(BT_LE_DEACTIVATING);
482                 int ret;
483                 if (TIZEN_FEATURE_BT_USB_DONGLE) {
484                         ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN);
485                         if (ret < 0)
486                                 BT_ERR("Failed to call systemact service");
487                 } else {
488                         ret = __execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL);
489                 }
490                 if (ret < 0) {
491                         BT_ERR("running script failed");
492                         __bt_core_set_le_status(BT_LE_ACTIVATED);
493                         return -1;
494                 }
495         } else {
496                         g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
497         }
498
499         __bt_core_set_le_status(BT_LE_DEACTIVATED);
500
501         BT_DBG("-");
502         return 0;
503 }
504
505 int _bt_core_service_request_adapter(int service_function)
506 {
507         int ret = -1;
508
509         GArray *in_param1 = NULL;
510         GArray *in_param2 = NULL;
511         GArray *in_param3 = NULL;
512         GArray *in_param4 = NULL;
513         GArray *out_param = NULL;
514
515         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
516
517         ret = _bt_core_service_request(BT_CORE_SERVICE, service_function,
518                         in_param1, in_param2, in_param3, in_param4, &out_param);
519         if (ret < 0)
520                 BT_ERR("_bt_core_service_request_adapter() failed");
521
522         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
523
524         return ret;
525 }
526
527 static gboolean __bt_core_check_the_adapter_path(void)
528 {
529         GError *err = NULL;
530         GDBusProxy *manager_proxy = NULL;
531         GVariant *result = NULL;
532         char *adapter_path = NULL;
533         GDBusConnection *conn = NULL;
534
535         conn = _bt_core_get_gdbus_connection();
536         if (conn == NULL)
537                 return FALSE;
538
539         manager_proxy =  g_dbus_proxy_new_sync(conn,
540                         G_DBUS_PROXY_FLAGS_NONE, NULL,
541                         "org.bluez",
542                         "/",
543                         "org.freedesktop.DBus.ObjectManager",
544                         NULL, &err);
545
546         if (!manager_proxy) {
547                 if (err != NULL) {
548                         BT_ERR("Unable to create proxy: %s", err->message);
549                         g_clear_error(&err);
550                 } else {
551                         BT_ERR("Fail to create proxy");
552                 }
553                 goto fail;
554         }
555
556         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
557                         G_DBUS_CALL_FLAGS_NONE, 1000, NULL, &err);
558         if (!result) {
559                 if (err != NULL) {
560                         BT_ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
561                         g_clear_error(&err);
562                 } else{
563                         BT_ERR("Fail to get DefaultAdapter");
564                 }
565                 goto fail;
566         }
567
568         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
569                 BT_ERR("Incorrect result\n");
570                 goto fail;
571         }
572
573         g_variant_get(result, "(&o)", &adapter_path);
574
575         if (adapter_path == NULL ||
576                 strlen(adapter_path) >= BT_CORE_CHECK_ADAPTER_OBJECT_PATH_MAX) {
577                 BT_ERR("Adapter path is inproper\n");
578                 goto fail;
579         }
580
581         g_variant_unref(result);
582         g_object_unref(manager_proxy);
583
584         return TRUE;
585
586 fail:
587         if (result)
588                 g_variant_unref(result);
589
590         if (manager_proxy)
591                 g_object_unref(manager_proxy);
592
593         return FALSE;
594 }
595
596 void _bt_core_update_status(void)
597 {
598         int bt_status = VCONFKEY_BT_STATUS_OFF;
599         int bt_le_status = VCONFKEY_BT_LE_STATUS_OFF;
600         gboolean ret = FALSE;
601
602         ret = __bt_core_check_the_adapter_path();
603         BT_INFO("check the real status of bt_adapter");
604
605         if (ret != TRUE) {
606                 __bt_core_set_status(BT_DEACTIVATED);
607                 __bt_core_set_le_status(BT_DEACTIVATED);
608         } else {
609                 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0)
610                         BT_ERR("no bluetooth device info, so BT was disabled at previous session");
611                 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status) < 0)
612                         BT_ERR("no bluetooth le info, so BT LE was disabled at previous session");
613
614                 BT_INFO("bt_status = %d, bt_le_status = %d", bt_status, bt_le_status);
615
616                 if (bt_status & VCONFKEY_BT_STATUS_ON)
617                         __bt_core_set_status(BT_ACTIVATED);
618                 if (bt_le_status & VCONFKEY_BT_LE_STATUS_ON)
619                         __bt_core_set_le_status(BT_ACTIVATED);
620         }
621 }
622
623 gboolean _bt_core_enable_adapter(void)
624 {
625         int ret;
626
627         _bt_set_flightmode_request(FALSE);
628         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
629                 BT_ERR("Set vconf failed");
630
631         ret = _bt_enable_adapter();
632         if (ret < 0)
633                 return FALSE;
634         else
635                 return TRUE;
636 }
637
638 static gboolean __bt_core_terminate_cb(gpointer data)
639 {
640         _bt_core_terminate();
641
642         return FALSE;
643 }
644
645 gboolean _bt_core_disable_adapter(void)
646 {
647         int ret;
648         gboolean adapter_state;
649
650         _bt_set_flightmode_request(FALSE);
651
652         adapter_state = __bt_core_check_the_adapter_path();
653         if (adapter_state == FALSE)
654                 BT_INFO("Default adapter is NOT normal.");
655
656         ret = _bt_disable_adapter();
657         if (adapter_state == FALSE) {
658                 g_timeout_add(BT_CORE_IDLE_TERM_TIME,
659                               __bt_core_terminate_cb, NULL);
660                 return TRUE;
661         } else {
662                 if (ret < 0)
663                         return FALSE;
664                 else
665                         return TRUE;
666         }
667 }
668
669 gboolean _bt_core_recover_adapter(void)
670 {
671         int ret;
672 #if 0
673         int ret_le;
674 #endif
675         BT_INFO_C("Recover bt adapter");
676
677         _bt_set_flightmode_request(FALSE);
678         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
679                 BT_ERR("Set vconf failed");
680
681         is_recovery_mode = TRUE;
682
683         _bt_core_update_status();
684
685         if (_bt_core_get_status() == BT_ACTIVATED) {
686                 _bt_core_set_bt_status(BT_RECOVERY_MODE, 1);
687 #ifdef TIZEN_FEATURE_BUSACT
688                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
689 #endif
690         }
691         if (_bt_core_get_le_status() == BT_LE_ACTIVATED) {
692                 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 1);
693 #ifdef TIZEN_FEATURE_BUSACT
694                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
695 #endif
696         }
697
698         ret = _bt_disable_adapter();
699         if (ret < 0)
700                 BT_ERR("_bt_disable_adapter() failed");
701
702 /* In platform, don't seperate BR/EDR and LE status */
703 #if 0
704         ret_le = _bt_disable_adapter_le();
705         if (ret_le < 0)
706                 BT_ERR("_bt_disable_adapter_le() failed");
707 #endif
708         return TRUE;
709 }
710
711 gboolean _bt_core_enable_adapter_le(void)
712 {
713         int ret;
714
715         ret = _bt_enable_adapter_le();
716         if (ret < 0)
717                 return FALSE;
718         else
719                 return TRUE;
720 }
721
722 gboolean _bt_core_disable_adapter_le(void)
723 {
724         BT_DBG("+");
725
726         int ret;
727
728         ret = _bt_disable_adapter_le();
729         if (ret < 0)
730                 return FALSE;
731         else
732                 return TRUE;
733 }
734
735 gboolean __bt_core_reset_adapter(void)
736 {
737         /* Forcely terminate */
738         if (__execute_command("/usr/etc/bluetooth/bt-reset-env.sh", NULL) < 0)
739                 BT_ERR("running script failed");
740
741         g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
742
743         return TRUE;
744 }
745
746 static gboolean __bt_core_enable_core_timeout_cb(gpointer data)
747 {
748         BT_DBG("+");
749
750         core_enable_timer_id = 0;
751
752         _bt_core_init_vconf_value();
753
754         return FALSE;
755 }
756
757 gboolean _bt_core_enable_core(void)
758 {
759         BT_DBG("+");
760
761         _bt_core_update_status();
762
763         if (core_enable_timer_id > 0)
764                 g_source_remove(core_enable_timer_id);
765
766         core_enable_timer_id = g_timeout_add(200, (GSourceFunc)__bt_core_enable_core_timeout_cb, NULL);
767
768         BT_DBG("-");
769         return TRUE;
770 }
771
772 gboolean _bt_core_set_transfer_value(gboolean value)
773 {
774         const char *event_val = NULL;
775         gboolean ret = TRUE;
776
777         BT_DBG("value: %d", value);
778
779         event_val = value ? EVT_VAL_BT_TRANSFERING : EVT_VAL_BT_NON_TRANSFERING;
780
781         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_TRANSFERING_STATE,
782                                                 event_val) != ES_R_OK) {
783                 BT_ERR("Fail to set BT state value");
784                 ret = FALSE;
785         }
786
787         if (ret == FALSE || value == FALSE) {
788                 BT_DBG("Terminate bt-core process");
789                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
790         }
791
792         BT_DBG("-");
793         return ret;
794 }
795
796 gboolean _bt_core_factory_test_mode(const char *type, const char *arg)
797 {
798         BT_DBG("Test item : %s", type);
799
800 #ifdef TIZEN_FEATURE_ACTD
801         if (g_strcmp0(type, "Enable_RF_Test") == 0) {
802                 __bt_call_systemact_service(BT_SYSTEMACT_EDUTM_ON);
803         } else if (g_strcmp0(type, "Disable_RF_Test") == 0) {
804                 __bt_call_systemact_service(BT_SYSTEMACT_EDUTM_OFF);
805         } else {
806                 BT_DBG("Terminate bt-core process");
807                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
808                 return FALSE;
809         }
810 #else
811         char *cmd = NULL;
812         char *arg_list[3] = { NULL, NULL, NULL };
813
814         if (g_strcmp0(type, "Enable_RF_Test") == 0) {
815                 cmd = "/usr/etc/bluetooth/bt-edutm-on.sh";
816                 arg_list[0] = "bt-edutm-on.sh";
817         } else if (g_strcmp0(type, "Disable_RF_Test") == 0) {
818                 cmd = "/usr/etc/bluetooth/bt-edutm-off.sh";
819                 arg_list[0] = "bt-edutm-off.sh";
820         } else if (g_strcmp0(type, "Slave_Mode") == 0) {
821                 cmd = "/usr/etc/bluetooth/bt-mode-slave.sh";
822                 arg_list[0] = "bt-mode-slave.sh";
823         } else if (g_strcmp0(type, "Master_Mode") == 0) {
824                 cmd = "/usr/etc/bluetooth/bt-mode-master.sh";
825                 arg_list[0] = "bt-mode-master.sh";
826         } else if (g_strcmp0(type, "SSP_Debug_Mode") == 0) {
827                 cmd = "/usr/etc/bluetooth/bt-set-ssp-debug-mode.sh";
828                 arg_list[0] = "bt-set-ssp-debug-mode.sh";
829                 arg_list[1] = (char *)arg;
830         } else if (g_strcmp0(type, "RF_Channel") == 0) {
831                 cmd = "/usr/etc/bluetooth/bt-enable-rf-channel.sh";
832                 arg_list[0] = "bt-enable-rf-channel.sh";
833                 arg_list[1] = (char *)arg;
834         } else {
835                 return FALSE;
836         }
837
838         BT_DBG("Run %s", cmd);
839         if (__execute_command(cmd, arg_list) < 0)
840                 BT_ERR("running script failed");
841 #endif
842
843         return TRUE;
844 }
845
846 static gboolean __bt_core_recovery_cb(gpointer data)
847 {
848         int ret = 0;
849         gboolean is_request_failed = FALSE;
850         static gboolean is_first_failure = TRUE;
851
852         BT_DBG("+");
853
854         if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
855                 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
856                 if (ret < 0)
857                         is_request_failed = TRUE;
858         }
859
860         if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
861                 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
862                 if (ret < 0)
863                         is_request_failed = TRUE;
864         }
865
866         if (is_request_failed == TRUE) {
867                 BT_ERR("Recovery is failed.");
868                 if (is_first_failure == TRUE) {
869                         g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
870                         is_first_failure = FALSE;
871                         return FALSE;
872                 } else {
873                         is_first_failure = TRUE;
874                         return FALSE;
875                 }
876         } else
877                 is_first_failure = TRUE;
878
879         if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
880                 _bt_core_set_bt_status(BT_RECOVERY_MODE, 0);
881                 ret = _bt_enable_adapter();
882                 if (ret < 0)
883                         BT_ERR("_bt_enable_adapter() failed");
884         }
885
886 #if 0
887         if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
888                 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 0);
889                 ret = _bt_enable_adapter_le();
890                 if (ret < 0)
891                         BT_ERR("_bt_enable_adapter_le() failed");
892         }
893 #endif
894         is_recovery_mode = FALSE;
895
896         BT_DBG("-");
897
898         return FALSE;
899 }
900
901 static gboolean __bt_core_enable_timeout_cb(gpointer data)
902 {
903         bt_status_t adapter_status;
904         bt_le_status_t adapter_status_le;
905
906         BT_DBG("");
907
908         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
909                 BT_ERR("Set vconf failed");
910
911         adapter_status = _bt_core_get_status();
912         adapter_status_le = _bt_core_get_le_status();
913
914         if (adapter_status == BT_DEACTIVATED &&
915                         _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) {
916                 _bt_core_set_bt_status(BT_FLIGHT_MODE, 0);
917                 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
918                 _bt_enable_adapter();
919         }
920
921         if (adapter_status_le == BT_LE_DEACTIVATED &&
922                         _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) {
923                 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0);
924                 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
925                 _bt_enable_adapter_le();
926         }
927
928         return FALSE;
929 }
930
931 static gboolean __bt_core_disable_timeout_cb(gpointer data)
932 {
933         bt_status_t adapter_status;
934         bt_le_status_t adapter_status_le;
935
936         BT_DBG("");
937
938         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
939                 BT_ERR("Set vconf failed");
940
941         adapter_status = _bt_core_get_status();
942         adapter_status_le = _bt_core_get_le_status();
943
944         if (adapter_status == BT_ACTIVATED) {
945                 int bt_status_before_mode = 0;
946
947                 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0)
948                         _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode);
949
950 #ifdef TIZEN_FEATURE_BUSACT
951                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
952 #endif
953                 _bt_disable_adapter();
954         }
955
956         if (adapter_status_le == BT_LE_ACTIVATED) {
957                 int bt_le_status_before_mode = 0;
958
959                 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0)
960                         _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode);
961
962 #ifdef TIZEN_FEATURE_BUSACT
963                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
964 #endif
965                 _bt_disable_adapter_le();
966         }
967
968         return FALSE;
969 }
970
971 static int __bt_eventsystem_set_value(const char *event, const char *key, const char *value)
972 {
973         int ret;
974         bundle *b = NULL;
975
976         b = bundle_create();
977
978         bundle_add_str(b, key, value);
979
980         ret = eventsystem_send_system_event(event, b);
981
982         BT_DBG("eventsystem_send_system_event result: %d", ret);
983
984         bundle_free(b);
985
986         return ret;
987 }
988
989 void _bt_core_adapter_added_cb(void)
990 {
991         bt_status_t status;
992         bt_le_status_t le_status;
993         gboolean flight_mode_status;
994
995         BT_DBG("");
996
997         status = _bt_core_get_status();
998         BT_DBG("status : %d", status);
999         le_status = _bt_core_get_le_status();
1000         BT_DBG("le_status : %d", le_status);
1001
1002         if (status == BT_ACTIVATING)
1003                 __bt_core_set_status(BT_ACTIVATED);
1004         if (le_status == BT_LE_ACTIVATING)
1005                 __bt_core_set_le_status(BT_LE_ACTIVATED);
1006
1007         flight_mode_status = _bt_core_is_flight_mode_enabled();
1008
1009         if (flight_mode_status == TRUE && _bt_is_flightmode_request() == TRUE) {
1010                 _bt_set_flightmode_request(FALSE);
1011                 g_timeout_add(2000, (GSourceFunc)__bt_core_disable_timeout_cb, NULL);
1012                 return;
1013         }
1014         _bt_set_flightmode_request(FALSE);
1015
1016         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
1017                                                 EVT_VAL_BT_ON) != ES_R_OK)
1018                 BT_ERR("Fail to set BT state value");
1019
1020         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
1021                                                 EVT_VAL_BT_LE_ON) != ES_R_OK)
1022                 BT_ERR("Fail to set BT LE state value");
1023
1024         _bt_core_terminate();
1025 }
1026
1027 void _bt_core_adapter_removed_cb(void)
1028 {
1029         int flight_mode_value = 0;
1030         int power_saving_mode = 0;
1031         gboolean flight_mode_status;
1032         static int timer_id = -1;
1033
1034         BT_DBG("is_recovery_mode: %d", is_recovery_mode);
1035
1036         __bt_core_set_status(BT_DEACTIVATED);
1037         __bt_core_set_le_status(BT_LE_DEACTIVATED);
1038         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
1039                 BT_ERR("Set vconf failed");
1040         if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0)
1041                 BT_ERR("Set vconf failed");
1042
1043         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
1044                                                 EVT_VAL_BT_OFF) != ES_R_OK)
1045                 BT_ERR("Fail to set value");
1046
1047         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
1048                                                 EVT_VAL_BT_LE_OFF) != ES_R_OK)
1049                 BT_ERR("Fail to set value");
1050
1051         if (is_recovery_mode == TRUE) {
1052                 if (timer_id < 0)
1053                         timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
1054                 return;
1055         }
1056
1057         if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value) != 0)
1058                 BT_ERR("Fail to get the flight_mode_deactivated value");
1059
1060         if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &power_saving_mode) != 0)
1061                 BT_ERR("Fail to get the ps_mode_deactivated value");
1062
1063         flight_mode_status = _bt_core_is_flight_mode_enabled();
1064
1065         if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
1066                 _bt_set_flightmode_request(FALSE);
1067                 if (timer_id < 0)
1068                         timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_enable_timeout_cb, NULL);
1069                 return;
1070         }
1071         _bt_set_flightmode_request(FALSE);
1072
1073         if (flight_mode_value == 1 || power_saving_mode == 1) {
1074                 BT_DBG("Bt Core not terminated");
1075                 return;
1076         }
1077
1078         _bt_core_terminate();
1079 }