Skip to content

Commit 64143fc

Browse files
Thalleycarlescufi
authored andcommitted
Bluetooth: BAP: unicast released callback only after CIS disconnect
Ensure that the stream released callback is only called after the CIS has disconnected. Since the ACL disconnect event may come before the CIS disconnect event, we use the unicast_client_ep_idle_state in the unicast_client_reset function to use the existing state verification, and only after both the ACL and CIS has disconnected, we finalize the reset of the stream and call the released callback, assuming that the CIS can be disconnected. Signed-off-by: Emil Gydesen <[email protected]>
1 parent bb43c05 commit 64143fc

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

subsys/bluetooth/audio/bap_unicast_client.c

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ static int unicast_client_ep_set_codec(struct bt_bap_ep *ep, uint8_t id, uint16_
9797
static int unicast_client_ep_start(struct bt_bap_ep *ep,
9898
struct net_buf_simple *buf);
9999

100+
static void unicast_client_reset(struct bt_bap_ep *ep);
101+
100102
static int unicast_client_send_start(struct bt_bap_ep *ep)
101103
{
102104
if (ep->receiver_ready != true || ep->dir != BT_AUDIO_DIR_SOURCE) {
@@ -133,7 +135,7 @@ static int unicast_client_send_start(struct bt_bap_ep *ep)
133135
return 0;
134136
}
135137

136-
static void unicast_client_ep_idle_state(struct bt_bap_ep *ep);
138+
static int unicast_client_ep_idle_state(struct bt_bap_ep *ep);
137139

138140
/** Checks if the stream can terminate the CIS
139141
*
@@ -347,7 +349,21 @@ static void unicast_client_ep_iso_disconnected(struct bt_bap_ep *ep, uint8_t rea
347349
* the ISO has finalized the disconnection
348350
*/
349351
if (ep->status.state == BT_BAP_EP_STATE_IDLE) {
350-
unicast_client_ep_idle_state(ep);
352+
353+
(void)unicast_client_ep_idle_state(ep);
354+
355+
if (stream->conn != NULL) {
356+
struct bt_conn_info conn_info;
357+
int err;
358+
359+
err = bt_conn_get_info(stream->conn, &conn_info);
360+
if (err != 0 || conn_info.state == BT_CONN_STATE_DISCONNECTED) {
361+
/* Retrigger the reset of the EP if the ACL is disconnected before
362+
* the ISO is disconnected
363+
*/
364+
unicast_client_reset(ep);
365+
}
366+
}
351367
} else {
352368
if (stream->ops != NULL && stream->ops->stopped != NULL) {
353369
stream->ops->stopped(stream, reason);
@@ -513,29 +529,32 @@ static struct bt_bap_ep *unicast_client_ep_get(struct bt_conn *conn, enum bt_aud
513529
return unicast_client_ep_new(conn, dir, handle);
514530
}
515531

516-
static void unicast_client_ep_idle_state(struct bt_bap_ep *ep)
532+
static int unicast_client_ep_idle_state(struct bt_bap_ep *ep)
517533
{
518534
struct bt_bap_unicast_client_ep *client_ep =
519535
CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
520536
struct bt_bap_stream *stream = ep->stream;
521537
const struct bt_bap_stream_ops *ops;
522538

523539
if (stream == NULL) {
524-
return;
540+
return -EINVAL;
525541
}
526542

527543
/* If CIS is connected, disconnect and wait for CIS disconnection */
528544
if (unicast_client_can_disconnect_stream(stream)) {
529-
const int err = bt_bap_stream_disconnect(stream);
545+
int err;
546+
547+
LOG_DBG("Disconnecting stream");
548+
err = bt_bap_stream_disconnect(stream);
530549

531550
if (err != 0) {
532551
LOG_ERR("Failed to disconnect stream: %d", err);
533-
} else {
534-
return;
535552
}
553+
554+
return err;
536555
} else if (ep->iso != NULL && ep->iso->chan.state == BT_ISO_STATE_DISCONNECTING) {
537556
/* Wait */
538-
return;
557+
return -EBUSY;
539558
}
540559

541560
bt_bap_stream_reset(stream);
@@ -560,6 +579,8 @@ static void unicast_client_ep_idle_state(struct bt_bap_ep *ep)
560579
} else {
561580
LOG_WRN("No callback for released set");
562581
}
582+
583+
return 0;
563584
}
564585

565586
static void unicast_client_ep_qos_update(struct bt_bap_ep *ep,
@@ -910,7 +931,7 @@ static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_si
910931

911932
switch (status->state) {
912933
case BT_BAP_EP_STATE_IDLE:
913-
unicast_client_ep_idle_state(ep);
934+
(void)unicast_client_ep_idle_state(ep);
914935
break;
915936
case BT_BAP_EP_STATE_CODEC_CONFIGURED:
916937
switch (old_state) {
@@ -1751,24 +1772,22 @@ static void unicast_client_reset(struct bt_bap_ep *ep)
17511772
{
17521773
struct bt_bap_unicast_client_ep *client_ep =
17531774
CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
1754-
struct bt_bap_stream *stream = ep->stream;
1775+
int err;
17551776

17561777
LOG_DBG("ep %p", ep);
17571778

1758-
if (stream != NULL && ep->status.state != BT_BAP_EP_STATE_IDLE) {
1759-
const struct bt_bap_stream_ops *ops;
1779+
/* Pretend we received an idle state notification from the server to trigger all cleanup */
1780+
ep->status.state = BT_BAP_EP_STATE_IDLE;
1781+
err = unicast_client_ep_idle_state(ep);
1782+
if (err != 0) {
1783+
LOG_DBG("unicast_client_ep_idle_state returned %d", err);
17601784

1761-
/* Notify upper layer */
1762-
ops = stream->ops;
1763-
if (ops != NULL && ops->released != NULL) {
1764-
ops->released(stream);
1765-
} else {
1766-
LOG_WRN("No callback for released set");
1785+
if (err == -EBUSY) {
1786+
/* Wait for ISO disconnected event */
1787+
return;
17671788
}
17681789
}
17691790

1770-
bt_bap_stream_reset(stream);
1771-
17721791
(void)memset(ep, 0, sizeof(*ep));
17731792

17741793
client_ep->cp_handle = 0U;

0 commit comments

Comments
 (0)