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) {
183 bluetooth_device_address_t device_address;
184 _bt_convert_addr_string_to_type(device_address.addr,
187 if (func_data->pending == BT_PENDING_CONNECT) {
189 if (__bt_device_support_uuid(func_data->address,
192 pdata = g_new0(bt_audio_function_data_t, 1);
193 pdata->req_id = func_data->req_id;
194 pdata->out_param = func_data->out_param;
195 pdata->address = strdup(func_data->address);
196 pdata->pending = func_data->pending;
202 if (_bt_is_service_connected(func_data->address
204 _bt_audio_disconnect(func_data->req_id,
207 func_data->out_param);
216 req_info = _bt_get_request_info(func_data->req_id);
217 if (req_info == NULL) {
218 BT_ERR("req_info == NULL");
225 BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
227 result = BLUETOOTH_ERROR_INTERNAL;
228 /* If there is error then we need to set local initiated connection as false
229 * If don't do this then when headset initiate connection for HFP then we don't
230 * initiate connection for A2dp to headset as this flag was set to true in first
231 * connection failure attempt and not set in error case.*/
232 _bt_headset_set_local_connection(FALSE);
234 /* Remove the device from the list */
235 _bt_remove_headset_from_list(func_data->type, func_data->address);
237 /* Error, check if any waiting device is there */
238 if (g_wait_data == NULL)
241 if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
242 bluetooth_device_address_t device_address;
243 _bt_convert_addr_string_to_type(device_address.addr,
244 g_wait_data->address);
245 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
246 &device_address, g_wait_data->out_param1);
249 /* Event will be sent by the event reciever */
251 if (req_info->context == NULL) {
252 BT_DBG("req_info->context is NULL");
256 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
257 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
259 g_dbus_method_invocation_return_value(req_info->context,
260 g_variant_new("(iv)", result, out_param1));
262 _bt_delete_request_list(req_info->req_id);
264 g_clear_error(&g_error);
267 g_free(func_data->address);
272 static void __bt_free_wait_data()
274 if (g_wait_data != NULL) {
275 g_free(g_wait_data->address);
281 static void __bt_remove_device_from_wait_list()
283 /* Before deleting the request update the UI */
284 GVariant *out_param_1 = NULL;
285 int result = BLUETOOTH_ERROR_INTERNAL;
286 request_info_t *req_info;
288 req_info = _bt_get_request_info(g_wait_data->req_id);
289 if (req_info == NULL) {
290 BT_ERR("req_info == NULL");
294 out_param_1 = g_variant_new_from_data((const GVariantType *)"ay",
295 g_wait_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
297 g_dbus_method_invocation_return_value(req_info->context,
298 g_variant_new("(iv)", result, out_param_1));
300 _bt_delete_request_list(g_wait_data->req_id);
303 static void __bt_set_headset_disconnection_type(const char *address)
305 bt_connected_headset_data_t *connected_device;
308 node = g_list_first(g_connected_list);
309 while (node != NULL) {
310 connected_device = node->data;
311 if (g_strcmp0(connected_device->device_address, address) == 0) {
312 g_wait_data->disconnection_type = connected_device->type;
315 node = g_list_next(node);
319 gboolean _bt_is_headset_type_connected(int type, char *address)
323 node = g_list_first(g_connected_list);
324 while (node != NULL) {
325 bt_connected_headset_data_t *connected_device = node->data;
327 if (connected_device->type & type) {
329 g_strlcpy(address, connected_device->device_address,
330 BT_ADDRESS_STRING_SIZE + 1);
334 node = g_list_next(node);
339 #ifdef TIZEN_SUPPORT_DUAL_HF
340 gboolean __bt_is_companion_device(const char *addr)
342 #ifdef TIZEN_PROFILE_WEARABLE
343 char *host_device_address = NULL;
344 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
346 if (!host_device_address) {
347 BT_INFO("Failed to get a companion device address");
351 if (g_strcmp0(host_device_address, addr) == 0) {
352 BT_INFO("Found companion device");
353 free(host_device_address);
357 free(host_device_address);
360 /* TODO : Need to add companion device check condition for Phone models */
366 static int __bt_is_headset_connected(int type, int req_id,
367 const char *address, GArray *out_param1)
369 gboolean connected = FALSE;
370 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
371 bluetooth_device_address_t device_address;
372 bt_connected_headset_data_t *connected_device = NULL;
373 #ifdef TIZEN_SUPPORT_DUAL_HF
374 gboolean is_companion_device = FALSE;
377 /* Check if any other headset is connected */
380 node = g_list_first(g_connected_list);
381 while (node != NULL) {
382 connected_device = node->data;
383 if ((connected_device->type & type)) {
384 g_strlcpy(connected_address, connected_device->device_address,
385 BT_ADDRESS_STRING_SIZE + 1);
386 #ifdef TIZEN_SUPPORT_DUAL_HF
387 is_companion_device = __bt_is_companion_device(connected_address);
388 BT_INFO(" is_companion_device[%d]", is_companion_device);
390 if (!is_companion_device) {
399 node = g_list_next(node);
403 return BLUETOOTH_ERROR_NOT_CONNECTED;
405 BT_DBG("connected headset %s", connected_address);
407 if (g_strcmp0(connected_address, address) == 0)
408 return BLUETOOTH_ERROR_ALREADY_CONNECT;
409 #ifdef TIZEN_SUPPORT_DUAL_HF
410 else if (TRUE == __bt_is_companion_device(address))
411 return BLUETOOTH_ERROR_NOT_CONNECTED;
414 /* Convert BD adress from string type */
415 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
416 int value = BLUETOOTH_ERROR_NONE;
417 value = _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
419 /* If already one device is waiting, remove current waiting device and add new */
420 if (value == BLUETOOTH_ERROR_NONE) {
421 if (g_wait_data != NULL) {
422 if (g_strcmp0(g_wait_data->address, address) != 0) {
423 __bt_remove_device_from_wait_list();
424 __bt_free_wait_data();
428 if (g_wait_data == NULL) {
429 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
430 g_wait_data->address = g_strdup(address);
431 g_wait_data->req_id = req_id;
432 g_wait_data->type = type;
433 g_wait_data->ag_flag = FALSE;
434 g_wait_data->out_param1 = out_param1;
436 /* Set disconnection type */
437 __bt_set_headset_disconnection_type(connected_address);
446 static int __bt_is_headset_connecting(int type)
448 bt_connected_headset_data_t *connected_device = NULL;
450 /* Check if any other headset is connected */
453 node = g_list_first(g_connected_list);
454 while (node != NULL) {
455 connected_device = node->data;
456 if (connected_device->device_state == BT_STATE_CONNECTING)
457 return BLUETOOTH_ERROR_CONNECTION_BUSY;
458 node = g_list_next(node);
461 return BLUETOOTH_ERROR_NONE;
465 int __bt_is_headset_disconnecting(int type)
467 bt_connected_headset_data_t *connected_device = NULL;
469 /* Check if any other headset is connected */
472 node = g_list_first(g_connected_list);
473 while (node != NULL) {
474 connected_device = node->data;
475 if (connected_device->device_state == BT_STATE_DISCONNECTING) {
476 return BLUETOOTH_ERROR_CONNECTION_BUSY;
478 node = g_list_next(node);
481 return BLUETOOTH_ERROR_NONE;
485 void _bt_set_audio_wait_data_flag(gboolean flag)
487 BT_DBG("_bt_set_audio_wait_data_flag \n");
488 g_wait_data->ag_flag = flag;
491 bt_headset_wait_t *_bt_get_audio_wait_data(void)
493 BT_DBG("_bt_get_audio_wait_data \n");
497 void _bt_rel_wait_data(void)
499 BT_DBG("_bt_rel_wait_data \n");
500 __bt_free_wait_data();
503 void _bt_add_headset_to_list(int type, int status, const char *address)
505 bt_connected_headset_data_t *connected_device;
506 bt_connected_headset_data_t *device;
509 BT_DBG("_bt_add_headset_to_list \n");
511 node = g_list_first(g_connected_list);
512 while (node != NULL) {
513 device = (bt_connected_headset_data_t *)node->data;
515 if (g_strcmp0(device->device_address, address) == 0) {
516 BT_DBG("Address match, update connection type \n");
517 if (status == BT_STATE_CONNECTED)
518 device->type |= type;
519 device->device_state = status;
522 node = g_list_next(node);
525 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
526 /* Fix : NULL_RETURNS */
527 if (connected_device == NULL) {
528 BT_ERR("No memory allocated");
532 connected_device->device_state = status;
533 if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
534 connected_device->type |= type;
535 g_strlcpy(connected_device->device_address, address,
536 sizeof(connected_device->device_address));
537 g_connected_list = g_list_append(g_connected_list, connected_device);
540 int _bt_get_device_state_from_list(int type, const char *address)
543 bt_connected_headset_data_t *device;
546 node = g_list_first(g_connected_list);
547 while (node != NULL) {
548 device = (bt_connected_headset_data_t *)node->data;
549 if (g_strcmp0(device->device_address, address) == 0) {
550 BT_DBG("Device found");
551 return device->device_state;
553 node = g_list_next(node);
556 BT_DBG("Device not found");
557 return BLUETOOTH_ERROR_INTERNAL;
560 void _bt_remove_headset_from_list(int type, const char *address)
564 BT_DBG("_bt_remove_headset_from_list \n");
566 node = g_list_first(g_connected_list);
567 while (node != NULL) {
568 bt_connected_headset_data_t *connected_device = node->data;
570 if (g_strcmp0(connected_device->device_address, address) != 0) {
571 node = g_list_next(node);
575 BT_DBG("Address match \n");
577 BT_DBG("Connection type = %x\n", connected_device->type);
581 if (connected_device->type & BT_AUDIO_A2DP)
582 connected_device->type &= ~(BT_AUDIO_A2DP);
585 if (connected_device->type & BT_AUDIO_HSP)
586 connected_device->type &= ~(BT_AUDIO_HSP);
589 if (connected_device->type & BT_AUDIO_ALL)
590 connected_device->type &= ~(BT_AUDIO_ALL);
593 if (connected_device->type & BT_AVRCP)
594 connected_device->type &= ~(BT_AVRCP);
596 case BT_AUDIO_A2DP_SOURCE:
597 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
598 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
601 BT_DBG("Connection type = %x\n", connected_device->type);
603 if (connected_device->type == 0x00) {
604 g_connected_list = g_list_remove(g_connected_list, connected_device);
605 g_free(connected_device);
607 connected_device->device_state = BT_STATE_CONNECTED;
610 node = g_list_next(node);
614 static gboolean __bt_device_support_uuid(char *remote_address,
615 bt_audio_type_t type)
617 GArray *dev_list = NULL;
621 bluetooth_device_info_t info;
622 char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
623 gboolean ret = FALSE;
627 dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
629 _bt_get_bonded_devices(&dev_list);
630 size = (dev_list->len) / sizeof(bluetooth_device_info_t);
632 for (i = 0; i < size; i++) {
633 info = g_array_index(dev_list, bluetooth_device_info_t, i);
634 _bt_convert_addr_type_to_string(bond_address,
635 info.device_address.addr);
636 if (strcmp(bond_address, remote_address) != 0)
639 BT_INFO("Device address Matched");
641 while (j != info.service_index) {
642 if (type == BT_AUDIO_HSP) {
643 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
644 BT_INFO("HFP HS UUID exists");
648 } else if (type == BT_AUDIO_A2DP) {
649 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
650 BT_INFO("A2DP SINK UUID exists");
659 g_array_free(dev_list, TRUE);
664 gboolean _bt_is_service_connected(char* address, int type)
668 node = g_list_first(g_connected_list);
669 while (node != NULL) {
670 bt_connected_headset_data_t *conn_device = node->data;
672 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
673 (conn_device->type & type)) {
674 BT_INFO("Service connected");
678 node = g_list_next(node);
680 BT_INFO("Service not connected");
684 int _bt_audio_connect(int request_id, int type,
685 bluetooth_device_address_t *device_address,
688 int result = BLUETOOTH_ERROR_NONE;
689 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
690 GDBusProxy *adapter_proxy;
691 GDBusConnection *g_conn;
694 int value = BLUETOOTH_ERROR_NONE;
695 bt_audio_function_data_t *func_data;
696 guint hfp_hs_restricted = 0x0; /* set default "allowed" */
697 guint a2dp_restricted = 0x0;
699 BT_CHECK_PARAMETER(device_address, return);
701 adapter_proxy = _bt_get_adapter_proxy();
702 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
704 g_conn = _bt_get_system_gconn();
705 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
707 _bt_convert_addr_type_to_string(address, device_address->addr);
709 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
710 /* Fix : NULL_RETURNS */
711 if (func_data == NULL) {
712 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
716 func_data->address = g_strdup(address);
717 func_data->req_id = request_id;
718 func_data->type = type;
719 func_data->pending = BT_PENDING_NONE;
720 func_data->out_param = out_param1;
722 result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_HFP_HS, &hfp_hs_restricted);
723 if (result != BLUETOOTH_ERROR_NONE)
724 BT_ERR("Can't get hfp_hs restriction info");
726 result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_A2DP, &a2dp_restricted);
727 if (result != BLUETOOTH_ERROR_NONE)
728 BT_ERR("Can't get a2dp restriction info");
735 uuid = A2DP_SINK_UUID;
738 uuid = AVRCP_TARGET_UUID;
740 case BT_AUDIO_A2DP_SOURCE:
741 uuid = A2DP_SOURCE_UUID;
744 if ((hfp_hs_restricted == 0x0) && (a2dp_restricted == 0x0)) { /* in case of both profiles are not restricted */
745 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
747 func_data->pending = BT_PENDING_CONNECT;
749 } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
750 uuid = A2DP_SINK_UUID;
751 type = BT_AUDIO_A2DP;
753 BT_ERR("No audio role supported");
754 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
757 } else if ((hfp_hs_restricted == 0x1) && (a2dp_restricted == 0x1)) { /* in case of both profiles are restricted */
758 BT_ERR("All profiles are restricted");
759 result = BLUETOOTH_ERROR_INTERNAL;
761 } else if (a2dp_restricted == 0x01) { /* in case of a2dp is restricted, only connection for hfp_hs */
762 if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
766 BT_ERR("HFP_HS role is not supported");
767 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
770 } else if (hfp_hs_restricted == 0x01) { /* in case of hfp_hs is restricted, only connection for a2dp */
771 if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
772 uuid = A2DP_SINK_UUID;
773 type = BT_AUDIO_A2DP;
775 BT_ERR("A2DP role is not supported");
776 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
781 case BT_AVRCP_TARGET:
782 uuid = AVRCP_REMOTE_UUID;
785 BT_ERR("Unknown role");
786 result = BLUETOOTH_ERROR_INTERNAL;
789 BT_INFO("Connecting to service %s", uuid);
791 value = __bt_is_headset_connected(type, request_id, address, out_param1);
793 if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
794 return BLUETOOTH_ERROR_ALREADY_CONNECT;
795 } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
796 value = __bt_is_headset_connecting(type);
797 if (value != BLUETOOTH_ERROR_NONE) {
798 result = BLUETOOTH_ERROR_IN_PROGRESS;
801 _bt_headset_set_local_connection(TRUE);
802 ret = _bt_connect_profile(address, uuid,
803 __bt_audio_request_cb, func_data);
805 if (ret != BLUETOOTH_ERROR_NONE) {
806 BT_ERR("_bt_connect_profile Error");
807 _bt_headset_set_local_connection(FALSE);
808 g_free(func_data->address);
813 /* Add data to the connected list */
814 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
815 } else if (value == BLUETOOTH_ERROR_IN_PROGRESS) {
816 return BLUETOOTH_ERROR_IN_PROGRESS;
819 return BLUETOOTH_ERROR_NONE;
821 g_array_append_vals(out_param1, address,
827 int _bt_audio_disconnect(int request_id, int type,
828 bluetooth_device_address_t *device_address,
831 int result = BLUETOOTH_ERROR_NONE;
832 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
833 bt_audio_function_data_t *func_data;
834 GDBusProxy *adapter_proxy;
835 GDBusConnection *g_conn;
839 int value = BLUETOOTH_ERROR_NONE;
841 BT_CHECK_PARAMETER(device_address, return);
843 adapter_proxy = _bt_get_adapter_proxy();
844 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
846 g_conn = _bt_get_system_gconn();
847 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
849 _bt_convert_addr_type_to_string(address, device_address->addr);
851 func_data = g_malloc0(sizeof(bt_audio_function_data_t));
852 /* Fix : NULL_RETURNS */
853 if (func_data == NULL) {
854 BT_ERR("Memory allocation error");
855 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
858 func_data->address = g_strdup(address);
859 func_data->req_id = request_id;
860 func_data->pending = BT_PENDING_NONE;
861 func_data->out_param = out_param1;
862 func_data->type = type;
869 uuid = A2DP_SINK_UUID;
872 uuid = AVRCP_TARGET_UUID;
874 case BT_AUDIO_A2DP_SOURCE:
875 uuid = A2DP_SOURCE_UUID;
878 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
879 uuid = A2DP_SINK_UUID;
880 func_data->pending = BT_PENDING_DISCONNECT;
881 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
884 BT_ERR("No audio service connected");
885 result = BLUETOOTH_ERROR_NOT_CONNECTED;
889 case BT_AVRCP_TARGET:
890 uuid = AVRCP_REMOTE_UUID;
893 BT_ERR("Unknown role");
894 result = BLUETOOTH_ERROR_INTERNAL;
897 value = __bt_is_headset_disconnecting(type);
898 if (value != BLUETOOTH_ERROR_NONE) {
899 BT_INFO("Disconnect in progress");
900 result = BLUETOOTH_ERROR_IN_PROGRESS;
903 BT_INFO("Disconnecting service %s", uuid);
904 ret = _bt_disconnect_profile(address, uuid,
905 __bt_audio_request_cb, func_data);
907 if (ret != BLUETOOTH_ERROR_NONE) {
908 BT_ERR("_bt_disconnect_profile Error");
909 g_free(func_data->address);
915 * This logic is added for dual HF mode issue.
917 node = g_list_first(g_connected_list);
918 while (node != NULL) {
919 bt_connected_headset_data_t *connected_device = node->data;
921 if (g_strcmp0(connected_device->device_address, address) == 0) {
922 BT_DBG("Connection type update");
923 type = connected_device->type;
926 node = g_list_next(node);
928 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
930 return BLUETOOTH_ERROR_NONE;
932 if (out_param1 != NULL)
933 g_array_append_vals(out_param1, address,
939 void _bt_remove_from_connected_list(const char *address)
941 bt_connected_headset_data_t *connected_device;
944 node = g_list_first(g_connected_list);
945 while (node != NULL) {
946 connected_device = node->data;
947 if (connected_device != NULL &&
948 g_strcmp0(connected_device->device_address, address) == 0) {
949 BT_ERR("Device is removed from the list");
950 g_connected_list = g_list_remove(g_connected_list, connected_device);
951 g_free(connected_device);
954 node = g_list_next(node);
958 int _bt_hf_connect(int request_id,
959 bluetooth_device_address_t *device_address,
962 int result = BLUETOOTH_ERROR_NONE;
963 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
964 bt_function_data_t *func_data;
965 GDBusProxy *adapter_proxy;
966 GDBusConnection *g_conn;
970 BT_CHECK_PARAMETER(device_address, return);
972 _bt_convert_addr_type_to_string(address, device_address->addr);
974 adapter_proxy = _bt_get_adapter_proxy();
975 if (adapter_proxy == NULL) {
976 result = BLUETOOTH_ERROR_INTERNAL;
980 g_conn = _bt_get_system_gconn();
981 if (g_conn == NULL) {
982 result = BLUETOOTH_ERROR_INTERNAL;
986 func_data = g_malloc0(sizeof(bt_function_data_t));
987 /* Fix : NULL_RETURNS */
988 if (func_data == NULL) {
989 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
993 func_data->address = g_strdup(address);
994 func_data->req_id = request_id;
995 uuid = g_strdup(HFP_AG_UUID);
997 BT_DBG("Connecting to service %s", uuid);
999 ret = _bt_connect_profile(address, uuid,
1000 __bt_hf_request_cb, func_data);
1002 if (ret != BLUETOOTH_ERROR_NONE) {
1003 BT_ERR("_bt_connect_profile Error");
1004 g_free(func_data->address);
1010 return BLUETOOTH_ERROR_NONE;
1012 if (out_param1 != NULL)
1013 g_array_append_vals(out_param1, address,
1014 BT_ADDRESS_STR_LEN);
1019 int _bt_hf_disconnect(int request_id,
1020 bluetooth_device_address_t *device_address,
1023 int result = BLUETOOTH_ERROR_NONE;
1024 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1025 bt_function_data_t *func_data;
1026 GDBusProxy *adapter_proxy;
1027 GDBusConnection *g_conn;
1032 BT_CHECK_PARAMETER(device_address, return);
1034 _bt_convert_addr_type_to_string(address, device_address->addr);
1036 adapter_proxy = _bt_get_adapter_proxy();
1037 if (adapter_proxy == NULL) {
1038 result = BLUETOOTH_ERROR_INTERNAL;
1042 g_conn = _bt_get_system_gconn();
1043 if (g_conn == NULL) {
1044 result = BLUETOOTH_ERROR_INTERNAL;
1048 func_data = g_malloc0(sizeof(bt_function_data_t));
1049 /* Fix : NULL_RETURNS */
1050 if (func_data == NULL) {
1051 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1055 func_data->address = g_strdup(address);
1056 func_data->req_id = request_id;
1057 uuid = g_strdup(HFP_AG_UUID);
1059 BT_DBG("Disconnecting service %s", uuid);
1060 ret = _bt_disconnect_profile(address, uuid,
1061 __bt_hf_request_cb, func_data);
1063 if (ret != BLUETOOTH_ERROR_NONE) {
1064 BT_ERR("_bt_disconnect_profile Error");
1065 g_free(func_data->address);
1071 return BLUETOOTH_ERROR_NONE;
1073 if (out_param1 != NULL)
1074 g_array_append_vals(out_param1, address,
1075 BT_ADDRESS_STR_LEN);
1080 int _bt_audio_set_content_protect(gboolean status)
1082 GDBusConnection *conn;
1083 GError *error = NULL;
1087 conn = _bt_get_system_gconn();
1088 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1090 BT_DBG("Content Protection status = [%d]", status);
1092 g_dbus_connection_emit_signal(conn,
1093 NULL, BT_CONTENT_PROTECTION_PATH,
1094 BT_CONTENT_PROTECTION_INTERFACE,
1095 "ProtectionRequired",
1096 g_variant_new("(b)", status),
1100 /* dBUS gives error cause */
1101 ERR("Could not Emit Signal: errCode[%x], message[%s]",
1102 error->code, error->message);
1103 g_clear_error(&error);
1104 return BLUETOOTH_ERROR_INTERNAL;
1107 BT_DBG("Emit Signal done = [ProtectionRequired]");
1108 return BLUETOOTH_ERROR_NONE;
1111 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
1112 static void __bt_auto_connect_request_cb(GDBusProxy *proxy, GAsyncResult *res,
1116 GVariant *reply = NULL;
1118 reply = g_dbus_proxy_call_finish(proxy, res, &err);
1119 g_object_unref(proxy);
1120 g_variant_unref(reply);
1124 g_dbus_error_strip_remote_error(err);
1125 BT_INFO("Auto_connect_request Dbus Call Error: %s", err->message);
1127 if (strcmp("Host is down", err->message))
1129 BT_INFO("Fail reason is not 'Host Down'. Terminate auto connect");
1130 _bt_audio_stop_auto_connect();
1131 vconf_set_str(BT_LAST_CONNECTED_DEVICE, "");
1134 g_clear_error(&err);
1138 // It is the function that retry to create alarm.
1139 // Sometimes alarm mgr service is created later than bluetooth-frwk service in booting time.
1140 // So, in this case, we have to retry alarmmgr_add_alarm.
1141 static gboolean __bt_audio_alarm_retry_cb(gpointer data)
1144 alarm_id_t alarm_id;
1146 BT_DBG("__bt_audio_alarm_retry_cb called.");
1147 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1148 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1150 if (result != BLUETOOTH_ERROR_NONE)
1153 auto_connect_timer.alarm_id = alarm_id;
1158 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
1160 int result = BLUETOOTH_ERROR_NONE;
1161 char *address = NULL;
1162 alarm_id_t new_alarm_id;
1164 BT_INFO("alram id = [%d] , retry_count [%d] ",
1165 alarm_id, auto_connect_timer.retry_count);
1167 if (alarm_id != auto_connect_timer.alarm_id)
1170 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1172 if (address == NULL) {
1173 BT_ERR("Address vconf is null");
1174 auto_connect_timer.alarm_id = 0;
1178 BT_DBG("ADDRESS [%s]", address);
1180 result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
1181 __bt_auto_connect_request_cb, NULL);
1183 auto_connect_timer.retry_count--;
1185 BT_DBG("result [%d]", result);
1187 if (auto_connect_timer.retry_count <= 0) {
1188 BT_INFO("Stopping Auto connect retry");
1189 auto_connect_timer.alarm_id = 0;
1191 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1192 __bt_auto_connect_alarm_cb, NULL, &new_alarm_id);
1193 if (result == BLUETOOTH_ERROR_NONE)
1194 auto_connect_timer.alarm_id = new_alarm_id;
1201 static void __bt_auto_connect_alarm_remove()
1204 if (auto_connect_timer.alarm_id > 0) {
1205 _bt_service_remove_alarm(auto_connect_timer.alarm_id);
1206 auto_connect_timer.alarm_id = 0;
1208 auto_connect_timer.retry_count = 0;
1211 int _bt_audio_start_auto_connect(gboolean linkloss_flag)
1213 int result = BLUETOOTH_ERROR_NONE;
1214 char *address = NULL;
1215 alarm_id_t alarm_id = 0;
1219 address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1221 if (address == NULL) {
1222 BT_ERR("No target device");
1226 __bt_auto_connect_alarm_remove();
1228 auto_connect_timer.retry_count = BT_AUTO_CONNECT_TIMEOUT_RETRY_TIME /
1229 BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS;
1231 if (linkloss_flag) {
1232 BT_INFO("Start auto connection after linkloss");
1233 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1234 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1235 if (result != BLUETOOTH_ERROR_NONE) {
1236 g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
1238 auto_connect_timer.alarm_id = alarm_id;
1241 BT_INFO("Start auto connection after BT activated");
1242 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_BT_ACTIVATED,
1243 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1244 if (result == BLUETOOTH_ERROR_NONE)
1245 auto_connect_timer.alarm_id = alarm_id;
1249 return BLUETOOTH_ERROR_NONE;
1252 int _bt_audio_stop_auto_connect(void)
1255 __bt_auto_connect_alarm_remove();
1257 return BLUETOOTH_ERROR_NONE;
1260 void _bt_audio_set_auto_connect_device_addr(const char *address)
1262 if (address == NULL) {
1263 BT_ERR("address is null");
1267 BT_INFO("Last connected device is [%s]", address);
1268 vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
1270 #endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */