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 DBusGConnection *conn = NULL;
42 static void __bt_core_set_status(bt_status_t status)
44 adapter_status = status;
47 bt_status_t _bt_core_get_status(void)
49 return adapter_status;
52 static void __bt_core_set_le_status(bt_le_status_t status)
54 adapter_le_status = status;
57 bt_le_status_t _bt_core_get_le_status(void)
59 return adapter_le_status;
62 int _bt_core_get_bt_status(bt_mode_e mode)
64 return bt_status_before[mode];
67 int _bt_core_get_bt_le_status(bt_mode_e mode)
69 return bt_le_status_before[mode];
72 void _bt_core_set_bt_status(bt_mode_e mode, int status)
74 bt_status_before[mode] = status;
77 void _bt_core_set_bt_le_status(bt_mode_e mode, int status)
79 bt_le_status_before[mode] = status;
82 gboolean _bt_core_is_recovery_mode(void)
84 return is_recovery_mode;
87 gboolean _bt_core_is_flight_mode_enabled(void)
89 #ifdef TIZEN_TELEPHONY_ENABLED
93 ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &isFlightMode);
95 BT_ERR("vconf_get_bool failed");
103 static gboolean bt_core_enable_adapter(BtCore *agent,
104 DBusGMethodInvocation *context);
106 static gboolean bt_core_disable_adapter(BtCore *agent,
107 DBusGMethodInvocation *context);
109 static gboolean bt_core_recover_adapter(BtCore *agent,
110 DBusGMethodInvocation *context);
112 static gboolean bt_core_enable_adapter_le(BtCore *agent,
113 DBusGMethodInvocation *context);
115 static gboolean bt_core_disable_adapter_le(BtCore *agent,
116 DBusGMethodInvocation *context);
118 static gboolean bt_core_reset_adapter(BtCore *agent,
119 DBusGMethodInvocation *context);
121 static gboolean bt_core_enable_core(BtCore *agent,
122 DBusGMethodInvocation *context);
124 static int __execute_command(const char *cmd, char *const arg_list[]);
126 #include "bt-core-adapter-method.h"
129 G_DEFINE_TYPE(BtCore, bt_core, G_TYPE_OBJECT);
131 /*This is part of platform provided code skeleton for client server model*/
132 static void bt_core_class_init (BtCoreClass *bt_core_class)
134 dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(bt_core_class),
135 &dbus_glib_bt_core_object_info);
138 /*This is part of platform provided code skeleton for client server model*/
139 static void bt_core_init (BtCore *core)
144 BT_CORE_ERROR_REJECT,
145 BT_CORE_ERROR_CANCEL,
146 BT_CORE_ERROR_TIMEOUT,
149 #define BT_CORE_ERROR (bt_core_error_quark())
151 static GQuark bt_core_error_quark(void)
153 static GQuark quark = 0;
155 quark = g_quark_from_static_string("BtCore");
160 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
162 static GError *bt_core_error(BtCoreError error, const char *err_msg)
164 return g_error_new(BT_CORE_ERROR, error, err_msg, NULL);
167 static int __execute_command(const char *cmd, char *const arg_list[])
177 BT_ERR("fork failed");
183 BT_ERR("fork failed");
184 } else if (pid2 == 0) {
185 execv(cmd, arg_list);
192 BT_DBG("parent : forked[%d]", pid);
193 waitpid(pid, &status, 0);
194 BT_DBG("child is terminated : %d", status);
201 static DBusGProxy *_bt_get_connman_proxy(void)
206 conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
207 retv_if(conn == NULL, NULL);
210 proxy = dbus_g_proxy_new_for_name(conn,
212 CONNMAN_BLUETOOTH_TECHNOLOGY_PATH,
213 CONNMAN_BLUETOTOH_TECHNOLOGY_INTERFACE);
214 retv_if(proxy == NULL, NULL);
219 static int _bt_power_adapter(gboolean powered)
221 GValue state = { 0 };
222 GError *error = NULL;
225 proxy = _bt_get_connman_proxy();
226 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
228 g_value_init(&state, G_TYPE_BOOLEAN);
229 g_value_set_boolean(&state, powered);
231 BT_DBG("set power property state: %d to connman", powered);
233 dbus_g_proxy_call(proxy, "SetProperty", &error,
234 G_TYPE_STRING, "Powered",
235 G_TYPE_VALUE, &state,
236 G_TYPE_INVALID, G_TYPE_INVALID);
239 BT_ERR("Powered set err: \n [%s]", error->message);
241 g_value_unset(&state);
242 return BLUETOOTH_ERROR_INTERNAL;
244 return BLUETOOTH_ERROR_NONE;
247 int _bt_enable_adapter(void)
251 bt_le_status_t le_status;
252 #ifdef __TIZEN_MOBILE__
253 __bt_core_set_status(BT_ACTIVATING);
255 ret = __execute_command("/usr/etc/bluetooth/bt-stack-up.sh", NULL);
257 BT_ERR("running script failed");
258 ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh", NULL);
259 __bt_core_set_status(BT_DEACTIVATED);
263 _bt_power_adapter(TRUE);
269 int _bt_disable_adapter(void)
271 BT_INFO_C("Disable adapter");
272 #ifdef __TIZEN_MOBILE__
273 __bt_core_set_status(BT_DEACTIVATING);
275 if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) {
276 BT_ERR("running script failed");
277 __bt_core_set_status(BT_ACTIVATED);
281 _bt_power_adapter(FALSE);
286 int _bt_enable_adapter_le(void)
289 #ifdef __TIZEN_MOBILE__
293 status = _bt_core_get_status();
294 if (status == BT_DEACTIVATED) {
295 __bt_core_set_le_status(BT_LE_ACTIVATING);
296 BT_DBG("Activate BT");
297 ret = system("/usr/etc/bluetooth/bt-stack-up.sh &");
299 BT_ERR("running script failed");
300 ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh &", NULL);
301 __bt_core_set_status(BT_DEACTIVATED);
302 __bt_core_set_le_status(BT_LE_DEACTIVATED);
306 __bt_core_set_le_status(BT_LE_ACTIVATED);
309 _bt_power_adapter(TRUE);
314 int _bt_disable_adapter_le(void)
318 #ifdef __TIZEN_MOBILE__
321 status = _bt_core_get_status();
322 BT_DBG("status : %d", status);
324 if (status == BT_DEACTIVATED) {
325 __bt_core_set_le_status(BT_LE_DEACTIVATING);
327 if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) {
328 BT_ERR("running script failed");
329 __bt_core_set_le_status(BT_LE_ACTIVATED);
333 __bt_core_set_le_status(BT_LE_DEACTIVATED);
335 _bt_power_adapter(FALSE);
342 int _bt_core_service_request_adapter(int service_function)
346 GArray *in_param1 = NULL;
347 GArray *in_param2 = NULL;
348 GArray *in_param3 = NULL;
349 GArray *in_param4 = NULL;
350 GArray *out_param = NULL;
352 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
354 ret = _bt_core_service_request(BT_CORE_SERVICE, service_function,
355 in_param1, in_param2, in_param3, in_param4, &out_param);
357 BT_ERR("_bt_core_service_request_adapter() failed");
359 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
364 static void __bt_core_update_status(void)
366 int bt_status = VCONFKEY_BT_STATUS_OFF;
367 int bt_le_status = 0;
369 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0)
370 BT_ERR("no bluetooth device info, so BT was disabled at previous session");
371 #ifdef ENABLE_TIZEN_2_4
372 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status) < 0)
373 BT_ERR("no bluetooth le info, so BT LE was disabled at previous session");
376 BT_INFO("bt_status = %d, bt_le_status = %d", bt_status, bt_le_status);
378 if (bt_status == VCONFKEY_BT_STATUS_OFF)
379 __bt_core_set_status(BT_DEACTIVATED);
381 __bt_core_set_status(BT_ACTIVATED);
383 if (bt_le_status == 0)
384 __bt_core_set_le_status(BT_LE_DEACTIVATED);
386 __bt_core_set_le_status(BT_LE_ACTIVATED);
389 static gboolean bt_core_enable_adapter(BtCore *agent,
390 DBusGMethodInvocation *context)
392 char *sender = dbus_g_method_get_sender(context);
398 _bt_set_flightmode_request(FALSE);
399 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
400 BT_ERR("Set vconf failed");
402 ret = _bt_enable_adapter();
404 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
405 "Activation failed");
406 dbus_g_method_return_error(context, error);
411 dbus_g_method_return(context);
418 static gboolean bt_core_disable_adapter(BtCore *agent,
419 DBusGMethodInvocation *context)
421 char *sender = dbus_g_method_get_sender(context);
427 _bt_set_flightmode_request(FALSE);
428 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
429 BT_ERR("Set vconf failed");
431 ret = _bt_disable_adapter();
433 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
434 "Deactivation failed");
435 dbus_g_method_return_error(context, error);
440 dbus_g_method_return(context);
447 static gboolean bt_core_recover_adapter(BtCore *agent,
448 DBusGMethodInvocation *context)
453 BT_INFO_C("Recover bt adapter");
455 dbus_g_method_return(context);
457 _bt_set_flightmode_request(FALSE);
458 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
459 BT_ERR("Set vconf failed");
461 is_recovery_mode = TRUE;
463 __bt_core_update_status();
465 if (_bt_core_get_status() == BT_ACTIVATED) {
466 _bt_core_set_bt_status(BT_RECOVERY_MODE, 1);
467 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
469 if (_bt_core_get_le_status() == BT_LE_ACTIVATED) {
470 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 1);
471 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
474 ret = _bt_disable_adapter();
476 BT_ERR("_bt_disable_adapter() failed");
477 ret_le = _bt_disable_adapter_le();
479 BT_ERR("_bt_disable_adapter_le() failed");
484 static gboolean bt_core_enable_adapter_le(BtCore *agent,
485 DBusGMethodInvocation *context)
487 char *sender = dbus_g_method_get_sender(context);
493 ret = _bt_enable_adapter_le();
495 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
496 "LE Activation failed");
497 dbus_g_method_return_error(context, error);
503 dbus_g_method_return(context);
511 static gboolean bt_core_disable_adapter_le(BtCore *agent,
512 DBusGMethodInvocation *context)
516 char *sender = dbus_g_method_get_sender(context);
517 BT_DBG("sender : %s", sender);
523 ret = _bt_disable_adapter_le();
525 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
526 "LE Deactivation failed");
527 dbus_g_method_return_error(context, error);
532 dbus_g_method_return(context);
540 static int __bt_reset_adapter(void)
542 /* Forcely terminate */
543 if (__execute_command("/usr/etc/bluetooth/bt-reset-env.sh", NULL) < 0) {
544 BT_ERR("running script failed");
546 _bt_core_terminate();
550 static gboolean bt_core_reset_adapter(BtCore *agent,
551 DBusGMethodInvocation *context)
553 char *sender = dbus_g_method_get_sender(context);
559 ret = __bt_reset_adapter();
561 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
562 "Deactivation failed");
563 dbus_g_method_return_error(context, error);
568 dbus_g_method_return(context);
575 static gboolean __bt_core_enable_core_timeout_cb(gpointer data)
579 _bt_core_init_vconf_value();
584 static gboolean bt_core_enable_core(BtCore *agent,
585 DBusGMethodInvocation *context)
587 char *sender = dbus_g_method_get_sender(context);
594 __bt_core_update_status();
596 g_timeout_add(200, (GSourceFunc)__bt_core_enable_core_timeout_cb, NULL);
598 dbus_g_method_return(context);
606 static gboolean __bt_core_recovery_cb(gpointer data)
609 gboolean is_request_failed = FALSE;
610 static gboolean is_first_failure = TRUE;
614 if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
615 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
617 is_request_failed = TRUE;
620 if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
621 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
623 is_request_failed = TRUE;
626 if (is_request_failed == TRUE) {
627 BT_ERR("Recovery is failed.");
628 if (is_first_failure == TRUE) {
629 g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
630 is_first_failure = FALSE;
633 is_first_failure = TRUE;
637 is_first_failure = TRUE;
639 if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
640 _bt_core_set_bt_status(BT_RECOVERY_MODE, 0);
641 ret = _bt_enable_adapter();
643 BT_ERR("_bt_enable_adapter() failed");
645 if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
646 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 0);
647 ret = _bt_enable_adapter_le();
649 BT_ERR("_bt_enable_adapter_le() failed");
652 is_recovery_mode = FALSE;
659 static gboolean __bt_core_enable_timeout_cb(gpointer data)
661 bt_status_t adapter_status;
662 bt_le_status_t adapter_status_le;
666 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
667 BT_ERR("Set vconf failed");
669 adapter_status = _bt_core_get_status();
670 adapter_status_le = _bt_core_get_le_status();
672 if (adapter_status == BT_DEACTIVATED &&
673 _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) {
674 _bt_core_set_bt_status(BT_FLIGHT_MODE, 0);
675 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
676 _bt_enable_adapter();
679 if (adapter_status_le == BT_LE_DEACTIVATED &&
680 _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) {
681 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0);
682 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
683 _bt_enable_adapter_le();
689 static gboolean __bt_core_disable_timeout_cb(gpointer data)
691 bt_status_t adapter_status;
692 bt_le_status_t adapter_status_le;
696 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
697 BT_ERR("Set vconf failed");
699 adapter_status = _bt_core_get_status();
700 adapter_status_le = _bt_core_get_le_status();
702 if (adapter_status == BT_ACTIVATED) {
703 int bt_status_before_mode = 0;
705 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0)
706 _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode);
708 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
709 _bt_disable_adapter();
712 if (adapter_status_le == BT_LE_ACTIVATED) {
713 int bt_le_status_before_mode = 0;
715 #ifdef ENABLE_TIZEN_2_4
716 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0)
717 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode);
720 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
721 _bt_disable_adapter_le();
727 void _bt_core_adapter_added_cb(void)
730 bt_le_status_t le_status;
731 gboolean flight_mode_status;
735 status = _bt_core_get_status();
736 BT_DBG("status : %d", status);
737 le_status = _bt_core_get_le_status();
738 BT_DBG("le_status : %d", le_status);
740 if (status == BT_ACTIVATING)
741 __bt_core_set_status(BT_ACTIVATED);
742 if (le_status == BT_LE_ACTIVATING)
743 __bt_core_set_le_status(BT_LE_ACTIVATED);
745 flight_mode_status = _bt_core_is_flight_mode_enabled();
747 if (flight_mode_status == TRUE && _bt_is_flightmode_request() == TRUE) {
748 _bt_set_flightmode_request(FALSE);
749 g_timeout_add(2000, (GSourceFunc)__bt_core_disable_timeout_cb, NULL);
752 _bt_set_flightmode_request(FALSE);
754 _bt_core_terminate();
757 void _bt_core_adapter_removed_cb(void)
759 int flight_mode_value = 0;
760 int power_saving_mode = 0;
761 gboolean flight_mode_status;
762 static int timer_id = -1;
766 __bt_core_set_status(BT_DEACTIVATED);
767 __bt_core_set_le_status(BT_LE_DEACTIVATED);
768 if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
769 BT_ERR("Set vconf failed");
770 #ifdef ENABLE_TIZEN_2_4
771 if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0)
772 BT_ERR("Set vconf failed");
775 if (is_recovery_mode == TRUE)
778 timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
782 if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value) != 0)
783 BT_ERR("Fail to get the flight_mode_deactivated value");
785 if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &power_saving_mode) != 0)
786 BT_ERR("Fail to get the ps_mode_deactivated value");
788 flight_mode_status = _bt_core_is_flight_mode_enabled();
790 if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
791 _bt_set_flightmode_request(FALSE);
793 timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_enable_timeout_cb, NULL);
796 _bt_set_flightmode_request(FALSE);
798 if (flight_mode_value == 1 || power_saving_mode == 1){
799 BT_DBG("Bt Core not terminated");
803 _bt_core_terminate();