Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH v1] arm64: dts: monac-arduino-monza: Add Bluetooth UART node
From: Dmitry Baryshkov @ 2026-04-28 11:26 UTC (permalink / raw)
  To: Shuai Zhang
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel,
	linux-bluetooth, cheng.jiang, quic_chezhou, wei.deng, jinwang.li,
	mengshi.wu, Loic Poulain
In-Reply-To: <20260428025652.662502-1-shuai.zhang@oss.qualcomm.com>

On Tue, Apr 28, 2026 at 10:56:52AM +0800, Shuai Zhang wrote:
> enable bt on monac-arduino-monza
> 
> Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com>
> ---
>  arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> index ca14f0ea4..092ca0b59 100644
> --- a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> +++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> @@ -21,6 +21,7 @@ aliases {
>  		ethernet0 = &ethernet0;
>  		i2c1 = &i2c1;
>  		serial0 = &uart7;
> +		serial1 = &uart10;
>  	};
>  
>  	chosen {
> @@ -454,6 +455,16 @@ &uart7 {
>  	status = "okay";
>  };
>  
> +&uart10 {
> +	status = "okay";
> +	bluetooth: bluetooth {
> +		compatible = "qcom,qca2066-bt";

What powers on this BT device?

> +		max-speed = <3200000>;
> +		enable-gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>;
> +		status = "okay";
> +	};
> +};
> +
>  &usb_1 {
>  	status = "okay";
>  };
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry

^ permalink raw reply

* RE: Add ability to desynchronized transports for PTS tests
From: bluez.test.bot @ 2026-04-28 11:02 UTC (permalink / raw)
  To: linux-bluetooth, frederic.danis
In-Reply-To: <20260428080314.180777-2-frederic.danis@collabora.com>

[-- Attachment #1: Type: text/plain, Size: 1982 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/project/bluetooth/list/?series=1086648

---Test result---

Test Summary:
CheckPatch                    FAIL      1.47 seconds
GitLint                       PASS      0.88 seconds
BuildEll                      PASS      20.32 seconds
BluezMake                     PASS      655.21 seconds
MakeCheck                     PASS      19.02 seconds
MakeDistcheck                 PASS      245.44 seconds
CheckValgrind                 PASS      293.23 seconds
CheckSmatch                   PASS      349.70 seconds
bluezmakeextell               PASS      181.22 seconds
IncrementalBuild              PASS      659.72 seconds
ScanBuild                     PASS      1023.01 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,v2,2/3] doc: Add documentation for CIS transport Desynchronized property
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#73: 
Assisted-by: GPT:GPT-5.3-Codex

ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#73: 
Assisted-by: GPT:GPT-5.3-Codex

/github/workspace/src/patch/14543205.patch total: 1 errors, 1 warnings, 17 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/patch/14543205.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.




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

---
Regards,
Linux Bluetooth


^ permalink raw reply

* [bluez/bluez]
From: BluezTestBot @ 2026-04-28 10:03 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1086318
  Home:   https://github.com/bluez/bluez

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [bluez/bluez] f7a9de: audio: Add ability to desynchronized linked transport
From: fdanis-oss @ 2026-04-28 10:03 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1086648
  Home:   https://github.com/bluez/bluez
  Commit: f7a9de3726b2ee7f68be28b0b1c4b1afbfc24c4f
      https://github.com/bluez/bluez/commit/f7a9de3726b2ee7f68be28b0b1c4b1afbfc24c4f
  Author: Frédéric Danis <frederic.danis@collabora.com>
  Date:   2026-04-28 (Tue, 28 Apr 2026)

  Changed paths:
    M profiles/audio/transport.c

  Log Message:
  -----------
  audio: Add ability to desynchronized linked transport

If bluetoothd is started in testing mode a new Desynchronized property
is added, allowing to prevent automatic acquire of linked transport
objects.

When desynchronized, each transports needs to be acquired separately.

This allows to pass PTS tests BAP/UCL/STR/BV-543-C and BV-546-C.


  Commit: a4a58b50d3fd1cdccc2a0e68c43fa3af4ea55d0a
      https://github.com/bluez/bluez/commit/a4a58b50d3fd1cdccc2a0e68c43fa3af4ea55d0a
  Author: Frédéric Danis <frederic.danis@collabora.com>
  Date:   2026-04-28 (Tue, 28 Apr 2026)

  Changed paths:
    M doc/org.bluez.MediaTransport.rst

  Log Message:
  -----------
  doc: Add documentation for CIS transport Desynchronized property

This is only supported when bluetoothd is started in testing mode.

Assisted-by: GPT:GPT-5.3-Codex


  Commit: 37e8084672bfead40e0922abfa1683ee0878e10b
      https://github.com/bluez/bluez/commit/37e8084672bfead40e0922abfa1683ee0878e10b
  Author: Frédéric Danis <frederic.danis@collabora.com>
  Date:   2026-04-28 (Tue, 28 Apr 2026)

  Changed paths:
    M client/player.c

  Log Message:
  -----------
  client/player: Add support to desynchronize linked transports

After linked transports has been desynchronized, they should be acquired
separately and read handler should only be started for source local
endpoint.

This is used to pass PTS tests BAP/UCL/STR/BV-543-C and BV-546-C.


Compare: https://github.com/bluez/bluez/compare/f7a9de3726b2%5E...37e8084672bf

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* Re: [PATCH v1] arm64: dts: monac-arduino-monza: Add Bluetooth UART node
From: Konrad Dybcio @ 2026-04-28  9:31 UTC (permalink / raw)
  To: Shuai Zhang, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-bluetooth,
	cheng.jiang, quic_chezhou, wei.deng, jinwang.li, mengshi.wu,
	Loic Poulain
In-Reply-To: <20260428025652.662502-1-shuai.zhang@oss.qualcomm.com>

On 4/28/26 4:56 AM, Shuai Zhang wrote:
> enable bt on monac-arduino-monza
> 
> Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com>

This sign-off chain is invalid as-is - should this patch have
"From: Loic"? Who is the author?

> ---
>  arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> index ca14f0ea4..092ca0b59 100644
> --- a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> +++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> @@ -21,6 +21,7 @@ aliases {
>  		ethernet0 = &ethernet0;
>  		i2c1 = &i2c1;
>  		serial0 = &uart7;
> +		serial1 = &uart10;
>  	};
>  
>  	chosen {
> @@ -454,6 +455,16 @@ &uart7 {
>  	status = "okay";
>  };
>  
> +&uart10 {
> +	status = "okay";
> +	bluetooth: bluetooth {

Please keep a \n above the subnode definition

> +		compatible = "qcom,qca2066-bt";
> +		max-speed = <3200000>;
> +		enable-gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>;
> +		status = "okay";

The node is enabled already, because nothing disabled it. Drop the
status line.

Konrad

^ permalink raw reply

* [PATCH BlueZ v2 1/3] audio: Add ability to desynchronized linked transport
From: Frédéric Danis @ 2026-04-28  8:03 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20260428080314.180777-1-frederic.danis@collabora.com>

If bluetoothd is started in testing mode a new Desynchronized property
is added, allowing to prevent automatic acquire of linked transport
objects.

When desynchronized, each transports needs to be acquired separately.

This allows to pass PTS tests BAP/UCL/STR/BV-543-C and BV-546-C.
---
v1->v2: renamed 'desynchronized' to 'desync'

 profiles/audio/transport.c | 116 ++++++++++++++++++++++++++++++++-----
 1 file changed, 103 insertions(+), 13 deletions(-)

diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index 5c2a2777e..39e49ea49 100644
--- a/profiles/audio/transport.c
+++ b/profiles/audio/transport.c
@@ -37,6 +37,7 @@
 #include "src/shared/bap.h"
 #include "src/shared/bass.h"
 #include "src/shared/io.h"
+#include "src/btd.h"
 
 #ifdef HAVE_A2DP
 #include "avdtp.h"
@@ -109,11 +110,18 @@ struct bap_transport {
 	guint			resume_id;
 	struct iovec		*meta;
 	guint			chan_id;
+	bool			desync;
+		/* desync variable is only writable when testing is enabled;
+		 * otherwise, it defaults to false, meaning the Enable/Acquire
+		 * operations synchronize input/output directions that share
+		 * the same ISO socket CID/CIG.
+		 */
 };
 
 struct media_transport_ops {
 	const char *uuid;
 	const GDBusPropertyTable *properties;
+	const GDBusPropertyTable *test_properties;
 	void (*set_owner)(struct media_transport *transport,
 				struct media_owner *owner);
 	void (*remove_owner)(struct media_transport *transport,
@@ -351,7 +359,7 @@ static void transport_bap_remove_owner(struct media_transport *transport,
 {
 	struct bap_transport *bap = transport->data;
 
-	if (bap && bap->linked)
+	if (bap && bap->linked && !bap->desync)
 		queue_foreach(bt_bap_stream_io_get_links(bap->stream),
 				linked_transport_remove_owner, owner);
 }
@@ -729,7 +737,7 @@ static void transport_bap_set_owner(struct media_transport *transport,
 {
 	struct bap_transport *bap = transport->data;
 
-	if (bap && bap->linked)
+	if (bap && bap->linked && !bap->desync)
 		queue_foreach(bt_bap_stream_io_get_links(bap->stream),
 				linked_transport_set_owner, owner);
 }
@@ -1463,6 +1471,59 @@ static void set_links(const GDBusPropertyTable *property,
 	g_dbus_pending_property_success(id);
 }
 
+static gboolean get_desync(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &bap->desync);
+
+	return TRUE;
+}
+
+static void transport_desynchronize(void *data, void *user_data)
+{
+	struct bt_bap_stream *link = data;
+	bool desync = PTR_TO_UINT(user_data);
+	struct media_transport *transport;
+	struct bap_transport *bap;
+
+	transport = find_transport_by_bap_stream(link);
+	bap = transport->data;
+	bap->desync = desync;
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), transport->path,
+						MEDIA_TRANSPORT_INTERFACE,
+						"Desynchronized");
+}
+
+static void set_desync(const GDBusPropertyTable *property,
+			DBusMessageIter *iter, GDBusPendingPropertySet id,
+			void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN) {
+		g_dbus_pending_property_error(id,
+				ERROR_INTERFACE ".InvalidArguments",
+				"Expected BOOLEAN");
+		return;
+	}
+
+	dbus_message_iter_get_basic(iter, &bap->desync);
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), transport->path,
+						MEDIA_TRANSPORT_INTERFACE,
+						"Desynchronized");
+
+	/* Set desynchronized for all the links */
+	queue_foreach(bt_bap_stream_io_get_links(bap->stream),
+					transport_desynchronize,
+					UINT_TO_PTR(bap->desync));
+
+	g_dbus_pending_property_success(id);
+}
+
 static gboolean qos_ucast_exists(const GDBusPropertyTable *property, void *data)
 {
 	struct media_transport *transport = data;
@@ -1486,6 +1547,22 @@ static const GDBusPropertyTable transport_bap_uc_properties[] = {
 	{ }
 };
 
+static const GDBusPropertyTable transport_bap_uc_test_properties[] = {
+	{ "Device", "o", get_device },
+	{ "UUID", "s", get_uuid },
+	{ "Codec", "y", get_codec },
+	{ "Configuration", "ay", get_configuration },
+	{ "State", "s", get_state },
+	{ "QoS", "a{sv}", get_ucast_qos, NULL, qos_ucast_exists },
+	{ "Endpoint", "o", get_endpoint, NULL, endpoint_exists },
+	{ "Location", "u", get_location },
+	{ "Metadata", "ay", get_metadata, set_metadata },
+	{ "Links", "ao", get_links, NULL, links_exists },
+	{ "Volume", "q", get_volume, set_volume, volume_exists },
+	{ "Desynchronized", "b", get_desync, set_desync, links_exists},
+	{ }
+};
+
 static gboolean get_bcast_qos(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -1920,6 +1997,9 @@ static void transport_bap_update_links_uc(
 	g_dbus_emit_property_changed(btd_get_dbus_connection(), transport->path,
 						MEDIA_TRANSPORT_INTERFACE,
 						"Links");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), transport->path,
+						MEDIA_TRANSPORT_INTERFACE,
+						"Desynchronized");
 
 	DBG("stream %p linked %s", bap->stream, bap->linked ? "true" : "false");
 }
@@ -2037,8 +2117,9 @@ static guint transport_bap_resume(struct media_transport *transport,
 		return bap->resume_id;
 	}
 
-	id = bt_bap_stream_enable(bap->stream, bap->linked, NULL,
-					bap_enable_complete, owner);
+	id = bt_bap_stream_enable(bap->stream,
+				bap->desync ? false : bap->linked,
+				NULL, bap_enable_complete, owner);
 	if (!id)
 		return 0;
 
@@ -2161,7 +2242,7 @@ static void transport_bap_set_state(struct media_transport *transport,
 {
 	struct bap_transport *bap = transport->data;
 
-	if (!bap->linked)
+	if (!bap->linked || bap->desync)
 		return;
 
 	/* Update links */
@@ -2540,10 +2621,11 @@ static void *transport_asha_init(struct media_transport *transport, void *data)
 #define TRANSPORT_OPS(_uuid, _props, _set_owner, _remove_owner, _init, \
 		      _resume, _suspend, _cancel, _set_state, _get_stream, \
 		      _get_volume, _set_volume, _set_delay, _update_links, \
-		      _destroy) \
+		      _destroy, _test_props) \
 { \
 	.uuid = _uuid, \
 	.properties = _props, \
+	.test_properties = _test_props, \
 	.set_owner = _set_owner, \
 	.remove_owner = _remove_owner, \
 	.init = _init, \
@@ -2565,26 +2647,28 @@ static void *transport_asha_init(struct media_transport *transport, void *data)
 			transport_a2dp_resume, transport_a2dp_suspend, \
 			transport_a2dp_cancel, NULL, \
 			transport_a2dp_get_stream, transport_a2dp_get_volume, \
-			_set_volume, _set_delay, NULL, _destroy)
+			_set_volume, _set_delay, NULL, _destroy, NULL)
 
 #define BAP_OPS(_uuid, _props, _set_owner, _remove_owner, _update_links, \
-		_set_state) \
+		_set_state, _test_props) \
 	TRANSPORT_OPS(_uuid, _props, _set_owner, _remove_owner,\
 			transport_bap_init, \
 			transport_bap_resume, transport_bap_suspend, \
 			transport_bap_cancel, _set_state, \
 			transport_bap_get_stream, transport_bap_get_volume, \
 			transport_bap_set_volume, NULL, \
-			_update_links, transport_bap_destroy)
+			_update_links, transport_bap_destroy, _test_props)
 
 #define BAP_UC_OPS(_uuid) \
 	BAP_OPS(_uuid, transport_bap_uc_properties, \
 			transport_bap_set_owner, transport_bap_remove_owner, \
-			transport_bap_update_links_uc, transport_bap_set_state)
+			transport_bap_update_links_uc, \
+			transport_bap_set_state, \
+			transport_bap_uc_test_properties)
 
 #define BAP_BC_OPS(_uuid) \
 	BAP_OPS(_uuid, transport_bap_bc_properties, NULL, NULL, \
-			transport_bap_update_links_bc, NULL)
+			transport_bap_update_links_bc, NULL, NULL)
 
 #define ASHA_OPS(_uuid) \
 	TRANSPORT_OPS(_uuid, transport_asha_properties, NULL, NULL, \
@@ -2592,7 +2676,7 @@ static void *transport_asha_init(struct media_transport *transport, void *data)
 			transport_asha_resume, transport_asha_suspend, \
 			transport_asha_cancel, NULL, NULL, \
 			transport_asha_get_volume, transport_asha_set_volume, \
-			NULL, NULL, NULL)
+			NULL, NULL, NULL, NULL)
 
 static const struct media_transport_ops transport_ops[] = {
 #ifdef HAVE_A2DP
@@ -2647,6 +2731,7 @@ struct media_transport *media_transport_create(struct btd_device *device,
 	struct media_transport *transport;
 	const struct media_transport_ops *ops;
 	int fd;
+	const GDBusPropertyTable *properties;
 
 	transport = g_new0(struct media_transport, 1);
 	if (device)
@@ -2701,9 +2786,14 @@ struct media_transport *media_transport_create(struct btd_device *device,
 			goto fail;
 	}
 
+	if (btd_opts.testing && ops->test_properties)
+		properties = ops->test_properties;
+	else
+		properties = ops->properties;
+
 	if (g_dbus_register_interface(btd_get_dbus_connection(),
 				transport->path, MEDIA_TRANSPORT_INTERFACE,
-				transport_methods, NULL, ops->properties,
+				transport_methods, NULL, properties,
 				transport, media_transport_free) == FALSE) {
 		error("Could not register transport %s", transport->path);
 		goto fail;
-- 
2.43.0


^ permalink raw reply related

* [PATCH BlueZ v2 3/3] client/player: Add support to desynchronize linked transports
From: Frédéric Danis @ 2026-04-28  8:03 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20260428080314.180777-1-frederic.danis@collabora.com>

After linked transports has been desynchronized, they should be acquired
separately and read handler should only be started for source local
endpoint.

This is used to pass PTS tests BAP/UCL/STR/BV-543-C and BV-546-C.
---
 client/player.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/client/player.c b/client/player.c
index 1444e939d..c5e4beef0 100644
--- a/client/player.c
+++ b/client/player.c
@@ -5003,6 +5003,9 @@ static bool transport_recv(struct io *io, void *user_data)
 static void transport_new(GDBusProxy *proxy, int sk, uint16_t mtu[2])
 {
 	struct transport *transport;
+	DBusMessageIter iter;
+	const char *uuid;
+	bool reader = true;
 
 	transport = new0(struct transport, 1);
 	transport->proxy = proxy;
@@ -5014,7 +5017,27 @@ static void transport_new(GDBusProxy *proxy, int sk, uint16_t mtu[2])
 
 	io_set_disconnect_handler(transport->io, transport_disconnected,
 							transport, NULL);
-	io_set_read_handler(transport->io, transport_recv, transport, NULL);
+
+	if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+		return;
+
+	dbus_message_iter_get_basic(&iter, &uuid);
+
+	/* For BAP testing, streams may have been manually desynchronized.
+	 * In this case source and sink streams are acquired separately and
+	 * read handler should not be started for source local endpoint.
+	 */
+	if (g_dbus_proxy_get_property(proxy, "Desynchronized", &iter)) {
+		dbus_bool_t desync;
+
+		dbus_message_iter_get_basic(&iter, &desync);
+		if (desync && !strcmp(uuid, PAC_SOURCE_UUID))
+			reader = false;
+	}
+
+	if (reader)
+		io_set_read_handler(transport->io, transport_recv, transport,
+									NULL);
 
 	if (!ios)
 		ios = queue_new();
@@ -5325,6 +5348,7 @@ static void print_transport_properties(GDBusProxy *proxy)
 	print_property(proxy, "QoS");
 	print_property(proxy, "Location");
 	print_property(proxy, "Links");
+	print_property(proxy, "Desynchronized");
 }
 
 static void print_transports(void *data, void *user_data)
@@ -6091,6 +6115,53 @@ static void cmd_metadata_transport(int argc, char *argv[])
 	}
 }
 
+static void desync_cb(const DBusError *error, void *user_data)
+{
+	if (dbus_error_is_set(error)) {
+		bt_shell_printf("Failed to desynchronize: %s\n", error->name);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	bt_shell_printf("Desynchronize succeeded\n");
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_desync_transport(int argc, char *argv[])
+{
+	dbus_bool_t desync;
+	GDBusProxy *proxy;
+
+	if (argc < 3) {
+		bt_shell_printf("Missing argument to %s\n", argv[0]);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	proxy = g_dbus_proxy_lookup(transports, NULL, argv[1],
+					BLUEZ_MEDIA_TRANSPORT_INTERFACE);
+	if (!proxy) {
+		bt_shell_printf("Transport %s not found\n", argv[1]);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (!strcmp(argv[2], "on") || !strcmp(argv[2], "yes")) {
+		desync = TRUE;
+	} else if (!strcmp(argv[2], "off") || !strcmp(argv[2], "no")) {
+		desync = FALSE;
+	} else {
+		bt_shell_printf("Invalid argument %s\n", argv[2]);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (!g_dbus_proxy_set_property_basic(proxy, "Desynchronized",
+							DBUS_TYPE_BOOLEAN,
+							&desync, desync_cb,
+							NULL, NULL)) {
+		bt_shell_printf("Failed to desynchronize transport\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+}
+
 static const struct bt_shell_menu transport_menu = {
 	.name = "transport",
 	.desc = "Media Transport Submenu",
@@ -6126,6 +6197,9 @@ static const struct bt_shell_menu transport_menu = {
 	{ "metadata",    "<transport> [value...]", cmd_metadata_transport,
 						"Get/Set Transport Metadata",
 						transport_generator },
+	{ "desync",      "<transport> <on/off>", cmd_desync_transport,
+						"Desynchronize Transport",
+						transport_generator },
 	{} },
 };
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH BlueZ v2 2/3] doc: Add documentation for CIS transport Desynchronized property
From: Frédéric Danis @ 2026-04-28  8:03 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20260428080314.180777-1-frederic.danis@collabora.com>

This is only supported when bluetoothd is started in testing mode.

Assisted-by: GPT:GPT-5.3-Codex
---
 doc/org.bluez.MediaTransport.rst | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/doc/org.bluez.MediaTransport.rst b/doc/org.bluez.MediaTransport.rst
index 81cf9e4da..e50ec3f20 100644
--- a/doc/org.bluez.MediaTransport.rst
+++ b/doc/org.bluez.MediaTransport.rst
@@ -357,3 +357,17 @@ Possible values for both Unicast and Broadcast:
 :byte Retransmissions:
 
 	Indicates configured retransmissions.
+
+boolean Desynchronized [readwrite, optional, CIS only, testing, experimental]
+`````````````````````````````````````````````````````````````````````````````
+
+Available only when D-Bus testing interfaces are enabled and the transport has
+the **Links** property.
+
+Controls whether linked transports are acquired together.
+
+When set to False (default), acquiring one linked transport automatically
+acquires all links.
+
+When set to True, links are not acquired automatically and each link must be
+acquired separately.
-- 
2.43.0


^ permalink raw reply related

* [PATCH BlueZ v2 0/3] Add ability to desynchronized transports for PTS tests
From: Frédéric Danis @ 2026-04-28  8:03 UTC (permalink / raw)
  To: linux-bluetooth

If bluetoothd is started in testing mode a new Desynchronized property
is added to org.bluez.MediaTransport1, allowing to prevent automatic
acquire of linked transport objects.

When desynchronized, each transports needs to be acquired separately.

This allows to pass PTS tests BAP/UCL/STR/BV-543-C and BV-546-C which
requires to connect the ISO streams with one ASE in "Enable" state
while the other is in "Config QoS" state.

v1->v2:
  - renamed 'desynchronized' to 'desync' in profiles/audio/transport.c
  - added a comment for the 'desync' variable of 'struct bap_transport'
    in profiles/audio/transport.c 

Frédéric Danis (3):
  audio: Add ability to desynchronized linked transport
  doc: Add documentation for CIS transport Desynchronized property
  client/player: Add support to desynchronize linked transports

 client/player.c                  |  76 +++++++++++++++++++-
 doc/org.bluez.MediaTransport.rst |  14 ++++
 profiles/audio/transport.c       | 116 +++++++++++++++++++++++++++----
 3 files changed, 192 insertions(+), 14 deletions(-)

-- 
2.43.0


^ permalink raw reply

* [Bug 221426] Intel AX211 Bluetooth hci0 hardware error 0x0c with HID/HOG failures on 6.19.14-zen
From: bugzilla-daemon @ 2026-04-28  6:53 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-221426-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=221426

--- Comment #8 from The Linux kernel's regression tracker (Thorsten Leemhuis) (regressions@leemhuis.info) ---
(In reply to Paul Menzel from comment #7)

BTW, thx for CCing me

> https://www.kernel.org/doc/html/latest/admin-guide/reporting-regressions.html

The most detailed guide on bisection is:
https://docs.kernel.org/admin-guide/verify-bugs-and-bisect-regressions.html

Best follow that, as it will check latest mainline, which is important, as
6.19.y is already EOL. It will also ensure the problem happens on a vanilla
kernel, as -zen kernels are heavily patched (see
https://github.com/zen-kernel/zen-kernel/wiki/Detailed-Feature-List ) and thus
inadequate for upstream reporting.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* Re: [PATCH v1] arm64: dts: monac-arduino-monza: Add Bluetooth UART node
From: Paul Menzel @ 2026-04-28  6:16 UTC (permalink / raw)
  To: Shuai Zhang
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel,
	linux-bluetooth, cheng.jiang, quic_chezhou, wei.deng, jinwang.li,
	mengshi.wu, Loic Poulain
In-Reply-To: <20260428025652.662502-1-shuai.zhang@oss.qualcomm.com>

Dear Shuai,


Thank you for your patch. gemini/gemini-3.1-pro-preview found a typo in 
the summary/title and commit message [1]:

> This isn't a bug, but there's a typo in the board name (monac) in the
> subject line. It looks like it should be monaco-arduino-monza.


Am 28.04.26 um 04:56 schrieb Shuai Zhang:
> enable bt on monac-arduino-monza

Please elaborate, that it’s UART 10, and how you tested it – including 
the low-power states.

> Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com>
> ---
>   arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> index ca14f0ea4..092ca0b59 100644
> --- a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> +++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
> @@ -21,6 +21,7 @@ aliases {
>   		ethernet0 = &ethernet0;
>   		i2c1 = &i2c1;
>   		serial0 = &uart7;
> +		serial1 = &uart10;
>   	};
>   
>   	chosen {
> @@ -454,6 +455,16 @@ &uart7 {
>   	status = "okay";
>   };
>   
> +&uart10 {
> +	status = "okay";
> +	bluetooth: bluetooth {
> +		compatible = "qcom,qca2066-bt";
> +		max-speed = <3200000>;
> +		enable-gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>;

Next comment [1]:

> Should this node also include a clocks property?
> The device tree binding schema for qcom,qca2066-bt explicitly lists clocks
> in its required array to specify the external low-power 32.768 kHz clock
> input. Omitting it will cause dtbs_check to fail.
> While the Bluetooth driver treats the clock as optional, missing the sleep
> clock on Qualcomm platforms typically prevents the controller from entering
> low-power sleep states, which can lead to increased power consumption.

And this looks valid. From 
`Documentation/devicetree/bindings/net/bluetooth/qcom,qca2066-bt.yaml`:

     required:
       - compatible
       - clocks
       - enable-gpios

> +		status = "okay";
> +	};
> +};
> +
>   &usb_1 {
>   	status = "okay";
>   };


Kind regards,

Paul


[1]: 
https://sashiko.dev/#/patchset/20260428025652.662502-1-shuai.zhang%40oss.qualcomm.com

^ permalink raw reply

* RE: Add RAS Packet format and Notification support
From: bluez.test.bot @ 2026-04-28  3:36 UTC (permalink / raw)
  To: linux-bluetooth, prathibha.madugonde
In-Reply-To: <20260428023111.1640377-2-prathm@qti.qualcomm.com>

[-- Attachment #1: Type: text/plain, Size: 989 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/project/bluetooth/list/?series=1086507

---Test result---

Test Summary:
CheckPatch                    PASS      1.85 seconds
GitLint                       PASS      0.42 seconds
BuildEll                      PASS      20.23 seconds
BluezMake                     PASS      638.35 seconds
MakeCheck                     PASS      0.99 seconds
MakeDistcheck                 PASS      245.83 seconds
CheckValgrind                 PASS      222.44 seconds
CheckSmatch                   PASS      348.84 seconds
bluezmakeextell               PASS      181.26 seconds
IncrementalBuild              PASS      640.76 seconds
ScanBuild                     PASS      1012.70 seconds



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

---
Regards,
Linux Bluetooth


^ permalink raw reply

* [PATCH v1] arm64: dts: monac-arduino-monza: Add Bluetooth UART node
From: Shuai Zhang @ 2026-04-28  2:56 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-bluetooth,
	cheng.jiang, quic_chezhou, wei.deng, jinwang.li, mengshi.wu,
	shuai.zhang, Loic Poulain

enable bt on monac-arduino-monza

Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Signed-off-by: Shuai Zhang <shuai.zhang@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
index ca14f0ea4..092ca0b59 100644
--- a/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
+++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza.dts
@@ -21,6 +21,7 @@ aliases {
 		ethernet0 = &ethernet0;
 		i2c1 = &i2c1;
 		serial0 = &uart7;
+		serial1 = &uart10;
 	};
 
 	chosen {
@@ -454,6 +455,16 @@ &uart7 {
 	status = "okay";
 };
 
+&uart10 {
+	status = "okay";
+	bluetooth: bluetooth {
+		compatible = "qcom,qca2066-bt";
+		max-speed = <3200000>;
+		enable-gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>;
+		status = "okay";
+	};
+};
+
 &usb_1 {
 	status = "okay";
 };
-- 
2.34.1


^ permalink raw reply related

* [bluez/bluez] ace83f: src/shared: Add RAS packet format and notification...
From: prathibhamadugonde @ 2026-04-28  2:40 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1086507
  Home:   https://github.com/bluez/bluez
  Commit: ace83f49e878d588c268cb525e65156c6dcb80fe
      https://github.com/bluez/bluez/commit/ace83f49e878d588c268cb525e65156c6dcb80fe
  Author: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>
  Date:   2026-04-28 (Tue, 28 Apr 2026)

  Changed paths:
    M src/shared/rap.c
    M src/shared/rap.h

  Log Message:
  -----------
  src/shared: Add RAS packet format and notification support

Implement complete RAS data pipeline:
 - Handle HCI CS subevent result/continuation events
 - Serialize ranging/subevent headers per spec
 - GATT notifications for real-time ranging data


  Commit: 1c15a4a4463a498473a5ce53e5ac854a5260c8b7
      https://github.com/bluez/bluez/commit/1c15a4a4463a498473a5ce53e5ac854a5260c8b7
  Author: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>
  Date:   2026-04-28 (Tue, 28 Apr 2026)

  Changed paths:
    M profiles/ranging/rap_hci.c

  Log Message:
  -----------
  profiles/ranging: Read cs_mode_one_data members

Rearrage reading of cs_mode_one_data struct members as per spec.


Compare: https://github.com/bluez/bluez/compare/ace83f49e878%5E...1c15a4a4463a

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [PATCH BlueZ v5 3/3] profiles/ranging: Read cs_mode_one_data members
From: Prathibha Madugonde @ 2026-04-28  2:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg
In-Reply-To: <20260428023111.1640377-1-prathm@qti.qualcomm.com>

From: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>

Rearrage reading of cs_mode_one_data struct members as per spec.
---
 profiles/ranging/rap_hci.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/profiles/ranging/rap_hci.c b/profiles/ranging/rap_hci.c
index a3d2df608..08ddc077c 100644
--- a/profiles/ranging/rap_hci.c
+++ b/profiles/ranging/rap_hci.c
@@ -632,19 +632,22 @@ static void parse_mode_one_data(struct iovec *iov,
 	}
 
 	DBG("CS Step mode 1");
-	util_iov_pull_u8(iov, &mode_data->packet_quality);
-	util_iov_pull_u8(iov, &mode_data->packet_rssi_dbm);
-	util_iov_pull_u8(iov, &mode_data->packet_ant);
-	util_iov_pull_u8(iov, &mode_data->packet_nadm);
-
-	if (iov->iov_len >= 2) {
-		util_iov_pull_le16(iov, &time_val);
-		if (cs_role == CS_REFLECTOR)
-			mode_data->tod_toa_refl = time_val;
-		else
-			mode_data->toa_tod_init = time_val;
+	/* Parse fixed fields in specification order */
+	if (!util_iov_pull_u8(iov, &mode_data->packet_quality) ||
+		!util_iov_pull_u8(iov, &mode_data->packet_nadm) ||
+		!util_iov_pull_u8(iov, &mode_data->packet_rssi_dbm) ||
+		!util_iov_pull_le16(iov, &time_val) ||
+		!util_iov_pull_u8(iov, &mode_data->packet_ant)) {
+		DBG("Mode 1: failed to parse basic fields");
+		memset(mode_data, 0, sizeof(*mode_data));
+		return;
 	}
 
+	if (cs_role == CS_REFLECTOR)
+		mode_data->tod_toa_refl = time_val;
+	else
+		mode_data->toa_tod_init = time_val;
+
 	if ((cs_rtt_type == 0x01 || cs_rtt_type == 0x02) &&
 		iov->iov_len >= 6) {
 		int16_t i_val, q_val;
-- 
2.34.1


^ permalink raw reply related

* [PATCH BlueZ v5 2/3] unit/test-rap: Add PTS tests for CS reflector
From: Prathibha Madugonde @ 2026-04-28  2:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg
In-Reply-To: <20260428023111.1640377-1-prathm@qti.qualcomm.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 11085 bytes --]

From: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>

Added below RAS - Real time Ranging PTS testcases

RAS/SR/RCO/BV-01-C [Characteristic Read - RAS Features]
RAS/SR/RRD/BV-01-C [Real-time Ranging Data]
RAS/SR/RRD/BV-03-C [Real-time Ranging Data notifications and indications]
RAS/SR/RRD/BV-05-C [Real-Time Ranging Data disconnection]
---
 unit/test-rap.c | 264 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 260 insertions(+), 4 deletions(-)

diff --git a/unit/test-rap.c b/unit/test-rap.c
index 884cb1c96..6f65967a4 100644
--- a/unit/test-rap.c
+++ b/unit/test-rap.c
@@ -37,6 +37,7 @@ struct test_data_ras {
 	size_t iovcnt;
 	struct iovec *iov;
 	unsigned int ras_id;
+	struct bt_rap *rap;  /* Store rap instance for CS injection */
 };
 
 struct test_data_rap {
@@ -68,8 +69,8 @@ struct notify {
 	do {							\
 		const struct iovec iov[] = { args };		\
 		static struct test_data_ras data;			\
-		data.iovcnt = ARRAY_SIZE(iov_data(args));	\
-		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov_data(args))); \
+		data.iovcnt = ARRAY_SIZE(iov);	\
+		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov)); \
 		tester_add(name, &data, NULL, function,	\
 				test_teardown_ras);			\
 	} while (0)
@@ -155,6 +156,94 @@ static void gatt_notify_cb(struct gatt_db_attribute *attrib,
 		printf("%s: Failed to send notification\n", __func__);
 }
 
+static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct test_data_ras *data = user_data;
+	struct ccc_state *ccc;
+	uint16_t handle;
+	uint16_t ccc_value;
+	uint8_t ecode = 0;
+
+	handle = gatt_db_attribute_get_handle(attrib);
+
+	if (offset) {
+		ecode = BT_ATT_ERROR_INVALID_OFFSET;
+		goto done;
+	}
+
+	if (len != 2) {
+		ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+		goto done;
+	}
+
+	ccc_value = get_le16(value);
+
+	ccc = get_ccc_state(data, handle);
+	if (!ccc) {
+		ecode = BT_ATT_ERROR_UNLIKELY;
+		goto done;
+	}
+
+	ccc->value = ccc_value;
+
+	/* Send write response first */
+	gatt_db_attribute_write_result(attrib, id, 0);
+
+	/* If notifications/indications enabled on Real-time Ranging Data CCCD,
+	 * inject fake HCI CS subevent data to trigger notifications
+	 */
+	if (handle == 0x0006 && ccc_value != 0x0000 && data->rap) {
+		size_t event_size = sizeof(struct rap_ev_cs_subevent_result) +
+				    sizeof(struct cs_step_data);
+		struct rap_ev_cs_subevent_result *fake_event;
+		struct cs_mode_zero_data *mode_zero;
+
+		if (tester_use_debug())
+			tester_debug("Injecting fake CS data...");
+
+		fake_event = g_malloc0(event_size);
+		if (!fake_event)
+			return;  /* Already sent write response */
+
+		/* Fill in the header fields */
+		fake_event->conn_hdl = 0x0001;
+		fake_event->config_id = 0x01;
+		fake_event->start_acl_conn_evt_counter = 0x0000;
+		fake_event->proc_counter = 0x0001;
+		fake_event->freq_comp = 0x0000;
+		fake_event->ref_pwr_lvl = 0x00;
+		fake_event->proc_done_status = 0x00;
+		fake_event->subevt_done_status = 0x00;
+		fake_event->abort_reason = 0x00;
+		fake_event->num_ant_paths = 0x01;
+		fake_event->num_steps_reported = 0x01;
+
+		fake_event->step_data[0].step_mode = CS_MODE_ZERO;
+		fake_event->step_data[0].step_chnl = 0x00;
+		/* Mode 0: 1+1+1+4 bytes */
+		fake_event->step_data[0].step_data_length = 4;
+mode_zero = &fake_event->step_data[0].step_mode_data.mode_zero_data;
+		mode_zero->packet_quality = 0x01;
+		mode_zero->packet_rssi_dbm = 0x02;
+		mode_zero->packet_ant = 0x03;
+		mode_zero->init_measured_freq_offset = 0x04;
+
+		/* Inject the fake event to trigger notification */
+		bt_rap_hci_cs_subevent_result_callback(event_size, fake_event,
+						       data->rap);
+
+		g_free(fake_event);
+	}
+	return;
+
+done:
+	gatt_db_attribute_write_result(attrib, id, ecode);
+}
+
 static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
 					unsigned int id, uint16_t offset,
 					uint8_t opcode, struct bt_att *att,
@@ -184,10 +273,21 @@ done:
 
 static void ras_attached(struct bt_rap *rap, void *user_data)
 {
+	struct test_data_ras *data = user_data;
+
+	if (data) {
+		data->rap = rap;
+		bt_rap_ref(rap);  /* Keep a reference */
+	}
 }
 
 static void ras_detached(struct bt_rap *rap, void *user_data)
 {
+	struct test_data_ras *data = user_data;
+
+	if (data && data->rap == rap)
+		data->rap = NULL;
+
 	bt_rap_unref(rap);
 }
 
@@ -205,17 +305,18 @@ static void test_server(const void *user_data)
 	att = bt_att_new(io_get_fd(io), false);
 	g_assert(att);
 
+	bt_att_set_security(att, BT_ATT_SECURITY_MEDIUM);
 	bt_att_set_debug(att, BT_ATT_DEBUG, print_debug, "bt_att:", NULL);
 
 	data->db = gatt_db_new();
 	g_assert(data->db);
 
-	gatt_db_ccc_register(data->db, gatt_ccc_read_cb, NULL,
+	gatt_db_ccc_register(data->db, gatt_ccc_read_cb, gatt_ccc_write_cb,
 					gatt_notify_cb, data);
 
 	bt_rap_add_db(data->db);
 
-	data->ras_id = bt_rap_register(ras_attached, ras_detached, NULL);
+	data->ras_id = bt_rap_register(ras_attached, ras_detached, data);
 
 	data->server = bt_gatt_server_new(data->db, att, 64, 0);
 	g_assert(data->server);
@@ -426,6 +527,150 @@ static void test_server(const void *user_data)
 	DISC_RAS_CHAR_AFTER_TYPE, \
 	RAS_FIND_INFO
 
+/*
+ * RAS/SR/RCO/BV-01-C – Characteristic Read: RAS Features
+ *
+ *  ATT: Read Request (0x0a) len 2
+ *       Handle: 0x0003 (RAS Features value handle)
+ *
+ *  ATT: Read Response (0x0b) len 5
+ *       Value: 0x01 0x00 0x00 0x00
+ *       Feature bits:
+ *         Bit 0: Real-time ranging (1 = supported)
+ *         Bit 1: Retrieve stored results (0 = not supported)
+ *         Bit 2: Abort operation (0 = not supported)
+ *
+ *  Note: The RAS Features characteristic is registered with
+ *  BT_ATT_PERM_READ | BT_ATT_PERM_READ_ENCRYPT. Since the test sets
+ *  BT_ATT_SECURITY_MEDIUM, the encryption requirement is satisfied
+ *  and the server returns the feature value showing real-time ranging
+ *  support.
+ */
+
+#define ATT_READ_RAS_FEATURES \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x01, 0x00, 0x00, 0x00)
+
+#define RAS_SR_RCO_BV_01_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	RAS_FIND_BY_TYPE_VALUE, \
+	DISC_RAS_CHAR_AFTER_TYPE, \
+	RAS_FIND_INFO, \
+	ATT_READ_RAS_FEATURES
+
+/*
+ * RAS Real-time Ranging Data CCCD Configuration
+ * Round 1: Enable/Disable notifications (CCCD = 0x0001)
+ * Round 2: Enable/Disable indications (CCCD = 0x0002)
+ */
+#define RAS_REALTIME_CCCD_CONFIG \
+	/* Round 1: Enable notifications on Real-time Ranging Data CCCD */ \
+	/* (handle 0x0006) */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	/* Disable notifications */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13), \
+	/* Round 2: Enable indications on Real-time Ranging Data CCCD */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x02, 0x00), \
+	IOV_DATA(0x13), \
+	/* Disable indications */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13)
+
+/*
+ * Enable both notifications and indications (CCCD = 0x0003)
+ * Expect notification (0x1b) to be sent, not indication (0x1d)
+ * Then disable CCCD
+ *
+ * Note: This test is currently disabled because the GATT server rejects
+ * CCCD value 0x0003 (both notifications and indications enabled) before
+ * reaching the custom callback. The test infrastructure needs to be updated
+ * to support this scenario.
+ */
+#define RAS_REALTIME_CCCD_BOTH_ENABLE_DISABLE \
+	/* Enable notifications only (CCCD = 0x0001) */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	/* Disable CCCD */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13)
+
+/*
+ * Disconnection/Reconnection simulation for Real-time Ranging Data
+ * Enable notifications, disable (disconnect), re-enable (reconnect), disable
+ */
+#define RAS_REALTIME_CCCD_DISCONNECT_RECONNECT \
+	/* Step 1: Enable notifications */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	/* Step 3: Disable CCCD (simulates disconnection) */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13), \
+	/* Step 4: Re-enable notifications (simulates reconnection) */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	/* Disable CCCD to clean up */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13)
+
+/*
+ * RAS/SR/RRD/BV-01-C [Real-time Ranging Data]
+ * Verify that the IUT can configure CCCD for notifications/indications
+ * of the Real-time Ranging Data characteristic.
+ */
+#define RAS_SR_RRD_BV_01_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	RAS_FIND_BY_TYPE_VALUE, \
+	DISC_RAS_CHAR_AFTER_TYPE, \
+	RAS_FIND_INFO, \
+	RAS_REALTIME_CCCD_CONFIG
+
+/*
+ * RAS/SR/RRD/BV-03-C [Real-time Ranging Data notifications and indications]
+ * Verify that the IUT only sends Real-time Ranging Data notifications when
+ * configured for both notifications and indications (CCCD = 0x0003).
+ *
+ * Test Procedure:
+ * 1. Write 0x0003 to Real-time Ranging Data CCCD (enable both
+ *    notifications and indications)
+ * 2. Trigger CS Subevent Data (via fake HCI event injection)
+ * 3. Verify IUT sends only notifications (0x1b), not indications (0x1d)
+ */
+#define RAS_SR_RRD_BV_03_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	RAS_FIND_BY_TYPE_VALUE, \
+	DISC_RAS_CHAR_AFTER_TYPE, \
+	RAS_FIND_INFO, \
+	RAS_REALTIME_CCCD_BOTH_ENABLE_DISABLE
+
+/*
+ * RAS/SR/RRD/BV-05-C [Real-Time Ranging Data disconnection]
+ * Verify that the IUT does not resume sending Real-time Ranging Data
+ * notifications or indications after a disconnection occurs.
+ *
+ * Test Procedure:
+ * 1. Enable Real-time Ranging Data notifications
+ * 2. Trigger CS Subevent Data (IUT sends notifications)
+ * 3. Disable CCCD (simulates disconnection - CCCD resets to 0x0000)
+ * 4. Re-enable notifications (simulates reconnection and reconfiguration)
+ * 5. Verify IUT does not send old ranging data
+ *
+ * Note: In a unit test, we simulate disconnection by disabling and re-enabling
+ * the CCCD. The RAP implementation should clear any pending data when CCCD is
+ * disabled, ensuring no old data is sent after re-enabling.
+ */
+#define RAS_SR_RRD_BV_05_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	RAS_FIND_BY_TYPE_VALUE, \
+	DISC_RAS_CHAR_AFTER_TYPE, \
+	RAS_FIND_INFO, \
+	RAS_REALTIME_CCCD_DISCONNECT_RECONNECT
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
@@ -441,6 +686,17 @@ int main(int argc, char *argv[])
 					RAS_SR_SGGIT_CHA_BV_03_C);
 	define_test_ras("RAS/SR/SGGIT/CHA/BV-04-C", test_server,
 					RAS_SR_SGGIT_CHA_BV_04_C);
+	/* RAS Read Characteristic Operations */
+	define_test_ras("RAS/SR/RCO/BV-01-C", test_server,
+					RAS_SR_RCO_BV_01_C);
+	/* RAS Real-time Ranging Data */
+	define_test_ras("RAS/SR/RRD/BV-01-C", test_server,
+					RAS_SR_RRD_BV_01_C);
+	/* RAS Real-time Ranging Data with CS injection */
+	define_test_ras("RAS/SR/RRD/BV-03-C", test_server,
+					RAS_SR_RRD_BV_03_C);
+	define_test_ras("RAS/SR/RRD/BV-05-C", test_server,
+					RAS_SR_RRD_BV_05_C);
 
 	return tester_run();
 }
-- 
2.34.1


^ permalink raw reply related

* [PATCH BlueZ v5 1/3] src/shared: Add RAS packet format and notification support
From: Prathibha Madugonde @ 2026-04-28  2:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg
In-Reply-To: <20260428023111.1640377-1-prathm@qti.qualcomm.com>

From: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>

Implement complete RAS data pipeline:
 - Handle HCI CS subevent result/continuation events
 - Serialize ranging/subevent headers per spec
 - GATT notifications for real-time ranging data
---
 src/shared/rap.c | 1376 +++++++++++++++++++++++++++++++++++++++++++++-
 src/shared/rap.h |    4 +-
 2 files changed, 1366 insertions(+), 14 deletions(-)

diff --git a/src/shared/rap.c b/src/shared/rap.c
index ac6de04e0..db924b0e9 100644
--- a/src/shared/rap.c
+++ b/src/shared/rap.c
@@ -33,6 +33,170 @@
 /* Total number of attribute handles reserved for the RAS service */
 #define RAS_TOTAL_NUM_HANDLES		18
 
+/* 2(rc+cfg) + 1(tx_pwr) + 1(4 bits antenna_mask, 2 bits reserved,
+ * 2 bits pct_format)
+ */
+#define RAS_RANGING_HEADER_SIZE 4
+#define TOTAL_RAS_RANGING_HEADER_SIZE 5
+#define ATT_OVERHEAD 3 /* 1(opcode) + 2(char handle) */
+#define RAS_STEP_ABORTED_BIT   0x80/* set step aborted */
+#define RAS_SUBEVENT_HEADER_SIZE 8
+
+enum pct_format {
+	IQ = 0,
+	PHASE = 1,
+};
+
+enum ranging_done_status {
+	RANGING_DONE_ALL_RESULTS_COMPLETE = 0x0,
+	RANGING_DONE_PARTIAL_RESULTS = 0x1,
+	RANGING_DONE_ABORTED = 0xF,
+};
+
+enum subevent_done_status {
+	SUBEVENT_DONE_ALL_RESULTS_COMPLETE = 0x0,
+	SUBEVENT_DONE_PARTIAL_RESULTS = 0x1,
+	SUBEVENT_DONE_ABORTED = 0xF,
+};
+
+enum ranging_abort_reason {
+	RANGING_ABORT_NO_ABORT = 0x0,
+	RANGING_ABORT_LOCAL_HOST_OR_REMOTE = 0x1,
+	RANGING_ABORT_INSUFFICIENT_FILTERED_CHANNELS = 0x2,
+	RANGING_ABORT_INSTANT_HAS_PASSED = 0x3,
+	RANGING_ABORT_UNSPECIFIED = 0xF,
+};
+
+enum subevent_abort_reason {
+	SUBEVENT_ABORT_NO_ABORT = 0x0,
+	SUBEVENT_ABORT_LOCAL_HOST_OR_REMOTE = 0x1,
+	SUBEVENT_ABORT_NO_CS_SYNC_RECEIVED = 0x2,
+	SUBEVENT_ABORT_SCHEDULING_CONFLICTS_OR_LIMITED_RESOURCES = 0x3,
+	SUBEVENT_ABORT_UNSPECIFIED = 0xF,
+};
+
+/* Segmentation header: 1 byte
+ * bit 0: first_segment
+ * bit 1: last_segment
+ * bits 2-7: rolling_segment_counter (6 bits)
+ */
+struct segmentation_header {
+	uint8_t first_segment;
+	uint8_t last_segment;
+	uint8_t rolling_segment_counter;
+};
+
+/* Macros to pack/unpack segmentation header */
+#define SEG_HDR_PACK(first, last, counter) \
+	((uint8_t)(((first) ? 0x01 : 0x00) | \
+		((last) ? 0x02 : 0x00) | \
+		(((counter) & 0x3F) << 2)))
+
+#define SEG_HDR_UNPACK_FIRST(byte)    ((byte) & 0x01)
+#define SEG_HDR_UNPACK_LAST(byte)     (((byte) >> 1) & 0x01)
+#define SEG_HDR_UNPACK_COUNTER(byte)  (((byte) >> 2) & 0x3F)
+
+/* Ranging header: 4 bytes
+ * 0-1: ranging_counter (12 bits) | configuration_id (4 bits)
+ *      [little-endian]
+ * byte 2: selected_tx_power (signed)
+ * byte 3: antenna_paths_mask (4 bits) | reserved (2 bits) |
+ *         pct_format (2 bits)
+ */
+struct ranging_header {
+	uint16_t ranging_counter;
+	uint8_t configuration_id;
+	int8_t selected_tx_power;
+	uint8_t antenna_paths_mask;
+	uint8_t pct_format;
+} __packed;
+
+/* Macros to pack/unpack ranging header */
+#define RANGING_HDR_PACK_BYTE0_1(rc, cfg) \
+	((uint16_t)(((rc) & 0x0FFF) | (((cfg) & 0x0F) << 12)))
+
+#define RANGING_HDR_PACK_BYTE3(ant_mask, pct_fmt) \
+	((uint8_t)(((ant_mask) & 0x0F) | (((pct_fmt) & 0x03) << 6)))
+
+#define RANGING_HDR_UNPACK_RC(byte0_1) \
+	((uint16_t)((byte0_1) & 0x0FFF))
+
+#define RANGING_HDR_UNPACK_CFG(byte0_1) \
+	((uint8_t)(((byte0_1) >> 12) & 0x0F))
+
+#define RANGING_HDR_UNPACK_ANT_MASK(byte3) \
+	((uint8_t)((byte3) & 0x0F))
+
+#define RANGING_HDR_UNPACK_PCT_FMT(byte3) \
+	((uint8_t)(((byte3) >> 6) & 0x03))
+
+struct ras_subevent_header {
+	uint16_t start_acl_conn_event;
+	uint16_t frequency_compensation;
+	uint8_t ranging_done_status;
+	uint8_t subevent_done_status;
+	uint8_t ranging_abort_reason;
+	uint8_t subevent_abort_reason;
+	int8_t reference_power_level;
+	uint8_t num_steps_reported;
+};
+
+struct ras_subevent {
+	struct ras_subevent_header subevent_header;
+	uint8_t subevent_data[];
+};
+
+/* Role maps to Core CS roles (initiator/reflector) */
+enum cs_role {
+	CS_ROLE_INITIATOR = 0x00,
+	CS_ROLE_REFLECTOR = 0x01,
+};
+
+#define CS_INVALID_CONFIG_ID   0xFF
+/* Minimal enums (align to controller values if needed) */
+enum cs_procedure_done_status {
+	CS_PROC_ALL_RESULTS_COMPLETE = 0x00,
+	CS_PROC_PARTIAL_RESULTS      = 0x01,
+	CS_PROC_ABORTED              = 0x02
+};
+
+/* Main cs_procedure_data  */
+struct cs_procedure_data {
+	/* Identity and counters */
+	uint16_t counter;
+	uint8_t  num_antenna_paths;
+	/* Flags and status */
+	enum cs_procedure_done_status local_status;
+	enum cs_procedure_done_status remote_status;
+	bool contains_complete_subevent_;
+	/* RAS aggregation */
+	struct segmentation_header segmentation_header_;
+	struct ranging_header      ranging_header_;
+	struct iovec       ras_raw_data_;        /* raw concatenated */
+	uint16_t           ras_raw_data_index_;
+	struct ras_subevent_header  ras_subevent_header_;
+	struct iovec       ras_subevent_data_;   /* buffer per subevent */
+	uint8_t            ras_subevent_counter_;
+	/* Reference power levels */
+	int8_t initiator_reference_power_level;
+	int8_t reflector_reference_power_level;
+	bool ranging_header_prepended_;
+	bool ras_subevent_header_emitted;
+};
+
+struct cstracker {
+	enum cs_role        role;                 /* INITIATOR/REFLECTOR */
+	uint8_t             config_id;            /* CS_INVALID_CONFIG_ID */
+	uint8_t             selected_tx_power;    /* PROC_ENABLE_COMPLETE */
+	uint8_t             rtt_type;             /* RTT type */
+	struct cs_procedure_data *current_proc;
+	/* Cached header values for CONT events (per-connection state) */
+	uint16_t last_proc_counter;
+	uint16_t last_start_acl_conn_evt_counter;
+	uint16_t last_freq_comp;
+	int8_t last_ref_pwr_lvl;
+};
+
 /* Ranging Service context */
 struct ras {
 	struct bt_rap_db *rapdb;
@@ -43,9 +207,17 @@ struct ras {
 	struct gatt_db_attribute *realtime_chrc;
 	struct gatt_db_attribute *realtime_chrc_ccc;
 	struct gatt_db_attribute *ondemand_chrc;
+	struct gatt_db_attribute *ondemand_ccc;
 	struct gatt_db_attribute *cp_chrc;
+	struct gatt_db_attribute *cp_ccc;
 	struct gatt_db_attribute *ready_chrc;
+	struct gatt_db_attribute *ready_ccc;
 	struct gatt_db_attribute *overwritten_chrc;
+	struct gatt_db_attribute *overwritten_ccc;
+
+	/* CCC state tracking for mutual exclusivity */
+	uint16_t realtime_ccc_value;
+	uint16_t ondemand_ccc_value;
 };
 
 struct bt_rap_db {
@@ -70,6 +242,7 @@ struct bt_rap {
 	bt_rap_destroy_func_t debug_destroy;
 	void *debug_data;
 	void *user_data;
+	struct cstracker *resptracker;
 };
 
 static struct queue *rap_db;
@@ -90,6 +263,209 @@ struct bt_rap_ready {
 	void *data;
 };
 
+uint16_t default_ras_mtu = 247; /*Section 3.1.2 of RAP 1.0*/
+uint8_t ras_segment_header_size = 1;
+
+static struct cs_procedure_data *cs_procedure_data_create(
+					uint16_t procedure_counter,
+					uint8_t num_antenna_paths,
+					uint8_t configuration_id,
+					uint8_t selected_tx_power)
+{
+	struct cs_procedure_data *d;
+	uint8_t i;
+
+	d = calloc(1, sizeof(struct cs_procedure_data));
+
+	if (!d)
+		return NULL;
+
+	d->counter = procedure_counter;
+	d->num_antenna_paths = num_antenna_paths;
+	d->local_status = CS_PROC_PARTIAL_RESULTS;
+	d->remote_status = CS_PROC_PARTIAL_RESULTS;
+	d->contains_complete_subevent_ = false;
+	d->segmentation_header_.first_segment = 1;
+	d->segmentation_header_.last_segment = 0;
+	d->segmentation_header_.rolling_segment_counter = 0;
+	d->ranging_header_.ranging_counter = procedure_counter;
+	d->ranging_header_.configuration_id = configuration_id;
+	d->ranging_header_.selected_tx_power = selected_tx_power;
+	d->ranging_header_.antenna_paths_mask = 0;
+
+	for (i = 0; i < num_antenna_paths; i++)
+		d->ranging_header_.antenna_paths_mask |= (1u << i);
+
+	d->ranging_header_.pct_format = IQ;
+	memset(&d->ras_raw_data_, 0, sizeof(d->ras_raw_data_));
+	d->ras_raw_data_index_ = 0;
+	memset(&d->ras_subevent_data_, 0, sizeof(d->ras_subevent_data_));
+	d->ras_subevent_counter_ = 0;
+	d->initiator_reference_power_level = 0;
+	d->reflector_reference_power_level = 0;
+	d->ranging_header_prepended_ = false;
+	d->ras_subevent_header_emitted = false;
+
+	return d;
+}
+
+static void cs_procedure_data_destroy(struct cs_procedure_data *d)
+{
+	if (!d)
+		return;
+
+	free(d->ras_raw_data_.iov_base);
+	free(d->ras_subevent_data_.iov_base);
+	free(d);
+}
+
+static void cs_pd_set_local_status(struct cs_procedure_data *d,
+				enum cs_procedure_done_status s)
+{
+	if (d)
+		d->local_status = s;
+}
+
+static void cs_pd_set_remote_status(struct cs_procedure_data *d,
+				enum cs_procedure_done_status s)
+{
+	if (d)
+		d->remote_status = s;
+}
+
+static void cs_pd_set_reference_power_levels(struct cs_procedure_data *d,
+					int8_t init_lvl, int8_t ref_lvl)
+{
+	if (!d)
+		return;
+
+	d->initiator_reference_power_level = init_lvl;
+	d->reflector_reference_power_level = ref_lvl;
+}
+
+static void cs_pd_ras_begin_subevent(struct cs_procedure_data *d,
+				uint16_t start_acl_conn_event,
+				uint16_t frequency_compensation,
+				int8_t reference_power_level)
+{
+	if (!d)
+		return;
+
+	d->ras_subevent_counter_++;
+	d->ras_subevent_header_.start_acl_conn_event = start_acl_conn_event;
+	d->ras_subevent_header_.frequency_compensation =
+		frequency_compensation;
+	d->ras_subevent_header_.reference_power_level = reference_power_level;
+	d->ras_subevent_header_.num_steps_reported = 0;
+	d->ras_subevent_header_emitted = false;
+	d->ras_subevent_data_.iov_len = 0;
+}
+
+static bool cs_pd_ras_append_subevent_bytes(struct cs_procedure_data *d,
+					const uint8_t *bytes, size_t len)
+{
+	if (!d || !bytes || len == 0)
+		return false;
+
+	return util_iov_append(&d->ras_subevent_data_, bytes, len) != NULL;
+}
+
+static inline size_t serialize_ras_subevent_header(
+				const struct ras_subevent_header *h,
+				uint8_t *out, size_t out_len)
+{
+	uint16_t start_le;
+	uint16_t freq_le;
+
+	if (!h || !out || out_len < RAS_SUBEVENT_HEADER_SIZE)
+		return 0;
+
+	start_le = (uint16_t)h->start_acl_conn_event;
+	out[0] = (uint8_t)(start_le & 0xFF);
+	out[1] = (uint8_t)((start_le >> 8) & 0xFF);
+
+	freq_le = (uint16_t)h->frequency_compensation;
+	out[2] = (uint8_t)(freq_le & 0xFF);
+	out[3] = (uint8_t)((freq_le >> 8) & 0xFF);
+
+	out[4] = (uint8_t)((h->ranging_done_status & 0x0F) |
+			((h->subevent_done_status & 0x0F) << 4));
+
+	out[5] = (uint8_t)((h->ranging_abort_reason & 0x0F) |
+			((h->subevent_abort_reason & 0x0F) << 4));
+
+	out[6] = (uint8_t)h->reference_power_level;
+	out[7] = (uint8_t)h->num_steps_reported;
+
+	return RAS_SUBEVENT_HEADER_SIZE;
+}
+
+static bool cs_pd_ras_commit_subevent(struct cs_procedure_data *d,
+				uint8_t num_steps_reported,
+				uint8_t ranging_done_status,
+				uint8_t subevent_done_status,
+				uint8_t ranging_abort_reason,
+				uint8_t subevent_abort_reason)
+{
+	size_t hdr_sz;
+	size_t payload_sz;
+	size_t total;
+	uint8_t *buf;
+	size_t w;
+	bool ok;
+
+	if (!d)
+		return false;
+
+	d->ras_subevent_header_.num_steps_reported =
+		(uint8_t)(d->ras_subevent_header_.num_steps_reported +
+			num_steps_reported);
+	d->ras_subevent_header_.ranging_done_status = ranging_done_status;
+	d->ras_subevent_header_.subevent_done_status = subevent_done_status;
+	d->ras_subevent_header_.ranging_abort_reason = ranging_abort_reason;
+	d->ras_subevent_header_.subevent_abort_reason = subevent_abort_reason;
+
+	if (subevent_done_status == SUBEVENT_DONE_ALL_RESULTS_COMPLETE)
+		d->contains_complete_subevent_ = true;
+
+	if (subevent_done_status == SUBEVENT_DONE_PARTIAL_RESULTS)
+		return true;
+
+	if (!d->ras_subevent_header_emitted) {
+		hdr_sz = RAS_SUBEVENT_HEADER_SIZE;
+		payload_sz = d->ras_subevent_data_.iov_len;
+		total = hdr_sz + payload_sz;
+		buf = (uint8_t *)malloc(total);
+
+		if (!buf)
+			return false;
+
+		w = serialize_ras_subevent_header(&d->ras_subevent_header_,
+						buf, total);
+
+		if (w != hdr_sz) {
+			free(buf);
+			return false;
+		}
+
+		if (payload_sz > 0)
+			memcpy(buf + hdr_sz,
+				(const uint8_t *)d->ras_subevent_data_.iov_base,
+				payload_sz);
+
+		ok = util_iov_append(&d->ras_raw_data_, buf, total) != NULL;
+		free(buf);
+
+		if (!ok)
+			return false;
+
+		d->ras_subevent_data_.iov_len = 0;
+		d->ras_subevent_header_emitted = true;
+	}
+
+	return true;
+}
+
 static struct ras *rap_get_ras(struct bt_rap *rap)
 {
 	if (!rap)
@@ -155,6 +531,11 @@ static void rap_free(void *data)
 
 	rap_db_free(rap->rrapdb);
 
+	if (rap->resptracker) {
+		free(rap->resptracker);
+		rap->resptracker = NULL;
+	}
+
 	queue_destroy(rap->notify, free);
 	queue_destroy(rap->pending, NULL);
 	queue_destroy(rap->ready_cbs, rap_ready_free);
@@ -240,6 +621,22 @@ bool bt_rap_set_debug(struct bt_rap *rap, bt_rap_debug_func_t func,
 	return true;
 }
 
+static void cs_tracker_init(struct cstracker *t)
+{
+	if (!t)
+		return;
+
+	memset(t, 0, sizeof(*t));
+	t->role = CS_ROLE_REFLECTOR;
+	t->config_id = CS_INVALID_CONFIG_ID;
+	t->rtt_type = 0;
+	t->selected_tx_power = 0;
+	t->last_proc_counter = 0;
+	t->last_start_acl_conn_evt_counter = 0;
+	t->last_freq_comp = 0;
+	t->last_ref_pwr_lvl = 0;
+}
+
 static void ras_features_read_cb(struct gatt_db_attribute *attrib,
 				 unsigned int id, uint16_t offset,
 				 uint8_t opcode, struct bt_att *att,
@@ -304,6 +701,225 @@ static void ras_data_overwritten_read_cb(struct gatt_db_attribute *attrib,
 	gatt_db_attribute_read_result(attrib, id, 0, value, sizeof(value));
 }
 
+/* CCC write callbacks for custom handling */
+static void ras_realtime_ccc_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct ras *ras = user_data;
+	uint16_t ccc_value;
+
+	if (!ras) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_UNLIKELY);
+		return;
+	}
+
+	if (offset) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_INVALID_OFFSET);
+		return;
+	}
+
+	if (len != 2) {
+		gatt_db_attribute_write_result(attrib, id,
+			BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN);
+		return;
+	}
+
+	ccc_value = get_le16(value);
+
+	if (ccc_value != 0x0000 && ccc_value != 0x0001 &&
+	    ccc_value != 0x0002 && ccc_value != 0x0003) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ERROR_WRITE_REQUEST_REJECTED);
+		return;
+	}
+
+	/* Check mutual exclusivity: reject if trying to enable realtime
+	 * while ondemand is already enabled
+	 */
+	if (ccc_value != 0x0000 && ras->ondemand_ccc_value != 0x0000) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ERROR_CCC_IMPROPERLY_CONFIGURED);
+		return;
+	}
+
+	/* Update state */
+	ras->realtime_ccc_value = ccc_value;
+
+	gatt_db_attribute_write_result(attrib, id, 0);
+}
+
+static void ras_ondemand_ccc_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct ras *ras = user_data;
+	uint16_t ccc_value;
+
+	if (!ras) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_UNLIKELY);
+		return;
+	}
+
+	if (offset) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_INVALID_OFFSET);
+		return;
+	}
+
+	if (len != 2) {
+		gatt_db_attribute_write_result(attrib, id,
+				BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN);
+		return;
+	}
+
+	ccc_value = get_le16(value);
+
+	if (ccc_value != 0x0000 && ccc_value != 0x0001 && ccc_value != 0x0002 &&
+	    ccc_value != 0x0003) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ERROR_WRITE_REQUEST_REJECTED);
+		return;
+	}
+
+	/* Check mutual exclusivity: reject if trying to enable ondemand
+	 * while realtime is already enabled
+	 */
+	if (ccc_value != 0x0000 && ras->realtime_ccc_value != 0x0000) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ERROR_CCC_IMPROPERLY_CONFIGURED);
+		return;
+	}
+
+	/* Update state */
+	ras->ondemand_ccc_value = ccc_value;
+
+	gatt_db_attribute_write_result(attrib, id, 0);
+}
+
+static void ras_cp_ccc_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct ras *ras = user_data;
+	uint16_t ccc_value;
+
+	if (!ras) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_UNLIKELY);
+		return;
+	}
+
+	if (offset) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_INVALID_OFFSET);
+		return;
+	}
+
+	if (len != 2) {
+		gatt_db_attribute_write_result(attrib, id,
+			BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN);
+		return;
+	}
+
+	ccc_value = get_le16(value);
+
+	if (ccc_value != 0x0000 && ccc_value != 0x0001 &&
+	    ccc_value != 0x0002) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ERROR_WRITE_REQUEST_REJECTED);
+		return;
+	}
+
+	gatt_db_attribute_write_result(attrib, id, 0);
+}
+
+static void ras_ready_ccc_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct ras *ras = user_data;
+	uint16_t ccc_value;
+
+	if (!ras) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_UNLIKELY);
+		return;
+	}
+
+	if (offset) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_INVALID_OFFSET);
+		return;
+	}
+
+	if (len != 2) {
+		gatt_db_attribute_write_result(attrib, id,
+			BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN);
+		return;
+	}
+
+	ccc_value = get_le16(value);
+
+	if (ccc_value != 0x0000 && ccc_value != 0x0001 &&
+	    ccc_value != 0x0002 && ccc_value != 0x0003) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ERROR_WRITE_REQUEST_REJECTED);
+		return;
+	}
+
+	gatt_db_attribute_write_result(attrib, id, 0);
+}
+
+static void ras_overwritten_ccc_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct ras *ras = user_data;
+	uint16_t ccc_value;
+
+	if (!ras) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_UNLIKELY);
+		return;
+	}
+
+	if (offset) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_INVALID_OFFSET);
+		return;
+	}
+
+	if (len != 2) {
+		gatt_db_attribute_write_result(attrib, id,
+			BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN);
+		return;
+	}
+
+	ccc_value = get_le16(value);
+
+	if (ccc_value != 0x0000 && ccc_value != 0x0001 &&
+	    ccc_value != 0x0002 && ccc_value != 0x0003) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ERROR_WRITE_REQUEST_REJECTED);
+		return;
+	}
+
+	gatt_db_attribute_write_result(attrib, id, 0);
+}
 /* Service registration – store attribute pointers */
 static struct ras *register_ras_service(struct gatt_db *db)
 {
@@ -349,9 +965,9 @@ static struct ras *register_ras_service(struct gatt_db *db)
 						  NULL, NULL, ras);
 
 	ras->realtime_chrc_ccc =
-		gatt_db_service_add_ccc(ras->svc,
-					BT_ATT_PERM_READ |
-					BT_ATT_PERM_WRITE);
+		gatt_db_service_add_ccc_custom(ras->svc,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+					ras_realtime_ccc_write_cb, ras);
 
 	/* On-demand Ranging Data */
 	bt_uuid16_create(&uuid, RAS_ONDEMAND_DATA_UUID);
@@ -364,8 +980,9 @@ static struct ras *register_ras_service(struct gatt_db *db)
 						  ras_ondemand_read_cb, NULL,
 						  ras);
 
-	gatt_db_service_add_ccc(ras->svc,
-				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+	ras->ondemand_ccc = gatt_db_service_add_ccc_custom(ras->svc,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+					ras_ondemand_ccc_write_cb, ras);
 
 	/* RAS Control Point */
 	bt_uuid16_create(&uuid, RAS_CONTROL_POINT_UUID);
@@ -379,8 +996,9 @@ static struct ras *register_ras_service(struct gatt_db *db)
 						  ras_control_point_write_cb,
 						  ras);
 
-	gatt_db_service_add_ccc(ras->svc,
-				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+	ras->cp_ccc = gatt_db_service_add_ccc_custom(ras->svc,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+					ras_cp_ccc_write_cb, ras);
 
 	/* RAS Data Ready */
 	bt_uuid16_create(&uuid, RAS_DATA_READY_UUID);
@@ -394,8 +1012,9 @@ static struct ras *register_ras_service(struct gatt_db *db)
 						  ras_data_ready_read_cb, NULL,
 						  ras);
 
-	gatt_db_service_add_ccc(ras->svc,
-				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+	ras->ready_ccc = gatt_db_service_add_ccc_custom(ras->svc,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+					ras_ready_ccc_write_cb, ras);
 
 	/* RAS Data Overwritten */
 	bt_uuid16_create(&uuid, RAS_DATA_OVERWRITTEN_UUID);
@@ -409,8 +1028,9 @@ static struct ras *register_ras_service(struct gatt_db *db)
 						  ras_data_overwritten_read_cb,
 						  NULL, ras);
 
-	gatt_db_service_add_ccc(ras->svc,
-				BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+	ras->overwritten_ccc = gatt_db_service_add_ccc_custom(ras->svc,
+					BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+					ras_overwritten_ccc_write_cb, ras);
 
 	/* Activate the service */
 	gatt_db_service_set_active(ras->svc, true);
@@ -503,32 +1123,746 @@ bool bt_rap_unregister(unsigned int id)
 	return true;
 }
 
+static inline size_t serialize_segmentation_header(
+				const struct segmentation_header *s,
+				uint8_t *out, size_t out_len)
+{
+	if (!s || !out || out_len < 1)
+		return 0;
+
+	/* [0] bit0: first, bit1: last, bits2..7: rolling counter */
+	out[0] = (s->first_segment ? 0x01 : 0x00) |
+		(s->last_segment ? 0x02 : 0x00) |
+		((s->rolling_segment_counter & 0x3F) << 2);
+
+	return 1;
+}
+
+static inline size_t serialize_ranging_header(const struct ranging_header *r,
+						uint8_t *out, size_t out_len)
+{
+	uint16_t rcid;
+
+	if (!r || !out || out_len < RAS_RANGING_HEADER_SIZE)
+		return 0;
+
+	/* Little-endian pack: [rc (12 bits) | cfg_id (4 bits)] */
+	rcid = RANGING_HDR_PACK_BYTE0_1(r->ranging_counter,
+					r->configuration_id);
+
+	put_le16(rcid, out + 0);
+	out[2] = (uint8_t)r->selected_tx_power;
+	/* Byte 3: antenna_paths_mask | reserved | pct_format */
+	out[3] = RANGING_HDR_PACK_BYTE3(r->antenna_paths_mask,
+					r->pct_format);
+
+	return RAS_RANGING_HEADER_SIZE;
+}
+
+static inline uint16_t ras_att_value_payload_max(struct bt_rap *rap)
+{
+	struct bt_att *att = bt_rap_get_att(rap);
+	uint16_t mtu = att ? bt_att_get_mtu(att) : default_ras_mtu;
+
+	return (uint16_t)(mtu > ATT_OVERHEAD ?
+		(mtu - ATT_OVERHEAD - TOTAL_RAS_RANGING_HEADER_SIZE -
+		ras_segment_header_size) : 0);
+}
+
+/* Prepend data to an iovec */
+static bool iov_prepend_bytes(struct iovec *iov, const uint8_t *bytes,
+				size_t len)
+{
+	size_t new_len;
+	void *new_base;
+
+	if (!iov || !bytes || len == 0)
+		return false;
+
+	new_len = iov->iov_len + len;
+	new_base = malloc(new_len);
+
+	if (!new_base)
+		return false;
+
+	memcpy(new_base, bytes, len);
+
+	if (iov->iov_len > 0)
+		memcpy((uint8_t *)new_base + len, iov->iov_base,
+			iov->iov_len);
+
+	free(iov->iov_base);
+	iov->iov_base = new_base;
+	iov->iov_len = new_len;
+
+	return true;
+}
+
+/* Append the 4-byte RangingHeader to ras_raw_data_ on first segment */
+static bool ras_maybe_prepend_ranging_header(struct cs_procedure_data *d)
+{
+	uint8_t hdr[RAS_RANGING_HEADER_SIZE];
+	size_t w;
+	bool ok;
+
+	if (!d)
+		return false;
+
+	if (d->ranging_header_prepended_)
+		return false;
+
+	if (!d->segmentation_header_.first_segment)
+		return false;
+
+	if (d->ras_raw_data_index_ != 0)
+		return false;
+
+	w = serialize_ranging_header(&d->ranging_header_, hdr, sizeof(hdr));
+
+	if (w != RAS_RANGING_HEADER_SIZE)
+		return false;
+
+	ok = iov_prepend_bytes(&d->ras_raw_data_, hdr, w);
+
+	if (ok)
+		d->ranging_header_prepended_ = true;
+
+	return ok;
+}
+
+static void send_ras_segment_data(struct bt_rap *rap,
+				struct cs_procedure_data *proc)
+{
+	struct ras *ras;
+	uint16_t value_max;
+	const uint16_t header_len = ras_segment_header_size;
+	uint16_t raw_payload_size;
+	bool ok;
+
+	if (!rap || !proc)
+		return;
+
+	if (!rap->lrapdb || !rap->lrapdb->ras)
+		return;
+	ras = rap->lrapdb->ras;
+	value_max = ras_att_value_payload_max(rap);
+
+	if (value_max == 0) {
+		DBG(rap, "value_max=0 (MTU not available?)");
+		return;
+	}
+
+	if (value_max <= header_len) {
+		DBG(rap, "value_max(%u) too small for header", value_max);
+		return;
+	}
+
+	raw_payload_size = (uint16_t)(value_max - header_len);
+
+	/* Convert tail recursion to loop */
+	while (true) {
+		size_t total_len = proc->ras_raw_data_.iov_len;
+		size_t index = proc->ras_raw_data_index_;
+		size_t unsent_data_size;
+		uint16_t copy_size;
+		uint16_t seg_len;
+		uint8_t *seg;
+		uint16_t wr = 0;
+
+		if (index > total_len)
+			index = total_len;
+
+		unsent_data_size = total_len - index;
+
+		if (unsent_data_size == 0)
+			return;
+
+		/* Set last_segment if procedure complete or fits in segment */
+		if ((proc->local_status != CS_PROC_PARTIAL_RESULTS &&
+				unsent_data_size <= raw_payload_size) ||
+			(proc->contains_complete_subevent_ &&
+				unsent_data_size <= raw_payload_size)) {
+			proc->segmentation_header_.last_segment = 1;
+		} else {
+			proc->segmentation_header_.last_segment = 0;
+		}
+
+		/* Wait for more data if needed and not last segment */
+		if (unsent_data_size < raw_payload_size &&
+				proc->segmentation_header_.last_segment == 0) {
+			DBG(rap, "waiting for more data (unsent=%zu < "
+				"payload=%u)", unsent_data_size,
+				raw_payload_size);
+			return;
+		}
+
+		copy_size = (uint16_t)((unsent_data_size < raw_payload_size) ?
+				unsent_data_size : raw_payload_size);
+		seg_len = (uint16_t)(header_len + copy_size);
+		seg = (uint8_t *)malloc(seg_len);
+
+		if (!seg) {
+			DBG(rap, "OOM (%u)", seg_len);
+			return;
+		}
+
+		wr += (uint16_t)serialize_segmentation_header(
+				&proc->segmentation_header_, seg + wr,
+				seg_len - wr);
+		memcpy(seg + wr,
+			(const uint8_t *)proc->ras_raw_data_.iov_base + index,
+			copy_size);
+		wr += copy_size;
+
+		/* Try sending to real-time characteristic */
+		if (ras->realtime_chrc)
+			ok = gatt_db_attribute_notify(ras->realtime_chrc, seg,
+						wr, bt_rap_get_att(rap));
+
+		/* Try sending to on-demand characteristic */
+		if (ras->ondemand_chrc)
+			ok = gatt_db_attribute_notify(ras->ondemand_chrc, seg,
+						wr, bt_rap_get_att(rap));
+
+		free(seg);
+
+		if (!ok) {
+			DBG(rap, "Failed to send RAS notification");
+			return;
+		}
+
+		/* Advance read cursor and update segmentation state */
+		proc->ras_raw_data_index_ += copy_size;
+		proc->segmentation_header_.first_segment = 0;
+		proc->segmentation_header_.rolling_segment_counter =
+			(uint8_t)((proc->segmentation_header_
+				.rolling_segment_counter + 1) & 0x3F);
+
+		if (proc->segmentation_header_.last_segment ||
+				proc->ras_raw_data_index_ >=
+				proc->ras_raw_data_.iov_len) {
+			DBG(rap, "RAS clear ras buffers");
+			proc->ras_raw_data_.iov_len = 0;
+			proc->ras_raw_data_index_ = 0;
+			proc->ranging_header_prepended_ = false;
+			return;
+		}
+	}
+}
+
+static inline void resptracker_reset_current_proc(struct cstracker *t)
+{
+	if (!t)
+		return;
+
+	if (t->current_proc) {
+		cs_procedure_data_destroy(t->current_proc);
+		t->current_proc = NULL;
+	}
+}
+/* Unified local subevent handler */
+static void handle_local_subevent_result(struct bt_rap *rap,
+					bool has_header_fields,
+					uint8_t config_id,
+					uint8_t num_ant_paths,
+					uint16_t proc_counter,
+					uint16_t start_acl_conn_evt_counter,
+					uint16_t freq_comp,
+					int8_t  ref_pwr_lvl,
+					uint8_t proc_done_status,
+					uint8_t subevt_done_status,
+					uint8_t abort_reason,
+					uint8_t num_steps_reported,
+					const void *step_bytes)
+{
+	struct cstracker *resptracker;
+	struct cs_procedure_data *proc;
+	const struct cs_step_data *steps;
+	uint8_t idx;
+
+	if (!rap || !rap->resptracker || !step_bytes)
+		return;
+
+	resptracker = rap->resptracker;
+
+	if (resptracker->current_proc) {
+		struct cs_procedure_data *cur = resptracker->current_proc;
+
+		if (has_header_fields && cur->counter != proc_counter) {
+			/* Safety: a new procedure; destroy the previous one */
+			resptracker_reset_current_proc(resptracker);
+		}
+	}
+
+	proc = resptracker->current_proc;
+	/* Cache header info from a RESULT event for later CONT usage */
+	if (has_header_fields) {
+		resptracker->last_proc_counter = proc_counter;
+		resptracker->last_start_acl_conn_evt_counter =
+			start_acl_conn_evt_counter;
+		resptracker->last_freq_comp = freq_comp;
+		resptracker->last_ref_pwr_lvl = ref_pwr_lvl;
+	}
+
+	/* Create the procedure on first use */
+	if (!proc) {
+		uint16_t create_counter = has_header_fields ? proc_counter :
+					resptracker->last_proc_counter;
+
+		proc = cs_procedure_data_create(create_counter,
+						num_ant_paths,
+						config_id,
+						resptracker->selected_tx_power);
+		if (!proc)
+			return;
+
+		resptracker->current_proc = proc;
+
+		/* Reference power levels and status defaults */
+		cs_pd_set_reference_power_levels(proc,
+			has_header_fields ? ref_pwr_lvl :
+				resptracker->last_ref_pwr_lvl,
+			has_header_fields ? ref_pwr_lvl :
+				resptracker->last_ref_pwr_lvl);
+		cs_pd_set_local_status(proc,
+			(enum cs_procedure_done_status)proc_done_status);
+		cs_pd_set_remote_status(proc,
+			(enum cs_procedure_done_status)subevt_done_status);
+	}
+
+	/* Begin a new RAS subevent only when we have header fields */
+	if (has_header_fields) {
+		cs_pd_ras_begin_subevent(proc,
+					start_acl_conn_evt_counter,
+					freq_comp,
+					ref_pwr_lvl);
+	}
+
+	/* step_bytes points to an array of struct cs_step_data */
+	steps = (const struct cs_step_data *)step_bytes;
+
+	/* Process each step */
+	for (idx = 0; idx < num_steps_reported; idx++) {
+		const struct cs_step_data *step = &steps[idx];
+		const uint8_t mode = step->step_mode;
+		const uint8_t channel = step->step_chnl;
+		const uint8_t payload_len = step->step_data_length;
+		uint8_t mode_byte;
+		uint8_t mode_type;
+		const uint8_t *payload;
+		uint8_t plen;
+		bool step_aborted;
+
+		/* Check if step is aborted: bit 7 of step_mode or
+		 * 0 payload len
+		 */
+		step_aborted = (mode & RAS_STEP_ABORTED_BIT) ||
+			(payload_len == 0);
+
+		DBG(rap, "step[%u]: mode=0x%02x channel=%u payload_len=%u "
+			"aborted=%s", idx, mode, channel, payload_len,
+			step_aborted ? "YES" : "NO");
+
+		/* Slim-step serialization for RAS:
+		 * - 1 byte: mode (bit7 set if aborted)
+		 * - payload: exactly step_data_length bytes (raw mode data)
+		 */
+		mode_byte = step->step_mode;
+		payload = (const uint8_t *)&step->step_mode_data;
+		plen = step->step_data_length;
+
+		if (step_aborted) {
+			/* Ensure abort bit is set */
+			mode_byte |= RAS_STEP_ABORTED_BIT;
+			cs_pd_ras_append_subevent_bytes(proc, &mode_byte, 1);
+			/* No payload when aborted - per RAS spec Table 3.8 */
+			DBG(rap, "step[%u]: mode=0x%02x aborted, "
+				"no payload sent", idx, mode_byte);
+		} else {
+			mode_type = mode & 0x03;
+
+			/* Mode byte first (without abort bit) */
+			cs_pd_ras_append_subevent_bytes(proc, &mode_byte, 1);
+
+			switch (mode_type) {
+			case CS_MODE_ZERO: {
+				/* Mode 0: use raw structure bytes */
+				payload =
+					(const uint8_t *)&step->step_mode_data;
+				plen = step->step_data_length;
+				cs_pd_ras_append_subevent_bytes(proc,
+								payload, plen);
+				DBG(rap, "step[%u]: mode=0x%02x Mode0 "
+					"payload_len=%u sent",
+					idx, mode_byte, (unsigned int)plen);
+				break;
+			}
+			case CS_MODE_ONE: {
+				const struct cs_mode_one_data *m1 =
+					&step->step_mode_data.mode_one_data;
+				uint8_t buf[16];  /* Max Mode 1 size */
+				uint8_t *p = buf;
+				uint16_t time_val;
+				uint32_t pct1;
+				uint32_t pct2;
+				enum cs_role cs_role = resptracker->role;
+				uint8_t cs_rtt_type = resptracker->rtt_type;
+
+				*p++ = m1->packet_quality;
+				*p++ = m1->packet_nadm;
+				*p++ = m1->packet_rssi_dbm;
+
+				/* Time value (2 bytes LE) - use the
+				 * appropriate field based on role
+				 */
+				if (cs_role == CS_ROLE_REFLECTOR)
+					time_val = m1->tod_toa_refl;
+				else
+					time_val = m1->toa_tod_init;
+
+				*p++ = (uint8_t)(time_val & 0xFF);
+				*p++ = (uint8_t)((time_val >> 8) & 0xFF);
+
+				*p++ = m1->packet_ant;
+
+				/* PCT samples if RTT type contains
+				 * sounding sequence
+				 */
+				if (cs_rtt_type == 0x01 ||
+						cs_rtt_type == 0x02) {
+					pct1 = ((uint32_t)(m1->packet_pct1
+							.i_sample &
+							0x0FFF)) |
+						(((uint32_t)(m1->packet_pct1
+							.q_sample &
+							0x0FFF)) << 12);
+					*p++ = (uint8_t)(pct1 & 0xFF);
+					*p++ = (uint8_t)((pct1 >> 8) & 0xFF);
+					*p++ = (uint8_t)((pct1 >> 16) & 0xFF);
+
+					/* PCT2 (3 bytes) */
+					pct2 = ((uint32_t)(m1->packet_pct2
+							.i_sample &
+							0x0FFF)) |
+						(((uint32_t)(m1->packet_pct2
+							.q_sample &
+							0x0FFF)) << 12);
+					*p++ = (uint8_t)(pct2 & 0xFF);
+					*p++ = (uint8_t)((pct2 >> 8) & 0xFF);
+					*p++ = (uint8_t)((pct2 >> 16) & 0xFF);
+				}
+
+				plen = (uint8_t)(p - buf);
+				cs_pd_ras_append_subevent_bytes(proc, buf,
+								plen);
+				DBG(rap, "step[%u]: mode=0x%02x Mode1 "
+					"serialized payload_len=%u role=%s "
+					"rtt_type=0x%02x",
+					idx, mode_byte, (unsigned int)plen,
+					cs_role == CS_ROLE_INITIATOR ?
+						"INIT" : "REFL", cs_rtt_type);
+				break;
+			}
+			case CS_MODE_TWO: {
+				const struct cs_mode_two_data *m2 =
+					&step->step_mode_data.mode_two_data;
+				/* Max Mode 2 size: 1 + 5*(3+1) = 21 bytes */
+				uint8_t buf[64];
+				uint8_t *p = buf;
+				uint8_t k;
+				uint8_t num_paths = (num_ant_paths + 1) < 5 ?
+					(num_ant_paths + 1) : 5;
+
+				*p++ = m2->ant_perm_index;
+
+				/* Serialize each path: PCT (3 bytes) +
+				 * quality (1 byte)
+				 */
+				for (k = 0; k < num_paths; k++) {
+					/* Convert 4-byte structure PCT to
+					 * 3-byte wire format
+					 */
+					uint32_t pct =
+						((uint32_t)(m2->tone_pct[k]
+							.i_sample &
+							0x0FFF)) |
+						(((uint32_t)(m2->tone_pct[k]
+							.q_sample &
+							0x0FFF)) << 12);
+					*p++ = (uint8_t)(pct & 0xFF);
+					*p++ = (uint8_t)((pct >> 8) & 0xFF);
+					*p++ = (uint8_t)((pct >> 16) & 0xFF);
+
+					*p++ = m2->tone_quality_indicator[k];
+				}
+
+				plen = (uint8_t)(p - buf);
+				cs_pd_ras_append_subevent_bytes(proc, buf,
+								plen);
+				DBG(rap, "step[%u]: mode=0x%02x Mode2 "
+					"serialized payload_len=%u paths=%u",
+					idx, mode_byte, (unsigned int)plen,
+					num_paths);
+				break;
+			}
+			case CS_MODE_THREE: {
+				const struct cs_mode_three_data *m3 =
+					&step->step_mode_data.mode_three_data;
+				const struct cs_mode_one_data *m1 =
+					&m3->mode_one_data;
+				const struct cs_mode_two_data *m2 =
+					&m3->mode_two_data;
+				uint8_t buf[80];  /* Max Mode 3 size */
+				uint8_t *p = buf;
+				uint8_t k;
+				uint32_t pct1;
+				uint32_t pct2;
+				uint8_t num_paths = (num_ant_paths + 1) < 5 ?
+					(num_ant_paths + 1) : 5;
+				uint8_t cs_rtt_type = resptracker->rtt_type;
+				enum cs_role cs_role = resptracker->role;
+				uint16_t time_val;
+				bool include_pct;
+
+				/* Determine if PCT samples should be
+				 * included
+				 */
+				include_pct = (cs_rtt_type == 0x01 ||
+						cs_rtt_type == 0x02) &&
+					(cs_role == CS_ROLE_INITIATOR ||
+						cs_role == CS_ROLE_REFLECTOR);
+
+				/* Mode 1 portion - basic fields */
+				*p++ = m1->packet_quality;
+				*p++ = m1->packet_nadm;
+				*p++ = m1->packet_rssi_dbm;
+
+				/* Time value based on role */
+				if (cs_role == CS_ROLE_REFLECTOR)
+					time_val = m1->tod_toa_refl;
+				else
+					time_val = m1->toa_tod_init;
+
+				*p++ = (uint8_t)(time_val & 0xFF);
+				*p++ = (uint8_t)((time_val >> 8) & 0xFF);
+
+				*p++ = m1->packet_ant;
+
+				/* PCT samples if conditions met */
+				if (include_pct) {
+					pct1 = ((uint32_t)(m1->packet_pct1
+							.i_sample &
+							0x0FFF)) |
+						(((uint32_t)(m1->packet_pct1
+							.q_sample &
+							0x0FFF)) << 12);
+					*p++ = (uint8_t)(pct1 & 0xFF);
+					*p++ = (uint8_t)((pct1 >> 8) & 0xFF);
+					*p++ = (uint8_t)((pct1 >> 16) & 0xFF);
+
+					pct2 = ((uint32_t)(m1->packet_pct2
+							.i_sample &
+							0x0FFF)) |
+						(((uint32_t)(m1->packet_pct2
+							.q_sample &
+							0x0FFF)) << 12);
+					*p++ = (uint8_t)(pct2 & 0xFF);
+					*p++ = (uint8_t)((pct2 >> 8) & 0xFF);
+					*p++ = (uint8_t)((pct2 >> 16) & 0xFF);
+				}
+
+				/* Mode 2 portion */
+				*p++ = m2->ant_perm_index;
+
+				for (k = 0; k < num_paths; k++) {
+					uint32_t pct =
+						((uint32_t)(m2->tone_pct[k]
+							.i_sample &
+							0x0FFF)) |
+						(((uint32_t)(m2->tone_pct[k]
+							.q_sample &
+							0x0FFF)) << 12);
+					*p++ = (uint8_t)(pct & 0xFF);
+					*p++ = (uint8_t)((pct >> 8) & 0xFF);
+					*p++ = (uint8_t)((pct >> 16) & 0xFF);
+
+					*p++ = m2->tone_quality_indicator[k];
+				}
+
+				plen = (uint8_t)(p - buf);
+				cs_pd_ras_append_subevent_bytes(proc, buf,
+								plen);
+				DBG(rap, "step[%u]: mode=0x%02x Mode3 "
+					"serialized payload_len=%u paths=%u "
+					"role=%s rtt_type=0x%02x pct=%s",
+					idx, mode_byte, (unsigned int)plen,
+					num_paths,
+					cs_role == CS_ROLE_INITIATOR ?
+						"INIT" : "REFL",
+					cs_rtt_type,
+					include_pct ? "YES" : "NO");
+				break;
+			}
+			default:
+				/* Unknown mode: use raw structure bytes */
+				payload =
+					(const uint8_t *)&step->step_mode_data;
+				plen = step->step_data_length;
+				cs_pd_ras_append_subevent_bytes(proc, payload,
+								plen);
+				DBG(rap, "step[%u]: mode=0x%02x unknown mode, "
+					"payload_len=%u sent",
+					idx, mode_byte, (unsigned int)plen);
+				break;
+			}
+		}
+	}
+
+	/* Update status for this chunk */
+	cs_pd_set_local_status(proc,
+			(enum cs_procedure_done_status)proc_done_status);
+	cs_pd_set_remote_status(proc,
+			(enum cs_procedure_done_status)subevt_done_status);
+
+	/* Commit subevent chunk (RESULT or CONT) */
+	cs_pd_ras_commit_subevent(proc,
+		num_steps_reported,
+		proc_done_status,
+		subevt_done_status,
+		abort_reason & 0x0F,
+		(abort_reason >> 4) & 0x0F);
+
+	/* Ensure first segment body starts with the 4-byte RangingHeader */
+	ras_maybe_prepend_ranging_header(proc);
+
+	if (subevt_done_status != SUBEVENT_DONE_PARTIAL_RESULTS)
+		/* Send RAS raw segment data */
+		send_ras_segment_data(rap, proc);
+
+	/* Procedure complete? Clean up */
+	if (proc_done_status == CS_PROC_ALL_RESULTS_COMPLETE) {
+		DBG(rap, "Destroying CsProcedureData counter=%u and "
+			"clearing current_proc", proc->counter);
+		resptracker_reset_current_proc(resptracker);
+		/* Reset cached header values for next procedure */
+		resptracker->last_proc_counter = 0;
+		resptracker->last_start_acl_conn_evt_counter = 0;
+		resptracker->last_freq_comp = 0;
+		resptracker->last_ref_pwr_lvl = 0;
+	}
+}
+
+static void form_ras_data_with_cs_subevent_result(struct bt_rap *rap,
+		const struct rap_ev_cs_subevent_result *data,
+		uint16_t length)
+{
+	size_t base_len = offsetof(struct rap_ev_cs_subevent_result,
+					step_data);
+
+	if (!rap || !rap->resptracker || !data)
+		return;
+
+	/* Defensive check: base header must be present */
+	if (length < base_len)
+		return;
+
+	DBG(rap, "Received CS subevent result subevent: len=%d", length);
+
+	handle_local_subevent_result(rap,
+		true,			/* has header fields */
+		data->config_id,
+		data->num_ant_paths,
+		data->proc_counter,
+		data->start_acl_conn_evt_counter,
+		data->freq_comp,
+		data->ref_pwr_lvl,
+		data->proc_done_status,
+		data->subevt_done_status,
+		data->abort_reason,
+		data->num_steps_reported,
+		data->step_data);	/* start of steps */
+}
+static void form_ras_data_with_cs_subevent_result_cont(struct bt_rap *rap,
+		const struct rap_ev_cs_subevent_result_cont *cont,
+		uint16_t length)
+{
+	size_t base_len = offsetof(struct rap_ev_cs_subevent_result_cont,
+					step_data);
+	struct cstracker *resptracker;
+
+	if (!rap || !rap->resptracker || !cont)
+		return;
+
+	if (length < base_len)
+		return;
+
+	DBG(rap, "Received CS subevent result continue subevent: len=%d",
+		length);
+
+	resptracker = rap->resptracker;
+
+	/* Use cached header values captured from the last RESULT event */
+	handle_local_subevent_result(rap,
+		false,			/* CONT has no header fields */
+		cont->config_id,
+		cont->num_ant_paths,
+		resptracker->last_proc_counter,
+		resptracker->last_start_acl_conn_evt_counter,
+		resptracker->last_freq_comp,
+		resptracker->last_ref_pwr_lvl,
+		cont->proc_done_status,
+		cont->subevt_done_status,
+		cont->abort_reason,
+		cont->num_steps_reported,
+		cont->step_data);
+}
 void bt_rap_hci_cs_subevent_result_cont_callback(uint16_t length,
 						const void *param,
 						void *user_data)
 {
+	const struct rap_ev_cs_subevent_result_cont *cont = param;
 	struct bt_rap *rap = user_data;
 
 	DBG(rap, "Received CS subevent CONT: len=%d", length);
+
+	form_ras_data_with_cs_subevent_result_cont(rap, cont, length);
 }
 
 void bt_rap_hci_cs_subevent_result_callback(uint16_t length,
 					const void *param,
 					void *user_data)
 {
+	const struct rap_ev_cs_subevent_result *data = param;
 	struct bt_rap *rap = user_data;
 
 	DBG(rap, "Received CS subevent: len=%d", length);
+
+	/* Populate CsProcedureData and send RAS payload */
+	form_ras_data_with_cs_subevent_result(rap, data, length);
 }
 
 void bt_rap_hci_cs_procedure_enable_complete_callback(uint16_t length,
 						const void *param,
 						void *user_data)
 {
+	const struct rap_ev_cs_proc_enable_cmplt *data = param;
 	struct bt_rap *rap = user_data;
+	struct cstracker *resptracker;
 
 	DBG(rap, "Received CS procedure enable complete subevent: len=%d",
 	    length);
+
+	if (!rap->resptracker) {
+		resptracker = new0(struct cstracker, 1);
+		cs_tracker_init(resptracker);
+		rap->resptracker = resptracker;
+	}
+
+	resptracker = rap->resptracker;
+
+	/* Populate responder tracker */
+	resptracker->config_id = data->config_id;
+	resptracker->selected_tx_power = data->sel_tx_pwr;
 }
 
 void bt_rap_hci_cs_sec_enable_complete_callback(uint16_t length,
@@ -544,9 +1878,27 @@ void bt_rap_hci_cs_config_complete_callback(uint16_t length,
 					const void *param,
 					void *user_data)
 {
+	const struct rap_ev_cs_config_cmplt *data = param;
 	struct bt_rap *rap = user_data;
+	struct cstracker *resptracker;
+
+	if (!rap)
+		return;
 
 	DBG(rap, "Received CS config complete subevent: len=%d", length);
+
+	if (!rap->resptracker) {
+		resptracker = new0(struct cstracker, 1);
+		cs_tracker_init(resptracker);
+		rap->resptracker = resptracker;
+	}
+
+	resptracker = rap->resptracker;
+
+	/* Basic fields */
+	resptracker->config_id = data->config_id;
+	resptracker->role = data->role;
+	resptracker->rtt_type = data->rtt_type;
 }
 
 struct bt_rap *bt_rap_new(struct gatt_db *ldb, struct gatt_db *rdb)
@@ -786,7 +2138,7 @@ bool bt_rap_attach(struct bt_rap *rap, struct bt_gatt_client *client)
 
 	bt_uuid16_create(&uuid, RAS_UUID16);
 
-	gatt_db_foreach_service(rap->lrapdb->db, &uuid,
+	gatt_db_foreach_service(rap->rrapdb->db, &uuid,
 				foreach_rap_service, rap);
 
 	return true;
diff --git a/src/shared/rap.h b/src/shared/rap.h
index 15ddea295..c9431aecd 100644
--- a/src/shared/rap.h
+++ b/src/shared/rap.h
@@ -97,11 +97,11 @@ struct cs_mode_zero_data {
 
 struct cs_mode_one_data {
 	uint8_t packet_quality;
-	uint8_t packet_rssi_dbm;
-	uint8_t packet_ant;
 	uint8_t packet_nadm;
+	uint8_t packet_rssi_dbm;
 	int16_t toa_tod_init;
 	int16_t tod_toa_refl;
+	uint8_t packet_ant;
 	struct pct_iq_sample packet_pct1;
 	struct pct_iq_sample packet_pct2;
 };
-- 
2.34.1


^ permalink raw reply related

* [PATCH BlueZ v5 0/3] Add RAS Packet format and Notification support
From: Prathibha Madugonde @ 2026-04-28  2:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg

From: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>

Changes in v5:
 Fixed Max length err in title

Changes in v4:
 Fixed declaration after statement in src/shared/rap.c

Changes in v3:
 Fix for cs_mode_one_data struct members rearrage as per spec
 Reading of cs_mode_one_data in rap_hci.c
 Address cs_mode data struct padding in src/shared/rap.c 

Changes in v2:
 Fixed missing declaration in src/shared/rap.c

Patch overview:
  1/3 src/shared: Add RAS packet format and sending notifications to client
  2/3 uint/test-rap : Add PTS tests for CS reflector
  3/3 profiles/ranging: Read cs_mode_one_data members as per spec

 profiles/ranging/rap_hci.c |   25 +-
 src/shared/rap.c           | 1376 +++++++++++++++++++++++++++++++++++-
 src/shared/rap.h           |    4 +-
 unit/test-rap.c            |  264 ++++++-
 4 files changed, 1640 insertions(+), 29 deletions(-)

-- 
2.34.1


^ permalink raw reply

* RE: [BlueZ,v1] monitor: Add decoding support for Public Broadcast Announcements
From: bluez.test.bot @ 2026-04-27 21:10 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz
In-Reply-To: <20260427192223.2875358-1-luiz.dentz@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1322 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/project/bluetooth/list/?series=1086393

---Test result---

Test Summary:
CheckPatch                    PASS      0.54 seconds
GitLint                       PASS      0.34 seconds
BuildEll                      PASS      20.43 seconds
BluezMake                     PASS      645.74 seconds
MakeCheck                     PASS      0.94 seconds
MakeDistcheck                 PASS      244.36 seconds
CheckValgrind                 PASS      220.79 seconds
CheckSmatch                   WARNING   346.21 seconds
bluezmakeextell               PASS      180.86 seconds
IncrementalBuild              PASS      647.19 seconds
ScanBuild                     PASS      999.77 seconds

Details
##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
monitor/packet.c:2000:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/bt.h:3866:52: warning: array of flexible structuresmonitor/bt.h:3854:40: warning: array of flexible structures


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

---
Regards,
Linux Bluetooth


^ permalink raw reply

* RE: Add RAS Packet format and Notification support
From: bluez.test.bot @ 2026-04-27 21:01 UTC (permalink / raw)
  To: linux-bluetooth, prathibha.madugonde
In-Reply-To: <20260427170007.1282289-2-prathm@qti.qualcomm.com>

[-- Attachment #1: Type: text/plain, Size: 1667 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/project/bluetooth/list/?series=1086284

---Test result---

Test Summary:
CheckPatch                    PASS      1.60 seconds
GitLint                       FAIL      0.45 seconds
BuildEll                      PASS      17.63 seconds
BluezMake                     PASS      609.86 seconds
MakeCheck                     PASS      0.84 seconds
MakeDistcheck                 PASS      220.24 seconds
CheckValgrind                 PASS      203.58 seconds
CheckSmatch                   PASS      308.93 seconds
bluezmakeextell               PASS      168.18 seconds
IncrementalBuild              PASS      642.41 seconds
ScanBuild                     PASS      929.86 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,v4,1/3] src/shared: Add RAS packet formatting and notification support for CS reflector

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
1: T1 Title exceeds max length (94>80): "[BlueZ,v4,1/3] src/shared: Add RAS packet formatting and notification support for CS reflector"


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

---
Regards,
Linux Bluetooth


^ permalink raw reply

* [Bug 221426] Intel AX211 Bluetooth hci0 hardware error 0x0c with HID/HOG failures on 6.19.14-zen
From: bugzilla-daemon @ 2026-04-27 20:27 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-221426-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=221426

Paul Menzel (pmenzel+bugzilla.kernel.org@molgen.mpg.de) changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |regressions@leemhuis.info

--- Comment #7 from Paul Menzel (pmenzel+bugzilla.kernel.org@molgen.mpg.de) ---
(In reply to Cristian Cocos from comment #5)
> (In reply to Paul Menzel from comment #4)
> > (In reply to Cristian Cocos from comment #3)
> > > I do not recall this issue's happening with the previous Linux kernel
> > > (6.19.13), hence very likely no regression.
> > 
> > Sorry, that is a contradiction, if I am not mistaken. Which not/no is
> wrong?
> > ;-)
> 
> This phenomenon did NOT happen with the previous kernel version (6.19.13). I
> am not familiar with the "regression" jargon: I take it this counts as a ...
> "regression"? If so, please excuse my ignorance, and feel free to ignore my
> previous post.

No problem, I should have been more clear. Yes, a regression is that a new
problem was introduced. And actually that is a good thing, as you can find the
commit introducing the problem. The Linux kernel has a guide how to find that
commit via bisection [1]. It’s also something the user, that means you, could
do to help fixing the issue.


[1]:
https://www.kernel.org/doc/html/latest/admin-guide/reporting-regressions.html

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [Bug 221426] Intel AX211 Bluetooth hci0 hardware error 0x0c with HID/HOG failures on 6.19.14-zen
From: bugzilla-daemon @ 2026-04-27 20:25 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-221426-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=221426

Luiz Von Dentz (luiz.dentz@gmail.com) changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |luiz.dentz@gmail.com

--- Comment #6 from Luiz Von Dentz (luiz.dentz@gmail.com) ---
(In reply to Paul Menzel from comment #2)
> Thank you for your report. Do you know if it’s a regression, that means, did
> it work with earlier Linux versions?
> 
> What firmware is used?
> 
> The BlueZ issue template has some more commands helping to collect things
> aiding in debugging.
> 
> 
> [1]: https://github.com/bluez/bluez/tree/master/.github/ISSUE_TEMPLATE

It might be a good idea to file the issue directly in github if there is a
btmon trace then btsnoop-analyzer is used to analyze it, that said I suspect
this is firmware related if it is really generating a hardware error.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [Bug 221426] Intel AX211 Bluetooth hci0 hardware error 0x0c with HID/HOG failures on 6.19.14-zen
From: bugzilla-daemon @ 2026-04-27 20:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-221426-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=221426

--- Comment #5 from Cristian Cocos (cristi@ieee.org) ---
(In reply to Paul Menzel from comment #4)
> (In reply to Cristian Cocos from comment #3)
> > I do not recall this issue's happening with the previous Linux kernel
> > (6.19.13), hence very likely no regression.
> 
> Sorry, that is a contradiction, if I am not mistaken. Which not/no is wrong?
> ;-)

This phenomenon did NOT happen with the previous kernel version (6.19.13). I am
not familiar with the "regression" jargon: I take it this counts as a ...
"regression"? If so, please excuse my ignorance, and feel free to ignore my
previous post.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [bluez/bluez] a388a8: monitor: Add decoding support for Public Broadcast...
From: Luiz Augusto von Dentz @ 2026-04-27 20:14 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1086393
  Home:   https://github.com/bluez/bluez
  Commit: a388a8bf390b3cdbd1d26f34f924eb394bb7ce5d
      https://github.com/bluez/bluez/commit/a388a8bf390b3cdbd1d26f34f924eb394bb7ce5d
  Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  Date:   2026-04-27 (Mon, 27 Apr 2026)

  Changed paths:
    M monitor/packet.c

  Log Message:
  -----------
  monitor: Add decoding support for Public Broadcast Announcements

This adds support for decoding Public Broadcast Announcements (PBP).



To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [Bug 221426] Intel AX211 Bluetooth hci0 hardware error 0x0c with HID/HOG failures on 6.19.14-zen
From: bugzilla-daemon @ 2026-04-27 20:08 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-221426-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=221426

--- Comment #4 from Paul Menzel (pmenzel+bugzilla.kernel.org@molgen.mpg.de) ---
(In reply to Cristian Cocos from comment #3)
> (In reply to Paul Menzel from comment #2)
> > Thank you for your report. Do you know if it’s a regression, that means,
> did
> > it work with earlier Linux versions?
> 
> I do not recall this issue's happening with the previous Linux kernel
> (6.19.13), hence very likely no regression.

Sorry, that is a contradiction, if I am not mistaken. Which not/no is wrong?
;-)

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply


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