return result;
}
+BT_EXPORT_API int bluetooth_audio_select_role(bluetooth_audio_role_t role)
+{
+ int result;
+
+ BT_CHECK_ENABLED(return);
+
+ BT_INIT_PARAMS();
+ BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+ g_array_append_vals(in_param1, &role, sizeof(bluetooth_audio_role_t));
+
+ result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AUDIO_SELECT_ROLE,
+ in_param1, in_param2, in_param3, in_param4, &out_param);
+
+ BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+ return result;
+}
+
BT_EXPORT_API int bluetooth_ag_get_headset_volume(unsigned int *speaker_gain)
{
int result;
static guint timer_id = 0;
+static gboolean a2dp_init_pending = FALSE;
+
/* Adapter default states */
static bt_status_t adapter_state = BT_DEACTIVATED;
return result;
}
+static void __bt_handle_pending_a2dp_init(service_uuid_t *service_list, unsigned int count)
+{
+ int ret;
+ unsigned int i;
+ unsigned char *uuid;
+ char uuid_str[BT_UUID_STRING_SIZE];
+
+ if (!a2dp_init_pending)
+ return;
+
+ BT_DBG("+");
+ a2dp_init_pending = FALSE;
+ for (i = 0; i < count; i++) {
+ uuid = service_list[i].uuid;
+ _bt_service_convert_uuid_type_to_string(uuid_str, uuid);
+ BT_INFO("Adapter Service: [%s]", uuid_str);
+ if (!strcasecmp(uuid_str, A2DP_SINK_UUID)) {
+ BT_INFO("Enable A2DP Sink role");
+ /* Initialize A2DP Sink */
+ ret = _bt_audio_initialize(BT_A2DP_SINK_MODULE);
+ if (ret != BLUETOOTH_ERROR_NONE)
+ BT_ERR("_bt_audio_initialize(BT_A2DP_SINK_MODULE) Failed");
+
+ /* Initialize AVRCP Controller */
+ ret = _bt_audio_initialize(BT_AVRCP_CTRL_MODULE);
+ if (ret != BLUETOOTH_ERROR_NONE)
+ BT_ERR("_bt_audio_initialize(BT_AVRCP_CTRL_MODULE) Failed");
+
+ _bt_audio_set_current_role(BLUETOOTH_A2DP_SINK);
+ return;
+ }
+ }
+
+ BT_INFO("Enable A2DP Source role by default");
+ /* Initialize A2DP Source */
+ ret = _bt_audio_initialize(BT_A2DP_SOURCE_MODULE);
+ if (ret != BLUETOOTH_ERROR_NONE)
+ BT_ERR("_bt_audio_initialize(BT_A2DP_SOURCE_MODULE) Failed");
+
+ /* Initialize AVRCP Target */
+ ret = _bt_audio_initialize(BT_AVRCP_MODULE);
+ if (ret != BLUETOOTH_ERROR_NONE)
+ BT_ERR("_bt_audio_initialize(BT_AVRCP_MODULE) Failed");
+
+ _bt_audio_set_current_role(BLUETOOTH_A2DP_SOURCE);
+ BT_DBG("-");
+}
+
static void __bt_adapter_event_handler(int event_type, gpointer event_data)
{
int result = BLUETOOTH_ERROR_NONE;
count = list->num;
service_list = list->service_list;
+ __bt_handle_pending_a2dp_init(service_list, count);
__bt_adapter_handle_pending_requests(BT_IS_SERVICE_USED, service_list, count);
break;
}
BT_ERR("_bt_hidhost_initialize Failed");
return ret;
}
+
ret = _bt_socket_init();
if (ret != BLUETOOTH_ERROR_NONE) {
BT_ERR("_bt_socket_init Failed");
return ret;
}
- /* Initialize A2DP Source */
- ret = _bt_audio_initialize(BT_A2DP_SOURCE_MODULE);
- if (ret != BLUETOOTH_ERROR_NONE) {
- BT_ERR("_bt_audio_initialize(BT_A2DP_SOURCE_MODULE) Failed");
- return ret;
- }
- /* Initialize AVRCP Target */
- ret = _bt_audio_initialize(BT_AVRCP_MODULE);
- if (ret != BLUETOOTH_ERROR_NONE) {
- BT_ERR("_bt_audio_initialize(BT_AVRCP_MODULE) Failed");
- return ret;
+ /*
+ * Query local adapter services and based on a2dp service uuids initialized
+ * in bluetooth stack, enable A2DP sourec or A2DP sink role.
+ */
+ ret = adapter_get_service_uuids();
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("adapter_get_service_uuids failed: %d", ret);
+ return BLUETOOTH_ERROR_INTERNAL;
+ } else {
+ a2dp_init_pending = TRUE;
}
- /* Initialize A2DP Sink */
- ret = _bt_audio_initialize(BT_A2DP_SINK_MODULE);
- if (ret != BLUETOOTH_ERROR_NONE) {
- BT_ERR("_bt_audio_initialize(BT_A2DP_SINK_MODULE) Failed");
- return ret;
- }
/* Initialize HFP Audio Gateway */
ret = _bt_audio_initialize(BT_AG_MODULE);
if (ret != BLUETOOTH_ERROR_NONE) {
BT_ERR("_bt_audio_initialize(BT_AG_MODULE) Failed");
return ret;
}
- /* Initialize AVRCP Controller */
- ret = _bt_audio_initialize(BT_AVRCP_CTRL_MODULE);
- if (ret != BLUETOOTH_ERROR_NONE) {
- BT_ERR("_bt_audio_initialize(BT_AVRCP_CTRL_MODULE) Failed");
- return ret;
- }
/* Registering callback for receiving audio services searched */
ret = _bt_audio_initialize(BT_AUDIO_ALL_MODULE);
if (ret != BLUETOOTH_ERROR_NONE) {
int ret;
int status = VCONFKEY_BT_STATUS_OFF;
- BT_DBG("OAL initialized, Init profiles..");
- ret = _bt_init_profiles();
- if (ret != BLUETOOTH_ERROR_NONE)
- BT_ERR("Bluetooth profile init error: %d", ret);
-
+ BT_DBG("OAL initialized");
if (vconf_get_int(VCONFKEY_BT_STATUS, &status) != 0) {
BT_ERR("Fail to get the enabled value");
}
static void __bt_adapter_update_bt_enabled(void)
{
int result = BLUETOOTH_ERROR_NONE;
- BT_INFO("_bt_adapter_update_bt_enabled>>");
+ BT_INFO("_bt_adapter_update_bt_enabled >> Init profiles...");
+ if (BLUETOOTH_ERROR_NONE != _bt_init_profiles())
+ BT_ERR("Bluetooth profile init failed");
+
/* Update Bluetooth Status to notify other modules */
if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0)
BT_ERR("Set vconf failed\n");
static void __bt_adapter_update_bt_disabled(void)
{
int result = BLUETOOTH_ERROR_NONE;
- BT_INFO("_bt_adapter_update_bt_disabled>>");
+ BT_INFO("_bt_adapter_update_bt_disabled >> Cleanup profiles...");
+ _bt_cleanup_profiles();
int power_off_status = 0;
int ret;
/* Headset connection data structures */
gboolean connection_local = FALSE;
+static int curr_audio_role = BLUETOOTH_A2DP_SOURCE;
+static int pending_audio_role = -1;
+
static void __bt_remove_device_from_wait_list(char *prev_waiting_device);
static void __bt_audio_device_property_event_handler(event_dev_properties_t *event);
static void __bt_audio_cleanup_resources(void);
+static gboolean __handle_pending_audio_select_role(gpointer data);
+
#if 0
void _bt_headset_set_local_connection(gboolean value)
{
if (connected_device->type & type) {
if (address != NULL)
g_strlcpy(address, connected_device->device_address,
- BT_ADDRESS_STRING_SIZE + 1);
+ BT_ADDRESS_STRING_SIZE);
return TRUE;
}
node = g_list_next(node);
}
+
+ /*
+ * If Audio role selection request is pending (pending_audio_role > 0) then process pending
+ * audio role select request on BT_AUDIO_A2DP/BT_AUDIO_A2DP_SOURCE device dicaonnection.
+ */
+ if (pending_audio_role >= 0 &&
+ (type == BT_AUDIO_A2DP || type == BT_AUDIO_A2DP_SOURCE))
+ g_idle_add(__handle_pending_audio_select_role, NULL);
+}
+
+static void __handle_pending_requests(int result, int service_function, void *user_data, unsigned int size)
+{
+ GSList *l;
+ GArray *out_param;
+ invocation_info_t *req_info;
+
+ BT_DBG("+");
+
+ /* Get method invocation context */
+ for (l = _bt_get_invocation_list(); l != NULL; l = g_slist_next(l)) {
+ req_info = l->data;
+
+ if (req_info == NULL || req_info->service_function != service_function)
+ continue;
+
+ /* Create out param */
+ out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+
+ switch (service_function) {
+ case BT_AUDIO_SELECT_ROLE:
+ _bt_service_method_return(req_info->context, out_param, result);
+ g_array_free(out_param, TRUE);
+ _bt_free_info_from_invocation_list(req_info);
+ return;
+ default:
+ BT_ERR("Unknown service function[%d]", service_function);
+ return;
+ }
+ }
+
+ BT_DBG("-");
+}
+
+static gboolean __handle_pending_audio_select_role(gpointer data)
+{
+ int ret;
+ oal_status_t status;
+
+ BT_DBG("+");
+ if (BLUETOOTH_A2DP_SOURCE == pending_audio_role) {
+ /* Disable A2DP Sink role */
+ status = a2dp_sink_disable();
+ if (status != OAL_STATUS_SUCCESS) {
+ BT_ERR("Failed to Disable Bluetooth A2DP Sink Profile, status: %d", status);
+ ret = BLUETOOTH_ERROR_INTERNAL;
+ goto done;
+ }
+
+ /* Disable AVRCP CT role */
+ status = avrcp_ct_disable();
+ if (status != OAL_STATUS_SUCCESS) {
+ BT_ERR( "Failed to Disable Bluetooth AVRCP Controller Profile, status: %d", status);
+ ret = BLUETOOTH_ERROR_INTERNAL;
+ goto done;
+ }
+
+ /* Enable A2DP Source role */
+ ret = _bt_audio_initialize(BT_A2DP_SOURCE_MODULE);
+ if (ret != BLUETOOTH_ERROR_NONE) {
+ BT_ERR( "Failed to enable Bluetooth A2DP Source Profile");
+ goto done;
+ }
+
+ /* Enable AVRCP TG role */
+ ret = _bt_audio_initialize(BT_AVRCP_MODULE);
+ if (ret != BLUETOOTH_ERROR_NONE) {
+ BT_ERR( "Failed to enable Bluetooth AVRCP Target Profile");
+ goto done;
+ }
+ } else {
+ /* Disable A2DP Source role */
+ status = audio_disable();
+ if (OAL_STATUS_SUCCESS != status) {
+ BT_ERR("Failed to disable Bluetooth A2DP Source Profile, status: %d", status);
+ ret = BLUETOOTH_ERROR_INTERNAL;
+ goto done;
+ }
+
+ /* Disable AVRCP TG role */
+ ret = _bt_service_avrcp_disable();
+ if (ret != BLUETOOTH_ERROR_NONE) {
+ BT_ERR( "Failed to Disable Bluetooth AVRCP Target Profile");
+ goto done;
+ }
+
+ /* Enable A2DP Sink role */
+ ret = _bt_audio_initialize(BT_A2DP_SINK_MODULE);
+ if (ret != BLUETOOTH_ERROR_NONE) {
+ BT_ERR( "Failed to enable Bluetooth A2DP Sink Profile");
+ goto done;
+ }
+
+ /* Enable AVRCP CT role */
+ ret = _bt_audio_initialize(BT_AVRCP_CTRL_MODULE);
+ if (ret != BLUETOOTH_ERROR_NONE) {
+ BT_ERR( "Failed to enable Bluetooth AVRCP Controller Profile");
+ goto done;
+ }
+ }
+
+done:
+ if (ret == BLUETOOTH_ERROR_NONE)
+ _bt_audio_set_current_role(pending_audio_role);
+
+ __handle_pending_requests(ret, BT_AUDIO_SELECT_ROLE, NULL, 0);
+ pending_audio_role = -1;
+ BT_DBG("-");
+ return FALSE;
+}
+
+int _bt_audio_select_role(bluetooth_audio_role_t role)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ char address[BT_ADDRESS_STRING_SIZE];
+ bluetooth_device_address_t dev_addr;
+
+ retv_if(BLUETOOTH_A2DP_SINK < role, BLUETOOTH_ERROR_INVALID_PARAM);
+ retv_if(pending_audio_role >= 0, BLUETOOTH_ERROR_IN_PROGRESS);
+
+ BT_DBG("+");
+
+ if (curr_audio_role == role) {
+ BT_ERR("Desired audio role already enabled, return");
+ return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
+ }
+
+ pending_audio_role = role;
+
+ if (BLUETOOTH_A2DP_SINK == role) {
+ if (_bt_is_headset_type_connected(BT_AUDIO_A2DP, address)) {
+ _bt_convert_addr_string_to_type(dev_addr.addr, address);
+ result = _bt_audio_disconnect(BT_AUDIO_A2DP, &dev_addr);
+ if (result != BLUETOOTH_ERROR_NONE) {
+ BT_ERR( "_bt_audio_disconnect(BT_AUDIO_A2DP, %s) Failed", address);
+ result = BLUETOOTH_ERROR_INTERNAL;
+ }
+ } else {
+ BT_INFO("No BT_AUDIO_A2DP device is connected, proceed with role switch");
+ g_idle_add(__handle_pending_audio_select_role, NULL);
+ result = BLUETOOTH_ERROR_NONE;
+ }
+ } else {
+ if (_bt_is_headset_type_connected(BT_AUDIO_A2DP_SOURCE, address)) {
+ _bt_convert_addr_string_to_type(dev_addr.addr, address);
+ result = _bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, &dev_addr);
+ if (result != BLUETOOTH_ERROR_NONE) {
+ BT_ERR( "_bt_audio_disconnect(BT_AUDIO_A2DP_SOURCE, %s) Failed", address);
+ result = BLUETOOTH_ERROR_INTERNAL;
+ }
+ } else {
+ BT_INFO("No BT_AUDIO_A2DP_SOURCE device is connected, proceed with role switch");
+ g_idle_add(__handle_pending_audio_select_role, NULL);
+ result = BLUETOOTH_ERROR_NONE;
+ }
+ }
+
+ BT_DBG("-");
+ return result;
+}
+
+void _bt_audio_set_current_role(bluetooth_audio_role_t role)
+{
+ BT_INFO("role: %s", (role == BLUETOOTH_A2DP_SINK) ? "AUDIO_SINK" : "AUDIO_SOURCE");
+ curr_audio_role = role;
}
#include <cynara-creds-gdbus.h>
#include "bluetooth-api.h"
+#include "bluetooth-audio-api.h"
#include "bluetooth-gatt-server-api.h"
#include "bt-request-handler.h"
#include "bt-service-common.h"
|| service_function == BT_GATT_SERVER_DELETE_SERVICE
|| service_function == BT_START_LE_DISCOVERY
|| service_function == BT_STOP_LE_DISCOVERY
+ || service_function == BT_AUDIO_SELECT_ROLE
|| service_function == BT_OBEX_SERVER_ACCEPT_CONNECTION)
return TRUE;
else
result = BLUETOOTH_ERROR_NONE;
break;
}
+ case BT_AUDIO_SELECT_ROLE: {
+ bluetooth_audio_role_t role;
+
+ __bt_service_get_parameters(in_param1,
+ &role, sizeof(bluetooth_audio_role_t));
+
+ result = _bt_audio_select_role(role);
+ if (result == BLUETOOTH_ERROR_NONE) {
+ sender = (char*)g_dbus_method_invocation_get_sender(context);
+ _bt_save_invocation_context(context, result, sender,
+ function_name, NULL);
+ }
+ break;
+ }
case BT_AV_CONNECT: {
bluetooth_device_address_t address = { {0} };
__bt_service_get_parameters(in_param1,
case BT_OBEX_SERVER_CANCEL_TRANSFER:
case BT_OBEX_SERVER_CANCEL_ALL_TRANSFERS:
+ case BT_AUDIO_SELECT_ROLE:
case BT_AUDIO_CONNECT:
case BT_AUDIO_DISCONNECT:
case BT_AG_CONNECT:
#ifndef __BT_SERVICE_AUDIO_COMMON_H__
#define __BT_SERVICE_AUDIO_COMMON_H__
+#include "bluetooth-audio-api.h"
#include "bt-service-event-receiver.h"
#include <bt-service-common.h>
void _bt_audio_check_pending_disconnection(char *address, int type);
+int _bt_audio_select_role(bluetooth_audio_role_t role);
+
+void _bt_audio_set_current_role(bluetooth_audio_role_t role);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
BLUETOOTH_STATE_A2DP_HEADSET_CONNECTED = 0x0010,
} bluetooth_device_state_t;
+typedef enum {
+ BLUETOOTH_A2DP_SOURCE,
+ BLUETOOTH_A2DP_SINK,
+} bluetooth_audio_role_t;
+
/**
* @brief The function bluetooth_audio_init called to initializes the Audio
* service to bluetoothD and Global data related to audio.
*/
int bluetooth_ag_set_speaker_gain(unsigned int speaker_gain);
+/**
+ * @brief The function bluetooth_audio_select_role is called to set
+ * A2DP to Source or Sink.
+ *
+ * @param[in] role SINK/SOURCE.
+ * @return int Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_audio_select_role(bluetooth_audio_role_t role);
+
typedef struct {
int event;
int result;
BT_GET_SPEAKER_GAIN,
BT_SET_SPEAKER_GAIN,
BT_SET_CONTENT_PROTECT,
+ BT_AUDIO_SELECT_ROLE,
BT_OOB_READ_LOCAL_DATA = BT_FUNC_OOB_BASE,
BT_OOB_ADD_REMOTE_DATA,
BT_OOB_REMOVE_REMOTE_DATA,