summaryrefslogtreecommitdiff
path: root/net-wireless/bluez/files/bluez-5.68-bap-resume.patch
diff options
context:
space:
mode:
Diffstat (limited to 'net-wireless/bluez/files/bluez-5.68-bap-resume.patch')
-rw-r--r--net-wireless/bluez/files/bluez-5.68-bap-resume.patch187
1 files changed, 187 insertions, 0 deletions
diff --git a/net-wireless/bluez/files/bluez-5.68-bap-resume.patch b/net-wireless/bluez/files/bluez-5.68-bap-resume.patch
new file mode 100644
index 000000000000..fbc2eeda89cc
--- /dev/null
+++ b/net-wireless/bluez/files/bluez-5.68-bap-resume.patch
@@ -0,0 +1,187 @@
+From 466fce0209a3878512672159168943047a9e2323 Mon Sep 17 00:00:00 2001
+From: Pauli Virtanen <pav@iki.fi>
+Date: Sun, 2 Jul 2023 22:34:18 +0300
+Subject: transport: handle BAP Enabling state correctly when resuming
+
+If BAP stream is in Enabling state when transport acquire is attempted,
+we should wait for bap_state_changed to emit the completion event.
+
+transport->resume() is only called with new owner with no
+owner->pending, and shall return nonzero completion id on success.
+Currently if BAP stream is Enabling, it returns zero which fails the
+acquire operation.
+
+To fix this, return valid completion id in this case instead. Also keep
+track of the g_idle_add resume id, so that we don't try to give it to
+bt_bap_stream_cancel.
+
+Fixes sound server getting spurious Not Authorized errors when trying to
+acquire a pending transport. This can happen on BAP server: linked
+transports become pending when the first of the two enters Streaming. If
+sound server tries to acquire the other linked transport whose stream is
+still Enabling, the acquire fails (media_owner_free +
+btd_error_not_authorized).
+
+Log:
+===============================================================
+profiles/audio/transport.c:bap_state_changed() stream 0x25c2880: qos(2) -> enabling(3)
+...
+profiles/audio/transport.c:bap_state_changed() stream 0x25cc590: qos(2) -> enabling(3)
+...
+src/shared/bap.c:bap_stream_state_changed() stream 0x25cc590 dir 0x01: enabling -> streaming
+profiles/audio/bap.c:bap_state() stream 0x25cc590: enabling(3) -> streaming(4)
+profiles/audio/transport.c:bap_state_changed() stream 0x25cc590: enabling(3) -> streaming(4)
+/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/fd1: fd(36) ready
+profiles/audio/transport.c:transport_update_playing() /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/fd1 State=TRANSPORT_STATE_IDLE Playing=1
+profiles/audio/transport.c:transport_set_state() State changed /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/fd1: TRANSPORT_STATE_IDLE -> TRANSPORT_STATE_PENDING
+profiles/audio/transport.c:transport_set_state() State changed /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/fd0: TRANSPORT_STATE_IDLE -> TRANSPORT_STATE_PENDING
+profiles/audio/transport.c:media_owner_create() Owner created: sender=:1.1242
+profiles/audio/transport.c:media_owner_free() Owner :1.1242
+===============================================================
+---
+ profiles/audio/transport.c | 67 +++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 55 insertions(+), 12 deletions(-)
+
+diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
+index 77216e10b3..aa3a718b0f 100644
+--- a/profiles/audio/transport.c
++++ b/profiles/audio/transport.c
+@@ -86,6 +86,7 @@ struct bap_transport {
+ unsigned int state_id;
+ bool linked;
+ struct bt_bap_qos qos;
++ guint resume_id;
+ };
+
+ struct media_transport {
+@@ -1191,17 +1192,27 @@ static void bap_enable_complete(struct bt_bap_stream *stream,
+ media_transport_remove_owner(owner->transport);
+ }
+
+-static gboolean resume_complete(void *data)
++static void bap_resume_complete(struct media_transport *transport)
+ {
+- struct media_transport *transport = data;
++ struct bap_transport *bap = transport->data;
+ struct media_owner *owner = transport->owner;
+
++ DBG("stream %p owner %p resume complete", bap->stream, owner);
++
++ if (bap->resume_id) {
++ g_source_remove(bap->resume_id);
++ bap->resume_id = 0;
++ }
++
+ if (!owner)
+- return FALSE;
++ return;
++
++ if (owner->pending)
++ owner->pending->id = 0;
+
+ if (transport->fd < 0) {
+ media_transport_remove_owner(transport);
+- return FALSE;
++ return;
+ }
+
+ if (owner->pending) {
+@@ -1215,15 +1226,13 @@ static gboolean resume_complete(void *data)
+ DBUS_TYPE_INVALID);
+ if (!ret) {
+ media_transport_remove_owner(transport);
+- return FALSE;
++ return;
+ }
+ }
+
+ media_owner_remove(owner);
+
+ transport_set_state(transport, TRANSPORT_STATE_ACTIVE);
+-
+- return FALSE;
+ }
+
+ static void bap_update_links(const struct media_transport *transport);
+@@ -1306,6 +1315,32 @@ static void bap_update_qos(const struct media_transport *transport)
+ "Delay");
+ }
+
++static gboolean bap_resume_complete_cb(void *data)
++{
++ struct media_transport *transport = data;
++ struct bap_transport *bap = transport->data;
++
++ bap->resume_id = 0;
++ bap_resume_complete(transport);
++ return FALSE;
++}
++
++static gboolean bap_resume_wait_cb(void *data)
++{
++ struct media_transport *transport = data;
++ struct bap_transport *bap = transport->data;
++ struct media_owner *owner = transport->owner;
++
++ /* bap_state_changed will call completion callback when ready */
++ DBG("stream %p owner %p resume wait", bap->stream, owner);
++
++ bap->resume_id = 0;
++ if (owner && owner->pending)
++ owner->pending->id = 0;
++
++ return FALSE;
++}
++
+ static guint resume_bap(struct media_transport *transport,
+ struct media_owner *owner)
+ {
+@@ -1315,17 +1350,19 @@ static guint resume_bap(struct media_transport *transport,
+
+ if (!bap->stream)
+ return 0;
++ if (bap->resume_id)
++ return 0;
+
+ bap_update_links(transport);
+
+ switch (bt_bap_stream_get_state(bap->stream)) {
+ case BT_BAP_STREAM_STATE_ENABLING:
+ bap_enable_complete(bap->stream, 0x00, 0x00, owner);
+- if (owner->pending)
+- return owner->pending->id;
+- return 0;
++ bap->resume_id = g_idle_add(bap_resume_wait_cb, transport);
++ return bap->resume_id;
+ case BT_BAP_STREAM_STATE_STREAMING:
+- return g_idle_add(resume_complete, transport);
++ bap->resume_id = g_idle_add(bap_resume_complete_cb, transport);
++ return bap->resume_id;
+ }
+
+ meta = bt_bap_stream_get_metadata(bap->stream);
+@@ -1389,6 +1426,12 @@ static void cancel_bap(struct media_transport *transport, guint id)
+ {
+ struct bap_transport *bap = transport->data;
+
++ if (id == bap->resume_id && bap->resume_id) {
++ g_source_remove(bap->resume_id);
++ bap->resume_id = 0;
++ return;
++ }
++
+ if (!bap->stream)
+ return;
+
+@@ -1491,7 +1534,7 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
+ transport_update_playing(transport, TRUE);
+
+ done:
+- resume_complete(transport);
++ bap_resume_complete(transport);
+ }
+
+ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
+--
+cgit
+