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 static const char *__convert_audio_type_to_string(bt_audio_type_t type)
106 case BT_AVRCP_TARGET:
107 return "AVRCP_TARGET";
110 case BT_AUDIO_A2DP_SOURCE:
111 return "A2DP_SOURCE";
112 case BT_AUDIO_HFP_SOURCE:
121 void _bt_set_audio_wait_data_flag(gboolean flag)
123 BT_DBG("_bt_set_audio_wait_data_flag \n");
124 g_wait_data->ag_flag = flag;
127 bt_headset_wait_t *_bt_get_audio_wait_data(void)
129 BT_DBG("_bt_get_audio_wait_data \n");
133 static void __bt_free_wait_data(void)
135 if (g_wait_data != NULL) {
136 g_free(g_wait_data->address);
142 void _bt_rel_wait_data(void)
144 BT_DBG("_bt_rel_wait_data \n");
145 __bt_free_wait_data();
148 void _bt_add_headset_to_list(int type, int status, const char *address)
150 bt_connected_headset_data_t *connected_device;
151 bt_connected_headset_data_t *device;
154 BT_DBG("_bt_add_headset_to_list \n");
156 node = g_list_first(g_connected_list);
157 while (node != NULL) {
158 device = (bt_connected_headset_data_t *)node->data;
160 if (g_strcmp0(device->device_address, address) == 0) {
161 BT_DBG("Address match, update connection type \n");
162 if (status == BT_STATE_CONNECTED)
163 device->type |= type;
164 device->device_state = status;
167 node = g_list_next(node);
170 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
171 /* Fix : NULL_RETURNS */
172 if (connected_device == NULL) {
173 BT_ERR("No memory allocated");
177 connected_device->device_state = status;
178 //if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
179 if (status == BT_STATE_CONNECTED)
180 connected_device->type |= type;
181 g_strlcpy(connected_device->device_address, address,
182 sizeof(connected_device->device_address));
183 g_connected_list = g_list_append(g_connected_list, connected_device);
184 BT_DBG("Added device[%s] in connected list, device state [%d] Device Type [%d]",
185 address, connected_device->device_state, connected_device->type);
188 gboolean _bt_is_headset_type_connected(int type, char *address)
192 node = g_list_first(g_connected_list);
193 while (node != NULL) {
194 bt_connected_headset_data_t *connected_device = node->data;
196 if (connected_device->type & type) {
198 g_strlcpy(address, connected_device->device_address,
199 BT_ADDRESS_STRING_SIZE);
203 node = g_list_next(node);
209 gboolean _bt_is_headset_address_type_connected(int type, const char *address)
213 node = g_list_first(g_connected_list);
214 while (node != NULL) {
215 bt_connected_headset_data_t *connected_device = node->data;
217 if (connected_device && (connected_device->type & type)) {
218 if (memcmp(connected_device->device_address, address, 19) == 0)
222 node = g_list_next(node);
227 static void __bt_set_headset_disconnection_type(const char *address)
229 bt_connected_headset_data_t *connected_device;
232 node = g_list_first(g_connected_list);
233 while (node != NULL) {
234 connected_device = node->data;
235 if (g_strcmp0(connected_device->device_address, address) == 0) {
236 g_wait_data->disconnection_type = connected_device->type;
239 node = g_list_next(node);
243 #ifdef TIZEN_SUPPORT_DUAL_HF
244 gboolean __bt_is_companion_device(const char *addr)
246 if (TIZEN_PROFILE_WEARABLE) {
247 char *host_device_address = NULL;
248 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
250 if (!host_device_address) {
251 BT_INFO("Failed to get a companion device address");
255 if (g_strcmp0(host_device_address, addr) == 0) {
256 BT_INFO("addr[%s] is companion device", addr);
262 /* TODO : Need to add companion device check condition for Phone models */
268 static int __bt_is_headset_disconnecting(int type)
270 bt_connected_headset_data_t *connected_device = NULL;
272 /* Check if any other headset is connected */
275 node = g_list_first(g_connected_list);
276 while (node != NULL) {
277 connected_device = node->data;
278 if (connected_device->device_state == BT_STATE_DISCONNECTING)
279 return BLUETOOTH_ERROR_CONNECTION_BUSY;
280 node = g_list_next(node);
283 return BLUETOOTH_ERROR_NONE;
286 static int __bt_is_headset_connecting(int type)
288 bt_connected_headset_data_t *connected_device = NULL;
290 /* Check if any other headset is connected */
293 node = g_list_first(g_connected_list);
294 while (node != NULL) {
295 connected_device = node->data;
296 if (connected_device->device_state == BT_STATE_CONNECTING) {
297 BT_ERR("@@Device [%s] is already under connecting state", connected_device->device_address);
298 return BLUETOOTH_ERROR_CONNECTION_BUSY;
300 node = g_list_next(node);
303 return BLUETOOTH_ERROR_NONE;
306 static int __bt_is_headset_connected(int current_conn_type, const char *address)
308 gboolean connected = FALSE;
310 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
311 bluetooth_device_address_t device_address;
312 bt_connected_headset_data_t *connected_device = NULL;
313 #ifdef TIZEN_SUPPORT_DUAL_HF
314 gboolean is_companion_device = FALSE;
317 /* Check if any other headset is connected */
320 BT_DBG("Checking if any Headset connected or not: current device [%s] current audio type [%s]",
321 address, __convert_audio_type_to_string(current_conn_type));
322 node = g_list_first(g_connected_list);
323 while (node != NULL) {
324 connected_device = node->data;
325 BT_DBG("A Device is already connected found in list [%s] audio type [%s]",
326 connected_device->device_address, __convert_audio_type_to_string(connected_device->type));
327 if ((connected_device->type & current_conn_type)) {
328 g_strlcpy(connected_address, connected_device->device_address,
329 BT_ADDRESS_STRING_SIZE + 1);
330 #ifdef TIZEN_SUPPORT_DUAL_HF
331 is_companion_device = __bt_is_companion_device(connected_address);
332 BT_INFO("is_companion_device[%d]", is_companion_device);
334 if (!is_companion_device) {
343 node = g_list_next(node);
347 BT_DBG("There is no connected device with connection type [%s]",
348 __convert_audio_type_to_string(current_conn_type));
349 return BLUETOOTH_ERROR_NOT_CONNECTED;
352 BT_DBG("connected headset %s", connected_address);
354 if (g_strcmp0(connected_address, address) == 0)
355 return BLUETOOTH_ERROR_ALREADY_CONNECT;
356 #ifdef TIZEN_SUPPORT_DUAL_HF
357 else if (TRUE == __bt_is_companion_device(address))
358 return BLUETOOTH_ERROR_NOT_CONNECTED;
361 /* Convert BD address from string type */
362 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
363 int value = BLUETOOTH_ERROR_NONE;
364 BT_DBG("Already headset connected. addr [%s] connected type [%s] current audio type [%s]",
365 connected_address, __convert_audio_type_to_string(connected_device->type),
366 __convert_audio_type_to_string(current_conn_type));
367 disconn_type = connected_device->type & current_conn_type;
368 BT_DBG("Attempt disconnection of Type [%s] of already connected device",
369 __convert_audio_type_to_string(disconn_type));
370 value = _bt_audio_disconnect(disconn_type, &device_address);
372 /* If already one device is waiting, remove current waiting device and add new */
373 if (value == BLUETOOTH_ERROR_NONE) {
374 if (g_wait_data != NULL) {
375 if (g_strcmp0(g_wait_data->address, address) != 0) {
376 BT_INFO("Already one device was waiting for connection [%s], remove it", g_wait_data->address + 12);
377 __bt_remove_device_from_wait_list(g_wait_data->address);
378 __bt_free_wait_data();
382 if (g_wait_data == NULL) {
383 BT_INFO("Add current device [%s] into waiting list", address + 12);
384 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
385 g_wait_data->address = g_strdup(address);
386 g_wait_data->type = current_conn_type;
387 g_wait_data->ag_flag = FALSE;
389 /* Set disconnection type */
390 __bt_set_headset_disconnection_type(connected_address);
397 static void __bt_remove_device_from_wait_list(char *prev_waiting_device)
399 /* Before deleting the request update the UI */
400 bluetooth_device_address_t device_address;
401 int result = BLUETOOTH_ERROR_INTERNAL;
403 invocation_info_t *req_info;
404 BT_INFO("We are about to DBUS return previous waiting device [%s]", prev_waiting_device);
406 _bt_convert_addr_string_to_type(device_address.addr, prev_waiting_device);
408 req_info = _bt_get_request_info_data(BT_AV_CONNECT, prev_waiting_device);
409 if (req_info == NULL) {
410 BT_ERR("req_info == NULL");
413 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
414 g_array_append_vals(out_param, &device_address,
415 sizeof(bluetooth_device_address_t));
416 _bt_service_method_return(req_info->context,
418 g_array_free(out_param, TRUE);
419 _bt_free_info_from_invocation_list(req_info);
423 static int __bt_process_audio_profile_connect(bt_audio_type_t type, bluetooth_device_address_t *address)
425 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
426 int result = BLUETOOTH_ERROR_NONE;
427 BT_DBG("type %s", __convert_audio_type_to_string(type));
429 _bt_convert_addr_type_to_string(addr,
430 (unsigned char *)address->addr);
431 /* Attempt profile level connection based on type */
434 result = _bt_connect_remote_hfp(address);
437 result = _bt_a2dp_connect_remote_sink(address);
439 case BT_AVRCP_TARGET:
440 result = _bt_avrcp_connect_remote_ctrl(address);
443 result = _bt_avrcp_connect_remote_target(address);
445 case BT_AUDIO_A2DP_SOURCE:
446 return _bt_a2dp_connect_remote_source(address);
449 return _bt_connect_remote_ag(address);
451 BT_ERR("Unknown role");
452 return BLUETOOTH_ERROR_INTERNAL;
455 if (result == BLUETOOTH_ERROR_NONE) {
456 //_bt_headset_set_local_connection(TRUE);
457 /* Add data to the connected list */
458 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, addr);
459 BT_PERMANENT_LOG("Connect %s", __convert_audio_type_to_string(type));
461 BT_ERR("Profile [%s] connect failed!!", __convert_audio_type_to_string(type));
466 static int __bt_process_audio_profile_disconnect(bt_audio_type_t type, bluetooth_device_address_t *address)
468 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
469 int result = BLUETOOTH_ERROR_NONE;
471 BT_DBG("type %s", __convert_audio_type_to_string(type));
473 _bt_convert_addr_type_to_string(addr,
474 (unsigned char *)address->addr);
475 /* Attempt profile level connection based on type */
478 result = _bt_disconnect_remote_hfp(address);
481 result = _bt_a2dp_disconnect_remote_sink(address);
483 case BT_AVRCP_TARGET:
484 result = _bt_avrcp_disconnect_remote_ctrl(address);
487 result = _bt_avrcp_disconnect_remote_target(address);
489 case BT_AUDIO_A2DP_SOURCE:
490 return _bt_a2dp_disconnect_remote_source(address);
493 BT_ERR("Unknown role");
494 return BLUETOOTH_ERROR_INTERNAL;
497 if (result == BLUETOOTH_ERROR_NONE) {
499 * This logic is added for dual HF mode issue.
501 node = g_list_first(g_connected_list);
502 while (node != NULL) {
503 bt_connected_headset_data_t *connected_device = node->data;
505 if (g_strcmp0(connected_device->device_address, addr) == 0) {
506 BT_DBG("Connection type update. old type[%s] -> new type[%s]",
507 __convert_audio_type_to_string(connected_device->type),
508 __convert_audio_type_to_string(type));
509 type = connected_device->type;
512 node = g_list_next(node);
515 /* Update device status in connected list */
516 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, addr);
517 BT_PERMANENT_LOG("Disconnect %s", __convert_audio_type_to_string(type));
519 BT_ERR("Profile [%s] disconnect failed!!", __convert_audio_type_to_string(type));
525 int _bt_audio_initialize(bt_service_module_t module)
527 oal_status_t status = OAL_STATUS_SUCCESS;
528 int ret = BLUETOOTH_ERROR_NONE;
530 BT_INFO("_bt_audio_initialize: Module [%d]", module);
533 case BT_A2DP_SOURCE_MODULE: {
534 status = audio_enable(NULL, NULL);
535 if (OAL_STATUS_SUCCESS != status) {
536 BT_ERR("Failed to initialize Bluetooth A2DP Source Profile, status: %d", status);
537 return _bt_convert_oal_status_to_bt_error(status);
539 /* Register Audio module event handler */
540 _bt_service_register_event_handler_callback(module, _bt_a2dp_source_event_handler);
543 case BT_A2DP_SINK_MODULE: {
544 status = a2dp_sink_enable(NULL, NULL);
545 if (status != OAL_STATUS_SUCCESS) {
546 BT_ERR("Failed to initialize Bluetooth A2DP Sink Profile, status: %d", status);
547 return _bt_convert_oal_status_to_bt_error(status);
549 /* Register Audio sink module event handler */
550 _bt_service_register_event_handler_callback(module, _bt_a2dp_sink_event_handler);
553 case BT_HFP_MODULE: {
554 status = hf_client_enable();
555 if (OAL_STATUS_SUCCESS != status) {
556 BT_ERR("Failed to initialize Bluetooth HFP client Profile, status: %d", status);
557 return _bt_convert_oal_status_to_bt_error(status);
559 /* Register Audio module event handler */
560 _bt_service_register_event_handler_callback(module, _bt_hf_client_event_handler);
564 status = hfp_enable(1);
565 if (OAL_STATUS_SUCCESS != status) {
566 BT_ERR("Failed to initialize Bluetooth HFP Audio Gateway Profile, status: %d", status);
567 return _bt_convert_oal_status_to_bt_error(status);
569 /* Register Audio module event handler */
570 _bt_service_register_event_handler_callback(module, _bt_hf_event_handler);
573 case BT_AUDIO_ALL_MODULE: {
574 /* Register Audio module event handler */
575 _bt_service_register_event_handler_callback(module, __bt_audio_event_handler);
578 case BT_AVRCP_CTRL_MODULE: {
579 status = avrcp_ct_enable();
580 if (status != OAL_STATUS_SUCCESS) {
581 BT_ERR("Failed to initialize Bluetooth AVRCP Controller Profile, status: %d", status);
582 return _bt_convert_oal_status_to_bt_error(status);
584 /* Register Avrcp Controller event handler */
585 _bt_service_register_event_handler_callback(module, _bt_avrcp_ctrl_event_handler);
588 case BT_AVRCP_MODULE: {
589 /* Initialize AVRCP Target */
590 ret = _bt_service_avrcp_enable();
594 BT_ERR("Not Supported: Module [%d]", module);
595 return BLUETOOTH_ERROR_NOT_SUPPORT;
598 BT_INFO("Bluetooth audio interface initialised");
602 static void __bt_audio_event_handler(int oal_event, gpointer event_data)
605 case OAL_EVENT_ADAPTER_DISABLED: {
606 BT_INFO("Adapter Disabled..cleanup resources");
607 __bt_audio_cleanup_resources();
610 case OAL_EVENT_ADAPTER_ENABLED: {
611 /*TODO Currently not handled */
612 BT_INFO("Adapter Enabled..");
616 BT_DBG("Unknown event..[%d]", oal_event);
621 static void __bt_audio_cleanup_resources(void)
625 bt_pending_audio_conn_t *info = NULL;
627 /* Remove connected device list */
628 node = g_list_first(g_connected_list);
629 while (node != NULL) {
630 bt_connected_headset_data_t *connected_device = node->data;
631 BT_INFO("Data found [%s] in connected device list...remove it..", connected_device->device_address);
632 g_connected_list = g_list_remove(g_connected_list, connected_device);
633 node = g_list_next(node);
636 /* Remove pending connection list */
637 for (l = pending_audio_conn_list; l != NULL; l = g_slist_next(l)) {
638 info = (bt_pending_audio_conn_t*)l->data;
641 BT_INFO("Info found for addr [%s], remove it...", info->address);
642 pending_audio_conn_list = g_slist_remove(pending_audio_conn_list, info);
643 g_free(info->address);
650 static int __bt_process_audio_connect_all(bt_pending_audio_conn_t *info)
652 bluetooth_device_address_t device_address;
653 int result = BLUETOOTH_ERROR_NONE;
654 int type = BT_AUDIO_ALL;
658 _bt_convert_addr_string_to_type(device_address.addr, info->address);
660 /* Attempt profile level connection */
661 if (info->is_hfp_supported) {
663 result = _bt_connect_remote_hfp(&device_address);
665 if (info->is_a2dp_sink_supported)
666 BT_DBG("A2DP is supported by [%s]", info->address);
668 BT_DBG("A2DP is not supported");
669 } else if (info->is_a2dp_sink_supported) {
670 type = BT_AUDIO_A2DP;
671 result = _bt_a2dp_connect_remote_sink(&device_address);
672 } else if (info->is_a2dp_src_supported) {
673 type = BT_AUDIO_A2DP_SOURCE;
674 result = _bt_a2dp_connect_remote_source(&device_address);
676 if (result == BLUETOOTH_ERROR_NONE) {
677 //_bt_headset_set_local_connection(TRUE);
678 /* Add data to the connected list */
679 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, info->address);
681 BT_ERR("Profile connect failed!!");
686 bt_pending_audio_conn_t* _bt_get_pending_audio_conn_info(char *address)
688 bt_pending_audio_conn_t *info = NULL;
691 for (l = pending_audio_conn_list; l != NULL; l = g_slist_next(l)) {
692 info = (bt_pending_audio_conn_t*)l->data;
694 if (g_strcmp0(info->address, address) == 0 && info->search_status == SERVICE_SEARCH_DONE) {
695 BT_INFO("Pending data found for addr [%s]", info->address + 12);
699 BT_INFO("Pending data not found!!");
703 static void __bt_reply_pending_audio_connect_req(char *address, int result)
706 invocation_info_t *req_info;
709 ret_if(NULL == address);
711 /* Reply to async request for Audio connect, if any */
712 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, address);
713 ret_if(NULL == req_info);
715 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
716 g_array_append_vals(out_param, address, BT_ADDRESS_STRING_SIZE);
717 _bt_service_method_return(req_info->context, out_param, result);
719 g_array_free(out_param, TRUE);
720 _bt_free_info_from_invocation_list(req_info);
725 void _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(bt_pending_audio_conn_t *info, int result)
727 ret_if(NULL == info);
729 /* Reply to async request for Audio connect, if any */
730 __bt_reply_pending_audio_connect_req(info->address, result);
732 /* Remove pending audio conn info */
733 pending_audio_conn_list = g_slist_remove(pending_audio_conn_list, info);
734 g_free(info->address);
738 gboolean _bt_audio_check_pending_connection(char *address)
740 bt_pending_audio_conn_t *data = NULL;
741 bluetooth_device_address_t device_address;
743 data = _bt_get_pending_audio_conn_info(address);
746 BT_INFO("A2DP Connection is pending..initiate it...");
747 if (data->is_a2dp_sink_supported && data->conn_req_type == BT_AUDIO_ALL) {
748 _bt_convert_addr_string_to_type(device_address.addr, address);
749 if (_bt_audio_connect(BT_AUDIO_A2DP, &device_address) != BLUETOOTH_ERROR_NONE) {
750 BT_INFO("A2DP connect triggered for [%s] but it failed!!", data->address);
751 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
753 BT_INFO("A2DP connect triggered successfully for [%s]", data->address);
755 } else if (data->is_a2dp_src_supported && data->conn_req_type == BT_AUDIO_HFP_SOURCE) {
756 _bt_convert_addr_string_to_type(device_address.addr, address);
757 if (_bt_audio_connect(BT_AUDIO_A2DP_SOURCE, &device_address) != BLUETOOTH_ERROR_NONE) {
758 BT_INFO("A2DP sink connect triggered for [%s] but it failed!!", data->address);
759 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
761 BT_INFO("A2DP sink connect triggered successfully for [%s]", data->address);
766 BT_INFO("A2DP Connection is not pending..");
771 void _bt_audio_check_pending_disconnection(char *address, int type)
773 int ret = BLUETOOTH_ERROR_NONE;
774 bluetooth_device_address_t device_address;
776 if (_bt_is_service_connected(address, type)) {
777 BT_INFO("Service [%s] is connected with device [%s], disconnect it...",
778 __convert_audio_type_to_string(type), address + 12);
779 _bt_convert_addr_string_to_type(device_address.addr, address);
780 ret = __bt_process_audio_profile_disconnect(type, &device_address);
782 if (ret != BLUETOOTH_ERROR_NONE)
783 BT_ERR("Disconnecting service [%s] with device [%s] failed!!",
784 __convert_audio_type_to_string(type), address + 12);
786 BT_INFO("Service [%s] is Not connected with device [%s],..",
787 __convert_audio_type_to_string(type), address + 12);
791 int __bt_handle_audio_all_connect(bt_pending_audio_conn_t *info)
793 bt_remote_dev_info_t *rem_info;
797 retv_if(NULL == info, BLUETOOTH_ERROR_INTERNAL);
798 retv_if(NULL == info->address, BLUETOOTH_ERROR_INTERNAL);
800 rem_info = _bt_service_get_remote_dev_info(info->address);
802 BT_ERR("_bt_service_get_remote_dev_info returned NULL");
803 ret = BLUETOOTH_ERROR_NOT_PAIRED;
807 for (indx = 0; indx < rem_info->uuid_count; indx++) {
808 BT_INFO("UUID [%s]", rem_info->uuids[indx]);
809 if (0 == g_strcmp0(A2DP_SINK_UUID, rem_info->uuids[indx])) {
810 BT_INFO("Device supports A2DP Sink Profile");
811 info->is_a2dp_sink_supported = TRUE;
812 } else if (0 == g_strcmp0(A2DP_SOURCE_UUID, rem_info->uuids[indx])) {
813 BT_INFO("Device supports A2DP Source Profile");
814 info->is_a2dp_src_supported = TRUE;
815 } else if ((g_strcmp0(HFP_HS_UUID, rem_info->uuids[indx]) == 0)) {
816 BT_INFO("Device supports HFP Profile");
817 info->is_hfp_supported = TRUE;
821 if (info->is_a2dp_sink_supported == FALSE &&
822 info->is_hfp_supported == FALSE &&
823 info->is_a2dp_src_supported == FALSE) {
824 BT_ERR("No audio profile is supported");
825 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
829 BT_INFO("AUDIO_CONNECT_ALL request for [%s]", info->address + 12);
830 info->search_status = SERVICE_SEARCH_DONE;
832 /* Give preference to HFP over A2DP for outgoing connection sequence for AUDIO_ALL_CONNECT */
833 if (info->is_hfp_supported)
834 info->type = BT_AUDIO_HSP;
835 else if (info->is_a2dp_sink_supported)
836 info->type = BT_AUDIO_A2DP;
837 else if (info->is_a2dp_src_supported)
838 info->type = BT_AUDIO_A2DP_SOURCE;
840 ret = __bt_is_headset_connected(info->type, info->address);
841 if (ret == BLUETOOTH_ERROR_ALREADY_CONNECT) {
842 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
843 info->address + 12, "Already connected...");
847 if (ret == BLUETOOTH_ERROR_IN_PROGRESS) {
848 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
849 info->address + 12, "Already in progress...");
853 if (ret == BLUETOOTH_ERROR_NOT_CONNECTED) {
854 BT_ERR("Great, can start Audio All connect for [%s]", info->address + 12);
855 ret = __bt_is_headset_connecting(info->type);
856 if (ret != BLUETOOTH_ERROR_NONE) {
857 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
858 info->address + 12, "some other device conn in progress");
859 ret = BLUETOOTH_ERROR_IN_PROGRESS;
863 ret = __bt_process_audio_connect_all(info);
864 if (ret != BLUETOOTH_ERROR_NONE) {
865 BT_ERR("__bt_process_audio_connect_all failed");
869 BT_PERMANENT_LOG("Connect %s", __convert_audio_type_to_string(info->type));
870 /* If multiple profiles are supported, queue pending connection info */
871 if ((info->is_hfp_supported && info->is_a2dp_sink_supported) ||
872 (info->is_hfp_supported && info->is_a2dp_src_supported)) {
873 BT_INFO("[%s] Supports HFP and (A2DP_Src or, A2DP_Snk)", info->address + 12);
874 pending_audio_conn_list = g_slist_append(pending_audio_conn_list, (gpointer)info);
876 BT_INFO("[%s] Supports one profile only", info->address + 12);
878 * It means, we dont need pending connect info as only A2DP (Src/Snk) or
879 * HFP will be connected for present device, so lets free pending info.
881 g_free(info->address);
884 } else if (ret == BLUETOOTH_ERROR_NONE) {
885 BT_INFO("Waiting for disconnection...");
887 if ((info->is_hfp_supported && info->is_a2dp_sink_supported) ||
888 (info->is_hfp_supported && info->is_a2dp_src_supported)) {
889 BT_INFO("[%s] Supports HFP and (A2DP_Src or, A2DP_Snk)", info->address + 12);
890 pending_audio_conn_list = g_slist_append(pending_audio_conn_list, (gpointer)info);
892 BT_INFO("[%s] Supports one profile only", info->address + 12);
894 * It means, we dont need pending connect info as only A2DP (Src/Snk) or
895 * HFP will be connected for present device, so lets free pending info.
897 g_free(info->address);
902 return BLUETOOTH_ERROR_NONE;
905 BT_ERR("Audio connect all failed");
906 g_free(info->address);
911 static gboolean __audio_get_bonded_info(gpointer data)
913 bt_pending_audio_conn_t *info = data;
914 char address[BT_ADDRESS_STRING_SIZE];
916 retv_if(NULL == info, FALSE);
917 retv_if(NULL == info->address, FALSE);
919 if ((info->bonded_info_retries > 0) && !_bt_is_bonded_devices_retrived()) {
920 info->bonded_info_retries--;
924 g_strlcpy(address, info->address, BT_ADDRESS_STRING_SIZE);
925 if (info->bonded_info_retries <= 0) {
926 BT_ERR_C("Even after all retries, bonded devices stil not retrieved");
927 g_free(info->address);
932 if (BLUETOOTH_ERROR_NONE != __bt_handle_audio_all_connect(info)) {
933 BT_ERR("__bt_handle_audio_all_connect failed");
939 __bt_reply_pending_audio_connect_req(address, BLUETOOTH_ERROR_INTERNAL);
943 int _bt_audio_connect(int type, bluetooth_device_address_t *device_address)
945 int ret = BLUETOOTH_ERROR_NONE;
946 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
947 bt_pending_audio_conn_t *info = NULL;
949 BT_CHECK_PARAMETER(device_address, return);
951 _bt_convert_addr_type_to_string(address, device_address->addr);
952 BT_INFO("Audio Connect Request: type[%s] address [%s]",
953 __convert_audio_type_to_string(type), address + 12);
956 * If type is BT_AUDIO_ALL or BT_AUDIO_HFP_SOURCE, enqueue search info in
957 * order to find out supported services by the remote device.
959 if (type == BT_AUDIO_ALL || type == BT_AUDIO_HFP_SOURCE) {
960 if (NULL != _bt_get_pending_audio_conn_info(address)) {
961 BT_ERR("Connection for same device already in progress");
962 return BLUETOOTH_ERROR_IN_PROGRESS;
965 info = g_malloc0(sizeof(bt_pending_audio_conn_t));
966 info->search_status = SERVICE_SEARCH_STARTED;
967 info->address = g_strdup(address);
969 info->conn_req_type = type;
971 /* Request bonded device info */
972 if (!_bt_is_bonded_devices_retrived()) {
973 info->bonded_info_retries = 5;
974 /* Wait till bonded devices retrival is completed */
975 g_timeout_add_seconds(1, __audio_get_bonded_info, info);
976 return BLUETOOTH_ERROR_NONE;
979 return __bt_handle_audio_all_connect(info);
982 /* If type is A2DP Sink or HSP/HFP, check further */
983 ret = __bt_is_headset_connected(type, address);
984 if (ret == BLUETOOTH_ERROR_ALREADY_CONNECT) {
985 BT_ERR("Failed with BLUETOOTH_ERROR_ALREADY_CONNECT");
986 return BLUETOOTH_ERROR_ALREADY_CONNECT;
989 if (ret == BLUETOOTH_ERROR_IN_PROGRESS) {
990 BT_ERR("Failed with BLUETOOTH_ERROR_IN_PROGRESS");
991 return BLUETOOTH_ERROR_IN_PROGRESS;
994 if (ret == BLUETOOTH_ERROR_NONE) {
995 BT_INFO("Waiting for disconnection...");
996 } else if (ret == BLUETOOTH_ERROR_NOT_CONNECTED) {
997 ret = __bt_process_audio_profile_connect(type, device_address);
998 if (ret != BLUETOOTH_ERROR_NONE) {
999 BT_ERR("Failed with %d", ret);
1004 return BLUETOOTH_ERROR_NONE;
1007 int _bt_audio_disconnect(int type, bluetooth_device_address_t *device_address)
1009 int ret = BLUETOOTH_ERROR_NONE;
1010 int value = BLUETOOTH_ERROR_NONE;
1011 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1013 _bt_convert_addr_type_to_string(address, device_address->addr);
1014 BT_INFO("Audio Diconnect Request: type[%s] address [%s]",
1015 __convert_audio_type_to_string(type), address + 12);
1017 if (type == BT_AUDIO_ALL) {
1018 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
1019 type = BT_AUDIO_A2DP;
1020 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
1021 type = BT_AUDIO_HSP;
1023 BT_ERR("No audio service connected");
1024 return BLUETOOTH_ERROR_NOT_CONNECTED;
1026 } else if (type == BT_AUDIO_HFP_SOURCE) {
1027 if (_bt_is_service_connected(address, BT_AUDIO_A2DP_SOURCE)) {
1028 type = BT_AUDIO_A2DP_SOURCE;
1029 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
1030 type = BT_AUDIO_HSP;
1032 BT_ERR("No audio service connected");
1033 return BLUETOOTH_ERROR_NOT_CONNECTED;
1037 value = __bt_is_headset_disconnecting(type);
1038 if (value != BLUETOOTH_ERROR_NONE) {
1039 BT_INFO("Disconnect in progress");
1040 return BLUETOOTH_ERROR_IN_PROGRESS;
1043 ret = __bt_process_audio_profile_disconnect(type, device_address);
1047 gboolean _bt_is_service_connected(char* address, int type)
1050 node = g_list_first(g_connected_list);
1051 while (node != NULL) {
1052 bt_connected_headset_data_t *conn_device = node->data;
1054 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
1055 (conn_device->type & type)) {
1056 BT_INFO("Service connected");
1060 node = g_list_next(node);
1062 BT_INFO("Service not connected");
1066 void _bt_remove_headset_from_list(int type, const char *address)
1070 BT_DBG("type %s", __convert_audio_type_to_string(type));
1072 node = g_list_first(g_connected_list);
1073 while (node != NULL) {
1074 bt_connected_headset_data_t *connected_device = node->data;
1076 if (g_strcmp0(connected_device->device_address, address) != 0) {
1077 node = g_list_next(node);
1081 BT_DBG("Address match. Connection type = %s",
1082 __convert_audio_type_to_string(connected_device->type));
1086 if (connected_device->type & BT_AUDIO_A2DP)
1087 connected_device->type &= ~(BT_AUDIO_A2DP);
1090 if (connected_device->type & BT_AUDIO_HSP)
1091 connected_device->type &= ~(BT_AUDIO_HSP);
1094 if (connected_device->type & BT_AUDIO_ALL)
1095 connected_device->type &= ~(BT_AUDIO_ALL);
1097 case BT_AVRCP_TARGET:
1098 if (connected_device->type & BT_AVRCP_TARGET)
1099 connected_device->type &= ~(BT_AVRCP_TARGET);
1102 if (connected_device->type & BT_AVRCP)
1103 connected_device->type &= ~(BT_AVRCP);
1105 case BT_AUDIO_A2DP_SOURCE:
1106 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
1107 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
1113 if (connected_device->type == 0x00) {
1114 BT_INFO("Device will be completely removed from connected list as the only profile connected or connecting got disconnected");
1115 g_connected_list = g_list_remove(g_connected_list, connected_device);
1116 g_free(connected_device);
1118 connected_device->device_state = BT_STATE_CONNECTED;
1121 node = g_list_next(node);
1125 * If Audio role selection request is pending (pending_audio_role > 0) then process pending
1126 * audio role select request on BT_AUDIO_A2DP/BT_AUDIO_A2DP_SOURCE device dicaonnection.
1128 if (pending_audio_role >= 0 &&
1129 (type == BT_AUDIO_A2DP || type == BT_AUDIO_A2DP_SOURCE))
1130 g_idle_add(__handle_pending_audio_select_role, NULL);
1133 static void __handle_pending_requests(int result, int service_function, void *user_data, unsigned int size)
1137 invocation_info_t *req_info;
1141 /* Get method invocation context */
1142 for (l = _bt_get_invocation_list(); l != NULL; ) {
1144 l = g_slist_next(l);
1146 if (req_info == NULL || req_info->service_function != service_function)
1149 /* Create out param */
1150 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
1152 switch (service_function) {
1153 case BT_AUDIO_SELECT_ROLE:
1154 _bt_service_method_return(req_info->context, out_param, result);
1155 g_array_free(out_param, TRUE);
1156 _bt_free_info_from_invocation_list(req_info);
1159 BT_ERR("Unknown service function[%d]", service_function);
1167 static gboolean __handle_pending_audio_select_role(gpointer data)
1170 oal_status_t status;
1173 if (BLUETOOTH_A2DP_SOURCE == pending_audio_role) {
1174 /* Disable A2DP Sink role */
1175 status = a2dp_sink_disable();
1176 if (status != OAL_STATUS_SUCCESS) {
1177 BT_ERR("Failed to Disable Bluetooth A2DP Sink Profile, status: %d", status);
1178 ret = _bt_convert_oal_status_to_bt_error(status);
1182 /* Disable AVRCP CT role */
1183 status = avrcp_ct_disable();
1184 if (status != OAL_STATUS_SUCCESS) {
1185 BT_ERR("Failed to Disable Bluetooth AVRCP Controller Profile, status: %d", status);
1186 ret = _bt_convert_oal_status_to_bt_error(status);
1190 /* Enable A2DP Source role */
1191 ret = _bt_audio_initialize(BT_A2DP_SOURCE_MODULE);
1192 if (ret != BLUETOOTH_ERROR_NONE) {
1193 BT_ERR("Failed to enable Bluetooth A2DP Source Profile");
1197 /* Enable AVRCP TG role */
1198 ret = _bt_audio_initialize(BT_AVRCP_MODULE);
1199 if (ret != BLUETOOTH_ERROR_NONE) {
1200 BT_ERR("Failed to enable Bluetooth AVRCP Target Profile");
1204 /* Disable A2DP Source role */
1205 status = audio_disable();
1206 if (OAL_STATUS_SUCCESS != status) {
1207 BT_ERR("Failed to disable Bluetooth A2DP Source Profile, status: %d", status);
1208 ret = _bt_convert_oal_status_to_bt_error(status);
1212 /* Disable AVRCP TG role */
1213 ret = _bt_service_avrcp_disable();
1214 if (ret != BLUETOOTH_ERROR_NONE) {
1215 BT_ERR("Failed to Disable Bluetooth AVRCP Target Profile");
1219 /* Enable A2DP Sink role */
1220 ret = _bt_audio_initialize(BT_A2DP_SINK_MODULE);
1221 if (ret != BLUETOOTH_ERROR_NONE) {
1222 BT_ERR("Failed to enable Bluetooth A2DP Sink Profile");
1226 /* Enable AVRCP CT role */
1227 ret = _bt_audio_initialize(BT_AVRCP_CTRL_MODULE);
1228 if (ret != BLUETOOTH_ERROR_NONE) {
1229 BT_ERR("Failed to enable Bluetooth AVRCP Controller Profile");
1235 if (ret == BLUETOOTH_ERROR_NONE)
1236 _bt_audio_set_current_role(pending_audio_role);
1238 __handle_pending_requests(ret, BT_AUDIO_SELECT_ROLE, NULL, 0);
1239 pending_audio_role = -1;
1244 int _bt_audio_select_role(bluetooth_audio_role_t role)
1246 int result = BLUETOOTH_ERROR_NONE;
1247 char address[BT_ADDRESS_STRING_SIZE];
1248 bluetooth_device_address_t dev_addr;
1250 retv_if(BLUETOOTH_A2DP_SINK < role, BLUETOOTH_ERROR_INVALID_PARAM);
1251 retv_if(pending_audio_role >= 0, BLUETOOTH_ERROR_IN_PROGRESS);
1255 if (curr_audio_role == role) {
1256 BT_ERR("Desired audio role already enabled, return");
1257 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1260 pending_audio_role = role;
1262 if (BLUETOOTH_A2DP_SINK == role) {
1263 if (_bt_is_headset_type_connected(BT_AUDIO_A2DP, address)) {
1264 _bt_convert_addr_string_to_type(dev_addr.addr, address);
1265 result = _bt_audio_disconnect(BT_AUDIO_A2DP, &dev_addr);
1266 if (result != BLUETOOTH_ERROR_NONE) {
1267 BT_ERR("_bt_audio_disconnect(BT_AUDIO_A2DP, %s) Failed", address);
1268 result = _bt_convert_oal_status_to_bt_error(result);
1271 BT_INFO("No BT_AUDIO_A2DP device is connected, proceed with role switch");
1272 g_idle_add(__handle_pending_audio_select_role, NULL);
1273 result = BLUETOOTH_ERROR_NONE;
1276 if (_bt_is_headset_type_connected(BT_AUDIO_A2DP_SOURCE, address)) {
1277 _bt_convert_addr_string_to_type(dev_addr.addr, address);
1278 result = _bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, &dev_addr);
1279 if (result != BLUETOOTH_ERROR_NONE) {
1280 BT_ERR("_bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, %s) Failed", address);
1281 result = _bt_convert_oal_status_to_bt_error(result);
1284 BT_INFO("No BT_AUDIO_A2DP_SOURCE device is connected, proceed with role switch");
1285 g_idle_add(__handle_pending_audio_select_role, NULL);
1286 result = BLUETOOTH_ERROR_NONE;
1294 void _bt_audio_set_current_role(bluetooth_audio_role_t role)
1296 BT_INFO("role: %s", (role == BLUETOOTH_A2DP_SINK) ? "AUDIO_SINK" : "AUDIO_SOURCE");
1297 curr_audio_role = role;
1300 int _bt_hf_connect(bluetooth_device_address_t *device_address)
1302 int result = BLUETOOTH_ERROR_NONE;
1305 result = _bt_connect_remote_ag(device_address);
1306 if (result != BLUETOOTH_ERROR_NONE)
1307 BT_ERR("HF Client connect to remote AG failed");
1309 BT_PERMANENT_LOG("Connect AG");
1314 int _bt_hf_disconnect(bluetooth_device_address_t *device_address)
1316 int result = BLUETOOTH_ERROR_NONE;
1319 result = _bt_disconnect_remote_ag(device_address);
1320 if (result != BLUETOOTH_ERROR_NONE)
1321 BT_ERR("HF Client disconnect to remote AG failed");
1323 BT_PERMANENT_LOG("Disconnect AG");