2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
25 #include <syspopup_caller.h>
27 #include "bluetooth-api.h"
28 #include "bt-internal-types.h"
30 #include "bt-service-audio.h"
31 #include "bt-service-adapter.h"
32 #include "bt-service-common.h"
33 #include "bt-service-device.h"
34 #include "bt-service-event.h"
35 #include "bt-service-util.h"
37 #include "bt-service-headset-connection.h"
39 #ifdef TIZEN_SUPPORT_DUAL_HF
40 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
46 char device_address[BT_ADDRESS_STRING_SIZE + 1];
47 } bt_connected_headset_data_t;
49 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
53 } bt_auto_connect_timer_t;
55 bt_auto_connect_timer_t auto_connect_timer = {0, };
58 static GList *g_connected_list;
60 static bt_headset_wait_t *g_wait_data;
62 static bt_audio_function_data_t *pdata;
64 static void __bt_remove_device_from_wait_list();
66 static void __bt_free_wait_data();
68 static gboolean __bt_device_support_uuid(char *remote_address,
69 bt_audio_type_t type);
71 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
72 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param);
75 static void __bt_hf_request_cb(GDBusProxy *proxy, GAsyncResult *res,
78 GError *g_error = NULL;
79 GVariant *out_param1 = NULL;
80 GVariant *reply = NULL;
81 int result = BLUETOOTH_ERROR_NONE;
82 bt_function_data_t *func_data;
83 request_info_t *req_info;
85 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
86 g_object_unref(proxy);
88 func_data = user_data;
90 if (func_data == NULL) {
92 BT_ERR("func_data == NULL");
96 req_info = _bt_get_request_info(func_data->req_id);
97 if (req_info == NULL) {
98 BT_ERR("req_info == NULL");
103 BT_ERR("HF Connect Dbus Call Error");
104 result = _bt_convert_gerror(g_error);
106 BT_ERR("Error: %s\n", g_error->message);
107 g_clear_error(&g_error);
110 g_variant_unref(reply);
113 if (req_info->context == NULL)
116 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
117 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
119 g_dbus_method_invocation_return_value(req_info->context,
120 g_variant_new("(iv)", result, out_param1));
122 _bt_delete_request_list(req_info->req_id);
126 g_free(func_data->address);
131 void _bt_audio_check_pending_connect()
134 bluetooth_device_address_t device_address;
139 if (pdata->pending == BT_PENDING_CONNECT) {
141 _bt_convert_addr_string_to_type(device_address.addr,
143 _bt_audio_connect(pdata->req_id,
148 g_free(pdata->address);
157 static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res,
160 GError *g_error = NULL;
161 GVariant *out_param1 = NULL;
162 GVariant *reply = NULL;
163 int result = BLUETOOTH_ERROR_NONE;
164 bt_audio_function_data_t *func_data;
165 request_info_t *req_info;
167 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
168 g_object_unref(proxy);
169 g_variant_unref(reply);
171 func_data = user_data;
173 if (func_data == NULL) {
175 BT_ERR("func_data == NULL");
179 if (func_data->pending != BT_PENDING_NONE && g_error == NULL) {
180 bluetooth_device_address_t device_address;
181 _bt_convert_addr_string_to_type(device_address.addr,
184 if (func_data->pending == BT_PENDING_CONNECT) {
186 if (__bt_device_support_uuid(func_data->address,
189 pdata = g_new0(bt_audio_function_data_t, 1);
190 pdata->req_id = func_data->req_id;
191 pdata->address = strdup(func_data->address);
192 pdata->pending = func_data->pending;
197 if (_bt_is_service_connected(func_data->address
199 _bt_audio_disconnect(func_data->req_id,
200 BT_AUDIO_HSP, &device_address, NULL);
212 BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
214 result = BLUETOOTH_ERROR_INTERNAL;
215 /* If there is error then we need to set local initiated connection as false
216 * If don't do this then when headset initiate connection for HFP then we don't
217 * initiate connection for A2dp to headset as this flag was set to true in first
218 * connection failure attempt and not set in error case.*/
219 _bt_headset_set_local_connection(FALSE);
221 /* Remove the device from the list */
222 _bt_remove_headset_from_list(func_data->type, func_data->address);
224 /* Error, check if any waiting device is there */
225 if (g_wait_data == NULL)
228 if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
229 bluetooth_device_address_t device_address;
230 _bt_convert_addr_string_to_type(device_address.addr,
231 g_wait_data->address);
232 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
233 &device_address, NULL);
236 /* Event will be sent by the event reciever */
238 req_info = _bt_get_request_info(func_data->req_id);
239 if (req_info == NULL) {
240 BT_ERR("req_info == NULL");
242 } else if (req_info->context == NULL) {
243 BT_ERR("req_info->context is NULL");
247 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
248 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
250 g_dbus_method_invocation_return_value(req_info->context,
251 g_variant_new("(iv)", result, out_param1));
253 _bt_delete_request_list(req_info->req_id);
255 g_clear_error(&g_error);
258 g_free(func_data->address);
263 static void __bt_free_wait_data()
265 if (g_wait_data != NULL) {
266 g_free(g_wait_data->address);
272 static void __bt_remove_device_from_wait_list()
274 /* Before deleting the request update the UI */
275 GVariant *out_param_1 = NULL;
276 int result = BLUETOOTH_ERROR_INTERNAL;
277 request_info_t *req_info;
279 req_info = _bt_get_request_info(g_wait_data->req_id);
280 if (req_info == NULL) {
281 BT_ERR("req_info == NULL");
285 out_param_1 = g_variant_new_from_data((const GVariantType *)"ay",
286 g_wait_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
288 g_dbus_method_invocation_return_value(req_info->context,
289 g_variant_new("(iv)", result, out_param_1));
291 _bt_delete_request_list(g_wait_data->req_id);
294 static void __bt_set_headset_disconnection_type(const char *address)
296 bt_connected_headset_data_t *connected_device;
299 node = g_list_first(g_connected_list);
300 while (node != NULL) {
301 connected_device = node->data;
302 if (g_strcmp0(connected_device->device_address, address) == 0) {
303 g_wait_data->disconnection_type = connected_device->type;
306 node = g_list_next(node);
310 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
311 void _bt_check_already_connected_headset(int type, char *address)
314 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
315 bluetooth_device_address_t device_address;
316 int device_count = 0;
318 if (address != NULL) {
319 node = g_list_first(g_connected_list);
320 while (node != NULL) {
321 bt_connected_headset_data_t *connected_device = node->data;
322 if ((connected_device->type & type) &&
323 (g_strcmp0(connected_device->device_address, address) != 0)) {
325 /* Disconnect the earliest(1st) connected headset */
326 if (device_count == 1) {
327 g_strlcpy(connected_address,
328 connected_device->device_address,
329 BT_ADDRESS_STRING_SIZE + 1);
330 BT_DBG("Earliest/First Connected headset %s",
332 } else if (device_count == MAX_CONNECTED_HEADSET) {
333 _bt_convert_addr_string_to_type(device_address.addr,
335 _bt_audio_disconnect(0, type, &device_address, NULL);
339 node = g_list_next(node);
345 gboolean _bt_is_headset_type_connected(int type, char *address)
349 node = g_list_first(g_connected_list);
350 while (node != NULL) {
351 bt_connected_headset_data_t *connected_device = node->data;
353 if (connected_device->type & type) {
355 g_strlcpy(address, connected_device->device_address,
356 BT_ADDRESS_STRING_SIZE + 1);
360 node = g_list_next(node);
365 #ifdef TIZEN_SUPPORT_DUAL_HF
366 gboolean __bt_is_companion_device(const char *addr)
368 if (TIZEN_PROFILE_WEARABLE) {
369 char *host_device_address = NULL;
370 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
372 if (!host_device_address) {
373 BT_INFO("Failed to get a companion device address");
377 if (g_strcmp0(host_device_address, addr) == 0) {
378 BT_INFO("Found companion device");
379 free(host_device_address);
383 free(host_device_address);
386 /* TODO : Need to add companion device check condition for Phone models */
392 static int __bt_is_headset_connected(int type, int req_id,
395 gboolean connected = FALSE;
396 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
397 bluetooth_device_address_t device_address;
398 bt_connected_headset_data_t *connected_device = NULL;
399 #ifdef TIZEN_SUPPORT_DUAL_HF
400 gboolean is_companion_device = FALSE;
403 /* Check if any other headset is connected */
406 node = g_list_first(g_connected_list);
407 while (node != NULL) {
408 connected_device = node->data;
409 if ((connected_device->type & type)) {
410 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
412 /* Disconnect the earliest(1st) connected headset */
413 if (device_count == 1)
414 g_strlcpy(connected_address, connected_device->device_address,
415 BT_ADDRESS_STRING_SIZE + 1);
417 if (g_strcmp0(connected_device->device_address, address) == 0)
418 return BLUETOOTH_ERROR_ALREADY_CONNECT;
420 g_strlcpy(connected_address, connected_device->device_address,
421 BT_ADDRESS_STRING_SIZE + 1);
423 #ifdef TIZEN_SUPPORT_DUAL_HF
424 is_companion_device = __bt_is_companion_device(connected_address);
425 BT_INFO(" is_companion_device[%d]", is_companion_device);
427 if (!is_companion_device) {
432 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
433 if (device_count == MAX_CONNECTED_HEADSET) {
443 node = g_list_next(node);
447 __bt_free_wait_data();
448 return BLUETOOTH_ERROR_NOT_CONNECTED;
451 BT_DBG("connected headset %s", connected_address);
453 if (g_strcmp0(connected_address, address) == 0)
454 return BLUETOOTH_ERROR_ALREADY_CONNECT;
455 #ifdef TIZEN_SUPPORT_DUAL_HF
456 else if (TRUE == __bt_is_companion_device(address))
457 return BLUETOOTH_ERROR_NOT_CONNECTED;
460 /* Convert BD adress from string type */
461 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
462 int value = BLUETOOTH_ERROR_NONE;
463 value = _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
465 /* If already one device is waiting, remove current waiting device and add new */
466 if (value == BLUETOOTH_ERROR_NONE) {
467 if (g_wait_data != NULL) {
468 if (g_strcmp0(g_wait_data->address, address) != 0) {
469 __bt_remove_device_from_wait_list();
470 __bt_free_wait_data();
474 if (g_wait_data == NULL) {
475 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
476 g_wait_data->address = g_strdup(address);
477 g_wait_data->req_id = req_id;
478 g_wait_data->type = type;
479 g_wait_data->ag_flag = FALSE;
481 /* Set disconnection type */
482 __bt_set_headset_disconnection_type(connected_address);
489 static int __bt_is_headset_connecting(int type)
491 bt_connected_headset_data_t *connected_device = NULL;
493 /* Check if any other headset is connected */
496 node = g_list_first(g_connected_list);
497 while (node != NULL) {
498 connected_device = node->data;
499 if (connected_device->device_state == BT_STATE_CONNECTING)
500 return BLUETOOTH_ERROR_CONNECTION_BUSY;
501 node = g_list_next(node);
504 return BLUETOOTH_ERROR_NONE;
507 int __bt_is_headset_disconnecting(int type)
509 bt_connected_headset_data_t *connected_device = NULL;
511 /* Check if any other headset is connected */
514 node = g_list_first(g_connected_list);
515 while (node != NULL) {
516 connected_device = node->data;
517 if (connected_device->device_state == BT_STATE_DISCONNECTING)
518 return BLUETOOTH_ERROR_CONNECTION_BUSY;
520 node = g_list_next(node);
523 return BLUETOOTH_ERROR_NONE;
526 void _bt_set_audio_wait_data_flag(gboolean flag)
528 BT_DBG("_bt_set_audio_wait_data_flag \n");
529 g_wait_data->ag_flag = flag;
532 bt_headset_wait_t *_bt_get_audio_wait_data(void)
534 BT_DBG("_bt_get_audio_wait_data \n");
538 void _bt_rel_wait_data(void)
540 BT_DBG("_bt_rel_wait_data \n");
541 __bt_free_wait_data();
544 void _bt_add_headset_to_list(int type, int status, const char *address)
546 bt_connected_headset_data_t *connected_device;
547 bt_connected_headset_data_t *device;
550 BT_DBG("_bt_add_headset_to_list \n");
552 node = g_list_first(g_connected_list);
553 while (node != NULL) {
554 device = (bt_connected_headset_data_t *)node->data;
556 if (g_strcmp0(device->device_address, address) == 0) {
557 BT_DBG("Address match, update connection type \n");
558 if (status == BT_STATE_CONNECTED)
559 device->type |= type;
560 device->device_state = status;
563 node = g_list_next(node);
566 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
567 connected_device->device_state = status;
568 if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
569 connected_device->type |= type;
570 g_strlcpy(connected_device->device_address, address,
571 sizeof(connected_device->device_address));
572 g_connected_list = g_list_append(g_connected_list, connected_device);
575 int _bt_get_device_state_from_list(int type, const char *address)
578 bt_connected_headset_data_t *device;
581 node = g_list_first(g_connected_list);
582 while (node != NULL) {
583 device = (bt_connected_headset_data_t *)node->data;
584 if (g_strcmp0(device->device_address, address) == 0) {
585 BT_DBG("Device found");
586 return device->device_state;
588 node = g_list_next(node);
591 BT_DBG("Device not found");
592 return BLUETOOTH_ERROR_INTERNAL;
595 void _bt_remove_headset_from_list(int type, const char *address)
599 BT_DBG("_bt_remove_headset_from_list \n");
601 node = g_list_first(g_connected_list);
602 while (node != NULL) {
603 bt_connected_headset_data_t *connected_device = node->data;
605 if (g_strcmp0(connected_device->device_address, address) != 0) {
606 node = g_list_next(node);
610 BT_DBG("Address match \n");
612 BT_DBG("Connection type = %x\n", connected_device->type);
616 if (connected_device->type & BT_AUDIO_A2DP)
617 connected_device->type &= ~(BT_AUDIO_A2DP);
620 if (connected_device->type & BT_AUDIO_HSP)
621 connected_device->type &= ~(BT_AUDIO_HSP);
624 if (connected_device->type & BT_AUDIO_ALL)
625 connected_device->type &= ~(BT_AUDIO_ALL);
628 if (connected_device->type & BT_AVRCP)
629 connected_device->type &= ~(BT_AVRCP);
631 case BT_AUDIO_A2DP_SOURCE:
632 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
633 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
636 BT_DBG("Connection type = %x\n", connected_device->type);
638 if (connected_device->type == 0x00) {
639 g_connected_list = g_list_remove(g_connected_list, connected_device);
640 g_free(connected_device);
642 connected_device->device_state = BT_STATE_CONNECTED;
645 node = g_list_next(node);
649 static gboolean __bt_device_support_uuid(char *remote_address,
650 bt_audio_type_t type)
652 GArray *dev_list = NULL;
656 bluetooth_device_info_t info;
657 char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
658 gboolean ret = FALSE;
662 dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
664 _bt_get_bonded_devices(&dev_list);
665 size = (dev_list->len) / sizeof(bluetooth_device_info_t);
667 for (i = 0; i < size; i++) {
668 info = g_array_index(dev_list, bluetooth_device_info_t, i);
669 _bt_convert_addr_type_to_string(bond_address,
670 info.device_address.addr);
671 if (strcmp(bond_address, remote_address) != 0)
674 BT_INFO("Device address Matched");
676 while (j != info.service_index) {
677 if (type == BT_AUDIO_HSP) {
678 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
679 BT_INFO("HFP HS UUID exists");
683 } else if (type == BT_AUDIO_A2DP) {
684 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
685 BT_INFO("A2DP SINK UUID exists");
694 g_array_free(dev_list, TRUE);
699 gboolean _bt_is_service_connected(char* address, int type)
703 node = g_list_first(g_connected_list);
704 while (node != NULL) {
705 bt_connected_headset_data_t *conn_device = node->data;
707 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
708 (conn_device->type & type)) {
709 BT_INFO("Service connected");
713 node = g_list_next(node);
715 BT_INFO("Service not connected");
719 int _bt_audio_connect(int request_id, int type,
720 bluetooth_device_address_t *device_address,
723 int result = BLUETOOTH_ERROR_NONE;
724 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
725 GDBusProxy *adapter_proxy;
726 GDBusConnection *g_conn;
729 int value = BLUETOOTH_ERROR_NONE;
730 bt_audio_function_data_t *func_data;
731 guint hfp_hs_restricted = 0x0; /* set default "allowed" */
732 guint a2dp_restricted = 0x0;
734 BT_CHECK_PARAMETER(device_address, return);
736 adapter_proxy = _bt_get_adapter_proxy();
737 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
739 g_conn = _bt_gdbus_get_system_gconn();
740 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
742 _bt_convert_addr_type_to_string(address, device_address->addr);
744 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
745 func_data->address = g_strdup(address);
746 func_data->req_id = request_id;
747 func_data->type = type;
748 func_data->pending = BT_PENDING_NONE;
750 result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_HFP_HS, &hfp_hs_restricted);
751 if (result != BLUETOOTH_ERROR_NONE)
752 BT_ERR("Can't get hfp_hs restriction info");
754 result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_A2DP, &a2dp_restricted);
755 if (result != BLUETOOTH_ERROR_NONE)
756 BT_ERR("Can't get a2dp restriction info");
763 uuid = A2DP_SINK_UUID;
766 uuid = AVRCP_TARGET_UUID;
768 case BT_AUDIO_A2DP_SOURCE:
769 uuid = A2DP_SOURCE_UUID;
772 if ((hfp_hs_restricted == 0x0) && (a2dp_restricted == 0x0)) { /* in case of both profiles are not restricted */
773 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
775 func_data->pending = BT_PENDING_CONNECT;
777 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
778 uuid = A2DP_SINK_UUID;
779 type = BT_AUDIO_A2DP;
781 BT_ERR("No audio role supported");
782 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
785 } else if ((hfp_hs_restricted == 0x1) && (a2dp_restricted == 0x1)) { /* in case of both profiles are restricted */
786 BT_ERR("All profiles are restricted");
787 result = BLUETOOTH_ERROR_INTERNAL;
789 } else if (a2dp_restricted == 0x01) { /* in case of a2dp is restricted, only connection for hfp_hs */
790 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
794 BT_ERR("HFP_HS role is not supported");
795 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
798 } else if (hfp_hs_restricted == 0x01) { /* in case of hfp_hs is restricted, only connection for a2dp */
799 if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
800 uuid = A2DP_SINK_UUID;
801 type = BT_AUDIO_A2DP;
803 BT_ERR("A2DP role is not supported");
804 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
809 case BT_AVRCP_TARGET:
810 uuid = AVRCP_REMOTE_UUID;
813 BT_ERR("Unknown role");
814 result = BLUETOOTH_ERROR_INTERNAL;
817 BT_INFO("Connecting to service %s", uuid);
818 /* First Check if device is in connecting state if it than return error */
819 value = __bt_is_headset_connecting(type);
820 if (value != BLUETOOTH_ERROR_NONE) {
821 result = BLUETOOTH_ERROR_IN_PROGRESS;
825 value = __bt_is_headset_connected(type, request_id, address);
827 if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
828 result = BLUETOOTH_ERROR_ALREADY_CONNECT;
830 } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
831 _bt_headset_set_local_connection(TRUE);
832 ret = _bt_connect_profile(address, uuid,
833 __bt_audio_request_cb, func_data);
835 if (ret != BLUETOOTH_ERROR_NONE) {
836 BT_ERR("_bt_connect_profile Error");
837 _bt_headset_set_local_connection(FALSE);
838 g_free(func_data->address);
843 /* Add data to the connected list */
844 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
845 } else if (value == BLUETOOTH_ERROR_IN_PROGRESS) {
846 result = BLUETOOTH_ERROR_IN_PROGRESS;
851 g_array_free(out_param1, TRUE);
853 return BLUETOOTH_ERROR_NONE;
855 if (out_param1 != NULL)
856 g_array_append_vals(out_param1, address,
859 g_free(func_data->address);
865 int _bt_audio_disconnect(int request_id, int type,
866 bluetooth_device_address_t *device_address,
869 int result = BLUETOOTH_ERROR_NONE;
870 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
871 bt_audio_function_data_t *func_data;
872 GDBusProxy *adapter_proxy;
873 GDBusConnection *g_conn;
877 int value = BLUETOOTH_ERROR_NONE;
879 BT_CHECK_PARAMETER(device_address, return);
881 adapter_proxy = _bt_get_adapter_proxy();
882 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
884 g_conn = _bt_gdbus_get_system_gconn();
885 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
887 _bt_convert_addr_type_to_string(address, device_address->addr);
889 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
890 func_data->address = g_strdup(address);
891 func_data->req_id = request_id;
892 func_data->pending = BT_PENDING_NONE;
893 func_data->type = type;
900 uuid = A2DP_SINK_UUID;
903 uuid = AVRCP_TARGET_UUID;
905 case BT_AUDIO_A2DP_SOURCE:
906 uuid = A2DP_SOURCE_UUID;
909 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
910 uuid = A2DP_SINK_UUID;
911 func_data->pending = BT_PENDING_DISCONNECT;
912 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
915 BT_ERR("No audio service connected");
916 result = BLUETOOTH_ERROR_NOT_CONNECTED;
920 case BT_AVRCP_TARGET:
921 uuid = AVRCP_REMOTE_UUID;
924 BT_ERR("Unknown role");
925 result = BLUETOOTH_ERROR_INTERNAL;
928 value = __bt_is_headset_disconnecting(type);
929 if (value != BLUETOOTH_ERROR_NONE) {
930 BT_INFO("Disconnect in progress");
931 result = BLUETOOTH_ERROR_IN_PROGRESS;
934 BT_INFO("Disconnecting service %s", uuid);
935 ret = _bt_disconnect_profile(address, uuid,
936 __bt_audio_request_cb, func_data);
938 if (ret != BLUETOOTH_ERROR_NONE) {
939 BT_ERR("_bt_disconnect_profile Error");
940 g_free(func_data->address);
946 * This logic is added for dual HF mode issue.
948 node = g_list_first(g_connected_list);
949 while (node != NULL) {
950 bt_connected_headset_data_t *connected_device = node->data;
952 if (g_strcmp0(connected_device->device_address, address) == 0) {
953 BT_DBG("Connection type update");
954 type = connected_device->type;
957 node = g_list_next(node);
959 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
962 g_array_free(out_param1, TRUE);
964 return BLUETOOTH_ERROR_NONE;
966 if (out_param1 != NULL)
967 g_array_append_vals(out_param1, address,
970 g_free(func_data->address);
976 void _bt_remove_from_connected_list(const char *address)
978 bt_connected_headset_data_t *connected_device;
981 node = g_list_first(g_connected_list);
982 while (node != NULL) {
983 connected_device = node->data;
984 if (connected_device != NULL &&
985 g_strcmp0(connected_device->device_address, address) == 0) {
986 BT_ERR("Device is removed from the list");
987 g_connected_list = g_list_remove(g_connected_list, connected_device);
988 g_free(connected_device);
991 node = g_list_next(node);
995 int _bt_hf_connect(int request_id,
996 bluetooth_device_address_t *device_address,
999 int result = BLUETOOTH_ERROR_NONE;
1000 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1001 bt_function_data_t *func_data;
1002 GDBusProxy *adapter_proxy;
1003 GDBusConnection *g_conn;
1004 gboolean connected = FALSE;
1008 BT_CHECK_PARAMETER(device_address, return);
1010 _bt_convert_addr_type_to_string(address, device_address->addr);
1012 adapter_proxy = _bt_get_adapter_proxy();
1013 if (adapter_proxy == NULL) {
1014 result = BLUETOOTH_ERROR_INTERNAL;
1018 g_conn = _bt_gdbus_get_system_gconn();
1019 if (g_conn == NULL) {
1020 result = BLUETOOTH_ERROR_INTERNAL;
1024 /* Check if HF is connected or not */
1025 result = _bt_is_device_connected(device_address, BT_PROFILE_CONN_HFG, &connected);
1026 if (connected == TRUE) {
1027 BT_ERR("HF is already connected");
1028 result = BLUETOOTH_ERROR_ALREADY_CONNECT;
1032 func_data = g_malloc0(sizeof(bt_function_data_t));
1033 func_data->address = g_strdup(address);
1034 func_data->req_id = request_id;
1035 uuid = g_strdup(HFP_AG_UUID);
1037 BT_DBG("Connecting to service %s", uuid);
1039 ret = _bt_connect_profile(address, uuid,
1040 __bt_hf_request_cb, func_data);
1042 if (ret != BLUETOOTH_ERROR_NONE) {
1043 BT_ERR("_bt_connect_profile Error");
1044 g_free(func_data->address);
1051 g_array_free(out_param1, TRUE);
1053 return BLUETOOTH_ERROR_NONE;
1055 if (out_param1 != NULL)
1056 g_array_append_vals(out_param1, address,
1057 BT_ADDRESS_STR_LEN);
1062 int _bt_hf_disconnect(int request_id,
1063 bluetooth_device_address_t *device_address,
1066 int result = BLUETOOTH_ERROR_NONE;
1067 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1068 bt_function_data_t *func_data;
1069 GDBusProxy *adapter_proxy;
1070 GDBusConnection *g_conn;
1075 BT_CHECK_PARAMETER(device_address, return);
1077 _bt_convert_addr_type_to_string(address, device_address->addr);
1079 adapter_proxy = _bt_get_adapter_proxy();
1080 if (adapter_proxy == NULL) {
1081 result = BLUETOOTH_ERROR_INTERNAL;
1085 g_conn = _bt_gdbus_get_system_gconn();
1086 if (g_conn == NULL) {
1087 result = BLUETOOTH_ERROR_INTERNAL;
1091 func_data = g_malloc0(sizeof(bt_function_data_t));
1092 func_data->address = g_strdup(address);
1093 func_data->req_id = request_id;
1094 uuid = g_strdup(HFP_AG_UUID);
1096 BT_DBG("Disconnecting service %s", uuid);
1097 ret = _bt_disconnect_profile(address, uuid,
1098 __bt_hf_request_cb, func_data);
1100 if (ret != BLUETOOTH_ERROR_NONE) {
1101 BT_ERR("_bt_disconnect_profile Error");
1102 g_free(func_data->address);
1109 g_array_free(out_param1, TRUE);
1111 return BLUETOOTH_ERROR_NONE;
1113 if (out_param1 != NULL)
1114 g_array_append_vals(out_param1, address,
1115 BT_ADDRESS_STR_LEN);
1120 int _bt_audio_set_content_protect(gboolean status)
1122 GDBusConnection *conn;
1123 GError *error = NULL;
1127 conn = _bt_gdbus_get_system_gconn();
1128 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1130 BT_DBG("Content Protection status = [%d]", status);
1132 g_dbus_connection_emit_signal(conn,
1133 NULL, BT_CONTENT_PROTECTION_PATH,
1134 BT_CONTENT_PROTECTION_INTERFACE,
1135 "ProtectionRequired",
1136 g_variant_new("(b)", status),
1140 /* dBUS gives error cause */
1141 ERR("Could not Emit Signal: errCode[%x], message[%s]",
1142 error->code, error->message);
1143 g_clear_error(&error);
1144 return BLUETOOTH_ERROR_INTERNAL;
1147 BT_DBG("Emit Signal done = [ProtectionRequired]");
1148 return BLUETOOTH_ERROR_NONE;
1151 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
1152 static void __bt_auto_connect_request_cb(GDBusProxy *proxy, GAsyncResult *res,
1156 GVariant *reply = NULL;
1158 reply = g_dbus_proxy_call_finish(proxy, res, &err);
1159 g_object_unref(proxy);
1160 g_variant_unref(reply);
1164 g_dbus_error_strip_remote_error(err);
1165 BT_INFO("Auto_connect_request Dbus Call Error: %s", err->message);
1167 if (strcmp("Host is down", err->message)) {
1168 BT_INFO("Fail reason is not 'Host Down'. Terminate auto connect");
1169 _bt_audio_stop_auto_connect();
1170 vconf_set_str(BT_LAST_CONNECTED_DEVICE, "");
1173 g_clear_error(&err);
1177 // It is the function that retry to create alarm.
1178 // Sometimes alarm mgr service is created later than bluetooth-frwk service in booting time.
1179 // So, in this case, we have to retry alarmmgr_add_alarm.
1180 static gboolean __bt_audio_alarm_retry_cb(gpointer data)
1183 alarm_id_t alarm_id;
1185 BT_DBG("__bt_audio_alarm_retry_cb called.");
1186 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1187 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1189 if (result != BLUETOOTH_ERROR_NONE)
1192 auto_connect_timer.alarm_id = alarm_id;
1197 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
1199 int result = BLUETOOTH_ERROR_NONE;
1200 char *address = NULL;
1201 alarm_id_t new_alarm_id;
1203 BT_INFO("alram id = [%d] , retry_count [%d] ",
1204 alarm_id, auto_connect_timer.retry_count);
1206 if (alarm_id != auto_connect_timer.alarm_id)
1209 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1211 if (address == NULL) {
1212 BT_ERR("Address vconf is null");
1213 auto_connect_timer.alarm_id = 0;
1217 BT_DBG("ADDRESS [%s]", address);
1219 result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
1220 __bt_auto_connect_request_cb, NULL);
1222 auto_connect_timer.retry_count--;
1224 BT_DBG("result [%d]", result);
1226 if (auto_connect_timer.retry_count <= 0) {
1227 BT_INFO("Stopping Auto connect retry");
1228 auto_connect_timer.alarm_id = 0;
1230 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1231 __bt_auto_connect_alarm_cb, NULL, &new_alarm_id);
1232 if (result == BLUETOOTH_ERROR_NONE)
1233 auto_connect_timer.alarm_id = new_alarm_id;
1240 static void __bt_auto_connect_alarm_remove()
1243 if (auto_connect_timer.alarm_id > 0) {
1244 _bt_service_remove_alarm(auto_connect_timer.alarm_id);
1245 auto_connect_timer.alarm_id = 0;
1247 auto_connect_timer.retry_count = 0;
1250 int _bt_audio_start_auto_connect(gboolean linkloss_flag)
1252 int result = BLUETOOTH_ERROR_NONE;
1253 char *address = NULL;
1254 alarm_id_t alarm_id = 0;
1258 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1260 if (address == NULL) {
1261 BT_ERR("No target device");
1265 __bt_auto_connect_alarm_remove();
1267 auto_connect_timer.retry_count = BT_AUTO_CONNECT_TIMEOUT_RETRY_TIME /
1268 BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS;
1270 if (linkloss_flag) {
1271 BT_INFO("Start auto connection after linkloss");
1272 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1273 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1274 if (result != BLUETOOTH_ERROR_NONE)
1275 g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
1277 auto_connect_timer.alarm_id = alarm_id;
1280 BT_INFO("Start auto connection after BT activated");
1281 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_BT_ACTIVATED,
1282 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1283 if (result == BLUETOOTH_ERROR_NONE)
1284 auto_connect_timer.alarm_id = alarm_id;
1288 return BLUETOOTH_ERROR_NONE;
1291 int _bt_audio_stop_auto_connect(void)
1294 __bt_auto_connect_alarm_remove();
1296 return BLUETOOTH_ERROR_NONE;
1299 void _bt_audio_set_auto_connect_device_addr(const char *address)
1301 if (address == NULL) {
1302 BT_ERR("address is null");
1306 BT_INFO("Last connected device is [%s]", address);
1307 vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
1309 #endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */
1311 int _bt_audio_select_role(bluetooth_audio_role_t role)
1316 GError *error = NULL;
1317 GDBusConnection *g_conn = _bt_gdbus_get_system_gconn();
1318 gchar *adapter_path = _bt_get_adapter_path();
1320 BT_INFO("_bt_audio_select_role called [%d]", role);
1322 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
1323 BT_INFO("Adapter Path = %s", adapter_path);
1325 proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1326 BT_BLUEZ_NAME, adapter_path, BT_MEDIA_INTERFACE, NULL, &error);
1328 g_free(adapter_path);
1330 if (proxy == NULL) {
1331 BT_ERR("Unable to create proxy");
1334 BT_ERR("Error: %s", error->message);
1335 g_clear_error(&error);
1338 return BLUETOOTH_ERROR_INTERNAL;
1341 if (role == BLUETOOTH_A2DP_SOURCE)
1342 ret = g_dbus_proxy_call_sync(proxy, "SelectRole", g_variant_new("(s)", "source"),
1343 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1345 ret = g_dbus_proxy_call_sync(proxy, "SelectRole", g_variant_new("(s)", "sink"),
1346 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1348 g_object_unref(proxy);
1351 BT_ERR("Call SelectRole Failed");
1353 BT_ERR("errCode[%x], message[%s]", error->code, error->message);
1354 g_clear_error(&error);
1357 return BLUETOOTH_ERROR_INTERNAL;
1360 g_variant_unref(ret);
1361 return BLUETOOTH_ERROR_NONE;