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 #ifdef TIZEN_PROFILE_WEARABLE
41 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
48 char device_address[BT_ADDRESS_STRING_SIZE + 1];
49 } bt_connected_headset_data_t;
51 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
55 } bt_auto_connect_timer_t;
57 bt_auto_connect_timer_t auto_connect_timer = {0, };
60 static GList *g_connected_list;
62 static bt_headset_wait_t *g_wait_data;
64 static bt_audio_function_data_t *pdata;
66 static void __bt_remove_device_from_wait_list();
68 static void __bt_free_wait_data();
70 static gboolean __bt_device_support_uuid(char *remote_address,
71 bt_audio_type_t type);
73 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
74 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param);
77 static void __bt_hf_request_cb(GDBusProxy *proxy, GAsyncResult *res,
80 GError *g_error = NULL;
81 GVariant *out_param1 = NULL;
82 GVariant *reply = NULL;
83 int result = BLUETOOTH_ERROR_NONE;
84 bt_function_data_t *func_data;
85 request_info_t *req_info;
87 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
88 g_object_unref(proxy);
90 func_data = user_data;
92 if (func_data == NULL) {
94 BT_ERR("func_data == NULL");
98 req_info = _bt_get_request_info(func_data->req_id);
99 if (req_info == NULL) {
100 BT_ERR("req_info == NULL");
105 BT_ERR("HF Connect Dbus Call Error");
106 result = _bt_convert_gerror(g_error);
108 BT_ERR("Error: %s\n", g_error->message);
109 g_clear_error(&g_error);
112 g_variant_unref(reply);
115 if (req_info->context == NULL)
118 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
119 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
121 g_dbus_method_invocation_return_value(req_info->context,
122 g_variant_new("(iv)", result, out_param1));
124 _bt_delete_request_list(req_info->req_id);
128 g_free(func_data->address);
133 void _bt_audio_check_pending_connect()
136 bluetooth_device_address_t device_address;
141 if (pdata->pending == BT_PENDING_CONNECT) {
143 _bt_convert_addr_string_to_type(device_address.addr,
145 _bt_audio_connect(pdata->req_id,
150 g_free(pdata->address);
159 static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res,
162 GError *g_error = NULL;
163 GVariant *out_param1 = NULL;
164 GVariant *reply = NULL;
165 int result = BLUETOOTH_ERROR_NONE;
166 bt_audio_function_data_t *func_data;
167 request_info_t *req_info;
169 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
170 g_object_unref(proxy);
171 g_variant_unref(reply);
173 func_data = user_data;
175 if (func_data == NULL) {
177 BT_ERR("func_data == NULL");
181 if (func_data->pending != BT_PENDING_NONE && g_error == NULL) {
182 bluetooth_device_address_t device_address;
183 _bt_convert_addr_string_to_type(device_address.addr,
186 if (func_data->pending == BT_PENDING_CONNECT) {
188 if (__bt_device_support_uuid(func_data->address,
191 pdata = g_new0(bt_audio_function_data_t, 1);
192 pdata->req_id = func_data->req_id;
193 pdata->address = strdup(func_data->address);
194 pdata->pending = func_data->pending;
199 if (_bt_is_service_connected(func_data->address
201 _bt_audio_disconnect(func_data->req_id,
202 BT_AUDIO_HSP, &device_address, NULL);
211 req_info = _bt_get_request_info(func_data->req_id);
212 if (req_info == NULL) {
213 BT_ERR("req_info == NULL");
220 BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
222 result = BLUETOOTH_ERROR_INTERNAL;
223 /* If there is error then we need to set local initiated connection as false
224 * If don't do this then when headset initiate connection for HFP then we don't
225 * initiate connection for A2dp to headset as this flag was set to true in first
226 * connection failure attempt and not set in error case.*/
227 _bt_headset_set_local_connection(FALSE);
229 /* Remove the device from the list */
230 _bt_remove_headset_from_list(func_data->type, func_data->address);
232 /* Error, check if any waiting device is there */
233 if (g_wait_data == NULL)
236 if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
237 bluetooth_device_address_t device_address;
238 _bt_convert_addr_string_to_type(device_address.addr,
239 g_wait_data->address);
240 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
241 &device_address, NULL);
244 /* Event will be sent by the event reciever */
246 if (req_info->context == NULL) {
247 BT_DBG("req_info->context is NULL");
251 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
252 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
254 g_dbus_method_invocation_return_value(req_info->context,
255 g_variant_new("(iv)", result, out_param1));
257 _bt_delete_request_list(req_info->req_id);
259 g_clear_error(&g_error);
262 g_free(func_data->address);
267 static void __bt_free_wait_data()
269 if (g_wait_data != NULL) {
270 g_free(g_wait_data->address);
276 static void __bt_remove_device_from_wait_list()
278 /* Before deleting the request update the UI */
279 GVariant *out_param_1 = NULL;
280 int result = BLUETOOTH_ERROR_INTERNAL;
281 request_info_t *req_info;
283 req_info = _bt_get_request_info(g_wait_data->req_id);
284 if (req_info == NULL) {
285 BT_ERR("req_info == NULL");
289 out_param_1 = g_variant_new_from_data((const GVariantType *)"ay",
290 g_wait_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
292 g_dbus_method_invocation_return_value(req_info->context,
293 g_variant_new("(iv)", result, out_param_1));
295 _bt_delete_request_list(g_wait_data->req_id);
298 static void __bt_set_headset_disconnection_type(const char *address)
300 bt_connected_headset_data_t *connected_device;
303 node = g_list_first(g_connected_list);
304 while (node != NULL) {
305 connected_device = node->data;
306 if (g_strcmp0(connected_device->device_address, address) == 0) {
307 g_wait_data->disconnection_type = connected_device->type;
310 node = g_list_next(node);
314 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
315 void _bt_check_already_connected_headset(int type, char *address)
318 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
319 bluetooth_device_address_t device_address;
320 int device_count = 0;
322 if (address != NULL) {
323 node = g_list_first(g_connected_list);
324 while (node != NULL) {
325 bt_connected_headset_data_t *connected_device = node->data;
326 if ((connected_device->type & type) &&
327 (g_strcmp0(connected_device->device_address, address) != 0)) {
329 /* Disconnect the earliest(1st) connected headset */
330 if (device_count == 1) {
331 g_strlcpy(connected_address,
332 connected_device->device_address,
333 BT_ADDRESS_STRING_SIZE + 1);
334 BT_DBG("Earliest/First Connected headset %s",
336 } else if (device_count == MAX_CONNECTED_HEADSET) {
337 _bt_convert_addr_string_to_type(device_address.addr,
339 _bt_audio_disconnect(0, type, &device_address, NULL);
343 node = g_list_next(node);
349 gboolean _bt_is_headset_type_connected(int type, char *address)
353 node = g_list_first(g_connected_list);
354 while (node != NULL) {
355 bt_connected_headset_data_t *connected_device = node->data;
357 if (connected_device->type & type) {
359 g_strlcpy(address, connected_device->device_address,
360 BT_ADDRESS_STRING_SIZE + 1);
364 node = g_list_next(node);
369 #ifdef TIZEN_SUPPORT_DUAL_HF
370 gboolean __bt_is_companion_device(const char *addr)
372 #ifdef TIZEN_PROFILE_WEARABLE
373 char *host_device_address = NULL;
374 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
376 if (!host_device_address) {
377 BT_INFO("Failed to get a companion device address");
381 if (g_strcmp0(host_device_address, addr) == 0) {
382 BT_INFO("Found companion device");
383 free(host_device_address);
387 free(host_device_address);
390 /* TODO : Need to add companion device check condition for Phone models */
396 static int __bt_is_headset_connected(int type, int req_id,
399 gboolean connected = FALSE;
400 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
401 bluetooth_device_address_t device_address;
402 bt_connected_headset_data_t *connected_device = NULL;
403 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
404 int device_count = 0;
407 #ifdef TIZEN_SUPPORT_DUAL_HF
408 gboolean is_companion_device = FALSE;
411 /* Check if any other headset is connected */
414 node = g_list_first(g_connected_list);
415 while (node != NULL) {
416 connected_device = node->data;
417 if ((connected_device->type & type)) {
418 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
420 /* Disconnect the earliest(1st) connected headset */
421 if (device_count == 1)
422 g_strlcpy(connected_address, connected_device->device_address,
423 BT_ADDRESS_STRING_SIZE + 1);
425 if (g_strcmp0(connected_device->device_address, address) == 0)
426 return BLUETOOTH_ERROR_ALREADY_CONNECT;
428 g_strlcpy(connected_address, connected_device->device_address,
429 BT_ADDRESS_STRING_SIZE + 1);
431 #ifdef TIZEN_SUPPORT_DUAL_HF
432 is_companion_device = __bt_is_companion_device(connected_address);
433 BT_INFO(" is_companion_device[%d]", is_companion_device);
435 if (!is_companion_device) {
440 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
441 if (device_count == MAX_CONNECTED_HEADSET) {
451 node = g_list_next(node);
455 __bt_free_wait_data();
456 return BLUETOOTH_ERROR_NOT_CONNECTED;
459 BT_DBG("connected headset %s", connected_address);
461 if (g_strcmp0(connected_address, address) == 0)
462 return BLUETOOTH_ERROR_ALREADY_CONNECT;
463 #ifdef TIZEN_SUPPORT_DUAL_HF
464 else if (TRUE == __bt_is_companion_device(address))
465 return BLUETOOTH_ERROR_NOT_CONNECTED;
468 /* Convert BD adress from string type */
469 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
470 int value = BLUETOOTH_ERROR_NONE;
471 value = _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
473 /* If already one device is waiting, remove current waiting device and add new */
474 if (value == BLUETOOTH_ERROR_NONE) {
475 if (g_wait_data != NULL) {
476 if (g_strcmp0(g_wait_data->address, address) != 0) {
477 __bt_remove_device_from_wait_list();
478 __bt_free_wait_data();
482 if (g_wait_data == NULL) {
483 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
484 g_wait_data->address = g_strdup(address);
485 g_wait_data->req_id = req_id;
486 g_wait_data->type = type;
487 g_wait_data->ag_flag = FALSE;
489 /* Set disconnection type */
490 __bt_set_headset_disconnection_type(connected_address);
497 static int __bt_is_headset_connecting(int type)
499 bt_connected_headset_data_t *connected_device = NULL;
501 /* Check if any other headset is connected */
504 node = g_list_first(g_connected_list);
505 while (node != NULL) {
506 connected_device = node->data;
507 if (connected_device->device_state == BT_STATE_CONNECTING)
508 return BLUETOOTH_ERROR_CONNECTION_BUSY;
509 node = g_list_next(node);
512 return BLUETOOTH_ERROR_NONE;
515 int __bt_is_headset_disconnecting(int type)
517 bt_connected_headset_data_t *connected_device = NULL;
519 /* Check if any other headset is connected */
522 node = g_list_first(g_connected_list);
523 while (node != NULL) {
524 connected_device = node->data;
525 if (connected_device->device_state == BT_STATE_DISCONNECTING)
526 return BLUETOOTH_ERROR_CONNECTION_BUSY;
528 node = g_list_next(node);
531 return BLUETOOTH_ERROR_NONE;
534 void _bt_set_audio_wait_data_flag(gboolean flag)
536 BT_DBG("_bt_set_audio_wait_data_flag \n");
537 g_wait_data->ag_flag = flag;
540 bt_headset_wait_t *_bt_get_audio_wait_data(void)
542 BT_DBG("_bt_get_audio_wait_data \n");
546 void _bt_rel_wait_data(void)
548 BT_DBG("_bt_rel_wait_data \n");
549 __bt_free_wait_data();
552 void _bt_add_headset_to_list(int type, int status, const char *address)
554 bt_connected_headset_data_t *connected_device;
555 bt_connected_headset_data_t *device;
558 BT_DBG("_bt_add_headset_to_list \n");
560 node = g_list_first(g_connected_list);
561 while (node != NULL) {
562 device = (bt_connected_headset_data_t *)node->data;
564 if (g_strcmp0(device->device_address, address) == 0) {
565 BT_DBG("Address match, update connection type \n");
566 if (status == BT_STATE_CONNECTED)
567 device->type |= type;
568 device->device_state = status;
571 node = g_list_next(node);
574 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
575 connected_device->device_state = status;
576 if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
577 connected_device->type |= type;
578 g_strlcpy(connected_device->device_address, address,
579 sizeof(connected_device->device_address));
580 g_connected_list = g_list_append(g_connected_list, connected_device);
583 int _bt_get_device_state_from_list(int type, const char *address)
586 bt_connected_headset_data_t *device;
589 node = g_list_first(g_connected_list);
590 while (node != NULL) {
591 device = (bt_connected_headset_data_t *)node->data;
592 if (g_strcmp0(device->device_address, address) == 0) {
593 BT_DBG("Device found");
594 return device->device_state;
596 node = g_list_next(node);
599 BT_DBG("Device not found");
600 return BLUETOOTH_ERROR_INTERNAL;
603 void _bt_remove_headset_from_list(int type, const char *address)
607 BT_DBG("_bt_remove_headset_from_list \n");
609 node = g_list_first(g_connected_list);
610 while (node != NULL) {
611 bt_connected_headset_data_t *connected_device = node->data;
613 if (g_strcmp0(connected_device->device_address, address) != 0) {
614 node = g_list_next(node);
618 BT_DBG("Address match \n");
620 BT_DBG("Connection type = %x\n", connected_device->type);
624 if (connected_device->type & BT_AUDIO_A2DP)
625 connected_device->type &= ~(BT_AUDIO_A2DP);
628 if (connected_device->type & BT_AUDIO_HSP)
629 connected_device->type &= ~(BT_AUDIO_HSP);
632 if (connected_device->type & BT_AUDIO_ALL)
633 connected_device->type &= ~(BT_AUDIO_ALL);
636 if (connected_device->type & BT_AVRCP)
637 connected_device->type &= ~(BT_AVRCP);
639 case BT_AUDIO_A2DP_SOURCE:
640 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
641 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
644 BT_DBG("Connection type = %x\n", connected_device->type);
646 if (connected_device->type == 0x00) {
647 g_connected_list = g_list_remove(g_connected_list, connected_device);
648 g_free(connected_device);
650 connected_device->device_state = BT_STATE_CONNECTED;
653 node = g_list_next(node);
657 static gboolean __bt_device_support_uuid(char *remote_address,
658 bt_audio_type_t type)
660 GArray *dev_list = NULL;
664 bluetooth_device_info_t info;
665 char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
666 gboolean ret = FALSE;
670 dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
672 _bt_get_bonded_devices(&dev_list);
673 size = (dev_list->len) / sizeof(bluetooth_device_info_t);
675 for (i = 0; i < size; i++) {
676 info = g_array_index(dev_list, bluetooth_device_info_t, i);
677 _bt_convert_addr_type_to_string(bond_address,
678 info.device_address.addr);
679 if (strcmp(bond_address, remote_address) != 0)
682 BT_INFO("Device address Matched");
684 while (j != info.service_index) {
685 if (type == BT_AUDIO_HSP) {
686 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
687 BT_INFO("HFP HS UUID exists");
691 } else if (type == BT_AUDIO_A2DP) {
692 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
693 BT_INFO("A2DP SINK UUID exists");
702 g_array_free(dev_list, TRUE);
707 gboolean _bt_is_service_connected(char* address, int type)
711 node = g_list_first(g_connected_list);
712 while (node != NULL) {
713 bt_connected_headset_data_t *conn_device = node->data;
715 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
716 (conn_device->type & type)) {
717 BT_INFO("Service connected");
721 node = g_list_next(node);
723 BT_INFO("Service not connected");
727 int _bt_audio_connect(int request_id, int type,
728 bluetooth_device_address_t *device_address,
731 int result = BLUETOOTH_ERROR_NONE;
732 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
733 GDBusProxy *adapter_proxy;
734 GDBusConnection *g_conn;
737 int value = BLUETOOTH_ERROR_NONE;
738 bt_audio_function_data_t *func_data;
739 guint hfp_hs_restricted = 0x0; /* set default "allowed" */
740 guint a2dp_restricted = 0x0;
742 BT_CHECK_PARAMETER(device_address, return);
744 adapter_proxy = _bt_get_adapter_proxy();
745 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
747 g_conn = _bt_gdbus_get_system_gconn();
748 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
750 _bt_convert_addr_type_to_string(address, device_address->addr);
752 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
753 func_data->address = g_strdup(address);
754 func_data->req_id = request_id;
755 func_data->type = type;
756 func_data->pending = BT_PENDING_NONE;
758 result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_HFP_HS, &hfp_hs_restricted);
759 if (result != BLUETOOTH_ERROR_NONE)
760 BT_ERR("Can't get hfp_hs restriction info");
762 result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_A2DP, &a2dp_restricted);
763 if (result != BLUETOOTH_ERROR_NONE)
764 BT_ERR("Can't get a2dp restriction info");
771 uuid = A2DP_SINK_UUID;
774 uuid = AVRCP_TARGET_UUID;
776 case BT_AUDIO_A2DP_SOURCE:
777 uuid = A2DP_SOURCE_UUID;
780 if ((hfp_hs_restricted == 0x0) && (a2dp_restricted == 0x0)) { /* in case of both profiles are not restricted */
781 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
783 func_data->pending = BT_PENDING_CONNECT;
785 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
786 uuid = A2DP_SINK_UUID;
787 type = BT_AUDIO_A2DP;
789 BT_ERR("No audio role supported");
790 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
793 } else if ((hfp_hs_restricted == 0x1) && (a2dp_restricted == 0x1)) { /* in case of both profiles are restricted */
794 BT_ERR("All profiles are restricted");
795 result = BLUETOOTH_ERROR_INTERNAL;
797 } else if (a2dp_restricted == 0x01) { /* in case of a2dp is restricted, only connection for hfp_hs */
798 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
802 BT_ERR("HFP_HS role is not supported");
803 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
806 } else if (hfp_hs_restricted == 0x01) { /* in case of hfp_hs is restricted, only connection for a2dp */
807 if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
808 uuid = A2DP_SINK_UUID;
809 type = BT_AUDIO_A2DP;
811 BT_ERR("A2DP role is not supported");
812 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
817 case BT_AVRCP_TARGET:
818 uuid = AVRCP_REMOTE_UUID;
821 BT_ERR("Unknown role");
822 result = BLUETOOTH_ERROR_INTERNAL;
825 BT_INFO("Connecting to service %s", uuid);
826 /* First Check if device is in connecting state if it than return error */
827 value = __bt_is_headset_connecting(type);
828 if (value != BLUETOOTH_ERROR_NONE) {
829 result = BLUETOOTH_ERROR_IN_PROGRESS;
833 value = __bt_is_headset_connected(type, request_id, address);
835 if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
836 result = BLUETOOTH_ERROR_ALREADY_CONNECT;
838 } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
839 _bt_headset_set_local_connection(TRUE);
840 ret = _bt_connect_profile(address, uuid,
841 __bt_audio_request_cb, func_data);
843 if (ret != BLUETOOTH_ERROR_NONE) {
844 BT_ERR("_bt_connect_profile Error");
845 _bt_headset_set_local_connection(FALSE);
846 g_free(func_data->address);
851 /* Add data to the connected list */
852 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
853 } else if (value == BLUETOOTH_ERROR_IN_PROGRESS) {
854 result = BLUETOOTH_ERROR_IN_PROGRESS;
859 g_array_free(out_param1, TRUE);
861 return BLUETOOTH_ERROR_NONE;
863 if (out_param1 != NULL)
864 g_array_append_vals(out_param1, address,
867 g_free(func_data->address);
873 int _bt_audio_disconnect(int request_id, int type,
874 bluetooth_device_address_t *device_address,
877 int result = BLUETOOTH_ERROR_NONE;
878 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
879 bt_audio_function_data_t *func_data;
880 GDBusProxy *adapter_proxy;
881 GDBusConnection *g_conn;
885 int value = BLUETOOTH_ERROR_NONE;
887 BT_CHECK_PARAMETER(device_address, return);
889 adapter_proxy = _bt_get_adapter_proxy();
890 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
892 g_conn = _bt_gdbus_get_system_gconn();
893 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
895 _bt_convert_addr_type_to_string(address, device_address->addr);
897 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
898 func_data->address = g_strdup(address);
899 func_data->req_id = request_id;
900 func_data->pending = BT_PENDING_NONE;
901 func_data->type = type;
908 uuid = A2DP_SINK_UUID;
911 uuid = AVRCP_TARGET_UUID;
913 case BT_AUDIO_A2DP_SOURCE:
914 uuid = A2DP_SOURCE_UUID;
917 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
918 uuid = A2DP_SINK_UUID;
919 func_data->pending = BT_PENDING_DISCONNECT;
920 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
923 BT_ERR("No audio service connected");
924 result = BLUETOOTH_ERROR_NOT_CONNECTED;
928 case BT_AVRCP_TARGET:
929 uuid = AVRCP_REMOTE_UUID;
932 BT_ERR("Unknown role");
933 result = BLUETOOTH_ERROR_INTERNAL;
936 value = __bt_is_headset_disconnecting(type);
937 if (value != BLUETOOTH_ERROR_NONE) {
938 BT_INFO("Disconnect in progress");
939 result = BLUETOOTH_ERROR_IN_PROGRESS;
942 BT_INFO("Disconnecting service %s", uuid);
943 ret = _bt_disconnect_profile(address, uuid,
944 __bt_audio_request_cb, func_data);
946 if (ret != BLUETOOTH_ERROR_NONE) {
947 BT_ERR("_bt_disconnect_profile Error");
948 g_free(func_data->address);
954 * This logic is added for dual HF mode issue.
956 node = g_list_first(g_connected_list);
957 while (node != NULL) {
958 bt_connected_headset_data_t *connected_device = node->data;
960 if (g_strcmp0(connected_device->device_address, address) == 0) {
961 BT_DBG("Connection type update");
962 type = connected_device->type;
965 node = g_list_next(node);
967 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
970 g_array_free(out_param1, TRUE);
972 return BLUETOOTH_ERROR_NONE;
974 if (out_param1 != NULL)
975 g_array_append_vals(out_param1, address,
978 g_free(func_data->address);
984 void _bt_remove_from_connected_list(const char *address)
986 bt_connected_headset_data_t *connected_device;
989 node = g_list_first(g_connected_list);
990 while (node != NULL) {
991 connected_device = node->data;
992 if (connected_device != NULL &&
993 g_strcmp0(connected_device->device_address, address) == 0) {
994 BT_ERR("Device is removed from the list");
995 g_connected_list = g_list_remove(g_connected_list, connected_device);
996 g_free(connected_device);
999 node = g_list_next(node);
1003 int _bt_hf_connect(int request_id,
1004 bluetooth_device_address_t *device_address,
1007 int result = BLUETOOTH_ERROR_NONE;
1008 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1009 bt_function_data_t *func_data;
1010 GDBusProxy *adapter_proxy;
1011 GDBusConnection *g_conn;
1012 gboolean connected = FALSE;
1016 BT_CHECK_PARAMETER(device_address, return);
1018 _bt_convert_addr_type_to_string(address, device_address->addr);
1020 adapter_proxy = _bt_get_adapter_proxy();
1021 if (adapter_proxy == NULL) {
1022 result = BLUETOOTH_ERROR_INTERNAL;
1026 g_conn = _bt_gdbus_get_system_gconn();
1027 if (g_conn == NULL) {
1028 result = BLUETOOTH_ERROR_INTERNAL;
1032 /* Check if HF is connected or not */
1033 result = _bt_is_device_connected(device_address, BT_PROFILE_CONN_HFG, &connected);
1034 if (connected == TRUE) {
1035 BT_ERR("HF is already connected");
1036 result = BLUETOOTH_ERROR_ALREADY_CONNECT;
1040 func_data = g_malloc0(sizeof(bt_function_data_t));
1041 func_data->address = g_strdup(address);
1042 func_data->req_id = request_id;
1043 uuid = g_strdup(HFP_AG_UUID);
1045 BT_DBG("Connecting to service %s", uuid);
1047 ret = _bt_connect_profile(address, uuid,
1048 __bt_hf_request_cb, func_data);
1050 if (ret != BLUETOOTH_ERROR_NONE) {
1051 BT_ERR("_bt_connect_profile Error");
1052 g_free(func_data->address);
1059 g_array_free(out_param1, TRUE);
1061 return BLUETOOTH_ERROR_NONE;
1063 if (out_param1 != NULL)
1064 g_array_append_vals(out_param1, address,
1065 BT_ADDRESS_STR_LEN);
1070 int _bt_hf_disconnect(int request_id,
1071 bluetooth_device_address_t *device_address,
1074 int result = BLUETOOTH_ERROR_NONE;
1075 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1076 bt_function_data_t *func_data;
1077 GDBusProxy *adapter_proxy;
1078 GDBusConnection *g_conn;
1083 BT_CHECK_PARAMETER(device_address, return);
1085 _bt_convert_addr_type_to_string(address, device_address->addr);
1087 adapter_proxy = _bt_get_adapter_proxy();
1088 if (adapter_proxy == NULL) {
1089 result = BLUETOOTH_ERROR_INTERNAL;
1093 g_conn = _bt_gdbus_get_system_gconn();
1094 if (g_conn == NULL) {
1095 result = BLUETOOTH_ERROR_INTERNAL;
1099 func_data = g_malloc0(sizeof(bt_function_data_t));
1100 func_data->address = g_strdup(address);
1101 func_data->req_id = request_id;
1102 uuid = g_strdup(HFP_AG_UUID);
1104 BT_DBG("Disconnecting service %s", uuid);
1105 ret = _bt_disconnect_profile(address, uuid,
1106 __bt_hf_request_cb, func_data);
1108 if (ret != BLUETOOTH_ERROR_NONE) {
1109 BT_ERR("_bt_disconnect_profile Error");
1110 g_free(func_data->address);
1117 g_array_free(out_param1, TRUE);
1119 return BLUETOOTH_ERROR_NONE;
1121 if (out_param1 != NULL)
1122 g_array_append_vals(out_param1, address,
1123 BT_ADDRESS_STR_LEN);
1128 int _bt_audio_set_content_protect(gboolean status)
1130 GDBusConnection *conn;
1131 GError *error = NULL;
1135 conn = _bt_gdbus_get_system_gconn();
1136 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1138 BT_DBG("Content Protection status = [%d]", status);
1140 g_dbus_connection_emit_signal(conn,
1141 NULL, BT_CONTENT_PROTECTION_PATH,
1142 BT_CONTENT_PROTECTION_INTERFACE,
1143 "ProtectionRequired",
1144 g_variant_new("(b)", status),
1148 /* dBUS gives error cause */
1149 ERR("Could not Emit Signal: errCode[%x], message[%s]",
1150 error->code, error->message);
1151 g_clear_error(&error);
1152 return BLUETOOTH_ERROR_INTERNAL;
1155 BT_DBG("Emit Signal done = [ProtectionRequired]");
1156 return BLUETOOTH_ERROR_NONE;
1159 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
1160 static void __bt_auto_connect_request_cb(GDBusProxy *proxy, GAsyncResult *res,
1164 GVariant *reply = NULL;
1166 reply = g_dbus_proxy_call_finish(proxy, res, &err);
1167 g_object_unref(proxy);
1168 g_variant_unref(reply);
1172 g_dbus_error_strip_remote_error(err);
1173 BT_INFO("Auto_connect_request Dbus Call Error: %s", err->message);
1175 if (strcmp("Host is down", err->message)) {
1176 BT_INFO("Fail reason is not 'Host Down'. Terminate auto connect");
1177 _bt_audio_stop_auto_connect();
1178 vconf_set_str(BT_LAST_CONNECTED_DEVICE, "");
1181 g_clear_error(&err);
1185 // It is the function that retry to create alarm.
1186 // Sometimes alarm mgr service is created later than bluetooth-frwk service in booting time.
1187 // So, in this case, we have to retry alarmmgr_add_alarm.
1188 static gboolean __bt_audio_alarm_retry_cb(gpointer data)
1191 alarm_id_t alarm_id;
1193 BT_DBG("__bt_audio_alarm_retry_cb called.");
1194 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1195 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1197 if (result != BLUETOOTH_ERROR_NONE)
1200 auto_connect_timer.alarm_id = alarm_id;
1205 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
1207 int result = BLUETOOTH_ERROR_NONE;
1208 char *address = NULL;
1209 alarm_id_t new_alarm_id;
1211 BT_INFO("alram id = [%d] , retry_count [%d] ",
1212 alarm_id, auto_connect_timer.retry_count);
1214 if (alarm_id != auto_connect_timer.alarm_id)
1217 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1219 if (address == NULL) {
1220 BT_ERR("Address vconf is null");
1221 auto_connect_timer.alarm_id = 0;
1225 BT_DBG("ADDRESS [%s]", address);
1227 result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
1228 __bt_auto_connect_request_cb, NULL);
1230 auto_connect_timer.retry_count--;
1232 BT_DBG("result [%d]", result);
1234 if (auto_connect_timer.retry_count <= 0) {
1235 BT_INFO("Stopping Auto connect retry");
1236 auto_connect_timer.alarm_id = 0;
1238 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1239 __bt_auto_connect_alarm_cb, NULL, &new_alarm_id);
1240 if (result == BLUETOOTH_ERROR_NONE)
1241 auto_connect_timer.alarm_id = new_alarm_id;
1248 static void __bt_auto_connect_alarm_remove()
1251 if (auto_connect_timer.alarm_id > 0) {
1252 _bt_service_remove_alarm(auto_connect_timer.alarm_id);
1253 auto_connect_timer.alarm_id = 0;
1255 auto_connect_timer.retry_count = 0;
1258 int _bt_audio_start_auto_connect(gboolean linkloss_flag)
1260 int result = BLUETOOTH_ERROR_NONE;
1261 char *address = NULL;
1262 alarm_id_t alarm_id = 0;
1266 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1268 if (address == NULL) {
1269 BT_ERR("No target device");
1273 __bt_auto_connect_alarm_remove();
1275 auto_connect_timer.retry_count = BT_AUTO_CONNECT_TIMEOUT_RETRY_TIME /
1276 BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS;
1278 if (linkloss_flag) {
1279 BT_INFO("Start auto connection after linkloss");
1280 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1281 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1282 if (result != BLUETOOTH_ERROR_NONE)
1283 g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
1285 auto_connect_timer.alarm_id = alarm_id;
1288 BT_INFO("Start auto connection after BT activated");
1289 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_BT_ACTIVATED,
1290 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1291 if (result == BLUETOOTH_ERROR_NONE)
1292 auto_connect_timer.alarm_id = alarm_id;
1296 return BLUETOOTH_ERROR_NONE;
1299 int _bt_audio_stop_auto_connect(void)
1302 __bt_auto_connect_alarm_remove();
1304 return BLUETOOTH_ERROR_NONE;
1307 void _bt_audio_set_auto_connect_device_addr(const char *address)
1309 if (address == NULL) {
1310 BT_ERR("address is null");
1314 BT_INFO("Last connected device is [%s]", address);
1315 vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
1317 #endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */