Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ v1] shared/rap: Track RAS CCC state per connection
@ 2026-10-09 17:33 Luiz Augusto von Dentz
  2026-10-09 19:52 ` [BlueZ,v1] " bluez.test.bot
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Luiz Augusto von Dentz @ 2026-10-09 17:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

The Real-time, On-demand, Ranging Data Ready and Ranging Data Overwritten
CCC values were stored on the RAS service shared by all connections, while
ranging data is sent on the ATT channel of the connection that produced
it. One central's subscription could therefore decide whether, and with
which transport, another central was sent ranging data, and the Real-time
vs On-demand exclusivity check rejected a central because of another
central's configuration.

Store the values on the bt_rap session of the writing connection instead
and use them for the mode, transport and subscription checks.

Fixes: a9b39d71597d ("src/shared: Add RAS packet format and notification support")
Fixes: 2ac9fc0901c4 ("shared/rap: Honor CCCD transport for RAS on-demand ranging data")
Assisted-by: OpenCode:claude-opus-5.5
---
 src/shared/rap.c | 86 ++++++++++++++++++++++++++++--------------------
 1 file changed, 50 insertions(+), 36 deletions(-)

diff --git a/src/shared/rap.c b/src/shared/rap.c
index dae83a17947c..ebf12a6bba31 100644
--- a/src/shared/rap.c
+++ b/src/shared/rap.c
@@ -395,23 +395,17 @@ struct ras {
 	uint16_t ready_counter;
 	uint16_t overwritten_counter;
 
-	/* CCC state tracking for mutual exclusivity */
-	uint16_t realtime_ccc_value;
-	uint16_t ondemand_ccc_value;
-	/* CCC state for Ready/Overwritten so notifications are sent with
-	 * the transport (notification or indication) the client enabled.
-	 */
-	uint16_t ready_ccc_value;
-	uint16_t overwritten_ccc_value;
-
 	/* Initiator role: pending RAS Control Point request state */
 	struct ras_ondemand_client client;
 };
 
-static inline bool ras_is_ondemand_mode(const struct ras *ras)
-{
-	return ras && ras->ondemand_ccc_value != 0;
-}
+/* Responder role: CCC values written by the client of one connection. */
+struct ras_ccc_state {
+	uint16_t realtime;
+	uint16_t ondemand;
+	uint16_t ready;
+	uint16_t overwritten;
+};
 
 /* Initiator role: forward declaration needed by bt_rap_detach() below;
  * defined alongside the other RAS Control Point client helpers.
@@ -494,6 +488,11 @@ struct bt_rap {
 	 */
 	struct ras_ondemand_cache cache;
 
+	/* Responder role: this connection's RAS CCC values, so one central's
+	 * subscription cannot select what another central receives.
+	 */
+	struct ras_ccc_state ras_ccc;
+
 	/* Serialized real-time segments await transport-paced delivery. */
 	struct queue *realtime_segments;
 	unsigned int realtime_send_id;
@@ -501,6 +500,11 @@ struct bt_rap {
 	bool realtime_indicating;
 };
 
+static inline bool ras_is_ondemand_mode(const struct bt_rap *rap)
+{
+	return rap && rap->ras_ccc.ondemand != 0;
+}
+
 static struct queue *rap_db;
 static struct queue *bt_rap_cbs;
 static struct queue *sessions;
@@ -1415,6 +1419,7 @@ static void ras_ranging_data_ccc_write_cb(struct gatt_db_attribute *attrib,
 					void *user_data)
 {
 	struct ras *ras = user_data;
+	struct bt_rap *rap;
 	uint16_t ccc_value;
 	bool is_realtime;
 	uint16_t *this_ccc;
@@ -1426,7 +1431,12 @@ static void ras_ranging_data_ccc_write_cb(struct gatt_db_attribute *attrib,
 		return;
 	}
 
-	bt_rap_get_session(att, ras->rapdb->db);
+	rap = bt_rap_get_session(att, ras->rapdb->db);
+	if (!rap) {
+		gatt_db_attribute_write_result(attrib, id,
+					BT_ATT_ERROR_UNLIKELY);
+		return;
+	}
 
 	if (offset) {
 		gatt_db_attribute_write_result(attrib, id,
@@ -1451,10 +1461,10 @@ static void ras_ranging_data_ccc_write_cb(struct gatt_db_attribute *attrib,
 
 	/* Determine which CCC this is */
 	is_realtime = (attrib == ras->realtime_chrc_ccc);
-	this_ccc = is_realtime ? &ras->realtime_ccc_value :
-				 &ras->ondemand_ccc_value;
-	other_ccc = is_realtime ? &ras->ondemand_ccc_value :
-				  &ras->realtime_ccc_value;
+	this_ccc = is_realtime ? &rap->ras_ccc.realtime :
+				 &rap->ras_ccc.ondemand;
+	other_ccc = is_realtime ? &rap->ras_ccc.ondemand :
+				  &rap->ras_ccc.realtime;
 
 	/* Check mutual exclusivity: reject if trying to enable realtime
 	 * while ondemand is already enabled.
@@ -1487,6 +1497,7 @@ static void ras_ready_overwritten_ccc_write_cb(struct gatt_db_attribute *attrib,
 					void *user_data)
 {
 	struct ras *ras = user_data;
+	struct bt_rap *rap;
 	uint16_t ccc_value;
 
 	if (!ras) {
@@ -1495,6 +1506,13 @@ static void ras_ready_overwritten_ccc_write_cb(struct gatt_db_attribute *attrib,
 		return;
 	}
 
+	rap = bt_rap_get_session(att, ras->rapdb->db);
+	if (!rap) {
+		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);
@@ -1517,9 +1535,9 @@ static void ras_ready_overwritten_ccc_write_cb(struct gatt_db_attribute *attrib,
 	}
 
 	if (attrib == ras->ready_ccc)
-		ras->ready_ccc_value = ccc_value;
+		rap->ras_ccc.ready = ccc_value;
 	else if (attrib == ras->overwritten_ccc)
-		ras->overwritten_ccc_value = ccc_value;
+		rap->ras_ccc.overwritten = ccc_value;
 
 	gatt_db_attribute_write_result(attrib, id, 0);
 }
@@ -1921,7 +1939,7 @@ static void ras_send_ranging_data_ready(struct bt_rap *rap, struct ras *ras,
 
 	ras->ready_counter = counter;
 	put_le16(counter, value);
-	if (ras_ccc_use_indication(ras->ready_ccc_value))
+	if (ras_ccc_use_indication(rap->ras_ccc.ready))
 		gatt_db_attribute_indicate(ras->ready_chrc, value,
 					sizeof(value), bt_rap_get_att(rap));
 	else
@@ -1939,7 +1957,7 @@ static void ras_send_ranging_data_overwritten(struct bt_rap *rap,
 
 	ras->overwritten_counter = counter;
 	put_le16(counter, value);
-	if (ras_ccc_use_indication(ras->overwritten_ccc_value))
+	if (ras_ccc_use_indication(rap->ras_ccc.overwritten))
 		gatt_db_attribute_indicate(ras->overwritten_chrc, value,
 					sizeof(value), bt_rap_get_att(rap));
 	else
@@ -2121,7 +2139,7 @@ static bool send_ondemand_segment_data_cb(void *user_data)
 		 * The delay also bounds a transfer, so keep it short: at a
 		 * 247 byte MTU a 13 KB procedure is 57 segments.
 		 */
-		if (ras_data_ccc_use_indication(ras->ondemand_ccc_value)) {
+		if (ras_data_ccc_use_indication(rap->ras_ccc.ondemand)) {
 			uint16_t vhandle =
 				gatt_db_attribute_get_handle(
 					gatt_db_attribute_get_value(
@@ -2217,7 +2235,7 @@ static void send_ondemand_segment_data(struct bt_rap *rap, struct ras *ras)
 		return;
 
 	/* Ranging data must only reach a client that subscribed to it. */
-	if (!ras->ondemand_ccc_value) {
+	if (!rap->ras_ccc.ondemand) {
 		ras_cp_send_response_code(rap, ras,
 					RAS_CP_RSP_CODE_SERVER_BUSY);
 		return;
@@ -2285,7 +2303,7 @@ static bool send_realtime_segment_cb(void *user_data)
 	if (!segment)
 		return false;
 
-	if (ras_data_ccc_use_indication(ras->realtime_ccc_value)) {
+	if (ras_data_ccc_use_indication(rap->ras_ccc.realtime)) {
 		uint16_t vhandle = gatt_db_attribute_get_handle(
 					gatt_db_attribute_get_value(
 						ras->realtime_chrc));
@@ -2348,7 +2366,7 @@ static void send_ras_segment_data(struct bt_rap *rap,
 		return;
 
 	/* Ranging data must only reach a client that subscribed to it. */
-	if (!rap->lrapdb->ras->realtime_ccc_value)
+	if (!rap->ras_ccc.realtime)
 		return;
 
 	value_max = ras_att_value_payload_max(rap);
@@ -2828,7 +2846,7 @@ static void handle_local_subevent_result(struct bt_rap *rap,
 			/* A new real-time procedure supersedes queued
 			 * old ranging data.
 			 */
-			if (!ras_is_ondemand_mode(rap->lrapdb->ras))
+			if (!ras_is_ondemand_mode(rap))
 				ras_realtime_segments_clear(rap);
 
 			resptracker_reset_current_proc(resptracker);
@@ -2904,20 +2922,16 @@ static void handle_local_subevent_result(struct bt_rap *rap,
 	/* Ensure first segment body starts with the 4-byte RangingHeader */
 	ras_maybe_prepend_ranging_header(proc);
 
-	if (subevt_done_status != SUBEVENT_DONE_PARTIAL_RESULTS) {
-		struct ras *ras = rap->lrapdb ? rap->lrapdb->ras : NULL;
-
-		/* Real-time Ranging mode
-		 */
-		if (!ras_is_ondemand_mode(ras))
-			send_ras_segment_data(rap, proc);
-	}
+	/* Real-time Ranging mode */
+	if (subevt_done_status != SUBEVENT_DONE_PARTIAL_RESULTS &&
+			!ras_is_ondemand_mode(rap))
+		send_ras_segment_data(rap, proc);
 
 	/* Procedure complete? Clean up */
 	if (proc_done_status == CS_PROC_ALL_RESULTS_COMPLETE) {
 		struct ras *ras = rap->lrapdb ? rap->lrapdb->ras : NULL;
 
-		if (ras_is_ondemand_mode(ras)) {
+		if (ras_is_ondemand_mode(rap)) {
 			if (rap->cache.valid) {
 				uint16_t evicted_counter = rap->cache.counter;
 
-- 
2.55.0


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

* RE: [BlueZ,v1] shared/rap: Track RAS CCC state per connection
  2026-10-09 17:33 [PATCH BlueZ v1] shared/rap: Track RAS CCC state per connection Luiz Augusto von Dentz
@ 2026-10-09 19:52 ` bluez.test.bot
  2026-10-10  0:36 ` bluez.test.bot
  2026-10-12 21:50 ` [PATCH BlueZ v1] " patchwork-bot+bluetooth
  2 siblings, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-10-09 19:52 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

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

