Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v2 00/14] Ranging Profile and Ranging Service PTS fixes
@ 2026-10-09  9:25 Cheng Jiang
  2026-10-09  9:25 ` [PATCH v2 01/14] shared/gatt-client: Allow registering notify with explicit CCC value Cheng Jiang
                   ` (14 more replies)
  0 siblings, 15 replies; 18+ messages in thread
From: Cheng Jiang @ 2026-10-09  9:25 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: jinwang.li, wei.deng, xiuzhuo.shang, shuai.zhang, Cheng Jiang

Changes since v1, from review:

- src/ and unit/ are in separate patches throughout. Two of those splits
  leave the unit tests broken in between: patch 2 changes gatt_db_notify_t
  and patch 3 updates the test callbacks, so on patch 2 alone they do not
  compile; patch 6 advertises Abort Operation in RAS Features and patch 7
  updates the value test-rap expects. src/bluetoothd builds on every patch,
  and the tests pass once each pair is applied. Squashing the pairs would
  avoid it, if you would rather have that.

- gatt_db_attribute_indicate_only() is gone. gatt_db_notify_t now takes the
  ATT opcode of the operation it is serving, the way gatt_db_read_t and
  gatt_db_write_t already do, and gatt-database reads the transport from
  that argument instead of asking the attribute what the current call is
  doing. The test-rap hunk that read the old getter turned out to be dead
  code: that callback is never reached by any of the 25 cases, and dropping
  it leaves them all passing.

Qualifying the existing Ranging Profile and Ranging Service code against PTS
turned up behaviour that does not match the specifications, plus procedures
that were not implemented at all. This series is what the RAP Requester and
RAS Server needed to pass, and the PTS results it records.

Most of it comes down to one thing the GATT layer could not express. RAS
picks the notification or the indication transport per characteristic, and
when a client enables both, the choice is not the same everywhere:

- Ranging Data Ready and Ranging Data Overwritten must be indicated
  (RAS 3.4.2, 3.5.2; RAS/SR/RCO/BV-08-C and BV-09-C).
- On-demand and Real-time Ranging Data must be notified
  (RAS 3.2.2, 3.2.3.1; RAS/SR/RCO/BV-05..07-C and RAS/SR/RRD/BV-03-C).

gatt_db_attribute_notify() prefers notifications whenever the client enabled
them, so a server cannot honour the first rule, and
bt_gatt_client_register_notify() derives the CCC value from the
characteristic properties, so a requester cannot ask for one transport
specifically. Patches 1 to 4 add an entry point for each case.

Patches 5 to 9 apply that on the responder and fill in what the RAS Server
cases exercise: the transport of every notified characteristic now follows
the peer's CCCD, Abort Operation is implemented and advertised in RAS
Features, the requester's Control Point watchdog uses the 5 seconds
RAP 4.5.4.1 specifies, and Real-time Ranging Data is queued so segments are
not dropped when a procedure completes before they are all sent.

Segmented ranging data was also queued a whole transfer at a time, which
starves incoming ATT operations: notifications land on the att write queue,
which pick_next_send_op() drains ahead of the request queue and with no flow
control of its own. It now goes out a segment at a time, gated on
confirmations for indications and on a short delay otherwise, so an Abort
Operation stops a transfer the peer no longer wants instead of having to
wait for it to drain. A real flow control for the notification path, driven
by how much the att write queue has left to send, would be better than that
delay and is left for later.

Patches 10 to 12 add the requester side the RAP cases need: an API to select
Real-time or On-demand reception together with the transport to configure on
the peer, exposed as org.bluez.ChannelSounding1.SetRangingDataMode() and as
a bluetoothctl ranging-data-mode command.

Patches 13 and 14 document the new method and command, and record the
results: 19 RAP and 31 RAS cases pass with PTS 8.14.0.4, run against PTS
pre-generated ranging data (TSPX_test_method), since the PTS dongle in use
does not support Channel Sounding. That covers the RAS protocol behaviour
above but not the HCI Channel Sounding entry path. RAS/SR/SPE/BI-02-C is
listed as not applicable, since RAS.TS Table 5.1 selects it only when Abort
Operation is unsupported and the IUT supports it.

At the tip of the series, unit/test-rap, test-bap, test-bass, test-mcp,
test-micp, test-vcp and test-gatt all pass.

