[PATCH BlueZ 2/2] core/gatt-client: Add support for Includes property

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add implementation of Includes property in GATT service interface.
---
 src/gatt-client.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 136 insertions(+), 8 deletions(-)

diff --git a/src/gatt-client.c b/src/gatt-client.c
index 114981c..15219e2 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
@@ -72,6 +72,15 @@ struct service {
 	bt_uuid_t uuid;
 	char *path;
 	struct queue *chrcs;
+	struct queue *incl_services;
+};
+
+struct incl_service {
+	uint16_t handle;
+	uint16_t start_handle;
+	uint16_t end_handle;
+	struct service *service;
+	struct service *incl_service;
 };
 
 typedef bool (*async_dbus_op_complete_t)(void *data);
@@ -1398,10 +1407,39 @@ static gboolean service_get_primary(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static void append_incl_service_path(void *data, void *user_data)
+{
+	struct incl_service *incl_service = data;
+	DBusMessageIter *array = user_data;
+
+	if (!incl_service->incl_service)
+		return;
+
+	dbus_message_iter_append_basic(array, DBUS_TYPE_OBJECT_PATH,
+					&incl_service->incl_service->path);
+}
+
+static gboolean service_get_includes(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct service *service = data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{o}", &array);
+
+	queue_foreach(service->incl_services, append_incl_service_path, &array);
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+
+}
+
 static const GDBusPropertyTable service_properties[] = {
 	{ "UUID", "s", service_get_uuid },
 	{ "Device", "o", service_get_device },
 	{ "Primary", "b", service_get_primary },
+	{ "Includes", "ao", service_get_includes },
 	{ }
 };
 
@@ -1410,10 +1448,40 @@ static void service_free(void *data)
 	struct service *service = data;
 
 	queue_destroy(service->chrcs, NULL);  /* List should be empty here */
+	queue_destroy(service->incl_services, NULL);
 	g_free(service->path);
 	free(service);
 }
 
+static bool match_service_handle(const void *a, const void *b)
+{
+	const struct service *service = a;
+	uint16_t start_handle = PTR_TO_UINT(b);
+
+	return service->start_handle == start_handle;
+}
+
+static void add_included_service(struct gatt_db_attribute *attrib,
+							void *user_data)
+{
+	struct service *service = user_data;
+	struct incl_service *incl_service;
+	struct btd_gatt_client *client = service->client;
+
+	incl_service = new0(struct incl_service, 1);
+	incl_service->service = service;
+
+	gatt_db_attribute_get_incl_data(attrib, &incl_service->handle,
+					&incl_service->start_handle,
+					&incl_service->end_handle);
+
+	incl_service->incl_service = queue_find(client->services,
+				match_service_handle,
+				UINT_TO_PTR(incl_service->start_handle));
+
+	queue_push_tail(service->incl_services, incl_service);
+}
+
 static struct service *service_create(struct gatt_db_attribute *attr,
 						struct btd_gatt_client *client)
 {
@@ -1423,6 +1491,7 @@ static struct service *service_create(struct gatt_db_attribute *attr,
 
 	service = new0(struct service, 1);
 	service->chrcs = queue_new();
+	service->incl_services = queue_new();
 	service->client = client;
 
 	gatt_db_attribute_get_service_data(attr, &service->start_handle,
@@ -1434,6 +1503,8 @@ static struct service *service_create(struct gatt_db_attribute *attr,
 	service->path = g_strdup_printf("%s/service%04x", device_path,
 							service->start_handle);
 
+	gatt_db_service_foreach_incl(attr, add_included_service, service);
+
 	if (!g_dbus_register_interface(btd_get_dbus_connection(), service->path,
 						GATT_SERVICE_IFACE,
 						NULL, NULL,
@@ -1459,6 +1530,63 @@ static struct service *service_create(struct gatt_db_attribute *attr,
 	return service;
 }
 
+static void incl_service_on_unregister(void *data, void *user_data)
+{
+	struct incl_service *incl_service = (struct incl_service *) data;
+	struct service *service = (struct service *) user_data;
+
+	if (incl_service->incl_service == service) {
+		incl_service->incl_service = NULL;
+
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						incl_service->service->path,
+						GATT_SERVICE_IFACE,
+						"Includes");
+	}
+}
+
+static void incl_service_on_register(void *data, void *user_data)
+{
+	struct incl_service *incl_service = (struct incl_service *) data;
+	struct service *service = (struct service *) user_data;
+
+	if (!incl_service->incl_service &&
+			incl_service->start_handle == service->start_handle) {
+		incl_service->incl_service = service;
+
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						incl_service->service->path,
+						GATT_SERVICE_IFACE,
+						"Includes");
+	}
+}
+
+struct foreach_incl_service_data {
+	queue_foreach_func_t func;
+	void *user_data;
+};
+
+static void incl_service_cb(void *data, void *user_data)
+{
+	struct service *service = (struct service *) data;
+	struct foreach_incl_service_data *incl_data =
+				(struct foreach_incl_service_data *) user_data;
+
+	queue_foreach(service->incl_services, incl_data->func,
+							incl_data->user_data);
+}
+
+static void client_foreach_incl_service(struct btd_gatt_client *client,
+				queue_foreach_func_t func, void *user_data)
+{
+	struct foreach_incl_service_data incl_data = {
+		.user_data = user_data,
+		.func = func,
+	};
+
+	queue_foreach(client->services, incl_service_cb, &incl_data);
+}
+
 static void unregister_service(void *data)
 {
 	struct service *service = data;
@@ -1466,6 +1594,11 @@ static void unregister_service(void *data)
 	DBG("Removing GATT service: %s", service->path);
 
 	queue_remove_all(service->chrcs, NULL, NULL, unregister_characteristic);
+	queue_remove_all(service->incl_services, NULL, NULL, free);
+
+	/* Make sure that no one included service points to this one */
+	client_foreach_incl_service(service->client,
+					incl_service_on_unregister, service);
 
 	g_dbus_unregister_interface(btd_get_dbus_connection(), service->path,
 							GATT_SERVICE_IFACE);
@@ -1564,6 +1697,9 @@ static void export_service(struct gatt_db_attribute *attr, void *user_data)
 		return;
 	}
 
+	/* Check if any included service points to this one */
+	client_foreach_incl_service(client, incl_service_on_register, service);
+
 	queue_push_tail(client->services, service);
 }
 
@@ -1691,14 +1827,6 @@ void btd_gatt_client_service_added(struct btd_gatt_client *client,
 	export_service(attrib, client);
 }
 
-static bool match_service_handle(const void *a, const void *b)
-{
-	const struct service *service = a;
-	uint16_t start_handle = PTR_TO_UINT(b);
-
-	return service->start_handle == start_handle;
-}
-
 void btd_gatt_client_service_removed(struct btd_gatt_client *client,
 					struct gatt_db_attribute *attrib)
 {
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux