From: Mikel Astiz <[email protected]>
I resend the patches which were previously part of RFC v0 "WIP: btd_profile connect and disconnect", focusing now on the audio-related patches.
The proposal is to split A2DP roles into different btd_profile instances, in order to expose .connect and .disconnect.
The implementation includes the Source role only (patches 3 and 4), but you can imagine that the Sink would be analogous.
Mikel Astiz (4):
audio: Split A2DP into three btd_profile
audio: Trivial function rename
source: Expose internal connection API
source: Add profile .connect and .disconnect
audio/a2dp.c | 88 +++++++++++++-------------
audio/a2dp.h | 4 +-
audio/device.h | 3 +
audio/manager.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
audio/sink.c | 12 ++--
audio/source.c | 158 ++++++++++++++++++++++++++---------------------
audio/source.h | 2 +
7 files changed, 315 insertions(+), 139 deletions(-)
--
1.7.11.7
From: Mikel Astiz <[email protected]>
Separate the D-Bus code from the internal connection handling code,
exposing an internal API in case some internal codepath/plugin is
interested in using it.
---
audio/device.h | 3 ++
audio/source.c | 146 ++++++++++++++++++++++++++++++++-------------------------
audio/source.h | 2 +
3 files changed, 88 insertions(+), 63 deletions(-)
diff --git a/audio/device.h b/audio/device.h
index 1e2cac1..41e5635 100644
--- a/audio/device.h
+++ b/audio/device.h
@@ -22,6 +22,7 @@
*
*/
+struct audio_device;
struct source;
struct control;
struct target;
@@ -30,6 +31,8 @@ struct headset;
struct gateway;
struct dev_priv;
+typedef void (*audio_device_cb) (struct audio_device *dev, int err, void *data);
+
struct audio_device {
struct btd_device *btd_dev;
diff --git a/audio/source.c b/audio/source.c
index 04971d9..e48e308 100644
--- a/audio/source.c
+++ b/audio/source.c
@@ -53,7 +53,8 @@
#define STREAM_SETUP_RETRY_TIMER 2
struct pending_request {
- DBusMessage *msg;
+ audio_device_cb cb;
+ void *cb_data;
unsigned int id;
};
@@ -152,10 +153,12 @@ static void avdtp_state_callback(struct audio_device *dev,
}
static void pending_request_free(struct audio_device *dev,
- struct pending_request *pending)
+ struct pending_request *pending,
+ int err)
{
- if (pending->msg)
- dbus_message_unref(pending->msg);
+ if (pending->cb)
+ pending->cb(dev, err, pending->cb_data);
+
if (pending->id)
a2dp_cancel(dev, pending->id);
@@ -177,15 +180,12 @@ static void stream_state_changed(struct avdtp_stream *stream,
switch (new_state) {
case AVDTP_STATE_IDLE:
if (source->disconnect) {
- DBusMessage *reply;
struct pending_request *p;
p = source->disconnect;
source->disconnect = NULL;
- reply = dbus_message_new_method_return(p->msg);
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- pending_request_free(dev, p);
+ pending_request_free(dev, p, 0);
}
if (source->session) {
@@ -211,35 +211,24 @@ static void stream_state_changed(struct avdtp_stream *stream,
source->stream_state = new_state;
}
-static void error_failed(DBusMessage *msg,
- const char *desc)
-{
- DBusMessage *reply = btd_error_failed(msg, desc);
- g_dbus_send_message(btd_get_dbus_connection(), reply);
-}
-
static gboolean stream_setup_retry(gpointer user_data)
{
struct source *source = user_data;
struct pending_request *pending = source->connect;
+ int err;
source->retry_id = 0;
if (source->stream_state >= AVDTP_STATE_OPEN) {
DBG("Stream successfully created, after XCASE connect:connect");
- if (pending->msg) {
- DBusMessage *reply;
- reply = dbus_message_new_method_return(pending->msg);
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- }
+ err = 0;
} else {
DBG("Stream setup failed, after XCASE connect:connect");
- if (pending->msg)
- error_failed(pending->msg, "Stream setup failed");
+ err = -EIO;
}
source->connect = NULL;
- pending_request_free(source->dev, pending);
+ pending_request_free(source->dev, pending, err);
return FALSE;
}
@@ -258,14 +247,8 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
if (stream) {
DBG("Stream successfully created");
- if (pending->msg) {
- DBusMessage *reply;
- reply = dbus_message_new_method_return(pending->msg);
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- }
-
source->connect = NULL;
- pending_request_free(source->dev, pending);
+ pending_request_free(source->dev, pending, 0);
return;
}
@@ -279,10 +262,8 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
stream_setup_retry,
source);
} else {
- if (pending->msg)
- error_failed(pending->msg, "Stream setup failed");
source->connect = NULL;
- pending_request_free(source->dev, pending);
+ pending_request_free(source->dev, pending, -EIO);
DBG("Stream setup failed : %s", avdtp_strerror(err));
}
}
@@ -309,9 +290,7 @@ static void select_complete(struct avdtp *session, struct a2dp_sep *sep,
return;
failed:
- if (pending->msg)
- error_failed(pending->msg, "Stream setup failed");
- pending_request_free(source->dev, pending);
+ pending_request_free(source->dev, pending, -EIO);
source->connect = NULL;
avdtp_unref(source->session);
source->session = NULL;
@@ -352,9 +331,7 @@ static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp
return;
failed:
- if (pending->msg)
- error_failed(pending->msg, "Stream setup failed");
- pending_request_free(source->dev, pending);
+ pending_request_free(source->dev, pending, -EIO);
source->connect = NULL;
avdtp_unref(source->session);
source->session = NULL;
@@ -379,71 +356,114 @@ gboolean source_setup_stream(struct source *source, struct avdtp *session)
return TRUE;
}
+static void generic_cb(struct audio_device *dev, int err, void *data)
+{
+ DBusMessage *msg = data;
+ DBusMessage *reply;
+
+ if (err < 0) {
+ reply = btd_error_failed(msg, strerror(-err));
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ dbus_message_unref(msg);
+ return;
+ }
+
+ g_dbus_send_reply(btd_get_dbus_connection(), msg, DBUS_TYPE_INVALID);
+
+ dbus_message_unref(msg);
+}
+
static DBusMessage *local_connect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct audio_device *dev = data;
+ int err;
+
+ err = source_connect(dev, generic_cb, msg);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ dbus_message_ref(msg);
+
+ return NULL;
+}
+
+int source_connect(struct audio_device *dev, audio_device_cb cb, void *data)
+{
struct source *source = dev->source;
struct pending_request *pending;
if (!source->session)
source->session = avdtp_get(&dev->src, &dev->dst);
- if (!source->session)
- return btd_error_failed(msg, "Unable to get a session");
+ if (!source->session) {
+ DBG("Unable to get a session");
+ return -EIO;
+ }
if (source->connect || source->disconnect)
- return btd_error_busy(msg);
+ return -EBUSY;
if (source->stream_state >= AVDTP_STATE_OPEN)
- return btd_error_already_connected(msg);
+ return -EALREADY;
- if (!source_setup_stream(source, NULL))
- return btd_error_failed(msg, "Failed to create a stream");
+ if (!source_setup_stream(source, NULL)) {
+ DBG("Failed to create a stream");
+ return -EIO;
+ }
dev->auto_connect = FALSE;
pending = source->connect;
-
- pending->msg = dbus_message_ref(msg);
+ pending->cb = cb;
+ pending->cb_data = data;
DBG("stream creation in progress");
- return NULL;
+ return 0;
}
static DBusMessage *local_disconnect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
+ struct audio_device *dev = data;
+ int err;
+
+ err = source_disconnect(dev, generic_cb, msg);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ dbus_message_ref(msg);
+
+ return NULL;
+}
+
+int source_disconnect(struct audio_device *dev, audio_device_cb cb, void *data)
+{
struct audio_device *device = data;
struct source *source = device->source;
struct pending_request *pending;
int err;
if (!source->session)
- return btd_error_not_connected(msg);
+ return -ENOTCONN;
if (source->connect || source->disconnect)
- return btd_error_busy(msg);
+ return -EBUSY;
- if (source->stream_state < AVDTP_STATE_OPEN) {
- DBusMessage *reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
- avdtp_unref(source->session);
- source->session = NULL;
- return reply;
- }
+ if (source->stream_state < AVDTP_STATE_OPEN)
+ return -ENOTCONN;
err = avdtp_close(source->session, source->stream, FALSE);
if (err < 0)
- return btd_error_failed(msg, strerror(-err));
+ return err;
pending = g_new0(struct pending_request, 1);
- pending->msg = dbus_message_ref(msg);
+ pending->cb = cb;
+ pending->cb_data = data;
source->disconnect = pending;
- return NULL;
+ return 0;
}
static DBusMessage *local_get_properties(DBusConnection *conn,
@@ -504,10 +524,10 @@ static void source_free(struct audio_device *dev)
avdtp_unref(source->session);
if (source->connect)
- pending_request_free(dev, source->connect);
+ pending_request_free(dev, source->connect, -ECANCELED);
if (source->disconnect)
- pending_request_free(dev, source->disconnect);
+ pending_request_free(dev, source->disconnect, -ECANCELED);
if (source->retry_id)
g_source_remove(source->retry_id);
diff --git a/audio/source.h b/audio/source.h
index 695bded..dadb392 100644
--- a/audio/source.h
+++ b/audio/source.h
@@ -44,6 +44,8 @@ struct source *source_init(struct audio_device *dev);
void source_unregister(struct audio_device *dev);
gboolean source_is_active(struct audio_device *dev);
source_state_t source_get_state(struct audio_device *dev);
+int source_connect(struct audio_device *dev, audio_device_cb cb, void *data);
+int source_disconnect(struct audio_device *dev, audio_device_cb cb, void *data);
gboolean source_new_stream(struct audio_device *dev, struct avdtp *session,
struct avdtp_stream *stream);
gboolean source_setup_stream(struct source *source, struct avdtp *session);
--
1.7.11.7
From: Mikel Astiz <[email protected]>
Add the connection and disconnection hooks to the a2dp_source
btd_profile.
---
audio/manager.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 82 insertions(+)
diff --git a/audio/manager.c b/audio/manager.c
index c5d295e..77e3540 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -83,6 +83,12 @@ struct audio_adapter {
gint ref;
};
+struct profile_req {
+ struct btd_device *device;
+ struct btd_profile *profile;
+ btd_profile_cb cb;
+};
+
static gboolean auto_connect = TRUE;
static int max_connected_headsets = 1;
static GKeyFile *config = NULL;
@@ -776,6 +782,79 @@ static int avrcp_probe(struct btd_profile *p, struct btd_device *device,
return 0;
}
+static struct profile_req *new_profile_request(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ struct profile_req *req;
+
+ req = g_new0(struct profile_req, 1);
+ req->device = dev;
+ req->profile = profile;
+ req->cb = cb;
+
+ return req;
+}
+
+static void profile_cb(struct audio_device *dev, int err, void *data)
+{
+ struct profile_req *req = data;
+
+ req->cb(req->profile, req->device, err);
+
+ g_free(req);
+}
+
+static int a2dp_source_connect(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ struct audio_device *audio_dev;
+ struct profile_req *req;
+ int err;
+
+ audio_dev = get_audio_dev(dev);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ req = new_profile_request(dev, profile, cb);
+
+ err = source_connect(audio_dev, profile_cb, req);
+ if (err < 0) {
+ g_free(req);
+ return err;
+ }
+
+ return 0;
+}
+
+static int a2dp_source_disconnect(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ struct audio_device *audio_dev;
+ struct profile_req *req;
+ int err;
+
+ audio_dev = get_audio_dev(dev);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ req = new_profile_request(dev, profile, cb);
+
+ err = source_disconnect(audio_dev, profile_cb, req);
+ if (err < 0) {
+ g_free(req);
+ return err;
+ }
+
+ return 0;
+}
+
static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
{
adp->ref++;
@@ -1150,6 +1229,9 @@ static struct btd_profile a2dp_source_profile = {
.device_probe = a2dp_source_probe,
.device_remove = audio_remove,
+ .connect = a2dp_source_connect,
+ .disconnect = a2dp_source_disconnect,
+
.adapter_probe = a2dp_source_server_probe,
};
--
1.7.11.7
From: Mikel Astiz <[email protected]>
Use the local_ name prefix for local functions implementing the D-Bus
API.
---
audio/sink.c | 12 ++++++------
audio/source.c | 12 ++++++------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/audio/sink.c b/audio/sink.c
index 2e63579..b9e4fe0 100644
--- a/audio/sink.c
+++ b/audio/sink.c
@@ -390,7 +390,7 @@ gboolean sink_setup_stream(struct sink *sink, struct avdtp *session)
return TRUE;
}
-static DBusMessage *sink_connect(DBusConnection *conn,
+static DBusMessage *local_connect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct audio_device *dev = data;
@@ -423,7 +423,7 @@ static DBusMessage *sink_connect(DBusConnection *conn,
return NULL;
}
-static DBusMessage *sink_disconnect(DBusConnection *conn,
+static DBusMessage *local_disconnect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct audio_device *device = data;
@@ -457,7 +457,7 @@ static DBusMessage *sink_disconnect(DBusConnection *conn,
return NULL;
}
-static DBusMessage *sink_get_properties(DBusConnection *conn,
+static DBusMessage *local_get_properties(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct audio_device *device = data;
@@ -489,11 +489,11 @@ static DBusMessage *sink_get_properties(DBusConnection *conn,
}
static const GDBusMethodTable sink_methods[] = {
- { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, sink_connect) },
- { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, sink_disconnect) },
+ { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, local_connect) },
+ { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, local_disconnect) },
{ GDBUS_METHOD("GetProperties",
NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- sink_get_properties) },
+ local_get_properties) },
{ }
};
diff --git a/audio/source.c b/audio/source.c
index 1d0c74a..04971d9 100644
--- a/audio/source.c
+++ b/audio/source.c
@@ -379,7 +379,7 @@ gboolean source_setup_stream(struct source *source, struct avdtp *session)
return TRUE;
}
-static DBusMessage *source_connect(DBusConnection *conn,
+static DBusMessage *local_connect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct audio_device *dev = data;
@@ -412,7 +412,7 @@ static DBusMessage *source_connect(DBusConnection *conn,
return NULL;
}
-static DBusMessage *source_disconnect(DBusConnection *conn,
+static DBusMessage *local_disconnect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct audio_device *device = data;
@@ -446,7 +446,7 @@ static DBusMessage *source_disconnect(DBusConnection *conn,
return NULL;
}
-static DBusMessage *source_get_properties(DBusConnection *conn,
+static DBusMessage *local_get_properties(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct audio_device *device = data;
@@ -478,11 +478,11 @@ static DBusMessage *source_get_properties(DBusConnection *conn,
}
static const GDBusMethodTable source_methods[] = {
- { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, source_connect) },
- { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, source_disconnect) },
+ { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, local_connect) },
+ { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, local_disconnect) },
{ GDBUS_METHOD("GetProperties",
NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- source_get_properties) },
+ local_get_properties) },
{ }
};
--
1.7.11.7
From: Mikel Astiz <[email protected]>
Merging the three audio profiles (AVDTP, A2DP sink and A2DP source)
into one was convenient in the past was doesn't fit very well the new
btd_profile approach. The split is also more consistent with the
approach of the HFP/HSP profile.
---
audio/a2dp.c | 88 ++++++++++++++++++++++-------------------------
audio/a2dp.h | 4 ++-
audio/manager.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++---------
3 files changed, 133 insertions(+), 64 deletions(-)
diff --git a/audio/a2dp.c b/audio/a2dp.c
index 7799420..6bfc8c2 100644
--- a/audio/a2dp.c
+++ b/audio/a2dp.c
@@ -1167,73 +1167,67 @@ static struct a2dp_server *find_server(GSList *list, const bdaddr_t *src)
return NULL;
}
-int a2dp_register(const bdaddr_t *src, GKeyFile *config)
+int a2dp_server_register(const bdaddr_t *src, GKeyFile *config)
{
- gboolean source = TRUE, sink = FALSE;
gboolean delay_reporting = FALSE;
- char *str;
- GError *err = NULL;
struct a2dp_server *server;
+ int av_err;
- if (!config)
- goto proceed;
+ server = find_server(servers, src);
+ if (server)
+ return 0;
- str = g_key_file_get_string(config, "General", "Enable", &err);
+ server = g_new0(struct a2dp_server, 1);
- if (err) {
- DBG("audio.conf: %s", err->message);
- g_clear_error(&err);
- } else {
- if (strstr(str, "Sink"))
- source = TRUE;
- if (strstr(str, "Source"))
- sink = TRUE;
- g_free(str);
+ av_err = avdtp_init(src, config, &server->version);
+ if (av_err < 0) {
+ g_free(server);
+ return av_err;
}
- str = g_key_file_get_string(config, "General", "Disable", &err);
+ bacpy(&server->src, src);
+ servers = g_slist_append(servers, server);
- if (err) {
- DBG("audio.conf: %s", err->message);
- g_clear_error(&err);
- } else {
- if (strstr(str, "Sink"))
- source = FALSE;
- if (strstr(str, "Source"))
- sink = FALSE;
- g_free(str);
- }
+ if (config)
+ delay_reporting = g_key_file_get_boolean(config, "A2DP",
+ "DelayReporting", NULL);
-proceed:
+ if (delay_reporting)
+ server->version = 0x0103;
+ else
+ server->version = 0x0102;
+
+ return 0;
+}
+
+int a2dp_source_register(const bdaddr_t *src, GKeyFile *config)
+{
+ struct a2dp_server *server;
server = find_server(servers, src);
if (!server) {
- int av_err;
+ DBG("AVDTP not registered");
+ return -EPROTONOSUPPORT;
- server = g_new0(struct a2dp_server, 1);
+ }
- av_err = avdtp_init(src, config, &server->version);
- if (av_err < 0) {
- g_free(server);
- return av_err;
- }
+ server->source_enabled = TRUE;
- bacpy(&server->src, src);
- servers = g_slist_append(servers, server);
- }
+ return 0;
+}
- if (config)
- delay_reporting = g_key_file_get_boolean(config, "A2DP",
- "DelayReporting", NULL);
+int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config)
+{
+ struct a2dp_server *server;
- if (delay_reporting)
- server->version = 0x0103;
- else
- server->version = 0x0102;
+ server = find_server(servers, src);
+ if (!server) {
+ DBG("AVDTP not registered");
+ return -EPROTONOSUPPORT;
- server->source_enabled = source;
+ }
- server->sink_enabled = sink;
+ server->sink_enabled = TRUE;
return 0;
}
diff --git a/audio/a2dp.h b/audio/a2dp.h
index 736bc66..c471499 100644
--- a/audio/a2dp.h
+++ b/audio/a2dp.h
@@ -64,7 +64,9 @@ typedef void (*a2dp_stream_cb_t) (struct avdtp *session,
struct avdtp_error *err,
void *user_data);
-int a2dp_register(const bdaddr_t *src, GKeyFile *config);
+int a2dp_server_register(const bdaddr_t *src, GKeyFile *config);
+int a2dp_source_register(const bdaddr_t *src, GKeyFile *config);
+int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config);
void a2dp_unregister(const bdaddr_t *src);
struct a2dp_sep *a2dp_add_sep(const bdaddr_t *src, uint8_t type,
diff --git a/audio/manager.c b/audio/manager.c
index 4ea61bf..c5d295e 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -722,7 +722,7 @@ static int ag_probe(struct btd_profile *p, struct btd_device *device,
return 0;
}
-static int a2dp_probe(struct btd_profile *p, struct btd_device *device,
+static int a2dp_source_probe(struct btd_profile *p, struct btd_device *device,
GSList *uuids)
{
struct audio_device *audio_dev;
@@ -733,13 +733,23 @@ static int a2dp_probe(struct btd_profile *p, struct btd_device *device,
return -1;
}
- if (g_slist_find_custom(uuids, A2DP_SINK_UUID, bt_uuid_strcmp) &&
- audio_dev->sink == NULL)
- audio_dev->sink = sink_init(audio_dev);
+ audio_dev->source = source_init(audio_dev);
- if (g_slist_find_custom(uuids, A2DP_SOURCE_UUID, bt_uuid_strcmp) &&
- audio_dev->source == NULL)
- audio_dev->source = source_init(audio_dev);
+ return 0;
+}
+
+static int a2dp_sink_probe(struct btd_profile *p, struct btd_device *device,
+ GSList *uuids)
+{
+ struct audio_device *audio_dev;
+
+ audio_dev = get_audio_dev(device);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ audio_dev->sink = sink_init(audio_dev);
return 0;
}
@@ -975,7 +985,7 @@ static int a2dp_server_probe(struct btd_profile *p,
if (!adp)
return -EINVAL;
- err = a2dp_register(adapter_get_address(adapter), config);
+ err = a2dp_server_register(adapter_get_address(adapter), config);
if (err < 0)
audio_adapter_unref(adp);
@@ -998,6 +1008,40 @@ static void a2dp_server_remove(struct btd_profile *p,
audio_adapter_unref(adp);
}
+static int a2dp_source_server_probe(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct audio_adapter *adp;
+ const gchar *path = adapter_get_path(adapter);
+
+ DBG("path %s", path);
+
+ adp = audio_adapter_get(adapter);
+ if (!adp)
+ return -EINVAL;
+
+ audio_adapter_unref(adp); /* Referenced by a2dp server */
+
+ return a2dp_source_register(adapter_get_address(adapter), config);
+}
+
+static int a2dp_sink_server_probe(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct audio_adapter *adp;
+ const gchar *path = adapter_get_path(adapter);
+
+ DBG("path %s", path);
+
+ adp = audio_adapter_get(adapter);
+ if (!adp)
+ return -EINVAL;
+
+ audio_adapter_unref(adp); /* Referenced by a2dp server */
+
+ return a2dp_sink_register(adapter_get_address(adapter), config);
+}
+
static int avrcp_server_probe(struct btd_profile *p,
struct btd_adapter *adapter)
{
@@ -1090,18 +1134,35 @@ static struct btd_profile gateway_profile = {
.adapter_remove = gateway_server_remove,
};
-static struct btd_profile a2dp_profile = {
- .name = "audio-a2dp",
+static struct btd_profile avdtp_profile = {
+ .name = "audio-avdtp",
- .remote_uuids = BTD_UUIDS(A2DP_SOURCE_UUID, A2DP_SINK_UUID,
- ADVANCED_AUDIO_UUID),
- .device_probe = a2dp_probe,
- .device_remove = audio_remove,
+ .remote_uuids = BTD_UUIDS(ADVANCED_AUDIO_UUID),
.adapter_probe = a2dp_server_probe,
.adapter_remove = a2dp_server_remove,
};
+static struct btd_profile a2dp_source_profile = {
+ .name = "audio-source",
+
+ .remote_uuids = BTD_UUIDS(A2DP_SOURCE_UUID),
+ .device_probe = a2dp_source_probe,
+ .device_remove = audio_remove,
+
+ .adapter_probe = a2dp_source_server_probe,
+};
+
+static struct btd_profile a2dp_sink_profile = {
+ .name = "audio-sink",
+
+ .remote_uuids = BTD_UUIDS(A2DP_SINK_UUID),
+ .device_probe = a2dp_sink_probe,
+ .device_remove = audio_remove,
+
+ .adapter_probe = a2dp_sink_server_probe,
+};
+
static struct btd_profile avrcp_profile = {
.name = "audio-avrcp",
@@ -1194,7 +1255,13 @@ proceed:
btd_profile_register(&gateway_profile);
if (enabled.source || enabled.sink)
- btd_profile_register(&a2dp_profile);
+ btd_profile_register(&avdtp_profile);
+
+ if (enabled.source)
+ btd_profile_register(&a2dp_source_profile);
+
+ if (enabled.sink)
+ btd_profile_register(&a2dp_sink_profile);
if (enabled.control)
btd_profile_register(&avrcp_profile);
@@ -1219,8 +1286,14 @@ void audio_manager_exit(void)
if (enabled.gateway)
btd_profile_unregister(&gateway_profile);
+ if (enabled.source)
+ btd_profile_unregister(&a2dp_source_profile);
+
+ if (enabled.sink)
+ btd_profile_unregister(&a2dp_sink_profile);
+
if (enabled.source || enabled.sink)
- btd_profile_unregister(&a2dp_profile);
+ btd_profile_unregister(&avdtp_profile);
if (enabled.control)
btd_profile_unregister(&avrcp_profile);
--
1.7.11.7