diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index a23abdd..4d378a9 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
struct a2dp_setup {
struct a2dp_channel *chan;
struct avdtp *session;
+ struct queue *eps;
struct a2dp_sep *sep;
struct a2dp_remote_sep *rsep;
struct avdtp_stream *stream;
static void select_cb(struct a2dp_setup *setup, void *ret, int size)
{
- if (size < 0) {
- DBG("Endpoint replied an invalid configuration");
+ struct avdtp_service_capability *service;
+ struct avdtp_media_codec_capability *codec;
+ int err;
+
+ if (size) {
+ caps_add_codec(&setup->caps, setup->sep->codec, ret, size);
goto done;
}
- caps_add_codec(&setup->caps, setup->sep->codec, ret, size);
+ setup->sep = queue_pop_head(setup->eps);
+ if (!setup->sep) {
+ error("Unable to select a valid configuration");
+ queue_destroy(setup->eps, NULL);
+ goto done;
+ }
+
+ setup->rsep = find_remote_sep(setup->chan, setup->sep);
+ service = avdtp_get_codec(setup->rsep->sep);
+ codec = (struct avdtp_media_codec_capability *) service->data;
+
+ err = setup->sep->endpoint->select_configuration(setup->sep,
+ codec->data,
+ service->length - sizeof(*codec),
+ setup_ref(setup),
+ select_cb, setup->sep->user_data);
+ if (err == 0)
+ return;
done:
finalize_select(setup);
setup_unref(setup);
}
-static struct a2dp_sep *a2dp_find_sep(struct avdtp *session, GSList *list,
+static struct queue *a2dp_find_eps(struct avdtp *session, GSList *list,
const char *sender)
{
- struct a2dp_sep *first = NULL;
struct a2dp_channel *chan = find_channel(session);
+ struct queue *seps = NULL;
for (; list; list = list->next) {
struct a2dp_sep *sep = list->data;
if (!rsep)
continue;
- /* Locate last used if set */
- if (chan->last_used) {
- if (chan->last_used->sep == rsep)
- return sep;
- first = sep;
- continue;
- }
+ if (!seps)
+ seps = queue_new();
- return sep;
+ /* Prepend last used so it is preferred over others */
+ if (chan->last_used && chan->last_used->sep == rsep)
+ queue_push_head(seps, sep);
+ else
+ queue_push_tail(seps, sep);
}
- return first;
+ return seps;
}
-static struct a2dp_sep *a2dp_select_sep(struct avdtp *session, uint8_t type,
+static struct queue *a2dp_select_eps(struct avdtp *session, uint8_t type,
const char *sender)
{
struct a2dp_server *server;
- struct a2dp_sep *sep;
+ struct queue *seps;
GSList *l;
server = find_server(servers, avdtp_get_adapter(session));
l = type == AVDTP_SEP_TYPE_SINK ? server->sources : server->sinks;
/* Check sender's seps first */
- sep = a2dp_find_sep(session, l, sender);
- if (sep != NULL)
- return sep;
+ seps = a2dp_find_eps(session, l, sender);
+ if (seps != NULL)
+ return seps;
- return a2dp_find_sep(session, l, NULL);
+ return a2dp_find_eps(session, l, NULL);
}
static void store_remote_sep(void *data, void *user_data)
{
struct a2dp_setup *setup;
struct a2dp_setup_cb *cb_data;
- struct a2dp_sep *sep;
+ struct queue *eps;
struct avdtp_service_capability *service;
struct avdtp_media_codec_capability *codec;
int err;
- sep = a2dp_select_sep(session, type, sender);
- if (!sep) {
+ eps = a2dp_select_eps(session, type, sender);
+ if (!eps) {
error("Unable to select SEP");
return 0;
}
cb_data->select_cb = cb;
cb_data->user_data = user_data;
- setup->sep = sep;
- setup->rsep = find_remote_sep(setup->chan, sep);
+ setup->eps = eps;
+ setup->sep = queue_pop_head(eps);
+ setup->rsep = find_remote_sep(setup->chan, setup->sep);
if (setup->rsep == NULL) {
error("Could not find remote sep");
service = avdtp_get_codec(setup->rsep->sep);
codec = (struct avdtp_media_codec_capability *) service->data;
- err = sep->endpoint->select_configuration(sep, codec->data,
+ err = setup->sep->endpoint->select_configuration(setup->sep,
+ codec->data,
service->length - sizeof(*codec),
setup_ref(setup),
- select_cb, sep->user_data);
+ select_cb, setup->sep->user_data);
if (err == 0)
return cb_data->id;