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