[PATCH BlueZ 1/2] src/gatt-dbus.c: convert to shared/gatt-db implementation

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

 



---
 src/gatt-dbus.c | 182 ++++++++++++++++++++++++++------------------------------
 src/gatt-dbus.h |   3 +-
 src/gatt.c      |   2 +-
 3 files changed, 86 insertions(+), 101 deletions(-)

diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index c22e8af..f0cd26c 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -27,6 +27,7 @@
 
 #include <stdint.h>
 #include <errno.h>
+#include <assert.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -39,6 +40,9 @@
 #include "log.h"
 
 #include "error.h"
+#include "shared/queue.h"
+#include "shared/gatt-db.h"
+#include "shared/att-types.h"
 #include "attrib/gattrib.h"
 #include "attrib/att.h"
 #include "attrib/gatt.h"
@@ -56,22 +60,18 @@ struct external_service {
 	DBusMessage *reg;
 	GDBusClient *client;
 	GSList *proxies;
-	struct btd_attribute *service;
+	struct gatt_db_attribute *service;
 };
 
 struct proxy_write_data {
-	btd_attr_write_result_t result_cb;
-	void *user_data;
+	struct gatt_db_attribute *attrib;
+	unsigned int id;
 };
 
-/*
- * Attribute to Proxy hash table. Used to map incoming
- * ATT operations to its external characteristic proxy.
- */
-static GHashTable *proxy_hash;
-
 static GSList *external_services;
 
+static struct gatt_db *gatt_db;
+
 static int external_service_path_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct external_service *esvc = a;
@@ -116,7 +116,7 @@ static void remove_service(DBusConnection *conn, void *user_data)
 	external_services = g_slist_remove(external_services, esvc);
 
 	if (esvc->service)
-		btd_gatt_remove_service(esvc->service);
+		gatt_db_remove_service(gatt_db, esvc->service);
 
 	/*
 	 * Do not run in the same loop, this may be a disconnect
@@ -141,19 +141,19 @@ static uint8_t flags_string2int(const char *proper)
 
 	/* Regular Properties: See core spec 4.1 page 2183 */
 	if (!strcmp("broadcast", proper))
-		value = GATT_CHR_PROP_BROADCAST;
+		value = BT_GATT_CHRC_PROP_BROADCAST;
 	else if (!strcmp("read", proper))
-		value = GATT_CHR_PROP_READ;
+		value = BT_GATT_CHRC_PROP_READ;
 	else if (!strcmp("write-without-response", proper))
-		value = GATT_CHR_PROP_WRITE_WITHOUT_RESP;
+		value = BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP;
 	else if (!strcmp("write", proper))
-		value = GATT_CHR_PROP_WRITE;
+		value = BT_GATT_CHRC_PROP_WRITE;
 	else if (!strcmp("notify", proper))
-		value = GATT_CHR_PROP_NOTIFY;
+		value = BT_GATT_CHRC_PROP_NOTIFY;
 	else if (!strcmp("indicate", proper))
-		value = GATT_CHR_PROP_INDICATE;
+		value = BT_GATT_CHRC_PROP_INDICATE;
 	else if (!strcmp("authenticated-signed-writes", proper))
-		value = GATT_CHR_PROP_AUTH;
+		value = BT_GATT_CHRC_PROP_AUTH;
 	else
 		value = 0;
 
@@ -233,11 +233,13 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
 	esvc->proxies = g_slist_remove(esvc->proxies, proxy);
 }
 
