[RFC BlueZ 1/2] gatt-dbus: Add remote GATT service objects.

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

 



From: Arman Uguray <armansito@xxxxxxxxxxxx>

This CL adds the initial GATT client D-Bus API support for remote primary GATT
services. Characteristics, descriptors, and included services are not yet
handled.
---
 src/device.c    | 47 +++++++++++++++++++++++++++--
 src/gatt-dbus.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/gatt-dbus.h | 25 ++++++++++++++++
 3 files changed, 158 insertions(+), 6 deletions(-)

diff --git a/src/device.c b/src/device.c
index e624445..0623e4d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -65,6 +65,7 @@
 #include "textfile.h"
 #include "storage.h"
 #include "attrib-server.h"
+#include "gatt.h"
 
 #define IO_CAPABILITY_NOINPUTNOOUTPUT	0x03
 
@@ -186,6 +187,7 @@ struct btd_device {
 	GSList		*uuids;
 	GSList		*primaries;		/* List of primary services */
 	GSList		*services;		/* List of btd_service */
+	GSList		*gatt_services;		/* List of GATT DBus Services */
 	GSList		*pending;		/* Pending services */
 	GSList		*watches;		/* List of disconnect_data */
 	gboolean	temporary;
@@ -511,11 +513,18 @@ static void svc_dev_remove(gpointer user_data)
 	g_free(cb);
 }
 
+static void gatt_dbus_service_free(gpointer user_data)
+{
+	struct btd_gatt_dbus_service *service = user_data;
+	btd_gatt_dbus_service_free(service);
+}
+
 static void device_free(gpointer user_data)
 {
 	struct btd_device *device = user_data;
 
 	g_slist_free_full(device->uuids, g_free);
+	g_slist_free_full(device->gatt_services, gatt_dbus_service_free);
 	g_slist_free_full(device->primaries, g_free);
 	g_slist_free_full(device->attios, g_free);
 	g_slist_free_full(device->attios_offline, g_free);
@@ -2287,6 +2296,7 @@ static struct btd_device *device_new(struct btd_adapter *adapter,
 
 	str2ba(address, &device->bdaddr);
 	device->adapter = adapter;
+	device->gatt_services = NULL;
 
 	return btd_device_ref(device);
 }
@@ -3317,6 +3327,35 @@ done:
 	return FALSE;
 }
 
+static void expose_btd_dbus_gatt_services(struct btd_device *device)
+{
+	GSList *l;
+
+	/* Clear current list of GATT services. */
+	g_slist_free_full(device->gatt_services, gatt_dbus_service_free);
+	device->gatt_services = NULL;
+	for (l = device->primaries; l; l = g_slist_next(l)) {
+		struct gatt_primary *prim = l->data;
+
+		/* Don't create objects for the GAP and GATT services. */
+		if (bt_uuid_strcmp(prim->uuid, GATT_UUID) == 0) {
+			DBG("Skipping GATT UUID for GATT service objects.");
+			continue;
+		}
+		if (bt_uuid_strcmp(prim->uuid, GAP_UUID) == 0) {
+			DBG("Skipping GAP UUID for GATT service objects.");
+			continue;
+		}
+
+		struct btd_gatt_dbus_service *service;
+		service = btd_gatt_dbus_service_create(device, prim);
+		if (service == NULL)
+			continue;
+		device->gatt_services = g_slist_append(device->gatt_services,
+							service);
+	}
+}
+
 static void register_all_services(struct browse_req *req, GSList *services)
 {
 	struct btd_device *device = req->device;
@@ -3329,6 +3368,8 @@ static void register_all_services(struct browse_req *req, GSList *services)
 
 	device_register_primaries(device, g_slist_copy(services), -1);
 
+	expose_btd_dbus_gatt_services(device);
+
 	device_probe_profiles(device, req->profiles_added);
 
 	if (device->attios == NULL && device->attios_offline == NULL)
@@ -3501,10 +3542,10 @@ done:
 		bonding_request_free(device->bonding);
 	}
 