This is an automated email and please do not reply to this email.

Dear Submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.

----- Output -----

error: patch failed: src/shared/rap.c:395
error: src/shared/rap.c: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

Please resolve the issue and submit the patches again.


---
Regards,
Linux Bluetooth


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

* RE: [BlueZ,v1] shared/rap: Track RAS CCC state per connection
  2026-10-09 17:33 [PATCH BlueZ v1] shared/rap: Track RAS CCC state per connection Luiz Augusto von Dentz
  2026-10-09 19:52 ` [BlueZ,v1] " bluez.test.bot
@ 2026-10-10  0:36 ` bluez.test.bot
  2026-10-12 21:50 ` [PATCH BlueZ v1] " patchwork-bot+bluetooth
  2 siblings, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-10-10  0:36 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

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

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

Dear submitter,

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

---Test result---

Test Summary:
CheckPatch                    PASS      0.45 seconds
GitLint                       PASS      0.27 seconds
BuildEll                      PASS      17.65 seconds
BluezMake                     PASS      308.92 seconds
MakeCheck                     PASS      0.79 seconds
MakeDistcheck                 PASS      131.48 seconds
CheckValgrind                 PASS      140.30 seconds
CheckSmatch                   PASS      248.33 seconds
bluezmakeextell               PASS      94.48 seconds
TestFunctional                PASS      1078.28 seconds
IncrementalBuild              PASS      316.23 seconds
ScanBuild                     PASS      1002.11 seconds



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

---
Regards,
Linux Bluetooth


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

* Re: [PATCH BlueZ v1] shared/rap: Track RAS CCC state per connection
  2026-10-09 17:33 [PATCH BlueZ v1] shared/rap: Track RAS CCC state per connection Luiz Augusto von Dentz
  2026-10-09 19:52 ` [BlueZ,v1] " bluez.test.bot
  2026-10-10  0:36 ` bluez.test.bot
@ 2026-10-12 21:50 ` patchwork-bot+bluetooth
  2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+bluetooth @ 2026-10-12 21:50 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hello:

This patch was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Fri,  9 Oct 2026 13:33:41 -0400 you wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> The Real-time, On-demand, Ranging Data Ready and Ranging Data Overwritten
> CCC values were stored on the RAS service shared by all connections, while
> ranging data is sent on the ATT channel of the connection that produced
> it. One central's subscription could therefore decide whether, and with
> which transport, another central was sent ranging data, and the Real-time
> vs On-demand exclusivity check rejected a central because of another
> central's configuration.
> 
> [...]

Here is the summary with links:
  - [BlueZ,v1] shared/rap: Track RAS CCC state per connection
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=da2406695f70

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2026-10-12 21:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-09 17:33 [PATCH BlueZ v1] shared/rap: Track RAS CCC state per connection Luiz Augusto von Dentz
2026-10-09 19:52 ` [BlueZ,v1] " bluez.test.bot
2026-10-10  0:36 ` bluez.test.bot
2026-10-12 21:50 ` [PATCH BlueZ v1] " patchwork-bot+bluetooth

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