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");
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__
291 status = _bt_core_get_status();
292 if (status == BT_DEACTIVATED) {
293 __bt_core_set_le_status(BT_LE_ACTIVATING);
294 BT_DBG("Activate BT");
295 ret = system("/usr/etc/bluetooth/bt-stack-up.sh &");
297 BT_ERR("running script failed");
298 ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh &", NULL);
299 __bt_core_set_status(BT_DEACTIVATED);
300 __bt_core_set_le_status(BT_LE_DEACTIVATED);
304 __bt_core_set_le_status(BT_LE_ACTIVATED);
307 _bt_power_adapter(TRUE);
312 int _bt_disable_adapter_le(void)
316 #ifdef __TIZEN_MOBILE__
317 status = _bt_core_get_status();
318 BT_DBG("status : %d", status);
320 if (status == BT_DEACTIVATED) {
321 __bt_core_set_le_status(BT_LE_DEACTIVATING);
323 if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) {
324 BT_ERR("running script failed");
325 __bt_core_set_le_status(BT_LE_ACTIVATED);
329 __bt_core_set_le_status(BT_LE_DEACTIVATED);
331 _bt_power_adapter(FALSE);
338 int _bt_core_service_request_adapter(int service_function)
342 GArray *in_param1 = NULL;
343 GArray *in_param2 = NULL;
344 GArray *in_param3 = NULL;
345 GArray *in_param4 = NULL;
346 GArray *out_param = NULL;
348 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
350 ret = _bt_core_service_request(BT_CORE_SERVICE, service_function,
351 in_param1, in_param2, in_param3, in_param4, &out_param);
353 BT_ERR("_bt_core_service_request_adapter() failed");
355 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
360 static void __bt_core_update_status(void)
362 int bt_status = VCONFKEY_BT_STATUS_OFF;
363 int bt_le_status = 0;
365 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0)
366 BT_ERR("no bluetooth device info, so BT was disabled at previous session");
367 #ifdef ENABLE_TIZEN_2_4
368 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status) < 0)
369 BT_ERR("no bluetooth le info, so BT LE was disabled at previous session");
372 BT_INFO("bt_status = %d, bt_le_status = %d", bt_status, bt_le_status);
374 if (bt_status == VCONFKEY_BT_STATUS_OFF)
375 __bt_core_set_status(BT_DEACTIVATED);
377 __bt_core_set_status(BT_ACTIVATED);
379 if (bt_le_status == 0)
380 __bt_core_set_le_status(BT_LE_DEACTIVATED);
382 __bt_core_set_le_status(BT_LE_ACTIVATED);
385 static gboolean bt_core_enable_adapter(BtCore *agent,
386 DBusGMethodInvocation *context)
388 char *sender = dbus_g_method_get_sender(context);
394 _bt_set_flightmode_request(FALSE);
395 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
396 BT_ERR("Set vconf failed");
398 ret = _bt_enable_adapter();
400 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
401 "Activation failed");
402 dbus_g_method_return_error(context, error);
407 dbus_g_method_return(context);
414 static gboolean bt_core_disable_adapter(BtCore *agent,
415 DBusGMethodInvocation *context)
417 char *sender = dbus_g_method_get_sender(context);
423 _bt_set_flightmode_request(FALSE);
424 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
425 BT_ERR("Set vconf failed");
427 ret = _bt_disable_adapter();
429 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
430 "Deactivation failed");
431 dbus_g_method_return_error(context, error);
436 dbus_g_method_return(context);
443 static gboolean bt_core_recover_adapter(BtCore *agent,
444 DBusGMethodInvocation *context)
449 BT_INFO_C("Recover bt adapter");
451 dbus_g_method_return(context);
453 _bt_set_flightmode_request(FALSE);
454 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
455 BT_ERR("Set vconf failed");
457 is_recovery_mode = TRUE;
459 __bt_core_update_status();
461 if (_bt_core_get_status() == BT_ACTIVATED) {
462 _bt_core_set_bt_status(BT_RECOVERY_MODE, 1);
463 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
465 if (_bt_core_get_le_status() == BT_LE_ACTIVATED) {
466 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 1);
467 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
470 ret = _bt_disable_adapter();
472 BT_ERR("_bt_disable_adapter() failed");
473 ret_le = _bt_disable_adapter_le();
475 BT_ERR("_bt_disable_adapter_le() failed");
480 static gboolean bt_core_enable_adapter_le(BtCore *agent,
481 DBusGMethodInvocation *context)
483 char *sender = dbus_g_method_get_sender(context);
489 ret = _bt_enable_adapter_le();
491 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
492 "LE Activation failed");
493 dbus_g_method_return_error(context, error);
499 dbus_g_method_return(context);
507 static gboolean bt_core_disable_adapter_le(BtCore *agent,
508 DBusGMethodInvocation *context)
512 char *sender = dbus_g_method_get_sender(context);
513 BT_DBG("sender : %s", sender);
519 ret = _bt_disable_adapter_le();
521 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
522 "LE Deactivation failed");
523 dbus_g_method_return_error(context, error);
528 dbus_g_method_return(context);
536 static int __bt_reset_adapter(void)
538 /* Forcely terminate */
539 if (__execute_command("/usr/etc/bluetooth/bt-reset-env.sh", NULL) < 0) {
540 BT_ERR("running script failed");
542 _bt_core_terminate();
546 static gboolean bt_core_reset_adapter(BtCore *agent,
547 DBusGMethodInvocation *context)
549 char *sender = dbus_g_method_get_sender(context);
555 ret = __bt_reset_adapter();
557 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
558 "Deactivation failed");
559 dbus_g_method_return_error(context, error);
564 dbus_g_method_return(context);
571 static gboolean __bt_core_enable_core_timeout_cb(gpointer data)
575 _bt_core_init_vconf_value();
580 static gboolean bt_core_enable_core(BtCore *agent,
581 DBusGMethodInvocation *context)
583 char *sender = dbus_g_method_get_sender(context);
590 __bt_core_update_status();
592 g_timeout_add(200, (GSourceFunc)__bt_core_enable_core_timeout_cb, NULL);
594 dbus_g_method_return(context);
602 static gboolean __bt_core_recovery_cb(gpointer data)
605 gboolean is_request_failed = FALSE;
606 static gboolean is_first_failure = TRUE;
610 if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
611 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
613 is_request_failed = TRUE;
616 if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
617 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
619 is_request_failed = TRUE;
622 if (is_request_failed == TRUE) {
623 BT_ERR("Recovery is failed.");
624 if (is_first_failure == TRUE) {
625 g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
626 is_first_failure = FALSE;
629 is_first_failure = TRUE;
633 is_first_failure = TRUE;
635 if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
636 _bt_core_set_bt_status(BT_RECOVERY_MODE, 0);
637 ret = _bt_enable_adapter();
639 BT_ERR("_bt_enable_adapter() failed");
641 if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
642 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 0);
643 ret = _bt_enable_adapter_le();
645 BT_ERR("_bt_enable_adapter_le() failed");
648 is_recovery_mode = FALSE;
655 static gboolean __bt_core_enable_timeout_cb(gpointer data)
657 bt_status_t adapter_status;
658 bt_le_status_t adapter_status_le;
662 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
663 BT_ERR("Set vconf failed");
665 adapter_status = _bt_core_get_status();
666 adapter_status_le = _bt_core_get_le_status();
668 if (adapter_status == BT_DEACTIVATED &&
669 _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) {
670 _bt_core_set_bt_status(BT_FLIGHT_MODE, 0);
671 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
672 _bt_enable_adapter();
675 if (adapter_status_le == BT_LE_DEACTIVATED &&
676 _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) {
677 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0);
678 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
679 _bt_enable_adapter_le();
685 static gboolean __bt_core_disable_timeout_cb(gpointer data)
687 bt_status_t adapter_status;
688 bt_le_status_t adapter_status_le;
692 if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
693 BT_ERR("Set vconf failed");
695 adapter_status = _bt_core_get_status();
696 adapter_status_le = _bt_core_get_le_status();
698 if (adapter_status == BT_ACTIVATED) {
699 int bt_status_before_mode = 0;
701 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0)
702 _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode);
704 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
705 _bt_disable_adapter();
708 if (adapter_status_le == BT_LE_ACTIVATED) {
709 int bt_le_status_before_mode = 0;
711 #ifdef ENABLE_TIZEN_2_4
712 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0)
713 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode);
716 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
717 _bt_disable_adapter_le();
723 void _bt_core_adapter_added_cb(void)
726 bt_le_status_t le_status;
727 gboolean flight_mode_status;
731 status = _bt_core_get_status();
732 BT_DBG("status : %d", status);
733 le_status = _bt_core_get_le_status();
734 BT_DBG("le_status : %d", le_status);
736 if (status == BT_ACTIVATING)
737 __bt_core_set_status(BT_ACTIVATED);
738 if (le_status == BT_LE_ACTIVATING)
739 __bt_core_set_le_status(BT_LE_ACTIVATED);
741 flight_mode_status = _bt_core_is_flight_mode_enabled();
743 if (flight_mode_status == TRUE && _bt_is_flightmode_request() == TRUE) {
744 _bt_set_flightmode_request(FALSE);
745 g_timeout_add(2000, (GSourceFunc)__bt_core_disable_timeout_cb, NULL);
748 _bt_set_flightmode_request(FALSE);
750 _bt_core_terminate();
753 void _bt_core_adapter_removed_cb(void)
755 int flight_mode_value = 0;
756 int power_saving_mode = 0;
757 gboolean flight_mode_status;
758 static int timer_id = -1;
762 __bt_core_set_status(BT_DEACTIVATED);
763 __bt_core_set_le_status(BT_LE_DEACTIVATED);
764 if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
765 BT_ERR("Set vconf failed");
766 #ifdef ENABLE_TIZEN_2_4
767 if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0)
768 BT_ERR("Set vconf failed");
771 if (is_recovery_mode == TRUE)
774 timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
778 if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value) != 0)
779 BT_ERR("Fail to get the flight_mode_deactivated value");
781 if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &power_saving_mode) != 0)
782 BT_ERR("Fail to get the ps_mode_deactivated value");
784 flight_mode_status = _bt_core_is_flight_mode_enabled();
786 if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
787 _bt_set_flightmode_request(FALSE);
789 timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_enable_timeout_cb, NULL);
792 _bt_set_flightmode_request(FALSE);
794 if (flight_mode_value == 1 || power_saving_mode == 1){
795 BT_DBG("Bt Core not terminated");
799 _bt_core_terminate();