4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 #include <sys/socket.h>
24 #include <sys/errno.h>
29 #include <oal-event.h>
30 #include <oal-hardware.h>
31 #include <oal-audio-src.h>
32 #include <oal-a2dp-sink.h>
34 #include "bt-service-common.h"
35 #include "bt-request-handler.h"
36 #include "bt-service-audio-common.h"
37 #include "bt-service-core-device.h"
38 #include "bt-service-a2dp-src.h"
39 #include "bt-service-a2dp-sink.h"
40 #include "bt-service-avrcp-tg.h"
41 #include "bt-service-avrcp-ctrl.h"
42 #include "bt-service-hf.h"
43 #include "bt-service-hf-client.h"
44 #include "oal-hf-client.h"
46 #ifdef TIZEN_SUPPORT_DUAL_HF
47 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
50 /* Static variables and Macros */
51 static GList *g_connected_list;
52 static bt_headset_wait_t *g_wait_data;
56 char device_address[BT_ADDRESS_STRING_SIZE + 1];
57 } bt_connected_headset_data_t;
59 /* List for saving device service search info */
60 static GSList *pending_audio_conn_list = NULL;
62 /* Headset connection data structures */
63 gboolean connection_local = FALSE;
65 static int curr_audio_role = BLUETOOTH_A2DP_SOURCE;
66 static int pending_audio_role = -1;
68 static void __bt_remove_device_from_wait_list(char *prev_waiting_device);
70 static void __bt_audio_event_handler(int oal_event, gpointer event_data);
72 static int __bt_process_audio_connect_all(bt_pending_audio_conn_t *info);
74 static int __bt_is_headset_connecting(int type);
76 static int __bt_is_headset_disconnecting(int type);
78 static void __bt_audio_cleanup_resources(void);
80 static gboolean __handle_pending_audio_select_role(gpointer data);
82 static void __bt_reply_pending_audio_connect_req(char *address, int result);
85 void _bt_headset_set_local_connection(gboolean value)
87 BT_INFO("setting connection_local to %d", value);
88 connection_local = value;
91 gboolean _bt_headset_get_local_connection()
93 return connection_local;
97 void _bt_set_audio_wait_data_flag(gboolean flag)
99 BT_DBG("_bt_set_audio_wait_data_flag \n");
100 g_wait_data->ag_flag = flag;
103 bt_headset_wait_t *_bt_get_audio_wait_data(void)
105 BT_DBG("_bt_get_audio_wait_data \n");
109 static void __bt_free_wait_data(void)
111 if (g_wait_data != NULL) {
112 g_free(g_wait_data->address);
118 void _bt_rel_wait_data(void)
120 BT_DBG("_bt_rel_wait_data \n");
121 __bt_free_wait_data();
124 void _bt_add_headset_to_list(int type, int status, const char *address)
126 bt_connected_headset_data_t *connected_device;
127 bt_connected_headset_data_t *device;
130 BT_DBG("_bt_add_headset_to_list \n");
132 node = g_list_first(g_connected_list);
133 while (node != NULL) {
134 device = (bt_connected_headset_data_t *)node->data;
136 if (g_strcmp0(device->device_address, address) == 0) {
137 BT_DBG("Address match, update connection type \n");
138 if (status == BT_STATE_CONNECTED)
139 device->type |= type;
140 device->device_state = status;
143 node = g_list_next(node);
146 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
147 /* Fix : NULL_RETURNS */
148 if (connected_device == NULL) {
149 BT_ERR("No memory allocated");
153 connected_device->device_state = status;
154 //if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
155 if (status == BT_STATE_CONNECTED)
156 connected_device->type |= type;
157 g_strlcpy(connected_device->device_address, address,
158 sizeof(connected_device->device_address));
159 g_connected_list = g_list_append(g_connected_list, connected_device);
160 BT_INFO("Added device[%s] in connected list, device state [%d] Device Type [%d]",
161 address, connected_device->device_state, connected_device->type);
164 gboolean _bt_is_headset_type_connected(int type, char *address)
168 node = g_list_first(g_connected_list);
169 while (node != NULL) {
170 bt_connected_headset_data_t *connected_device = node->data;
172 if (connected_device->type & type) {
174 g_strlcpy(address, connected_device->device_address,
175 BT_ADDRESS_STRING_SIZE);
179 node = g_list_next(node);
185 gboolean _bt_is_headset_address_type_connected(int type, const char *address)
189 node = g_list_first(g_connected_list);
190 while (node != NULL) {
191 bt_connected_headset_data_t *connected_device = node->data;
193 if (connected_device && (connected_device->type & type)) {
194 if (memcmp(connected_device->device_address, address, 19) == 0)
198 node = g_list_next(node);
203 static void __bt_set_headset_disconnection_type(const char *address)
205 bt_connected_headset_data_t *connected_device;
208 node = g_list_first(g_connected_list);
209 while (node != NULL) {
210 connected_device = node->data;
211 if (g_strcmp0(connected_device->device_address, address) == 0) {
212 g_wait_data->disconnection_type = connected_device->type;
215 node = g_list_next(node);
219 #ifdef TIZEN_SUPPORT_DUAL_HF
220 gboolean __bt_is_companion_device(const char *addr)
222 if (TIZEN_PROFILE_WEARABLE) {
223 char *host_device_address = NULL;
224 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
226 if (!host_device_address) {
227 BT_INFO("Failed to get a companion device address");
231 if (g_strcmp0(host_device_address, addr) == 0) {
232 BT_INFO("addr[%s] is companion device", addr);
238 /* TODO : Need to add companion device check condition for Phone models */
244 static int __bt_is_headset_disconnecting(int type)
246 bt_connected_headset_data_t *connected_device = NULL;
248 /* Check if any other headset is connected */
251 node = g_list_first(g_connected_list);
252 while (node != NULL) {
253 connected_device = node->data;
254 if (connected_device->device_state == BT_STATE_DISCONNECTING)
255 return BLUETOOTH_ERROR_CONNECTION_BUSY;
256 node = g_list_next(node);
259 return BLUETOOTH_ERROR_NONE;
262 static int __bt_is_headset_connecting(int type)
264 bt_connected_headset_data_t *connected_device = NULL;
266 /* Check if any other headset is connected */
269 node = g_list_first(g_connected_list);
270 while (node != NULL) {
271 connected_device = node->data;
272 if (connected_device->device_state == BT_STATE_CONNECTING) {
273 BT_ERR("@@Device [%s] is already under connecting state", connected_device->device_address);
274 return BLUETOOTH_ERROR_CONNECTION_BUSY;
276 node = g_list_next(node);
279 return BLUETOOTH_ERROR_NONE;
282 static int __bt_is_headset_connected(int current_conn_type, const char *address)
284 gboolean connected = FALSE;
286 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
287 bluetooth_device_address_t device_address;
288 bt_connected_headset_data_t *connected_device = NULL;
289 #ifdef TIZEN_SUPPORT_DUAL_HF
290 gboolean is_companion_device = FALSE;
293 /* Check if any other headset is connected */
296 BT_INFO("Checking if any Headset connected or not: current device [%s] current dev type [%d]", address, current_conn_type);
297 node = g_list_first(g_connected_list);
298 while (node != NULL) {
299 connected_device = node->data;
300 BT_INFO(" A Device is already connected found in list [%s] conn type [%d]",
301 connected_device->device_address, connected_device->type);
302 if ((connected_device->type & current_conn_type)) {
303 g_strlcpy(connected_address, connected_device->device_address,
304 BT_ADDRESS_STRING_SIZE + 1);
305 #ifdef TIZEN_SUPPORT_DUAL_HF
306 is_companion_device = __bt_is_companion_device(connected_address);
307 BT_INFO(" is_companion_device[%d]", is_companion_device);
309 if (!is_companion_device) {
318 node = g_list_next(node);
322 BT_INFO("There is no connected device with connection type [%d]", current_conn_type);
323 return BLUETOOTH_ERROR_NOT_CONNECTED;
326 BT_DBG("connected headset %s", connected_address);
328 if (g_strcmp0(connected_address, address) == 0)
329 return BLUETOOTH_ERROR_ALREADY_CONNECT;
330 #ifdef TIZEN_SUPPORT_DUAL_HF
331 else if (TRUE == __bt_is_companion_device(address))
332 return BLUETOOTH_ERROR_NOT_CONNECTED;
335 /* Convert BD address from string type */
336 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
337 int value = BLUETOOTH_ERROR_NONE;
338 BT_DBG("Already connected headset addr [%s] connected headset type [0x%x] current dev conn type [0x%x]",
339 connected_address, connected_device->type, current_conn_type);
340 disconn_type = connected_device->type & current_conn_type;
341 BT_DBG("Attempt disconnection of Type [0x%x] of already connected device" , disconn_type);
342 value = _bt_audio_disconnect(disconn_type, &device_address);
344 /* If already one device is waiting, remove current waiting device and add new */
345 if (value == BLUETOOTH_ERROR_NONE) {
346 if (g_wait_data != NULL) {
347 if (g_strcmp0(g_wait_data->address, address) != 0) {
348 BT_INFO("Already one device was waiting for connection [%s], remove it", g_wait_data->address);
349 __bt_remove_device_from_wait_list(g_wait_data->address);
350 __bt_free_wait_data();
354 if (g_wait_data == NULL) {
355 BT_INFO("Add current device [%s] into waiting list", address);
356 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
357 g_wait_data->address = g_strdup(address);
358 g_wait_data->type = current_conn_type;
359 g_wait_data->ag_flag = FALSE;
361 /* Set disconnection type */
362 __bt_set_headset_disconnection_type(connected_address);
369 static void __bt_remove_device_from_wait_list(char *prev_waiting_device)
371 /* Before deleting the request update the UI */
372 bluetooth_device_address_t device_address;
373 int result = BLUETOOTH_ERROR_INTERNAL;
375 invocation_info_t *req_info;
376 BT_INFO("We are about to DBUS return previous waiting device [%s]", prev_waiting_device);
378 _bt_convert_addr_string_to_type(device_address.addr, prev_waiting_device);
380 req_info = _bt_get_request_info_data(BT_AV_CONNECT, prev_waiting_device);
381 if (req_info == NULL) {
382 BT_ERR("req_info == NULL");
385 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
386 g_array_append_vals(out_param, &device_address,
387 sizeof(bluetooth_device_address_t));
388 _bt_service_method_return(req_info->context,
390 g_array_free(out_param, TRUE);
391 g_free(req_info->user_data);
392 _bt_free_info_from_invocation_list(req_info);
396 static int __bt_process_audio_profile_connect(bt_audio_type_t type, bluetooth_device_address_t *address)
398 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
399 int result = BLUETOOTH_ERROR_NONE;
402 _bt_convert_addr_type_to_string(addr,
403 (unsigned char *)address->addr);
404 /* Attempt profile level connection based on type */
407 result = _bt_connect_remote_hfp(address);
410 result = _bt_a2dp_connect_remote_sink(address);
412 case BT_AVRCP_TARGET:
413 result = _bt_avrcp_connect_remote_ctrl(address);
416 result = _bt_avrcp_connect_remote_target(address);
418 case BT_AUDIO_A2DP_SOURCE:
419 return _bt_a2dp_connect_remote_source(address);
422 return _bt_connect_remote_ag(address);
424 BT_ERR("Unknown role");
425 return BLUETOOTH_ERROR_INTERNAL;
428 if (result == BLUETOOTH_ERROR_NONE) {
429 //_bt_headset_set_local_connection(TRUE);
430 /* Add data to the connected list */
431 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, addr);
432 BT_PERMANENT_LOG("Connect %d", type);
434 BT_ERR("Profile [%d] connect failed!!", type);
440 static int __bt_process_audio_profile_disconnect(bt_audio_type_t type, bluetooth_device_address_t *address)
442 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
443 int result = BLUETOOTH_ERROR_NONE;
447 _bt_convert_addr_type_to_string(addr,
448 (unsigned char *)address->addr);
449 /* Attempt profile level connection based on type */
452 result = _bt_disconnect_remote_hfp(address);
455 result = _bt_a2dp_disconnect_remote_sink(address);
457 case BT_AVRCP_TARGET:
458 result = _bt_avrcp_disconnect_remote_ctrl(address);
461 result = _bt_avrcp_disconnect_remote_target(address);
463 case BT_AUDIO_A2DP_SOURCE:
464 return _bt_a2dp_disconnect_remote_source(address);
467 BT_ERR("Unknown role");
468 return BLUETOOTH_ERROR_INTERNAL;
471 if (result == BLUETOOTH_ERROR_NONE) {
473 * This logic is added for dual HF mode issue.
475 node = g_list_first(g_connected_list);
476 while (node != NULL) {
477 bt_connected_headset_data_t *connected_device = node->data;
479 if (g_strcmp0(connected_device->device_address, addr) == 0) {
480 BT_DBG("Connection type update");
481 type = connected_device->type;
484 node = g_list_next(node);
487 /* Update device status in connected list */
488 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, addr);
489 BT_PERMANENT_LOG("Disconnect %d", type);
491 BT_ERR("Profile [%d] connect failed!!", type);
497 int _bt_audio_initialize(bt_service_module_t module)
499 oal_status_t status = OAL_STATUS_SUCCESS;
500 int ret = BLUETOOTH_ERROR_NONE;
502 BT_INFO("_bt_audio_initialize: Module [%d]", module);
505 case BT_A2DP_SOURCE_MODULE: {
506 status = audio_enable(NULL, NULL);
507 if (OAL_STATUS_SUCCESS != status) {
508 BT_ERR("Failed to initialize Bluetooth A2DP Source Profile, status: %d", status);
509 return BLUETOOTH_ERROR_INTERNAL;
511 /* Register Audio module event handler */
512 _bt_service_register_event_handler_callback(module, _bt_a2dp_source_event_handler);
515 case BT_A2DP_SINK_MODULE: {
516 status = a2dp_sink_enable(NULL, NULL);
517 if (status != OAL_STATUS_SUCCESS) {
518 BT_ERR("Failed to initialize Bluetooth A2DP Sink Profile, status: %d", status);
519 return BLUETOOTH_ERROR_INTERNAL;
521 /* Register Audio sink module event handler */
522 _bt_service_register_event_handler_callback(module, _bt_a2dp_sink_event_handler);
525 case BT_HFP_MODULE: {
526 status = hf_client_enable();
527 if (OAL_STATUS_SUCCESS != status) {
528 BT_ERR("Failed to initialize Bluetooth HFP client Profile, status: %d", status);
529 return BLUETOOTH_ERROR_INTERNAL;
531 /* Register Audio module event handler */
532 _bt_service_register_event_handler_callback(module, _bt_hf_client_event_handler);
536 status = hfp_enable(1);
537 if (OAL_STATUS_SUCCESS != status) {
538 BT_ERR("Failed to initialize Bluetooth HFP Audio Gateway Profile, status: %d", status);
539 return BLUETOOTH_ERROR_INTERNAL;
541 /* Register Audio module event handler */
542 _bt_service_register_event_handler_callback(module, _bt_hf_event_handler);
545 case BT_AUDIO_ALL_MODULE: {
546 /* Register Audio module event handler */
547 _bt_service_register_event_handler_callback(module, __bt_audio_event_handler);
550 case BT_AVRCP_CTRL_MODULE: {
551 status = avrcp_ct_enable();
552 if (status != OAL_STATUS_SUCCESS) {
553 BT_ERR("Failed to initialize Bluetooth AVRCP Controller Profile, status: %d", status);
554 return BLUETOOTH_ERROR_INTERNAL;
556 /* Register Avrcp Controller event handler */
557 _bt_service_register_event_handler_callback(module, _bt_avrcp_ctrl_event_handler);
560 case BT_AVRCP_MODULE: {
561 /* Initialize AVRCP Target */
562 ret = _bt_service_avrcp_enable();
566 BT_ERR("Not Supported: Module [%d]", module);
567 return BLUETOOTH_ERROR_NOT_SUPPORT;
570 BT_INFO("Bluetooth audio interface initialised");
574 static void __bt_audio_event_handler(int oal_event, gpointer event_data)
579 case OAL_EVENT_ADAPTER_DISABLED: {
580 BT_INFO("Adapter Disabled..cleanup resources");
581 __bt_audio_cleanup_resources();
584 case OAL_EVENT_ADAPTER_ENABLED: {
585 /*TODO Currently not handled */
586 BT_INFO("Adapter Enabled..");
590 BT_ERR("Unknown event..[%d]", oal_event);
595 static void __bt_audio_cleanup_resources(void)
599 bt_pending_audio_conn_t *info = NULL;
602 /* Remove connected device list */
603 node = g_list_first(g_connected_list);
604 while (node != NULL) {
605 bt_connected_headset_data_t *connected_device = node->data;
606 BT_INFO("Data found [%s] in connected device list...remove it..", connected_device->device_address);
607 g_connected_list = g_list_remove(g_connected_list, connected_device);
608 node = g_list_next(node);
611 /* Remove pending connection list */
612 for (l = pending_audio_conn_list; l != NULL; l = g_slist_next(l)) {
613 info = (bt_pending_audio_conn_t*)l->data;
616 BT_INFO("Info found for addr [%s], remove it...", info->address);
617 pending_audio_conn_list = g_slist_remove(pending_audio_conn_list, info);
618 g_free(info->address);
627 static int __bt_process_audio_connect_all(bt_pending_audio_conn_t *info)
629 bluetooth_device_address_t device_address;
630 int result = BLUETOOTH_ERROR_NONE;
631 int type = BT_AUDIO_ALL;
634 _bt_convert_addr_string_to_type(device_address.addr, info->address);
636 /* Attempt profile level connection */
637 if (info->is_hfp_supported) {
639 result = _bt_connect_remote_hfp(&device_address);
641 if (info->is_a2dp_sink_supported)
642 BT_INFO("A2DP is supported by [%s]", info->address);
644 BT_INFO("A2DP is not supported");
645 } else if (info->is_a2dp_sink_supported) {
646 type = BT_AUDIO_A2DP;
647 result = _bt_a2dp_connect_remote_sink(&device_address);
648 } else if (info->is_a2dp_src_supported) {
649 type = BT_AUDIO_A2DP_SOURCE;
650 result = _bt_a2dp_connect_remote_source(&device_address);
652 if (result == BLUETOOTH_ERROR_NONE) {
653 //_bt_headset_set_local_connection(TRUE);
654 /* Add data to the connected list */
655 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, info->address);
657 BT_ERR("Profile connect failed!!");
663 bt_pending_audio_conn_t* _bt_get_pending_audio_conn_info(char *address)
666 bt_pending_audio_conn_t *info = NULL;
669 for (l = pending_audio_conn_list; l != NULL; l = g_slist_next(l)) {
670 info = (bt_pending_audio_conn_t*)l->data;
672 if (g_strcmp0(info->address, address) == 0 && info->search_status == SERVICE_SEARCH_DONE) {
673 BT_INFO("Pending data found for addr [%s]", info->address);
677 BT_INFO("Pending data not found!!");
681 static void __bt_reply_pending_audio_connect_req(char *address, int result)
684 invocation_info_t *req_info;
687 ret_if(NULL == address);
689 /* Reply to async request for Audio connect, if any */
690 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, address);
691 ret_if(NULL == req_info);
693 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
694 g_array_append_vals(out_param, address, BT_ADDRESS_STRING_SIZE);
695 _bt_service_method_return(req_info->context, out_param, result);
697 g_array_free(out_param, TRUE);
698 g_free(req_info->user_data);
699 _bt_free_info_from_invocation_list(req_info);
704 void _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(bt_pending_audio_conn_t *info, int result)
706 ret_if(NULL == info);
708 /* Reply to async request for Audio connect, if any */
709 __bt_reply_pending_audio_connect_req(info->address, result);
711 /* Remove pending audio conn info */
712 pending_audio_conn_list = g_slist_remove(pending_audio_conn_list, info);
713 g_free(info->address);
717 gboolean _bt_audio_check_pending_connection(char *address)
719 bt_pending_audio_conn_t *data = NULL;
720 bluetooth_device_address_t device_address;
723 data = _bt_get_pending_audio_conn_info(address);
726 BT_INFO("A2DP Connection is pending..initiate it...");
727 if (data->is_a2dp_sink_supported && data->conn_req_type == BT_AUDIO_ALL) {
728 _bt_convert_addr_string_to_type(device_address.addr, address);
729 if (_bt_audio_connect(BT_AUDIO_A2DP, &device_address) != BLUETOOTH_ERROR_NONE) {
730 BT_INFO("A2DP connect triggered for [%s] but it failed!!", data->address);
731 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
733 BT_INFO("A2DP connect triggered successfully for [%s]", data->address);
735 } else if (data->is_a2dp_src_supported && data->conn_req_type == BT_AUDIO_HFP_SOURCE) {
736 _bt_convert_addr_string_to_type(device_address.addr, address);
737 if (_bt_audio_connect(BT_AUDIO_A2DP_SOURCE, &device_address) != BLUETOOTH_ERROR_NONE) {
738 BT_INFO("A2DP sink connect triggered for [%s] but it failed!!", data->address);
739 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
741 BT_INFO("A2DP sink connect triggered successfully for [%s]", data->address);
746 BT_INFO("A2DP Connection is not pending..");
752 void _bt_audio_check_pending_disconnection(char *address, int type)
754 int ret = BLUETOOTH_ERROR_NONE;
755 bluetooth_device_address_t device_address;
758 if (_bt_is_service_connected(address, type)) {
759 BT_INFO("Service [%d] is connected with device [%s], disconnect it...", type, address);
760 _bt_convert_addr_string_to_type(device_address.addr, address);
761 ret = __bt_process_audio_profile_disconnect(type, &device_address);
763 if (ret != BLUETOOTH_ERROR_NONE)
764 BT_ERR("Disconnecting service [%d] with device [%s] failed!!", type, address);
766 BT_INFO("Service [%d] is Not connected with device [%s],..", type, address);
771 int __bt_handle_audio_all_connect(bt_pending_audio_conn_t *info)
773 bt_remote_dev_info_t *rem_info;
779 retv_if(NULL == info, BLUETOOTH_ERROR_INTERNAL);
780 retv_if(NULL == info->address, BLUETOOTH_ERROR_INTERNAL);
782 rem_info = _bt_service_get_remote_dev_info(info->address);
784 BT_ERR("_bt_service_get_remote_dev_info returned NULL");
785 ret = BLUETOOTH_ERROR_NOT_PAIRED;
789 for (indx = 0; indx < rem_info->uuid_count; indx++) {
790 BT_INFO("UUID [%s]", rem_info->uuids[indx]);
791 if (0 == g_strcmp0(A2DP_SINK_UUID, rem_info->uuids[indx])) {
792 BT_INFO("Device supports A2DP Sink Profile");
793 info->is_a2dp_sink_supported = TRUE;
794 } else if (0 == g_strcmp0(A2DP_SOURCE_UUID, rem_info->uuids[indx])) {
795 BT_INFO("Device supports A2DP Source Profile");
796 info->is_a2dp_src_supported = TRUE;
797 } else if ((g_strcmp0(HFP_HS_UUID, rem_info->uuids[indx]) == 0)) {
798 BT_INFO("Device supports HFP Profile");
799 info->is_hfp_supported = TRUE;
803 if (info->is_a2dp_sink_supported == FALSE &&
804 info->is_hfp_supported == FALSE &&
805 info->is_a2dp_src_supported == FALSE) {
806 BT_ERR("No audio profile is supported");
807 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
811 BT_INFO("AUDIO_CONNECT_ALL request for [%s]", info->address);
812 info->search_status = SERVICE_SEARCH_DONE;
814 /* Give preference to HFP over A2DP for outgoing connection sequence for AUDIO_ALL_CONNECT */
815 if (info->is_hfp_supported)
816 info->type = BT_AUDIO_HSP;
817 else if (info->is_a2dp_sink_supported)
818 info->type = BT_AUDIO_A2DP;
819 else if (info->is_a2dp_src_supported)
820 info->type = BT_AUDIO_A2DP_SOURCE;
822 ret = __bt_is_headset_connected(info->type, info->address);
823 if (ret == BLUETOOTH_ERROR_ALREADY_CONNECT) {
824 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
825 info->address, "Already connected...");
829 if (ret == BLUETOOTH_ERROR_IN_PROGRESS) {
830 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
831 info->address, "Already in progress...");
835 if (ret == BLUETOOTH_ERROR_NOT_CONNECTED) {
836 BT_ERR("Great, can start Audio All connect for [%s]", info->address);
837 ret = __bt_is_headset_connecting(info->type);
838 if (ret != BLUETOOTH_ERROR_NONE) {
839 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
840 info->address, "some other device conn in progress");
841 ret = BLUETOOTH_ERROR_IN_PROGRESS;
845 ret = __bt_process_audio_connect_all(info);
846 if (ret != BLUETOOTH_ERROR_NONE) {
847 BT_ERR("__bt_process_audio_connect_all failed");
851 BT_PERMANENT_LOG("Connect %d", info->type);
852 /* If multiple profiles are supported, queue pending connection info */
853 if ((info->is_hfp_supported && info->is_a2dp_sink_supported) ||
854 (info->is_hfp_supported && info->is_a2dp_src_supported)) {
855 BT_INFO("[%s] Supports HFP and (A2DP_Src or, A2DP_Snk)", info->address);
856 pending_audio_conn_list = g_slist_append(pending_audio_conn_list, (gpointer)info);
858 BT_INFO("[%s] Supports one profile only", info->address);
860 * It means, we dont need pending connect info as only A2DP (Src/Snk) or
861 * HFP will be connected for present device, so lets free pending info.
863 g_free(info->address);
866 } else if (ret == BLUETOOTH_ERROR_NONE) {
867 BT_INFO("Waiting for disconnection...");
869 if ((info->is_hfp_supported && info->is_a2dp_sink_supported) ||
870 (info->is_hfp_supported && info->is_a2dp_src_supported)) {
871 BT_INFO("[%s] Supports HFP and (A2DP_Src or, A2DP_Snk)", info->address);
872 pending_audio_conn_list = g_slist_append(pending_audio_conn_list, (gpointer)info);
874 BT_INFO("[%s] Supports one profile only", info->address);
876 * It means, we dont need pending connect info as only A2DP (Src/Snk) or
877 * HFP will be connected for present device, so lets free pending info.
879 g_free(info->address);
885 return BLUETOOTH_ERROR_NONE;
888 BT_ERR("Audio connect all failed");
889 g_free(info->address);
894 static gboolean __audio_get_bonded_info(gpointer data)
896 bt_pending_audio_conn_t *info = data;
897 char address[BT_ADDRESS_STRING_SIZE];
901 retv_if(NULL == info, FALSE);
902 retv_if(NULL == info->address, FALSE);
904 if ((info->bonded_info_retries > 0) && !_bt_is_bonded_devices_retrived()) {
905 info->bonded_info_retries--;
909 g_strlcpy(address, info->address, BT_ADDRESS_STRING_SIZE);
910 if (info->bonded_info_retries <= 0) {
911 BT_ERR_C("Even after all retries, bonded devices stil not retrieved");
912 g_free(info->address);
917 if (BLUETOOTH_ERROR_NONE != __bt_handle_audio_all_connect(info)) {
918 BT_ERR("__bt_handle_audio_all_connect failed");
925 __bt_reply_pending_audio_connect_req(address, BLUETOOTH_ERROR_INTERNAL);
929 int _bt_audio_connect(int type, bluetooth_device_address_t *device_address)
931 int ret = BLUETOOTH_ERROR_NONE;
932 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
933 bt_pending_audio_conn_t *info = NULL;
937 BT_CHECK_PARAMETER(device_address, return);
939 _bt_convert_addr_type_to_string(address, device_address->addr);
940 BT_INFO("Adderss: [%s], request type: [%d]", address, type);
943 * If type is BT_AUDIO_ALL or BT_AUDIO_HFP_SOURCE, enqueue search info in
944 * order to find out supported services by the remote device.
946 if (type == BT_AUDIO_ALL || type == BT_AUDIO_HFP_SOURCE) {
947 if (NULL != _bt_get_pending_audio_conn_info(address)) {
948 BT_ERR("Connection for same device already in progress");
949 return BLUETOOTH_ERROR_IN_PROGRESS;
952 info = g_malloc0(sizeof(bt_pending_audio_conn_t));
953 info->search_status = SERVICE_SEARCH_STARTED;
954 info->address = g_strdup(address);
956 info->conn_req_type = type;
958 /* Request bonded device info */
959 if (!_bt_is_bonded_devices_retrived()) {
960 info->bonded_info_retries = 5;
961 /* Wait till bonded devices retrival is completed */
962 g_timeout_add_seconds(1, __audio_get_bonded_info, info);
963 return BLUETOOTH_ERROR_NONE;
966 return __bt_handle_audio_all_connect(info);
969 /* If type is A2DP Sink or HSP/HFP, check further */
970 ret = __bt_is_headset_connected(type, address);
971 if (ret == BLUETOOTH_ERROR_ALREADY_CONNECT) {
972 BT_ERR("Failed with BLUETOOTH_ERROR_ALREADY_CONNECT");
973 return BLUETOOTH_ERROR_ALREADY_CONNECT;
976 if (ret == BLUETOOTH_ERROR_IN_PROGRESS) {
977 BT_ERR("Failed with BLUETOOTH_ERROR_IN_PROGRESS");
978 return BLUETOOTH_ERROR_IN_PROGRESS;
981 if (ret == BLUETOOTH_ERROR_NONE) {
982 BT_INFO("Waiting for disconnection...");
983 } else if (ret == BLUETOOTH_ERROR_NOT_CONNECTED) {
984 ret = __bt_process_audio_profile_connect(type, device_address);
985 if (ret != BLUETOOTH_ERROR_NONE) {
986 BT_ERR("Failed with %d", ret);
991 return BLUETOOTH_ERROR_NONE;
994 int _bt_audio_disconnect(int type, bluetooth_device_address_t *device_address)
996 int ret = BLUETOOTH_ERROR_NONE;
997 int value = BLUETOOTH_ERROR_NONE;
998 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1000 _bt_convert_addr_type_to_string(address, device_address->addr);
1001 BT_INFO("Audio Diconnect Request: type[%d] address [%s]", type, address);
1003 if (type == BT_AUDIO_ALL) {
1004 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
1005 type = BT_AUDIO_A2DP;
1006 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
1007 type = BT_AUDIO_HSP;
1009 BT_ERR("No audio service connected");
1010 return BLUETOOTH_ERROR_NOT_CONNECTED;
1012 } else if (type == BT_AUDIO_HFP_SOURCE) {
1013 if (_bt_is_service_connected(address, BT_AUDIO_A2DP_SOURCE)) {
1014 type = BT_AUDIO_A2DP_SOURCE;
1015 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
1016 type = BT_AUDIO_HSP;
1018 BT_ERR("No audio service connected");
1019 return BLUETOOTH_ERROR_NOT_CONNECTED;
1023 value = __bt_is_headset_disconnecting(type);
1024 if (value != BLUETOOTH_ERROR_NONE) {
1025 BT_INFO("Disconnect in progress");
1026 return BLUETOOTH_ERROR_IN_PROGRESS;
1029 ret = __bt_process_audio_profile_disconnect(type, device_address);
1033 gboolean _bt_is_service_connected(char* address, int type)
1036 node = g_list_first(g_connected_list);
1037 while (node != NULL) {
1038 bt_connected_headset_data_t *conn_device = node->data;
1040 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
1041 (conn_device->type & type)) {
1042 BT_INFO("Service connected");
1046 node = g_list_next(node);
1048 BT_INFO("Service not connected");
1052 void _bt_remove_headset_from_list(int type, const char *address)
1056 BT_DBG("_bt_remove_headset_from_list \n");
1058 node = g_list_first(g_connected_list);
1059 while (node != NULL) {
1060 bt_connected_headset_data_t *connected_device = node->data;
1062 if (g_strcmp0(connected_device->device_address, address) != 0) {
1063 node = g_list_next(node);
1067 BT_DBG("Address match \n");
1069 BT_DBG("Connection type = %x\n", connected_device->type);
1073 if (connected_device->type & BT_AUDIO_A2DP)
1074 connected_device->type &= ~(BT_AUDIO_A2DP);
1077 if (connected_device->type & BT_AUDIO_HSP)
1078 connected_device->type &= ~(BT_AUDIO_HSP);
1081 if (connected_device->type & BT_AUDIO_ALL)
1082 connected_device->type &= ~(BT_AUDIO_ALL);
1084 case BT_AVRCP_TARGET:
1085 if (connected_device->type & BT_AVRCP_TARGET)
1086 connected_device->type &= ~(BT_AVRCP_TARGET);
1089 if (connected_device->type & BT_AVRCP)
1090 connected_device->type &= ~(BT_AVRCP);
1092 case BT_AUDIO_A2DP_SOURCE:
1093 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
1094 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
1100 BT_DBG("Connection type = %x\n", connected_device->type);
1102 if (connected_device->type == 0x00) {
1103 BT_INFO("Device will be completely removed from connected list as the only profile connected or connecting got disconnected");
1104 g_connected_list = g_list_remove(g_connected_list, connected_device);
1105 g_free(connected_device);
1107 connected_device->device_state = BT_STATE_CONNECTED;
1110 node = g_list_next(node);
1114 * If Audio role selection request is pending (pending_audio_role > 0) then process pending
1115 * audio role select request on BT_AUDIO_A2DP/BT_AUDIO_A2DP_SOURCE device dicaonnection.
1117 if (pending_audio_role >= 0 &&
1118 (type == BT_AUDIO_A2DP || type == BT_AUDIO_A2DP_SOURCE))
1119 g_idle_add(__handle_pending_audio_select_role, NULL);
1122 static void __handle_pending_requests(int result, int service_function, void *user_data, unsigned int size)
1126 invocation_info_t *req_info;
1130 /* Get method invocation context */
1131 for (l = _bt_get_invocation_list(); l != NULL; ) {
1133 l = g_slist_next(l);
1135 if (req_info == NULL || req_info->service_function != service_function)
1138 /* Create out param */
1139 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
1141 switch (service_function) {
1142 case BT_AUDIO_SELECT_ROLE:
1143 _bt_service_method_return(req_info->context, out_param, result);
1144 g_array_free(out_param, TRUE);
1145 _bt_free_info_from_invocation_list(req_info);
1148 BT_ERR("Unknown service function[%d]", service_function);
1156 static gboolean __handle_pending_audio_select_role(gpointer data)
1159 oal_status_t status;
1162 if (BLUETOOTH_A2DP_SOURCE == pending_audio_role) {
1163 /* Disable A2DP Sink role */
1164 status = a2dp_sink_disable();
1165 if (status != OAL_STATUS_SUCCESS) {
1166 BT_ERR("Failed to Disable Bluetooth A2DP Sink Profile, status: %d", status);
1167 ret = BLUETOOTH_ERROR_INTERNAL;
1171 /* Disable AVRCP CT role */
1172 status = avrcp_ct_disable();
1173 if (status != OAL_STATUS_SUCCESS) {
1174 BT_ERR("Failed to Disable Bluetooth AVRCP Controller Profile, status: %d", status);
1175 ret = BLUETOOTH_ERROR_INTERNAL;
1179 /* Enable A2DP Source role */
1180 ret = _bt_audio_initialize(BT_A2DP_SOURCE_MODULE);
1181 if (ret != BLUETOOTH_ERROR_NONE) {
1182 BT_ERR("Failed to enable Bluetooth A2DP Source Profile");
1186 /* Enable AVRCP TG role */
1187 ret = _bt_audio_initialize(BT_AVRCP_MODULE);
1188 if (ret != BLUETOOTH_ERROR_NONE) {
1189 BT_ERR("Failed to enable Bluetooth AVRCP Target Profile");
1193 /* Disable A2DP Source role */
1194 status = audio_disable();
1195 if (OAL_STATUS_SUCCESS != status) {
1196 BT_ERR("Failed to disable Bluetooth A2DP Source Profile, status: %d", status);
1197 ret = BLUETOOTH_ERROR_INTERNAL;
1201 /* Disable AVRCP TG role */
1202 ret = _bt_service_avrcp_disable();
1203 if (ret != BLUETOOTH_ERROR_NONE) {
1204 BT_ERR("Failed to Disable Bluetooth AVRCP Target Profile");
1208 /* Enable A2DP Sink role */
1209 ret = _bt_audio_initialize(BT_A2DP_SINK_MODULE);
1210 if (ret != BLUETOOTH_ERROR_NONE) {
1211 BT_ERR("Failed to enable Bluetooth A2DP Sink Profile");
1215 /* Enable AVRCP CT role */
1216 ret = _bt_audio_initialize(BT_AVRCP_CTRL_MODULE);
1217 if (ret != BLUETOOTH_ERROR_NONE) {
1218 BT_ERR("Failed to enable Bluetooth AVRCP Controller Profile");
1224 if (ret == BLUETOOTH_ERROR_NONE)
1225 _bt_audio_set_current_role(pending_audio_role);
1227 __handle_pending_requests(ret, BT_AUDIO_SELECT_ROLE, NULL, 0);
1228 pending_audio_role = -1;
1233 int _bt_audio_select_role(bluetooth_audio_role_t role)
1235 int result = BLUETOOTH_ERROR_NONE;
1236 char address[BT_ADDRESS_STRING_SIZE];
1237 bluetooth_device_address_t dev_addr;
1239 retv_if(BLUETOOTH_A2DP_SINK < role, BLUETOOTH_ERROR_INVALID_PARAM);
1240 retv_if(pending_audio_role >= 0, BLUETOOTH_ERROR_IN_PROGRESS);
1244 if (curr_audio_role == role) {
1245 BT_ERR("Desired audio role already enabled, return");
1246 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1249 pending_audio_role = role;
1251 if (BLUETOOTH_A2DP_SINK == role) {
1252 if (_bt_is_headset_type_connected(BT_AUDIO_A2DP, address)) {
1253 _bt_convert_addr_string_to_type(dev_addr.addr, address);
1254 result = _bt_audio_disconnect(BT_AUDIO_A2DP, &dev_addr);
1255 if (result != BLUETOOTH_ERROR_NONE) {
1256 BT_ERR("_bt_audio_disconnect(BT_AUDIO_A2DP, %s) Failed", address);
1257 result = BLUETOOTH_ERROR_INTERNAL;
1260 BT_INFO("No BT_AUDIO_A2DP device is connected, proceed with role switch");
1261 g_idle_add(__handle_pending_audio_select_role, NULL);
1262 result = BLUETOOTH_ERROR_NONE;
1265 if (_bt_is_headset_type_connected(BT_AUDIO_A2DP_SOURCE, address)) {
1266 _bt_convert_addr_string_to_type(dev_addr.addr, address);
1267 result = _bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, &dev_addr);
1268 if (result != BLUETOOTH_ERROR_NONE) {
1269 BT_ERR("_bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, %s) Failed", address);
1270 result = BLUETOOTH_ERROR_INTERNAL;
1273 BT_INFO("No BT_AUDIO_A2DP_SOURCE device is connected, proceed with role switch");
1274 g_idle_add(__handle_pending_audio_select_role, NULL);
1275 result = BLUETOOTH_ERROR_NONE;
1283 void _bt_audio_set_current_role(bluetooth_audio_role_t role)
1285 BT_INFO("role: %s", (role == BLUETOOTH_A2DP_SINK) ? "AUDIO_SINK" : "AUDIO_SOURCE");
1286 curr_audio_role = role;
1289 int _bt_hf_connect(bluetooth_device_address_t *device_address)
1291 int result = BLUETOOTH_ERROR_NONE;
1294 result = _bt_connect_remote_ag(device_address);
1295 if (result != BLUETOOTH_ERROR_NONE)
1296 BT_ERR("HF Client connect to remote AG failed");
1298 BT_PERMANENT_LOG("Connect AG");
1303 int _bt_hf_disconnect(bluetooth_device_address_t *device_address)
1305 int result = BLUETOOTH_ERROR_NONE;
1308 result = _bt_disconnect_remote_ag(device_address);
1309 if (result != BLUETOOTH_ERROR_NONE)
1310 BT_ERR("HF Client disconnect to remote AG failed");
1312 BT_PERMANENT_LOG("Disconnect AG");