-	if (device->connect) {
-		if (!device->le_state.svc_resolved)
-			device_browse_primary(device, NULL);
+	if (!device->le_state.svc_resolved)
+		device_browse_primary(device, NULL);
 
+	if (device->connect) {
 		if (err < 0)
 			reply = btd_error_failed(device->connect,
 							strerror(-err));
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index c5f1597..60b87fa 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -37,6 +37,9 @@
 #include "lib/uuid.h"
 #include "dbus-common.h"
 #include "log.h"
+#include "attrib/att.h"
+#include "attrib/gattrib.h"
+#include "attrib/gatt.h"
 
 #include "error.h"
 #include "gatt.h"
@@ -47,6 +50,12 @@
 #define GATT_CHR_IFACE			"org.bluez.GattCharacteristic1"
 #define GATT_DESCRIPTOR_IFACE		"org.bluez.GattDescriptor1"
 
+struct btd_gatt_dbus_service {
+	bt_uuid_t uuid;
+	struct btd_device *device;
+	char *path;
+};
+
 struct external_app {
 	char *owner;
 	char *path;
@@ -436,7 +445,7 @@ static DBusMessage *unregister_service(DBusConnection *conn,
 	return dbus_message_new_method_return(msg);
 }
 
-static const GDBusMethodTable methods[] = {
+static const GDBusMethodTable manager_methods[] = {
 	{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("RegisterService",
 				GDBUS_ARGS({ "service", "o"},
 						{ "options", "a{sv}"}),
@@ -450,8 +459,8 @@ static const GDBusMethodTable methods[] = {
 gboolean gatt_dbus_manager_register(void)
 {
 	if (g_dbus_register_interface(btd_get_dbus_connection(),
-				"/org/bluez", GATT_MGR_IFACE,
-				methods, NULL, NULL, NULL, NULL) == FALSE)
+				"/org/bluez", GATT_MGR_IFACE, manager_methods,
+				NULL, NULL, NULL, NULL) == FALSE)
 		return FALSE;
 
 	proxy_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
@@ -468,3 +477,80 @@ void gatt_dbus_manager_unregister(void)
 	g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
 							GATT_MGR_IFACE);
 }
+
+static gboolean service_property_get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	char uuid[MAX_LEN_UUID_STR + 1];
+	const char *ptr = uuid;
+	struct btd_gatt_dbus_service *service = data;
+
+	bt_uuid_to_string(&service->uuid, uuid, sizeof(uuid));
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);
+
+	return TRUE;
+}
+
+static const GDBusPropertyTable service_properties[] = {
+	{ "UUID", "s", service_property_get_uuid },
+	{}
+};
+
+static void service_free(gpointer user_data)
+{
+	struct btd_gatt_dbus_service *service = user_data;
+
+	g_free(service->path);
+	g_free(service);
+}
+
+struct btd_gatt_dbus_service *btd_gatt_dbus_service_create(
+		struct btd_device *device, struct gatt_primary *primary)
+{
+	struct btd_gatt_dbus_service *service;
+	bt_uuid_t uuid;
+	const char *device_path = device_get_path(device);
+
+	DBG("GATT service UUID: %s", primary->uuid);
+
+	service = g_try_malloc0(sizeof(struct btd_gatt_dbus_service));
+	if (service == NULL)
+		return NULL;
+
+	service->path = g_strdup_printf("%s/service%04X", device_path,
+					primary->range.start);
+
+	if (bt_string_to_uuid(&uuid, primary->uuid)) {
+		error("Primary has invalid UUID: %s", primary->uuid);
+		goto fail;
+	}
+
+	bt_uuid_to_uuid128(&uuid, &service->uuid);
+
+	DBG("Creating GATT service %s", service->path);
+
+	if (g_dbus_register_interface(btd_get_dbus_connection(),
+					service->path, GATT_SERVICE_IFACE,
+					NULL, NULL, service_properties,
+					service,
+					service_free) == FALSE) {
+		char device_addr[18];
+		ba2str(device_get_address(device), device_addr);
+		error("Unable to register GATT service: UUID: %s, device: %s",
+			primary->uuid, device_addr);
+		goto fail;
+	}
+
+	service->device = device;
+	return service;
+
+fail:
+	service_free(service);
+	return NULL;
+}
+
+void btd_gatt_dbus_service_free(struct btd_gatt_dbus_service* service)
+{
+	g_dbus_unregister_interface(btd_get_dbus_connection(),
+					service->path, GATT_SERVICE_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
index 310cfa9..08d3f11 100644
--- a/src/gatt-dbus.h
+++ b/src/gatt-dbus.h
@@ -21,5 +21,30 @@
  *
  */
 
+struct btd_gatt_dbus_service;
+struct btd_device;
+struct gatt_primary;
+
 gboolean gatt_dbus_manager_register(void);
 void gatt_dbus_manager_unregister(void);
+
+/*
+ * btd_gatt_dbus_service_create - Create a GATT service that represents a remote
+ * primary GATT service and expose it via D-Bus.
+ *
+ * @device:	The remote device that hosts the GATT service.
+ * @primary:	The primary GATT service.
+ *
+ * Returns a reference to the GATT service object. In case of error, NULL is
+ * returned.
+ */
+struct btd_gatt_dbus_service *btd_gatt_dbus_service_create(
+		struct btd_device *device, struct gatt_primary *primary);
+
+/*
+ * btd_gatt_dbus_service_free - Unregister a GATT service as a D-Bus object and
+ * free up its memory.
+ *
+ * @service: The GATT service object to remove.
+ */
+void btd_gatt_dbus_service_free(struct btd_gatt_dbus_service* service);
-- 
1.8.3.2

--
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