Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ v5 0/2] RAP: streamline session handling, reflector setup
@ 2026-07-21  8:41 Naga Bhavani Akella
  2026-07-21  8:41 ` [PATCH BlueZ v5 1/2] rap: use session lookup for RAS operations Naga Bhavani Akella
  2026-07-21  8:41 ` [PATCH BlueZ v5 2/2] profiles: centralize " Naga Bhavani Akella
  0 siblings, 2 replies; 5+ messages in thread
From: Naga Bhavani Akella @ 2026-07-21  8:41 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg,
	Naga Bhavani Akella

This series removes RAS accessed callback bridge and
switches RAP users to direct session lookup.

The first patch refactors the shared RAP layer by introducing explicit
attachment/disconnection helpers, adding bt_rap_get_session(), and
using session lookup directly from the RAS GATT server callbacks.
With all users migrated, the accessed-notification bridge and its public
registration APIs are removed.

The second patch updates the ranging RAP profile accordingly.
Reflector setup is consolidated into a dedicated helper, D-Bus registration
state is tracked explicitly, cleanup is centralized in rap_data_free(), and
RAS accessed callback handling is dropped.


Naga Bhavani Akella (2):
  rap: use session lookup for RAS operations
  profiles: centralize reflector setup

 profiles/ranging/rap.c | 137 +++++++++++++++++++++++++----------------
 src/shared/rap.c       | 107 ++++++++++++++++++++++++++++++--
 src/shared/rap.h       |   2 +
 3 files changed, 189 insertions(+), 57 deletions(-)

-- 


^ permalink raw reply	[flat|nested] 5+ messages in thread
* [PATCH BlueZ v6 1/2] rap: use session lookup for RAS operations
@ 2026-07-27  6:59 Naga Bhavani Akella
  2026-07-27  8:52 ` RAP: streamline session handling, reflector setup bluez.test.bot
  0 siblings, 1 reply; 5+ messages in thread
From: Naga Bhavani Akella @ 2026-07-27  6:59 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg,
	Naga Bhavani Akella

Store disconnect information in RAP state and
centralize attachment handling through dedicated helpers.
Add bt_rap_get_session() and use it from all RAS
GATT server callbacks
---
 src/shared/rap.c | 143 +++++++++++++++++++++++++++++++++++++++++++++--
 src/shared/rap.h |   2 +
 2 files changed, 141 insertions(+), 4 deletions(-)

diff --git a/src/shared/rap.c b/src/shared/rap.c
index dfb272d3a..b0c5f8ae7 100644
--- a/src/shared/rap.c
+++ b/src/shared/rap.c
@@ -19,7 +19,6 @@
 
 #include "src/shared/queue.h"
 #include "src/shared/util.h"
-#include "src/shared/timeout.h"
 #include "src/shared/att.h"
 #include "src/shared/gatt-db.h"
 #include "src/shared/gatt-server.h"
@@ -291,6 +290,7 @@ struct bt_rap {
 	struct bt_att *att;
 
 	unsigned int idle_id;
+	unsigned int disconn_id;
 
 	struct queue *notify;
 	struct queue *pending;
@@ -564,6 +564,40 @@ static void rap_detached(void *data, void *user_data)
 	cb->detached(rap, cb->user_data);
 }
 
+static void rap_attached(void *data, void *user_data)
+{
+	struct bt_rap_cb *cb = data;
+	struct bt_rap *rap = user_data;
+
+	if (!cb->attached)
+		return;
+
+	cb->attached(rap, cb->user_data);
+}
+
+static void rap_disconnected(int err, void *user_data)
+{
+	struct bt_rap *rap = user_data;
+
+	rap->disconn_id = 0;
+
+	bt_rap_detach(rap);
+}
+
+static void rap_attach_att(struct bt_rap *rap, struct bt_att *att)
+{
+	if (rap->disconn_id) {
+		if (att == bt_rap_get_att(rap))
+			return;
+		bt_att_unregister_disconnect(rap->att, rap->disconn_id);
+	}
+
+	rap->att = att;
+	rap->disconn_id = bt_att_register_disconnect(rap->att,
+							rap_disconnected,
+							rap, NULL);
+}
+
 void bt_rap_detach(struct bt_rap *rap)
 {
 	if (!queue_remove(sessions, rap))
@@ -573,6 +607,9 @@ void bt_rap_detach(struct bt_rap *rap)
 	bt_gatt_client_unref(rap->client);
 	rap->client = NULL;
 
+	bt_att_unregister_disconnect(rap->att, rap->disconn_id);
+	rap->att = NULL;
+
 	queue_foreach(bt_rap_cbs, rap_detached, rap);
 }
 
@@ -653,6 +690,34 @@ struct bt_att *bt_rap_get_att(struct bt_rap *rap)
 	return bt_gatt_client_get_att(rap->client);
 }
 
+struct bt_rap *bt_rap_get_session(struct bt_att *att, struct gatt_db *db)
+{
+	const struct queue_entry *entry;
+	struct bt_rap *rap;
+
+	for (entry = queue_get_entries(sessions); entry; entry = entry->next) {
+		rap = entry->data;
+
+		if (att == bt_rap_get_att(rap))
+			return rap;
+	}
+
+	rap = bt_rap_new(db, NULL);
+	if (!rap)
+		return NULL;
+
+	rap->att = att;
+
+	/*
+	 * A rejected attach (e.g. a duplicate session for a device that
+	 * already has one) leaves rap already freed - don't touch it.
+	 */
+	if (!bt_rap_attach(rap, NULL))
+		return NULL;
+
+	return rap;
+}
+
 struct bt_rap *bt_rap_ref(struct bt_rap *rap)
 {
 	if (!rap)
@@ -729,6 +794,7 @@ static void ras_features_read_cb(struct gatt_db_attribute *attrib,
 				 uint8_t opcode, struct bt_att *att,
 				 void *user_data)
 {
+	struct ras *ras = user_data;
 	/*
 	 * Feature mask: bits 0-2 set:
 	 *  - Real-time ranging
@@ -737,6 +803,9 @@ static void ras_features_read_cb(struct gatt_db_attribute *attrib,
 	 */
 	uint8_t value[4] = { 0x01, 0x00, 0x00, 0x00 };
 
+	if (ras)
+		bt_rap_get_session(att, ras->rapdb->db);
+
 	gatt_db_attribute_read_result(attrib, id, 0, value, sizeof(value));
 }
 
@@ -745,6 +814,11 @@ static void ras_ondemand_read_cb(struct gatt_db_attribute *attrib,
 				 uint8_t opcode, struct bt_att *att,
 				 void *user_data)
 {
+	struct ras *ras = user_data;
+
+	if (ras)
+		bt_rap_get_session(att, ras->rapdb->db);
+
 	/* No static read data – on‑demand data is pushed via
 	 * notifications
 	 */
@@ -761,6 +835,11 @@ static void ras_control_point_write_cb(struct gatt_db_attribute *attrib,
 				       uint8_t opcode, struct bt_att *att,
 				       void *user_data)
 {
+	struct ras *ras = user_data;
+
+	if (ras)
+		bt_rap_get_session(att, ras->rapdb->db);
+
 	/* Control point handler - implementation TBD */
 }
 
@@ -770,9 +849,13 @@ static void ras_data_ready_read_cb(struct gatt_db_attribute *attrib,
 				   uint8_t opcode, struct bt_att *att,
 				   void *user_data)
 {
+	struct ras *ras = user_data;
 	uint16_t counter = 0;
 	uint8_t value[2];
 
+	if (ras)
+		bt_rap_get_session(att, ras->rapdb->db);
+
 	put_le16(counter, value);
 	gatt_db_attribute_read_result(attrib, id, 0, value, sizeof(value));
 }
@@ -783,8 +866,12 @@ static void ras_data_overwritten_read_cb(struct gatt_db_attribute *attrib,
 					 uint8_t opcode, struct bt_att *att,
 					 void *user_data)
 {
+	struct ras *ras = user_data;
 	uint8_t value[2] = { 0x00, 0x00 };
 
+	if (ras)
+		bt_rap_get_session(att, ras->rapdb->db);
+
 	gatt_db_attribute_read_result(attrib, id, 0, value, sizeof(value));
 }
 
@@ -806,6 +893,8 @@ static void ras_ranging_data_ccc_write_cb(struct gatt_db_attribute *attrib,
 		return;
 	}
 
+	bt_rap_get_session(att, ras->rapdb->db);
+
 	if (offset) {
 		gatt_db_attribute_write_result(attrib, id,
 					BT_ATT_ERROR_INVALID_OFFSET);
@@ -2794,28 +2883,74 @@ static void rap_idle(void *data)
 bool bt_rap_attach(struct bt_rap *rap, struct bt_gatt_client *client)
 {
 	bt_uuid_t uuid;
+	bool attached;
+
+	if (queue_find(sessions, NULL, rap)) {
+		if (client && !rap->client)
+			goto clone;
+		/*
+		 * Already attached: treat re-attach as idempotent rather
+		 * than failing, so e.g. a second rap_accept() on the same
+		 * session succeeds instead of erroring out.
+		 */
+		return true;
+	}
 
 	if (!sessions)
 		sessions = queue_new();
 
 	queue_push_tail(sessions, rap);
 
-	if (!client)
+	/*
+	 * Notify profile callbacks before rap_attach_att() below runs, so
+	 * bt_rap_get_att(rap) inside a rap_attached callback only sees the
+	 * att already set on rap (e.g. by bt_rap_get_session()), not the
+	 * one about to be registered a few lines down.
+	 *
+	 * A callback may reject this session (e.g. a duplicate ad-hoc
+	 * session for a device that already has one) by unref'ing rap,
+	 * which can free it. Hold our own reference across the
+	 * notification so a rejection can never drop the count to zero
+	 * while callbacks are still running.
+	 *
+	 * Releasing that reference below is what may actually free rap
+	 * (via rap_free() -> bt_rap_detach(), which removes it from
+	 * `sessions` before the object is freed). Check membership only
+	 * *after* the unref, and only by pointer identity - never by
+	 * dereferencing rap - so the check itself is safe even if rap no
+	 * longer exists.
+	 */
+	bt_rap_ref(rap);
+	queue_foreach(bt_rap_cbs, rap_attached, rap);
+	bt_rap_unref(rap);
+
+	attached = queue_find(sessions, NULL, rap);
+	if (!attached)
+		return false;
+
+	if (!client) {
+		if (rap->att)
+			rap_attach_att(rap, rap->att);
 		return true;
+	}
 
 	if (rap->client)
 		return false;
 
+clone:
 	rap->client = bt_gatt_client_clone(client);
 	if (!rap->client)
 		return false;
 
+	rap_attach_att(rap, bt_gatt_client_get_att(client));
+
 	bt_gatt_client_idle_register(rap->client, rap_idle, rap, NULL);
 
 	bt_uuid16_create(&uuid, RAS_UUID16);
 
-	gatt_db_foreach_service(rap->rrapdb->db, &uuid,
-				foreach_rap_service, rap);
+	if (rap->rrapdb)
+		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 5582635e6..a44831e6e 100644
--- a/src/shared/rap.h
+++ b/src/shared/rap.h
@@ -15,6 +15,7 @@
 struct bt_rap;
 struct gatt_db;
 struct bt_gatt_client;
+struct bt_att;
 
 /* Channel Sounding Events */
 struct bt_rap_hci_cs_options {
@@ -171,6 +172,7 @@ bool bt_rap_attach(struct bt_rap *rap, struct bt_gatt_client *client);
 void bt_rap_detach(struct bt_rap *rap);
 
 struct bt_att *bt_rap_get_att(struct bt_rap *rap);
+struct bt_rap *bt_rap_get_session(struct bt_att *att, struct gatt_db *db);
 
 bool bt_rap_set_user_data(struct bt_rap *rap, void *user_data);
 
-- 


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

end of thread, other threads:[~2026-07-27  8:52 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21  8:41 [PATCH BlueZ v5 0/2] RAP: streamline session handling, reflector setup Naga Bhavani Akella
2026-07-21  8:41 ` [PATCH BlueZ v5 1/2] rap: use session lookup for RAS operations Naga Bhavani Akella
2026-07-21  9:48   ` RAP: streamline session handling, reflector setup bluez.test.bot
2026-07-21  8:41 ` [PATCH BlueZ v5 2/2] profiles: centralize " Naga Bhavani Akella
  -- strict thread matches above, loose matches on Subject: below --
2026-07-27  6:59 [PATCH BlueZ v6 1/2] rap: use session lookup for RAS operations Naga Bhavani Akella
2026-07-27  8:52 ` RAP: streamline session handling, reflector setup bluez.test.bot

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