All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ 00/11] On demand connection in Generic Attribute
@ 2011-07-12 20:28 Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 01/11] Remove not necessary data from gatt_service Claudio Takahasi
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Dependency:"[PATCH BlueZ 00/12] On demand connection management"

The following patch series contains cleanups in the Generic Attribute
code and it uses the mechanism based on registered connection callbacks
to manage connections.

Watchers register connection callback to allow receiving notifications. If
watchers are not registered and other GATT based profile doesn't require
an active connection, callbacks can be unregistered. SetProperty and
DiscoverCharacteristics methods request on demand connection if necessary.

Claudio Takahasi (11):
  Remove not necessary data from gatt_service
  Remove storing device path in gatt_service
  Remove leftover D-Bus message in gatt_service
  Cleanup of primary service registration
  Cleanup of primary service structs
  Register the ATT connection callbacks
  Remove implicit connection from generic API
  Change GAttrib ref counting in Generic Attribute
  Register ATT connection callback based on watchers
  On demand connection for characteristics discovery
  Add on demand characteristic write

 attrib/client.c |  593 ++++++++++++++++++++++++++----------------------------
 attrib/client.h |    2 +-
 src/device.c    |    2 +-
 3 files changed, 288 insertions(+), 309 deletions(-)

-- 
1.7.6


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

* [PATCH BlueZ 01/11] Remove not necessary data from gatt_service
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 02/11] Remove storing device path in gatt_service Claudio Takahasi
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Bluetooth source and destination address can be obtained from the
device object. GATT service doesn't need to keep these addresses.
---
 attrib/client.c |   47 ++++++++++++++++++++++++++++++-----------------
 1 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 1ef2699..0d828c0 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -56,8 +56,6 @@
 struct gatt_service {
 	struct btd_device *dev;
 	DBusConnection *conn;
-	bdaddr_t sba;
-	bdaddr_t dba;
 	char *path;
 	GSList *primary;
 	GAttrib *attrib;
@@ -160,6 +158,17 @@ static void gatt_service_free(void *user_data)
 	g_free(gatt);
 }
 
+static void gatt_get_address(struct gatt_service *gatt,
+				bdaddr_t *sba, bdaddr_t *dba)
+{
+	struct btd_device *device = gatt->dev;
+	struct btd_adapter *adapter;
+
+	adapter = device_get_adapter(device);
+	adapter_get_address(adapter, sba);
+	device_get_address(device, dba);
+}
+
 static int gatt_dev_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct gatt_service *gatt = a;
