From bac077c96b67c8db8df76a49f68f4493db39fc61 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Wed, 15 Oct 2025 18:40:12 +0300 Subject: [PATCH] transport: wait until BAP fd is writable/readable before resuming Connection may still be pending when entering STREAMING. Wait until the fd becomes readable/writable before continuing. --- profiles/audio/transport.c | 69 ++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c index 83e3c9791..08ed699b2 100644 --- a/profiles/audio/transport.c +++ b/profiles/audio/transport.c @@ -108,6 +108,7 @@ struct bap_transport { struct bt_bap_qos qos; guint resume_id; struct iovec *meta; + guint chan_id; }; struct media_transport_ops { @@ -2098,10 +2099,20 @@ static guint transport_bap_suspend(struct media_transport *transport, return id; } +static void bap_clear_chan(struct bap_transport *bap) +{ + if (bap->chan_id) { + g_source_remove(bap->chan_id); + bap->chan_id = 0; + } +} + static void transport_bap_cancel(struct media_transport *transport, guint id) { struct bap_transport *bap = transport->data; + bap_clear_chan(bap); + if (id == bap->resume_id && bap->resume_id) { g_source_remove(bap->resume_id); bap->resume_id = 0; @@ -2162,6 +2173,38 @@ static void bap_metadata_changed(struct media_transport *transport) } } +static gboolean bap_transport_fd_ready(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + struct media_transport *transport = data; + struct bap_transport *bap = transport->data; + int fd; + uint16_t imtu, omtu; + GError *err = NULL; + + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) { + error("Transport connection failed"); + goto done; + } + + if (!bt_io_get(chan, &err, BT_IO_OPT_OMTU, &omtu, + BT_IO_OPT_IMTU, &imtu, + BT_IO_OPT_INVALID)) { + error("%s", err->message); + goto done; + } + + fd = g_io_channel_unix_get_fd(chan); + media_transport_set_fd(transport, fd, imtu, omtu); + transport_update_playing(transport, TRUE); + +done: + bap->chan_id = 0; + bap_resume_complete(transport); + + return FALSE; +} + static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state, uint8_t new_state, void *user_data) { @@ -2170,9 +2213,7 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state, struct media_owner *owner = transport->owner; struct io *io; GIOChannel *chan; - GError *err = NULL; int fd; - uint16_t imtu, omtu; if (bap->stream != stream) return; @@ -2209,7 +2250,6 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state, bap_update_bcast_qos(transport); bap_metadata_changed(transport); - transport_update_playing(transport, TRUE); break; case BT_BAP_STREAM_STATE_RELEASING: if (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SINK) @@ -2231,21 +2271,20 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state, goto done; } - chan = g_io_channel_unix_new(fd); - - if (!bt_io_get(chan, &err, BT_IO_OPT_OMTU, &omtu, - BT_IO_OPT_IMTU, &imtu, - BT_IO_OPT_INVALID)) { - error("%s", err->message); - goto done; - } + /* Wait for FD to become ready */ + bap_clear_chan(bap); + chan = g_io_channel_unix_new(fd); + bap->chan_id = g_io_add_watch(chan, + G_IO_OUT | G_IO_IN | + G_IO_HUP | G_IO_ERR | G_IO_NVAL, + bap_transport_fd_ready, transport); g_io_channel_unref(chan); - - media_transport_set_fd(transport, fd, imtu, omtu); - transport_update_playing(transport, TRUE); + if (bap->chan_id) + return; done: + bap_clear_chan(bap); bap_resume_complete(transport); } @@ -2287,6 +2326,8 @@ static void transport_bap_destroy(void *data) { struct bap_transport *bap = data; + bap_clear_chan(bap); + util_iov_free(bap->meta, 1); bt_bap_state_unregister(bt_bap_stream_get_session(bap->stream), bap->state_id); -- 2.47.3