.delayreport = endpoint_delayreport_ind,
};
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+static sdp_record_t *a2dp_record(uint8_t type, gboolean sink_enabled)
+#else
static sdp_record_t *a2dp_record(uint8_t type)
+#endif
{
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
uuid_t root_uuid, l2cap_uuid, avdtp_uuid, a2dp_uuid;
sdp_data_t *psm, *version, *features;
uint16_t lp = AVDTP_UUID;
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-#ifdef SUPPORT_LOCAL_DEVICE_A2DP_SINK
- uint16_t a2dp_ver = 0x0102, avdtp_ver = 0x0103, feat = 0x0002;
-#else
- uint16_t a2dp_ver = 0x0102, avdtp_ver = 0x0103, feat = 0x0001;
-#endif
+ uint16_t a2dp_ver, avdtp_ver, feat;
+ if (sink_enabled) {
+ DBG("A2DP record for Sink role");
+ a2dp_ver = 0x0102;
+ avdtp_ver = 0x0103;
+ feat = 0x0002;
+ } else {
+ DBG("A2DP record for Source role");
+ a2dp_ver = 0x0102;
+ avdtp_ver = 0x0103;
+ feat = 0x0001;
+ }
#else
uint16_t a2dp_ver = 0x0103, avdtp_ver = 0x0103, feat = 0x000f;
#endif
if (server->io)
return true;
- server->io = bt_io_listen(NULL, confirm_cb, server, NULL, &err,
+#if defined(TIZEN_FEATURE_BLUEZ_MODIFY)
+ if (btd_adapter_get_a2dp_role(server->adapter) == BLUETOOTH_A2DP_SINK_ROLE) {
+ server->io = bt_io_listen(NULL, confirm_cb, server, NULL, &err,
BT_IO_OPT_SOURCE_BDADDR,
btd_adapter_get_address(server->adapter),
BT_IO_OPT_PSM, AVDTP_PSM,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-#if defined(TIZEN_FEATURE_BLUEZ_MODIFY) && defined(SUPPORT_LOCAL_DEVICE_A2DP_SINK)
BT_IO_OPT_IMTU, 895,
-#endif
BT_IO_OPT_MASTER, true,
BT_IO_OPT_INVALID);
+ } else {
+ server->io = bt_io_listen(NULL, confirm_cb, server, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR,
+ btd_adapter_get_address(server->adapter),
+ BT_IO_OPT_PSM, AVDTP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_MASTER, true,
+ BT_IO_OPT_INVALID);
+ }
+#else
+ server->io = bt_io_listen(NULL, confirm_cb, server, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR,
+ btd_adapter_get_address(server->adapter),
+ BT_IO_OPT_PSM, AVDTP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_MASTER, true,
+ BT_IO_OPT_INVALID);
+#endif
if (server->io)
return true;
if (*record_id != 0)
goto add;
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ if (btd_adapter_get_a2dp_role(adapter) == BLUETOOTH_A2DP_SINK_ROLE)
+ record = a2dp_record(type, true);
+ else
+ record = a2dp_record(type, false);
+#else
record = a2dp_record(type);
+#endif
if (!record) {
error("Unable to allocate new service record");
a2dp_unregister_sep(sep);
static int a2dp_init(void)
{
btd_register_adapter_driver(&media_driver);
-#if defined(TIZEN_FEATURE_BLUEZ_MODIFY) && defined(SUPPORT_LOCAL_DEVICE_A2DP_SINK)
btd_profile_register(&a2dp_source_profile);
-#endif
btd_profile_register(&a2dp_sink_profile);
return 0;
return FALSE;
}
-#if defined TIZEN_FEATURE_BLUEZ_MODIFY && defined SUPPORT_LOCAL_DEVICE_A2DP_SINK
-static void set_disconnect_timer(struct avdtp *session, gboolean disconn)
-#else
-static void set_disconnect_timer(struct avdtp *session)
-#endif
+#if defined TIZEN_FEATURE_BLUEZ_MODIFY
+static void set_disconnect_timer_for_sink(struct avdtp *session, gboolean disconn)
{
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
char name[6];
-#endif
+
if (session->dc_timer)
remove_disconnect_timer(session);
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
device_get_name(session->device, name, sizeof(name));
DBG("name : [%s]", name);
if (g_str_equal(name, "VW BT") || g_str_equal(name, "VW MI") ||
session->dc_timer = g_timeout_add(200, disconnect_timeout,
session);
} else {
-#endif
-#if defined TIZEN_FEATURE_BLUEZ_MODIFY && defined SUPPORT_LOCAL_DEVICE_A2DP_SINK
if (disconn == TRUE)
session->dc_timer = g_timeout_add(100,
disconnect_timeout,
session->dc_timer = g_timeout_add_seconds(DISCONNECT_TIMEOUT,
disconnect_timeout,
session);
-#else
+ }
+}
+#endif
+
+static void set_disconnect_timer(struct avdtp *session)
+{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ char name[6];
+#endif
+ if (session->dc_timer)
+ remove_disconnect_timer(session);
+
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ device_get_name(session->device, name, sizeof(name));
+ DBG("name : [%s]", name);
+ if (g_str_equal(name, "VW BT") || g_str_equal(name, "VW MI") ||
+ g_str_equal(name, "Seat ")) {
+ session->dc_timer = g_timeout_add_seconds(3, disconnect_timeout,
+ session);
+ } else if (g_str_equal(name, "CAR M")) {
+ session->dc_timer = g_timeout_add(200, disconnect_timeout,
+ session);
+ } else {
session->dc_timer = g_timeout_add_seconds(DISCONNECT_TIMEOUT,
disconnect_timeout,
session);
-#endif
}
+#endif
}
void avdtp_unref(struct avdtp *session)
return;
session->ref--;
+#if defined TIZEN_FEATURE_BLUEZ_MODIFY
+ struct btd_adapter *adapter;
+ adapter = avdtp_get_adapter(session);
+#endif
DBG("%p: ref=%d", session, session->ref);
if (session->ref > 0)
return;
-#if defined TIZEN_FEATURE_BLUEZ_MODIFY && defined SUPPORT_LOCAL_DEVICE_A2DP_SINK
- set_disconnect_timer(session, TRUE);
+#if defined TIZEN_FEATURE_BLUEZ_MODIFY
+ if (btd_adapter_get_a2dp_role(adapter) == BLUETOOTH_A2DP_SINK_ROLE)
+ set_disconnect_timer_for_sink(session, TRUE);
+ else
+ set_disconnect_timer(session);
#else
set_disconnect_timer(session);
#endif
struct avdtp *session = user_data;
char address[18];
int err_no = EIO;
+#if defined TIZEN_FEATURE_BLUEZ_MODIFY
+ struct btd_adapter *adapter;
+ adapter = avdtp_get_adapter(session);
+#endif
if (err) {
err_no = err->code;
(GIOFunc) session_cb, session,
NULL);
- if (session->stream_setup)
-#if defined TIZEN_FEATURE_BLUEZ_MODIFY && defined SUPPORT_LOCAL_DEVICE_A2DP_SINK
- set_disconnect_timer(session, FALSE);
+ if (session->stream_setup) {
+#if defined TIZEN_FEATURE_BLUEZ_MODIFY
+ if (btd_adapter_get_a2dp_role(adapter) == BLUETOOTH_A2DP_SINK_ROLE)
+ set_disconnect_timer_for_sink(session, FALSE);
+ else
+ set_disconnect_timer(session);
#else
set_disconnect_timer(session);
#endif
+ }
} else if (session->pending_open)
handle_transport_connect(session, chan, session->imtu,
session->omtu);
GError *err = NULL;
GIOChannel *io;
const bdaddr_t *src;
+#if defined TIZEN_FEATURE_BLUEZ_MODIFY
+ struct btd_adapter *adapter;
+ adapter = avdtp_get_adapter(session);
+#endif
src = btd_adapter_get_address(device_get_adapter(session->device));
- io = bt_io_connect(avdtp_connect_cb, session,
+#if defined TIZEN_FEATURE_BLUEZ_MODIFY
+ if (btd_adapter_get_a2dp_role(adapter) == BLUETOOTH_A2DP_SINK_ROLE) {
+ io = bt_io_connect(avdtp_connect_cb, session,
NULL, &err,
BT_IO_OPT_SOURCE_BDADDR, src,
BT_IO_OPT_DEST_BDADDR,
device_get_address(session->device),
BT_IO_OPT_PSM, AVDTP_PSM,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-#if defined TIZEN_FEATURE_BLUEZ_MODIFY && defined SUPPORT_LOCAL_DEVICE_A2DP_SINK
BT_IO_OPT_IMTU, 895,
-#endif
BT_IO_OPT_INVALID);
+ } else {
+ io = bt_io_connect(avdtp_connect_cb, session,
+ NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_DEST_BDADDR,
+ device_get_address(session->device),
+ BT_IO_OPT_PSM, AVDTP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_INVALID);
+ }
+#else
+ io = bt_io_connect(avdtp_connect_cb, session,
+ NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_DEST_BDADDR,
+ device_get_address(session->device),
+ BT_IO_OPT_PSM, AVDTP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_INVALID);
+#endif
+
if (!io) {
error("%s", err->message);
g_error_free(err);
#define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
#define MEDIA_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+#define A2DP_SINK_ROLE "sink"
+#define A2DP_SOURCE_ROLE "source"
+#endif
+
#define REQUEST_TIMEOUT (3 * 1000) /* 3 seconds */
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
static gboolean set_avrcp_status = FALSE;
static gboolean send_track_changed_event = FALSE;
+gboolean current_delay_reporting = false;
+struct media_endpoint *source_endpoint = NULL;
+struct media_endpoint *sink_endpoint = NULL;
+
static int media_set_sink_callback(struct btd_device *device,
struct media_player *mp);
static void media_sink_state_changed_cb(struct btd_service *service,
if (endpoint->sep) {
a2dp_remove_sep(endpoint->sep);
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
return;
+#endif
}
info("Endpoint unregistered: sender=%s path=%s", endpoint->sender,
endpoint->sep = a2dp_add_sep(endpoint->adapter->btd_adapter,
AVDTP_SEP_TYPE_SOURCE, endpoint->codec,
delay_reporting, &a2dp_endpoint,
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ endpoint, NULL, err);
+#else
endpoint, a2dp_destroy_endpoint, err);
+#endif
if (endpoint->sep == NULL)
return FALSE;
endpoint->sep = a2dp_add_sep(endpoint->adapter->btd_adapter,
AVDTP_SEP_TYPE_SINK, endpoint->codec,
delay_reporting, &a2dp_endpoint,
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ endpoint, NULL, err);
+#else
endpoint, a2dp_destroy_endpoint, err);
+#endif
if (endpoint->sep == NULL)
return FALSE;
endpoint->adapter = adapter;
- if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0)
+ if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) {
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ source_endpoint = endpoint;
+ if (btd_adapter_get_a2dp_role(adapter->btd_adapter) == BLUETOOTH_A2DP_SINK_ROLE)
+ return endpoint;
+ else
+ succeeded = endpoint_init_a2dp_source(endpoint,
+ delay_reporting, err);
+#else
succeeded = endpoint_init_a2dp_source(endpoint,
delay_reporting, err);
- else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0)
+#endif
+ } else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) {
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ sink_endpoint = endpoint;
+ if (btd_adapter_get_a2dp_role(adapter->btd_adapter) == BLUETOOTH_A2DP_SOURCE_ROLE)
+ return endpoint;
+ else
+ succeeded = endpoint_init_a2dp_sink(endpoint,
+ delay_reporting, err);
+#else
succeeded = endpoint_init_a2dp_sink(endpoint,
delay_reporting, err);
- else if (strcasecmp(uuid, HFP_AG_UUID) == 0 ||
+#endif
+ } else if (strcasecmp(uuid, HFP_AG_UUID) == 0 ||
strcasecmp(uuid, HSP_AG_UUID) == 0)
succeeded = TRUE;
else if (strcasecmp(uuid, HFP_HS_UUID) == 0 ||
return endpoint;
}
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+static int parse_a2dp_uuid(DBusMessageIter *props, const char **uuid)
+{
+ gboolean has_uuid = FALSE;
+
+ while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
+ const char *key;
+ DBusMessageIter value, entry;
+ int var;
+
+ dbus_message_iter_recurse(props, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
+
+ var = dbus_message_iter_get_arg_type(&value);
+ if (strcasecmp(key, "UUID") == 0) {
+ if (var != DBUS_TYPE_STRING)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, uuid);
+ has_uuid = TRUE;
+ }
+ dbus_message_iter_next(props);
+ }
+
+ return has_uuid ? 0 : -EINVAL;
+}
+#endif
+
static int parse_properties(DBusMessageIter *props, const char **uuid,
gboolean *delay_reporting, uint8_t *codec,
uint8_t **capabilities, int *size)
return (has_uuid && has_codec) ? 0 : -EINVAL;
}
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+static DBusMessage *a2dp_select_role(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct media_adapter *adapter = data;
+ DBusMessageIter args, props;
+ const char *a2dp_role;
+ gboolean ret;
+ int err;
+
+ if (!dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &a2dp_role,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ if (!g_strcmp0(a2dp_role, A2DP_SINK_ROLE)) {
+ btd_adapter_set_a2dp_role(adapter->btd_adapter, BLUETOOTH_A2DP_SINK_ROLE);
+ a2dp_remove_sep(source_endpoint->sep);
+ ret = endpoint_init_a2dp_sink(sink_endpoint, current_delay_reporting, NULL);
+ if (!ret)
+ DBG("could not init a2dp sink");
+ } else if (!g_strcmp0(a2dp_role, A2DP_SOURCE_ROLE)) {
+ btd_adapter_set_a2dp_role(adapter->btd_adapter, BLUETOOTH_A2DP_SOURCE_ROLE);
+ a2dp_remove_sep(sink_endpoint->sep);
+ ret = endpoint_init_a2dp_source(source_endpoint, current_delay_reporting, NULL);
+ if (!ret)
+ DBG("could not init a2dp source");
+ } else {
+ DBG("invalid a2dp role");
+ return btd_error_invalid_args(msg);
+ }
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+#endif
+
static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
void *data)
{
uint8_t *capabilities;
int size = 0;
int err;
-
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ if (btd_adapter_get_a2dp_role(adapter->btd_adapter) == BLUETOOTH_A2DP_SINK_ROLE) {
+ a2dp_sink_support = true;
+ a2dp_source_support = false;
+ } else {
+ a2dp_sink_support = false;
+ a2dp_source_support = true;
+ }
+#endif
sender = dbus_message_get_sender(msg);
dbus_message_iter_init(msg, &args);
&capabilities, &size) < 0)
return btd_error_invalid_args(msg);
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- if(!a2dp_sink_support && !g_strcmp0(uuid, A2DP_SINK_UUID)) {
- error("A2DP sink role is not supported.");
- return btd_error_not_supported(msg);
- }
-
- if(!a2dp_source_support && !g_strcmp0(uuid, A2DP_SOURCE_UUID)) {
- error("A2DP source role is not supported.");
- return btd_error_not_supported(msg);
- }
+ current_delay_reporting = delay_reporting;
#endif
if (media_endpoint_create(adapter, sender, path, uuid, delay_reporting,
codec, capabilities, size, &err) == NULL) {
NULL, register_player) },
{ GDBUS_METHOD("UnregisterPlayer",
GDBUS_ARGS({ "player", "o" }), NULL, unregister_player) },
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ { GDBUS_METHOD("SelectRole",
+ GDBUS_ARGS({ "role", "s" }), NULL, a2dp_select_role) },
+#endif
{ },
};
unsigned int db_id; /* Service event handler for GATT db */
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
uint8_t central_rpa_res_support;
+ bluetooth_a2dp_role_t a2dp_role;
#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
bool scan_filter_support; /* platform's scan filtering support */
uint8_t scan_type; /* scan type */
if (adapter->stored_alias)
g_key_file_set_string(key_file, "General", "Alias",
adapter->stored_alias);
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ /* Store A2DP Role */
+ if (adapter->a2dp_role == BLUETOOTH_A2DP_SINK_ROLE)
+ g_key_file_set_string(key_file, "General", "DefaultA2DPRole", "sink");
+ else
+ g_key_file_set_string(key_file, "General", "DefaultA2DPRole", "source");
+#endif
ba2str(&adapter->bdaddr, address);
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/settings", address);
g_key_file_free(key_file);
}
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+bluetooth_a2dp_role_t btd_adapter_get_a2dp_role(struct btd_adapter *adapter)
+{
+ if (!adapter)
+ return BLUETOOTH_A2DP_SOURCE_ROLE;
+
+ return adapter->a2dp_role;
+}
+
+void btd_adapter_set_a2dp_role(struct btd_adapter *adapter, bluetooth_a2dp_role_t role)
+{
+ if (!adapter) {
+ DBG("Could not set a2dp role");
+ return;
+ }
+
+ if (role == BLUETOOTH_A2DP_SOURCE_ROLE) {
+ DBG("Set audio source role");
+ adapter->a2dp_role = BLUETOOTH_A2DP_SOURCE_ROLE;
+ } else if (role == BLUETOOTH_A2DP_SINK_ROLE) {
+ DBG("Set audio sink role");
+ adapter->a2dp_role = BLUETOOTH_A2DP_SINK_ROLE;
+ }
+
+ store_adapter_info(adapter);
+}
+#endif
+
static void trigger_pairable_timeout(struct btd_adapter *adapter);
static void adapter_start(struct btd_adapter *adapter);
static void adapter_stop(struct btd_adapter *adapter);
char address[18];
struct stat st;
GError *gerr = NULL;
-
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ char *str;
+#endif
ba2str(&adapter->bdaddr, address);
key_file = g_key_file_new();
gerr = NULL;
}
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ /* Get A2DP Role */
+ str = g_key_file_get_string(key_file, "General", "DefaultA2DPRole", &gerr);
+ if (gerr || !str) {
+ adapter->a2dp_role = BLUETOOTH_A2DP_SOURCE_ROLE;
+ g_error_free(gerr);
+ gerr = NULL;
+ } else {
+ if (g_strcmp0(str, "sink") == 0)
+ adapter->a2dp_role = BLUETOOTH_A2DP_SINK_ROLE;
+ else if (g_strcmp0(str, "source") == 0)
+ adapter->a2dp_role = BLUETOOTH_A2DP_SOURCE_ROLE;
+ }
+#endif
+
g_key_file_free(key_file);
}
key->pin_len);
device_set_bonded(device, BDADDR_BREDR);
-#if defined(TIZEN_FEATURE_BLUEZ_MODIFY) && defined(SUPPORT_LOCAL_DEVICE_A2DP_SINK)
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
} else {
- DBG("store_hint %d", ev->store_hint);
- btd_device_set_temporary(device, false);
+ if (btd_adapter_get_a2dp_role(adapter) == BLUETOOTH_A2DP_SINK_ROLE) {
+ DBG("store_hint %d", ev->store_hint);
+ btd_device_set_temporary(device, false);
+ }
}
#else
}
struct btd_adapter;
struct btd_device;
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+typedef enum {
+ BLUETOOTH_A2DP_SOURCE_ROLE = 0,
+ BLUETOOTH_A2DP_SINK_ROLE,
+} bluetooth_a2dp_role_t;
+#endif
+
struct btd_adapter *btd_adapter_get_default(void);
bool btd_adapter_is_default(struct btd_adapter *adapter);
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+bluetooth_a2dp_role_t btd_adapter_get_a2dp_role(struct btd_adapter *adapter);
+void btd_adapter_set_a2dp_role(struct btd_adapter *adapter, bluetooth_a2dp_role_t role);
+#endif
uint16_t btd_adapter_get_index(struct btd_adapter *adapter);
typedef void (*adapter_cb) (struct btd_adapter *adapter, gpointer user_data);