summaryrefslogtreecommitdiff
path: root/src/bt-connection-handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bt-connection-handler.c')
-rwxr-xr-xsrc/bt-connection-handler.c560
1 files changed, 560 insertions, 0 deletions
diff --git a/src/bt-connection-handler.c b/src/bt-connection-handler.c
new file mode 100755
index 0000000..2d554e0
--- /dev/null
+++ b/src/bt-connection-handler.c
@@ -0,0 +1,560 @@
+/*
+* bt-connection-popup
+*
+* Copyright 2012 Samsung Electronics Co., Ltd
+*
+* Contact: Hocheol Seo <hocheol.seo@samsung.com>
+* Injun Yang <injun.yang@samsung.com>
+* Seungyoun Ju <sy39.ju@samsung.com>
+*
+* Licensed under the Flora License, Version 1.1 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.tizenopensource.org/license
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*/
+
+#include <aul.h>
+#include <bluetooth.h>
+#include <vconf.h>
+
+#include "bt-connection-main.h"
+#include "bt-connection-view.h"
+#include "bt-connection-handler.h"
+
+#define VCONFKEY_SAP_STATUS "memory/private/sap/conn_status"
+#define BT_ADDRESS_LENGTH 18
+
+static bool is_le_disconnecting;
+
+static int __bt_app_destory_cb(void *data)
+{
+ bt_app_data_t *ad = NULL;
+
+ DBG("");
+
+ ad = (bt_app_data_t *)data;
+ if (ad == NULL) {
+ ERR("Invalid param");
+ return 0;
+ }
+
+ if (ad->timer) {
+ ecore_timer_del(ad->timer);
+ ad->timer = NULL;
+ }
+
+ _bt_destroy_app(ad);
+
+ return 0;
+}
+
+static void __bt_wms_status_handler(keynode_t *key, void *data)
+{
+ int status;
+ int type;
+ bt_app_data_t *ad;
+
+ ad = (bt_app_data_t *)data;
+ if (ad == NULL) {
+ ERR("Invalid param");
+ return;
+ }
+
+ type = vconf_keynode_get_type(key);
+ if (type == VCONF_TYPE_BOOL)
+ status = vconf_keynode_get_bool(key);
+ else {
+ ERR("Invalid vconf type : %d", type);
+ return;
+ }
+
+ DBG("WMS is %s", status == WMS_CONNECTED ?
+ "connected" : "disconnected" );
+
+ if (status == WMS_CONNECTED) {
+ /* To show connected view, create new popup */
+ /* or update edc part */
+ /* See _bt_update_connect_status_popup() */
+ if (ad->timer) {
+ ecore_timer_del(ad->timer);
+ ad->timer = NULL;
+ }
+ _bt_create_connected_popup(ad);
+
+ _bt_send_result(ad, KEY_VAL_CONNECTED);
+
+ ad->timer = ecore_timer_add(APP_DESTORY_TIMEOUT,
+ (Ecore_Task_Cb) __bt_app_destory_cb, ad);
+ }
+
+ return;
+}
+
+static void __bt_hf_connection_state_changed(int result, bool connected, const char *remote_address, bt_audio_profile_type_e type, void *user_data)
+{
+ if (connected == true) {
+ DBG("Bluetooth HF is connected");
+ }
+ else {
+ DBG("Bluetooth HF is disconnected");
+ }
+}
+
+static bool __bt_adapter_bonded_device_cb(bt_device_info_s *device_info, void *user_data)
+{
+ int ret;
+ bool is_connected = false;
+ char* remote_address = (char*)user_data;
+
+ if (!(device_info->bt_class.major_device_class & BT_MAJOR_DEVICE_CLASS_COMPUTER) &&
+ !(device_info->bt_class.major_device_class & BT_MAJOR_DEVICE_CLASS_PHONE))
+ return true;
+
+ memcpy(remote_address, device_info->remote_address, BT_ADDRESS_LENGTH);
+ ret = bt_device_is_profile_connected(device_info->remote_address, BT_PROFILE_AG, &is_connected);
+ if (ret == BT_ERROR_NONE && is_connected) {
+ remote_address[0] = '\0';
+ return false;
+ }
+
+ return true;
+}
+
+static gboolean __bt_hf_is_connected(const char* remote_address)
+{
+ int ret;
+ gboolean is_connected = FALSE;
+
+ ret = bt_adapter_foreach_bonded_device(__bt_adapter_bonded_device_cb, (void*)remote_address);
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_adapter_foreach_bonded_device is failed 0x%X", ret);
+ return FALSE;
+ }
+
+ if (remote_address[0] == '\0')
+ is_connected = TRUE;
+ DBG("Aleady HF is %s", is_connected ? "connected" : "disconnected");
+
+ return is_connected;
+}
+
+static void __bt_adapter_state_changed(int result,
+ bt_adapter_state_e adapter_state, void *user_data)
+{
+ int ret;
+ char remote_address[BT_ADDRESS_LENGTH] = { 0, };
+
+ if (user_data == NULL) {
+ ERR("Invalid param");
+ return;
+ }
+
+ if (result != BT_ERROR_NONE) {
+ ERR("BT Adapter operation is failed : %d", result);
+ return;
+ }
+
+ DBG("BT Adapter is %s", adapter_state == BT_ADAPTER_ENABLED ?
+ "enabled" : "disabled");
+
+ if (adapter_state == BT_ADAPTER_ENABLED) {
+ if (__bt_hf_is_connected(&remote_address[0]) == FALSE) {
+ DBG("Make a HF connection");
+ ret = bt_audio_connect(&remote_address[0], BT_AUDIO_PROFILE_TYPE_AG);
+ if (ret != BT_ERROR_NONE) {
+ ERR("HF Connection is failed");
+ return;
+ }
+ }
+ }
+
+ return;
+}
+
+int _bt_get_wms_status(void)
+{
+ int ret;
+ int status = WMS_DISCONNECTED;
+
+ ret = vconf_get_bool(VCONFKEY_WMS_WMANAGER_CONNECTED, &status);
+ if (ret != 0) {
+ ERR("Vconf get failed");
+ return WMS_DISCONNECTED;
+ }
+
+ DBG("WMS status : %d", status);
+
+ return status;
+}
+
+void _bt_get_sap_status(void)
+{
+ int ret;
+ int status = 0;
+
+ ret = vconf_get_int(VCONFKEY_SAP_STATUS, &status);
+ if (ret != 0) {
+ ERR("Vconf get failed");
+ }
+
+ DBG("SAP status : %d", status);
+
+ return;
+}
+
+gboolean _bt_send_result(bt_app_data_t *ad, const char *val)
+{
+ if (ad == NULL)
+ return FALSE;
+
+ bundle *kb;
+ bundle *res_b;
+ int ret;
+ static gboolean is_sent = FALSE;
+
+ DBG("");
+
+ if (ad->service_clone == NULL) {
+ ERR("Invalid param");
+ return FALSE;
+ }
+
+ if (is_sent == TRUE) {
+ ERR("Aleady send response !!!");
+ return FALSE;
+ }
+
+ ret = service_to_bundle(ad->service_clone, &kb);
+ if (ret != SERVICE_ERROR_NONE) {
+ ERR("service is failed : %d", ret);
+ return FALSE;
+ }
+
+ aul_create_result_bundle(kb, &res_b);
+ if (res_b == NULL)
+ return FALSE;
+
+ bundle_add(res_b, "__BT_CONNECTION__", val);
+
+ aul_send_service_result(res_b);
+ bundle_free(res_b);
+ bundle_free(kb);
+
+ is_sent = TRUE;
+
+ DBG("Send result : %s", val);
+
+ return TRUE;
+}
+
+bool __device_check_gatt_cb(bt_profile_e profile, void *user_data)
+{
+ bool *is_connected = (bool *)user_data;
+
+ if (profile == BT_PROFILE_GATT) {
+ *is_connected = true;
+ return false;
+ }
+
+ return true;
+}
+
+bool __bt_le_is_connected(const char *remote_address)
+{
+ int ret;
+ bool is_connected = false;
+
+ if (remote_address == NULL) {
+ return false;
+ }
+
+ ret = bt_device_foreach_connected_profiles(remote_address,
+ __device_check_gatt_cb, &is_connected);
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_device_foreach_connected_profiles fail (0x%08x)", ret);
+ return false;
+ }
+
+ return is_connected;
+}
+
+void __bt_gatt_disconnected_cb(int result, void *user_data)
+{
+ DBG("called");
+ if (result != BT_ERROR_NONE) {
+ ERR("GATT disconnect fail (0x%08x)", result);
+ is_le_disconnecting = false;
+ }
+
+ return;
+#if 0
+ char remote_address[BT_ADDRESS_LENGTH] = { 0, };
+ bool is_advertising = false;
+ int ret;
+
+ if (result != BT_ERROR_NONE) {
+ ERR("GATT disconnect fail (0x%08x)", result);
+ return;
+ }
+
+ if (__bt_hf_is_connected(&remote_address[0]) == TRUE) {
+ DBG("Handsfree is already connected");
+ return;
+ }
+
+ ret = bt_adapter_is_advertising(&is_advertising);
+ if (ret == BT_ERROR_NONE && is_advertising) {
+ ret = bt_adapter_stop_advertising();
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_adapter_stop_advertising failed (0x%08x)", ret);
+ }
+ }
+
+ DBG("Make a HF connection");
+ ret = bt_audio_connect(&remote_address[0], BT_AUDIO_PROFILE_TYPE_AG);
+ if (ret != BT_ERROR_NONE) {
+ ERR("HF Connection is failed");
+ return;
+ }
+
+ return;
+#endif
+}
+
+static void __bt_device_connection_state_changed_cb(bool connected,
+ const char *remote_address,
+ void *user_data)
+{
+ bool is_advertising = false;
+ int ret;
+ char remote_add[BT_ADDRESS_LENGTH] = { 0, };
+
+ DBG("address: %s, connected: %d", remote_address, connected);
+
+ if (is_le_disconnecting == false || connected == true) {
+ DBG("is_le_disconnecting IS FALSE");
+ return;
+ }
+ is_le_disconnecting = false;
+
+ if (__bt_hf_is_connected(&remote_add[0]) == true) {
+ DBG("Handsfree is already connected");
+ return;
+ }
+
+ if (strncmp(remote_address, remote_add, BT_ADDRESS_LENGTH-1) != 0) {
+ DBG("remote address is different");
+ return;
+ }
+
+ ret = bt_adapter_is_advertising(&is_advertising);
+ if (ret == BT_ERROR_NONE && is_advertising) {
+ ret = bt_adapter_stop_advertising();
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_adapter_stop_advertising failed (0x%08x)", ret);
+ }
+ }
+
+ DBG("Make a HF connection");
+ ret = bt_audio_connect(&remote_add[0], BT_AUDIO_PROFILE_TYPE_AG);
+ if (ret != BT_ERROR_NONE) {
+ ERR("HF Connection is failed");
+ return;
+ }
+
+ return;
+}
+
+gboolean _bt_init(void *data)
+{
+ int ret;
+ bt_adapter_state_e adapter_state = BT_ADAPTER_DISABLED;
+ char remote_address[BT_ADDRESS_LENGTH] = { 0, };
+ bool is_advertising = false;
+
+ bt_app_data_t *ad;
+ ad = (bt_app_data_t *)data;
+
+ is_le_disconnecting = false;
+
+ if (ad == NULL) {
+ return FALSE;
+ }
+
+ if (ad->initialize == TRUE) {
+ DBG("bt_initialize already done");
+ return TRUE;
+ }
+
+ ret = bt_initialize();
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_initialize is failed : %d", ret);
+ return FALSE;
+ }
+
+ ret = bt_adapter_set_state_changed_cb(__bt_adapter_state_changed, data);
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_adapter_set_state_changed_cb is failed : %d", ret);
+ bt_deinitialize();
+ return FALSE;
+ }
+
+ ret = bt_device_set_connection_state_changed_cb(__bt_device_connection_state_changed_cb,
+ NULL);
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_device_set_connection_state_changed_cb is failed : %d", ret);
+ return FALSE;
+ }
+
+ ret = bt_adapter_get_state(&adapter_state);
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_adapter_get_state is failed : %d", ret);
+ return FALSE;
+ }
+
+ ret = bt_audio_initialize();
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_audio_initialize is failed : %d", ret);
+ return FALSE;
+ }
+
+ ret = bt_audio_set_connection_state_changed_cb(__bt_hf_connection_state_changed, NULL);
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_audio_set_connection_state_changed_cb is failed : %d", ret);
+ bt_hf_deinitialize();
+ return FALSE;
+ }
+
+ if (adapter_state == BT_ADAPTER_ENABLED) {
+ DBG("Aleady BT enabled");
+#ifdef FEATURE_TIZENW
+ if (__bt_hf_is_connected(&remote_address[0]) == FALSE) {
+ DBG("Make a HF connection");
+ ret = bt_audio_connect(&remote_address[0], BT_AUDIO_PROFILE_TYPE_AG);
+ if (ret != BT_ERROR_NONE) {
+ ERR("HF Connection is failed");
+ return FALSE;
+ }
+ }
+#else
+ if (__bt_hf_is_connected(&remote_address[0]) == FALSE) {
+ if (__bt_le_is_connected(&remote_address[0])) {
+
+ ret = bt_adapter_is_advertising(&is_advertising);
+ if (ret == BT_ERROR_NONE && is_advertising) {
+ ret = bt_adapter_stop_advertising();
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_adapter_stop_advertising failed (0x%08x)",
+ ret);
+ }
+ }
+
+ ret = bt_device_disconnect_le(__bt_gatt_disconnected_cb, &remote_address[0]);
+ if (ret == BT_ERROR_NONE)
+ is_le_disconnecting = true;
+ return TRUE;
+ }
+
+ DBG("Make a HF connection");
+ ret = bt_audio_connect(&remote_address[0], BT_AUDIO_PROFILE_TYPE_AG);
+ if (ret != BT_ERROR_NONE) {
+ ERR("HF Connection is failed");
+ return FALSE;
+ }
+ }
+#endif /* FEATURE_TIZENW */
+ return TRUE;
+ } else {
+ DBG("Enable BT adapter");
+ ret = bt_adapter_enable();
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_adapter_enable is failed : %d", ret);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+void _bt_deinit(void *data)
+{
+ int ret;
+ char remote_address[BT_ADDRESS_LENGTH] = { 0, };
+ bool is_advertising = FALSE;
+ bt_app_data_t *ad;
+ ad = (bt_app_data_t *)data;
+
+ if (ad == NULL) return;
+
+ if (ad->initialize == FALSE) {
+ DBG("bt_deinitialize already done");
+ return;
+ }
+
+ if (__bt_hf_is_connected(&remote_address[0]) == FALSE) {
+ ret = bt_adapter_is_advertising(&is_advertising);
+ if (ret == BT_ERROR_NONE && !is_advertising) {
+ ret = bt_adapter_start_advertising(NULL);
+ if (ret != BT_ERROR_NONE) {
+ ERR("bt_adapter_stop_advertising failed (0x%08x)", ret);
+ }
+ }
+ }
+
+ ret = bt_audio_unset_connection_state_changed_cb();
+ if (ret != BT_ERROR_NONE)
+ ERR("bt_audio_unset_connection_state_changed_cb is failed : %d", ret);
+
+ ret = bt_audio_deinitialize();
+ if (ret != BT_ERROR_NONE)
+ ERR("bt_audio_deinitialize is failed : %d", ret);
+
+ ret = bt_hf_deinitialize();
+ if (ret != BT_ERROR_NONE)
+ ERR("bt_hf_deinitialize is failed : %d", ret);
+
+ ret = bt_device_unset_connection_state_changed_cb();
+ if (ret != BT_ERROR_NONE)
+ ERR("bt_device_unset_connection_state_changed_cb is failed : %d", ret);
+
+ ret = bt_adapter_unset_state_changed_cb();
+ if (ret != BT_ERROR_NONE)
+ ERR("bt_adapter_unset_state_changed_cb is failed : %d", ret);
+
+ ret = bt_deinitialize();
+ if (ret != BT_ERROR_NONE)
+ ERR("bt_deinitialize is failed : %d", ret);
+
+ return;
+}
+
+gboolean _bt_register_vconf_handler(void *data)
+{
+ int ret;
+
+ ret =
+ vconf_notify_key_changed(VCONFKEY_WMS_WMANAGER_CONNECTED,
+ (vconf_callback_fn) __bt_wms_status_handler, data);
+ if (ret < 0) {
+ ERR("Unable to register key handler");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void _bt_unregister_vconf_handler(void)
+{
+ vconf_ignore_key_changed(VCONFKEY_WMS_WMANAGER_CONNECTED,
+ (vconf_callback_fn) __bt_wms_status_handler);
+
+ return;
+}