Skip to content

Commit 9f97b43

Browse files
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 <[email protected]>
1 parent 40a6f08 commit 9f97b43

File tree

2 files changed

+42
-16
lines changed

2 files changed

+42
-16
lines changed

subsys/bluetooth/audio/ascs.c

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <zephyr/bluetooth/bluetooth.h>
1919
#include <zephyr/bluetooth/conn.h>
2020
#include <zephyr/bluetooth/gatt.h>
21+
#include "zephyr/bluetooth/iso.h"
2122
#include <zephyr/bluetooth/audio/audio.h>
2223
#include <zephyr/bluetooth/audio/capabilities.h>
2324

@@ -240,6 +241,7 @@ void ascs_ep_set_state(struct bt_audio_ep *ep, uint8_t state)
240241
switch (old_state) {
241242
case BT_AUDIO_EP_STATE_ENABLING:
242243
case BT_AUDIO_EP_STATE_STREAMING:
244+
ep->receiver_ready = false;
243245
break;
244246
default:
245247
BT_ASSERT_MSG(false,
@@ -268,6 +270,7 @@ void ascs_ep_set_state(struct bt_audio_ep *ep, uint8_t state)
268270
case BT_AUDIO_EP_STATE_QOS_CONFIGURED:
269271
case BT_AUDIO_EP_STATE_ENABLING:
270272
case BT_AUDIO_EP_STATE_STREAMING:
273+
ep->receiver_ready = false;
271274
break;
272275
case BT_AUDIO_EP_STATE_DISABLING:
273276
if (ep->dir == BT_AUDIO_DIR_SOURCE) {
@@ -477,6 +480,21 @@ static void ascs_iso_sent(struct bt_iso_chan *chan)
477480
}
478481
}
479482

483+
static int ase_stream_start(struct bt_audio_stream *stream)
484+
{
485+
int err = 0;
486+
487+
if (unicast_server_cb != NULL && unicast_server_cb->start != NULL) {
488+
err = unicast_server_cb->start(stream);
489+
} else {
490+
err = -ENOTSUP;
491+
}
492+
493+
ascs_ep_set_state(stream->ep, BT_AUDIO_EP_STATE_STREAMING);
494+
495+
return err;
496+
}
497+
480498
static void ascs_iso_connected(struct bt_iso_chan *chan)
481499
{
482500
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)
485503
struct bt_audio_stream *sink_stream = audio_iso->sink_stream;
486504
struct bt_audio_stream *stream;
487505
struct bt_audio_ep *ep;
506+
int err;
488507

489508
if (sink_stream != NULL && sink_stream->iso == chan) {
490509
stream = sink_stream;
@@ -512,7 +531,14 @@ static void ascs_iso_connected(struct bt_iso_chan *chan)
512531
return;
513532
}
514533

515-
ascs_ep_set_state(ep, BT_AUDIO_EP_STATE_STREAMING);
534+
if (ep->dir == BT_AUDIO_DIR_SOURCE && !ep->receiver_ready) {
535+
return;
536+
}
537+
538+
err = ase_stream_start(stream);
539+
if (err) {
540+
BT_ERR("Could not start stream %d", err);
541+
}
516542
}
517543

518544
static void ascs_iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
@@ -2037,17 +2063,15 @@ static void ase_start(struct bt_ascs_ase *ase)
20372063
{
20382064
struct bt_audio_stream *stream;
20392065
struct bt_audio_ep *ep;
2040-
int err;
20412066

20422067
BT_DBG("ase %p", ase);
20432068

20442069
ep = &ase->ep;
20452070

20462071
/* Valid for an ASE only if ASE_State field = 0x02 (QoS Configured) */
20472072
if (ep->status.state != BT_AUDIO_EP_STATE_ENABLING) {
2048-
err = -EBADMSG;
20492073
BT_WARN("Invalid operation in state: %s", bt_audio_ep_state_str(ep->status.state));
2050-
ascs_cp_rsp_add_errno(ASE_ID(ase), BT_ASCS_START_OP, err,
2074+
ascs_cp_rsp_add_errno(ASE_ID(ase), BT_ASCS_START_OP, -EBADMSG,
20512075
BT_ASCS_REASON_NONE);
20522076
return;
20532077
}
@@ -2065,22 +2089,21 @@ static void ase_start(struct bt_ascs_ase *ase)
20652089
return;
20662090
}
20672091

2092+
ep->receiver_ready = true;
2093+
20682094
stream = ep->stream;
2069-
if (unicast_server_cb != NULL && unicast_server_cb->start != NULL) {
2070-
err = unicast_server_cb->start(stream);
2071-
} else {
2072-
err = -ENOTSUP;
2073-
}
2095+
if (stream->iso->state == BT_ISO_STATE_CONNECTED) {
2096+
int err;
20742097

2075-
if (err) {
2076-
BT_ERR("Start failed: %d", err);
2077-
ascs_cp_rsp_add(ASE_ID(ase), BT_ASCS_START_OP, err,
2078-
BT_ASCS_REASON_NONE);
2079-
return;
2098+
err = ase_stream_start(stream);
2099+
if (err) {
2100+
BT_ERR("Start failed: %d", err);
2101+
ascs_cp_rsp_add(ASE_ID(ase), BT_ASCS_START_OP, err,
2102+
BT_ASCS_REASON_NONE);
2103+
return;
2104+
}
20802105
}
20812106

2082-
ascs_ep_set_state(ep, BT_AUDIO_EP_STATE_STREAMING);
2083-
20842107
ascs_cp_rsp_success(ASE_ID(ase), BT_ASCS_START_OP);
20852108
}
20862109

subsys/bluetooth/audio/endpoint.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ struct bt_audio_ep {
6262
struct bt_gatt_subscribe_params subscribe;
6363
struct bt_gatt_discover_params discover;
6464

65+
/* FIXME: Replace with metastate */
66+
bool receiver_ready;
67+
6568
/* TODO: Consider client/server container split */
6669
union {
6770
struct {

0 commit comments

Comments
 (0)