Skip to contentSkip to conversation

src/shared: implement custom CCC callbacks for intercepting client notification subscriptions

PATCH Applied Prathibha Madugonde 3 participants 3 messages Apr 23 – Apr 24 Bluetooth drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 src/shared: implement custom CCC callbacks for intercepting client notification subscriptions

From: Prathibha Madugonde <[email protected]>

---
 src/shared/gatt-db.c | 119 ++++++++++++++++++++++++++++++++++++++++++-
 src/shared/gatt-db.h |   4 ++
 2 files changed, 122 insertions(+), 1 deletion(-)
src/shared/gatt-db.c +118 -1
index d0e149d6f..87cc61cf3 100644
@@ -1214,6 +1214,112 @@ gatt_db_service_add_ccc(struct gatt_db_attribute *attrib, uint32_t permissions)
 	return ccc;
 }
 
+static void ccc_custom_read(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct gatt_db *db = attrib->service->db;
+
+	db->ccc->read_func(attrib, id, offset, opcode, att, db->ccc->user_data);
+}
+
+static void custom_write_result(struct gatt_db_attribute *attr, int err,
+							void *user_data)
+{
+	int *result = user_data;
+
+	*result = err;
+}
+
+static void ccc_custom_write(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct gatt_db_ccc *data = user_data;
+	struct gatt_db *db = attrib->service->db;
+	struct pending_write *p;
+	int err = 0;
+
+	/* Create another pending write to handle results from custom write
+	 * function.
+	 */
+	p = new0(struct pending_write, 1);
+	p->attrib = attrib;
+	p->id = ++attrib->write_id;
+	p->func = custom_write_result;
+	p->user_data = &err;
+
+	queue_push_tail(attrib->pending_writes, p);
+
+	/* Call custom write function first */
+	data->write_func(attrib, p->id, offset, value, len, opcode, att,
+							data->user_data);
+
+	if (err) {
+		gatt_db_attribute_write_result(attrib, id, err);
+		return;
+	}
+
+	/* If custom write function did not return error proceed to call the
+	 * default CCC write function.
+	 */
+	db->ccc->write_func(attrib, id, offset, value, len, opcode, att,
+							db->ccc->user_data);
+}
+
+struct gatt_db_attribute *
+gatt_db_service_add_ccc_custom(struct gatt_db_attribute *attrib,
+				uint32_t permissions,
+				gatt_db_write_t write_func, void *user_data)
+{
+	struct gatt_db *db;
+	struct gatt_db_attribute *ccc;
+	struct gatt_db_attribute *value;
+	uint16_t handle = 0;
+	struct gatt_db_ccc *data;
+
+	if (!attrib || !permissions)
+		return NULL;
+
+	db = attrib->service->db;
+
+	if (!db->ccc)
+		return NULL;
+
+	/* Locate value handle */
+	gatt_db_service_foreach_char(attrib, find_ccc_value, &handle);
+
+	if (!handle)
+		return NULL;
+
+	value = gatt_db_get_attribute(db, handle);
+	if (!value || value->notify_func)
+		return NULL;
+
+	data = new0(struct gatt_db_ccc, 1);
+	data->write_func = write_func;
+	data->user_data = user_data;
+
+	ccc = service_insert_descriptor(attrib->service, 0, &ccc_uuid,
+					permissions,
+					ccc_custom_read,
+					ccc_custom_write,
+					data);
+	if (!ccc) {
+		free(data);
+		return NULL;
+	}
+
+	gatt_db_attribute_set_fixed_length(ccc, 2);
+	ccc->notify_func = db->ccc->notify_func;
+	value->notify_func = db->ccc->notify_func;
+
+	return ccc;
+}
+
 void gatt_db_ccc_register(struct gatt_db *db, gatt_db_read_t read_func,
 				gatt_db_write_t write_func,
 				gatt_db_notify_t notify_func,
@@ -2338,6 +2444,8 @@ bool gatt_db_attribute_notify(struct gatt_db_attribute *attrib,
 					struct bt_att *att)
 {
 	struct gatt_db_attribute *ccc;
+	struct gatt_db *db;
+	void *notify_user_data;
 
 	if (!attrib || !attrib->notify_func)
 		return false;
@@ -2350,7 +2458,16 @@ bool gatt_db_attribute_notify(struct gatt_db_attribute *attrib,
 	if (!ccc)
 		return false;
 
-	attrib->notify_func(attrib, ccc, value, len, att, ccc->user_data);
+	/* For custom CCC descriptors, use the database user_data for
+	 * notify_func. For regular CCC descriptors, use the CCC's user_data.
+	 */
+	db = attrib->service->db;
+	if (ccc->write_func == ccc_custom_write && db && db->ccc)
+		notify_user_data = db->ccc->user_data;
+	else
+		notify_user_data = ccc->user_data;
+
+	attrib->notify_func(attrib, ccc, value, len, att, notify_user_data);
 
 	return true;
 }
src/shared/gatt-db.h +4 -0
index dc2daf7fc..da0600c01 100644
@@ -112,6 +112,10 @@ gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
 struct gatt_db_attribute *
 gatt_db_service_add_ccc(struct gatt_db_attribute *attrib, uint32_t permissions);
 
+struct gatt_db_attribute *
+gatt_db_service_add_ccc_custom(struct gatt_db_attribute *attrib,
+				uint32_t permissions,
+				gatt_db_write_t write_func, void *user_data);
 struct gatt_db_attribute *
 gatt_db_insert_included(struct gatt_db *db, uint16_t handle,
 			struct gatt_db_attribute *include);
Signature · 1 line
2.34.1
#1 lore raw

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/project/bluetooth/list/?series=1084770

---Test result---

Test Summary:

CheckPatch                    PASS      0.38 seconds
GitLint                       FAIL      0.23 seconds
BuildEll                      PASS      20.05 seconds
BluezMake                     PASS      648.61 seconds
MakeCheck                     PASS      0.99 seconds
MakeDistcheck                 PASS      245.41 seconds
CheckValgrind                 PASS      222.86 seconds
CheckSmatch                   PASS      346.42 seconds
bluezmakeextell               PASS      180.81 seconds
IncrementalBuild              PASS      656.03 seconds
ScanBuild                     PASS      1015.21 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ] src/shared: implement custom CCC callbacks for intercepting client notification subscriptions

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
1: T1 Title exceeds max length (101>80): "[BlueZ] src/shared: implement custom CCC callbacks for intercepting client notification subscriptions"

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

---
Regards,
Linux Bluetooth

#2 lore raw
In reply to Prathibha Madugonde
This patch was applied to bluetooth/bluez.git (master) by Luiz Augusto von Dentz <[email protected]>:

Hello:

This patch was applied to bluetooth/bluez.git (master) by Luiz Augusto von Dentz <[email protected]>:

Quoted 6 lines · On Thu, 23 Apr 2026 20:34:54 +0530 you wrote:

From: Prathibha Madugonde <[email protected]>

---
 src/shared/gatt-db.c | 119 ++++++++++++++++++++++++++++++++++++++++++-
 src/shared/gatt-db.h |   4 ++
 2 files changed, 122 insertions(+), 1 deletion(-)

Here is the summary with links:
- [BlueZ] src/shared: implement custom CCC callbacks for intercepting client notification subscriptions

    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=83ddf46ccc06

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html