@@ -368,6 +377,7 @@ fail:
 static int l2cap_connect(struct gatt_service *gatt, GError **gerr,
 								gboolean listen)
 {
+	bdaddr_t sba, dba;
 	GIOChannel *io;
 
 	if (gatt->attrib != NULL) {
@@ -381,17 +391,18 @@ static int l2cap_connect(struct gatt_service *gatt, GError **gerr,
 	 * Configuration it is necessary to poll the server from time
 	 * to time checking for modifications.
 	 */
+	gatt_get_address(gatt, &sba, &dba);
 	if (gatt->psm < 0)
 		io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, gerr,
-			BT_IO_OPT_SOURCE_BDADDR, &gatt->sba,
-			BT_IO_OPT_DEST_BDADDR, &gatt->dba,
+			BT_IO_OPT_SOURCE_BDADDR, &sba,
+			BT_IO_OPT_DEST_BDADDR, &dba,
 			BT_IO_OPT_CID, ATT_CID,
 			BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
 			BT_IO_OPT_INVALID);
 	else
 		io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, gerr,
-			BT_IO_OPT_SOURCE_BDADDR, &gatt->sba,
-			BT_IO_OPT_DEST_BDADDR, &gatt->dba,
+			BT_IO_OPT_SOURCE_BDADDR, &sba,
+			BT_IO_OPT_DEST_BDADDR, &dba,
 			BT_IO_OPT_PSM, gatt->psm,
 			BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
 			BT_IO_OPT_INVALID);
@@ -579,11 +590,13 @@ static void store_characteristics(struct gatt_service *gatt,
 {
 	char *characteristics;
 	struct att_primary *att = prim->att;
+	bdaddr_t sba, dba;
 
 	characteristics = characteristic_list_to_string(prim->chars);
 
-	write_device_characteristics(&gatt->sba, &gatt->dba, att->start,
-							characteristics);
+	gatt_get_address(gatt, &sba, &dba);
+
+	write_device_characteristics(&sba, &dba, att->start, characteristics);
 
 	g_free(characteristics);
 }
@@ -645,6 +658,7 @@ static void load_characteristics(gpointer data, gpointer user_data)
 	struct primary *prim = data;
 	struct att_primary *att = prim->att;
 	struct gatt_service *gatt = user_data;
+	bdaddr_t sba, dba;
 	GSList *chrs_list;
 	char *str;
 
@@ -653,7 +667,9 @@ static void load_characteristics(gpointer data, gpointer user_data)
 		return;
 	}
 
-	str = read_device_characteristics(&gatt->sba, &gatt->dba, att->start);
+	gatt_get_address(gatt, &sba, &dba);
+
+	str = read_device_characteristics(&sba, &dba, att->start);
 	if (str == NULL)
 		return;
 
@@ -673,6 +689,7 @@ static void load_characteristics(gpointer data, gpointer user_data)
 static void store_attribute(struct gatt_service *gatt, uint16_t handle,
 				uint16_t type, uint8_t *value, gsize len)
 {
+	bdaddr_t sba, dba;
 	bt_uuid_t uuid;
 	char *str, *tmp;
 	guint i;
@@ -687,7 +704,10 @@ static void store_attribute(struct gatt_service *gatt, uint16_t handle,
 	for (i = 0, tmp = str + MAX_LEN_UUID_STR; i < len; i++, tmp += 2)
 		sprintf(tmp, "%02X", value[i]);
 
-	write_device_attribute(&gatt->sba, &gatt->dba, handle, str);
+	gatt_get_address(gatt, &sba, &dba);
+
+	write_device_attribute(&sba, &dba, handle, str);
+
 	g_free(str);
 }
 
@@ -1052,21 +1072,14 @@ GSList *attrib_client_register(DBusConnection *connection,
 					struct btd_device *device, int psm,
 					GAttrib *attrib, GSList *primaries)
 {
-	struct btd_adapter *adapter = device_get_adapter(device);
 	const char *path = device_get_path(device);
 	struct gatt_service *gatt;
-	bdaddr_t sba, dba;
-
-	adapter_get_address(adapter, &sba);
-	device_get_address(device, &dba);
 
 	gatt = g_new0(struct gatt_service, 1);
 	gatt->dev = btd_device_ref(device);
 	gatt->conn = dbus_connection_ref(connection);
 	gatt->listen = FALSE;
 	gatt->path = g_strdup(path);
-	bacpy(&gatt->sba, &sba);
-	bacpy(&gatt->dba, &dba);
 	gatt->psm = psm;
 
 	if (attrib)
-- 
1.7.6


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

* [PATCH BlueZ 02/11] Remove storing device path in gatt_service
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 01/11] Remove not necessary data from gatt_service Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 03/11] Remove leftover D-Bus message " Claudio Takahasi
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

---
 attrib/client.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 0d828c0..f7c78d3 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -56,7 +56,6 @@
 struct gatt_service {
 	struct btd_device *dev;
 	DBusConnection *conn;
-	char *path;
 	GSList *primary;
 	GAttrib *attrib;
 	DBusMessage *msg;
@@ -152,7 +151,6 @@ static void gatt_service_free(void *user_data)
 
 	g_slist_free_full(gatt->primary, primary_free);
 	g_attrib_unref(gatt->attrib);
-	g_free(gatt->path);
 	btd_device_unref(gatt->dev);
 	dbus_connection_unref(gatt->conn);
 	g_free(gatt);
@@ -1043,7 +1041,11 @@ static GDBusMethodTable prim_methods[] = {
 
 static GSList *register_primaries(struct gatt_service *gatt, GSList *primaries)
 {
+	struct btd_device *device = gatt->dev;
 	GSList *l, *paths;
+	const char *device_path;
+
+	device_path = device_get_path(device);
 
 	for (paths = NULL, l = primaries; l; l = l->next) {
 		struct att_primary *att = l->data;
@@ -1052,7 +1054,7 @@ static GSList *register_primaries(struct gatt_service *gatt, GSList *primaries)
 		prim = g_new0(struct primary, 1);
 		prim->att = att;
 		prim->gatt = gatt;
-		prim->path = g_strdup_printf("%s/service%04x", gatt->path,
+		prim->path = g_strdup_printf("%s/service%04x", device_path,
 								att->start);
 
 		g_dbus_register_interface(gatt->conn, prim->path,
@@ -1072,14 +1074,12 @@ GSList *attrib_client_register(DBusConnection *connection,
 					struct btd_device *device, int psm,
 					GAttrib *attrib, GSList *primaries)
 {
-	const char *path = device_get_path(device);
 	struct gatt_service *gatt;
 
 	gatt = g_new0(struct gatt_service, 1);
 	gatt->dev = btd_device_ref(device);
 	gatt->conn = dbus_connection_ref(connection);
 	gatt->listen = FALSE;
-	gatt->path = g_strdup(path);
 	gatt->psm = psm;
 
 	if (attrib)
-- 
1.7.6


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

* [PATCH BlueZ 03/11] Remove leftover D-Bus message in gatt_service
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 01/11] Remove not necessary data from gatt_service Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 02/11] Remove storing device path in gatt_service Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 04/11] Cleanup of primary service registration Claudio Takahasi
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

---
 attrib/client.c |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index f7c78d3..93d0da7 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -58,7 +58,6 @@ struct gatt_service {
 	DBusConnection *conn;
 	GSList *primary;
 	GAttrib *attrib;
-	DBusMessage *msg;
 	int psm;
 	gboolean listen;
 };
@@ -343,12 +342,6 @@ static void connect_cb(GIOChannel *chan, GError *gerr, gpointer user_data)
 	struct gatt_service *gatt = user_data;
 
 	if (gerr) {
-		if (gatt->msg) {
-			DBusMessage *reply = btd_error_failed(gatt->msg,
-							gerr->message);
-			g_dbus_send_message(gatt->conn, reply);
-		}
-
 		error("%s", gerr->message);
 		goto fail;
 	}
-- 
1.7.6


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

* [PATCH BlueZ 04/11] Cleanup of primary service registration
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (2 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 03/11] Remove leftover D-Bus message " Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 05/11] Cleanup of primary service structs Claudio Takahasi
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

---
 attrib/client.c |   47 ++++++++++++++++++++++++-----------------------
 1 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 93d0da7..98e25c7 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -1032,35 +1032,28 @@ static GDBusMethodTable prim_methods[] = {
 	{ }
 };
 
-static GSList *register_primaries(struct gatt_service *gatt, GSList *primaries)
+static struct primary *primary_register(struct gatt_service *gatt,
+						struct att_primary *prim)
 {
 	struct btd_device *device = gatt->dev;
-	GSList *l, *paths;
 	const char *device_path;
+	struct primary *data;
 
 	device_path = device_get_path(device);
 
-	for (paths = NULL, l = primaries; l; l = l->next) {
-		struct att_primary *att = l->data;
-		struct primary *prim;
+	data = g_new0(struct primary, 1);
+	data->att = prim;
+	data->gatt = gatt;
+	data->path = g_strdup_printf("%s/service%04x", device_path,
+								prim->start);
 
-		prim = g_new0(struct primary, 1);
-		prim->att = att;
-		prim->gatt = gatt;
-		prim->path = g_strdup_printf("%s/service%04x", device_path,
-								att->start);
+	g_dbus_register_interface(gatt->conn, data->path,
+					CHAR_INTERFACE, prim_methods,
+					NULL, NULL, data, NULL);
 
-		g_dbus_register_interface(gatt->conn, prim->path,
-				CHAR_INTERFACE, prim_methods,
-				NULL, NULL, prim, NULL);
-		DBG("Registered: %s", prim->path);
+	load_characteristics(data, gatt);
 
-		gatt->primary = g_slist_append(gatt->primary, prim);
-		paths = g_slist_append(paths, g_strdup(prim->path));
-		load_characteristics(prim, gatt);
-	}
-
-	return paths;
+	return data;
 }
 
 GSList *attrib_client_register(DBusConnection *connection,
@@ -1068,6 +1061,7 @@ GSList *attrib_client_register(DBusConnection *connection,
 					GAttrib *attrib, GSList *primaries)
 {
 	struct gatt_service *gatt;
+	GSList *l;
 
 	gatt = g_new0(struct gatt_service, 1);
 	gatt->dev = btd_device_ref(device);
@@ -1075,12 +1069,19 @@ GSList *attrib_client_register(DBusConnection *connection,
 	gatt->listen = FALSE;
 	gatt->psm = psm;
 
-	if (attrib)
-		gatt->attrib = g_attrib_ref(attrib);
+	for (l = primaries; l; l = l->next) {
+		struct att_primary *prim = l->data;
+		struct primary *data;
+
+		data = primary_register(gatt, prim);
+		gatt->primary = g_slist_append(gatt->primary, data);
+
+		DBG("Registered: %s", data->path);
+	}
 
 	gatt_services = g_slist_append(gatt_services, gatt);
 
-	return register_primaries(gatt, primaries);
+	return gatt_services;
 }
 
 void attrib_client_unregister(struct btd_device *device)
-- 
1.7.6


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

* [PATCH BlueZ 05/11] Cleanup of primary service structs
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (3 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 04/11] Cleanup of primary service registration Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 06/11] Register the ATT connection callbacks Claudio Takahasi
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Get rid of local structure to store all GATT primary services of a
given device. "primary" struct has been renamed to "gatt_service"
to avoid misinterpretation or confusion with "att_primary".
---
 attrib/client.c |  332 ++++++++++++++++++++++++-------------------------------
 attrib/client.h |    2 +-
 src/device.c    |    2 +-
 3 files changed, 146 insertions(+), 190 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 98e25c7..482aff1 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -53,15 +53,6 @@
 
 #define CHAR_INTERFACE "org.bluez.Characteristic"
 
-struct gatt_service {
-	struct btd_device *dev;
-	DBusConnection *conn;
-	GSList *primary;
-	GAttrib *attrib;
-	int psm;
-	gboolean listen;
-};
-
 struct format {
 	guint8 format;
 	guint8 exponent;
@@ -70,16 +61,20 @@ struct format {
 	guint16 desc;
 } __attribute__ ((packed));
 
-struct primary {
-	struct gatt_service *gatt;
-	struct att_primary *att;
+struct gatt_service {
+	struct btd_device *dev;
+	struct att_primary *prim;
+	DBusConnection *conn;
+	GAttrib *attrib;
+	int psm;
 	char *path;
 	GSList *chars;
 	GSList *watchers;
+	gboolean listen;
 };
 
 struct characteristic {
-	struct primary *prim;
+	struct gatt_service *gatt;
 	char *path;
 	uint16_t handle;
 	uint16_t end;
@@ -93,7 +88,7 @@ struct characteristic {
 };
 
 struct query_data {
-	struct primary *prim;
+	struct gatt_service *gatt;
 	struct characteristic *chr;
 	DBusMessage *msg;
 	uint16_t handle;
@@ -103,7 +98,7 @@ struct watcher {
 	guint id;
 	char *name;
 	char *path;
-	struct primary *prim;
+	struct gatt_service *gatt;
 };
 
 static GSList *gatt_services = NULL;
@@ -129,26 +124,11 @@ static void watcher_free(void *user_data)
 	g_free(watcher);
 }
 
-static void primary_free(void *user_data)
+static void gatt_service_free(struct gatt_service *gatt)
 {
-	struct primary *prim = user_data;
-	GSList *l;
-
-	for (l = prim->watchers; l; l = l->next) {
-		struct watcher *watcher = l->data;
-		g_dbus_remove_watch(prim->gatt->conn, watcher->id);
-	}
-
-	g_slist_free_full(prim->chars, characteristic_free);
-	g_free(prim->path);
-	g_free(prim);
-}
-
-static void gatt_service_free(void *user_data)
-{
-	struct gatt_service *gatt = user_data;
-
-	g_slist_free_full(gatt->primary, primary_free);
+	g_slist_free_full(gatt->watchers, watcher_free);
+	g_slist_free_full(gatt->chars, characteristic_free);
+	g_free(gatt->path);
 	g_attrib_unref(gatt->attrib);
 	btd_device_unref(gatt->dev);
 	dbus_connection_unref(gatt->conn);
@@ -166,14 +146,6 @@ static void gatt_get_address(struct gatt_service *gatt,
 	device_get_address(device, dba);
 }
 
-static int gatt_dev_cmp(gconstpointer a, gconstpointer b)
-{
-	const struct gatt_service *gatt = a;
-	const struct btd_device *dev = b;
-
-	return gatt->dev != dev;
-}
-
 static int characteristic_handle_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct characteristic *chr = a;
@@ -229,12 +201,11 @@ static void append_char_dict(DBusMessageIter *iter, struct characteristic *chr)
 static void watcher_exit(DBusConnection *conn, void *user_data)
 {
 	struct watcher *watcher = user_data;
-	struct primary *prim = watcher->prim;
-	struct gatt_service *gatt = prim->gatt;
+	struct gatt_service *gatt = watcher->gatt;
 
-	DBG("%s watcher %s exited", prim->path, watcher->name);
+	DBG("%s watcher %s exited", gatt->path, watcher->name);
 
-	prim->watchers = g_slist_remove(prim->watchers, watcher);
+	gatt->watchers = g_slist_remove(gatt->watchers, watcher);
 
 	g_attrib_unref(gatt->attrib);
 }
@@ -256,7 +227,7 @@ static void update_watchers(gpointer data, gpointer user_data)
 {
 	struct watcher *w = data;
 	struct characteristic *chr = user_data;
-	DBusConnection *conn = w->prim->gatt->conn;
+	DBusConnection *conn = w->gatt->conn;
 	DBusMessage *msg;
 
 	msg = dbus_message_new_method_call(w->name, w->path,
@@ -277,8 +248,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
 {
 	struct gatt_service *gatt = user_data;
 	struct characteristic *chr;
-	struct primary *prim;
-	GSList *lprim, *lchr;
+	GSList *l;
 	uint8_t opdu[ATT_MAX_MTU];
 	guint handle;
 	uint16_t olen;
@@ -291,17 +261,12 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
 
 	handle = att_get_u16(&pdu[1]);
 
-	for (lprim = gatt->primary, prim = NULL, chr = NULL; lprim;
-						lprim = lprim->next) {
-		prim = lprim->data;
+	l = g_slist_find_custom(gatt->chars, GUINT_TO_POINTER(handle),
+						characteristic_handle_cmp);
+	if (!l)
+		return;
 
-		lchr = g_slist_find_custom(prim->chars,
-			GUINT_TO_POINTER(handle), characteristic_handle_cmp);
-		if (lchr) {
-			chr = lchr->data;
-			break;
-		}
-	}
+	chr = l->data;
 
 	if (chr == NULL) {
 		DBG("Attribute handle 0x%02x not found", handle);
@@ -317,7 +282,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
 		if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
 			DBG("Can't change Characteristic 0x%02x", handle);
 
-		g_slist_foreach(prim->watchers, update_watchers, chr);
+		g_slist_foreach(gatt->watchers, update_watchers, chr);
 		break;
 	}
 }
@@ -415,7 +380,7 @@ static DBusMessage *register_watcher(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
 	const char *sender = dbus_message_get_sender(msg);
-	struct primary *prim = data;
+	struct gatt_service *gatt = data;
 	struct watcher *watcher;
 	GError *gerr = NULL;
 	char *path;
@@ -424,7 +389,7 @@ static DBusMessage *register_watcher(DBusConnection *conn,
 							DBUS_TYPE_INVALID))
 		return btd_error_invalid_args(msg);
 
-	if (l2cap_connect(prim->gatt, &gerr, TRUE) < 0) {
+	if (l2cap_connect(gatt, &gerr, TRUE) < 0) {
 		DBusMessage *reply = btd_error_failed(msg, gerr->message);
 		g_error_free(gerr);
 		return reply;
@@ -432,12 +397,12 @@ static DBusMessage *register_watcher(DBusConnection *conn,
 
 	watcher = g_new0(struct watcher, 1);
 	watcher->name = g_strdup(sender);
-	watcher->prim = prim;
+	watcher->gatt = gatt;
 	watcher->path = g_strdup(path);
 	watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
 							watcher, watcher_free);
 
-	prim->watchers = g_slist_append(prim->watchers, watcher);
+	gatt->watchers = g_slist_append(gatt->watchers, watcher);
 
 	return dbus_message_new_method_return(msg);
 }
@@ -446,7 +411,7 @@ static DBusMessage *unregister_watcher(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
 	const char *sender = dbus_message_get_sender(msg);
-	struct primary *prim = data;
+	struct gatt_service *gatt = data;
 	struct watcher *watcher, *match;
 	GSList *l;
 	char *path;
@@ -458,14 +423,14 @@ static DBusMessage *unregister_watcher(DBusConnection *conn,
 	match = g_new0(struct watcher, 1);
 	match->name = g_strdup(sender);
 	match->path = g_strdup(path);
-	l = g_slist_find_custom(prim->watchers, match, watcher_cmp);
+	l = g_slist_find_custom(gatt->watchers, match, watcher_cmp);
 	watcher_free(match);
 	if (!l)
 		return btd_error_not_authorized(msg);
 
 	watcher = l->data;
 	g_dbus_remove_watch(conn, watcher->id);
-	prim->watchers = g_slist_remove(prim->watchers, watcher);
+	gatt->watchers = g_slist_remove(gatt->watchers, watcher);
 	watcher_free(watcher);
 
 	return dbus_message_new_method_return(msg);
@@ -474,7 +439,7 @@ static DBusMessage *unregister_watcher(DBusConnection *conn,
 static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg,
 			DBusMessageIter *iter, struct characteristic *chr)
 {
-	struct gatt_service *gatt = chr->prim->gatt;
+	struct gatt_service *gatt = chr->gatt;
 	DBusMessageIter sub;
 	GError *gerr = NULL;
 	uint8_t *value;
@@ -576,36 +541,34 @@ static char *characteristic_list_to_string(GSList *chars)
 	return g_string_free(characteristics, FALSE);
 }
 
-static void store_characteristics(struct gatt_service *gatt,
-							struct primary *prim)
+static void store_characteristics(const bdaddr_t *sba, const bdaddr_t *dba,
+						uint16_t start, GSList *chars)
 {
 	char *characteristics;
-	struct att_primary *att = prim->att;
-	bdaddr_t sba, dba;
-
-	characteristics = characteristic_list_to_string(prim->chars);
 
-	gatt_get_address(gatt, &sba, &dba);
+	characteristics = characteristic_list_to_string(chars);
 
-	write_device_characteristics(&sba, &dba, att->start, characteristics);
+	write_device_characteristics(sba, dba, start, characteristics);
 
 	g_free(characteristics);
 }
 
-static void register_characteristics(struct primary *prim)
+static void register_characteristic(gpointer data, gpointer user_data)
 {
-	GSList *lc;
-
-	for (lc = prim->chars; lc; lc = lc->next) {
-		struct characteristic *chr = lc->data;
-		g_dbus_register_interface(prim->gatt->conn, chr->path,
-				CHAR_INTERFACE, char_methods,
-				NULL, NULL, chr, NULL);
-		DBG("Registered: %s", chr->path);
-	}
+	struct characteristic *chr = data;
+	DBusConnection *conn = chr->gatt->conn;
+	const char *gatt_path = user_data;
+
+	chr->path = g_strdup_printf("%s/characteristic%04x", gatt_path,
+								chr->handle);
+
+	g_dbus_register_interface(conn, chr->path, CHAR_INTERFACE,
+					char_methods, NULL, NULL, chr, NULL);
+
+	DBG("Registered: %s", chr->path);
 }
 
-static GSList *string_to_characteristic_list(struct primary *prim,
+static GSList *string_to_characteristic_list(struct gatt_service *gatt,
 							const char *str)
 {
 	GSList *l = NULL;
@@ -632,10 +595,7 @@ static GSList *string_to_characteristic_list(struct primary *prim,
 			continue;
 		}
 
-		chr->prim = prim;
-		chr->path = g_strdup_printf("%s/characteristic%04x",
-						prim->path, chr->handle);
-
+		chr->gatt = gatt;
 		l = g_slist_append(l, chr);
 	}
 
@@ -644,37 +604,23 @@ static GSList *string_to_characteristic_list(struct primary *prim,
 	return l;
 }
 
-static void load_characteristics(gpointer data, gpointer user_data)
+static GSList *load_characteristics(struct gatt_service *gatt, uint16_t start)
 {
-	struct primary *prim = data;
-	struct att_primary *att = prim->att;
-	struct gatt_service *gatt = user_data;
-	bdaddr_t sba, dba;
 	GSList *chrs_list;
+	bdaddr_t sba, dba;
 	char *str;
 
-	if (prim->chars) {
-		DBG("Characteristics already loaded");
-		return;
-	}
-
 	gatt_get_address(gatt, &sba, &dba);
 
-	str = read_device_characteristics(&sba, &dba, att->start);
+	str = read_device_characteristics(&sba, &dba, start);
 	if (str == NULL)
-		return;
+		return NULL;
 
-	chrs_list = string_to_characteristic_list(prim, str);
+	chrs_list = string_to_characteristic_list(gatt, str);
 
 	free(str);
 
-	if (chrs_list == NULL)
-		return;
-
-	prim->chars = chrs_list;
-	register_characteristics(prim);
-
-	return;
+	return chrs_list;
 }
 
 static void store_attribute(struct gatt_service *gatt, uint16_t handle,
@@ -706,7 +652,7 @@ static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len,
 							gpointer user_data)
 {
 	struct query_data *current = user_data;
-	struct gatt_service *gatt = current->prim->gatt;
+	struct gatt_service *gatt = current->gatt;
 	struct characteristic *chr = current->chr;
 
 	if (status == 0) {
@@ -740,7 +686,7 @@ static void update_char_format(guint8 status, const guint8 *pdu, guint16 len,
 								gpointer user_data)
 {
 	struct query_data *current = user_data;
-	struct gatt_service *gatt = current->prim->gatt;
+	struct gatt_service *gatt = current->gatt;
 	struct characteristic *chr = current->chr;
 
 	if (status != 0)
@@ -766,7 +712,7 @@ static void update_char_value(guint8 status, const guint8 *pdu,
 					guint16 len, gpointer user_data)
 {
 	struct query_data *current = user_data;
-	struct gatt_service *gatt = current->prim->gatt;
+	struct gatt_service *gatt = current->gatt;
 	struct characteristic *chr = current->chr;
 
 	if (status == 0)
@@ -800,7 +746,7 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
 							gpointer user_data)
 {
 	struct query_data *current = user_data;
-	struct gatt_service *gatt = current->prim->gatt;
+	struct gatt_service *gatt = current->gatt;
 	struct att_data_list *list;
 	guint8 format;
 	int i;
@@ -832,7 +778,7 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
 			continue;
 		}
 		qfmt = g_new0(struct query_data, 1);
-		qfmt->prim = current->prim;
+		qfmt->gatt = current->gatt;
 		qfmt->chr = current->chr;
 		qfmt->handle = handle;
 
@@ -858,11 +804,10 @@ static void update_all_chars(gpointer data, gpointer user_data)
 {
 	struct query_data *qdesc, *qvalue;
 	struct characteristic *chr = data;
-	struct primary *prim = user_data;
-	struct gatt_service *gatt = prim->gatt;
+	struct gatt_service *gatt = user_data;
 
 	qdesc = g_new0(struct query_data, 1);
-	qdesc->prim = prim;
+	qdesc->gatt = gatt;
 	qdesc->chr = chr;
 
 	gatt->attrib = g_attrib_ref(gatt->attrib);
@@ -870,7 +815,7 @@ static void update_all_chars(gpointer data, gpointer user_data)
 									qdesc);
 
 	qvalue = g_new0(struct query_data, 1);
-	qvalue->prim = prim;
+	qvalue->gatt = gatt;
 	qvalue->chr = chr;
 
 	gatt->attrib = g_attrib_ref(gatt->attrib);
@@ -883,11 +828,11 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 	DBusMessage *reply;
 	DBusMessageIter iter, array_iter;
 	struct query_data *current = user_data;
-	struct primary *prim = current->prim;
-	struct att_primary *att = prim->att;
-	struct gatt_service *gatt = prim->gatt;
+	struct gatt_service *gatt = current->gatt;
+	struct att_primary *prim = gatt->prim;
 	uint16_t *previous_end = NULL;
 	GSList *l;
+	bdaddr_t sba, dba;
 
 	if (status != 0) {
 		const char *str = att_ecode2str(status);
@@ -903,17 +848,15 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 		guint handle = current_chr->value_handle;
 		GSList *lchr;
 
-		lchr = g_slist_find_custom(prim->chars,
+		lchr = g_slist_find_custom(gatt->chars,
 			GUINT_TO_POINTER(handle), characteristic_handle_cmp);
 		if (lchr)
 			continue;
 
 		chr = g_new0(struct characteristic, 1);
-		chr->prim = prim;
+		chr->gatt = gatt;
 		chr->perm = current_chr->properties;
 		chr->handle = current_chr->value_handle;
-		chr->path = g_strdup_printf("%s/characteristic%04x",
-						prim->path, chr->handle);
 		strncpy(chr->type, current_chr->uuid, sizeof(chr->type));
 
 		if (previous_end)
@@ -921,14 +864,16 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 
 		previous_end = &chr->end;
 
-		prim->chars = g_slist_append(prim->chars, chr);
+		gatt->chars = g_slist_append(gatt->chars, chr);
 	}
 
 	if (previous_end)
-		*previous_end = att->end;
+		*previous_end = prim->end;
+
+	gatt_get_address(gatt, &sba, &dba);
+	store_characteristics(&sba, &dba, prim->start, gatt->chars);
 
-	store_characteristics(gatt, prim);
-	register_characteristics(prim);
+	g_slist_foreach(gatt->chars, register_characteristic, gatt->path);
 
 	reply = dbus_message_new_method_return(current->msg);
 
@@ -937,7 +882,7 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
 				DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter);
 
-	for (l = prim->chars; l; l = l->next) {
+	for (l = gatt->chars; l; l = l->next) {
 		struct characteristic *chr = l->data;
 
 		dbus_message_iter_append_basic(&array_iter,
@@ -946,7 +891,7 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 
 	dbus_message_iter_close_container(&iter, &array_iter);
 
-	g_slist_foreach(prim->chars, update_all_chars, prim);
+	g_slist_foreach(gatt->chars, update_all_chars, gatt);
 
 fail:
 	g_dbus_send_message(gatt->conn, reply);
@@ -957,23 +902,22 @@ fail:
 static DBusMessage *discover_char(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
-	struct primary *prim = data;
-	struct att_primary *att = prim->att;
-	struct gatt_service *gatt = prim->gatt;
+	struct gatt_service *gatt = data;
+	struct att_primary *prim = gatt->prim;
 	struct query_data *qchr;
 	GError *gerr = NULL;
 
-	if (l2cap_connect(prim->gatt, &gerr, FALSE) < 0) {
+	if (l2cap_connect(gatt, &gerr, FALSE) < 0) {
 		DBusMessage *reply = btd_error_failed(msg, gerr->message);
 		g_error_free(gerr);
 		return reply;
 	}
 
 	qchr = g_new0(struct query_data, 1);
-	qchr->prim = prim;
+	qchr->gatt = gatt;
 	qchr->msg = dbus_message_ref(msg);
 
-	gatt_discover_char(gatt->attrib, att->start, att->end, NULL,
+	gatt_discover_char(gatt->attrib, prim->start, prim->end, NULL,
 						char_discovered_cb, qchr);
 
 	return NULL;
@@ -982,7 +926,7 @@ static DBusMessage *discover_char(DBusConnection *conn, DBusMessage *msg,
 static DBusMessage *prim_get_properties(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
-	struct primary *prim = data;
+	struct gatt_service *gatt = data;
 	DBusMessage *reply;
 	DBusMessageIter iter;
 	DBusMessageIter dict;
@@ -1002,16 +946,16 @@ static DBusMessage *prim_get_properties(DBusConnection *conn, DBusMessage *msg,
 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
 
-	chars = g_new0(char *, g_slist_length(prim->chars) + 1);
+	chars = g_new0(char *, g_slist_length(gatt->chars) + 1);
 
-	for (i = 0, l = prim->chars; l; l = l->next, i++) {
+	for (i = 0, l = gatt->chars; l; l = l->next, i++) {
 		struct characteristic *chr = l->data;
 		chars[i] = chr->path;
 	}
 
 	dict_append_array(&dict, "Characteristics", DBUS_TYPE_OBJECT_PATH,
 								&chars, i);
-	uuid = prim->att->uuid;
+	uuid = gatt->prim->uuid;
 	dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
 
 	g_free(chars);
@@ -1032,80 +976,92 @@ static GDBusMethodTable prim_methods[] = {
 	{ }
 };
 
-static struct primary *primary_register(struct gatt_service *gatt,
-						struct att_primary *prim)
+static struct gatt_service *primary_register(DBusConnection *conn,
+						struct btd_device *device,
+						struct att_primary *prim,
+						int psm)
 {
-	struct btd_device *device = gatt->dev;
+	struct gatt_service *gatt;
 	const char *device_path;
-	struct primary *data;
 
 	device_path = device_get_path(device);
 
-	data = g_new0(struct primary, 1);
-	data->att = prim;
-	data->gatt = gatt;
-	data->path = g_strdup_printf("%s/service%04x", device_path,
+	gatt = g_new0(struct gatt_service, 1);
+	gatt->dev = btd_device_ref(device);
+	gatt->prim = prim;
+	gatt->psm = psm;
+	gatt->listen = FALSE;
+	gatt->conn = dbus_connection_ref(conn);
+	gatt->path = g_strdup_printf("%s/service%04x", device_path,
 								prim->start);
 
-	g_dbus_register_interface(gatt->conn, data->path,
+	g_dbus_register_interface(gatt->conn, gatt->path,
 					CHAR_INTERFACE, prim_methods,
-					NULL, NULL, data, NULL);
-
-	load_characteristics(data, gatt);
+					NULL, NULL, gatt, NULL);
+	gatt->chars = load_characteristics(gatt, prim->start);
+	g_slist_foreach(gatt->chars, register_characteristic, gatt->path);
 
-	return data;
+	return gatt;
 }
 
 GSList *attrib_client_register(DBusConnection *connection,
 					struct btd_device *device, int psm,
 					GAttrib *attrib, GSList *primaries)
 {
-	struct gatt_service *gatt;
-	GSList *l;
-
-	gatt = g_new0(struct gatt_service, 1);
-	gatt->dev = btd_device_ref(device);
-	gatt->conn = dbus_connection_ref(connection);
-	gatt->listen = FALSE;
-	gatt->psm = psm;
+	GSList *l, *services;
 
-	for (l = primaries; l; l = l->next) {
+	for (l = primaries, services = NULL; l; l = l->next) {
 		struct att_primary *prim = l->data;
-		struct primary *data;
+		struct gatt_service *gatt;
+
+		gatt = primary_register(connection, device, prim, psm);
 
-		data = primary_register(gatt, prim);
-		gatt->primary = g_slist_append(gatt->primary, data);
+		DBG("Registered: %s", gatt->path);
 
-		DBG("Registered: %s", data->path);
+		services = g_slist_append(services, g_strdup(gatt->path));
+		gatt_services = g_slist_append(gatt_services, gatt);
 	}
 
-	gatt_services = g_slist_append(gatt_services, gatt);
+	return services;
+}
+
+static void primary_unregister(struct gatt_service *gatt)
+{
+	GSList *l;
 
-	return gatt_services;
+	for (l = gatt->chars; l; l = l->next) {
+		struct characteristic *chr = l->data;
+		g_dbus_unregister_interface(gatt->conn, chr->path,
+							CHAR_INTERFACE);
+	}
+
+	g_dbus_unregister_interface(gatt->conn, gatt->path, CHAR_INTERFACE);
 }
 
-void attrib_client_unregister(struct btd_device *device)
+static int path_cmp(gconstpointer data, gconstpointer user_data)
 {
-	struct gatt_service *gatt;
-	GSList *l, *lp, *lc;
+	const char *path = data;
+	const char *gatt_path = user_data;
 
-	l = g_slist_find_custom(gatt_services, device, gatt_dev_cmp);
-	if (!l)
-		return;
+	return g_strcmp0(path, gatt_path);
+}
+
+void attrib_client_unregister(GSList *services)
+{
+	GSList *l, *left;
 
-	gatt = l->data;
-	gatt_services = g_slist_remove(gatt_services, gatt);
+	for (l = gatt_services, left = NULL; l; l = l->next) {
+		struct gatt_service *gatt = l->data;
 
-	for (lp = gatt->primary; lp; lp = lp->next) {
-		struct primary *prim = lp->data;
-		for (lc = prim->chars; lc; lc = lc->next) {
-			struct characteristic *chr = lc->data;
-			g_dbus_unregister_interface(gatt->conn, chr->path,
-								CHAR_INTERFACE);
+		if (!g_slist_find_custom(services, gatt->path, path_cmp)) {
+			left = g_slist_append(left, gatt);
+			continue;
 		}
-		g_dbus_unregister_interface(gatt->conn, prim->path,
-								CHAR_INTERFACE);
+
+		primary_unregister(gatt);
+		gatt_service_free(gatt);
 	}
 
-	gatt_service_free(gatt);
+	g_slist_free(gatt_services);
+	gatt_services = left;
 }
diff --git a/attrib/client.h b/attrib/client.h
index b29797c..948f030 100644
--- a/attrib/client.h
+++ b/attrib/client.h
@@ -25,4 +25,4 @@
 GSList *attrib_client_register(DBusConnection *connection,
 					struct btd_device *device, int psm,
 					GAttrib *attrib, GSList *primaries);
-void attrib_client_unregister(struct btd_device *device);
+void attrib_client_unregister(GSList *services);
diff --git a/src/device.c b/src/device.c
index 4d17082..9342d19 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1037,7 +1037,7 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
 	g_slist_free(device->drivers);
 	device->drivers = NULL;
 
-	attrib_client_unregister(device);
+	attrib_client_unregister(device->services);
 
 	btd_device_unref(device);
 }
-- 
1.7.6


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

* [PATCH BlueZ 06/11] Register the ATT connection callbacks
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (4 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 05/11] Cleanup of primary service structs Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 07/11] Remove implicit connection from generic API Claudio Takahasi
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Registers the ATT connection and disconnection callbacks in the generic
attribute API. First commit to remove implicit L2CAP connection
establishment.
---
 attrib/client.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 482aff1..29cb34a 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -48,6 +48,7 @@
 
 #include "att.h"
 #include "gattrib.h"
+#include "attio.h"
 #include "gatt.h"
 #include "client.h"
 
@@ -66,6 +67,7 @@ struct gatt_service {
 	struct att_primary *prim;
 	DBusConnection *conn;
 	GAttrib *attrib;
+	guint attioid;
 	int psm;
 	char *path;
 	GSList *chars;
@@ -976,6 +978,20 @@ static GDBusMethodTable prim_methods[] = {
 	{ }
 };
 
+static void attio_connected(GAttrib *attrib, gpointer user_data)
+{
+	struct gatt_service *gatt = user_data;
+
+	gatt->attrib = attrib;
+}
+
+static void attio_disconnected(gpointer user_data)
+{
+	struct gatt_service *gatt = user_data;
+
+	gatt->attrib = NULL;
+}
+
 static struct gatt_service *primary_register(DBusConnection *conn,
 						struct btd_device *device,
 						struct att_primary *prim,
@@ -995,6 +1011,9 @@ static struct gatt_service *primary_register(DBusConnection *conn,
 	gatt->path = g_strdup_printf("%s/service%04x", device_path,
 								prim->start);
 
+	gatt->attioid = btd_device_add_attio_callback(device, attio_connected,
+						attio_disconnected, gatt);
+
 	g_dbus_register_interface(gatt->conn, gatt->path,
 					CHAR_INTERFACE, prim_methods,
 					NULL, NULL, gatt, NULL);
@@ -1020,6 +1039,7 @@ GSList *attrib_client_register(DBusConnection *connection,
 
 		services = g_slist_append(services, g_strdup(gatt->path));
 		gatt_services = g_slist_append(gatt_services, gatt);
+
 	}
 
 	return services;
@@ -1029,6 +1049,8 @@ static void primary_unregister(struct gatt_service *gatt)
 {
 	GSList *l;
 
+	btd_device_remove_attio_callback(gatt->dev, gatt->attioid);
+
 	for (l = gatt->chars; l; l = l->next) {
 		struct characteristic *chr = l->data;
 		g_dbus_unregister_interface(gatt->conn, chr->path,
-- 
1.7.6


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

* [PATCH BlueZ 07/11] Remove implicit connection from generic API
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (5 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 06/11] Register the ATT connection callbacks Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 08/11] Change GAttrib ref counting in Generic Attribute Claudio Takahasi
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Generic attribute API should not actively manage L2CAP connections.
GAttrib instance is notified through registered callbacks. SetProperty
or DiscoverCharacteristic now returns NotConnected error if the link
is down.
---
 attrib/client.c |  121 +++++--------------------------------------------------
 1 files changed, 10 insertions(+), 111 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 29cb34a..7f0dac4 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -72,7 +72,6 @@ struct gatt_service {
 	char *path;
 	GSList *chars;
 	GSList *watchers;
-	gboolean listen;
 };
 
 struct characteristic {
@@ -289,114 +288,18 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
 	}
 }
 
-static void attrib_destroy(gpointer user_data)
-{
-	struct gatt_service *gatt = user_data;
-
-	gatt->attrib = NULL;
-}
-
-static void attrib_disconnect(gpointer user_data)
-{
-	struct gatt_service *gatt = user_data;
-
-	/* Remote initiated disconnection only */
-	g_attrib_unref(gatt->attrib);
-}
-
-static void connect_cb(GIOChannel *chan, GError *gerr, gpointer user_data)
-{
-	struct gatt_service *gatt = user_data;
-
-	if (gerr) {
-		error("%s", gerr->message);
-		goto fail;
-	}
-
-	if (gatt->attrib == NULL)
-		return;
-
-	/* Listen mode: used for notification and indication */
-	if (gatt->listen == TRUE) {
-		g_attrib_register(gatt->attrib,
-					ATT_OP_HANDLE_NOTIFY,
-					events_handler, gatt, NULL);
-		g_attrib_register(gatt->attrib,
-					ATT_OP_HANDLE_IND,
-					events_handler, gatt, NULL);
-		return;
-	}
-
-	return;
-fail:
-	g_attrib_unref(gatt->attrib);
-}
-
-static int l2cap_connect(struct gatt_service *gatt, GError **gerr,
-								gboolean listen)
-{
-	bdaddr_t sba, dba;
-	GIOChannel *io;
-
-	if (gatt->attrib != NULL) {
-		gatt->attrib = g_attrib_ref(gatt->attrib);
-		gatt->listen = listen;
-		return 0;
-	}
-
-	/*
-	 * FIXME: If the service doesn't support Client Characteristic
-	 * Configuration it is necessary to poll the server from time
-	 * to time checking for modifications.
-	 */
-	gatt_get_address(gatt, &sba, &dba);
-	if (gatt->psm < 0)
-		io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, gerr,
-			BT_IO_OPT_SOURCE_BDADDR, &sba,
-			BT_IO_OPT_DEST_BDADDR, &dba,
-			BT_IO_OPT_CID, ATT_CID,
-			BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
-			BT_IO_OPT_INVALID);
-	else
-		io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, gerr,
-			BT_IO_OPT_SOURCE_BDADDR, &sba,
-			BT_IO_OPT_DEST_BDADDR, &dba,
-			BT_IO_OPT_PSM, gatt->psm,
-			BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
-			BT_IO_OPT_INVALID);
-	if (!io)
-		return -1;
-
-	gatt->attrib = g_attrib_new(io);
-	g_io_channel_unref(io);
-	gatt->listen = listen;
-
-	g_attrib_set_destroy_function(gatt->attrib, attrib_destroy, gatt);
-	g_attrib_set_disconnect_function(gatt->attrib, attrib_disconnect,
-									gatt);
-
-	return 0;
-}
-
 static DBusMessage *register_watcher(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
 	const char *sender = dbus_message_get_sender(msg);
 	struct gatt_service *gatt = data;
 	struct watcher *watcher;
-	GError *gerr = NULL;
 	char *path;
 
 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
 							DBUS_TYPE_INVALID))
 		return btd_error_invalid_args(msg);
 
-	if (l2cap_connect(gatt, &gerr, TRUE) < 0) {
-		DBusMessage *reply = btd_error_failed(msg, gerr->message);
-		g_error_free(gerr);
-		return reply;
-	}
-
 	watcher = g_new0(struct watcher, 1);
 	watcher->name = g_strdup(sender);
 	watcher->gatt = gatt;
@@ -443,10 +346,12 @@ static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg,
 {
 	struct gatt_service *gatt = chr->gatt;
 	DBusMessageIter sub;
-	GError *gerr = NULL;
 	uint8_t *value;
 	int len;
 
+	if (gatt->attrib == NULL)
+		return btd_error_not_connected(msg);
+
 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
 			dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE)
 		return btd_error_invalid_args(msg);
@@ -455,12 +360,6 @@ static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg,
 
 	dbus_message_iter_get_fixed_array(&sub, &value, &len);
 
-	if (l2cap_connect(gatt, &gerr, FALSE) < 0) {
-		DBusMessage *reply = btd_error_failed(msg, gerr->message);
-		g_error_free(gerr);
-		return reply;
-	}
-
 	gatt_write_cmd(gatt->attrib, chr->handle, value, len, NULL, NULL);
 
 	characteristic_set_value(chr, value, len);
@@ -907,13 +806,9 @@ static DBusMessage *discover_char(DBusConnection *conn, DBusMessage *msg,
 	struct gatt_service *gatt = data;
 	struct att_primary *prim = gatt->prim;
 	struct query_data *qchr;
-	GError *gerr = NULL;
 
-	if (l2cap_connect(gatt, &gerr, FALSE) < 0) {
-		DBusMessage *reply = btd_error_failed(msg, gerr->message);
-		g_error_free(gerr);
-		return reply;
-	}
+	if (gatt->attrib == NULL)
+		return btd_error_not_connected(msg);
 
 	qchr = g_new0(struct query_data, 1);
 	qchr->gatt = gatt;
@@ -983,6 +878,11 @@ static void attio_connected(GAttrib *attrib, gpointer user_data)
 	struct gatt_service *gatt = user_data;
 
 	gatt->attrib = attrib;
+
+	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_NOTIFY,
+					events_handler, gatt, NULL);
+	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_IND,
+					events_handler, gatt, NULL);
 }
 
 static void attio_disconnected(gpointer user_data)
@@ -1006,7 +906,6 @@ static struct gatt_service *primary_register(DBusConnection *conn,
 	gatt->dev = btd_device_ref(device);
 	gatt->prim = prim;
 	gatt->psm = psm;
-	gatt->listen = FALSE;
 	gatt->conn = dbus_connection_ref(conn);
 	gatt->path = g_strdup_printf("%s/service%04x", device_path,
 								prim->start);
-- 
1.7.6


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

* [PATCH BlueZ 08/11] Change GAttrib ref counting in Generic Attribute
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (6 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 07/11] Remove implicit connection from generic API Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 09/11] Register ATT connection callback based on watchers Claudio Takahasi
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

---
 attrib/client.c |   12 ------------
 1 files changed, 0 insertions(+), 12 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 7f0dac4..5177524 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -130,7 +130,6 @@ static void gatt_service_free(struct gatt_service *gatt)
 	g_slist_free_full(gatt->watchers, watcher_free);
 	g_slist_free_full(gatt->chars, characteristic_free);
 	g_free(gatt->path);
-	g_attrib_unref(gatt->attrib);
 	btd_device_unref(gatt->dev);
 	dbus_connection_unref(gatt->conn);
 	g_free(gatt);
@@ -207,8 +206,6 @@ static void watcher_exit(DBusConnection *conn, void *user_data)
 	DBG("%s watcher %s exited", gatt->path, watcher->name);
 
 	gatt->watchers = g_slist_remove(gatt->watchers, watcher);
-
-	g_attrib_unref(gatt->attrib);
 }
 
 static int characteristic_set_value(struct characteristic *chr,
@@ -579,7 +576,6 @@ static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len,
 		}
 	}
 
-	g_attrib_unref(gatt->attrib);
 	g_free(current);
 }
 
@@ -605,7 +601,6 @@ static void update_char_format(guint8 status, const guint8 *pdu, guint16 len,
 				(void *) chr->format, sizeof(*chr->format));
 
 done:
-	g_attrib_unref(gatt->attrib);
 	g_free(current);
 }
 
@@ -630,7 +625,6 @@ static void update_char_value(guint8 status, const guint8 *pdu,
 		}
 	}
 
-	g_attrib_unref(gatt->attrib);
 	g_free(current);
 }
 
@@ -684,11 +678,9 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
 		qfmt->handle = handle;
 
 		if (uuid_desc16_cmp(&uuid, GATT_CHARAC_USER_DESC_UUID) == 0) {
-			gatt->attrib = g_attrib_ref(gatt->attrib);
 			gatt_read_char(gatt->attrib, handle, 0, update_char_desc,
 									qfmt);
 		} else if (uuid_desc16_cmp(&uuid, GATT_CHARAC_FMT_UUID) == 0) {
-			gatt->attrib = g_attrib_ref(gatt->attrib);
 			gatt_read_char(gatt->attrib, handle, 0,
 						update_char_format, qfmt);
 		} else
@@ -697,7 +689,6 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
 
 	att_data_list_free(list);
 done:
-	g_attrib_unref(gatt->attrib);
 	g_free(current);
 }
 
@@ -711,7 +702,6 @@ static void update_all_chars(gpointer data, gpointer user_data)
 	qdesc->gatt = gatt;
 	qdesc->chr = chr;
 
-	gatt->attrib = g_attrib_ref(gatt->attrib);
 	gatt_find_info(gatt->attrib, chr->handle + 1, chr->end, descriptor_cb,
 									qdesc);
 
@@ -719,7 +709,6 @@ static void update_all_chars(gpointer data, gpointer user_data)
 	qvalue->gatt = gatt;
 	qvalue->chr = chr;
 
-	gatt->attrib = g_attrib_ref(gatt->attrib);
 	gatt_read_char(gatt->attrib, chr->handle, 0, update_char_value, qvalue);
 }
 
@@ -796,7 +785,6 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 
 fail:
 	g_dbus_send_message(gatt->conn, reply);
-	g_attrib_unref(gatt->attrib);
 	g_free(current);
 }
 
-- 
1.7.6


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

* [PATCH BlueZ 09/11] Register ATT connection callback based on watchers
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (7 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 08/11] Change GAttrib ref counting in Generic Attribute Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 10/11] On demand connection for characteristics discovery Claudio Takahasi
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

In the Generic Attribute API, the ATT connection should be requested
on demand. In the case of watchers, the connection doesn't need to be
stay up if there isn't watcher registered.
---
 attrib/client.c |   55 ++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 32 insertions(+), 23 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 5177524..962cdb7 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -285,6 +285,25 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
 	}
 }
 
+static void attio_connected(GAttrib *attrib, gpointer user_data)
+{
+	struct gatt_service *gatt = user_data;
+
+	gatt->attrib = attrib;
+
+	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_NOTIFY,
+					events_handler, gatt, NULL);
+	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_IND,
+					events_handler, gatt, NULL);
+}
+
+static void attio_disconnected(gpointer user_data)
+{
+	struct gatt_service *gatt = user_data;
+
+	gatt->attrib = NULL;
+}
+
 static DBusMessage *register_watcher(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
@@ -304,6 +323,12 @@ static DBusMessage *register_watcher(DBusConnection *conn,
 	watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
 							watcher, watcher_free);
 
+	if (gatt->attioid == 0)
+		gatt->attioid = btd_device_add_attio_callback(gatt->dev,
+							attio_connected,
+							attio_disconnected,
+							gatt);
+
 	gatt->watchers = g_slist_append(gatt->watchers, watcher);
 
 	return dbus_message_new_method_return(msg);
@@ -335,6 +360,11 @@ static DBusMessage *unregister_watcher(DBusConnection *conn,
 	gatt->watchers = g_slist_remove(gatt->watchers, watcher);
 	watcher_free(watcher);
 
+	if (gatt->watchers == NULL && gatt->attioid) {
+		btd_device_remove_attio_callback(gatt->dev, gatt->attioid);
+		gatt->attioid = 0;
+	}
+
 	return dbus_message_new_method_return(msg);
 }
 
@@ -861,25 +891,6 @@ static GDBusMethodTable prim_methods[] = {
 	{ }
 };
 
-static void attio_connected(GAttrib *attrib, gpointer user_data)
-{
-	struct gatt_service *gatt = user_data;
-
-	gatt->attrib = attrib;
-
-	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_NOTIFY,
-					events_handler, gatt, NULL);
-	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_IND,
-					events_handler, gatt, NULL);
-}
-
-static void attio_disconnected(gpointer user_data)
-{
-	struct gatt_service *gatt = user_data;
-
-	gatt->attrib = NULL;
-}
-
 static struct gatt_service *primary_register(DBusConnection *conn,
 						struct btd_device *device,
 						struct att_primary *prim,
@@ -898,9 +909,6 @@ static struct gatt_service *primary_register(DBusConnection *conn,
 	gatt->path = g_strdup_printf("%s/service%04x", device_path,
 								prim->start);
 
-	gatt->attioid = btd_device_add_attio_callback(device, attio_connected,
-						attio_disconnected, gatt);
-
 	g_dbus_register_interface(gatt->conn, gatt->path,
 					CHAR_INTERFACE, prim_methods,
 					NULL, NULL, gatt, NULL);
@@ -936,7 +944,8 @@ static void primary_unregister(struct gatt_service *gatt)
 {
 	GSList *l;
 
-	btd_device_remove_attio_callback(gatt->dev, gatt->attioid);
+	if (gatt->attioid)
+		btd_device_remove_attio_callback(gatt->dev, gatt->attioid);
 
 	for (l = gatt->chars; l; l = l->next) {
 		struct characteristic *chr = l->data;
-- 
1.7.6


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

* [PATCH BlueZ 10/11] On demand connection for characteristics discovery
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (8 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 09/11] Register ATT connection callback based on watchers Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-12 20:28 ` [PATCH BlueZ 11/11] Add on demand characteristic write Claudio Takahasi
  2011-07-27  7:33 ` [PATCH BlueZ 00/11] On demand connection in Generic Attribute Johan Hedberg
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

In the Generic Attribute API, when DiscoverCharacteristics is called
ATT connection should be requested if the link is not up. A query
list is required to control when the link can be disconnected since
the discover finishes after receiving all caracteristic declarations.
---
 attrib/client.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 75 insertions(+), 9 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 962cdb7..03d161e 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -62,6 +62,12 @@ struct format {
 	guint16 desc;
 } __attribute__ ((packed));
 
+struct query {
+	DBusMessage *msg;
+	guint attioid;
+	GSList *list;
+};
+
 struct gatt_service {
 	struct btd_device *dev;
 	struct att_primary *prim;
@@ -72,6 +78,7 @@ struct gatt_service {
 	char *path;
 	GSList *chars;
 	GSList *watchers;
+	struct query *query;
 };
 
 struct characteristic {
@@ -91,7 +98,6 @@ struct characteristic {
 struct query_data {
 	struct gatt_service *gatt;
 	struct characteristic *chr;
-	DBusMessage *msg;
 	uint16_t handle;
 };
 
@@ -576,6 +582,27 @@ static void store_attribute(struct gatt_service *gatt, uint16_t handle,
 	g_free(str);
 }
 
+static void query_list_append(struct gatt_service *gatt, struct query_data *data)
+{
+	struct query *query = gatt->query;
+
+	query->list = g_slist_append(query->list, data);
+}
+
+static void query_list_remove(struct gatt_service *gatt, struct query_data *data)
+{
+	struct query *query = gatt->query;
+
+	query->list = g_slist_remove(query->list, data);
+	if (query->list != NULL)
+		return;
+
+	btd_device_remove_attio_callback(gatt->dev, query->attioid);
+	g_free(query);
+
+	gatt->query = NULL;
+}
+
 static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len,
 							gpointer user_data)
 {
@@ -606,6 +633,7 @@ static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len,
 		}
 	}
 
+	query_list_remove(gatt, current);
 	g_free(current);
 }
 
@@ -631,6 +659,7 @@ static void update_char_format(guint8 status, const guint8 *pdu, guint16 len,
 				(void *) chr->format, sizeof(*chr->format));
 
 done:
+	query_list_remove(gatt, current);
 	g_free(current);
 }
 
@@ -655,6 +684,7 @@ static void update_char_value(guint8 status, const guint8 *pdu,
 		}
 	}
 
+	query_list_remove(gatt, current);
 	g_free(current);
 }
 
@@ -708,9 +738,11 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
 		qfmt->handle = handle;
 
 		if (uuid_desc16_cmp(&uuid, GATT_CHARAC_USER_DESC_UUID) == 0) {
+			query_list_append(gatt, qfmt);
 			gatt_read_char(gatt->attrib, handle, 0, update_char_desc,
 									qfmt);
 		} else if (uuid_desc16_cmp(&uuid, GATT_CHARAC_FMT_UUID) == 0) {
+			query_list_append(gatt, qfmt);
 			gatt_read_char(gatt->attrib, handle, 0,
 						update_char_format, qfmt);
 		} else
@@ -719,6 +751,7 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
 
 	att_data_list_free(list);
 done:
+	query_list_remove(gatt, current);
 	g_free(current);
 }
 
@@ -732,6 +765,8 @@ static void update_all_chars(gpointer data, gpointer user_data)
 	qdesc->gatt = gatt;
 	qdesc->chr = chr;
 
+	query_list_append(gatt, qdesc);
+
 	gatt_find_info(gatt->attrib, chr->handle + 1, chr->end, descriptor_cb,
 									qdesc);
 
@@ -739,6 +774,8 @@ static void update_all_chars(gpointer data, gpointer user_data)
 	qvalue->gatt = gatt;
 	qvalue->chr = chr;
 
+	query_list_append(gatt, qvalue);
+
 	gatt_read_char(gatt->attrib, chr->handle, 0, update_char_value, qvalue);
 }
 
@@ -758,7 +795,7 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 		const char *str = att_ecode2str(status);
 
 		DBG("Discover all characteristics failed: %s", str);
-		reply = btd_error_failed(current->msg, str);
+		reply = btd_error_failed(gatt->query->msg, str);
 		goto fail;
 	}
 
@@ -795,7 +832,7 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 
 	g_slist_foreach(gatt->chars, register_characteristic, gatt->path);
 
-	reply = dbus_message_new_method_return(current->msg);
+	reply = dbus_message_new_method_return(gatt->query->msg);
 
 	dbus_message_iter_init_append(reply, &iter);
 
@@ -815,25 +852,54 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
 
 fail:
 	g_dbus_send_message(gatt->conn, reply);
+	query_list_remove(gatt, current);
 	g_free(current);
 }
 
+static void send_discover(GAttrib *attrib, gpointer user_data)
+{
+	struct query_data *qchr = user_data;
+	struct gatt_service *gatt = qchr->gatt;
+	struct att_primary *prim = gatt->prim;
+
+	gatt->attrib = attrib;
+
+	gatt_discover_char(gatt->attrib, prim->start, prim->end, NULL,
+						char_discovered_cb, qchr);
+}
+
+static void cancel_discover(gpointer user_data)
+{
+	struct query_data *qchr = user_data;
+	struct gatt_service *gatt = qchr->gatt;
+
+	gatt->attrib = NULL;
+}
+
 static DBusMessage *discover_char(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
 	struct gatt_service *gatt = data;
-	struct att_primary *prim = gatt->prim;
+	struct query *query;
 	struct query_data *qchr;
 
-	if (gatt->attrib == NULL)
-		return btd_error_not_connected(msg);
+	if (gatt->query)
+		return btd_error_busy(msg);
+
+	query = g_new0(struct query, 1);
 
 	qchr = g_new0(struct query_data, 1);
 	qchr->gatt = gatt;
-	qchr->msg = dbus_message_ref(msg);
 
-	gatt_discover_char(gatt->attrib, prim->start, prim->end, NULL,
-						char_discovered_cb, qchr);
+	query->msg = dbus_message_ref(msg);
+	query->attioid = btd_device_add_attio_callback(gatt->dev,
+							send_discover,
+							cancel_discover,
+							qchr);
+
+	gatt->query = query;
+
+	query_list_append(gatt, qchr);
 
 	return NULL;
 }
-- 
1.7.6


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

* [PATCH BlueZ 11/11] Add on demand characteristic write
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (9 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 10/11] On demand connection for characteristics discovery Claudio Takahasi
@ 2011-07-12 20:28 ` Claudio Takahasi
  2011-07-27  7:33 ` [PATCH BlueZ 00/11] On demand connection in Generic Attribute Johan Hedberg
  11 siblings, 0 replies; 13+ messages in thread
From: Claudio Takahasi @ 2011-07-12 20:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Changes the Generic Attribute registering a callback to request ATT
connection(if necessary) and write the characteristic value.
---
 attrib/client.c |   42 +++++++++++++++++++++++++++++++++++++-----
 1 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 03d161e..70cbf15 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -77,6 +77,7 @@ struct gatt_service {
 	int psm;
 	char *path;
 	GSList *chars;
+	GSList *offline_chars;
 	GSList *watchers;
 	struct query *query;
 };
@@ -135,6 +136,7 @@ static void gatt_service_free(struct gatt_service *gatt)
 {
 	g_slist_free_full(gatt->watchers, watcher_free);
 	g_slist_free_full(gatt->chars, characteristic_free);
+	g_slist_free(gatt->offline_chars);
 	g_free(gatt->path);
 	btd_device_unref(gatt->dev);
 	dbus_connection_unref(gatt->conn);
@@ -291,6 +293,29 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
 	}
 }
 
+static void offline_char_written(gpointer user_data)
+{
+	struct characteristic *chr = user_data;
+	struct gatt_service *gatt = chr->gatt;
+
+	gatt->offline_chars = g_slist_remove(gatt->offline_chars, chr);
+
+	if (gatt->offline_chars || gatt->watchers)
+		return;
+
+	btd_device_remove_attio_callback(gatt->dev, gatt->attioid);
+	gatt->attioid = 0;
+}
+
+static void offline_char_write(gpointer data, gpointer user_data)
+{
+	struct characteristic *chr = data;
+	GAttrib *attrib = user_data;
+
+	gatt_write_cmd(attrib, chr->handle, chr->value, chr->vlen,
+						offline_char_written, chr);
+}
+
 static void attio_connected(GAttrib *attrib, gpointer user_data)
 {
 	struct gatt_service *gatt = user_data;
@@ -301,6 +326,8 @@ static void attio_connected(GAttrib *attrib, gpointer user_data)
 					events_handler, gatt, NULL);
 	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_IND,
 					events_handler, gatt, NULL);
+
+	g_slist_foreach(gatt->offline_chars, offline_char_write, attrib);
 }
 
 static void attio_disconnected(gpointer user_data)
@@ -382,9 +409,6 @@ static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg,
 	uint8_t *value;
 	int len;
 
-	if (gatt->attrib == NULL)
-		return btd_error_not_connected(msg);
-
 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
 			dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE)
 		return btd_error_invalid_args(msg);
@@ -393,10 +417,18 @@ static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg,
 
 	dbus_message_iter_get_fixed_array(&sub, &value, &len);
 
-	gatt_write_cmd(gatt->attrib, chr->handle, value, len, NULL, NULL);
-
 	characteristic_set_value(chr, value, len);
 
+	if (gatt->attioid == 0) {
+		gatt->attioid = btd_device_add_attio_callback(gatt->dev,
+							attio_connected,
+							attio_disconnected,
+							gatt);
+		gatt->offline_chars = g_slist_append(gatt->offline_chars, chr);
+	} else
+		gatt_write_cmd(gatt->attrib, chr->handle, value, len,
+								NULL, NULL);
+
 	return dbus_message_new_method_return(msg);
 }
 
-- 
1.7.6


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

* Re: [PATCH BlueZ 00/11] On demand connection in Generic Attribute
  2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
                   ` (10 preceding siblings ...)
  2011-07-12 20:28 ` [PATCH BlueZ 11/11] Add on demand characteristic write Claudio Takahasi
@ 2011-07-27  7:33 ` Johan Hedberg
  11 siblings, 0 replies; 13+ messages in thread
From: Johan Hedberg @ 2011-07-27  7:33 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth

Hi Claudio,

On Tue, Jul 12, 2011, Claudio Takahasi wrote:
> Dependency:"[PATCH BlueZ 00/12] On demand connection management"
> 
> The following patch series contains cleanups in the Generic Attribute
> code and it uses the mechanism based on registered connection callbacks
> to manage connections.
> 
> Watchers register connection callback to allow receiving notifications. If
> watchers are not registered and other GATT based profile doesn't require
> an active connection, callbacks can be unregistered. SetProperty and
> DiscoverCharacteristics methods request on demand connection if necessary.
> 
> Claudio Takahasi (11):
>   Remove not necessary data from gatt_service
>   Remove storing device path in gatt_service
>   Remove leftover D-Bus message in gatt_service
>   Cleanup of primary service registration
>   Cleanup of primary service structs
>   Register the ATT connection callbacks
>   Remove implicit connection from generic API
>   Change GAttrib ref counting in Generic Attribute
>   Register ATT connection callback based on watchers
>   On demand connection for characteristics discovery
>   Add on demand characteristic write
> 
>  attrib/client.c |  593 ++++++++++++++++++++++++++----------------------------
>  attrib/client.h |    2 +-
>  src/device.c    |    2 +-
>  3 files changed, 288 insertions(+), 309 deletions(-)

This patch set has been pushed upstream. Thanks.

Johan

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

end of thread, other threads:[~2011-07-27  7:33 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-12 20:28 [PATCH BlueZ 00/11] On demand connection in Generic Attribute Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 01/11] Remove not necessary data from gatt_service Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 02/11] Remove storing device path in gatt_service Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 03/11] Remove leftover D-Bus message " Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 04/11] Cleanup of primary service registration Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 05/11] Cleanup of primary service structs Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 06/11] Register the ATT connection callbacks Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 07/11] Remove implicit connection from generic API Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 08/11] Change GAttrib ref counting in Generic Attribute Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 09/11] Register ATT connection callback based on watchers Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 10/11] On demand connection for characteristics discovery Claudio Takahasi
2011-07-12 20:28 ` [PATCH BlueZ 11/11] Add on demand characteristic write Claudio Takahasi
2011-07-27  7:33 ` [PATCH BlueZ 00/11] On demand connection in Generic Attribute Johan Hedberg

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.