diff options
Diffstat (limited to 'src/bt-connection-handler.c')
-rwxr-xr-x | src/bt-connection-handler.c | 560 |
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; +} |