-static void proxy_read_cb(struct btd_attribute *attr,
-				btd_attr_read_result_t result, void *user_data)
+static void proxy_read_cb(struct gatt_db_attribute *attr,
+			  unsigned int id, uint16_t offset,
+			  uint8_t opcode, bdaddr_t *bdaddr,
+			  void *user_data)
 {
 	DBusMessageIter iter, array;
-	GDBusProxy *proxy;
+	GDBusProxy *proxy = (GDBusProxy *)user_data;
 	uint8_t *value;
 	int len;
 
@@ -247,21 +249,15 @@ static void proxy_read_cb(struct btd_attribute *attr,
 	 * properties changes automatically, it is not necessary to
 	 * get the value directly from the GATT server.
 	 */
-	proxy = g_hash_table_lookup(proxy_hash, attr);
-	if (!proxy) {
-		result(-ENOENT, NULL, 0, user_data);
-		return;
-	}
-
 	if (!g_dbus_proxy_get_property(proxy, "Value", &iter)) {
 		/* Unusual situation, read property will checked earlier */
-		result(-EPERM, NULL, 0, user_data);
+		gatt_db_attribute_read_result(attr, id, -EPERM, NULL, 0);
 		return;
 	}
 
 	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
 		DBG("External service inconsistent!");
-		result(-EPERM, NULL, 0, user_data);
+		gatt_db_attribute_read_result(attr, id, -EPERM, NULL, 0);
 		return;
 	}
 
@@ -270,13 +266,13 @@ static void proxy_read_cb(struct btd_attribute *attr,
 
 	DBG("attribute: %p read %d bytes", attr, len);
 
-	result(0, value, len, user_data);
+	gatt_db_attribute_read_result(attr, id, 0, value, len);
 }
 
 static void proxy_write_reply(const DBusError *derr, void *user_data)
 {
 	struct proxy_write_data *wdata = user_data;
-	int err;
+	uint8_t ecode = 0;
 
 	/*
 	 * Security requirements shall be handled by the core. If external
@@ -285,39 +281,29 @@ static void proxy_write_reply(const DBusError *derr, void *user_data)
 	 */
 
 	if (!dbus_error_is_set(derr)) {
-		err = 0;
+		ecode = 0;
 		goto done;
 	}
 
 	DBG("Write reply: %s", derr->message);
 
-	if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY))
-		err = -ETIMEDOUT;
-	else if (dbus_error_has_name(derr, ERROR_INTERFACE ".InvalidArguments"))
-		err = -EINVAL;
-	else
-		err = -EPROTO;
+	ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
 
 done:
-	if (wdata && wdata->result_cb)
-		wdata->result_cb(err, wdata->user_data);
+	if (wdata && wdata->attrib)
+		gatt_db_attribute_write_result(wdata->attrib, wdata->id, ecode);
 }
 
