Fix the instance id's miss-matching issue
[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         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
652                 BT_ERR("Set vconf failed");
653
654         adapter_state = __bt_core_check_the_adapter_path();
655         if (adapter_state == FALSE)
656                 BT_INFO("Default adapter is NOT normal.");
657
658         ret = _bt_disable_adapter();
659         if (adapter_state == FALSE) {
660                 g_timeout_add(BT_CORE_IDLE_TERM_TIME,
661                               __bt_core_terminate_cb, NULL);
662                 return TRUE;
663         } else {
664                 if (ret < 0)
665                         return FALSE;
666                 else
667                         return TRUE;
668         }
669 }
670
671 gboolean _bt_core_recover_adapter(void)
672 {
673         int ret;
674 #if 0
675         int ret_le;
676 #endif
677         BT_INFO_C("Recover bt adapter");
678
679         _bt_set_flightmode_request(FALSE);
680         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
681                 BT_ERR("Set vconf failed");
682
683         is_recovery_mode = TRUE;
684
685         _bt_core_update_status();
686
687         if (_bt_core_get_status() == BT_ACTIVATED) {
688                 _bt_core_set_bt_status(BT_RECOVERY_MODE, 1);
689 #ifdef TIZEN_FEATURE_BUSACT
690                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
691 #endif
692         }
693         if (_bt_core_get_le_status() == BT_LE_ACTIVATED) {
694                 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 1);
695 #ifdef TIZEN_FEATURE_BUSACT
696                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
697 #endif
698         }
699
700         ret = _bt_disable_adapter();
701         if (ret < 0)
702                 BT_ERR("_bt_disable_adapter() failed");
703
704 /* In platform, don't seperate BR/EDR and LE status */
705 #if 0
706         ret_le = _bt_disable_adapter_le();
707         if (ret_le < 0)
708                 BT_ERR("_bt_disable_adapter_le() failed");
709 #endif
710         return TRUE;
711 }
712
713 gboolean _bt_core_enable_adapter_le(void)
714 {
715         int ret;
716
717         ret = _bt_enable_adapter_le();
718         if (ret < 0)
719                 return FALSE;
720         else
721                 return TRUE;
722 }
723
724 gboolean _bt_core_disable_adapter_le(void)
725 {
726         BT_DBG("+");
727
728         int ret;
729
730         ret = _bt_disable_adapter_le();
731         if (ret < 0)
732                 return FALSE;
733         else
734                 return TRUE;
735 }
736
737 gboolean __bt_core_reset_adapter(void)
738 {
739         /* Forcely terminate */
740         if (__execute_command("/usr/etc/bluetooth/bt-reset-env.sh", NULL) < 0)
741                 BT_ERR("running script failed");
742
743         g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
744
745         return TRUE;
746 }
747
748 static gboolean __bt_core_enable_core_timeout_cb(gpointer data)
749 {
750         BT_DBG("+");
751
752         core_enable_timer_id = 0;
753
754         _bt_core_init_vconf_value();
755
756         return FALSE;
757 }
758
759 gboolean _bt_core_enable_core(void)
760 {
761         BT_DBG("+");
762
763         _bt_core_update_status();
764
765         if (core_enable_timer_id > 0)
766                 g_source_remove(core_enable_timer_id);
767
768         core_enable_timer_id = g_timeout_add(200, (GSourceFunc)__bt_core_enable_core_timeout_cb, NULL);
769
770         BT_DBG("-");
771         return TRUE;
772 }
773
774 gboolean _bt_core_set_transfer_value(gboolean value)
775 {
776         const char *event_val = NULL;
777         gboolean ret = TRUE;
778
779         BT_DBG("value: %d", value);
780
781         event_val = value ? EVT_VAL_BT_TRANSFERING : EVT_VAL_BT_NON_TRANSFERING;
782
783         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_TRANSFERING_STATE,
784                                                 event_val) != ES_R_OK) {
785                 BT_ERR("Fail to set BT state value");
786                 ret = FALSE;
787         }
788
789         if (ret == FALSE || value == FALSE) {
790                 BT_DBG("Terminate bt-core process");
791                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
792         }
793
794         BT_DBG("-");
795         return ret;
796 }
797
798 gboolean _bt_core_factory_test_mode(const char *type, const char *arg)
799 {
800         BT_DBG("Test item : %s", type);
801
802 #ifdef TIZEN_FEATURE_ACTD
803         if (g_strcmp0(type, "Enable_RF_Test") == 0) {
804                 __bt_call_systemact_service(BT_SYSTEMACT_EDUTM_ON);
805         } else if (g_strcmp0(type, "Disable_RF_Test") == 0) {
806                 __bt_call_systemact_service(BT_SYSTEMACT_EDUTM_OFF);
807         } else {
808                 BT_DBG("Terminate bt-core process");
809                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
810                 return FALSE;
811         }
812 #else
813         char *cmd = NULL;
814         char *arg_list[3] = { NULL, NULL, NULL };
815
816         if (g_strcmp0(type, "Enable_RF_Test") == 0) {
817                 cmd = "/usr/etc/bluetooth/bt-edutm-on.sh";
818                 arg_list[0] = "bt-edutm-on.sh";
819         } else if (g_strcmp0(type, "Disable_RF_Test") == 0) {
820                 cmd = "/usr/etc/bluetooth/bt-edutm-off.sh";
821                 arg_list[0] = "bt-edutm-off.sh";
822         } else if (g_strcmp0(type, "Slave_Mode") == 0) {
823                 cmd = "/usr/etc/bluetooth/bt-mode-slave.sh";
824                 arg_list[0] = "bt-mode-slave.sh";
825         } else if (g_strcmp0(type, "Master_Mode") == 0) {
826                 cmd = "/usr/etc/bluetooth/bt-mode-master.sh";
827                 arg_list[0] = "bt-mode-master.sh";
828         } else if (g_strcmp0(type, "SSP_Debug_Mode") == 0) {
829                 cmd = "/usr/etc/bluetooth/bt-set-ssp-debug-mode.sh";
830                 arg_list[0] = "bt-set-ssp-debug-mode.sh";
831                 arg_list[1] = (char *)arg;
832         } else if (g_strcmp0(type, "RF_Channel") == 0) {
833                 cmd = "/usr/etc/bluetooth/bt-enable-rf-channel.sh";
834                 arg_list[0] = "bt-enable-rf-channel.sh";
835                 arg_list[1] = (char *)arg;
836         } else {
837                 return FALSE;
838         }
839
840         BT_DBG("Run %s", cmd);
841         if (__execute_command(cmd, arg_list) < 0)
842                 BT_ERR("running script failed");
843 #endif
844
845         return TRUE;
846 }
847
848 static gboolean __bt_core_recovery_cb(gpointer data)
849 {
850         int ret = 0;
851         gboolean is_request_failed = FALSE;
852         static gboolean is_first_failure = TRUE;
853
854         BT_DBG("+");
855
856         if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
857                 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
858                 if (ret < 0)
859                         is_request_failed = TRUE;
860         }
861
862         if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
863                 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
864                 if (ret < 0)
865                         is_request_failed = TRUE;
866         }
867
868         if (is_request_failed == TRUE) {
869                 BT_ERR("Recovery is failed.");
870                 if (is_first_failure == TRUE) {
871                         g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
872                         is_first_failure = FALSE;
873                         return FALSE;
874                 } else {
875                         is_first_failure = TRUE;
876                         return FALSE;
877                 }
878         } else
879                 is_first_failure = TRUE;
880
881         if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
882                 _bt_core_set_bt_status(BT_RECOVERY_MODE, 0);
883                 ret = _bt_enable_adapter();
884                 if (ret < 0)
885                         BT_ERR("_bt_enable_adapter() failed");
886         }
887
888 #if 0
889         if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
890                 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 0);
891                 ret = _bt_enable_adapter_le();
892                 if (ret < 0)
893                         BT_ERR("_bt_enable_adapter_le() failed");
894         }
895 #endif
896         is_recovery_mode = FALSE;
897
898         BT_DBG("-");
899
900         return FALSE;
901 }
902
903 static gboolean __bt_core_enable_timeout_cb(gpointer data)
904 {
905         bt_status_t adapter_status;
906         bt_le_status_t adapter_status_le;
907
908         BT_DBG("");
909
910         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
911                 BT_ERR("Set vconf failed");
912
913         adapter_status = _bt_core_get_status();
914         adapter_status_le = _bt_core_get_le_status();
915
916         if (adapter_status == BT_DEACTIVATED &&
917                         _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) {
918                 _bt_core_set_bt_status(BT_FLIGHT_MODE, 0);
919                 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
920                 _bt_enable_adapter();
921         }
922
923         if (adapter_status_le == BT_LE_DEACTIVATED &&
924                         _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) {
925                 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0);
926                 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
927                 _bt_enable_adapter_le();
928         }
929
930         return FALSE;
931 }
932
933 static gboolean __bt_core_disable_timeout_cb(gpointer data)
934 {
935         bt_status_t adapter_status;
936         bt_le_status_t adapter_status_le;
937
938         BT_DBG("");
939
940         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
941                 BT_ERR("Set vconf failed");
942
943         adapter_status = _bt_core_get_status();
944         adapter_status_le = _bt_core_get_le_status();
945
946         if (adapter_status == BT_ACTIVATED) {
947                 int bt_status_before_mode = 0;
948
949                 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0)
950                         _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode);
951
952 #ifdef TIZEN_FEATURE_BUSACT
953                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
954 #endif
955                 _bt_disable_adapter();
956         }
957
958         if (adapter_status_le == BT_LE_ACTIVATED) {
959                 int bt_le_status_before_mode = 0;
960
961                 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0)
962                         _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode);
963
964 #ifdef TIZEN_FEATURE_BUSACT
965                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
966 #endif
967                 _bt_disable_adapter_le();
968         }
969
970         return FALSE;
971 }
972
973 static int __bt_eventsystem_set_value(const char *event, const char *key, const char *value)
974 {
975         int ret;
976         bundle *b = NULL;
977
978         b = bundle_create();
979
980         bundle_add_str(b, key, value);
981
982         ret = eventsystem_send_system_event(event, b);
983
984         BT_DBG("eventsystem_send_system_event result: %d", ret);
985
986         bundle_free(b);
987
988         return ret;
989 }
990
991 void _bt_core_adapter_added_cb(void)
992 {
993         bt_status_t status;
994         bt_le_status_t le_status;
995         gboolean flight_mode_status;
996
997         BT_DBG("");
998
999         status = _bt_core_get_status();
1000         BT_DBG("status : %d", status);
1001         le_status = _bt_core_get_le_status();
1002         BT_DBG("le_status : %d", le_status);
1003
1004         if (status == BT_ACTIVATING)
1005                 __bt_core_set_status(BT_ACTIVATED);
1006         if (le_status == BT_LE_ACTIVATING)
1007                 __bt_core_set_le_status(BT_LE_ACTIVATED);
1008
1009         flight_mode_status = _bt_core_is_flight_mode_enabled();
1010
1011         if (flight_mode_status == TRUE && _bt_is_flightmode_request() == TRUE) {
1012                 _bt_set_flightmode_request(FALSE);
1013                 g_timeout_add(2000, (GSourceFunc)__bt_core_disable_timeout_cb, NULL);
1014                 return;
1015         }
1016         _bt_set_flightmode_request(FALSE);
1017
1018         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
1019                                                 EVT_VAL_BT_ON) != ES_R_OK)
1020                 BT_ERR("Fail to set BT state value");
1021
1022         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
1023                                                 EVT_VAL_BT_LE_ON) != ES_R_OK)
1024                 BT_ERR("Fail to set BT LE state value");
1025
1026         _bt_core_terminate();
1027 }
1028
1029 void _bt_core_adapter_removed_cb(void)
1030 {
1031         int flight_mode_value = 0;
1032         int power_saving_mode = 0;
1033         gboolean flight_mode_status;
1034         static int timer_id = -1;
1035
1036         BT_DBG("is_recovery_mode: %d", is_recovery_mode);
1037
1038         __bt_core_set_status(BT_DEACTIVATED);
1039         __bt_core_set_le_status(BT_LE_DEACTIVATED);
1040         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
1041                 BT_ERR("Set vconf failed");
1042         if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0)
1043                 BT_ERR("Set vconf failed");
1044
1045         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
1046                                                 EVT_VAL_BT_OFF) != ES_R_OK)
1047                 BT_ERR("Fail to set value");
1048
1049         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
1050                                                 EVT_VAL_BT_LE_OFF) != ES_R_OK)
1051                 BT_ERR("Fail to set value");
1052
1053         if (is_recovery_mode == TRUE) {
1054                 if (timer_id < 0)
1055                         timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
1056                 return;
1057         }
1058
1059         if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value) != 0)
1060                 BT_ERR("Fail to get the flight_mode_deactivated value");
1061
1062         if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &power_saving_mode) != 0)
1063                 BT_ERR("Fail to get the ps_mode_deactivated value");
1064
1065         flight_mode_status = _bt_core_is_flight_mode_enabled();
1066
1067         if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
1068                 _bt_set_flightmode_request(FALSE);
1069                 if (timer_id < 0)
1070                         timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_enable_timeout_cb, NULL);
1071                 return;
1072         }
1073         _bt_set_flightmode_request(FALSE);
1074
1075         if (flight_mode_value == 1 || power_saving_mode == 1) {
1076                 BT_DBG("Bt Core not terminated");
1077                 return;
1078         }
1079
1080         _bt_core_terminate();
1081 }