Cheng Jiang (14):
  shared/gatt-client: Allow registering notify with explicit CCC value
  shared/gatt-db: Pass the ATT opcode to the notify callback
  unit: Take the ATT opcode in the notify callbacks
  shared/gatt-db: Add gatt_db_attribute_indicate()
  shared/rap: Honor CCCD transport for RAS on-demand ranging data
  shared/rap: Add RAS Control Point Abort Operation
  unit/test-rap: Expect Abort Operation in RAS Features
  shared/rap: Shorten the requester Control Point response timeout
  shared/rap: Add real-time ranging data delivery on the responder
  shared/rap: Add requester ranging data subscription API
  profiles/ranging: Expose requester ranging data mode over D-Bus
  client: Add Channel Sounding ranging data mode control
  doc: Document Channel Sounding ranging data mode control
  doc/qualification: Add RAP/RAS PTS qualification results

 client/cs.c                        |  87 +++
 doc/bluetoothctl-cs.rst            |  24 +
 doc/org.bluez.ChannelSounding1.rst |  32 ++
 doc/qualification/rap-pts.rst      | 180 ++++++
 doc/qualification/ras-pts.rst      | 135 +++++
 profiles/ranging/rap.c             |  36 ++
 src/gatt-database.c                |  10 +-
 src/shared/gatt-client.c           |  43 +-
 src/shared/gatt-client.h           |   7 +
 src/shared/gatt-db.c               |  21 +-
 src/shared/gatt-db.h               |  15 +-
 src/shared/rap.c                   | 842 ++++++++++++++++++++++++-----
 src/shared/rap.h                   |  23 +
 unit/test-bap.c                    |   3 +-
 unit/test-bass.c                   |   3 +-
 unit/test-mcp.c                    |   3 +-
 unit/test-micp.c                   |   3 +-
 unit/test-rap.c                    |   9 +-
 unit/test-vcp.c                    |   3 +-
 19 files changed, 1335 insertions(+), 144 deletions(-)
 create mode 100644 doc/qualification/rap-pts.rst
 create mode 100644 doc/qualification/ras-pts.rst

-- 
2.43.0


