4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Girishashok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
25 #include <vconf-keys.h>
27 #include "bt-core-main.h"
28 #include "bt-core-adapter.h"
29 #include "bt-core-common.h"
30 #include "bt-core-dbus-handler.h"
31 #include "bt-core-noti-handler.h"
33 static bt_status_t adapter_status = BT_DEACTIVATED;
34 static bt_le_status_t adapter_le_status = BT_LE_DEACTIVATED;
35 static gboolean is_recovery_mode = FALSE;
37 static int bt_status_before[BT_MODE_MAX] = { VCONFKEY_BT_STATUS_OFF, };
38 static int bt_le_status_before[BT_MODE_MAX] = { 0, };
40 static void __bt_core_set_status(bt_status_t status)
42 adapter_status = status;
45 bt_status_t _bt_core_get_status(void)
47 return adapter_status;
50 static void __bt_core_set_le_status(bt_le_status_t status)
52 adapter_le_status = status;
55 bt_le_status_t _bt_core_get_le_status(void)
57 return adapter_le_status;
60 int _bt_core_get_bt_status(bt_mode_e mode)
62 return bt_status_before[mode];
65 int _bt_core_get_bt_le_status(bt_mode_e mode)
67 return bt_le_status_before[mode];
70 void _bt_core_set_bt_status(bt_mode_e mode, int status)
72 bt_status_before[mode] = status;
75 void _bt_core_set_bt_le_status(bt_mode_e mode, int status)
77 bt_le_status_before[mode] = status;
80 gboolean _bt_core_is_recovery_mode(void)
82 return is_recovery_mode;
85 gboolean _bt_core_is_flight_mode_enabled(void)
87 #ifdef TIZEN_TELEPHONY_ENABLED
91 ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &isFlightMode);
93 BT_ERR("vconf_get_bool failed");
101 static gboolean bt_core_enable_adapter(BtCore *agent,
102 DBusGMethodInvocation *context);
104 static gboolean bt_core_disable_adapter(BtCore *agent,
105 DBusGMethodInvocation *context);
107 static gboolean bt_core_recover_adapter(BtCore *agent,
108 DBusGMethodInvocation *context);
110 static gboolean bt_core_enable_adapter_le(BtCore *agent,
111 DBusGMethodInvocation *context);
113 static gboolean bt_core_disable_adapter_le(BtCore *agent,
114 DBusGMethodInvocation *context);
116 static gboolean bt_core_reset_adapter(BtCore *agent,
117 DBusGMethodInvocation *context);
119 static gboolean bt_core_enable_core(BtCore *agent,
120 DBusGMethodInvocation *context);
122 static int __execute_command(const char *cmd, char *const arg_list[]);
124 #include "bt-core-adapter-method.h"
127 G_DEFINE_TYPE(BtCore, bt_core, G_TYPE_OBJECT);
129 /*This is part of platform provided code skeleton for client server model*/
130 static void bt_core_class_init (BtCoreClass *bt_core_class)
132 dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(bt_core_class),
133 &dbus_glib_bt_core_object_info);
136 /*This is part of platform provided code skeleton for client server model*/
137 static void bt_core_init (BtCore *core)
142 BT_CORE_ERROR_REJECT,
143 BT_CORE_ERROR_CANCEL,
144 BT_CORE_ERROR_TIMEOUT,
147 #define BT_CORE_ERROR (bt_core_error_quark())
149 static GQuark bt_core_error_quark(void)
151 static GQuark quark = 0;
153 quark = g_quark_from_static_string("BtCore");
158 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
160 static GError *bt_core_error(BtCoreError error, const char *err_msg)
162 return g_error_new(BT_CORE_ERROR, error, err_msg, NULL);
165 static int __execute_command(const char *cmd, char *const arg_list[])
175 BT_ERR("fork failed");
181 BT_ERR("fork failed");
182 } else if (pid2 == 0) {
183 execv(cmd, arg_list);
190 BT_DBG("parent : forked[%d]", pid);
191 waitpid(pid, &status, 0);
192 BT_DBG("child is terminated : %d", status);
199 int _bt_enable_adapter(void)
203 bt_le_status_t le_status;
207 status = _bt_core_get_status();
208 if (status != BT_DEACTIVATED) {
209 BT_ERR("Invalid state %d", status);
213 le_status = _bt_core_get_le_status();
214 if (le_status == BT_LE_ACTIVATED) {
215 /* Turn on PSCAN, (ISCAN if needed) */
216 /* Return with 0 for the Enabled response. */
217 __bt_core_set_status(BT_ACTIVATED);
218 BT_INFO("BR/EDR is enabled.");
222 __bt_core_set_status(BT_ACTIVATING);
224 ret = __execute_command("/usr/etc/bluetooth/bt-stack-up.sh", NULL);
226 BT_ERR("running script failed");
227 ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh", NULL);
228 __bt_core_set_status(BT_DEACTIVATED);
235 int _bt_disable_adapter(void)
238 bt_le_status_t le_status;
240 BT_INFO_C("Disable adapter");
242 le_status = _bt_core_get_le_status();
243 BT_DBG("le_status : %d", le_status);
244 if (le_status == BT_LE_ACTIVATED) {
245 /* Turn off PSCAN, (ISCAN if needed) */
246 /* Return with 0 for the Disabled response. */
247 __bt_core_set_status(BT_DEACTIVATED);
248 BT_INFO("BR/EDR is disabled. now LE only mode");
252 status = _bt_core_get_status();
253 if (status == BT_ACTIVATING) {
254 /* Forcely terminate */
255 if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) {
256 BT_ERR("running script failed");
258 _bt_core_terminate();
260 } else if (status != BT_ACTIVATED) {
261 BT_ERR("Invalid state %d", status);
264 __bt_core_set_status(BT_DEACTIVATING);
266 if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) {
267 BT_ERR("running script failed");
268 __bt_core_set_status( BT_ACTIVATED);
275 int _bt_enable_adapter_le(void)
281 bt_le_status_t le_status;
282 le_status = _bt_core_get_le_status();
283 retv_if(le_status != BT_LE_DEACTIVATED, -1);
285 status = _bt_core_get_status();
286 if (status == BT_DEACTIVATED) {
287 __bt_core_set_le_status(BT_LE_ACTIVATING);
288 BT_DBG("Activate BT");
289 ret = __execute_command("/usr/etc/bluetooth/bt-stack-up.sh", NULL);
291 BT_ERR("running script failed");
292 ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh &", NULL);
293 __bt_core_set_status(BT_DEACTIVATED);
294 __bt_core_set_le_status(BT_LE_DEACTIVATED);
298 __bt_core_set_le_status(BT_LE_ACTIVATED);
303 int _bt_disable_adapter_le(void)
308 bt_le_status_t le_status;
310 le_status = _bt_core_get_le_status();
311 retv_if(le_status == BT_LE_DEACTIVATED, 0);
312 retv_if(le_status == BT_LE_DEACTIVATING, -1);
314 status = _bt_core_get_status();
315 BT_DBG("status : %d", status);
317 if (status == BT_DEACTIVATED) {
318 __bt_core_set_le_status(BT_LE_DEACTIVATING);
320 if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) {
321 BT_ERR("running script failed");
322 __bt_core_set_le_status(BT_LE_ACTIVATED);
327 __bt_core_set_le_status(BT_LE_DEACTIVATED);
333 int _bt_core_service_request_adapter(int service_function)
337 GArray *in_param1 = NULL;
338 GArray *in_param2 = NULL;
339 GArray *in_param3 = NULL;
340 GArray *in_param4 = NULL;
341 GArray *out_param = NULL;
343 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
345 ret = _bt_core_service_request(BT_CORE_SERVICE, service_function,
346 in_param1, in_param2, in_param3, in_param4, &out_param);
348 BT_ERR("_bt_core_service_request_adapter() failed");
350 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
355 static void __bt_core_update_status(void)
357 int bt_status = VCONFKEY_BT_STATUS_OFF;
358 int bt_le_status = 0;
360 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0)
361 BT_ERR("no bluetooth device info, so BT was disabled at previous session");
362 #ifdef ENABLE_TIZEN_2_4
363 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status) < 0)
364 BT_ERR("no bluetooth le info, so BT LE was disabled at previous session");
367 BT_INFO("bt_status = %d, bt_le_status = %d", bt_status, bt_le_status);
369 if (bt_status == VCONFKEY_BT_STATUS_OFF)
370 __bt_core_set_status(BT_DEACTIVATED);
372 __bt_core_set_status(BT_ACTIVATED);
374 if (bt_le_status == 0)
375 __bt_core_set_le_status(BT_LE_DEACTIVATED);
377 __bt_core_set_le_status(BT_LE_ACTIVATED);
380 static gboolean bt_core_enable_adapter(BtCore *agent,
381 DBusGMethodInvocation *context)
383 char *sender = dbus_g_method_get_sender(context);
389 _bt_set_flightmode_request(FALSE);
390 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
391 BT_ERR("Set vconf failed");
393 ret = _bt_enable_adapter();
395 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
396 "Activation failed");
397 dbus_g_method_return_error(context, error);
402 dbus_g_method_return(context);
409 static gboolean bt_core_disable_adapter(BtCore *agent,
410 DBusGMethodInvocation *context)
412 char *sender = dbus_g_method_get_sender(context);
418 _bt_set_flightmode_request(FALSE);
419 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
420 BT_ERR("Set vconf failed");
422 ret = _bt_disable_adapter();
424 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
425 "Deactivation failed");
426 dbus_g_method_return_error(context, error);
431 dbus_g_method_return(context);
438 static gboolean bt_core_recover_adapter(BtCore *agent,
439 DBusGMethodInvocation *context)
444 BT_INFO_C("Recover bt adapter");
446 dbus_g_method_return(context);
448 _bt_set_flightmode_request(FALSE);
449 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
450 BT_ERR("Set vconf failed");
452 is_recovery_mode = TRUE;
454 __bt_core_update_status();
456 if (_bt_core_get_status() == BT_ACTIVATED) {
457 _bt_core_set_bt_status(BT_RECOVERY_MODE, 1);
458 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
460 if (_bt_core_get_le_status() == BT_LE_ACTIVATED) {
461 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 1);
462 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
465 ret = _bt_disable_adapter();
467 BT_ERR("_bt_disable_adapter() failed");
468 ret_le = _bt_disable_adapter_le();
470 BT_ERR("_bt_disable_adapter_le() failed");
475 static gboolean bt_core_enable_adapter_le(BtCore *agent,
476 DBusGMethodInvocation *context)
478 char *sender = dbus_g_method_get_sender(context);
484 ret = _bt_enable_adapter_le();
486 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
487 "LE Activation failed");
488 dbus_g_method_return_error(context, error);
494 dbus_g_method_return(context);
502 static gboolean bt_core_disable_adapter_le(BtCore *agent,
503 DBusGMethodInvocation *context)
507 char *sender = dbus_g_method_get_sender(context);
508 BT_DBG("sender : %s", sender);
514 ret = _bt_disable_adapter_le();
516 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
517 "LE Deactivation failed");
518 dbus_g_method_return_error(context, error);
523 dbus_g_method_return(context);
531 static int __bt_reset_adapter(void)
533 /* Forcely terminate */
534 if (__execute_command("/usr/etc/bluetooth/bt-reset-env.sh", NULL) < 0) {
535 BT_ERR("running script failed");
537 _bt_core_terminate();
541 static gboolean bt_core_reset_adapter(BtCore *agent,
542 DBusGMethodInvocation *context)
544 char *sender = dbus_g_method_get_sender(context);
550 ret = __bt_reset_adapter();
552 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
553 "Deactivation failed");
554 dbus_g_method_return_error(context, error);
559 dbus_g_method_return(context);
566 static gboolean __bt_core_enable_core_timeout_cb(gpointer data)
570 _bt_core_init_vconf_value();
575 static gboolean bt_core_enable_core(BtCore *agent,
576 DBusGMethodInvocation *context)
578 char *sender = dbus_g_method_get_sender(context);
585 __bt_core_update_status();
587 g_timeout_add(200, (GSourceFunc)__bt_core_enable_core_timeout_cb, NULL);
589 dbus_g_method_return(context);
597 static gboolean __bt_core_recovery_cb(gpointer data)
600 gboolean is_request_failed = FALSE;
601 static gboolean is_first_failure = TRUE;
605 if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
606 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
608 is_request_failed = TRUE;
611 if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
612 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
614 is_request_failed = TRUE;
617 if (is_request_failed == TRUE) {
618 BT_ERR("Recovery is failed.");
619 if (is_first_failure == TRUE) {
620 g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
621 is_first_failure = FALSE;
624 is_first_failure = TRUE;
628 is_first_failure = TRUE;
630 if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
631 _bt_core_set_bt_status(BT_RECOVERY_MODE, 0);
632 ret = _bt_enable_adapter();
634 BT_ERR("_bt_enable_adapter() failed");
636 if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
637 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 0);
638 ret = _bt_enable_adapter_le();
640 BT_ERR("_bt_enable_adapter_le() failed");
643 is_recovery_mode = FALSE;
650 static gboolean __bt_core_enable_timeout_cb(gpointer data)
652 bt_status_t adapter_status;
653 bt_le_status_t adapter_status_le;
657 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
658 BT_ERR("Set vconf failed");
660 adapter_status = _bt_core_get_status();
661 adapter_status_le = _bt_core_get_le_status();
663 if (adapter_status == BT_DEACTIVATED &&
664 _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) {
665 _bt_core_set_bt_status(BT_FLIGHT_MODE, 0);
666 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
667 _bt_enable_adapter();
670 if (adapter_status_le == BT_LE_DEACTIVATED &&
671 _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) {
672 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0);
673 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
674 _bt_enable_adapter_le();
680 static gboolean __bt_core_disable_timeout_cb(gpointer data)
682 bt_status_t adapter_status;
683 bt_le_status_t adapter_status_le;
687 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
688 BT_ERR("Set vconf failed");
690 adapter_status = _bt_core_get_status();
691 adapter_status_le = _bt_core_get_le_status();
693 if (adapter_status == BT_ACTIVATED) {
694 int bt_status_before_mode = 0;
696 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0)
697 _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode);
699 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
700 _bt_disable_adapter();
703 if (adapter_status_le == BT_LE_ACTIVATED) {
704 int bt_le_status_before_mode = 0;
706 #ifdef ENABLE_TIZEN_2_4
707 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0)
708 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode);
711 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
712 _bt_disable_adapter_le();
718 void _bt_core_adapter_added_cb(void)
721 bt_le_status_t le_status;
722 gboolean flight_mode_status;
726 status = _bt_core_get_status();
727 BT_DBG("status : %d", status);
728 le_status = _bt_core_get_le_status();
729 BT_DBG("le_status : %d", le_status);
731 if (status == BT_ACTIVATING)
732 __bt_core_set_status(BT_ACTIVATED);
733 if (le_status == BT_LE_ACTIVATING)
734 __bt_core_set_le_status(BT_LE_ACTIVATED);
736 flight_mode_status = _bt_core_is_flight_mode_enabled();
738 if (flight_mode_status == TRUE && _bt_is_flightmode_request() == TRUE) {
739 _bt_set_flightmode_request(FALSE);
740 g_timeout_add(2000, (GSourceFunc)__bt_core_disable_timeout_cb, NULL);
743 _bt_set_flightmode_request(FALSE);
745 _bt_core_terminate();
748 void _bt_core_adapter_removed_cb(void)
750 int flight_mode_value = 0;
751 int power_saving_mode = 0;
752 gboolean flight_mode_status;
753 static int timer_id = -1;
757 __bt_core_set_status(BT_DEACTIVATED);
758 __bt_core_set_le_status(BT_LE_DEACTIVATED);
759 if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
760 BT_ERR("Set vconf failed");
761 #ifdef ENABLE_TIZEN_2_4
762 if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0)
763 BT_ERR("Set vconf failed");
766 if (is_recovery_mode == TRUE)
769 timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
773 if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value) != 0)
774 BT_ERR("Fail to get the flight_mode_deactivated value");
776 if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &power_saving_mode) != 0)
777 BT_ERR("Fail to get the ps_mode_deactivated value");
779 flight_mode_status = _bt_core_is_flight_mode_enabled();
781 if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
782 _bt_set_flightmode_request(FALSE);
784 timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_enable_timeout_cb, NULL);
787 _bt_set_flightmode_request(FALSE);
789 if (flight_mode_value == 1 || power_saving_mode == 1){
790 BT_DBG("Bt Core not terminated");
794 _bt_core_terminate();