* [PATCH BlueZ] src/shared: implement custom CCC callbacks for intercepting client notification subscriptions
@ 2026-04-23 15:04 Prathibha Madugonde
2026-04-23 16:08 ` [BlueZ] " bluez.test.bot
0 siblings, 1 reply; 2+ messages in thread
From: Prathibha Madugonde @ 2026-04-23 15:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg
From: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>
---
src/shared/gatt-db.c | 119 ++++++++++++++++++++++++++++++++++++++++++-
src/shared/gatt-db.h | 4 ++
2 files changed, 122 insertions(+), 1 deletion(-)
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index d0e149d6f..87cc61cf3 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -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;
}
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index dc2daf7fc..da0600c01 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -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);
--
2.34.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* RE: [BlueZ] src/shared: implement custom CCC callbacks for intercepting client notification subscriptions
2026-04-23 15:04 [PATCH BlueZ] src/shared: implement custom CCC callbacks for intercepting client notification subscriptions Prathibha Madugonde
@ 2026-04-23 16:08 ` bluez.test.bot
0 siblings, 0 replies; 2+ messages in thread
From: bluez.test.bot @ 2026-04-23 16:08 UTC (permalink / raw)
To: linux-bluetooth, prathibha.madugonde
[-- Attachment #1: Type: text/plain, Size: 1683 bytes --]
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
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-04-23 16:08 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-23 15:04 [PATCH BlueZ] src/shared: implement custom CCC callbacks for intercepting client notification subscriptions Prathibha Madugonde
2026-04-23 16:08 ` [BlueZ] " 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