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);
209 req_info = _bt_get_request_info(func_data->req_id);
210 if (req_info == NULL) {
211 BT_ERR("req_info == NULL");
218 BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
220 result = BLUETOOTH_ERROR_INTERNAL;
221 /* If there is error then we need to set local initiated connection as false
222 * If don't do this then when headset initiate connection for HFP then we don't
223 * initiate connection for A2dp to headset as this flag was set to true in first
224 * connection failure attempt and not set in error case.*/
225 _bt_headset_set_local_connection(FALSE);
227 /* Remove the device from the list */
228 _bt_remove_headset_from_list(func_data->type, func_data->address);
230 /* Error, check if any waiting device is there */
231 if (g_wait_data == NULL)
234 if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
235 bluetooth_device_address_t device_address;
236 _bt_convert_addr_string_to_type(device_address.addr,
237 g_wait_data->address);
238 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
239 &device_address, NULL);
242 /* Event will be sent by the event reciever */
244 if (req_info->context == NULL) {
245 BT_DBG("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 gboolean _bt_is_headset_type_connected(int type, char *address)
316 node = g_list_first(g_connected_list);
317 while (node != NULL) {
318 bt_connected_headset_data_t *connected_device = node->data;
320 if (connected_device->type & type) {
322 g_strlcpy(address, connected_device->device_address,
323 BT_ADDRESS_STRING_SIZE + 1);
327 node = g_list_next(node);
332 #ifdef TIZEN_SUPPORT_DUAL_HF
333 gboolean __bt_is_companion_device(const char *addr)
335 if (TIZEN_PROFILE_WEARABLE) {
336 char *host_device_address = NULL;
337 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
339 if (!host_device_address) {
340 BT_INFO("Failed to get a companion device address");
344 if (g_strcmp0(host_device_address, addr) == 0) {
345 BT_INFO("Found companion device");
346 free(host_device_address);
350 free(host_device_address);
353 /* TODO : Need to add companion device check condition for Phone models */
359 static int __bt_is_headset_connected(int type, int req_id,
362 gboolean connected = FALSE;
363 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
364 bluetooth_device_address_t device_address;
365 bt_connected_headset_data_t *connected_device = NULL;
366 #ifdef TIZEN_SUPPORT_DUAL_HF
367 gboolean is_companion_device = FALSE;
370 /* Check if any other headset is connected */
373 node = g_list_first(g_connected_list);
374 while (node != NULL) {
375 connected_device = node->data;
376 if ((connected_device->type & type)) {
377 g_strlcpy(connected_address, connected_device->device_address,
378 BT_ADDRESS_STRING_SIZE + 1);
379 #ifdef TIZEN_SUPPORT_DUAL_HF
380 is_companion_device = __bt_is_companion_device(connected_address);
381 BT_INFO(" is_companion_device[%d]", is_companion_device);
383 if (!is_companion_device) {
392 node = g_list_next(node);
396 return BLUETOOTH_ERROR_NOT_CONNECTED;
398 BT_DBG("connected headset %s", connected_address);
400 if (g_strcmp0(connected_address, address) == 0)
401 return BLUETOOTH_ERROR_ALREADY_CONNECT;
402 #ifdef TIZEN_SUPPORT_DUAL_HF
403 else if (TRUE == __bt_is_companion_device(address))
404 return BLUETOOTH_ERROR_NOT_CONNECTED;
407 /* Convert BD adress from string type */
408 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
409 int value = BLUETOOTH_ERROR_NONE;
410 value = _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
412 /* If already one device is waiting, remove current waiting device and add new */
413 if (value == BLUETOOTH_ERROR_NONE) {
414 if (g_wait_data != NULL) {
415 if (g_strcmp0(g_wait_data->address, address) != 0) {
416 __bt_remove_device_from_wait_list();
417 __bt_free_wait_data();
421 if (g_wait_data == NULL) {
422 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
423 g_wait_data->address = g_strdup(address);
424 g_wait_data->req_id = req_id;
425 g_wait_data->type = type;
426 g_wait_data->ag_flag = FALSE;
428 /* Set disconnection type */
429 __bt_set_headset_disconnection_type(connected_address);
436 static int __bt_is_headset_connecting(int type)
438 bt_connected_headset_data_t *connected_device = NULL;
440 /* Check if any other headset is connected */
443 node = g_list_first(g_connected_list);
444 while (node != NULL) {
445 connected_device = node->data;
446 if (connected_device->device_state == BT_STATE_CONNECTING)
447 return BLUETOOTH_ERROR_CONNECTION_BUSY;
448 node = g_list_next(node);
451 return BLUETOOTH_ERROR_NONE;
454 int __bt_is_headset_disconnecting(int type)
456 bt_connected_headset_data_t *connected_device = NULL;
458 /* Check if any other headset is connected */
461 node = g_list_first(g_connected_list);
462 while (node != NULL) {
463 connected_device = node->data;
464 if (connected_device->device_state == BT_STATE_DISCONNECTING)
465 return BLUETOOTH_ERROR_CONNECTION_BUSY;
467 node = g_list_next(node);
470 return BLUETOOTH_ERROR_NONE;
473 void _bt_set_audio_wait_data_flag(gboolean flag)
475 BT_DBG("_bt_set_audio_wait_data_flag \n");
476 g_wait_data->ag_flag = flag;
479 bt_headset_wait_t *_bt_get_audio_wait_data(void)
481 BT_DBG("_bt_get_audio_wait_data \n");
485 void _bt_rel_wait_data(void)
487 BT_DBG("_bt_rel_wait_data \n");
488 __bt_free_wait_data();
491 void _bt_add_headset_to_list(int type, int status, const char *address)
493 bt_connected_headset_data_t *connected_device;
494 bt_connected_headset_data_t *device;
497 BT_DBG("_bt_add_headset_to_list \n");
499 node = g_list_first(g_connected_list);
500 while (node != NULL) {
501 device = (bt_connected_headset_data_t *)node->data;
503 if (g_strcmp0(device->device_address, address) == 0) {
504 BT_DBG("Address match, update connection type \n");
505 if (status == BT_STATE_CONNECTED)
506 device->type |= type;
507 device->device_state = status;
510 node = g_list_next(node);
513 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
514 connected_device->device_state = status;
515 if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
516 connected_device->type |= type;
517 g_strlcpy(connected_device->device_address, address,
518 sizeof(connected_device->device_address));
519 g_connected_list = g_list_append(g_connected_list, connected_device);
522 int _bt_get_device_state_from_list(int type, const char *address)
525 bt_connected_headset_data_t *device;
528 node = g_list_first(g_connected_list);
529 while (node != NULL) {
530 device = (bt_connected_headset_data_t *)node->data;
531 if (g_strcmp0(device->device_address, address) == 0) {
532 BT_DBG("Device found");
533 return device->device_state;
535 node = g_list_next(node);
538 BT_DBG("Device not found");
539 return BLUETOOTH_ERROR_INTERNAL;
542 void _bt_remove_headset_from_list(int type, const char *address)
546 BT_DBG("_bt_remove_headset_from_list \n");
548 node = g_list_first(g_connected_list);
549 while (node != NULL) {
550 bt_connected_headset_data_t *connected_device = node->data;
552 if (g_strcmp0(connected_device->device_address, address) != 0) {
553 node = g_list_next(node);
557 BT_DBG("Address match \n");
559 BT_DBG("Connection type = %x\n", connected_device->type);
563 if (connected_device->type & BT_AUDIO_A2DP)
564 connected_device->type &= ~(BT_AUDIO_A2DP);
567 if (connected_device->type & BT_AUDIO_HSP)
568 connected_device->type &= ~(BT_AUDIO_HSP);
571 if (connected_device->type & BT_AUDIO_ALL)
572 connected_device->type &= ~(BT_AUDIO_ALL);
575 if (connected_device->type & BT_AVRCP)
576 connected_device->type &= ~(BT_AVRCP);
578 case BT_AUDIO_A2DP_SOURCE:
579 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
580 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
583 BT_DBG("Connection type = %x\n", connected_device->type);
585 if (connected_device->type == 0x00) {
586 g_connected_list = g_list_remove(g_connected_list, connected_device);
587 g_free(connected_device);
589 connected_device->device_state = BT_STATE_CONNECTED;
592 node = g_list_next(node);
596 static gboolean __bt_device_support_uuid(char *remote_address,
597 bt_audio_type_t type)
599 GArray *dev_list = NULL;
603 bluetooth_device_info_t info;
604 char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
605 gboolean ret = FALSE;
609 dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
611 _bt_get_bonded_devices(&dev_list);
612 size = (dev_list->len) / sizeof(bluetooth_device_info_t);
614 for (i = 0; i < size; i++) {
615 info = g_array_index(dev_list, bluetooth_device_info_t, i);
616 _bt_convert_addr_type_to_string(bond_address,
617 info.device_address.addr);
618 if (strcmp(bond_address, remote_address) != 0)
621 BT_INFO("Device address Matched");
623 while (j != info.service_index) {
624 if (type == BT_AUDIO_HSP) {
625 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
626 BT_INFO("HFP HS UUID exists");
630 } else if (type == BT_AUDIO_A2DP) {
631 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
632 BT_INFO("A2DP SINK UUID exists");
641 g_array_free(dev_list, TRUE);
646 gboolean _bt_is_service_connected(char* address, int type)
650 node = g_list_first(g_connected_list);
651 while (node != NULL) {
652 bt_connected_headset_data_t *conn_device = node->data;
654 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
655 (conn_device->type & type)) {
656 BT_INFO("Service connected");
660 node = g_list_next(node);
662 BT_INFO("Service not connected");
666 int _bt_audio_connect(int request_id, int type,
667 bluetooth_device_address_t *device_address,
670 int result = BLUETOOTH_ERROR_NONE;
671 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
672 GDBusProxy *adapter_proxy;
673 GDBusConnection *g_conn;
676 int value = BLUETOOTH_ERROR_NONE;
677 bt_audio_function_data_t *func_data;
678 guint hfp_hs_restricted = 0x0; /* set default "allowed" */
679 guint a2dp_restricted = 0x0;
681 BT_CHECK_PARAMETER(device_address, return);
683 adapter_proxy = _bt_get_adapter_proxy();
684 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
686 g_conn = _bt_gdbus_get_system_gconn();
687 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
689 _bt_convert_addr_type_to_string(address, device_address->addr);
691 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
692 func_data->address = g_strdup(address);
693 func_data->req_id = request_id;
694 func_data->type = type;
695 func_data->pending = BT_PENDING_NONE;
697 result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_HFP_HS, &hfp_hs_restricted);
698 if (result != BLUETOOTH_ERROR_NONE)
699 BT_ERR("Can't get hfp_hs restriction info");
701 result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_A2DP, &a2dp_restricted);
702 if (result != BLUETOOTH_ERROR_NONE)
703 BT_ERR("Can't get a2dp restriction info");
710 uuid = A2DP_SINK_UUID;
713 uuid = AVRCP_TARGET_UUID;
715 case BT_AUDIO_A2DP_SOURCE:
716 uuid = A2DP_SOURCE_UUID;
719 if ((hfp_hs_restricted == 0x0) && (a2dp_restricted == 0x0)) { /* in case of both profiles are not restricted */
720 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
722 func_data->pending = BT_PENDING_CONNECT;
724 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
725 uuid = A2DP_SINK_UUID;
726 type = BT_AUDIO_A2DP;
728 BT_ERR("No audio role supported");
729 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
732 } else if ((hfp_hs_restricted == 0x1) && (a2dp_restricted == 0x1)) { /* in case of both profiles are restricted */
733 BT_ERR("All profiles are restricted");
734 result = BLUETOOTH_ERROR_INTERNAL;
736 } else if (a2dp_restricted == 0x01) { /* in case of a2dp is restricted, only connection for hfp_hs */
737 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
741 BT_ERR("HFP_HS role is not supported");
742 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
745 } else if (hfp_hs_restricted == 0x01) { /* in case of hfp_hs is restricted, only connection for a2dp */
746 if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
747 uuid = A2DP_SINK_UUID;
748 type = BT_AUDIO_A2DP;
750 BT_ERR("A2DP role is not supported");
751 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
756 case BT_AVRCP_TARGET:
757 uuid = AVRCP_REMOTE_UUID;
760 BT_ERR("Unknown role");
761 result = BLUETOOTH_ERROR_INTERNAL;
764 BT_INFO("Connecting to service %s", uuid);
766 value = __bt_is_headset_connected(type, request_id, address);
768 if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
769 return BLUETOOTH_ERROR_ALREADY_CONNECT;
770 } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
771 value = __bt_is_headset_connecting(type);
772 if (value != BLUETOOTH_ERROR_NONE) {
773 result = BLUETOOTH_ERROR_IN_PROGRESS;
776 _bt_headset_set_local_connection(TRUE);
777 ret = _bt_connect_profile(address, uuid,
778 __bt_audio_request_cb, func_data);
780 if (ret != BLUETOOTH_ERROR_NONE) {
781 BT_ERR("_bt_connect_profile Error");
782 _bt_headset_set_local_connection(FALSE);
783 g_free(func_data->address);
788 /* Add data to the connected list */
789 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
790 } else if (value == BLUETOOTH_ERROR_IN_PROGRESS) {
791 return BLUETOOTH_ERROR_IN_PROGRESS;
795 g_array_free(out_param1, TRUE);
797 return BLUETOOTH_ERROR_NONE;
799 if (out_param1 != NULL)
800 g_array_append_vals(out_param1, address,
806 int _bt_audio_disconnect(int request_id, int type,
807 bluetooth_device_address_t *device_address,
810 int result = BLUETOOTH_ERROR_NONE;
811 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
812 bt_audio_function_data_t *func_data;
813 GDBusProxy *adapter_proxy;
814 GDBusConnection *g_conn;
818 int value = BLUETOOTH_ERROR_NONE;
820 BT_CHECK_PARAMETER(device_address, return);
822 adapter_proxy = _bt_get_adapter_proxy();
823 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
825 g_conn = _bt_gdbus_get_system_gconn();
826 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
828 _bt_convert_addr_type_to_string(address, device_address->addr);
830 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
831 func_data->address = g_strdup(address);
832 func_data->req_id = request_id;
833 func_data->pending = BT_PENDING_NONE;
834 func_data->type = type;
841 uuid = A2DP_SINK_UUID;
844 uuid = AVRCP_TARGET_UUID;
846 case BT_AUDIO_A2DP_SOURCE:
847 uuid = A2DP_SOURCE_UUID;
850 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
851 uuid = A2DP_SINK_UUID;
852 func_data->pending = BT_PENDING_DISCONNECT;
853 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
856 BT_ERR("No audio service connected");
857 result = BLUETOOTH_ERROR_NOT_CONNECTED;
861 case BT_AVRCP_TARGET:
862 uuid = AVRCP_REMOTE_UUID;
865 BT_ERR("Unknown role");
866 result = BLUETOOTH_ERROR_INTERNAL;
869 value = __bt_is_headset_disconnecting(type);
870 if (value != BLUETOOTH_ERROR_NONE) {
871 BT_INFO("Disconnect in progress");
872 result = BLUETOOTH_ERROR_IN_PROGRESS;
875 BT_INFO("Disconnecting service %s", uuid);
876 ret = _bt_disconnect_profile(address, uuid,
877 __bt_audio_request_cb, func_data);
879 if (ret != BLUETOOTH_ERROR_NONE) {
880 BT_ERR("_bt_disconnect_profile Error");
881 g_free(func_data->address);
887 * This logic is added for dual HF mode issue.
889 node = g_list_first(g_connected_list);
890 while (node != NULL) {
891 bt_connected_headset_data_t *connected_device = node->data;
893 if (g_strcmp0(connected_device->device_address, address) == 0) {
894 BT_DBG("Connection type update");
895 type = connected_device->type;
898 node = g_list_next(node);
900 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
903 g_array_free(out_param1, TRUE);
905 return BLUETOOTH_ERROR_NONE;
907 if (out_param1 != NULL)
908 g_array_append_vals(out_param1, address,
914 void _bt_remove_from_connected_list(const char *address)
916 bt_connected_headset_data_t *connected_device;
919 node = g_list_first(g_connected_list);
920 while (node != NULL) {
921 connected_device = node->data;
922 if (connected_device != NULL &&
923 g_strcmp0(connected_device->device_address, address) == 0) {
924 BT_ERR("Device is removed from the list");
925 g_connected_list = g_list_remove(g_connected_list, connected_device);
926 g_free(connected_device);
929 node = g_list_next(node);
933 int _bt_hf_connect(int request_id,
934 bluetooth_device_address_t *device_address,
937 int result = BLUETOOTH_ERROR_NONE;
938 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
939 bt_function_data_t *func_data;
940 GDBusProxy *adapter_proxy;
941 GDBusConnection *g_conn;
942 gboolean connected = FALSE;
946 BT_CHECK_PARAMETER(device_address, return);
948 _bt_convert_addr_type_to_string(address, device_address->addr);
950 adapter_proxy = _bt_get_adapter_proxy();
951 if (adapter_proxy == NULL) {
952 result = BLUETOOTH_ERROR_INTERNAL;
956 g_conn = _bt_gdbus_get_system_gconn();
957 if (g_conn == NULL) {
958 result = BLUETOOTH_ERROR_INTERNAL;
962 /* Check if HF is connected or not */
963 result = _bt_is_device_connected(device_address, BT_PROFILE_CONN_HFG, &connected);
964 if (connected == TRUE) {
965 BT_ERR("HF is already connected");
966 result = BLUETOOTH_ERROR_ALREADY_CONNECT;
970 func_data = g_malloc0(sizeof(bt_function_data_t));
971 func_data->address = g_strdup(address);
972 func_data->req_id = request_id;
973 uuid = g_strdup(HFP_AG_UUID);
975 BT_DBG("Connecting to service %s", uuid);
977 ret = _bt_connect_profile(address, uuid,
978 __bt_hf_request_cb, func_data);
980 if (ret != BLUETOOTH_ERROR_NONE) {
981 BT_ERR("_bt_connect_profile Error");
982 g_free(func_data->address);
989 g_array_free(out_param1, TRUE);
991 return BLUETOOTH_ERROR_NONE;
993 if (out_param1 != NULL)
994 g_array_append_vals(out_param1, address,
1000 int _bt_hf_disconnect(int request_id,
1001 bluetooth_device_address_t *device_address,
1004 int result = BLUETOOTH_ERROR_NONE;
1005 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1006 bt_function_data_t *func_data;
1007 GDBusProxy *adapter_proxy;
1008 GDBusConnection *g_conn;
1013 BT_CHECK_PARAMETER(device_address, return);
1015 _bt_convert_addr_type_to_string(address, device_address->addr);
1017 adapter_proxy = _bt_get_adapter_proxy();
1018 if (adapter_proxy == NULL) {
1019 result = BLUETOOTH_ERROR_INTERNAL;
1023 g_conn = _bt_gdbus_get_system_gconn();
1024 if (g_conn == NULL) {
1025 result = BLUETOOTH_ERROR_INTERNAL;
1029 func_data = g_malloc0(sizeof(bt_function_data_t));
1030 func_data->address = g_strdup(address);
1031 func_data->req_id = request_id;
1032 uuid = g_strdup(HFP_AG_UUID);
1034 BT_DBG("Disconnecting service %s", uuid);
1035 ret = _bt_disconnect_profile(address, uuid,
1036 __bt_hf_request_cb, func_data);
1038 if (ret != BLUETOOTH_ERROR_NONE) {
1039 BT_ERR("_bt_disconnect_profile Error");
1040 g_free(func_data->address);
1047 g_array_free(out_param1, TRUE);
1049 return BLUETOOTH_ERROR_NONE;
1051 if (out_param1 != NULL)
1052 g_array_append_vals(out_param1, address,
1053 BT_ADDRESS_STR_LEN);
1058 int _bt_audio_set_content_protect(gboolean status)
1060 GDBusConnection *conn;
1061 GError *error = NULL;
1065 conn = _bt_gdbus_get_system_gconn();
1066 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1068 BT_DBG("Content Protection status = [%d]", status);
1070 g_dbus_connection_emit_signal(conn,
1071 NULL, BT_CONTENT_PROTECTION_PATH,
1072 BT_CONTENT_PROTECTION_INTERFACE,
1073 "ProtectionRequired",
1074 g_variant_new("(b)", status),
1078 /* dBUS gives error cause */
1079 ERR("Could not Emit Signal: errCode[%x], message[%s]",
1080 error->code, error->message);
1081 g_clear_error(&error);
1082 return BLUETOOTH_ERROR_INTERNAL;
1085 BT_DBG("Emit Signal done = [ProtectionRequired]");
1086 return BLUETOOTH_ERROR_NONE;
1089 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
1090 static void __bt_auto_connect_request_cb(GDBusProxy *proxy, GAsyncResult *res,
1094 GVariant *reply = NULL;
1096 reply = g_dbus_proxy_call_finish(proxy, res, &err);
1097 g_object_unref(proxy);
1098 g_variant_unref(reply);
1102 g_dbus_error_strip_remote_error(err);
1103 BT_INFO("Auto_connect_request Dbus Call Error: %s", err->message);
1105 if (strcmp("Host is down", err->message)) {
1106 BT_INFO("Fail reason is not 'Host Down'. Terminate auto connect");
1107 _bt_audio_stop_auto_connect();
1108 vconf_set_str(BT_LAST_CONNECTED_DEVICE, "");
1111 g_clear_error(&err);
1115 // It is the function that retry to create alarm.
1116 // Sometimes alarm mgr service is created later than bluetooth-frwk service in booting time.
1117 // So, in this case, we have to retry alarmmgr_add_alarm.
1118 static gboolean __bt_audio_alarm_retry_cb(gpointer data)
1121 alarm_id_t alarm_id;
1123 BT_DBG("__bt_audio_alarm_retry_cb called.");
1124 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1125 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1127 if (result != BLUETOOTH_ERROR_NONE)
1130 auto_connect_timer.alarm_id = alarm_id;
1135 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
1137 int result = BLUETOOTH_ERROR_NONE;
1138 char *address = NULL;
1139 alarm_id_t new_alarm_id;
1141 BT_INFO("alram id = [%d] , retry_count [%d] ",
1142 alarm_id, auto_connect_timer.retry_count);
1144 if (alarm_id != auto_connect_timer.alarm_id)
1147 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1149 if (address == NULL) {
1150 BT_ERR("Address vconf is null");
1151 auto_connect_timer.alarm_id = 0;
1155 BT_DBG("ADDRESS [%s]", address);
1157 result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
1158 __bt_auto_connect_request_cb, NULL);
1160 auto_connect_timer.retry_count--;
1162 BT_DBG("result [%d]", result);
1164 if (auto_connect_timer.retry_count <= 0) {
1165 BT_INFO("Stopping Auto connect retry");
1166 auto_connect_timer.alarm_id = 0;
1168 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1169 __bt_auto_connect_alarm_cb, NULL, &new_alarm_id);
1170 if (result == BLUETOOTH_ERROR_NONE)
1171 auto_connect_timer.alarm_id = new_alarm_id;
1178 static void __bt_auto_connect_alarm_remove()
1181 if (auto_connect_timer.alarm_id > 0) {
1182 _bt_service_remove_alarm(auto_connect_timer.alarm_id);
1183 auto_connect_timer.alarm_id = 0;
1185 auto_connect_timer.retry_count = 0;
1188 int _bt_audio_start_auto_connect(gboolean linkloss_flag)
1190 int result = BLUETOOTH_ERROR_NONE;
1191 char *address = NULL;
1192 alarm_id_t alarm_id = 0;
1196 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1198 if (address == NULL) {
1199 BT_ERR("No target device");
1203 __bt_auto_connect_alarm_remove();
1205 auto_connect_timer.retry_count = BT_AUTO_CONNECT_TIMEOUT_RETRY_TIME /
1206 BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS;
1208 if (linkloss_flag) {
1209 BT_INFO("Start auto connection after linkloss");
1210 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1211 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1212 if (result != BLUETOOTH_ERROR_NONE)
1213 g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
1215 auto_connect_timer.alarm_id = alarm_id;
1218 BT_INFO("Start auto connection after BT activated");
1219 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_BT_ACTIVATED,
1220 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1221 if (result == BLUETOOTH_ERROR_NONE)
1222 auto_connect_timer.alarm_id = alarm_id;
1226 return BLUETOOTH_ERROR_NONE;
1229 int _bt_audio_stop_auto_connect(void)
1232 __bt_auto_connect_alarm_remove();
1234 return BLUETOOTH_ERROR_NONE;
1237 void _bt_audio_set_auto_connect_device_addr(const char *address)
1239 if (address == NULL) {
1240 BT_ERR("address is null");
1244 BT_INFO("Last connected device is [%s]", address);
1245 vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
1247 #endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */