* [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 v5 1/2] rap: use session lookup for RAS operations
2026-07-21 8:41 [PATCH BlueZ v5 0/2] RAP: streamline session handling, reflector setup Naga Bhavani Akella
@ 2026-07-21 8:41 ` 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
1 sibling, 1 reply; 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
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 instead of the previous accessed
notification bridge. As part of the cleanup,
remove the accessed callback registration APIs,
related notification code, and the unused timeout.h include
---
src/shared/rap.c | 107 +++++++++++++++++++++++++++++++++++++++++++++--
src/shared/rap.h | 2 +
2 files changed, 105 insertions(+), 4 deletions(-)
diff --git a/src/shared/rap.c b/src/shared/rap.c
index dfb272d3a..962b84240 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,29 @@ 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) {
+ struct bt_rap *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;
+
+ bt_rap_attach(rap, NULL);
+
+ return rap;
+}
+
struct bt_rap *bt_rap_ref(struct bt_rap *rap)
{
if (!rap)
@@ -729,6 +789,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 +798,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 +809,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 +830,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 +844,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 +861,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 +888,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);
@@ -2795,27 +2879,42 @@ bool bt_rap_attach(struct bt_rap *rap, struct bt_gatt_client *client)
{
bt_uuid_t uuid;
+ if (queue_find(sessions, NULL, rap)) {
+ if (client && !rap->client)
+ goto clone;
+ return true;
+ }
+
if (!sessions)
sessions = queue_new();
queue_push_tail(sessions, rap);
- if (!client)
+ queue_foreach(bt_rap_cbs, rap_attached, rap);
+
+ 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* [PATCH BlueZ v5 2/2] profiles: centralize reflector setup
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 8:41 ` Naga Bhavani Akella
1 sibling, 0 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
Add a helper for reflector initialization and track D-Bus registration
state in rap_data. Simplify connection handling, move interface cleanup
to object destruction, and streamline removal logic.
Remove the legacy RAS accessed callback path and its registration
handling from initialization and shutdown.
---
profiles/ranging/rap.c | 137 +++++++++++++++++++++++++----------------
1 file changed, 84 insertions(+), 53 deletions(-)
diff --git a/profiles/ranging/rap.c b/profiles/ranging/rap.c
index 3ffc0da76..71cdc592b 100644
--- a/profiles/ranging/rap.c
+++ b/profiles/ranging/rap.c
@@ -65,10 +65,12 @@ struct rap_data {
void *hci_sm; /* Per-device HCI state machine */
uint16_t conn_handle; /* Last known connection handle */
struct cs_session active_session; /* active==false when idle */
+ bool dbus_registered;
};
static struct queue *sessions;
static struct queue *adapter_list; /* List of rap_adapter_data */
+static int rap_setup_reflector(struct rap_data *data);
/* Adapter data management */
static bool match_adapter(const void *data, const void *match_data)
@@ -218,6 +220,13 @@ static bool match_data(const void *data, const void *match_data)
static void rap_data_free(struct rap_data *data)
{
+ if (data->dbus_registered) {
+ g_dbus_unregister_interface(btd_get_dbus_connection(),
+ device_get_path(data->device),
+ CS_INTERFACE);
+ data->dbus_registered = false;
+ }
+
if (data->service) {
btd_service_set_user_data(data->service, NULL);
bt_rap_set_user_data(data->rap, NULL);
@@ -281,14 +290,13 @@ static void rap_attached(struct bt_rap *rap, void *user_data)
struct rap_data *data;
struct bt_att *att;
struct btd_device *device;
+ int err;
DBG("%p", rap);
data = queue_find(sessions, match_data, rap);
- if (data) {
- DBG("data is already present");
- return;
- }
+ if (data)
+ goto setup;
att = bt_rap_get_att(rap);
if (!att) {
@@ -306,6 +314,11 @@ static void rap_attached(struct bt_rap *rap, void *user_data)
data->rap = rap;
rap_data_add(data);
+
+setup:
+ err = rap_setup_reflector(data);
+ if (err)
+ error("Failed to set up reflector session: %d", err);
}
enum cs_dict_target {
@@ -662,19 +675,13 @@ static void rap_remove(struct btd_service *service)
return;
}
- g_dbus_unregister_interface(btd_get_dbus_connection(),
- device_get_path(device),
- CS_INTERFACE);
-
rap_data_remove(data);
}
-static int rap_accept(struct btd_service *service)
+static int rap_setup_reflector(struct rap_data *data)
{
- struct btd_device *device = btd_service_get_device(service);
+ struct btd_device *device = data->device;
struct btd_adapter *adapter = device_get_adapter(device);
- struct bt_gatt_client *client = btd_device_get_gatt_client(device);
- struct rap_data *data = btd_service_get_user_data(service);
struct bt_att *att;
const bdaddr_t *bdaddr;
uint8_t bdaddr_type;
@@ -682,26 +689,18 @@ static int rap_accept(struct btd_service *service)
char addr[18];
ba2str(device_get_address(device), addr);
- DBG("%s", addr);
- if (!data) {
- error("RAP Service not handled by profile");
- return -EINVAL;
- }
-
- /* init shared adapter HCI channel */
- if (!data->adapter_data) {
- data->adapter_data = rap_adapter_data_ref(adapter);
+ if (!data->hci_sm) {
if (!data->adapter_data) {
- error("Failed to get adapter HCI channel");
- return -EINVAL;
+ data->adapter_data = rap_adapter_data_ref(adapter);
+ if (!data->adapter_data) {
+ error("Failed to get adapter HCI channel");
+ return -EINVAL;
+ }
+ DBG("Using shared HCI channel for adapter (ref =%d)",
+ data->adapter_data->ref_count);
}
- DBG("Using shared HCI channel for adapter (ref_count=%d)",
- data->adapter_data->ref_count);
- }
- /* per-device HCI state machine */
- if (!data->hci_sm) {
data->hci_sm = bt_rap_attach_hci(data->rap,
data->adapter_data->hci,
btd_opts.defaults.bcs.role,
@@ -721,38 +720,70 @@ static int rap_accept(struct btd_service *service)
data);
}
- if (!bt_rap_attach(data->rap, client)) {
- error("RAP unable to attach");
- return -EINVAL;
- }
-
- /* Set up connection handle mapping for CS event routing */
- att = bt_rap_get_att(data->rap);
- bdaddr = device_get_address(device);
- bdaddr_type = device_get_le_address_type(device);
-
- if (att && data->adapter_data->hci && data->hci_sm) {
- if (bt_hci_get_conn_handle(data->adapter_data->hci,
- (const uint8_t *) bdaddr, &handle)) {
- DBG("Found conn handle 0x%04X for %s", handle, addr);
- data->conn_handle = handle;
- bt_rap_set_conn_hndl(data->hci_sm,
+ /* Set up connection handle mapping for CS event routing. Retried on
+ * every call until it succeeds, since att may not be available yet
+ * the first time this runs (e.g. called from bt_rap_attach()'s
+ * attached callback before rap->client/att are set).
+ */
+ if (!data->conn_handle) {
+ att = bt_rap_get_att(data->rap);
+ bdaddr = device_get_address(device);
+ bdaddr_type = device_get_le_address_type(device);
+
+ if (att && data->adapter_data->hci) {
+ if (bt_hci_get_conn_handle(data->adapter_data->hci,
+ (const uint8_t *)bdaddr, &handle)) {
+ DBG("conn handle 0x%04X for %s", handle, addr);
+ data->conn_handle = handle;
+ bt_rap_set_conn_hndl(data->hci_sm,
data->rap, handle,
- (const uint8_t *) bdaddr,
+ (const uint8_t *)bdaddr,
bdaddr_type,
btd_device_is_initiator(device));
- } else {
- error("Failed to find connection handle for device %s",
- addr);
+ } else {
+ error("Failed to find conn for device %s",
+ addr);
+ }
}
}
- btd_service_connecting_complete(service, 0);
+ if (!data->dbus_registered) {
+ g_dbus_register_interface(btd_get_dbus_connection(),
+ device_get_path(device),
+ CS_INTERFACE, cs_dbus_methods,
+ NULL, cs_dbus_properties, data, NULL);
+ data->dbus_registered = true;
+ }
+
+ return 0;
+}
+
+static int rap_accept(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ struct bt_gatt_client *client = btd_device_get_gatt_client(device);
+ struct rap_data *data = btd_service_get_user_data(service);
+ char addr[18];
+ int err;
- g_dbus_register_interface(btd_get_dbus_connection(),
- device_get_path(data->device),
- CS_INTERFACE, cs_dbus_methods,
- NULL, cs_dbus_properties, data, NULL);
+ ba2str(device_get_address(device), addr);
+ DBG("%s", addr);
+
+ if (!data) {
+ error("RAP Service not handled by profile");
+ return -EINVAL;
+ }
+
+ if (!bt_rap_attach(data->rap, client)) {
+ error("RAP unable to attach");
+ return -EINVAL;
+ }
+
+ err = rap_setup_reflector(data);
+ if (err)
+ return err;
+
+ btd_service_connecting_complete(service, 0);
return 0;
}
--
^ permalink raw reply related [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