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"
44 #ifdef TIZEN_SUPPORT_DUAL_HF
45 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
48 /* Static variables and Macros */
49 static GList *g_connected_list;
50 static bt_headset_wait_t *g_wait_data;
54 char device_address[BT_ADDRESS_STRING_SIZE + 1];
55 } bt_connected_headset_data_t;
57 /* List for saving device service search info */
58 static GSList *pending_audio_conn_list = NULL;
60 /* Headset connection data structures */
61 gboolean connection_local = FALSE;
63 static int curr_audio_role = BLUETOOTH_A2DP_SOURCE;
64 static int pending_audio_role = -1;
66 static void __bt_remove_device_from_wait_list(char *prev_waiting_device);
68 static void __bt_audio_event_handler(int oal_event, gpointer event_data);
70 static int __bt_process_audio_connect_all(bt_pending_audio_conn_t *info);
72 static int __bt_is_headset_connecting(int type);
74 static int __bt_is_headset_disconnecting(int type);
76 static void __bt_audio_cleanup_resources(void);
78 static gboolean __handle_pending_audio_select_role(gpointer data);
80 static void __bt_reply_pending_audio_connect_req(char *address, int result);
83 void _bt_headset_set_local_connection(gboolean value)
85 BT_INFO("setting connection_local to %d", value);
86 connection_local = value;
89 gboolean _bt_headset_get_local_connection()
91 return connection_local;
95 void _bt_set_audio_wait_data_flag(gboolean flag)
97 BT_DBG("_bt_set_audio_wait_data_flag \n");
98 g_wait_data->ag_flag = flag;
101 bt_headset_wait_t *_bt_get_audio_wait_data(void)
103 BT_DBG("_bt_get_audio_wait_data \n");
107 static void __bt_free_wait_data(void)
109 if (g_wait_data != NULL) {
110 g_free(g_wait_data->address);
116 void _bt_rel_wait_data(void)
118 BT_DBG("_bt_rel_wait_data \n");
119 __bt_free_wait_data();
122 void _bt_add_headset_to_list(int type, int status, const char *address)
124 bt_connected_headset_data_t *connected_device;
125 bt_connected_headset_data_t *device;
128 BT_DBG("_bt_add_headset_to_list \n");
130 node = g_list_first(g_connected_list);
131 while (node != NULL) {
132 device = (bt_connected_headset_data_t *)node->data;
134 if (g_strcmp0(device->device_address, address) == 0) {
135 BT_DBG("Address match, update connection type \n");
136 if (status == BT_STATE_CONNECTED)
137 device->type |= type;
138 device->device_state = status;
141 node = g_list_next(node);
144 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
145 /* Fix : NULL_RETURNS */
146 if (connected_device == NULL) {
147 BT_ERR("No memory allocated");
151 connected_device->device_state = status;
152 //if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
153 if (status == BT_STATE_CONNECTED)
154 connected_device->type |= type;
155 g_strlcpy(connected_device->device_address, address,
156 sizeof(connected_device->device_address));
157 g_connected_list = g_list_append(g_connected_list, connected_device);
158 BT_INFO("Added device[%s] in connected list, device state [%d] Device Type [%d]",
159 address, connected_device->device_state, connected_device->type);
162 gboolean _bt_is_headset_type_connected(int type, char *address)
166 node = g_list_first(g_connected_list);
167 while (node != NULL) {
168 bt_connected_headset_data_t *connected_device = node->data;
170 if (connected_device->type & type) {
172 g_strlcpy(address, connected_device->device_address,
173 BT_ADDRESS_STRING_SIZE);
177 node = g_list_next(node);
183 gboolean _bt_is_headset_address_type_connected(int type, const char *address)
187 node = g_list_first(g_connected_list);
188 while (node != NULL) {
189 bt_connected_headset_data_t *connected_device = node->data;
191 if (connected_device && (connected_device->type & type)) {
192 if (memcmp(connected_device->device_address, address, 19) == 0)
196 node = g_list_next(node);
201 static void __bt_set_headset_disconnection_type(const char *address)
203 bt_connected_headset_data_t *connected_device;
206 node = g_list_first(g_connected_list);
207 while (node != NULL) {
208 connected_device = node->data;
209 if (g_strcmp0(connected_device->device_address, address) == 0) {
210 g_wait_data->disconnection_type = connected_device->type;
213 node = g_list_next(node);
217 #ifdef TIZEN_SUPPORT_DUAL_HF
218 gboolean __bt_is_companion_device(const char *addr)
220 if (TIZEN_PROFILE_WEARABLE) {
221 char *host_device_address = NULL;
222 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
224 if (!host_device_address) {
225 BT_INFO("Failed to get a companion device address");
229 if (g_strcmp0(host_device_address, addr) == 0) {
230 BT_INFO("addr[%s] is companion device", addr);
236 /* TODO : Need to add companion device check condition for Phone models */
242 static int __bt_is_headset_disconnecting(int type)
244 bt_connected_headset_data_t *connected_device = NULL;
246 /* Check if any other headset is connected */
249 node = g_list_first(g_connected_list);
250 while (node != NULL) {
251 connected_device = node->data;
252 if (connected_device->device_state == BT_STATE_DISCONNECTING)
253 return BLUETOOTH_ERROR_CONNECTION_BUSY;
254 node = g_list_next(node);
257 return BLUETOOTH_ERROR_NONE;
260 static int __bt_is_headset_connecting(int type)
262 bt_connected_headset_data_t *connected_device = NULL;
264 /* Check if any other headset is connected */
267 node = g_list_first(g_connected_list);
268 while (node != NULL) {
269 connected_device = node->data;
270 if (connected_device->device_state == BT_STATE_CONNECTING) {
271 BT_ERR("@@Device [%s] is already under connecting state", connected_device->device_address);
272 return BLUETOOTH_ERROR_CONNECTION_BUSY;
274 node = g_list_next(node);
277 return BLUETOOTH_ERROR_NONE;
280 static int __bt_is_headset_connected(int current_conn_type, const char *address)
282 gboolean connected = FALSE;
284 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
285 bluetooth_device_address_t device_address;
286 bt_connected_headset_data_t *connected_device = NULL;
287 #ifdef TIZEN_SUPPORT_DUAL_HF
288 gboolean is_companion_device = FALSE;
291 /* Check if any other headset is connected */
294 BT_INFO("Checking if any Headset connected or not: current device [%s] current dev type [%d]", address, current_conn_type);
295 node = g_list_first(g_connected_list);
296 while (node != NULL) {
297 connected_device = node->data;
298 BT_INFO(" A Device is already connected found in list [%s] conn type [%d]",
299 connected_device->device_address, connected_device->type);
300 if ((connected_device->type & current_conn_type)) {
301 g_strlcpy(connected_address, connected_device->device_address,
302 BT_ADDRESS_STRING_SIZE + 1);
303 #ifdef TIZEN_SUPPORT_DUAL_HF
304 is_companion_device = __bt_is_companion_device(connected_address);
305 BT_INFO(" is_companion_device[%d]", is_companion_device);
307 if (!is_companion_device) {
316 node = g_list_next(node);
320 BT_INFO("There is no connected device with connection type [%d]", current_conn_type);
321 return BLUETOOTH_ERROR_NOT_CONNECTED;
324 BT_DBG("connected headset %s", connected_address);
326 if (g_strcmp0(connected_address, address) == 0)
327 return BLUETOOTH_ERROR_ALREADY_CONNECT;
328 #ifdef TIZEN_SUPPORT_DUAL_HF
329 else if (TRUE == __bt_is_companion_device(address))
330 return BLUETOOTH_ERROR_NOT_CONNECTED;
333 /* Convert BD address from string type */
334 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
335 int value = BLUETOOTH_ERROR_NONE;
336 BT_DBG("Already connected headset addr [%s] connected headset type [0x%x] current dev conn type [0x%x]",
337 connected_address, connected_device->type, current_conn_type);
338 disconn_type = connected_device->type & current_conn_type;
339 BT_DBG("Attempt disconnection of Type [0x%x] of already connected device" , disconn_type);
340 value = _bt_audio_disconnect(disconn_type, &device_address);
342 /* If already one device is waiting, remove current waiting device and add new */
343 if (value == BLUETOOTH_ERROR_NONE) {
344 if (g_wait_data != NULL) {
345 if (g_strcmp0(g_wait_data->address, address) != 0) {
346 BT_INFO("Already one device was waiting for connection [%s], remove it", g_wait_data->address);
347 __bt_remove_device_from_wait_list(g_wait_data->address);
348 __bt_free_wait_data();
352 if (g_wait_data == NULL) {
353 BT_INFO("Add current device [%s] into waiting list", address);
354 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
355 g_wait_data->address = g_strdup(address);
356 g_wait_data->type = current_conn_type;
357 g_wait_data->ag_flag = FALSE;
359 /* Set disconnection type */
360 __bt_set_headset_disconnection_type(connected_address);
367 static void __bt_remove_device_from_wait_list(char *prev_waiting_device)
369 /* Before deleting the request update the UI */
370 bluetooth_device_address_t device_address;
371 int result = BLUETOOTH_ERROR_INTERNAL;
373 invocation_info_t *req_info;
374 BT_INFO("We are about to DBUS return previous waiting device [%s]", prev_waiting_device);
376 _bt_convert_addr_string_to_type(device_address.addr, prev_waiting_device);
378 req_info = _bt_get_request_info_data(BT_AV_CONNECT, prev_waiting_device);
379 if (req_info == NULL) {
380 BT_ERR("req_info == NULL");
383 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
384 g_array_append_vals(out_param, &device_address,
385 sizeof(bluetooth_device_address_t));
386 _bt_service_method_return(req_info->context,
388 g_array_free(out_param, TRUE);
389 g_free(req_info->user_data);
390 _bt_free_info_from_invocation_list(req_info);
394 static int __bt_process_audio_profile_connect(bt_audio_type_t type, bluetooth_device_address_t *address)
396 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
397 int result = BLUETOOTH_ERROR_NONE;
400 _bt_convert_addr_type_to_string(addr,
401 (unsigned char *)address->addr);
402 /* Attempt profile level connection based on type */
405 result = _bt_connect_remote_hfp(address);
408 result = _bt_a2dp_connect_remote_sink(address);
410 case BT_AVRCP_TARGET:
411 result = _bt_avrcp_connect_remote_ctrl(address);
414 result = _bt_avrcp_connect_remote_target(address);
416 case BT_AUDIO_A2DP_SOURCE:
417 return _bt_a2dp_connect_remote_source(address);
420 BT_ERR("Unknown role");
421 return BLUETOOTH_ERROR_INTERNAL;
424 if (result == BLUETOOTH_ERROR_NONE) {
425 //_bt_headset_set_local_connection(TRUE);
426 /* Add data to the connected list */
427 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, addr);
429 BT_ERR("Profile [%d] connect failed!!", type);
435 static int __bt_process_audio_profile_disconnect(bt_audio_type_t type, bluetooth_device_address_t *address)
437 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
438 int result = BLUETOOTH_ERROR_NONE;
442 _bt_convert_addr_type_to_string(addr,
443 (unsigned char *)address->addr);
444 /* Attempt profile level connection based on type */
447 result = _bt_disconnect_remote_hfp(address);
450 result = _bt_a2dp_disconnect_remote_sink(address);
452 case BT_AVRCP_TARGET:
453 result = _bt_avrcp_disconnect_remote_ctrl(address);
456 result = _bt_avrcp_disconnect_remote_target(address);
458 case BT_AUDIO_A2DP_SOURCE:
459 return _bt_a2dp_disconnect_remote_source(address);
462 BT_ERR("Unknown role");
463 return BLUETOOTH_ERROR_INTERNAL;
466 if (result == BLUETOOTH_ERROR_NONE) {
468 * This logic is added for dual HF mode issue.
470 node = g_list_first(g_connected_list);
471 while (node != NULL) {
472 bt_connected_headset_data_t *connected_device = node->data;
474 if (g_strcmp0(connected_device->device_address, addr) == 0) {
475 BT_DBG("Connection type update");
476 type = connected_device->type;
479 node = g_list_next(node);
482 /* Update device status in connected list */
483 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, addr);
485 BT_ERR("Profile [%d] connect failed!!", type);
491 int _bt_audio_initialize(bt_service_module_t module)
493 oal_status_t status = OAL_STATUS_SUCCESS;
494 int ret = BLUETOOTH_ERROR_NONE;
496 BT_INFO("_bt_audio_initialize: Module [%d]", module);
499 case BT_A2DP_SOURCE_MODULE: {
500 status = audio_enable(NULL, NULL);
501 if (OAL_STATUS_SUCCESS != status) {
502 BT_ERR("Failed to initialize Bluetooth A2DP Source Profile, status: %d", status);
503 return BLUETOOTH_ERROR_INTERNAL;
505 /* Register Audio module event handler */
506 _bt_service_register_event_handler_callback(module, _bt_a2dp_source_event_handler);
509 case BT_A2DP_SINK_MODULE: {
510 status = a2dp_sink_enable(NULL, NULL);
511 if (status != OAL_STATUS_SUCCESS) {
512 BT_ERR("Failed to initialize Bluetooth A2DP Sink Profile, status: %d", status);
513 return BLUETOOTH_ERROR_INTERNAL;
515 /* Register Audio sink module event handler */
516 _bt_service_register_event_handler_callback(module, _bt_a2dp_sink_event_handler);
519 case BT_HFP_MODULE: {
520 return BLUETOOTH_ERROR_NOT_SUPPORT;
523 status = hfp_enable(1);
524 if (OAL_STATUS_SUCCESS != status) {
525 BT_ERR("Failed to initialize Bluetooth HFP Audio Gateway Profile, status: %d", status);
526 return BLUETOOTH_ERROR_INTERNAL;
528 /* Register Audio module event handler */
529 _bt_service_register_event_handler_callback(module, _bt_hf_event_handler);
532 case BT_AUDIO_ALL_MODULE: {
533 /* Register Audio module event handler */
534 _bt_service_register_event_handler_callback(module, __bt_audio_event_handler);
537 case BT_AVRCP_CTRL_MODULE: {
538 status = avrcp_ct_enable();
539 if (status != OAL_STATUS_SUCCESS) {
540 BT_ERR("Failed to initialize Bluetooth AVRCP Controller Profile, status: %d", status);
541 return BLUETOOTH_ERROR_INTERNAL;
543 /* Register Avrcp Controller event handler */
544 _bt_service_register_event_handler_callback(module, _bt_avrcp_ctrl_event_handler);
547 case BT_AVRCP_MODULE: {
548 /* Initialize AVRCP Target */
549 ret = _bt_service_avrcp_enable();
553 BT_ERR("Not Supported: Module [%d]", module);
554 return BLUETOOTH_ERROR_NOT_SUPPORT;
557 BT_INFO("Bluetooth audio interface initialised");
561 static void __bt_audio_event_handler(int oal_event, gpointer event_data)
566 case OAL_EVENT_ADAPTER_DISABLED: {
567 BT_INFO("Adapter Disabled..cleanup resources");
568 __bt_audio_cleanup_resources();
571 case OAL_EVENT_ADAPTER_ENABLED: {
572 /*TODO Currently not handled */
573 BT_INFO("Adapter Enabled..");
577 BT_ERR("Unknown event..[%d]", oal_event);
582 static void __bt_audio_cleanup_resources(void)
586 bt_pending_audio_conn_t *info = NULL;
589 /* Remove connected device list */
590 node = g_list_first(g_connected_list);
591 while (node != NULL) {
592 bt_connected_headset_data_t *connected_device = node->data;
593 BT_INFO("Data found [%s] in connected device list...remove it..", connected_device->device_address);
594 g_connected_list = g_list_remove(g_connected_list, connected_device);
595 node = g_list_next(node);
598 /* Remove pending connection list */
599 for (l = pending_audio_conn_list; l != NULL; l = g_slist_next(l)) {
600 info = (bt_pending_audio_conn_t*)l->data;
603 BT_INFO("Info found for addr [%s], remove it...", info->address);
604 pending_audio_conn_list = g_slist_remove(pending_audio_conn_list, info);
605 g_free(info->address);
614 static int __bt_process_audio_connect_all(bt_pending_audio_conn_t *info)
616 bluetooth_device_address_t device_address;
617 int result = BLUETOOTH_ERROR_NONE;
618 int type = BT_AUDIO_ALL;
621 _bt_convert_addr_string_to_type(device_address.addr, info->address);
623 /* Attempt profile level connection */
624 if (info->is_hfp_supported) {
626 result = _bt_connect_remote_hfp(&device_address);
628 if (info->is_a2dp_sink_supported)
629 BT_INFO("A2DP is supported by [%s]", info->address);
631 BT_INFO("A2DP is not supported");
632 } else if (info->is_a2dp_sink_supported) {
633 type = BT_AUDIO_A2DP;
634 result = _bt_a2dp_connect_remote_sink(&device_address);
635 } else if (info->is_a2dp_src_supported) {
636 type = BT_AUDIO_A2DP_SOURCE;
637 result = _bt_a2dp_connect_remote_source(&device_address);
639 if (result == BLUETOOTH_ERROR_NONE) {
640 //_bt_headset_set_local_connection(TRUE);
641 /* Add data to the connected list */
642 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, info->address);
644 BT_ERR("Profile connect failed!!");
650 bt_pending_audio_conn_t* _bt_get_pending_audio_conn_info(char *address)
653 bt_pending_audio_conn_t *info = NULL;
656 for (l = pending_audio_conn_list; l != NULL; l = g_slist_next(l)) {
657 info = (bt_pending_audio_conn_t*)l->data;
659 if (g_strcmp0(info->address, address) == 0 && info->search_status == SERVICE_SEARCH_DONE) {
660 BT_INFO("Pending data found for addr [%s]", info->address);
664 BT_INFO("Pending data not found!!");
668 static void __bt_reply_pending_audio_connect_req(char *address, int result)
671 invocation_info_t *req_info;
674 ret_if(NULL == address);
676 /* Reply to async request for Audio connect, if any */
677 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, address);
678 ret_if(NULL == req_info);
680 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
681 g_array_append_vals(out_param, address, BT_ADDRESS_STRING_SIZE);
682 _bt_service_method_return(req_info->context, out_param, result);
684 g_array_free(out_param, TRUE);
685 g_free(req_info->user_data);
686 _bt_free_info_from_invocation_list(req_info);
691 void _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(bt_pending_audio_conn_t *info, int result)
693 ret_if(NULL == info);
695 /* Reply to async request for Audio connect, if any */
696 __bt_reply_pending_audio_connect_req(info->address, result);
698 /* Remove pending audio conn info */
699 pending_audio_conn_list = g_slist_remove(pending_audio_conn_list, info);
700 g_free(info->address);
704 gboolean _bt_audio_check_pending_connection(char *address)
706 bt_pending_audio_conn_t *data = NULL;
707 bluetooth_device_address_t device_address;
710 data = _bt_get_pending_audio_conn_info(address);
713 BT_INFO("A2DP Connection is pending..initiate it...");
714 if (data->is_a2dp_sink_supported && data->conn_req_type == BT_AUDIO_ALL) {
715 _bt_convert_addr_string_to_type(device_address.addr, address);
716 if (_bt_audio_connect(BT_AUDIO_A2DP, &device_address) != BLUETOOTH_ERROR_NONE) {
717 BT_INFO("A2DP connect triggered for [%s] but it failed!!", data->address);
718 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
720 BT_INFO("A2DP connect triggered successfully for [%s]", data->address);
722 } else if (data->is_a2dp_src_supported && data->conn_req_type == BT_AUDIO_HFP_SOURCE) {
723 _bt_convert_addr_string_to_type(device_address.addr, address);
724 if (_bt_audio_connect(BT_AUDIO_A2DP_SOURCE, &device_address) != BLUETOOTH_ERROR_NONE) {
725 BT_INFO("A2DP sink connect triggered for [%s] but it failed!!", data->address);
726 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
728 BT_INFO("A2DP sink connect triggered successfully for [%s]", data->address);
733 BT_INFO("A2DP Connection is not pending..");
739 void _bt_audio_check_pending_disconnection(char *address, int type)
741 int ret = BLUETOOTH_ERROR_NONE;
742 bluetooth_device_address_t device_address;
745 if (_bt_is_service_connected(address, type)) {
746 BT_INFO("Service [%d] is connected with device [%s], disconnect it...", type, address);
747 _bt_convert_addr_string_to_type(device_address.addr, address);
748 ret = __bt_process_audio_profile_disconnect(type, &device_address);
750 if (ret != BLUETOOTH_ERROR_NONE)
751 BT_ERR("Disconnecting service [%d] with device [%s] failed!!", type, address);
753 BT_INFO("Service [%d] is Not connected with device [%s],..", type, address);
758 int __bt_handle_audio_all_connect(bt_pending_audio_conn_t *info)
760 bt_remote_dev_info_t *rem_info;
766 retv_if(NULL == info, BLUETOOTH_ERROR_INTERNAL);
767 retv_if(NULL == info->address, BLUETOOTH_ERROR_INTERNAL);
769 rem_info = _bt_service_get_remote_dev_info(info->address);
771 BT_ERR("_bt_service_get_remote_dev_info returned NULL");
772 ret = BLUETOOTH_ERROR_NOT_PAIRED;
776 for (indx = 0; indx < rem_info->uuid_count; indx++) {
777 BT_INFO("UUID [%s]", rem_info->uuids[indx]);
778 if (0 == g_strcmp0(A2DP_SINK_UUID, rem_info->uuids[indx])) {
779 BT_INFO("Device supports A2DP Sink Profile");
780 info->is_a2dp_sink_supported = TRUE;
781 } else if (0 == g_strcmp0(A2DP_SOURCE_UUID, rem_info->uuids[indx])) {
782 BT_INFO("Device supports A2DP Source Profile");
783 info->is_a2dp_src_supported = TRUE;
784 } else if ((g_strcmp0(HFP_HS_UUID, rem_info->uuids[indx]) == 0)) {
785 BT_INFO("Device supports HFP Profile");
786 info->is_hfp_supported = TRUE;
790 if (info->is_a2dp_sink_supported == FALSE &&
791 info->is_hfp_supported == FALSE &&
792 info->is_a2dp_src_supported == FALSE) {
793 BT_ERR("No audio profile is supported");
794 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
798 BT_INFO("AUDIO_CONNECT_ALL request for [%s]", info->address);
799 info->search_status = SERVICE_SEARCH_DONE;
801 /* Give preference to HFP over A2DP for outgoing connection sequence for AUDIO_ALL_CONNECT */
802 if (info->is_hfp_supported)
803 info->type = BT_AUDIO_HSP;
804 else if (info->is_a2dp_sink_supported)
805 info->type = BT_AUDIO_A2DP;
806 else if (info->is_a2dp_src_supported)
807 info->type = BT_AUDIO_A2DP_SOURCE;
809 ret = __bt_is_headset_connected(info->type, info->address);
810 if (ret == BLUETOOTH_ERROR_ALREADY_CONNECT) {
811 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
812 info->address, "Already connected...");
816 if (ret == BLUETOOTH_ERROR_IN_PROGRESS) {
817 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
818 info->address, "Already in progress...");
822 if (ret == BLUETOOTH_ERROR_NOT_CONNECTED) {
823 BT_ERR("Great, can start Audio All connect for [%s]", info->address);
824 ret = __bt_is_headset_connecting(info->type);
825 if (ret != BLUETOOTH_ERROR_NONE) {
826 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
827 info->address, "some other device conn in progress");
828 ret = BLUETOOTH_ERROR_IN_PROGRESS;
832 ret = __bt_process_audio_connect_all(info);
833 if (ret != BLUETOOTH_ERROR_NONE) {
834 BT_ERR("__bt_process_audio_connect_all failed");
838 /* If multiple profiles are supported, queue pending connection info */
839 if ((info->is_hfp_supported && info->is_a2dp_sink_supported) ||
840 (info->is_hfp_supported && info->is_a2dp_src_supported)) {
841 BT_INFO("[%s] Supports HFP and (A2DP_Src or, A2DP_Snk)", info->address);
842 pending_audio_conn_list = g_slist_append(pending_audio_conn_list, (gpointer)info);
844 BT_INFO("[%s] Supports one profile only", info->address);
846 * It means, we dont need pending connect info as only A2DP (Src/Snk) or
847 * HFP will be connected for present device, so lets free pending info.
849 g_free(info->address);
852 } else if (ret == BLUETOOTH_ERROR_NONE) {
853 BT_INFO("Waiting for disconnection...");
855 * It means, we dont need pending connect info as only A2DP (Src/Snk) or
856 * HFP will be connected for present device, so lets free pending info.
858 g_free(info->address);
863 return BLUETOOTH_ERROR_NONE;
866 BT_ERR("Audio connect all failed");
867 g_free(info->address);
872 static gboolean __audio_get_bonded_info(gpointer data)
874 bt_pending_audio_conn_t *info = data;
875 char address[BT_ADDRESS_STRING_SIZE];
879 retv_if(NULL == info, FALSE);
880 retv_if(NULL == info->address, FALSE);
882 if ((info->bonded_info_retries > 0) && !_bt_is_bonded_devices_retrived()) {
883 info->bonded_info_retries--;
887 g_strlcpy(address, info->address, BT_ADDRESS_STRING_SIZE);
888 if (info->bonded_info_retries <= 0) {
889 BT_ERR_C("Even after all retries, bonded devices stil not retrieved");
890 g_free(info->address);
895 if (BLUETOOTH_ERROR_NONE != __bt_handle_audio_all_connect(info)) {
896 BT_ERR("__bt_handle_audio_all_connect failed");
903 __bt_reply_pending_audio_connect_req(address, BLUETOOTH_ERROR_INTERNAL);
907 int _bt_audio_connect(int type, bluetooth_device_address_t *device_address)
909 int ret = BLUETOOTH_ERROR_NONE;
910 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
911 bt_pending_audio_conn_t *info = NULL;
915 BT_CHECK_PARAMETER(device_address, return);
917 _bt_convert_addr_type_to_string(address, device_address->addr);
918 BT_INFO("Adderss: [%s], request type: [%d]", address, type);
921 * If type is BT_AUDIO_ALL or BT_AUDIO_HFP_SOURCE, enqueue search info in
922 * order to find out supported services by the remote device.
924 if (type == BT_AUDIO_ALL || type == BT_AUDIO_HFP_SOURCE) {
925 if (NULL != _bt_get_pending_audio_conn_info(address)) {
926 BT_ERR("Connection for same device already in progress");
927 return BLUETOOTH_ERROR_IN_PROGRESS;
930 info = g_malloc0(sizeof(bt_pending_audio_conn_t));
931 info->search_status = SERVICE_SEARCH_STARTED;
932 info->address = g_strdup(address);
934 info->conn_req_type = type;
936 /* Request bonded device info */
937 if (!_bt_is_bonded_devices_retrived()) {
938 info->bonded_info_retries = 5;
939 /* Wait till bonded devices retrival is completed */
940 g_timeout_add_seconds(1, __audio_get_bonded_info, info);
941 return BLUETOOTH_ERROR_NONE;
944 return __bt_handle_audio_all_connect(info);
947 /* If type is A2DP Sink or HSP/HFP, check further */
948 ret = __bt_is_headset_connected(type, address);
949 if (ret == BLUETOOTH_ERROR_ALREADY_CONNECT) {
950 BT_ERR("Failed with BLUETOOTH_ERROR_ALREADY_CONNECT");
951 return BLUETOOTH_ERROR_ALREADY_CONNECT;
954 if (ret == BLUETOOTH_ERROR_IN_PROGRESS) {
955 BT_ERR("Failed with BLUETOOTH_ERROR_IN_PROGRESS");
956 return BLUETOOTH_ERROR_IN_PROGRESS;
959 if (ret == BLUETOOTH_ERROR_NONE) {
960 BT_INFO("Waiting for disconnection...");
961 } else if (ret == BLUETOOTH_ERROR_NOT_CONNECTED) {
962 ret = __bt_process_audio_profile_connect(type, device_address);
963 if (ret != BLUETOOTH_ERROR_NONE) {
964 BT_ERR("Failed with %d", ret);
969 return BLUETOOTH_ERROR_NONE;
972 int _bt_audio_disconnect(int type, bluetooth_device_address_t *device_address)
974 int ret = BLUETOOTH_ERROR_NONE;
975 int value = BLUETOOTH_ERROR_NONE;
976 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
978 _bt_convert_addr_type_to_string(address, device_address->addr);
979 BT_INFO("Audio Diconnect Request: type[%d] address [%s]", type, address);
981 if (type == BT_AUDIO_ALL) {
982 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
983 type = BT_AUDIO_A2DP;
984 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
987 BT_ERR("No audio service connected");
988 return BLUETOOTH_ERROR_NOT_CONNECTED;
990 } else if (type == BT_AUDIO_HFP_SOURCE) {
991 if (_bt_is_service_connected(address, BT_AUDIO_A2DP_SOURCE)) {
992 type = BT_AUDIO_A2DP_SOURCE;
993 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
996 BT_ERR("No audio service connected");
997 return BLUETOOTH_ERROR_NOT_CONNECTED;
1001 value = __bt_is_headset_disconnecting(type);
1002 if (value != BLUETOOTH_ERROR_NONE) {
1003 BT_INFO("Disconnect in progress");
1004 return BLUETOOTH_ERROR_IN_PROGRESS;
1007 ret = __bt_process_audio_profile_disconnect(type, device_address);
1011 gboolean _bt_is_service_connected(char* address, int type)
1014 node = g_list_first(g_connected_list);
1015 while (node != NULL) {
1016 bt_connected_headset_data_t *conn_device = node->data;
1018 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
1019 (conn_device->type & type)) {
1020 BT_INFO("Service connected");
1024 node = g_list_next(node);
1026 BT_INFO("Service not connected");
1030 void _bt_remove_headset_from_list(int type, const char *address)
1034 BT_DBG("_bt_remove_headset_from_list \n");
1036 node = g_list_first(g_connected_list);
1037 while (node != NULL) {
1038 bt_connected_headset_data_t *connected_device = node->data;
1040 if (g_strcmp0(connected_device->device_address, address) != 0) {
1041 node = g_list_next(node);
1045 BT_DBG("Address match \n");
1047 BT_DBG("Connection type = %x\n", connected_device->type);
1051 if (connected_device->type & BT_AUDIO_A2DP)
1052 connected_device->type &= ~(BT_AUDIO_A2DP);
1055 if (connected_device->type & BT_AUDIO_HSP)
1056 connected_device->type &= ~(BT_AUDIO_HSP);
1059 if (connected_device->type & BT_AUDIO_ALL)
1060 connected_device->type &= ~(BT_AUDIO_ALL);
1062 case BT_AVRCP_TARGET:
1063 if (connected_device->type & BT_AVRCP_TARGET)
1064 connected_device->type &= ~(BT_AVRCP_TARGET);
1067 if (connected_device->type & BT_AVRCP)
1068 connected_device->type &= ~(BT_AVRCP);
1070 case BT_AUDIO_A2DP_SOURCE:
1071 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
1072 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
1078 BT_DBG("Connection type = %x\n", connected_device->type);
1080 if (connected_device->type == 0x00) {
1081 BT_INFO("Device will be completely removed from connected list as the only profile connected or connecting got disconnected");
1082 g_connected_list = g_list_remove(g_connected_list, connected_device);
1083 g_free(connected_device);
1085 connected_device->device_state = BT_STATE_CONNECTED;
1088 node = g_list_next(node);
1092 * If Audio role selection request is pending (pending_audio_role > 0) then process pending
1093 * audio role select request on BT_AUDIO_A2DP/BT_AUDIO_A2DP_SOURCE device dicaonnection.
1095 if (pending_audio_role >= 0 &&
1096 (type == BT_AUDIO_A2DP || type == BT_AUDIO_A2DP_SOURCE))
1097 g_idle_add(__handle_pending_audio_select_role, NULL);
1100 static void __handle_pending_requests(int result, int service_function, void *user_data, unsigned int size)
1104 invocation_info_t *req_info;
1108 /* Get method invocation context */
1109 for (l = _bt_get_invocation_list(); l != NULL; l = g_slist_next(l)) {
1112 if (req_info == NULL || req_info->service_function != service_function)
1115 /* Create out param */
1116 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
1118 switch (service_function) {
1119 case BT_AUDIO_SELECT_ROLE:
1120 _bt_service_method_return(req_info->context, out_param, result);
1121 g_array_free(out_param, TRUE);
1122 _bt_free_info_from_invocation_list(req_info);
1125 BT_ERR("Unknown service function[%d]", service_function);
1133 static gboolean __handle_pending_audio_select_role(gpointer data)
1136 oal_status_t status;
1139 if (BLUETOOTH_A2DP_SOURCE == pending_audio_role) {
1140 /* Disable A2DP Sink role */
1141 status = a2dp_sink_disable();
1142 if (status != OAL_STATUS_SUCCESS) {
1143 BT_ERR("Failed to Disable Bluetooth A2DP Sink Profile, status: %d", status);
1144 ret = BLUETOOTH_ERROR_INTERNAL;
1148 /* Disable AVRCP CT role */
1149 status = avrcp_ct_disable();
1150 if (status != OAL_STATUS_SUCCESS) {
1151 BT_ERR("Failed to Disable Bluetooth AVRCP Controller Profile, status: %d", status);
1152 ret = BLUETOOTH_ERROR_INTERNAL;
1156 /* Enable A2DP Source role */
1157 ret = _bt_audio_initialize(BT_A2DP_SOURCE_MODULE);
1158 if (ret != BLUETOOTH_ERROR_NONE) {
1159 BT_ERR("Failed to enable Bluetooth A2DP Source Profile");
1163 /* Enable AVRCP TG role */
1164 ret = _bt_audio_initialize(BT_AVRCP_MODULE);
1165 if (ret != BLUETOOTH_ERROR_NONE) {
1166 BT_ERR("Failed to enable Bluetooth AVRCP Target Profile");
1170 /* Disable A2DP Source role */
1171 status = audio_disable();
1172 if (OAL_STATUS_SUCCESS != status) {
1173 BT_ERR("Failed to disable Bluetooth A2DP Source Profile, status: %d", status);
1174 ret = BLUETOOTH_ERROR_INTERNAL;
1178 /* Disable AVRCP TG role */
1179 ret = _bt_service_avrcp_disable();
1180 if (ret != BLUETOOTH_ERROR_NONE) {
1181 BT_ERR("Failed to Disable Bluetooth AVRCP Target Profile");
1185 /* Enable A2DP Sink role */
1186 ret = _bt_audio_initialize(BT_A2DP_SINK_MODULE);
1187 if (ret != BLUETOOTH_ERROR_NONE) {
1188 BT_ERR("Failed to enable Bluetooth A2DP Sink Profile");
1192 /* Enable AVRCP CT role */
1193 ret = _bt_audio_initialize(BT_AVRCP_CTRL_MODULE);
1194 if (ret != BLUETOOTH_ERROR_NONE) {
1195 BT_ERR("Failed to enable Bluetooth AVRCP Controller Profile");
1201 if (ret == BLUETOOTH_ERROR_NONE)
1202 _bt_audio_set_current_role(pending_audio_role);
1204 __handle_pending_requests(ret, BT_AUDIO_SELECT_ROLE, NULL, 0);
1205 pending_audio_role = -1;
1210 int _bt_audio_select_role(bluetooth_audio_role_t role)
1212 int result = BLUETOOTH_ERROR_NONE;
1213 char address[BT_ADDRESS_STRING_SIZE];
1214 bluetooth_device_address_t dev_addr;
1216 retv_if(BLUETOOTH_A2DP_SINK < role, BLUETOOTH_ERROR_INVALID_PARAM);
1217 retv_if(pending_audio_role >= 0, BLUETOOTH_ERROR_IN_PROGRESS);
1221 if (curr_audio_role == role) {
1222 BT_ERR("Desired audio role already enabled, return");
1223 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1226 pending_audio_role = role;
1228 if (BLUETOOTH_A2DP_SINK == role) {
1229 if (_bt_is_headset_type_connected(BT_AUDIO_A2DP, address)) {
1230 _bt_convert_addr_string_to_type(dev_addr.addr, address);
1231 result = _bt_audio_disconnect(BT_AUDIO_A2DP, &dev_addr);
1232 if (result != BLUETOOTH_ERROR_NONE) {
1233 BT_ERR("_bt_audio_disconnect(BT_AUDIO_A2DP, %s) Failed", address);
1234 result = BLUETOOTH_ERROR_INTERNAL;
1237 BT_INFO("No BT_AUDIO_A2DP device is connected, proceed with role switch");
1238 g_idle_add(__handle_pending_audio_select_role, NULL);
1239 result = BLUETOOTH_ERROR_NONE;
1242 if (_bt_is_headset_type_connected(BT_AUDIO_A2DP_SOURCE, address)) {
1243 _bt_convert_addr_string_to_type(dev_addr.addr, address);
1244 result = _bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, &dev_addr);
1245 if (result != BLUETOOTH_ERROR_NONE) {
1246 BT_ERR("_bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, %s) Failed", address);
1247 result = BLUETOOTH_ERROR_INTERNAL;
1250 BT_INFO("No BT_AUDIO_A2DP_SOURCE device is connected, proceed with role switch");
1251 g_idle_add(__handle_pending_audio_select_role, NULL);
1252 result = BLUETOOTH_ERROR_NONE;
1260 void _bt_audio_set_current_role(bluetooth_audio_role_t role)
1262 BT_INFO("role: %s", (role == BLUETOOTH_A2DP_SINK) ? "AUDIO_SINK" : "AUDIO_SOURCE");
1263 curr_audio_role = role;