linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/8] doc/gatt-api: Add Handle property
@ 2019-01-30 13:54 Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 2/8] shared/gatt-db: Allow passing 0 as handle to gatt_db_insert_* Luiz Augusto von Dentz
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-30 13:54 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

When acting as server it is useful to select where to allocate the
handle for an attribute so it can be restored in the same position when
restarting the daemon or rebooting the system.

In order to do that the application also needs to know in which handle
the attribute is allocated the very first time it is registered, this
also allows for a better integration with PTS and tools like auto-pts
which needs to know the handles where the attributes have been
allocated.
---
 v2: Fixes inserting characteristics and descriptors with handle 0x0000,
 add a patch to enable list-attribute to list with local attributes and
 print changes to attribute Handle property.

 doc/gatt-api.txt | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
index 8dda60b8a..491eb026a 100644
--- a/doc/gatt-api.txt
+++ b/doc/gatt-api.txt
@@ -50,6 +50,14 @@ Properties	string UUID [read-only]
 			Array of object paths representing the included
 			services of this service.
 
+		uint16 Handle [read-write, optional] (Server Only)
+
+			Service handle. When available in the server it
+			would attempt to use to allocate into the database
+			which may fail, to auto allocate the value 0x0000
+			shall be used which will cause the allocated handle to
+			be set once registered.
+
 
 Characteristic hierarchy
 ========================
@@ -257,6 +265,14 @@ Properties	string UUID [read-only]
 				"secure-write" (Server only)
 				"authorize"
 
+		uint16 Handle [read-write, optional] (Server Only)
+
+			Characteristic handle. When available in the server it
+			would attempt to use to allocate into the database
+			which may fail, to auto allocate the value 0x0000
+			shall be used which will cause the allocated handle to
+			be set once registered.
+
 Characteristic Descriptors hierarchy
 ====================================
 
@@ -332,6 +348,14 @@ Properties	string UUID [read-only]
 				"secure-write" (Server Only)
 				"authorize"
 
+		uint16 Handle [read-write, optional] (Server Only)
+
+			Characteristic handle. When available in the server it
+			would attempt to use to allocate into the database
+			which may fail, to auto allocate the value 0x0000
+			shall be used which will cause the allocated handle to
+			be set once registered.
+
 GATT Profile hierarchy
 =====================
 
-- 
2.17.2


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

* [PATCH v2 2/8] shared/gatt-db: Allow passing 0 as handle to gatt_db_insert_*
  2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
@ 2019-01-30 13:54 ` Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 3/8] gatt: Implement Handle property Luiz Augusto von Dentz
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-30 13:54 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Handle 0 should be allocate on the next handle just as any of
gatt_db_add_* functions.
---
 src/shared/gatt-db.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index d28301ac4..c62255fee 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -525,9 +525,12 @@ struct gatt_db_attribute *gatt_db_insert_service(struct gatt_db *db,
 
 	after = NULL;
 
-	if (!db || handle < 1)
+	if (!db)
 		return NULL;
 
+	if (!handle)
+		handle = db->next_handle;
+
 	if (num_handles < 1 || (handle + num_handles - 1) > UINT16_MAX)
 		return NULL;
 
@@ -585,8 +588,7 @@ struct gatt_db_attribute *gatt_db_add_service(struct gatt_db *db,
 						bool primary,
 						uint16_t num_handles)
 {
-	return gatt_db_insert_service(db, db->next_handle, uuid, primary,
-								num_handles);
+	return gatt_db_insert_service(db, 0, uuid, primary, num_handles);
 }
 
 unsigned int gatt_db_register(struct gatt_db *db,
@@ -768,7 +770,7 @@ gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
 					gatt_db_write_t write_func,
 					void *user_data)
 {
-	if (!attrib || !handle)
+	if (!attrib)
 		return NULL;
 
 	return service_insert_characteristic(attrib->service, handle, uuid,
@@ -856,7 +858,7 @@ gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
 					gatt_db_write_t write_func,
 					void *user_data)
 {
-	if (!attrib || !handle)
+	if (!attrib)
 		return NULL;
 
 	return service_insert_descriptor(attrib->service, handle, uuid,
-- 
2.17.2


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

* [PATCH v2 3/8] gatt: Implement Handle property
  2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 2/8] shared/gatt-db: Allow passing 0 as handle to gatt_db_insert_* Luiz Augusto von Dentz
@ 2019-01-30 13:54 ` Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 4/8] gatt: Write back the handle to " Luiz Augusto von Dentz
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-30 13:54 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This parses the Handle property and if it exists attempt to insert
attributes in their locations.
---
 src/gatt-database.c | 47 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 4 deletions(-)

