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