From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ 2/4] shared/gatt-db: Add support for notifying attribute changes
Date: Thu, 16 Jul 2020 16:18:55 -0700 [thread overview]
Message-ID: <20200716231857.934396-2-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20200716231857.934396-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This enables to get notified when an attribute has been changed e.g.
it is being removed so the code can detect changes changes at attribute
level.
---
src/shared/gatt-db.c | 103 +++++++++++++++++++++++++++++++++++++++++++
src/shared/gatt-db.h | 8 ++++
2 files changed, 111 insertions(+)
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 5eccab3b9..e939ddc3a 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -81,6 +81,13 @@ struct notify {
void *user_data;
};
+struct attribute_notify {
+ unsigned int id;
+ gatt_db_attribute_cb_t removed;
+ gatt_db_destroy_func_t destroy;
+ void *user_data;
+};
+
struct pending_read {
struct gatt_db_attribute *attrib;
unsigned int id;
@@ -114,6 +121,9 @@ struct gatt_db_attribute {
unsigned int write_id;
struct queue *pending_writes;
+
+ unsigned int next_notify_id;
+ struct queue *notify_list;
};
struct gatt_db_service {
@@ -171,6 +181,16 @@ static void pending_write_free(void *data)
pending_write_result(p, -ECANCELED);
}
+static void attribute_notify_destroy(void *data)
+{
+ struct attribute_notify *notify = data;
+
+ if (notify->destroy)
+ notify->destroy(notify->user_data);
+
+ free(notify);
+}
+
static void attribute_destroy(struct gatt_db_attribute *attribute)
{
/* Attribute was not initialized by user */
@@ -179,6 +199,7 @@ static void attribute_destroy(struct gatt_db_attribute *attribute)
queue_destroy(attribute->pending_reads, pending_read_free);
queue_destroy(attribute->pending_writes, pending_write_free);
+ queue_destroy(attribute->notify_list, attribute_notify_destroy);
free(attribute->value);
free(attribute);
@@ -208,6 +229,7 @@ static struct gatt_db_attribute *new_attribute(struct gatt_db_service *service,
attribute->pending_reads = queue_new();
attribute->pending_writes = queue_new();
+ attribute->notify_list = queue_new();
return attribute;
@@ -352,12 +374,38 @@ static bool db_hash_update(void *user_data)
return false;
}
+static void handle_attribute_notify(void *data, void *user_data)
+{
+ struct attribute_notify *notify = data;
+ struct gatt_db_attribute *attrib = user_data;
+
+ if (notify->removed)
+ notify->removed(attrib, notify->user_data);
+}
+
+static void notify_attribute_changed(struct gatt_db_service *service)
+{
+ int i;
+
+ for (i = 0; i < service->num_handles; i++) {
+ struct gatt_db_attribute *attr = service->attributes[i];
+
+ if (!attr)
+ continue;
+
+ queue_foreach(attr->notify_list, handle_attribute_notify, attr);
+ }
+}
+
static void notify_service_changed(struct gatt_db *db,
struct gatt_db_service *service,
bool added)
{
struct notify_data data;
+ if (!added)
+ notify_attribute_changed(service);
+
if (queue_isempty(db->notify_list))
return;
@@ -1993,3 +2041,58 @@ void *gatt_db_attribute_get_user_data(struct gatt_db_attribute *attrib)
return attrib->user_data;
}
+
+static bool match_attribute_notify_id(const void *a, const void *b)
+{
+ const struct attribute_notify *notify = a;
+ unsigned int id = PTR_TO_UINT(b);
+
+ return notify->id == id;
+}
+
+unsigned int gatt_db_attribute_register(struct gatt_db_attribute *attrib,
+ gatt_db_attribute_cb_t removed,
+ void *user_data,
+ gatt_db_destroy_func_t destroy)
+{
+ struct attribute_notify *notify;
+
+ if (!attrib || !removed)
+ return 0;
+
+ notify = new0(struct attribute_notify, 1);
+ notify->removed = removed;
+ notify->destroy = destroy;
+ notify->user_data = user_data;
+
+ if (attrib->next_notify_id < 1)
+ attrib->next_notify_id = 1;
+
+ notify->id = attrib->next_notify_id++;
+
+ if (!queue_push_tail(attrib->notify_list, notify)) {
+ free(notify);
+ return 0;
+ }
+
+ return notify->id;
+}
+
+bool gatt_db_attribute_unregister(struct gatt_db_attribute *attrib,
+ unsigned int id)
+{
+ struct attribute_notify *notify;
+
+ if (!attrib || !id)
+ return false;
+
+ notify = queue_find(attrib->notify_list, match_attribute_notify_id,
+ UINT_TO_PTR(id));
+ if (!notify)
+ return false;
+
+ queue_remove(attrib->notify_list, notify);
+ attribute_notify_destroy(notify);
+
+ return true;
+}
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index a0fd66c53..5bf19d302 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -281,3 +281,11 @@ bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib,
bool gatt_db_attribute_reset(struct gatt_db_attribute *attrib);
void *gatt_db_attribute_get_user_data(struct gatt_db_attribute *attrib);
+
+unsigned int gatt_db_attribute_register(struct gatt_db_attribute *attrib,
+ gatt_db_attribute_cb_t removed,
+ void *user_data,
+ gatt_db_destroy_func_t destroy);
+
+bool gatt_db_attribute_unregister(struct gatt_db_attribute *attrib,
+ unsigned int id);
--
2.25.3
next prev parent reply other threads:[~2020-07-16 23:19 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-16 23:18 [PATCH BlueZ 1/4] shared/att: Fix possible crash on disconnect Luiz Augusto von Dentz
2020-07-16 23:18 ` Luiz Augusto von Dentz [this message]
2020-07-16 23:18 ` [PATCH BlueZ 3/4] shared/gatt-client: Remove notification if its attribute is removed Luiz Augusto von Dentz
2020-07-16 23:18 ` [PATCH BlueZ 4/4] share/gatt-client: Don't remove active services Luiz Augusto von Dentz
2020-07-16 23:48 ` [BlueZ,1/4] shared/att: Fix possible crash on disconnect bluez.test.bot
2020-07-16 23:51 ` bluez.test.bot
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=20200716231857.934396-2-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.