^ permalink raw reply	[flat|nested] 18+ messages in thread
* [PATCH 01/11] shared/gatt-client: Allow registering notify with explicit CCC value
@ 2026-10-01 13:18 Cheng Jiang
  2026-10-01 16:03 ` Ranging Profile and Ranging Service PTS fixes bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Cheng Jiang @ 2026-10-01 13:18 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: jinwang.li, wei.deng, xiuzhuo.shang, shuai.zhang, Cheng Jiang

bt_gatt_client_register_notify() picks the CCC value to write based on
the characteristic properties, preferring notifications over indications
when both are supported. A client that specifically needs one of the two
- for example the Ranging Service, which distinguishes notification and
indication transports - has no way to request it.

Add bt_gatt_client_register_notify_with_ccc() which takes the desired
CCC value (0x0001 for notifications, 0x0002 for indications) and writes
it verbatim. register_notify() gains a ccc_value argument and rejects a
value the characteristic does not support. The existing entry point
keeps its behaviour by passing 0, which restores the property-based
selection.

Assisted-by: Claude:claude-opus-4.8
---
 src/shared/gatt-client.c | 41 +++++++++++++++++++++++++++++++++++-----
 src/shared/gatt-client.h |  7 +++++++
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 92ad7c39c..1cf361f50 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -232,6 +232,7 @@ struct notify_data {
 	uint8_t att_ecode;
 	int ref_count;
 	struct notify_chrc *chrc;
+	uint16_t ccc_value;
 	bt_gatt_client_register_callback_t callback;
 	bt_gatt_client_notify_callback_t notify;
 	void *user_data;
@@ -1670,10 +1671,9 @@ static bool notify_data_write_ccc(struct notify_data *notify_data, bool enable,
 	assert(notify_data->chrc->ccc_handle);
 
 	if (enable) {
-		/* Try to enable notifications or indications based on
-		 * whatever the characteristic supports.
-		 */
-		if (properties & BT_GATT_CHRC_PROP_NOTIFY)
+		if (notify_data->ccc_value)
+			value = cpu_to_le16(notify_data->ccc_value);
+		else if (properties & BT_GATT_CHRC_PROP_NOTIFY)
 			value = cpu_to_le16(0x0001);
 		else if (properties & BT_GATT_CHRC_PROP_INDICATE)
 			value = cpu_to_le16(0x0002);
@@ -1749,6 +1749,7 @@ static bool match_notify_chrc_value_handle(const void *a, const void *b)
 
 static unsigned int register_notify(struct bt_gatt_client *client,
 				uint16_t handle,
+				uint16_t ccc_value,
 				bt_gatt_client_register_callback_t callback,
 				bt_gatt_client_notify_callback_t notify,
 				void *user_data,
@@ -1778,10 +1779,20 @@ static unsigned int register_notify(struct bt_gatt_client *client,
 	if (chrc->notify_count == INT_MAX)
 		return 0;
 
+	if (ccc_value == 0x0001 && !(chrc->properties & BT_GATT_CHRC_PROP_NOTIFY))
+		return 0;
+
+	if (ccc_value == 0x0002 && !(chrc->properties & BT_GATT_CHRC_PROP_INDICATE))
+		return 0;
+
+	if (ccc_value != 0 && ccc_value != 0x0001 && ccc_value != 0x0002)
+		return 0;
+
 	notify_data = new0(struct notify_data, 1);
 	notify_data->client = client;
 	notify_data->ref_count = 1;
 	notify_data->chrc = chrc;
+	notify_data->ccc_value = ccc_value;
 	notify_data->callback = callback;
 	notify_data->notify = notify;
 	notify_data->user_data = user_data;
@@ -1871,6 +1882,7 @@ static bool register_service_changed(struct bt_gatt_client *client)
 	 */
 	client->svc_chngd_ind_id = register_notify(client,
 					gatt_db_attribute_get_handle(attr),
+					0x0002,
 					service_changed_register_cb,
 					service_changed_cb,
 					client, NULL);
@@ -3834,10 +3846,29 @@ unsigned int bt_gatt_client_register_notify(struct bt_gatt_client *client,
 	if (client->in_svc_chngd)
 		return 0;
 
-	return register_notify(client, chrc_value_handle, callback, notify,
+	return register_notify(client, chrc_value_handle, 0, callback, notify,
 							user_data, destroy);
 }
 
+unsigned int bt_gatt_client_register_notify_with_ccc(
+				struct bt_gatt_client *client,
+				uint16_t chrc_value_handle, uint16_t ccc_value,
+				bt_gatt_client_register_callback_t callback,
+				bt_gatt_client_notify_callback_t notify,
+				void *user_data,
+				bt_gatt_client_destroy_func_t destroy)
+{
+	if (!client || !client->db || !chrc_value_handle ||
+			(!callback && !notify) || !ccc_value)
+		return 0;
+
+	if (client->in_svc_chngd)
+		return 0;
+
+	return register_notify(client, chrc_value_handle, ccc_value, callback,
+						notify, user_data, destroy);
+}
+
 bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
 							unsigned int id)
 {
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 63cf99500..1b19c885b 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -122,6 +122,13 @@ unsigned int bt_gatt_client_register_notify(struct bt_gatt_client *client,
 				bt_gatt_client_notify_callback_t notify,
 				void *user_data,
 				bt_gatt_client_destroy_func_t destroy);
+unsigned int bt_gatt_client_register_notify_with_ccc(
+				struct bt_gatt_client *client,
+				uint16_t chrc_value_handle, uint16_t ccc_value,
+				bt_gatt_client_register_callback_t callback,
+				bt_gatt_client_notify_callback_t notify,
+				void *user_data,
+				bt_gatt_client_destroy_func_t destroy);
 bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
 							unsigned int id);
 
-- 
2.43.0


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

end of thread, other threads:[~2026-10-09 17:20 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-09  9:25 [PATCH v2 00/14] Ranging Profile and Ranging Service PTS fixes Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 01/14] shared/gatt-client: Allow registering notify with explicit CCC value Cheng Jiang
2026-10-09 15:42   ` Ranging Profile and Ranging Service PTS fixes bluez.test.bot
2026-10-09  9:25 ` [PATCH v2 02/14] shared/gatt-db: Pass the ATT opcode to the notify callback Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 03/14] unit: Take the ATT opcode in the notify callbacks Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 04/14] shared/gatt-db: Add gatt_db_attribute_indicate() Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 05/14] shared/rap: Honor CCCD transport for RAS on-demand ranging data Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 06/14] shared/rap: Add RAS Control Point Abort Operation Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 07/14] unit/test-rap: Expect Abort Operation in RAS Features Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 08/14] shared/rap: Shorten the requester Control Point response timeout Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 09/14] shared/rap: Add real-time ranging data delivery on the responder Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 10/14] shared/rap: Add requester ranging data subscription API Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 11/14] profiles/ranging: Expose requester ranging data mode over D-Bus Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 12/14] client: Add Channel Sounding ranging data mode control Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 13/14] doc: Document " Cheng Jiang
2026-10-09  9:25 ` [PATCH v2 14/14] doc/qualification: Add RAP/RAS PTS qualification results Cheng Jiang
2026-10-09 17:20 ` [PATCH v2 00/14] Ranging Profile and Ranging Service PTS fixes patchwork-bot+bluetooth
  -- strict thread matches above, loose matches on Subject: below --
2026-10-01 13:18 [PATCH 01/11] shared/gatt-client: Allow registering notify with explicit CCC value Cheng Jiang
2026-10-01 16:03 ` Ranging Profile and Ranging Service PTS fixes 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