-static void proxy_write_cb(struct btd_attribute *attr,
-					const uint8_t *value, size_t len,
-					btd_attr_write_result_t result,
-					void *user_data)
+static void proxy_write_cb(struct gatt_db_attribute *attrib,
+			   unsigned int id, uint16_t offset,
+			   const uint8_t *value, size_t len,
+			   uint8_t opcode, bdaddr_t *bdaddr,
+			   void *user_data)
 {
-	GDBusProxy *proxy;
-
-	proxy = g_hash_table_lookup(proxy_hash, attr);
-	if (!proxy) {
-		result(-ENOENT, user_data);
-		return;
-	}
+	GDBusProxy *proxy = (GDBusProxy *)user_data;
 
 	/*
-	 * "result" callback defines if the core wants to receive the
+	 * opcode defines if the core wants to receive the
 	 * operation result, allowing to select ATT Write Request or Write
 	 * Command. Descriptors requires Write Request operation. For
 	 * Characteristics, the implementation will define which operations
@@ -325,19 +311,20 @@ static void proxy_write_cb(struct btd_attribute *attr,
 	 * TODO: Write Long Characteristics/Descriptors.
 	 */
 
-	if (result) {
+	if (opcode != BT_ATT_OP_WRITE_CMD) {
 		struct proxy_write_data *wdata;
 
 		wdata = g_new0(struct proxy_write_data, 1);
-		wdata->result_cb = result;
-		wdata->user_data = user_data;
+		wdata->attrib = attrib;
+		wdata->id = id;
 
 		if (!g_dbus_proxy_set_property_array(proxy, "Value",
 						DBUS_TYPE_BYTE, value, len,
 						proxy_write_reply,
 						wdata, g_free)) {
 			g_free(wdata);
-			result(-ENOENT, user_data);
+			gatt_db_attribute_write_result(attrib, id, BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND);
+
 		}
 	} else {
 		/*
@@ -356,7 +343,8 @@ static void proxy_write_cb(struct btd_attribute *attr,
 }
 
 static int register_external_service(struct external_service *esvc,
-							GDBusProxy *proxy)
+							GDBusProxy *proxy,
+							int num_handles)
 {
 	DBusMessageIter iter;
 	const char *str, *path, *iface;
@@ -379,20 +367,23 @@ static int register_external_service(struct external_service *esvc,
 	if (bt_string_to_uuid(&uuid, str) < 0)
 		return -EINVAL;
 
-	esvc->service = btd_gatt_add_service(&uuid);
+	esvc->service = gatt_db_add_service(gatt_db, &uuid, true, num_handles);
 	if (!esvc->service)
 		return -EINVAL;
 
 	return 0;
 }
 
-static int add_char(GDBusProxy *proxy, const bt_uuid_t *uuid)
+static int add_char(struct gatt_db_attribute *service,
+		    GDBusProxy *proxy, const bt_uuid_t *uuid)
 {
 	DBusMessageIter iter;
 	struct btd_attribute *attr;
-	btd_attr_write_t write_cb;
-	btd_attr_read_t read_cb;
+	gatt_db_write_t write_cb;
+	gatt_db_read_t read_cb;
 	uint8_t propmask = 0;
+	uint32_t permissions = 0;
+	struct gatt_db_attribute *res;
 
 	/*
 	 * Optional property. If is not informed, read and write
@@ -402,45 +393,46 @@ static int add_char(GDBusProxy *proxy, const bt_uuid_t *uuid)
 	if (g_dbus_proxy_get_property(proxy, "Flags", &iter))
 		propmask = flags_get_bitmask(&iter);
 	else
-		propmask = GATT_CHR_PROP_WRITE_WITHOUT_RESP
-						| GATT_CHR_PROP_WRITE
-						| GATT_CHR_PROP_READ;
+		propmask = BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP
+						| BT_GATT_CHRC_PROP_WRITE
+						| BT_GATT_CHRC_PROP_READ;
 	if (!propmask)
 		return -EINVAL;
 
-	if (propmask & GATT_CHR_PROP_READ)
+	if (propmask & BT_GATT_CHRC_PROP_READ) {
 		read_cb = proxy_read_cb;
-	else
+		permissions |= BT_ATT_PERM_READ;
+	} else {
 		read_cb = NULL;
+	}
 
-	if (propmask & (GATT_CHR_PROP_WRITE | GATT_CHR_PROP_WRITE_WITHOUT_RESP))
+	if (propmask & (BT_GATT_CHRC_PROP_WRITE | BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP)) {
 		write_cb = proxy_write_cb;
-	else
+		permissions |= BT_ATT_PERM_WRITE;
+	} else {
 		write_cb = NULL;
+	}
 
-	attr = btd_gatt_add_char(uuid, propmask, read_cb, write_cb);
-	if (!attr)
-		return -ENOMEM;
-
-	g_hash_table_insert(proxy_hash, attr, g_dbus_proxy_ref(proxy));
+	res = gatt_db_service_add_characteristic(service, uuid, permissions, propmask,
+					   read_cb, write_cb, proxy);
+	assert(res);
 
 	return 0;
 }
 
-static int add_char_desc(GDBusProxy *proxy, const bt_uuid_t *uuid)
+static int add_char_desc(struct gatt_db_attribute *service,
+			 GDBusProxy *proxy, const bt_uuid_t *uuid)
 {
-	struct btd_attribute *attr;
-
-	attr = btd_gatt_add_char_desc(uuid, proxy_read_cb, proxy_write_cb);
-	if (!attr)
-		return -ENOMEM;
-
-	g_hash_table_insert(proxy_hash, attr, g_dbus_proxy_ref(proxy));
+	struct gatt_db_attribute *attr;
 
+	attr = gatt_db_service_add_descriptor(service, uuid, BT_ATT_PERM_READ,
+				       proxy_read_cb, proxy_write_cb, proxy);
+	assert(attr);
 	return 0;
 }
 
-static int register_external_characteristics(GSList *proxies)
+static int register_external_characteristics(struct gatt_db_attribute *service,
+					     GSList *proxies)
 
 {
 	GSList *list;
@@ -468,9 +460,9 @@ static int register_external_characteristics(GSList *proxies)
 		path = g_dbus_proxy_get_path(proxy);
 
 		if (!strcmp(GATT_CHR_IFACE, iface))
-			ret = add_char(proxy, &uuid);
+			ret = add_char(service, proxy, &uuid);
 		else
-			ret = add_char_desc(proxy, &uuid);
+			ret = add_char_desc(service, proxy, &uuid);
 
 		if (ret < 0)
 			return ret;
@@ -492,13 +484,15 @@ static void client_ready(GDBusClient *client, void *user_data)
 		goto fail;
 
 	proxy = esvc->proxies->data;
-	if (register_external_service(esvc, proxy) < 0)
+	int num_handles = (g_slist_length(esvc->proxies) * 2) + 1;
+	if (register_external_service(esvc, proxy, num_handles) < 0)
 		goto fail;
 
-	if (register_external_characteristics(g_slist_next(esvc->proxies)) < 0)
+	if (register_external_characteristics(esvc->service, g_slist_next(esvc->proxies)) < 0)
 		goto fail;
 
 	DBG("Added GATT service %s", esvc->path);
+	gatt_db_service_set_active(esvc->service, true);
 
 	reply = dbus_message_new_method_return(esvc->reg);
 	g_dbus_send_message(conn, reply);
@@ -627,32 +621,22 @@ static const GDBusMethodTable methods[] = {
 	{ }
 };
 
-gboolean gatt_dbus_manager_register(void)
+gboolean gatt_dbus_manager_register(struct gatt_db *db)
 {
 	if (!g_dbus_register_interface(btd_get_dbus_connection(),
 				"/org/bluez", GATT_MGR_IFACE,
 				methods, NULL, NULL, NULL, NULL))
 		return FALSE;
 
-	proxy_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
-				NULL, (GDestroyNotify) g_dbus_proxy_unref);
-
+	gatt_db = db;
 	return TRUE;
 }
 
 void gatt_dbus_manager_unregister(void)
 {
-	/* We might not have initialized if experimental features are
-	 * not enabled.
-	 */
-	if (!proxy_hash)
-		return;
-
-	g_hash_table_destroy(proxy_hash);
-	proxy_hash = NULL;
-
 	g_slist_free_full(external_services, external_service_free);
 
 	g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
 							GATT_MGR_IFACE);
+	gatt_db = NULL;
 }
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
index 310cfa9..7716648 100644
--- a/src/gatt-dbus.h
+++ b/src/gatt-dbus.h
@@ -21,5 +21,6 @@
  *
  */
 
-gboolean gatt_dbus_manager_register(void);
+struct gatt_db;
+gboolean gatt_dbus_manager_register(struct gatt_db *db);
 void gatt_dbus_manager_unregister(void);
diff --git a/src/gatt.c b/src/gatt.c
index 3060462..4028919 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -309,7 +309,7 @@ void gatt_init(void)
 {
 	DBG("Starting GATT server");
 
-	gatt_dbus_manager_register();
+	gatt_dbus_manager_register(NULL);
 }
 
 void gatt_cleanup(void)
-- 
1.9.1

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