diff --git a/src/gatt-database.c b/src/gatt-database.c
index 2c2f035b1..025f777eb 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -1839,6 +1839,25 @@ static bool parse_primary(GDBusProxy *proxy, bool *primary)
 	return true;
 }
 
+static bool parse_handle(GDBusProxy *proxy, uint16_t *handle)
+{
+	DBusMessageIter iter;
+
+	/* Handle property is optional */
+	if (!g_dbus_proxy_get_property(proxy, "Handle", &iter)) {
+		*handle = 0;
+		return true;
+	}
+
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT16)
+		return false;
+
+	dbus_message_iter_get_basic(&iter, &handle);
+
+	return true;
+}
+
 static uint8_t dbus_error_to_att_ecode(const char *error_name)
 {
 
@@ -2601,14 +2620,21 @@ fail:
 static bool database_add_desc(struct external_service *service,
 						struct external_desc *desc)
 {
+	uint16_t handle;
 	bt_uuid_t uuid;
 
+	if (!parse_handle(desc->proxy, &handle)) {
+		error("Failed to read \"Handle\" property of descriptor");
+		return false;
+	}
+
 	if (!parse_uuid(desc->proxy, &uuid)) {
 		error("Failed to read \"UUID\" property of descriptor");
 		return false;
 	}
 
-	desc->attrib = gatt_db_service_add_descriptor(service->attrib, &uuid,
+	desc->attrib = gatt_db_service_insert_descriptor(service->attrib,
+							handle, &uuid,
 							desc->perm,
 							desc_read_cb,
 							desc_write_cb, desc);
@@ -2750,9 +2776,15 @@ static void database_add_includes(struct external_service *service)
 static bool database_add_chrc(struct external_service *service,
 						struct external_chrc *chrc)
 {
+	uint16_t handle;
 	bt_uuid_t uuid;
 	const struct queue_entry *entry;
 
+	if (!parse_handle(chrc->proxy, &handle)) {
+		error("Failed to read \"Handle\" property of characteristic");
+		return false;
+	}
+
 	if (!parse_uuid(chrc->proxy, &uuid)) {
 		error("Failed to read \"UUID\" property of characteristic");
 		return false;
@@ -2763,8 +2795,8 @@ static bool database_add_chrc(struct external_service *service,
 		return false;
 	}
 
-	chrc->attrib = gatt_db_service_add_characteristic(service->attrib,
-						&uuid, chrc->perm,
+	chrc->attrib = gatt_db_service_insert_characteristic(service->attrib,
+						handle, &uuid, chrc->perm,
 						chrc->props, chrc_read_cb,
 						chrc_write_cb, chrc);
 	if (!chrc->attrib) {
@@ -2807,6 +2839,7 @@ static bool database_add_service(struct external_service *service)
 {
 	bt_uuid_t uuid;
 	bool primary;
+	uint16_t handle;
 	const struct queue_entry *entry;
 
 	if (!parse_uuid(service->proxy, &uuid)) {
@@ -2824,7 +2857,13 @@ static bool database_add_service(struct external_service *service)
 		return false;
 	}
 
-	service->attrib = gatt_db_add_service(service->app->database->db, &uuid,
+	if (!parse_handle(service->proxy, &handle)) {
+		error("Failed to read \"Handle\" property of service");
+		return false;
+	}
+
+	service->attrib = gatt_db_insert_service(service->app->database->db,
+						handle, &uuid,
 						primary, service->attr_cnt);
 	if (!service->attrib)
 		return false;
-- 
2.17.2


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

* [PATCH v2 4/8] gatt: Write back the handle to Handle property
  2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 2/8] shared/gatt-db: Allow passing 0 as handle to gatt_db_insert_* Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 3/8] gatt: Implement Handle property Luiz Augusto von Dentz
@ 2019-01-30 13:54 ` Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 5/8] client: Enable Handle property for GATT attributes Luiz Augusto von Dentz
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-30 13:54 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

If the application has set an attribute with Handle set to 0 inform the
allocated handle by writting the Handle property.
---
 src/gatt-database.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/src/gatt-database.c b/src/gatt-database.c
index 025f777eb..b159786ea 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -2617,6 +2617,18 @@ fail:
 	gatt_db_attribute_write_result(attrib, id, BT_ATT_ERROR_UNLIKELY);
 }
 
+static void write_handle(struct GDBusProxy *proxy, uint16_t handle)
+{
+	DBusMessageIter iter;
+
+	/* Check if the attribute has the Handle property */
+	if (!g_dbus_proxy_get_property(proxy, "Handle", &iter))
+		return;
+
+	g_dbus_proxy_set_property_basic(proxy, "Handle", DBUS_TYPE_UINT16,
+					&handle, NULL, NULL, NULL);
+}
+
 static bool database_add_desc(struct external_service *service,
 						struct external_desc *desc)
 {
@@ -2645,6 +2657,11 @@ static bool database_add_desc(struct external_service *service,
 
 	desc->handled = true;
 
+	if (!handle) {
+		handle = gatt_db_attribute_get_handle(desc->attrib);
+		write_handle(desc->proxy, handle);
+	}
+
 	return true;
 }
 
@@ -2810,6 +2827,11 @@ static bool database_add_chrc(struct external_service *service,
 	if (!database_add_cep(service, chrc))
 		return false;
 
+	if (!handle) {
+		handle = gatt_db_attribute_get_handle(chrc->attrib);
+		write_handle(chrc->proxy, handle);
+	}
+
 	/* Handle the descriptors that belong to this characteristic. */
 	for (entry = queue_get_entries(service->descs); entry;
 							entry = entry->next) {
@@ -2868,6 +2890,11 @@ static bool database_add_service(struct external_service *service)
 	if (!service->attrib)
 		return false;
 
+	if (!handle) {
+		handle = gatt_db_attribute_get_handle(service->attrib);
+		write_handle(service->proxy, handle);
+	}
+
 	database_add_includes(service);
 
 	entry = queue_get_entries(service->chrcs);
-- 
2.17.2


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

* [PATCH v2 5/8] client: Enable Handle property for GATT attributes
  2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2019-01-30 13:54 ` [PATCH v2 4/8] gatt: Write back the handle to " Luiz Augusto von Dentz
@ 2019-01-30 13:54 ` Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 6/8] client: Enable setting attribute handles Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-30 13:54 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This enable bluetoothd to write back the actual value of attribute
handles.
---
 client/gatt.c | 140 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 124 insertions(+), 16 deletions(-)

diff --git a/client/gatt.c b/client/gatt.c
index b6b517bdf..b29e68136 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -62,6 +62,7 @@
 struct desc {
 	struct chrc *chrc;
 	char *path;
+	uint16_t handle;
 	char *uuid;
 	char **flags;
 	int value_len;
@@ -72,6 +73,7 @@ struct desc {
 struct chrc {
 	struct service *service;
 	char *path;
+	uint16_t handle;
 	char *uuid;
 	char **flags;
 	bool notifying;
@@ -88,6 +90,7 @@ struct chrc {
 struct service {
 	DBusConnection *conn;
 	char *path;
+	uint16_t handle;
 	char *uuid;
 	bool primary;
 	GList *chrcs;
@@ -117,21 +120,25 @@ static void print_service(struct service *service, const char *description)
 
 	text = bt_uuidstr_to_str(service->uuid);
 	if (!text)
-		bt_shell_printf("%s%s%s%s Service\n\t%s\n\t%s\n",
+		bt_shell_printf("%s%s%s%s Service (Handle 0x%04x)\n\t%s\n\t"
+					"%s\n",
 					description ? "[" : "",
 					description ? : "",
 					description ? "] " : "",
 					service->primary ? "Primary" :
 					"Secondary",
-					service->path, service->uuid);
+					service->handle, service->path,
+					service->uuid);
 	else
-		bt_shell_printf("%s%s%s%s Service\n\t%s\n\t%s\n\t%s\n",
+		bt_shell_printf("%s%s%s%s Service (Handle 0x%04x)\n\t%s\n\t%s"
+					"\n\t%s\n",
 					description ? "[" : "",
 					description ? : "",
 					description ? "] " : "",
 					service->primary ? "Primary" :
 					"Secondary",
-					service->path, service->uuid, text);
+					service->handle, service->path,
+					service->uuid, text);
 }
 
 static void print_inc_service(struct service *service, const char *description)
@@ -140,21 +147,25 @@ static void print_inc_service(struct service *service, const char *description)
 
 	text = bt_uuidstr_to_str(service->uuid);
 	if (!text)
-		bt_shell_printf("%s%s%s%s Included Service\n\t%s\n\t%s\n",
+		bt_shell_printf("%s%s%s%s Included Service (Handle 0x%04x)\n\t"
+					"%s\n\t%s\n",
 					description ? "[" : "",
 					description ? : "",
 					description ? "] " : "",
 					service->primary ? "Primary" :
 					"Secondary",
-					service->path, service->uuid);
+					service->handle, service->path,
+					service->uuid);
 	else
-		bt_shell_printf("%s%s%s%s Included Service\n\t%s\n\t%s\n\t%s\n",
+		bt_shell_printf("%s%s%s%s Included Service (Handle 0x%04x)\n\t"
+					"%s\n\t%s\n\t%s\n",
 					description ? "[" : "",
 					description ? : "",
 					description ? "] " : "",
 					service->primary ? "Primary" :
 					"Secondary",
-					service->path, service->uuid, text);
+					service->handle, service->path,
+					service->uuid, text);
 }
 
 static void print_service_proxy(GDBusProxy *proxy, const char *description)
@@ -207,17 +218,20 @@ static void print_chrc(struct chrc *chrc, const char *description)
 
 	text = bt_uuidstr_to_str(chrc->uuid);
 	if (!text)
-		bt_shell_printf("%s%s%sCharacteristic\n\t%s\n\t%s\n",
+		bt_shell_printf("%s%s%sCharacteristic (Handle 0x%04x)\n\t%s\n\t"
+					"%s\n",
 					description ? "[" : "",
 					description ? : "",
 					description ? "] " : "",
-					chrc->path, chrc->uuid);
+					chrc->handle, chrc->path, chrc->uuid);
 	else
-		bt_shell_printf("%s%s%sCharacteristic\n\t%s\n\t%s\n\t%s\n",
+		bt_shell_printf("%s%s%sCharacteristic (Handle 0x%04x)\n\t%s\n\t"
+					"%s\n\t%s\n",
 					description ? "[" : "",
 					description ? : "",
 					description ? "] " : "",
-					chrc->path, chrc->uuid, text);
+					chrc->handle, chrc->path, chrc->uuid,
+					text);
 }
 
 static void print_characteristic(GDBusProxy *proxy, const char *description)
@@ -297,17 +311,20 @@ static void print_desc(struct desc *desc, const char *description)
 
 	text = bt_uuidstr_to_str(desc->uuid);
 	if (!text)
-		bt_shell_printf("%s%s%sDescriptor\n\t%s\n\t%s\n",
+		bt_shell_printf("%s%s%sDescriptor (Handle 0x%04x)\n\t%s\n\t"
+					"%s\n",
 					description ? "[" : "",
 					description ? : "",
 					description ? "] " : "",
-					desc->path, desc->uuid);
+					desc->handle, desc->path, desc->uuid);
 	else
-		bt_shell_printf("%s%s%sDescriptor\n\t%s\n\t%s\n\t%s\n",
+		bt_shell_printf("%s%s%sDescriptor (Handle 0x%04x)\n\t%s\n\t"
+					"%s\n\t%s\n",
 					description ? "[" : "",
 					description ? : "",
 					description ? "] " : "",
-					desc->path, desc->uuid, text);
+					desc->handle, desc->path, desc->uuid,
+					text);
 }
 
 static void print_descriptor(GDBusProxy *proxy, const char *description)
@@ -1259,6 +1276,36 @@ static void service_free(void *data)
 	g_free(service);
 }
 
+static gboolean service_get_handle(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct service *service = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+						&service->handle);
+
+	return TRUE;
+}
+
+static void service_set_handle(const GDBusPropertyTable *property,
+			DBusMessageIter *value, GDBusPendingPropertySet id,
+			void *data)
+{
+	struct service *service = data;
+
+	if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_UINT16) {
+		g_dbus_pending_property_error(id, "org.bluez.InvalidArguments",
+					"Invalid arguments in method call");
+		return;
+	}
+
+	dbus_message_iter_get_basic(value, &service->handle);
+
+	print_service(service, COLORED_CHG);
+
+	g_dbus_pending_property_success(id);
+}
+
 static gboolean service_get_uuid(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -1326,6 +1373,7 @@ static gboolean service_exist_includes(const GDBusPropertyTable *property,
 
 
 static const GDBusPropertyTable service_properties[] = {
+	{ "Handle", "q", service_get_handle, service_set_handle },
 	{ "UUID", "s", service_get_uuid },
 	{ "Primary", "b", service_get_primary },
 	{ "Includes", "ao", service_get_includes,
@@ -1493,6 +1541,35 @@ void gatt_unregister_include(DBusConnection *conn, GDBusProxy *proxy,
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
+static gboolean chrc_get_handle(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct chrc *chrc = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &chrc->handle);
+
+	return TRUE;
+}
+
+static void chrc_set_handle(const GDBusPropertyTable *property,
+			DBusMessageIter *value, GDBusPendingPropertySet id,
+			void *data)
+{
+	struct chrc *chrc = data;
+
+	if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_UINT16) {
+		g_dbus_pending_property_error(id, "org.bluez.InvalidArguments",
+					"Invalid arguments in method call");
+		return;
+	}
+
+	dbus_message_iter_get_basic(value, &chrc->handle);
+
+	print_chrc(chrc, COLORED_CHG);
+
+	g_dbus_pending_property_success(id);
+}
+
 static gboolean chrc_get_uuid(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -1616,6 +1693,7 @@ static gboolean chrc_notify_acquired_exists(const GDBusPropertyTable *property,
 }
 
 static const GDBusPropertyTable chrc_properties[] = {
+	{ "Handle", "s", chrc_get_handle, chrc_set_handle, NULL },
 	{ "UUID", "s", chrc_get_uuid, NULL, NULL },
 	{ "Service", "o", chrc_get_service, NULL, NULL },
 	{ "Value", "ay", chrc_get_value, NULL, NULL },
@@ -2342,6 +2420,35 @@ static const GDBusMethodTable desc_methods[] = {
 	{ }
 };
 
+static gboolean desc_get_handle(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct desc *desc = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &desc->handle);
+
+	return TRUE;
+}
+
+static void desc_set_handle(const GDBusPropertyTable *property,
+			DBusMessageIter *value, GDBusPendingPropertySet id,
+			void *data)
+{
+	struct desc *desc = data;
+
+	if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_UINT16) {
+		g_dbus_pending_property_error(id, "org.bluez.InvalidArguments",
+					"Invalid arguments in method call");
+		return;
+	}
+
+	dbus_message_iter_get_basic(value, &desc->handle);
+
+	print_desc(desc, COLORED_CHG);
+
+	g_dbus_pending_property_success(id);
+}
+
 static gboolean desc_get_uuid(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -2400,6 +2507,7 @@ static gboolean desc_get_flags(const GDBusPropertyTable *property,
 }
 
 static const GDBusPropertyTable desc_properties[] = {
+	{ "Handle", "q", desc_get_handle, desc_set_handle, NULL },
 	{ "UUID", "s", desc_get_uuid, NULL, NULL },
 	{ "Characteristic", "o", desc_get_chrc, NULL, NULL },
 	{ "Value", "ay", desc_get_value, NULL, NULL },
-- 
2.17.2


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

* [PATCH v2 6/8] client: Enable setting attribute handles
  2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2019-01-30 13:54 ` [PATCH v2 5/8] client: Enable Handle property for GATT attributes Luiz Augusto von Dentz
@ 2019-01-30 13:54 ` Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 7/8] client: Enable list-attributes to print local attributes Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-30 13:54 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This emulates application setting their attribute handles.
---
 client/gatt.c       | 11 ++++++++++-
 client/main.c       | 13 +++++++------
 src/gatt-database.c | 24 +++++++++++++++++++-----
 3 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/client/gatt.c b/client/gatt.c
index b29e68136..42fe795d7 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -1410,6 +1410,9 @@ void gatt_register_service(DBusConnection *conn, GDBusProxy *proxy,
 	service->path = g_strdup_printf("%s/service%p", APP_PATH, service);
 	service->primary = primary;
 
+	if (argc > 2)
+		service->handle = atoi(argv[2]);
+
 	if (g_dbus_register_interface(conn, service->path,
 					SERVICE_INTERFACE, NULL, NULL,
 					service_properties, service,
@@ -1693,7 +1696,7 @@ static gboolean chrc_notify_acquired_exists(const GDBusPropertyTable *property,
 }
 
 static const GDBusPropertyTable chrc_properties[] = {
-	{ "Handle", "s", chrc_get_handle, chrc_set_handle, NULL },
+	{ "Handle", "q", chrc_get_handle, chrc_set_handle, NULL },
 	{ "UUID", "s", chrc_get_uuid, NULL, NULL },
 	{ "Service", "o", chrc_get_service, NULL, NULL },
 	{ "Value", "ay", chrc_get_value, NULL, NULL },
@@ -2289,6 +2292,9 @@ void gatt_register_chrc(DBusConnection *conn, GDBusProxy *proxy,
 	chrc->flags = g_strsplit(argv[2], ",", -1);
 	chrc->authorization_req = attr_authorization_flag_exists(chrc->flags);
 
+	if (argc > 3)
+		chrc->handle = atoi(argv[3]);
+
 	if (g_dbus_register_interface(conn, chrc->path, CHRC_INTERFACE,
 					chrc_methods, NULL, chrc_properties,
 					chrc, chrc_free) == FALSE) {
@@ -2555,6 +2561,9 @@ void gatt_register_desc(DBusConnection *conn, GDBusProxy *proxy,
 	desc->path = g_strdup_printf("%s/desc%p", desc->chrc->path, desc);
 	desc->flags = g_strsplit(argv[2], ",", -1);
 
+	if (argc > 3)
+		desc->handle = atoi(argv[3]);
+
 	if (g_dbus_register_interface(conn, desc->path, DESC_INTERFACE,
 					desc_methods, NULL, desc_properties,
 					desc, desc_free) == FALSE) {
diff --git a/client/main.c b/client/main.c
index a4647f334..07c8ec008 100644
--- a/client/main.c
+++ b/client/main.c
@@ -2619,22 +2619,23 @@ static const struct bt_shell_menu gatt_menu = {
 						"Register profile to connect" },
 	{ "unregister-application", NULL, cmd_unregister_app,
 						"Unregister profile" },
-	{ "register-service", "<UUID>", cmd_register_service,
+	{ "register-service", "<UUID> [handle]", cmd_register_service,
 					"Register application service."  },
 	{ "unregister-service", "<UUID/object>", cmd_unregister_service,
 					"Unregister application service" },
-	{ "register-includes", "<UUID>", cmd_register_includes,
+	{ "register-includes", "<UUID> [handle]", cmd_register_includes,
 					"Register as Included service in." },
 	{ "unregister-includes", "<Service-UUID><Inc-UUID>",
 			cmd_unregister_includes,
 				 "Unregister Included service." },
-	{ "register-characteristic", "<UUID> <Flags=read,write,notify...> "
-					, cmd_register_characteristic,
-					"Register application characteristic" },
+	{ "register-characteristic",
+			"<UUID> <Flags=read,write,notify...> [handle]",
+			cmd_register_characteristic,
+			"Register application characteristic" },
 	{ "unregister-characteristic", "<UUID/object>",
 				cmd_unregister_characteristic,
 				"Unregister application characteristic" },
-	{ "register-descriptor", "<UUID> <Flags=read,write...>",
+	{ "register-descriptor", "<UUID> <Flags=read,write...> [handle]",
 					cmd_register_descriptor,
 					"Register application descriptor" },
 	{ "unregister-descriptor", "<UUID/object>",
diff --git a/src/gatt-database.c b/src/gatt-database.c
index b159786ea..cca70c947 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -1843,17 +1843,16 @@ static bool parse_handle(GDBusProxy *proxy, uint16_t *handle)
 {
 	DBusMessageIter iter;
 
+	*handle = 0;
+
 	/* Handle property is optional */
-	if (!g_dbus_proxy_get_property(proxy, "Handle", &iter)) {
-		*handle = 0;
+	if (!g_dbus_proxy_get_property(proxy, "Handle", &iter))
 		return true;
-	}
-
 
 	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT16)
 		return false;
 
-	dbus_message_iter_get_basic(&iter, &handle);
+	dbus_message_iter_get_basic(&iter, handle);
 
 	return true;
 }
@@ -2634,6 +2633,7 @@ static bool database_add_desc(struct external_service *service,
 {
 	uint16_t handle;
 	bt_uuid_t uuid;
+	char str[MAX_LEN_UUID_STR];
 
 	if (!parse_handle(desc->proxy, &handle)) {
 		error("Failed to read \"Handle\" property of descriptor");
@@ -2662,6 +2662,10 @@ static bool database_add_desc(struct external_service *service,
 		write_handle(desc->proxy, handle);
 	}
 
+	bt_uuid_to_string(&uuid, str, sizeof(str));
+
+	DBG("handle 0x%04x UUID %s", handle, str);
+
 	return true;
 }
 
@@ -2795,6 +2799,7 @@ static bool database_add_chrc(struct external_service *service,
 {
 	uint16_t handle;
 	bt_uuid_t uuid;
+	char str[MAX_LEN_UUID_STR];
 	const struct queue_entry *entry;
 
 	if (!parse_handle(chrc->proxy, &handle)) {
@@ -2832,6 +2837,10 @@ static bool database_add_chrc(struct external_service *service,
 		write_handle(chrc->proxy, handle);
 	}
 
+	bt_uuid_to_string(&uuid, str, sizeof(str));
+
+	DBG("handle 0x%04x UUID %s", handle, str);
+
 	/* Handle the descriptors that belong to this characteristic. */
 	for (entry = queue_get_entries(service->descs); entry;
 							entry = entry->next) {
@@ -2863,6 +2872,7 @@ static bool database_add_service(struct external_service *service)
 	bool primary;
 	uint16_t handle;
 	const struct queue_entry *entry;
+	char str[MAX_LEN_UUID_STR];
 
 	if (!parse_uuid(service->proxy, &uuid)) {
 		error("Failed to read \"UUID\" property of service");
@@ -2895,6 +2905,10 @@ static bool database_add_service(struct external_service *service)
 		write_handle(service->proxy, handle);
 	}
 
+	bt_uuid_to_string(&uuid, str, sizeof(str));
+
+	DBG("handle 0x%04x UUID %s", handle, str);
+
 	database_add_includes(service);
 
 	entry = queue_get_entries(service->chrcs);
-- 
2.17.2


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

* [PATCH v2 7/8] client: Enable list-attributes to print local attributes
  2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
                   ` (4 preceding siblings ...)
  2019-01-30 13:54 ` [PATCH v2 6/8] client: Enable setting attribute handles Luiz Augusto von Dentz
@ 2019-01-30 13:54 ` Luiz Augusto von Dentz
  2019-01-30 13:54 ` [PATCH v2 8/8] client: Don't expose pointer value in attribute path Luiz Augusto von Dentz
  2019-01-31 12:17 ` [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
  7 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-30 13:54 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This enable passing "local" to list-attributes to print the attributes
registered locally:

> list-attributes local
Primary Service (Handle 0x0400)
	/org/bluez/app/service0x74ccb0
	0x1820
	Internet Protocol Support
---
 client/gatt.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 client/main.c | 15 ++++++++++++---
 2 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/client/gatt.c b/client/gatt.c
index 42fe795d7..8e06e793f 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -414,8 +414,50 @@ static void list_attributes(const char *path, GList *source)
 	}
 }
 
+static void list_descs(GList *descs)
+{
+	GList *l;
+
+	for (l = descs; l; l = g_list_next(l)) {
+		struct desc *desc = l->data;
+
+		print_desc(desc, NULL);
+	}
+}
+
+static void list_chrcs(GList *chrcs)
+{
+	GList *l;
+
+	for (l = chrcs; l; l = g_list_next(l)) {
+		struct chrc *chrc = l->data;
+
+		print_chrc(chrc, NULL);
+
+		list_descs(chrc->descs);
+	}
+}
+
+static void list_services(void)
+{
+	GList *l;
+
+	for (l = local_services; l; l = g_list_next(l)) {
+		struct service *service = l->data;
+
+		print_service(service, NULL);
+
+		list_chrcs(service->chrcs);
+	}
+}
+
 void gatt_list_attributes(const char *path)
 {
+	if (path && !strcmp(path, "local")) {
+		list_services();
+		return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+	}
+
 	list_attributes(path, services);
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
diff --git a/client/main.c b/client/main.c
index 07c8ec008..16433f96d 100644
--- a/client/main.c
+++ b/client/main.c
@@ -1905,12 +1905,21 @@ static void cmd_disconn(int argc, char *argv[])
 static void cmd_list_attributes(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
+	const char *path;
+
+	if (argc > 1 && !strcmp(argv[1], "local")) {
+		path = argv[1];
+		goto done;
+	}
 
 	proxy = find_device(argc, argv);
 	if (!proxy)
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 
-	gatt_list_attributes(g_dbus_proxy_get_path(proxy));
+	path = g_dbus_proxy_get_path(proxy);
+
+done:
+	gatt_list_attributes(path);
 
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
@@ -2596,8 +2605,8 @@ static const struct bt_shell_menu gatt_menu = {
 	.name = "gatt",
 	.desc = "Generic Attribute Submenu",
 	.entries = {
-	{ "list-attributes", "[dev]", cmd_list_attributes, "List attributes",
-							dev_generator },
+	{ "list-attributes", "[dev/local]", cmd_list_attributes,
+				"List attributes", dev_generator },
 	{ "select-attribute", "<attribute/UUID>",  cmd_select_attribute,
 				"Select attribute", attribute_generator },
 	{ "attribute-info", "[attribute/UUID]",  cmd_attribute_info,
-- 
2.17.2


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

* [PATCH v2 8/8] client: Don't expose pointer value in attribute path
  2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
                   ` (5 preceding siblings ...)
  2019-01-30 13:54 ` [PATCH v2 7/8] client: Enable list-attributes to print local attributes Luiz Augusto von Dentz
@ 2019-01-30 13:54 ` Luiz Augusto von Dentz
  2019-01-31 12:17 ` [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
  7 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-30 13:54 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Instead use the position in the list to create a unique path:

[bluetooth]# register-service 0x1820
[NEW] Primary Service (Handle 0x0000)
	/org/bluez/app/service0
	0x1820
	Internet Protocol Support
---
 client/gatt.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/client/gatt.c b/client/gatt.c
index 8e06e793f..06364a820 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -1449,7 +1449,8 @@ void gatt_register_service(DBusConnection *conn, GDBusProxy *proxy,
 	service = g_new0(struct service, 1);
 	service->conn = conn;
 	service->uuid = g_strdup(argv[1]);
-	service->path = g_strdup_printf("%s/service%p", APP_PATH, service);
+	service->path = g_strdup_printf("%s/service%u", APP_PATH,
+					g_list_length(local_services));
 	service->primary = primary;
 
 	if (argc > 2)
@@ -2330,7 +2331,8 @@ void gatt_register_chrc(DBusConnection *conn, GDBusProxy *proxy,
 	chrc = g_new0(struct chrc, 1);
 	chrc->service = service;
 	chrc->uuid = g_strdup(argv[1]);
-	chrc->path = g_strdup_printf("%s/chrc%p", service->path, chrc);
+	chrc->path = g_strdup_printf("%s/chrc%u", service->path,
+					g_list_length(service->chrcs));
 	chrc->flags = g_strsplit(argv[2], ",", -1);
 	chrc->authorization_req = attr_authorization_flag_exists(chrc->flags);
 
@@ -2600,7 +2602,8 @@ void gatt_register_desc(DBusConnection *conn, GDBusProxy *proxy,
 	desc = g_new0(struct desc, 1);
 	desc->chrc = g_list_last(service->chrcs)->data;
 	desc->uuid = g_strdup(argv[1]);
-	desc->path = g_strdup_printf("%s/desc%p", desc->chrc->path, desc);
+	desc->path = g_strdup_printf("%s/desc%u", desc->chrc->path,
+					g_list_length(desc->chrc->descs));
 	desc->flags = g_strsplit(argv[2], ",", -1);
 
 	if (argc > 3)
-- 
2.17.2


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

* Re: [PATCH v2 1/8] doc/gatt-api: Add Handle property
  2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
                   ` (6 preceding siblings ...)
  2019-01-30 13:54 ` [PATCH v2 8/8] client: Don't expose pointer value in attribute path Luiz Augusto von Dentz
@ 2019-01-31 12:17 ` Luiz Augusto von Dentz
  7 siblings, 0 replies; 9+ messages in thread
From: Luiz Augusto von Dentz @ 2019-01-31 12:17 UTC (permalink / raw)
  To: linux-bluetooth

Hi,
On Wed, Jan 30, 2019 at 3:54 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> When acting as server it is useful to select where to allocate the
> handle for an attribute so it can be restored in the same position when
> restarting the daemon or rebooting the system.
>
> In order to do that the application also needs to know in which handle
> the attribute is allocated the very first time it is registered, this
> also allows for a better integration with PTS and tools like auto-pts
> which needs to know the handles where the attributes have been
> allocated.
> ---
>  v2: Fixes inserting characteristics and descriptors with handle 0x0000,
>  add a patch to enable list-attribute to list with local attributes and
>  print changes to attribute Handle property.
>
>  doc/gatt-api.txt | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
> index 8dda60b8a..491eb026a 100644
> --- a/doc/gatt-api.txt
> +++ b/doc/gatt-api.txt
> @@ -50,6 +50,14 @@ Properties   string UUID [read-only]
>                         Array of object paths representing the included
>                         services of this service.
>
> +               uint16 Handle [read-write, optional] (Server Only)
> +
> +                       Service handle. When available in the server it
> +                       would attempt to use to allocate into the database
> +                       which may fail, to auto allocate the value 0x0000
> +                       shall be used which will cause the allocated handle to
> +                       be set once registered.
> +
>
>  Characteristic hierarchy
>  ========================
> @@ -257,6 +265,14 @@ Properties string UUID [read-only]
>                                 "secure-write" (Server only)
>                                 "authorize"
>
> +               uint16 Handle [read-write, optional] (Server Only)
> +
> +                       Characteristic handle. When available in the server it
> +                       would attempt to use to allocate into the database
> +                       which may fail, to auto allocate the value 0x0000
> +                       shall be used which will cause the allocated handle to
> +                       be set once registered.
> +
>  Characteristic Descriptors hierarchy
>  ====================================
>
> @@ -332,6 +348,14 @@ Properties string UUID [read-only]
>                                 "secure-write" (Server Only)
>                                 "authorize"
>
> +               uint16 Handle [read-write, optional] (Server Only)
> +
> +                       Characteristic handle. When available in the server it
> +                       would attempt to use to allocate into the database
> +                       which may fail, to auto allocate the value 0x0000
> +                       shall be used which will cause the allocated handle to
> +                       be set once registered.
> +
>  GATT Profile hierarchy
>  =====================
>
> --
> 2.17.2

Applied.

-- 
Luiz Augusto von Dentz

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

end of thread, other threads:[~2019-01-31 12:18 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-30 13:54 [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz
2019-01-30 13:54 ` [PATCH v2 2/8] shared/gatt-db: Allow passing 0 as handle to gatt_db_insert_* Luiz Augusto von Dentz
2019-01-30 13:54 ` [PATCH v2 3/8] gatt: Implement Handle property Luiz Augusto von Dentz
2019-01-30 13:54 ` [PATCH v2 4/8] gatt: Write back the handle to " Luiz Augusto von Dentz
2019-01-30 13:54 ` [PATCH v2 5/8] client: Enable Handle property for GATT attributes Luiz Augusto von Dentz
2019-01-30 13:54 ` [PATCH v2 6/8] client: Enable setting attribute handles Luiz Augusto von Dentz
2019-01-30 13:54 ` [PATCH v2 7/8] client: Enable list-attributes to print local attributes Luiz Augusto von Dentz
2019-01-30 13:54 ` [PATCH v2 8/8] client: Don't expose pointer value in attribute path Luiz Augusto von Dentz
2019-01-31 12:17 ` [PATCH v2 1/8] doc/gatt-api: Add Handle property Luiz Augusto von Dentz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).