Fix the AVRCP path miss-matching problem
[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         int ret;
799         BT_DBG("Test item : %s", type);
800
801 #ifdef TIZEN_FEATURE_ACTD
802         if (g_strcmp0(type, "Enable_RF_Test") == 0) {
803                 ret = __bt_call_systemact_service(BT_SYSTEMACT_EDUTM_ON);
804                 if (ret < 0)
805                         BT_ERR("Failed to call systemact service");
806         } else if (g_strcmp0(type, "Disable_RF_Test") == 0) {
807                 ret = __bt_call_systemact_service(BT_SYSTEMACT_EDUTM_OFF);
808                 if (ret < 0)
809                         BT_ERR("Failed to call systemact service");
810         } else {
811                 BT_DBG("Terminate bt-core process");
812                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
813                 return FALSE;
814         }
815 #else
816         char *cmd = NULL;
817         char *arg_list[3] = { NULL, NULL, NULL };
818
819         if (g_strcmp0(type, "Enable_RF_Test") == 0) {
820                 cmd = "/usr/etc/bluetooth/bt-edutm-on.sh";
821                 arg_list[0] = "bt-edutm-on.sh";
822         } else if (g_strcmp0(type, "Disable_RF_Test") == 0) {
823                 cmd = "/usr/etc/bluetooth/bt-edutm-off.sh";
824                 arg_list[0] = "bt-edutm-off.sh";
825         } else if (g_strcmp0(type, "Slave_Mode") == 0) {
826                 cmd = "/usr/etc/bluetooth/bt-mode-slave.sh";
827                 arg_list[0] = "bt-mode-slave.sh";
828         } else if (g_strcmp0(type, "Master_Mode") == 0) {
829                 cmd = "/usr/etc/bluetooth/bt-mode-master.sh";
830                 arg_list[0] = "bt-mode-master.sh";
831         } else if (g_strcmp0(type, "SSP_Debug_Mode") == 0) {
832                 cmd = "/usr/etc/bluetooth/bt-set-ssp-debug-mode.sh";
833                 arg_list[0] = "bt-set-ssp-debug-mode.sh";
834                 arg_list[1] = (char *)arg;
835         } else if (g_strcmp0(type, "RF_Channel") == 0) {
836                 cmd = "/usr/etc/bluetooth/bt-enable-rf-channel.sh";
837                 arg_list[0] = "bt-enable-rf-channel.sh";
838                 arg_list[1] = (char *)arg;
839         } else {
840                 return FALSE;
841         }
842
843         BT_DBG("Run %s", cmd);
844         if (__execute_command(cmd, arg_list) < 0)
845                 BT_ERR("running script failed");
846 #endif
847
848         return TRUE;
849 }
850
851 static gboolean __bt_core_recovery_cb(gpointer data)
852 {
853         int ret = 0;
854         gboolean is_request_failed = FALSE;
855         static gboolean is_first_failure = TRUE;
856
857         BT_DBG("+");
858
859         if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
860                 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
861                 if (ret < 0)
862                         is_request_failed = TRUE;
863         }
864
865         if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
866                 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
867                 if (ret < 0)
868                         is_request_failed = TRUE;
869         }
870
871         if (is_request_failed == TRUE) {
872                 BT_ERR("Recovery is failed.");
873                 if (is_first_failure == TRUE) {
874                         g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
875                         is_first_failure = FALSE;
876                         return FALSE;
877                 } else {
878                         is_first_failure = TRUE;
879                         return FALSE;
880                 }
881         } else
882                 is_first_failure = TRUE;
883
884         if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
885                 _bt_core_set_bt_status(BT_RECOVERY_MODE, 0);
886                 ret = _bt_enable_adapter();
887                 if (ret < 0)
888                         BT_ERR("_bt_enable_adapter() failed");
889         }
890
891 #if 0
892         if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
893                 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 0);
894                 ret = _bt_enable_adapter_le();
895                 if (ret < 0)
896                         BT_ERR("_bt_enable_adapter_le() failed");
897         }
898 #endif
899         is_recovery_mode = FALSE;
900
901         BT_DBG("-");
902
903         return FALSE;
904 }
905
906 static gboolean __bt_core_enable_timeout_cb(gpointer data)
907 {
908         bt_status_t adapter_status;
909         bt_le_status_t adapter_status_le;
910
911         BT_DBG("");
912
913         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
914                 BT_ERR("Set vconf failed");
915
916         adapter_status = _bt_core_get_status();
917         adapter_status_le = _bt_core_get_le_status();
918
919         if (adapter_status == BT_DEACTIVATED &&
920                         _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) {
921                 _bt_core_set_bt_status(BT_FLIGHT_MODE, 0);
922                 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
923                 _bt_enable_adapter();
924         }
925
926         if (adapter_status_le == BT_LE_DEACTIVATED &&
927                         _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) {
928                 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0);
929                 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
930                 _bt_enable_adapter_le();
931         }
932
933         return FALSE;
934 }
935
936 static gboolean __bt_core_disable_timeout_cb(gpointer data)
937 {
938         bt_status_t adapter_status;
939         bt_le_status_t adapter_status_le;
940
941         BT_DBG("");
942
943         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
944                 BT_ERR("Set vconf failed");
945
946         adapter_status = _bt_core_get_status();
947         adapter_status_le = _bt_core_get_le_status();
948
949         if (adapter_status == BT_ACTIVATED) {
950                 int bt_status_before_mode = 0;
951
952                 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0)
953                         _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode);
954
955 #ifdef TIZEN_FEATURE_BUSACT
956                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
957 #endif
958                 _bt_disable_adapter();
959         }
960
961         if (adapter_status_le == BT_LE_ACTIVATED) {
962                 int bt_le_status_before_mode = 0;
963
964                 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0)
965                         _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode);
966
967 #ifdef TIZEN_FEATURE_BUSACT
968                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
969 #endif
970                 _bt_disable_adapter_le();
971         }
972
973         return FALSE;
974 }
975
976 static int __bt_eventsystem_set_value(const char *event, const char *key, const char *value)
977 {
978         int ret;
979         bundle *b = NULL;
980
981         b = bundle_create();
982
983         bundle_add_str(b, key, value);
984
985         ret = eventsystem_send_system_event(event, b);
986
987         BT_DBG("eventsystem_send_system_event result: %d", ret);
988
989         bundle_free(b);
990
991         return ret;
992 }
993
994 void _bt_core_adapter_added_cb(void)
995 {
996         bt_status_t status;
997         bt_le_status_t le_status;
998         gboolean flight_mode_status;
999
1000         BT_DBG("");
1001
1002         status = _bt_core_get_status();
1003         BT_DBG("status : %d", status);
1004         le_status = _bt_core_get_le_status();
1005         BT_DBG("le_status : %d", le_status);
1006
1007         if (status == BT_ACTIVATING)
1008                 __bt_core_set_status(BT_ACTIVATED);
1009         if (le_status == BT_LE_ACTIVATING)
1010                 __bt_core_set_le_status(BT_LE_ACTIVATED);
1011
1012         flight_mode_status = _bt_core_is_flight_mode_enabled();
1013
1014         if (flight_mode_status == TRUE && _bt_is_flightmode_request() == TRUE) {
1015                 _bt_set_flightmode_request(FALSE);
1016                 g_timeout_add(2000, (GSourceFunc)__bt_core_disable_timeout_cb, NULL);
1017                 return;
1018         }
1019         _bt_set_flightmode_request(FALSE);
1020
1021         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
1022                                                 EVT_VAL_BT_ON) != ES_R_OK)
1023                 BT_ERR("Fail to set BT state value");
1024
1025         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
1026                                                 EVT_VAL_BT_LE_ON) != ES_R_OK)
1027                 BT_ERR("Fail to set BT LE state value");
1028
1029         _bt_core_terminate();
1030 }
1031
1032 void _bt_core_adapter_removed_cb(void)
1033 {
1034         int flight_mode_value = 0;
1035         int power_saving_mode = 0;
1036         gboolean flight_mode_status;
1037         static int timer_id = -1;
1038
1039         BT_DBG("is_recovery_mode: %d", is_recovery_mode);
1040
1041         __bt_core_set_status(BT_DEACTIVATED);
1042         __bt_core_set_le_status(BT_LE_DEACTIVATED);
1043         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
1044                 BT_ERR("Set vconf failed");
1045         if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0)
1046                 BT_ERR("Set vconf failed");
1047
1048         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
1049                                                 EVT_VAL_BT_OFF) != ES_R_OK)
1050                 BT_ERR("Fail to set value");
1051
1052         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
1053                                                 EVT_VAL_BT_LE_OFF) != ES_R_OK)
1054                 BT_ERR("Fail to set value");
1055
1056         if (is_recovery_mode == TRUE) {
1057                 if (timer_id < 0)
1058                         timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
1059                 return;
1060         }
1061
1062         if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value) != 0)
1063                 BT_ERR("Fail to get the flight_mode_deactivated value");
1064
1065         if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &power_saving_mode) != 0)
1066                 BT_ERR("Fail to get the ps_mode_deactivated value");
1067
1068         flight_mode_status = _bt_core_is_flight_mode_enabled();
1069
1070         if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
1071                 _bt_set_flightmode_request(FALSE);
1072                 if (timer_id < 0)
1073                         timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_enable_timeout_cb, NULL);
1074                 return;
1075         }
1076         _bt_set_flightmode_request(FALSE);
1077
1078         if (flight_mode_value == 1 || power_saving_mode == 1) {
1079                 BT_DBG("Bt Core not terminated");
1080                 return;
1081         }
1082
1083         _bt_core_terminate();
1084 }