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>
30 #include "oal-a2dp-sink.h"
31 #include "oal-audio-src.h"
32 #include "oal-device-mgr.h"
33 #include "oal-event.h"
34 #include "oal-hardware.h"
35 #include "oal-hf-client.h"
37 #include "bt-request-handler.h"
38 #include "bt-service-a2dp-sink.h"
39 #include "bt-service-a2dp-src.h"
40 #include "bt-service-avrcp-ctrl.h"
41 #include "bt-service-avrcp-tg.h"
42 #include "bt-service-audio-common.h"
43 #include "bt-service-common.h"
44 #include "bt-service-core-device.h"
45 #include "bt-service-headset-connection.h"
46 #include "bt-service-hf.h"
47 #include "bt-service-hf-client.h"
49 #ifdef TIZEN_SUPPORT_DUAL_HF
50 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
53 /* Static variables and Macros */
54 static GList *g_connected_list;
55 static bt_headset_wait_t *g_wait_data;
59 char device_address[BT_ADDRESS_STRING_SIZE + 1];
60 } bt_connected_headset_data_t;
62 /* List for saving device service search info */
63 static GSList *pending_audio_conn_list = NULL;
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);
84 static const char *__convert_audio_type_to_string(bt_audio_type_t type)
94 return "AVRCP_TARGET";
97 case BT_AUDIO_A2DP_SOURCE:
99 case BT_AUDIO_HFP_SOURCE:
108 void _bt_set_audio_wait_data_flag(gboolean flag)
110 BT_DBG("_bt_set_audio_wait_data_flag \n");
111 g_wait_data->ag_flag = flag;
114 bt_headset_wait_t *_bt_get_audio_wait_data(void)
116 BT_DBG("_bt_get_audio_wait_data \n");
120 static void __bt_free_wait_data(void)
122 if (g_wait_data != NULL) {
123 g_free(g_wait_data->address);
129 void _bt_rel_wait_data(void)
131 BT_DBG("_bt_rel_wait_data \n");
132 __bt_free_wait_data();
135 void _bt_add_headset_to_list(int type, int status, const char *address)
137 bt_connected_headset_data_t *connected_device;
138 bt_connected_headset_data_t *device;
141 BT_DBG("_bt_add_headset_to_list \n");
143 node = g_list_first(g_connected_list);
144 while (node != NULL) {
145 device = (bt_connected_headset_data_t *)node->data;
147 if (g_strcmp0(device->device_address, address) == 0) {
148 BT_DBG("Address match, update connection type \n");
149 if (status == BT_STATE_CONNECTED)
150 device->type |= type;
151 device->device_state = status;
154 node = g_list_next(node);
157 connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
158 /* Fix : NULL_RETURNS */
159 if (connected_device == NULL) {
160 BT_ERR("No memory allocated");
164 connected_device->device_state = status;
165 //if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
166 if (status == BT_STATE_CONNECTED)
167 connected_device->type |= type;
168 g_strlcpy(connected_device->device_address, address,
169 sizeof(connected_device->device_address));
170 g_connected_list = g_list_append(g_connected_list, connected_device);
171 BT_DBG("Added device[%s] in connected list, device state [%d] Device Type [%d]",
172 address, connected_device->device_state, connected_device->type);
175 gboolean _bt_is_headset_type_connected(int type, char *address)
179 node = g_list_first(g_connected_list);
180 while (node != NULL) {
181 bt_connected_headset_data_t *connected_device = node->data;
183 if (connected_device->type & type) {
185 g_strlcpy(address, connected_device->device_address,
186 BT_ADDRESS_STRING_SIZE);
190 node = g_list_next(node);
196 gboolean _bt_is_headset_address_type_connected(int type, const char *address)
200 node = g_list_first(g_connected_list);
201 while (node != NULL) {
202 bt_connected_headset_data_t *connected_device = node->data;
204 if (connected_device && (connected_device->type & type)) {
205 if (memcmp(connected_device->device_address, address, 19) == 0)
209 node = g_list_next(node);
214 static void __bt_set_headset_disconnection_type(const char *address)
216 bt_connected_headset_data_t *connected_device;
219 node = g_list_first(g_connected_list);
220 while (node != NULL) {
221 connected_device = node->data;
222 if (g_strcmp0(connected_device->device_address, address) == 0) {
223 g_wait_data->disconnection_type = connected_device->type;
226 node = g_list_next(node);
230 #ifdef TIZEN_SUPPORT_DUAL_HF
231 gboolean __bt_is_companion_device(const char *addr)
233 if (TIZEN_PROFILE_WEARABLE) {
234 char *host_device_address = NULL;
235 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
237 if (!host_device_address) {
238 BT_INFO("Failed to get a companion device address");
242 if (g_strcmp0(host_device_address, addr) == 0) {
243 BT_INFO("addr[%s] is companion device", addr);
249 /* TODO : Need to add companion device check condition for Phone models */
255 static int __bt_is_headset_disconnecting(int type)
257 bt_connected_headset_data_t *connected_device = NULL;
259 /* Check if any other headset is connected */
262 node = g_list_first(g_connected_list);
263 while (node != NULL) {
264 connected_device = node->data;
265 if (connected_device->device_state == BT_STATE_DISCONNECTING)
266 return BLUETOOTH_ERROR_CONNECTION_BUSY;
267 node = g_list_next(node);
270 return BLUETOOTH_ERROR_NONE;
273 static int __bt_is_headset_connecting(int type)
275 bt_connected_headset_data_t *connected_device = NULL;
277 /* Check if any other headset is connected */
280 node = g_list_first(g_connected_list);
281 while (node != NULL) {
282 connected_device = node->data;
283 if (connected_device->device_state == BT_STATE_CONNECTING) {
284 BT_ERR("@@Device [%s] is already under connecting state", connected_device->device_address);
285 return BLUETOOTH_ERROR_CONNECTION_BUSY;
287 node = g_list_next(node);
290 return BLUETOOTH_ERROR_NONE;
293 static int __bt_is_headset_connected(int current_conn_type, const char *address)
295 gboolean connected = FALSE;
297 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
298 bluetooth_device_address_t device_address;
299 bt_connected_headset_data_t *connected_device = NULL;
300 #ifdef TIZEN_SUPPORT_DUAL_HF
301 gboolean is_companion_device = FALSE;
304 /* Check if any other headset is connected */
307 BT_DBG("Checking if any Headset connected or not: current device [%s] current audio type [%s]",
308 address, __convert_audio_type_to_string(current_conn_type));
309 node = g_list_first(g_connected_list);
310 while (node != NULL) {
311 connected_device = node->data;
312 BT_DBG("A Device is already connected found in list [%s] audio type [%s]",
313 connected_device->device_address, __convert_audio_type_to_string(connected_device->type));
314 if ((connected_device->type & current_conn_type)) {
315 g_strlcpy(connected_address, connected_device->device_address,
316 BT_ADDRESS_STRING_SIZE + 1);
317 #ifdef TIZEN_SUPPORT_DUAL_HF
318 is_companion_device = __bt_is_companion_device(connected_address);
319 BT_INFO("is_companion_device[%d]", is_companion_device);
321 if (!is_companion_device) {
330 node = g_list_next(node);
334 BT_DBG("There is no connected device with connection type [%s]",
335 __convert_audio_type_to_string(current_conn_type));
336 return BLUETOOTH_ERROR_NOT_CONNECTED;
339 BT_DBG("connected headset %s", connected_address);
341 if (g_strcmp0(connected_address, address) == 0)
342 return BLUETOOTH_ERROR_ALREADY_CONNECT;
343 #ifdef TIZEN_SUPPORT_DUAL_HF
344 else if (TRUE == __bt_is_companion_device(address))
345 return BLUETOOTH_ERROR_NOT_CONNECTED;
348 /* Convert BD address from string type */
349 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
350 int value = BLUETOOTH_ERROR_NONE;
351 BT_DBG("Already headset connected. addr [%s] connected type [%s] current audio type [%s]",
352 connected_address, __convert_audio_type_to_string(connected_device->type),
353 __convert_audio_type_to_string(current_conn_type));
354 disconn_type = connected_device->type & current_conn_type;
355 BT_DBG("Attempt disconnection of Type [%s] of already connected device",
356 __convert_audio_type_to_string(disconn_type));
357 value = _bt_audio_disconnect(disconn_type, &device_address);
359 /* If already one device is waiting, remove current waiting device and add new */
360 if (value == BLUETOOTH_ERROR_NONE) {
361 if (g_wait_data != NULL) {
362 if (g_strcmp0(g_wait_data->address, address) != 0) {
363 BT_INFO("Already one device was waiting for connection [%s], remove it", g_wait_data->address + 12);
364 __bt_remove_device_from_wait_list(g_wait_data->address);
365 __bt_free_wait_data();
369 if (g_wait_data == NULL) {
370 BT_INFO("Add current device [%s] into waiting list", address + 12);
371 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
372 g_wait_data->address = g_strdup(address);
373 g_wait_data->type = current_conn_type;
374 g_wait_data->ag_flag = FALSE;
376 /* Set disconnection type */
377 __bt_set_headset_disconnection_type(connected_address);
384 static void __bt_remove_device_from_wait_list(char *prev_waiting_device)
386 /* Before deleting the request update the UI */
387 bluetooth_device_address_t device_address;
388 int result = BLUETOOTH_ERROR_INTERNAL;
390 invocation_info_t *req_info;
391 BT_INFO("We are about to DBUS return previous waiting device [%s]", prev_waiting_device);
393 _bt_convert_addr_string_to_type(device_address.addr, prev_waiting_device);
395 req_info = _bt_get_request_info_data(BT_AV_CONNECT, prev_waiting_device);
396 if (req_info == NULL) {
397 BT_ERR("req_info == NULL");
400 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
401 g_array_append_vals(out_param, &device_address,
402 sizeof(bluetooth_device_address_t));
403 _bt_service_method_return(req_info->context,
405 g_array_free(out_param, TRUE);
406 _bt_free_info_from_invocation_list(req_info);
410 static int __bt_process_audio_profile_connect(bt_audio_type_t type, bluetooth_device_address_t *address)
412 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
413 int result = BLUETOOTH_ERROR_NONE;
414 BT_DBG("type %s", __convert_audio_type_to_string(type));
416 _bt_convert_addr_type_to_string(addr,
417 (unsigned char *)address->addr);
418 /* Attempt profile level connection based on type */
421 result = _bt_connect_remote_hfp(address);
424 result = _bt_a2dp_connect_remote_sink(address);
426 case BT_AVRCP_TARGET:
427 result = _bt_avrcp_connect_remote_ctrl(address);
430 result = _bt_avrcp_connect_remote_target(address);
432 case BT_AUDIO_A2DP_SOURCE:
433 return _bt_a2dp_connect_remote_source(address);
436 return _bt_connect_remote_ag(address);
438 BT_ERR("Unknown role");
439 return BLUETOOTH_ERROR_INTERNAL;
442 if (result == BLUETOOTH_ERROR_NONE) {
443 _bt_headset_set_local_connection(TRUE);
444 /* Add data to the connected list */
445 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, addr);
446 BT_PERMANENT_LOG("Connect %s", __convert_audio_type_to_string(type));
448 BT_ERR("Profile [%s] connect failed!!", __convert_audio_type_to_string(type));
453 static int __bt_process_audio_profile_disconnect(bt_audio_type_t type, bluetooth_device_address_t *address)
455 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
456 int result = BLUETOOTH_ERROR_NONE;
458 BT_DBG("type %s", __convert_audio_type_to_string(type));
460 _bt_convert_addr_type_to_string(addr,
461 (unsigned char *)address->addr);
462 /* Attempt profile level connection based on type */
465 result = _bt_disconnect_remote_hfp(address);
468 result = _bt_a2dp_disconnect_remote_sink(address);
470 case BT_AVRCP_TARGET:
471 result = _bt_avrcp_disconnect_remote_ctrl(address);
474 result = _bt_avrcp_disconnect_remote_target(address);
476 case BT_AUDIO_A2DP_SOURCE:
477 return _bt_a2dp_disconnect_remote_source(address);
480 BT_ERR("Unknown role");
481 return BLUETOOTH_ERROR_INTERNAL;
484 if (result == BLUETOOTH_ERROR_NONE) {
486 * This logic is added for dual HF mode issue.
488 node = g_list_first(g_connected_list);
489 while (node != NULL) {
490 bt_connected_headset_data_t *connected_device = node->data;
492 if (g_strcmp0(connected_device->device_address, addr) == 0) {
493 BT_DBG("Connection type update. old type[%s] -> new type[%s]",
494 __convert_audio_type_to_string(connected_device->type),
495 __convert_audio_type_to_string(type));
496 type = connected_device->type;
499 node = g_list_next(node);
502 /* Update device status in connected list */
503 _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, addr);
504 BT_PERMANENT_LOG("Disconnect %s", __convert_audio_type_to_string(type));
506 BT_ERR("Profile [%s] disconnect failed!!", __convert_audio_type_to_string(type));
512 int _bt_audio_initialize(bt_service_module_t module)
514 oal_status_t status = OAL_STATUS_SUCCESS;
515 int ret = BLUETOOTH_ERROR_NONE;
517 BT_INFO("_bt_audio_initialize: Module [%d]", module);
520 case BT_A2DP_SOURCE_MODULE: {
521 status = audio_enable(NULL, NULL);
522 if (OAL_STATUS_SUCCESS != status) {
523 BT_ERR("Failed to initialize Bluetooth A2DP Source Profile, status: %d", status);
524 return _bt_convert_oal_status_to_bt_error(status);
526 /* Register Audio module event handler */
527 _bt_service_register_event_handler_callback(module, _bt_a2dp_source_event_handler);
530 case BT_A2DP_SINK_MODULE: {
531 status = a2dp_sink_enable(NULL, NULL);
532 if (status != OAL_STATUS_SUCCESS) {
533 BT_ERR("Failed to initialize Bluetooth A2DP Sink Profile, status: %d", status);
534 return _bt_convert_oal_status_to_bt_error(status);
536 /* Register Audio sink module event handler */
537 _bt_service_register_event_handler_callback(module, _bt_a2dp_sink_event_handler);
540 case BT_HFP_MODULE: {
541 status = hf_client_enable();
542 if (OAL_STATUS_SUCCESS != status) {
543 BT_ERR("Failed to initialize Bluetooth HFP client Profile, status: %d", status);
544 return _bt_convert_oal_status_to_bt_error(status);
546 /* Register Audio module event handler */
547 _bt_service_register_event_handler_callback(module, _bt_hf_client_event_handler);
551 status = hfp_enable(1);
552 if (OAL_STATUS_SUCCESS != status) {
553 BT_ERR("Failed to initialize Bluetooth HFP Audio Gateway Profile, status: %d", status);
554 return _bt_convert_oal_status_to_bt_error(status);
556 /* Register Audio module event handler */
557 _bt_service_register_event_handler_callback(module, _bt_hf_event_handler);
560 case BT_AUDIO_ALL_MODULE: {
561 /* Register Audio module event handler */
562 _bt_service_register_event_handler_callback(module, __bt_audio_event_handler);
565 case BT_AVRCP_CTRL_MODULE: {
566 status = avrcp_ct_enable();
567 if (status != OAL_STATUS_SUCCESS) {
568 BT_ERR("Failed to initialize Bluetooth AVRCP Controller Profile, status: %d", status);
569 return _bt_convert_oal_status_to_bt_error(status);
571 /* Register Avrcp Controller event handler */
572 _bt_service_register_event_handler_callback(module, _bt_avrcp_ctrl_event_handler);
575 case BT_AVRCP_MODULE: {
576 /* Initialize AVRCP Target */
577 ret = _bt_service_avrcp_enable();
581 BT_ERR("Not Supported: Module [%d]", module);
582 return BLUETOOTH_ERROR_NOT_SUPPORT;
585 BT_INFO("Bluetooth audio interface initialised");
589 static void __bt_audio_event_handler(int oal_event, gpointer event_data)
592 case OAL_EVENT_ADAPTER_DISABLED: {
593 BT_INFO("Adapter Disabled..cleanup resources");
594 __bt_audio_cleanup_resources();
597 case OAL_EVENT_ADAPTER_ENABLED: {
598 /*TODO Currently not handled */
599 BT_INFO("Adapter Enabled..");
603 BT_DBG("Unknown event..[%d]", oal_event);
608 static void __bt_audio_cleanup_resources(void)
612 bt_pending_audio_conn_t *info = NULL;
614 /* Remove connected device list */
615 node = g_list_first(g_connected_list);
616 while (node != NULL) {
617 bt_connected_headset_data_t *connected_device = node->data;
618 BT_INFO("Data found [%s] in connected device list...remove it..", connected_device->device_address);
619 g_connected_list = g_list_remove(g_connected_list, connected_device);
620 node = g_list_next(node);
623 /* Remove pending connection list */
624 for (l = pending_audio_conn_list; l != NULL; l = g_slist_next(l)) {
625 info = (bt_pending_audio_conn_t*)l->data;
628 BT_INFO("Info found for addr [%s], remove it...", info->address);
629 pending_audio_conn_list = g_slist_remove(pending_audio_conn_list, info);
630 g_free(info->address);
637 static int __bt_process_audio_connect_all(bt_pending_audio_conn_t *info)
639 bluetooth_device_address_t device_address;
640 int result = BLUETOOTH_ERROR_NONE;
641 int type = BT_AUDIO_ALL;
645 _bt_convert_addr_string_to_type(device_address.addr, info->address);
647 /* Attempt profile level connection */
648 if (info->is_hfp_supported) {
650 result = _bt_connect_remote_hfp(&device_address);
652 if (info->is_a2dp_sink_supported)
653 BT_DBG("A2DP is supported by [%s]", info->address);
655 BT_DBG("A2DP is not supported");
656 } else if (info->is_a2dp_sink_supported) {
657 type = BT_AUDIO_A2DP;
658 result = _bt_a2dp_connect_remote_sink(&device_address);
659 } else if (info->is_a2dp_src_supported) {
660 type = BT_AUDIO_A2DP_SOURCE;
661 result = _bt_a2dp_connect_remote_source(&device_address);
663 if (result == BLUETOOTH_ERROR_NONE) {
664 //_bt_headset_set_local_connection(TRUE);
665 /* Add data to the connected list */
666 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, info->address);
668 BT_ERR("Profile connect failed!!");
673 bt_pending_audio_conn_t* _bt_get_pending_audio_conn_info(char *address)
675 bt_pending_audio_conn_t *info = NULL;
678 for (l = pending_audio_conn_list; l != NULL; l = g_slist_next(l)) {
679 info = (bt_pending_audio_conn_t*)l->data;
681 if (g_strcmp0(info->address, address) == 0 && info->search_status == SERVICE_SEARCH_DONE) {
682 BT_INFO("Pending data found for addr [%s]", info->address + 12);
686 BT_INFO("Pending data not found!!");
690 static void __bt_reply_pending_audio_connect_req(char *address, int result)
693 invocation_info_t *req_info;
696 ret_if(NULL == address);
698 /* Reply to async request for Audio connect, if any */
699 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, address);
700 ret_if(NULL == req_info);
702 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
703 g_array_append_vals(out_param, address, BT_ADDRESS_STRING_SIZE);
704 _bt_service_method_return(req_info->context, out_param, result);
706 g_array_free(out_param, TRUE);
707 _bt_free_info_from_invocation_list(req_info);
709 if (result != BLUETOOTH_ERROR_NONE)
710 _bt_headset_set_local_connection(FALSE);
715 void _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(bt_pending_audio_conn_t *info, int result)
717 ret_if(NULL == info);
719 /* Reply to async request for Audio connect, if any */
720 __bt_reply_pending_audio_connect_req(info->address, result);
722 /* Remove pending audio conn info */
723 pending_audio_conn_list = g_slist_remove(pending_audio_conn_list, info);
724 g_free(info->address);
728 gboolean _bt_audio_check_pending_connection(char *address)
730 bt_pending_audio_conn_t *data = NULL;
731 bluetooth_device_address_t device_address;
733 data = _bt_get_pending_audio_conn_info(address);
736 BT_INFO("A2DP Connection is pending..initiate it...");
737 if (data->is_a2dp_sink_supported && data->conn_req_type == BT_AUDIO_ALL) {
738 _bt_convert_addr_string_to_type(device_address.addr, address);
739 if (_bt_audio_connect(BT_AUDIO_A2DP, &device_address) != BLUETOOTH_ERROR_NONE) {
740 BT_INFO("A2DP connect triggered for [%s] but it failed!!", data->address);
741 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
743 BT_INFO("A2DP connect triggered successfully for [%s]", data->address);
745 } else if (data->is_a2dp_src_supported && data->conn_req_type == BT_AUDIO_HFP_SOURCE) {
746 _bt_convert_addr_string_to_type(device_address.addr, address);
747 if (_bt_audio_connect(BT_AUDIO_A2DP_SOURCE, &device_address) != BLUETOOTH_ERROR_NONE) {
748 BT_INFO("A2DP sink connect triggered for [%s] but it failed!!", data->address);
749 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
751 BT_INFO("A2DP sink connect triggered successfully for [%s]", data->address);
756 BT_INFO("A2DP Connection is not pending..");
761 void _bt_audio_check_pending_disconnection(char *address, int type)
763 int ret = BLUETOOTH_ERROR_NONE;
764 bluetooth_device_address_t device_address;
766 if (_bt_is_service_connected(address, type)) {
767 BT_INFO("Service [%s] is connected with device [%s], disconnect it...",
768 __convert_audio_type_to_string(type), address + 12);
769 _bt_convert_addr_string_to_type(device_address.addr, address);
770 ret = __bt_process_audio_profile_disconnect(type, &device_address);
772 if (ret != BLUETOOTH_ERROR_NONE)
773 BT_ERR("Disconnecting service [%s] with device [%s] failed!!",
774 __convert_audio_type_to_string(type), address + 12);
776 BT_INFO("Service [%s] is Not connected with device [%s],..",
777 __convert_audio_type_to_string(type), address + 12);
781 int __bt_handle_audio_all_connect(bt_pending_audio_conn_t *info)
783 bt_remote_dev_info_t *rem_info;
787 retv_if(NULL == info, BLUETOOTH_ERROR_INTERNAL);
788 retv_if(NULL == info->address, BLUETOOTH_ERROR_INTERNAL);
790 rem_info = _bt_service_get_remote_dev_info(info->address);
792 BT_ERR("_bt_service_get_remote_dev_info returned NULL");
793 ret = BLUETOOTH_ERROR_NOT_PAIRED;
797 for (indx = 0; indx < rem_info->uuid_count; indx++) {
798 BT_INFO("UUID [%s]", rem_info->uuids[indx]);
799 if (0 == g_strcmp0(A2DP_SINK_UUID, rem_info->uuids[indx])) {
800 BT_INFO("Device supports A2DP Sink Profile");
801 info->is_a2dp_sink_supported = TRUE;
802 } else if (0 == g_strcmp0(A2DP_SOURCE_UUID, rem_info->uuids[indx])) {
803 BT_INFO("Device supports A2DP Source Profile");
804 info->is_a2dp_src_supported = TRUE;
805 } else if ((g_strcmp0(HFP_HS_UUID, rem_info->uuids[indx]) == 0)) {
806 BT_INFO("Device supports HFP Profile");
807 info->is_hfp_supported = TRUE;
811 if (info->is_a2dp_sink_supported == FALSE &&
812 info->is_hfp_supported == FALSE &&
813 info->is_a2dp_src_supported == FALSE) {
814 BT_ERR("No audio profile is supported");
815 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
819 BT_INFO("AUDIO_CONNECT_ALL request for [%s]", info->address + 12);
820 info->search_status = SERVICE_SEARCH_DONE;
822 /* Give preference to HFP over A2DP for outgoing connection sequence for AUDIO_ALL_CONNECT */
823 if (info->is_hfp_supported)
824 info->type = BT_AUDIO_HSP;
825 else if (info->is_a2dp_sink_supported)
826 info->type = BT_AUDIO_A2DP;
827 else if (info->is_a2dp_src_supported)
828 info->type = BT_AUDIO_A2DP_SOURCE;
830 ret = __bt_is_headset_connected(info->type, info->address);
831 if (ret == BLUETOOTH_ERROR_ALREADY_CONNECT) {
832 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
833 info->address + 12, "Already connected...");
837 if (ret == BLUETOOTH_ERROR_IN_PROGRESS) {
838 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
839 info->address + 12, "Already in progress...");
843 if (ret == BLUETOOTH_ERROR_NOT_CONNECTED) {
844 BT_ERR("Great, can start Audio All connect for [%s]", info->address + 12);
845 ret = __bt_is_headset_connecting(info->type);
846 if (ret != BLUETOOTH_ERROR_NONE) {
847 BT_ERR("Can't start Audio All connect for [%s], reason: [%s]",
848 info->address + 12, "some other device conn in progress");
849 ret = BLUETOOTH_ERROR_IN_PROGRESS;
853 ret = __bt_process_audio_connect_all(info);
854 if (ret != BLUETOOTH_ERROR_NONE) {
855 BT_ERR("__bt_process_audio_connect_all failed");
859 BT_PERMANENT_LOG("Connect %s", __convert_audio_type_to_string(info->type));
860 /* If multiple profiles are supported, queue pending connection info */
861 if ((info->is_hfp_supported && info->is_a2dp_sink_supported) ||
862 (info->is_hfp_supported && info->is_a2dp_src_supported)) {
863 BT_INFO("[%s] Supports HFP and (A2DP_Src or, A2DP_Snk)", info->address + 12);
864 pending_audio_conn_list = g_slist_append(pending_audio_conn_list, (gpointer)info);
866 BT_INFO("[%s] Supports one profile only", info->address + 12);
868 * It means, we dont need pending connect info as only A2DP (Src/Snk) or
869 * HFP will be connected for present device, so lets free pending info.
871 g_free(info->address);
874 } else if (ret == BLUETOOTH_ERROR_NONE) {
875 BT_INFO("Waiting for disconnection...");
877 if ((info->is_hfp_supported && info->is_a2dp_sink_supported) ||
878 (info->is_hfp_supported && info->is_a2dp_src_supported)) {
879 BT_INFO("[%s] Supports HFP and (A2DP_Src or, A2DP_Snk)", info->address + 12);
880 pending_audio_conn_list = g_slist_append(pending_audio_conn_list, (gpointer)info);
882 BT_INFO("[%s] Supports one profile only", info->address + 12);
884 * It means, we dont need pending connect info as only A2DP (Src/Snk) or
885 * HFP will be connected for present device, so lets free pending info.
887 g_free(info->address);
892 return BLUETOOTH_ERROR_NONE;
895 BT_ERR("Audio connect all failed");
896 g_free(info->address);
901 static gboolean __audio_get_bonded_info(gpointer data)
903 bt_pending_audio_conn_t *info = data;
904 char address[BT_ADDRESS_STRING_SIZE];
906 retv_if(NULL == info, FALSE);
907 retv_if(NULL == info->address, FALSE);
909 if ((info->bonded_info_retries > 0) && !_bt_is_bonded_devices_retrived()) {
910 info->bonded_info_retries--;
914 g_strlcpy(address, info->address, BT_ADDRESS_STRING_SIZE);
915 if (info->bonded_info_retries <= 0) {
916 BT_ERR_C("Even after all retries, bonded devices stil not retrieved");
917 g_free(info->address);
922 if (BLUETOOTH_ERROR_NONE != __bt_handle_audio_all_connect(info)) {
923 BT_ERR("__bt_handle_audio_all_connect failed");
929 __bt_reply_pending_audio_connect_req(address, BLUETOOTH_ERROR_INTERNAL);
933 int _bt_audio_connect(int type, bluetooth_device_address_t *device_address)
935 int ret = BLUETOOTH_ERROR_NONE;
936 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
937 bt_pending_audio_conn_t *info = NULL;
939 BT_CHECK_PARAMETER(device_address, return);
941 _bt_convert_addr_type_to_string(address, device_address->addr);
942 BT_INFO("Audio Connect Request: type[%s] address [%s]",
943 __convert_audio_type_to_string(type), address + 12);
946 * If type is BT_AUDIO_ALL or BT_AUDIO_HFP_SOURCE, enqueue search info in
947 * order to find out supported services by the remote device.
949 if (type == BT_AUDIO_ALL || type == BT_AUDIO_HFP_SOURCE) {
950 if (NULL != _bt_get_pending_audio_conn_info(address)) {
951 BT_ERR("Connection for same device already in progress");
952 return BLUETOOTH_ERROR_IN_PROGRESS;
955 info = g_malloc0(sizeof(bt_pending_audio_conn_t));
956 info->search_status = SERVICE_SEARCH_STARTED;
957 info->address = g_strdup(address);
959 info->conn_req_type = type;
961 /* Request bonded device info */
962 if (!_bt_is_bonded_devices_retrived()) {
963 info->bonded_info_retries = 5;
964 /* Wait till bonded devices retrival is completed */
965 g_timeout_add_seconds(1, __audio_get_bonded_info, info);
966 return BLUETOOTH_ERROR_NONE;
969 return __bt_handle_audio_all_connect(info);
972 /* If type is A2DP Sink or HSP/HFP, check further */
973 ret = __bt_is_headset_connected(type, address);
974 if (ret == BLUETOOTH_ERROR_ALREADY_CONNECT) {
975 BT_ERR("Failed with BLUETOOTH_ERROR_ALREADY_CONNECT");
976 return BLUETOOTH_ERROR_ALREADY_CONNECT;
979 if (ret == BLUETOOTH_ERROR_IN_PROGRESS) {
980 BT_ERR("Failed with BLUETOOTH_ERROR_IN_PROGRESS");
981 return BLUETOOTH_ERROR_IN_PROGRESS;
984 if (ret == BLUETOOTH_ERROR_NONE) {
985 BT_INFO("Waiting for disconnection...");
986 } else if (ret == BLUETOOTH_ERROR_NOT_CONNECTED) {
987 ret = __bt_process_audio_profile_connect(type, device_address);
988 if (ret != BLUETOOTH_ERROR_NONE) {
989 BT_ERR("Failed with %d", ret);
994 return BLUETOOTH_ERROR_NONE;
997 int _bt_audio_disconnect(int type, bluetooth_device_address_t *device_address)
999 int ret = BLUETOOTH_ERROR_NONE;
1000 int value = BLUETOOTH_ERROR_NONE;
1001 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1003 _bt_convert_addr_type_to_string(address, device_address->addr);
1004 BT_INFO("Audio Diconnect Request: type[%s] address [%s]",
1005 __convert_audio_type_to_string(type), address + 12);
1007 if (type == BT_AUDIO_ALL) {
1008 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
1009 type = BT_AUDIO_A2DP;
1010 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
1011 type = BT_AUDIO_HSP;
1013 BT_ERR("No audio service connected");
1014 return BLUETOOTH_ERROR_NOT_CONNECTED;
1016 } else if (type == BT_AUDIO_HFP_SOURCE) {
1017 if (_bt_is_service_connected(address, BT_AUDIO_A2DP_SOURCE)) {
1018 type = BT_AUDIO_A2DP_SOURCE;
1019 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
1020 type = BT_AUDIO_HSP;
1022 BT_ERR("No audio service connected");
1023 return BLUETOOTH_ERROR_NOT_CONNECTED;
1027 value = __bt_is_headset_disconnecting(type);
1028 if (value != BLUETOOTH_ERROR_NONE) {
1029 BT_INFO("Disconnect in progress");
1030 return BLUETOOTH_ERROR_IN_PROGRESS;
1033 ret = __bt_process_audio_profile_disconnect(type, device_address);
1037 gboolean _bt_is_service_connected(char* address, int type)
1040 node = g_list_first(g_connected_list);
1041 while (node != NULL) {
1042 bt_connected_headset_data_t *conn_device = node->data;
1044 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
1045 (conn_device->type & type)) {
1046 BT_INFO("Service connected");
1050 node = g_list_next(node);
1052 BT_INFO("Service not connected");
1056 void _bt_remove_headset_from_list(int type, const char *address)
1060 BT_DBG("type %s", __convert_audio_type_to_string(type));
1062 node = g_list_first(g_connected_list);
1063 while (node != NULL) {
1064 bt_connected_headset_data_t *connected_device = node->data;
1066 if (g_strcmp0(connected_device->device_address, address) != 0) {
1067 node = g_list_next(node);
1071 BT_DBG("Address match. Connection type = %s",
1072 __convert_audio_type_to_string(connected_device->type));
1076 if (connected_device->type & BT_AUDIO_A2DP)
1077 connected_device->type &= ~(BT_AUDIO_A2DP);
1080 if (connected_device->type & BT_AUDIO_HSP)
1081 connected_device->type &= ~(BT_AUDIO_HSP);
1084 if (connected_device->type & BT_AUDIO_ALL)
1085 connected_device->type &= ~(BT_AUDIO_ALL);
1087 case BT_AVRCP_TARGET:
1088 if (connected_device->type & BT_AVRCP_TARGET)
1089 connected_device->type &= ~(BT_AVRCP_TARGET);
1092 if (connected_device->type & BT_AVRCP)
1093 connected_device->type &= ~(BT_AVRCP);
1095 case BT_AUDIO_A2DP_SOURCE:
1096 if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
1097 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
1100 if (connected_device->type & BT_AUDIO_AG)
1101 connected_device->type &= ~(BT_AUDIO_AG);
1107 if (connected_device->type == 0x00) {
1108 BT_INFO("Device will be completely removed from connected list as the only profile connected or connecting got disconnected");
1109 g_connected_list = g_list_remove(g_connected_list, connected_device);
1110 g_free(connected_device);
1112 connected_device->device_state = BT_STATE_CONNECTED;
1115 node = g_list_next(node);
1119 * If Audio role selection request is pending (pending_audio_role > 0) then process pending
1120 * audio role select request on BT_AUDIO_A2DP/BT_AUDIO_A2DP_SOURCE device dicaonnection.
1122 if (pending_audio_role >= 0 &&
1123 (type == BT_AUDIO_A2DP || type == BT_AUDIO_A2DP_SOURCE))
1124 g_idle_add(__handle_pending_audio_select_role, NULL);
1127 static void __handle_pending_requests(int result, int service_function, void *user_data, unsigned int size)
1131 invocation_info_t *req_info;
1135 /* Get method invocation context */
1136 for (l = _bt_get_invocation_list(); l != NULL; ) {
1138 l = g_slist_next(l);
1140 if (req_info == NULL || req_info->service_function != service_function)
1143 /* Create out param */
1144 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
1146 switch (service_function) {
1147 case BT_AUDIO_SELECT_ROLE:
1148 _bt_service_method_return(req_info->context, out_param, result);
1149 g_array_free(out_param, TRUE);
1150 _bt_free_info_from_invocation_list(req_info);
1153 BT_ERR("Unknown service function[%d]", service_function);
1161 static gboolean __handle_pending_audio_select_role(gpointer data)
1164 oal_status_t status;
1167 if (BLUETOOTH_A2DP_SOURCE == pending_audio_role) {
1168 /* Disable A2DP Sink role */
1169 status = a2dp_sink_disable();
1170 if (status != OAL_STATUS_SUCCESS) {
1171 BT_ERR("Failed to Disable Bluetooth A2DP Sink Profile, status: %d", status);
1172 ret = _bt_convert_oal_status_to_bt_error(status);
1176 /* Disable AVRCP CT role */
1177 status = avrcp_ct_disable();
1178 if (status != OAL_STATUS_SUCCESS) {
1179 BT_ERR("Failed to Disable Bluetooth AVRCP Controller Profile, status: %d", status);
1180 ret = _bt_convert_oal_status_to_bt_error(status);
1184 /* Enable A2DP Source role */
1185 ret = _bt_audio_initialize(BT_A2DP_SOURCE_MODULE);
1186 if (ret != BLUETOOTH_ERROR_NONE) {
1187 BT_ERR("Failed to enable Bluetooth A2DP Source Profile");
1191 /* Enable AVRCP TG role */
1192 ret = _bt_audio_initialize(BT_AVRCP_MODULE);
1193 if (ret != BLUETOOTH_ERROR_NONE) {
1194 BT_ERR("Failed to enable Bluetooth AVRCP Target Profile");
1198 /* Disable A2DP Source role */
1199 status = audio_disable();
1200 if (OAL_STATUS_SUCCESS != status) {
1201 BT_ERR("Failed to disable Bluetooth A2DP Source Profile, status: %d", status);
1202 ret = _bt_convert_oal_status_to_bt_error(status);
1206 /* Disable AVRCP TG role */
1207 ret = _bt_service_avrcp_disable();
1208 if (ret != BLUETOOTH_ERROR_NONE) {
1209 BT_ERR("Failed to Disable Bluetooth AVRCP Target Profile");
1213 /* Enable A2DP Sink role */
1214 ret = _bt_audio_initialize(BT_A2DP_SINK_MODULE);
1215 if (ret != BLUETOOTH_ERROR_NONE) {
1216 BT_ERR("Failed to enable Bluetooth A2DP Sink Profile");
1220 /* Enable AVRCP CT role */
1221 ret = _bt_audio_initialize(BT_AVRCP_CTRL_MODULE);
1222 if (ret != BLUETOOTH_ERROR_NONE) {
1223 BT_ERR("Failed to enable Bluetooth AVRCP Controller Profile");
1229 if (ret == BLUETOOTH_ERROR_NONE)
1230 _bt_audio_set_current_role(pending_audio_role);
1232 __handle_pending_requests(ret, BT_AUDIO_SELECT_ROLE, NULL, 0);
1233 pending_audio_role = -1;
1238 int _bt_audio_select_role(bluetooth_audio_role_t role)
1240 int result = BLUETOOTH_ERROR_NONE;
1241 char address[BT_ADDRESS_STRING_SIZE];
1242 bluetooth_device_address_t dev_addr;
1244 retv_if(BLUETOOTH_A2DP_SINK < role, BLUETOOTH_ERROR_INVALID_PARAM);
1245 retv_if(pending_audio_role >= 0, BLUETOOTH_ERROR_IN_PROGRESS);
1249 if (curr_audio_role == role) {
1250 BT_ERR("Desired audio role already enabled, return");
1251 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1254 pending_audio_role = role;
1256 if (BLUETOOTH_A2DP_SINK == role) {
1257 if (_bt_is_headset_type_connected(BT_AUDIO_A2DP, address)) {
1258 _bt_convert_addr_string_to_type(dev_addr.addr, address);
1259 result = _bt_audio_disconnect(BT_AUDIO_A2DP, &dev_addr);
1260 if (result != BLUETOOTH_ERROR_NONE) {
1261 BT_ERR("_bt_audio_disconnect(BT_AUDIO_A2DP, %s) Failed", address);
1262 result = _bt_convert_oal_status_to_bt_error(result);
1265 BT_INFO("No BT_AUDIO_A2DP device is connected, proceed with role switch");
1266 g_idle_add(__handle_pending_audio_select_role, NULL);
1267 result = BLUETOOTH_ERROR_NONE;
1270 if (_bt_is_headset_type_connected(BT_AUDIO_A2DP_SOURCE, address)) {
1271 _bt_convert_addr_string_to_type(dev_addr.addr, address);
1272 result = _bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, &dev_addr);
1273 if (result != BLUETOOTH_ERROR_NONE) {
1274 BT_ERR("_bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, %s) Failed", address);
1275 result = _bt_convert_oal_status_to_bt_error(result);
1278 BT_INFO("No BT_AUDIO_A2DP_SOURCE device is connected, proceed with role switch");
1279 g_idle_add(__handle_pending_audio_select_role, NULL);
1280 result = BLUETOOTH_ERROR_NONE;
1288 void _bt_audio_set_current_role(bluetooth_audio_role_t role)
1290 BT_INFO("role: %s", (role == BLUETOOTH_A2DP_SINK) ? "AUDIO_SINK" : "AUDIO_SOURCE");
1291 curr_audio_role = role;
1294 int _bt_hf_connect(bluetooth_device_address_t *device_address)
1296 int result = BLUETOOTH_ERROR_NONE;
1299 result = _bt_connect_remote_ag(device_address);
1300 if (result != BLUETOOTH_ERROR_NONE)
1301 BT_ERR("HF Client connect to remote AG failed");
1303 BT_PERMANENT_LOG("Connect AG");
1308 int _bt_hf_disconnect(bluetooth_device_address_t *device_address)
1310 int result = BLUETOOTH_ERROR_NONE;
1313 result = _bt_disconnect_remote_ag(device_address);
1314 if (result != BLUETOOTH_ERROR_NONE)
1315 BT_ERR("HF Client disconnect to remote AG failed");
1317 BT_PERMANENT_LOG("Disconnect AG");
1322 void _bt_audio_handle_incoming_authorization(char *address, int service_id)
1324 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
1325 gboolean connected = FALSE;
1326 bluetooth_device_address_t device_address;
1327 oal_status_t res = OAL_STATUS_SUCCESS;
1329 _bt_convert_addr_string_to_type(device_address.addr, address);
1331 switch (service_id) {
1332 case HSP_SERVICE_ID:
1333 case HFP_SERVICE_ID:
1334 connected = _bt_is_headset_type_connected(BT_AUDIO_HSP, connected_address);
1335 BT_DBG("Connected [0x%x]", connected);
1337 case HSP_HS_SERVICE_ID:
1338 case HFP_HS_SERVICE_ID:
1339 connected = _bt_is_headset_type_connected(BT_AUDIO_AG, connected_address);
1340 BT_DBG("Connected [0x%x]", connected);
1343 BT_ERR("Invalid HFP device ID.. [%d]", service_id);
1348 BT_INFO("[%d] device is already connected..check which device..", service_id);
1349 if (g_strcmp0(connected_address, address) != 0) {
1350 BT_INFO("Different device is connected[%s] reject current [%s] device authorization request",
1351 connected_address, address);
1352 res = device_reply_auth_request((bt_address_t*)&device_address, service_id, FALSE, FALSE);
1353 if (res != OAL_STATUS_SUCCESS)
1354 BT_ERR("authorize_response: %d", res);
1359 res = device_reply_auth_request((bt_address_t*)&device_address, service_id, TRUE, FALSE);
1360 if (res != OAL_STATUS_SUCCESS)
1361 BT_ERR("authorize_response: %d", res);