diff --git a/src/shared/bap.c b/src/shared/bap.c
index fda1e35..1c15a4e 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
struct queue *pending_states;
bool no_cache_config;
bool client;
+ bool locked;
+ bool need_reconfig;
void *user_data;
};
if (!stream->client)
return 0;
+ if (stream->need_reconfig)
+ return 0;
+
memset(&qos, 0, sizeof(qos));
/* TODO: Figure out how to pass these values around */
/* If stream does not belong to a client session, clean it up now */
if (!bap_stream_valid(stream)) {
stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
- stream = NULL;
return 0;
}
stream->ep->dir == link->ep->dir)
return -EINVAL;
+ if (stream->client && !(stream->locked && link->locked))
+ return -EINVAL;
+
if (!stream->links)
stream->links = queue_new();
ep->stream->cc = new0(struct iovec, 1);
util_iov_memcpy(ep->stream->cc, cfg->cc, cfg->cc_len);
+
+ ep->stream->need_reconfig = false;
}
static void bap_stream_config_cfm_cb(struct bt_bap_stream *stream, int err)
return false;
}
-static bool find_ep_unused(const void *data, const void *user_data)
-{
- const struct bt_bap_endpoint *ep = data;
- const struct match_pac *match = user_data;
-
- if (ep->stream)
- return false;
-
- if (match->rpac)
- return ep->dir == match->rpac->type;
- else
- return true;
-}
-
-static bool find_ep_pacs(const void *data, const void *user_data)
-{
- const struct bt_bap_endpoint *ep = data;
- const struct match_pac *match = user_data;
-
- if (!ep->stream)
- return false;
-
- if (ep->stream->lpac != match->lpac)
- return false;
-
- if (ep->stream->rpac != match->rpac)
- return false;
-
- switch (ep->state) {
- case BT_BAP_STREAM_STATE_CONFIG:
- case BT_BAP_STREAM_STATE_QOS:
- return true;
- }
-
- return false;
-}
-
static bool find_ep_source(const void *data, const void *user_data)
{
const struct bt_bap_endpoint *ep = data;
return stream;
}
+static bool find_ep_ucast(const void *data, const void *user_data)
+{
+ const struct bt_bap_endpoint *ep = data;
+ const struct match_pac *match = user_data;
+
+ if (ep->stream) {
+ if (!ep->stream->client)
+ return false;
+ if (ep->stream->locked)
+ return false;
+ if (!queue_isempty(ep->stream->pending_states))
+ return false;
+
+ switch (ep->stream->state) {
+ case BT_BAP_STREAM_STATE_IDLE:
+ case BT_BAP_STREAM_STATE_CONFIG:
+ case BT_BAP_STREAM_STATE_QOS:
+ break;
+ default:
+ return false;
+ }
+ }
+
+ if (ep->dir != match->rpac->type)
+ return false;
+
+ switch (match->lpac->type) {
+ case BT_BAP_SOURCE:
+ if (ep->dir != BT_BAP_SINK)
+ return false;
+ break;
+ case BT_BAP_SINK:
+ if (ep->dir != BT_BAP_SOURCE)
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
static struct bt_bap_stream *bap_ucast_stream_new(struct bt_bap *bap,
struct bt_bap_pac *lpac,
struct bt_bap_pac *rpac,
match.lpac = lpac;
match.rpac = rpac;
- /* Check for existing stream */
- ep = queue_find(bap->remote_eps, find_ep_pacs, &match);
+ /* Get free ASE */
+ ep = queue_find(bap->remote_eps, find_ep_ucast, &match);
if (!ep) {
- /* Check for unused ASE */
- ep = queue_find(bap->remote_eps, find_ep_unused, &match);
- if (!ep) {
- DBG(bap, "Unable to find unused ASE");
- return NULL;
- }
+ DBG(bap, "Unable to find usable ASE");
+ return NULL;
}
stream = ep->stream;
- if (!stream)
+ if (stream) {
+ /* Replace lpac: the stream generally needs to be reconfigured
+ * after this, otherwise things like codec config not match.
+ */
+ bap_stream_clear_cfm(stream);
+ stream->lpac = lpac;
+ util_iov_free(stream->cc, 1);
+ stream->cc = util_iov_dup(data, 1);
+ stream->need_reconfig = true;
+ } else {
stream = bap_stream_new(bap, ep, lpac, rpac, data, true);
+ }
return stream;
}
return bap_bcast_stream_new(bap, lpac, pqos, data);
}
+void bt_bap_stream_lock(struct bt_bap_stream *stream)
+{
+ if (!stream || !stream->client)
+ return;
+
+ /* Reserve stream ASE for use by upper level, so it won't get
+ * reallocated
+ */
+ stream->locked = true;
+}
+
+void bt_bap_stream_unlock(struct bt_bap_stream *stream)
+{
+ if (!stream || !stream->client)
+ return;
+
+ stream->locked = false;
+}
+
struct bt_bap *bt_bap_stream_get_session(struct bt_bap_stream *stream)
{
if (!stream)
diff --git a/src/shared/bap.h b/src/shared/bap.h
index d105814..fba8b6b 100644
--- a/src/shared/bap.h
+++ b/src/shared/bap.h
struct bt_bap_qos *pqos,
struct iovec *data);
+void bt_bap_stream_lock(struct bt_bap_stream *stream);
+void bt_bap_stream_unlock(struct bt_bap_stream *stream);
+
struct bt_bap *bt_bap_stream_get_session(struct bt_bap_stream *stream);
uint8_t bt_bap_stream_get_state(struct bt_bap_stream *stream);