From 9f97b433ddc704d3729af45a9eb46976e09afc9c Mon Sep 17 00:00:00 2001 From: Szymon Czapracki Date: Thu, 6 Oct 2022 12:57:38 +0200 Subject: [PATCH] Bluetooth: Audio: Fix ASE race condition This patch fixes invalid ASE state transition, ASE now waits for Receiver Start Ready before going into Streaming state. Signed-off-by: Szymon Czapracki --- subsys/bluetooth/audio/ascs.c | 55 ++++++++++++++++++++++--------- subsys/bluetooth/audio/endpoint.h | 3 ++ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/subsys/bluetooth/audio/ascs.c b/subsys/bluetooth/audio/ascs.c index 045439efb6b02..e5c4decb80de7 100644 --- a/subsys/bluetooth/audio/ascs.c +++ b/subsys/bluetooth/audio/ascs.c @@ -18,6 +18,7 @@ #include #include #include +#include "zephyr/bluetooth/iso.h" #include #include @@ -240,6 +241,7 @@ void ascs_ep_set_state(struct bt_audio_ep *ep, uint8_t state) switch (old_state) { case BT_AUDIO_EP_STATE_ENABLING: case BT_AUDIO_EP_STATE_STREAMING: + ep->receiver_ready = false; break; default: BT_ASSERT_MSG(false, @@ -268,6 +270,7 @@ void ascs_ep_set_state(struct bt_audio_ep *ep, uint8_t state) case BT_AUDIO_EP_STATE_QOS_CONFIGURED: case BT_AUDIO_EP_STATE_ENABLING: case BT_AUDIO_EP_STATE_STREAMING: + ep->receiver_ready = false; break; case BT_AUDIO_EP_STATE_DISABLING: if (ep->dir == BT_AUDIO_DIR_SOURCE) { @@ -477,6 +480,21 @@ static void ascs_iso_sent(struct bt_iso_chan *chan) } } +static int ase_stream_start(struct bt_audio_stream *stream) +{ + int err = 0; + + if (unicast_server_cb != NULL && unicast_server_cb->start != NULL) { + err = unicast_server_cb->start(stream); + } else { + err = -ENOTSUP; + } + + ascs_ep_set_state(stream->ep, BT_AUDIO_EP_STATE_STREAMING); + + return err; +} + static void ascs_iso_connected(struct bt_iso_chan *chan) { struct bt_audio_iso *audio_iso = CONTAINER_OF(chan, struct bt_audio_iso, @@ -485,6 +503,7 @@ static void ascs_iso_connected(struct bt_iso_chan *chan) struct bt_audio_stream *sink_stream = audio_iso->sink_stream; struct bt_audio_stream *stream; struct bt_audio_ep *ep; + int err; if (sink_stream != NULL && sink_stream->iso == chan) { stream = sink_stream; @@ -512,7 +531,14 @@ static void ascs_iso_connected(struct bt_iso_chan *chan) return; } - ascs_ep_set_state(ep, BT_AUDIO_EP_STATE_STREAMING); + if (ep->dir == BT_AUDIO_DIR_SOURCE && !ep->receiver_ready) { + return; + } + + err = ase_stream_start(stream); + if (err) { + BT_ERR("Could not start stream %d", err); + } } static void ascs_iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) @@ -2037,7 +2063,6 @@ static void ase_start(struct bt_ascs_ase *ase) { struct bt_audio_stream *stream; struct bt_audio_ep *ep; - int err; BT_DBG("ase %p", ase); @@ -2045,9 +2070,8 @@ static void ase_start(struct bt_ascs_ase *ase) /* Valid for an ASE only if ASE_State field = 0x02 (QoS Configured) */ if (ep->status.state != BT_AUDIO_EP_STATE_ENABLING) { - err = -EBADMSG; BT_WARN("Invalid operation in state: %s", bt_audio_ep_state_str(ep->status.state)); - ascs_cp_rsp_add_errno(ASE_ID(ase), BT_ASCS_START_OP, err, + ascs_cp_rsp_add_errno(ASE_ID(ase), BT_ASCS_START_OP, -EBADMSG, BT_ASCS_REASON_NONE); return; } @@ -2065,22 +2089,21 @@ static void ase_start(struct bt_ascs_ase *ase) return; } + ep->receiver_ready = true; + stream = ep->stream; - if (unicast_server_cb != NULL && unicast_server_cb->start != NULL) { - err = unicast_server_cb->start(stream); - } else { - err = -ENOTSUP; - } + if (stream->iso->state == BT_ISO_STATE_CONNECTED) { + int err; - if (err) { - BT_ERR("Start failed: %d", err); - ascs_cp_rsp_add(ASE_ID(ase), BT_ASCS_START_OP, err, - BT_ASCS_REASON_NONE); - return; + err = ase_stream_start(stream); + if (err) { + BT_ERR("Start failed: %d", err); + ascs_cp_rsp_add(ASE_ID(ase), BT_ASCS_START_OP, err, + BT_ASCS_REASON_NONE); + return; + } } - ascs_ep_set_state(ep, BT_AUDIO_EP_STATE_STREAMING); - ascs_cp_rsp_success(ASE_ID(ase), BT_ASCS_START_OP); } diff --git a/subsys/bluetooth/audio/endpoint.h b/subsys/bluetooth/audio/endpoint.h index 3b18253330240..a5a2e3c95b17e 100644 --- a/subsys/bluetooth/audio/endpoint.h +++ b/subsys/bluetooth/audio/endpoint.h @@ -62,6 +62,9 @@ struct bt_audio_ep { struct bt_gatt_subscribe_params subscribe; struct bt_gatt_discover_params discover; + /* FIXME: Replace with metastate */ + bool receiver_ready; + /* TODO: Consider client/server container split */ union { struct {