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);
214 BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
216 result = BLUETOOTH_ERROR_INTERNAL;
217 /* If there is error then we need to set local initiated connection as false
218 * If don't do this then when headset initiate connection for HFP then we don't
219 * initiate connection for A2dp to headset as this flag was set to true in first
220 * connection failure attempt and not set in error case.*/
221 _bt_headset_set_local_connection(FALSE);
223 /* Remove the device from the list */
224 _bt_remove_headset_from_list(func_data->type, func_data->address);
226 /* Error, check if any waiting device is there */
227 if (g_wait_data == NULL)
230 if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
231 bluetooth_device_address_t device_address;
232 _bt_convert_addr_string_to_type(device_address.addr,
233 g_wait_data->address);
234 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
235 &device_address, NULL);
238 /* Event will be sent by the event reciever */
240 req_info = _bt_get_request_info(func_data->req_id);
241 if (req_info == NULL) {
242 BT_ERR("req_info == NULL");
244 } else if (req_info->context == NULL) {
245 BT_ERR("req_info->context is NULL");
249 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
250 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
252 g_dbus_method_invocation_return_value(req_info->context,
253 g_variant_new("(iv)", result, out_param1));
255 _bt_delete_request_list(req_info->req_id);
257 g_clear_error(&g_error);
260 g_free(func_data->address);
265 static void __bt_free_wait_data()
267 if (g_wait_data != NULL) {
268 g_free(g_wait_data->address);
274 static void __bt_remove_device_from_wait_list()
276 /* Before deleting the request update the UI */
277 GVariant *out_param_1 = NULL;
278 int result = BLUETOOTH_ERROR_INTERNAL;
279 request_info_t *req_info;
281 req_info = _bt_get_request_info(g_wait_data->req_id);
282 if (req_info == NULL) {
283 BT_ERR("req_info == NULL");
287 out_param_1 = g_variant_new_from_data((const GVariantType *)"ay",
288 g_wait_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
290 g_dbus_method_invocation_return_value(req_info->context,
291 g_variant_new("(iv)", result, out_param_1));
293 _bt_delete_request_list(g_wait_data->req_id);
296 static void __bt_set_headset_disconnection_type(const char *address)
298 bt_connected_headset_data_t *connected_device;
301 node = g_list_first(g_connected_list);
302 while (node != NULL) {
303 connected_device = node->data;
304 if (g_strcmp0(connected_device->device_address, address) == 0) {
305 g_wait_data->disconnection_type = connected_device->type;
308 node = g_list_next(node);
312 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
313 void _bt_check_already_connected_headset(int type, char *address)
316 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
317 bluetooth_device_address_t device_address;
318 int device_count = 0;
320 if (address != NULL) {
321 node = g_list_first(g_connected_list);
322 while (node != NULL) {
323 bt_connected_headset_data_t *connected_device = node->data;
324 if ((connected_device->type & type) &&
325 (g_strcmp0(connected_device->device_address, address) != 0)) {
327 /* Disconnect the earliest(1st) connected headset */
328 if (device_count == 1) {
329 g_strlcpy(connected_address,
330 connected_device->device_address,
331 BT_ADDRESS_STRING_SIZE + 1);
332 BT_DBG("Earliest/First Connected headset %s",
334 } else if (device_count == MAX_CONNECTED_HEADSET) {
335 _bt_convert_addr_string_to_type(device_address.addr,
337 _bt_audio_disconnect(0, type, &device_address, NULL);
341 node = g_list_next(node);
347 gboolean _bt_is_headset_type_connected(int type, char *address)
351 node = g_list_first(g_connected_list);
352 while (node != NULL) {
353 bt_connected_headset_data_t *connected_device = node->data;
355 if (connected_device->type & type) {
357 g_strlcpy(address, connected_device->device_address,
358 BT_ADDRESS_STRING_SIZE + 1);
362 node = g_list_next(node);
367 #ifdef TIZEN_SUPPORT_DUAL_HF
368 gboolean __bt_is_companion_device(const char *addr)
370 #ifdef TIZEN_PROFILE_WEARABLE
371 char *host_device_address = NULL;
372 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
374 if (!host_device_address) {
375 BT_INFO("Failed to get a companion device address");
379 if (g_strcmp0(host_device_address, addr) == 0) {
380 BT_INFO("Found companion device");
381 free(host_device_address);
385 free(host_device_address);
388 /* TODO : Need to add companion device check condition for Phone models */
394 static int __bt_is_headset_connected(int type, int req_id,
397 gboolean connected = FALSE;
398 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
399 bluetooth_device_address_t device_address;
400 bt_connected_headset_data_t *connected_device = NULL;
401 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
402 int device_count = 0;
405 #ifdef TIZEN_SUPPORT_DUAL_HF
406 gboolean is_companion_device = FALSE;
409 /* Check if any other headset is connected */
412 node = g_list_first(g_connected_list);
413 while (node != NULL) {
414 connected_device = node->data;
415 if ((connected_device->type & type)) {
416 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
418 /* Disconnect the earliest(1st) connected headset */
419 if (device_count == 1)
420 g_strlcpy(connected_address, connected_device->device_address,
421 BT_ADDRESS_STRING_SIZE + 1);
423 if (g_strcmp0(connected_device->device_address, address) == 0)
424 return BLUETOOTH_ERROR_ALREADY_CONNECT;
426 g_strlcpy(connected_address, connected_device->device_address,
427 BT_ADDRESS_STRING_SIZE + 1);
429 #ifdef TIZEN_SUPPORT_DUAL_HF
430 is_companion_device = __bt_is_companion_device(connected_address);
431 BT_INFO(" is_companion_device[%d]", is_companion_device);
433 if (!is_companion_device) {
438 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
439 if (device_count == MAX_CONNECTED_HEADSET) {
449 node = g_list_next(node);
453 __bt_free_wait_data();
454 return BLUETOOTH_ERROR_NOT_CONNECTED;
457 BT_DBG("connected headset %s", connected_address);
459 if (g_strcmp0(connected_address, address) == 0)
460 return BLUETOOTH_ERROR_ALREADY_CONNECT;
461 #ifdef TIZEN_SUPPORT_DUAL_HF
462 else if (TRUE == __bt_is_companion_device(address))
463 return BLUETOOTH_ERROR_NOT_CONNECTED;
466 /* Convert BD adress from string type */
467 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
468 int value = BLUETOOTH_ERROR_NONE;
469 value = _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
471 /* If already one device is waiting, remove current waiting device and add new */
472 if (value == BLUETOOTH_ERROR_NONE) {
473 if (g_wait_data != NULL) {
474 if (g_strcmp0(g_wait_data->address, address) != 0) {
475 __bt_remove_device_from_wait_list();
476 __bt_free_wait_data();
480 if (g_wait_data == NULL) {
481 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
482 g_wait_data->address = g_strdup(address);
483 g_wait_data->req_id = req_id;
484 g_wait_data->type = type;
485 g_wait_data->ag_flag = FALSE;
487 /* Set disconnection type */
488 __bt_set_headset_disconnection_type(connected_address);
495 static int __bt_is_headset_connecting(int type)
497 bt_connected_headset_data_t *connected_device = NULL;
499 /* Check if any other headset is connected */
502 node = g_list_first(g_connected_list);
503 while (node != NULL) {
504 connected_device = node->data;
505 if (connected_device->device_state == BT_STATE_CONNECTING)
506 return BLUETOOTH_ERROR_CONNECTION_BUSY;
507 node = g_list_next(node);
510 return BLUETOOTH_ERROR_NONE;
513 int __bt_is_headset_disconnecting(int type)
515 bt_connected_headset_data_t *connected_device = NULL;
517 /* Check if any other headset is connected */
520 node = g_list_first(g_connected_list);
521 while (node != NULL) {
522 connected_device = node->data;
523 if (connected_device->device_state == BT_STATE_DISCONNECTING)
524 return BLUETOOTH_ERROR_CONNECTION_BUSY;
526 node = g_list_next(node);
529 return BLUETOOTH_ERROR_NONE;
532 void _bt_set_audio_wait_data_flag(gboolean flag)
534 BT_DBG("_bt_set_audio_wait_data_flag \n");
535 g_wait_data->ag_flag = flag;
538 bt_headset_wait_t *_bt_get_audio_wait_data(void)
540 BT_DBG("_bt_get_audio_wait_data \n");
544 void _bt_rel_wait_data(void)
546 BT_DBG("_bt_rel_wait_data \n");
547 __bt_free_wait_data();
550 void _bt_add_headset_to_list(int type, int status, const char *address)
552 bt_connected_headset_data_t *connected_device;
553 bt_connected_headset_data_t *device;
556 BT_DBG("_bt_add_headset_to_list \n");
558 node = g_list_first(g_connected_list);
559 while (node != NULL) {
560 device = (bt_connected_headset_data_t *)node->data;
562 if (g_strcmp0(device->device_address, address) == 0) {
563 BT_DBG("Address match, update connection type \n");
564 if (status == BT_STATE_CONNECTED)
565 device->type |= type;
566 device->device_state = status;
569 node = g_list_next(node);
572 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
573 connected_device->device_state = status;
574 if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
575 connected_device->type |= type;
576 g_strlcpy(connected_device->device_address, address,
577 sizeof(connected_device->device_address));
578 g_connected_list = g_list_append(g_connected_list, connected_device);
581 int _bt_get_device_state_from_list(int type, const char *address)
584 bt_connected_headset_data_t *device;
587 node = g_list_first(g_connected_list);
588 while (node != NULL) {
589 device = (bt_connected_headset_data_t *)node->data;
590 if (g_strcmp0(device->device_address, address) == 0) {
591 BT_DBG("Device found");
592 return device->device_state;
594 node = g_list_next(node);
597 BT_DBG("Device not found");
598 return BLUETOOTH_ERROR_INTERNAL;
601 void _bt_remove_headset_from_list(int type, const char *address)
605 BT_DBG("_bt_remove_headset_from_list \n");
607 node = g_list_first(g_connected_list);
608 while (node != NULL) {
609 bt_connected_headset_data_t *connected_device = node->data;
611 if (g_strcmp0(connected_device->device_address, address) != 0) {
612 node = g_list_next(node);
616 BT_DBG("Address match \n");
618 BT_DBG("Connection type = %x\n", connected_device->type);
622 if (connected_device->type & BT_AUDIO_A2DP)
623 connected_device->type &= ~(BT_AUDIO_A2DP);
626 if (connected_device->type & BT_AUDIO_HSP)
627 connected_device->type &= ~(BT_AUDIO_HSP);
630 if (connected_device->type & BT_AUDIO_ALL)
631 connected_device->type &= ~(BT_AUDIO_ALL);
634 if (connected_device->type & BT_AVRCP)
635 connected_device->type &= ~(BT_AVRCP);
637 case BT_AUDIO_A2DP_SOURCE:
638 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
639 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
642 BT_DBG("Connection type = %x\n", connected_device->type);
644 if (connected_device->type == 0x00) {
645 g_connected_list = g_list_remove(g_connected_list, connected_device);
646 g_free(connected_device);
648 connected_device->device_state = BT_STATE_CONNECTED;
651 node = g_list_next(node);
655 static gboolean __bt_device_support_uuid(char *remote_address,
656 bt_audio_type_t type)
658 GArray *dev_list = NULL;
662 bluetooth_device_info_t info;
663 char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
664 gboolean ret = FALSE;
668 dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
670 _bt_get_bonded_devices(&dev_list);
671 size = (dev_list->len) / sizeof(bluetooth_device_info_t);
673 for (i = 0; i < size; i++) {
674 info = g_array_index(dev_list, bluetooth_device_info_t, i);
675 _bt_convert_addr_type_to_string(bond_address,
676 info.device_address.addr);
677 if (strcmp(bond_address, remote_address) != 0)
680 BT_INFO("Device address Matched");
682 while (j != info.service_index) {
683 if (type == BT_AUDIO_HSP) {
684 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
685 BT_INFO("HFP HS UUID exists");
689 } else if (type == BT_AUDIO_A2DP) {
690 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
691 BT_INFO("A2DP SINK UUID exists");
700 g_array_free(dev_list, TRUE);
705 gboolean _bt_is_service_connected(char* address, int type)
709 node = g_list_first(g_connected_list);
710 while (node != NULL) {
711 bt_connected_headset_data_t *conn_device = node->data;
713 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
714 (conn_device->type & type)) {
715 BT_INFO("Service connected");
719 node = g_list_next(node);
721 BT_INFO("Service not connected");
725 int _bt_audio_connect(int request_id, int type,
726 bluetooth_device_address_t *device_address,
729 int result = BLUETOOTH_ERROR_NONE;
730 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
731 GDBusProxy *adapter_proxy;
732 GDBusConnection *g_conn;
735 int value = BLUETOOTH_ERROR_NONE;
736 bt_audio_function_data_t *func_data;
737 guint hfp_hs_trusted = TRUE; /* set default "allowed" */
738 guint a2dp_trusted = TRUE;
740 BT_CHECK_PARAMETER(device_address, return);
742 adapter_proxy = _bt_get_adapter_proxy();
743 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
745 g_conn = _bt_gdbus_get_system_gconn();
746 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
748 _bt_convert_addr_type_to_string(address, device_address->addr);
750 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
751 func_data->address = g_strdup(address);
752 func_data->req_id = request_id;
753 func_data->type = type;
754 func_data->pending = BT_PENDING_NONE;
756 result = _bt_get_trust_profile(device_address, TRUSTED_PROFILE_HFP_HF, &hfp_hs_trusted);
757 if (result != BLUETOOTH_ERROR_NONE)
758 BT_ERR("Can't get hfp_hs restriction info");
760 result = _bt_get_trust_profile(device_address, TRUSTED_PROFILE_A2DP, &a2dp_trusted);
761 if (result != BLUETOOTH_ERROR_NONE)
762 BT_ERR("Can't get a2dp restriction info");
769 uuid = A2DP_SINK_UUID;
772 uuid = AVRCP_TARGET_UUID;
774 case BT_AUDIO_A2DP_SOURCE:
775 uuid = A2DP_SOURCE_UUID;
778 if ((hfp_hs_trusted == TRUE) && (a2dp_trusted == TRUE)) { /* in case of both profiles are not restricted */
779 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
781 func_data->pending = BT_PENDING_CONNECT;
783 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
784 uuid = A2DP_SINK_UUID;
785 type = BT_AUDIO_A2DP;
787 BT_ERR("No audio role supported");
788 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
791 } else if ((hfp_hs_trusted == FALSE) && (a2dp_trusted == FALSE)) { /* in case of both profiles are restricted */
792 BT_ERR("All profiles are restricted");
793 result = BLUETOOTH_ERROR_INTERNAL;
795 } else if (a2dp_trusted == FALSE) { /* in case of a2dp is restricted, only connection for hfp_hs */
796 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
800 BT_ERR("HFP_HS role is not supported");
801 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
804 } else if (hfp_hs_trusted == FALSE) { /* in case of hfp_hs is restricted, only connection for a2dp */
805 if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
806 uuid = A2DP_SINK_UUID;
807 type = BT_AUDIO_A2DP;
809 BT_ERR("A2DP role is not supported");
810 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
815 case BT_AVRCP_TARGET:
816 uuid = AVRCP_REMOTE_UUID;
819 BT_ERR("Unknown role");
820 result = BLUETOOTH_ERROR_INTERNAL;
823 BT_INFO("Connecting to service %s", uuid);
824 /* First Check if device is in connecting state if it than return error */
825 value = __bt_is_headset_connecting(type);
826 if (value != BLUETOOTH_ERROR_NONE) {
827 result = BLUETOOTH_ERROR_IN_PROGRESS;
831 value = __bt_is_headset_connected(type, request_id, address);
833 if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
834 result = BLUETOOTH_ERROR_ALREADY_CONNECT;
836 } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
837 _bt_headset_set_local_connection(TRUE);
838 ret = _bt_connect_profile(address, uuid,
839 __bt_audio_request_cb, func_data);
841 if (ret != BLUETOOTH_ERROR_NONE) {
842 BT_ERR("_bt_connect_profile Error");
843 _bt_headset_set_local_connection(FALSE);
844 g_free(func_data->address);
849 /* Add data to the connected list */
850 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
851 } else if (value == BLUETOOTH_ERROR_IN_PROGRESS) {
852 result = BLUETOOTH_ERROR_IN_PROGRESS;
857 g_array_free(out_param1, TRUE);
859 return BLUETOOTH_ERROR_NONE;
861 if (out_param1 != NULL)
862 g_array_append_vals(out_param1, address,
865 g_free(func_data->address);
871 int _bt_audio_disconnect(int request_id, int type,
872 bluetooth_device_address_t *device_address,
875 int result = BLUETOOTH_ERROR_NONE;
876 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
877 bt_audio_function_data_t *func_data;
878 GDBusProxy *adapter_proxy;
879 GDBusConnection *g_conn;
883 int value = BLUETOOTH_ERROR_NONE;
885 BT_CHECK_PARAMETER(device_address, return);
887 adapter_proxy = _bt_get_adapter_proxy();
888 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
890 g_conn = _bt_gdbus_get_system_gconn();
891 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
893 _bt_convert_addr_type_to_string(address, device_address->addr);
895 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
896 func_data->address = g_strdup(address);
897 func_data->req_id = request_id;
898 func_data->pending = BT_PENDING_NONE;
899 func_data->type = type;
906 uuid = A2DP_SINK_UUID;
909 uuid = AVRCP_TARGET_UUID;
911 case BT_AUDIO_A2DP_SOURCE:
912 uuid = A2DP_SOURCE_UUID;
915 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
916 uuid = A2DP_SINK_UUID;
917 func_data->pending = BT_PENDING_DISCONNECT;
918 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
921 BT_ERR("No audio service connected");
922 result = BLUETOOTH_ERROR_NOT_CONNECTED;
926 case BT_AVRCP_TARGET:
927 uuid = AVRCP_REMOTE_UUID;
930 BT_ERR("Unknown role");
931 result = BLUETOOTH_ERROR_INTERNAL;
934 value = __bt_is_headset_disconnecting(type);
935 if (value != BLUETOOTH_ERROR_NONE) {
936 BT_INFO("Disconnect in progress");
937 result = BLUETOOTH_ERROR_IN_PROGRESS;
940 BT_INFO("Disconnecting service %s", uuid);
941 ret = _bt_disconnect_profile(address, uuid,
942 __bt_audio_request_cb, func_data);
944 if (ret != BLUETOOTH_ERROR_NONE) {
945 BT_ERR("_bt_disconnect_profile Error");
946 g_free(func_data->address);
952 * This logic is added for dual HF mode issue.
954 node = g_list_first(g_connected_list);
955 while (node != NULL) {
956 bt_connected_headset_data_t *connected_device = node->data;
958 if (g_strcmp0(connected_device->device_address, address) == 0) {
959 BT_DBG("Connection type update");
960 type = connected_device->type;
963 node = g_list_next(node);
965 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
968 g_array_free(out_param1, TRUE);
970 return BLUETOOTH_ERROR_NONE;
972 if (out_param1 != NULL)
973 g_array_append_vals(out_param1, address,
976 g_free(func_data->address);
982 void _bt_remove_from_connected_list(const char *address)
984 bt_connected_headset_data_t *connected_device;
987 node = g_list_first(g_connected_list);
988 while (node != NULL) {
989 connected_device = node->data;
990 if (connected_device != NULL &&
991 g_strcmp0(connected_device->device_address, address) == 0) {
992 BT_ERR("Device is removed from the list");
993 g_connected_list = g_list_remove(g_connected_list, connected_device);
994 g_free(connected_device);
997 node = g_list_next(node);
1001 int _bt_hf_connect(int request_id,
1002 bluetooth_device_address_t *device_address,
1005 int result = BLUETOOTH_ERROR_NONE;
1006 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1007 bt_function_data_t *func_data;
1008 GDBusProxy *adapter_proxy;
1009 GDBusConnection *g_conn;
1010 gboolean connected = FALSE;
1014 BT_CHECK_PARAMETER(device_address, return);
1016 _bt_convert_addr_type_to_string(address, device_address->addr);
1018 adapter_proxy = _bt_get_adapter_proxy();
1019 if (adapter_proxy == NULL) {
1020 result = BLUETOOTH_ERROR_INTERNAL;
1024 g_conn = _bt_gdbus_get_system_gconn();
1025 if (g_conn == NULL) {
1026 result = BLUETOOTH_ERROR_INTERNAL;
1030 /* Check if HF is connected or not */
1031 result = _bt_is_device_connected(device_address, BT_PROFILE_CONN_HFG, &connected);
1032 if (connected == TRUE) {
1033 BT_ERR("HF is already connected");
1034 result = BLUETOOTH_ERROR_ALREADY_CONNECT;
1038 func_data = g_malloc0(sizeof(bt_function_data_t));
1039 func_data->address = g_strdup(address);
1040 func_data->req_id = request_id;
1041 uuid = g_strdup(HFP_AG_UUID);
1043 BT_DBG("Connecting to service %s", uuid);
1045 ret = _bt_connect_profile(address, uuid,
1046 __bt_hf_request_cb, func_data);
1048 if (ret != BLUETOOTH_ERROR_NONE) {
1049 BT_ERR("_bt_connect_profile Error");
1050 g_free(func_data->address);
1057 g_array_free(out_param1, TRUE);
1059 return BLUETOOTH_ERROR_NONE;
1061 if (out_param1 != NULL)
1062 g_array_append_vals(out_param1, address,
1063 BT_ADDRESS_STR_LEN);
1068 int _bt_hf_disconnect(int request_id,
1069 bluetooth_device_address_t *device_address,
1072 int result = BLUETOOTH_ERROR_NONE;
1073 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1074 bt_function_data_t *func_data;
1075 GDBusProxy *adapter_proxy;
1076 GDBusConnection *g_conn;
1081 BT_CHECK_PARAMETER(device_address, return);
1083 _bt_convert_addr_type_to_string(address, device_address->addr);
1085 adapter_proxy = _bt_get_adapter_proxy();
1086 if (adapter_proxy == NULL) {
1087 result = BLUETOOTH_ERROR_INTERNAL;
1091 g_conn = _bt_gdbus_get_system_gconn();
1092 if (g_conn == NULL) {
1093 result = BLUETOOTH_ERROR_INTERNAL;
1097 func_data = g_malloc0(sizeof(bt_function_data_t));
1098 func_data->address = g_strdup(address);
1099 func_data->req_id = request_id;
1100 uuid = g_strdup(HFP_AG_UUID);
1102 BT_DBG("Disconnecting service %s", uuid);
1103 ret = _bt_disconnect_profile(address, uuid,
1104 __bt_hf_request_cb, func_data);
1106 if (ret != BLUETOOTH_ERROR_NONE) {
1107 BT_ERR("_bt_disconnect_profile Error");
1108 g_free(func_data->address);
1115 g_array_free(out_param1, TRUE);
1117 return BLUETOOTH_ERROR_NONE;
1119 if (out_param1 != NULL)
1120 g_array_append_vals(out_param1, address,
1121 BT_ADDRESS_STR_LEN);
1126 int _bt_audio_set_content_protect(gboolean status)
1128 GDBusConnection *conn;
1129 GError *error = NULL;
1133 conn = _bt_gdbus_get_system_gconn();
1134 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1136 BT_DBG("Content Protection status = [%d]", status);
1138 g_dbus_connection_emit_signal(conn,
1139 NULL, BT_CONTENT_PROTECTION_PATH,
1140 BT_CONTENT_PROTECTION_INTERFACE,
1141 "ProtectionRequired",
1142 g_variant_new("(b)", status),
1146 /* dBUS gives error cause */
1147 ERR("Could not Emit Signal: errCode[%x], message[%s]",
1148 error->code, error->message);
1149 g_clear_error(&error);
1150 return BLUETOOTH_ERROR_INTERNAL;
1153 BT_DBG("Emit Signal done = [ProtectionRequired]");
1154 return BLUETOOTH_ERROR_NONE;
1157 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
1158 static void __bt_auto_connect_request_cb(GDBusProxy *proxy, GAsyncResult *res,
1162 GVariant *reply = NULL;
1164 reply = g_dbus_proxy_call_finish(proxy, res, &err);
1165 g_object_unref(proxy);
1166 g_variant_unref(reply);
1170 g_dbus_error_strip_remote_error(err);
1171 BT_INFO("Auto_connect_request Dbus Call Error: %s", err->message);
1173 if (strcmp("Host is down", err->message)) {
1174 BT_INFO("Fail reason is not 'Host Down'. Terminate auto connect");
1175 _bt_audio_stop_auto_connect();
1176 vconf_set_str(BT_LAST_CONNECTED_DEVICE, "");
1179 g_clear_error(&err);
1183 // It is the function that retry to create alarm.
1184 // Sometimes alarm mgr service is created later than bluetooth-frwk service in booting time.
1185 // So, in this case, we have to retry alarmmgr_add_alarm.
1186 static gboolean __bt_audio_alarm_retry_cb(gpointer data)
1189 alarm_id_t alarm_id;
1191 BT_DBG("__bt_audio_alarm_retry_cb called.");
1192 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1193 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1195 if (result != BLUETOOTH_ERROR_NONE)
1198 auto_connect_timer.alarm_id = alarm_id;
1203 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
1205 int result = BLUETOOTH_ERROR_NONE;
1206 char *address = NULL;
1207 alarm_id_t new_alarm_id;
1209 BT_INFO("alram id = [%d] , retry_count [%d] ",
1210 alarm_id, auto_connect_timer.retry_count);
1212 if (alarm_id != auto_connect_timer.alarm_id)
1215 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1217 if (address == NULL) {
1218 BT_ERR("Address vconf is null");
1219 auto_connect_timer.alarm_id = 0;
1223 BT_DBG("ADDRESS [%s]", address);
1225 result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
1226 __bt_auto_connect_request_cb, NULL);
1228 auto_connect_timer.retry_count--;
1230 BT_DBG("result [%d]", result);
1232 if (auto_connect_timer.retry_count <= 0) {
1233 BT_INFO("Stopping Auto connect retry");
1234 auto_connect_timer.alarm_id = 0;
1236 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1237 __bt_auto_connect_alarm_cb, NULL, &new_alarm_id);
1238 if (result == BLUETOOTH_ERROR_NONE)
1239 auto_connect_timer.alarm_id = new_alarm_id;
1246 static void __bt_auto_connect_alarm_remove()
1249 if (auto_connect_timer.alarm_id > 0) {
1250 _bt_service_remove_alarm(auto_connect_timer.alarm_id);
1251 auto_connect_timer.alarm_id = 0;
1253 auto_connect_timer.retry_count = 0;
1256 int _bt_audio_start_auto_connect(gboolean linkloss_flag)
1258 int result = BLUETOOTH_ERROR_NONE;
1259 char *address = NULL;
1260 alarm_id_t alarm_id = 0;
1264 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1266 if (address == NULL) {
1267 BT_ERR("No target device");
1271 __bt_auto_connect_alarm_remove();
1273 auto_connect_timer.retry_count = BT_AUTO_CONNECT_TIMEOUT_RETRY_TIME /
1274 BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS;
1276 if (linkloss_flag) {
1277 BT_INFO("Start auto connection after linkloss");
1278 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1279 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1280 if (result != BLUETOOTH_ERROR_NONE)
1281 g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
1283 auto_connect_timer.alarm_id = alarm_id;
1286 BT_INFO("Start auto connection after BT activated");
1287 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_BT_ACTIVATED,
1288 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1289 if (result == BLUETOOTH_ERROR_NONE)
1290 auto_connect_timer.alarm_id = alarm_id;
1294 return BLUETOOTH_ERROR_NONE;
1297 int _bt_audio_stop_auto_connect(void)
1300 __bt_auto_connect_alarm_remove();
1302 return BLUETOOTH_ERROR_NONE;
1305 void _bt_audio_set_auto_connect_device_addr(const char *address)
1307 if (address == NULL) {
1308 BT_ERR("address is null");
1312 BT_INFO("Last connected device is [%s]", address);
1313 vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
1315 #endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */