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