Linux bluetooth development
 help / color / mirror / Atom feed
From: Cheng Jiang <cheng.jiang@oss.qualcomm.com>
To: linux-bluetooth@vger.kernel.org
Cc: jinwang.li@oss.qualcomm.com, wei.deng@oss.qualcomm.com,
	xiuzhuo.shang@oss.qualcomm.com, shuai.zhang@oss.qualcomm.com,
	Cheng Jiang <cheng.jiang@oss.qualcomm.com>
Subject: [PATCH v2 01/14] shared/gatt-client: Allow registering notify with explicit CCC value
Date: Fri,  9 Oct 2026 17:25:17 +0800	[thread overview]
Message-ID: <20261009092532.3600749-2-cheng.jiang@oss.qualcomm.com> (raw)
In-Reply-To: <20261009092532.3600749-1-cheng.jiang@oss.qualcomm.com>

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 | 43 +++++++++++++++++++++++++++++++++++-----
 src/shared/gatt-client.h |  7 +++++++
 2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 95f83fa3e..5c29587bb 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -242,6 +242,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;
@@ -1680,10 +1681,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);
@@ -1759,6 +1759,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,
@@ -1788,10 +1789,22 @@ 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;
@@ -1881,6 +1894,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);
@@ -3852,10 +3866,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 ff90fd8ea..0c5d118c7 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -123,6 +123,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


  reply	other threads:[~2026-10-09  9:25 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-09  9:25 [PATCH v2 00/14] Ranging Profile and Ranging Service PTS fixes Cheng Jiang
2026-10-09  9:25 ` Cheng Jiang [this message]
2026-10-09 15:42   ` 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261009092532.3600749-2-cheng.jiang@oss.qualcomm.com \
    --to=cheng.jiang@oss.qualcomm.com \
    --cc=jinwang.li@oss.qualcomm.com \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=shuai.zhang@oss.qualcomm.com \
    --cc=wei.deng@oss.qualcomm.com \
    --cc=xiuzhuo.shang@oss.qualcomm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox