From: Kyle Pepper <cochcoder@proton.me>
To: linux-bluetooth@vger.kernel.org
Cc: Marcel Holtmann <marcel@holtmann.org>,
Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Subject: [PATCH] shared/asha: prime volume before starting audio
Date: Tue, 13 Oct 2026 03:46:27 +0000 [thread overview]
Message-ID: <20261013034613.516771-1-cochcoder@proton.me> (raw)
Some tested renderers remain silent unless the Volume characteristic is
written before START. Prime it with the selected volume and keep the
write best effort.
Test volume-before-START ordering and best-effort failure handling.
Assisted-by: OpenCode:gpt-6.1-sol
---
Submission review notes (not part of the commit message):
Local validation is for base 7428ca2df9356363079db0f48412c20cbdb9471f.
Compatibility with newer upstream tips has not been verified locally.
N8 startup evidence is from the combined downstream stack, not a
volume-only hardware ablation. Native ordering/failure unit tests are
included; other renderer coverage and human contribution review remain.
.gitignore | 1 +
Makefile.am | 6 +++
src/shared/asha.c | 4 ++
unit/test-asha-start.c | 99 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 110 insertions(+)
create mode 100644 unit/test-asha-start.c
diff --git a/.gitignore b/.gitignore
index 06b24735df..adff1ea84a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -112,6 +112,7 @@ unit/test-lib
unit/test-mgmt
unit/test-uhid
unit/test-hfp
+unit/test-asha-start
unit/test-crypto
unit/test-ecc
unit/test-hog
diff --git a/Makefile.am b/Makefile.am
index f742458d11..a56d66873b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -706,6 +706,12 @@ unit_test_avrcp_LDADD = lib/libbluetooth-internal.la \
unit_tests += unit/test-hfp
+unit_tests += unit/test-asha-start
+
+unit_test_asha_start_SOURCES = unit/test-asha-start.c
+unit_test_asha_start_LDADD = src/libshared-glib.la \
+ lib/libbluetooth-internal.la $(GLIB_LIBS)
+
unit_test_hfp_SOURCES = unit/test-hfp.c
unit_test_hfp_LDADD = src/libshared-glib.la $(GLIB_LIBS)
diff --git a/src/shared/asha.c b/src/shared/asha.c
index 79bb29bf9a..b5e8d67567 100644
--- a/src/shared/asha.c
+++ b/src/shared/asha.c
@@ -262,6 +262,10 @@ unsigned int bt_asha_start(struct bt_asha *asha, bt_asha_cb_t cb,
return 0;
}
+ /* Some renderers require a Volume write before START. */
+ if (!bt_asha_set_volume(asha, asha->volume))
+ DBG("ASHA volume priming failed, continuing with START");
+
ret = asha_send_acp(asha, acp_start_cmd, sizeof(acp_start_cmd), cb,
user_data);
if (ret < 0)
diff --git a/unit/test-asha-start.c b/unit/test-asha-start.c
new file mode 100644
index 0000000000..49df54c1f3
--- /dev/null
+++ b/unit/test-asha-start.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+#include <assert.h>
+
+/* Source-level mocks remain effective with link-time optimization. */
+#define bt_gatt_client_write_without_response test_write_command
+#define bt_gatt_client_write_value test_write_request
+#include "src/shared/asha.c"
+#undef bt_gatt_client_write_without_response
+#undef bt_gatt_client_write_value
+#include "src/shared/tester.h"
+
+static unsigned int commands, requests;
+static bool volume_ok, start_ok;
+static int8_t selected_volume;
+
+void btd_error(uint16_t index, const char *format, ...)
+{
+}
+
+void btd_debug(uint16_t index, const char *format, ...)
+{
+}
+
+unsigned int test_write_command(struct bt_gatt_client *client, uint16_t handle,
+ bool signed_write,
+ const uint8_t *value, uint16_t length)
+{
+ assert(client && handle == 0x82 && !signed_write);
+ assert(length == 1 && (int8_t) value[0] == selected_volume);
+ assert(requests == 0);
+ commands++;
+ return volume_ok;
+}
+
+unsigned int test_write_request(struct bt_gatt_client *client, uint16_t handle,
+ const uint8_t *value, uint16_t length,
+ bt_gatt_client_callback_t callback, void *data,
+ bt_gatt_client_destroy_func_t destroy)
+{
+ assert(client && handle == 0x79);
+ assert(commands == 1 && requests == 0);
+ assert(length == 5 && value[0] == 0x01 && value[1] == 0x01);
+ assert((int8_t) value[3] == selected_volume);
+ assert(callback && data && !destroy);
+ requests++;
+ return start_ok;
+}
+
+static void test_start(const void *user_data)
+{
+ const int8_t volumes[] = { -128, -127, -64, 0 };
+ unsigned int i, fail;
+
+ for (i = 0; i < ARRAY_SIZE(volumes); i++) {
+ for (fail = 0; fail < 2; fail++) {
+ struct bt_asha asha = {
+ .client = (void *) 1, .acp_handle = 0x79,
+ .volume_handle = 0x82, .volume = volumes[i],
+ };
+
+ selected_volume = volumes[i];
+ commands = requests = 0;
+ volume_ok = !fail;
+ start_ok = true;
+ assert(bt_asha_start(&asha, NULL, NULL) == 0);
+ assert(commands == 1 && requests == 1);
+ assert(asha.state == ASHA_STARTING);
+ assert(asha.volume == selected_volume);
+
+ /* A repeated start must not write the volume again. */
+ bt_asha_start(&asha, NULL, NULL);
+ assert(commands == 1 && requests == 1);
+ }
+ }
+
+ {
+ struct bt_asha asha = {
+ .client = (void *) 1, .acp_handle = 0x79,
+ .volume_handle = 0x82, .volume = -64,
+ };
+
+ commands = requests = 0;
+ selected_volume = asha.volume;
+ volume_ok = true;
+ start_ok = false;
+ assert(bt_asha_start(&asha, NULL, NULL) == (unsigned int) -1);
+ assert(asha.state == ASHA_STOPPED);
+ assert(commands == 1 && requests == 1);
+ }
+
+ tester_test_passed();
+}
+
+int main(int argc, char *argv[])
+{
+ tester_init(&argc, &argv);
+ tester_add("ASHA/start/volume", NULL, NULL, test_start, NULL);
+ return tester_run();
+}
base-commit: 7428ca2df9356363079db0f48412c20cbdb9471f
next reply other threads:[~2026-10-13 3:46 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 3:46 Kyle Pepper [this message]
2026-10-13 5:03 ` shared/asha: prime volume before starting audio bluez.test.bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261013034613.516771-1-cochcoder@proton.me \
--to=cochcoder@proton.me \
--cc=linux-bluetooth@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=marcel@holtmann.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox