Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] shared/asha: prime volume before starting audio
@ 2026-10-13  3:46 Kyle Pepper
  2026-10-13  5:03 ` bluez.test.bot
  0 siblings, 1 reply; 2+ messages in thread
From: Kyle Pepper @ 2026-10-13  3:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Marcel Holtmann, Luiz Augusto von Dentz

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


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* RE: shared/asha: prime volume before starting audio
  2026-10-13  3:46 [PATCH] shared/asha: prime volume before starting audio Kyle Pepper
@ 2026-10-13  5:03 ` bluez.test.bot
  0 siblings, 0 replies; 2+ messages in thread
From: bluez.test.bot @ 2026-10-13  5:03 UTC (permalink / raw)
  To: linux-bluetooth, cochcoder

[-- Attachment #1: Type: text/plain, Size: 3430 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1184354/

---Test result---

Test Summary:
CheckPatch                    PASS      0.47 seconds
GitLint                       PASS      0.27 seconds
BuildEll                      PASS      19.44 seconds
BluezMake                     PASS      291.44 seconds
MakeCheck                     PASS      14.18 seconds
MakeDistcheck                 PASS      145.25 seconds
CheckValgrind                 PASS      231.58 seconds
CheckSmatch                   PASS      290.49 seconds
bluezmakeextell               PASS      93.58 seconds
TestFunctional                FAIL      1198.04 seconds
IncrementalBuild              PASS      293.18 seconds
ScanBuild                     PASS      1131.33 seconds

Details
##############################
Test: TestFunctional - FAIL
Desc: Run test-functional
Output:
FAIL functional.test_bluetoothctl::test_bluetoothctl_pair_bredr[hosts15-vm2]: pytest_bluezenv.rpc.RemoteError: <pexpect.popen_spawn.PopenSpawn object at 0x7f9674e9e510>
    searcher: searcher_re:
        0: re.compile(b'Changing pairable on succeeded')
    <pexpect.popen_spawn.PopenSpawn object at 0x7f9674e9e510>
    searcher: searcher_re:
        0: re.compile(b'Changing pairable on succeeded')
    Remote traceback:
        Traceback (most recent call last):
          File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream
            result = method(*msg["a"], **msg["kw"])
          File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 256, in call_plugin
            return getattr(self.plugins[name], method)(*a, **kw)
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
          File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/host_plugins.py", line 502, in expect
            ret = self.ctl.expect(*a, **kw)
          File "/usr/lib/python3/dist-packages/pexpect/spawnbase.py", line 354, in expect
            return self.expect_list(compiled_pattern_list,
                   ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
                    timeout, searchwindowsize, async_)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/usr/lib/python3/dist-packages/pexpect/spawnbase.py", line 383, in expect_list
            return exp.expect_loop(timeout)
                   ~~~~~~~~~~~~~~~^^^^^^^^^
          File "/usr/lib/python3/dist-packages/pexpect/expect.py", line 181, in expect_loop
            return self.timeout(e)
                   ~~~~~~~~~~~~^^^
          File "/usr/lib/python3/dist-packages/pexpect/expect.py", line 144, in timeout
            raise exc
        pexpect.exceptions.TIMEOUT: <pexpect.popen_spawn.PopenSpawn object at 0x7f9674e9e510>
        searcher: searcher_re:
            0: re.compile(b'Changing pairable on succeeded')
        <pexpect.popen_spawn.PopenSpawn object at 0x7f9674e9e510>
        searcher: searcher_re:
            0: re.compile(b'Changing pairable on succeeded')
FAIL functional.test_hog::test_hog[sci-hosts18-vm2]: pytest_bluezenv.rpc.RemoteTimeoutError: Connection recv timed out


https://github.com/bluez/bluez/pull/2665

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-13  5:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13  3:46 [PATCH] shared/asha: prime volume before starting audio Kyle Pepper
2026-10-13  5:03 ` bluez.test.bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox