Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ 0/7] CCC persistence
@ 2011-10-13 14:43 Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 1/7] Add storage functions to deal with CCC Claudio Takahasi
                   ` (7 more replies)
  0 siblings, 8 replies; 17+ messages in thread
From: Claudio Takahasi @ 2011-10-13 14:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

The following patches implement the storage of the Client Characteristic
Configuration: controls notification & indication.

Bonding verification is coming in the next patch series.

Based on the requirements of the available profiles attrib server will
require some changes. The future plan is to move attribute values to
plugins (eg: time) and keep only the attribute declaration in the attrib
server.

Claudio Takahasi (6):
  Remove CCC for read by group
  Remove CCC for read by type
  Add CCC persistence in attrib server
  Remove notification and indication from server
  Remove CCC entries when device is removed
  Add generic function to delete by pattern

Vinicius Costa Gomes (1):
  Add storage functions to deal with CCC

 src/attrib-server.c |  217 ++++++++++-----------------------------------------
 src/storage.c       |  100 +++++++++++++++++-------
 src/storage.h       |    4 +
 3 files changed, 116 insertions(+), 205 deletions(-)

-- 
1.7.7


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

* [PATCH BlueZ 1/7] Add storage functions to deal with CCC
  2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
@ 2011-10-13 14:43 ` Claudio Takahasi
  2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 2/7] Remove CCC for read by group Claudio Takahasi
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Claudio Takahasi @ 2011-10-13 14:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

From: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>

CCC (Client Characteristic Configuration) is used to allow configuration
whether to send updates about an characteristic value.
---
 src/storage.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 src/storage.h |    4 ++++
 2 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/src/storage.c b/src/storage.c
index c64842c..082a046 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -1262,3 +1262,47 @@ int read_device_attributes(const bdaddr_t *sba, textfile_cb func, void *data)
 
 	return textfile_foreach(filename, func, data);
 }
+
+int read_device_ccc(bdaddr_t *local, bdaddr_t *peer, uint16_t handle,
+							uint16_t *value)
+{
+	char filename[PATH_MAX + 1], addr[18], key[23];
+	char *str;
+	unsigned int config;
+	int err = 0;
+
+	create_filename(filename, PATH_MAX, local, "ccc");
+
+	ba2str(peer, addr);
+	snprintf(key, sizeof(key), "%17s#%04X", addr, handle);
+
+	str = textfile_caseget(filename, key);
+	if (str == NULL)
+		return -ENOENT;
+
+	if (sscanf(str, "%04X", &config) != 1)
+		err = -ENOENT;
+	else
+		*value = config;
+
+	free(str);
+
+	return err;
+}
+
+int write_device_ccc(bdaddr_t *local, bdaddr_t *peer, uint16_t handle,
+							uint16_t value)
+{
+	char filename[PATH_MAX + 1], addr[18], key[23], config[5];
+
+	create_filename(filename, PATH_MAX, local, "ccc");
+
+	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+	ba2str(peer, addr);
+
+	snprintf(key, sizeof(key), "%17s#%04X", addr, handle);
+	snprintf(config, sizeof(config), "%04X", value);
+
+	return textfile_put(filename, key, config);
+}
diff --git a/src/storage.h b/src/storage.h
index dbe717f..1cb3637 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -83,6 +83,10 @@ char *read_device_characteristics(const bdaddr_t *sba, const bdaddr_t *dba,
 int write_device_attribute(const bdaddr_t *sba, const bdaddr_t *dba,
                                         uint16_t handle, const char *chars);
 int read_device_attributes(const bdaddr_t *sba, textfile_cb func, void *data);
+int read_device_ccc(bdaddr_t *local, bdaddr_t *peer, uint16_t handle,
+							uint16_t *value);
+int write_device_ccc(bdaddr_t *local, bdaddr_t *peer, uint16_t handle,
+							uint16_t value);
 
 #define PNP_UUID		"00001200-0000-1000-8000-00805f9b34fb"
 
-- 
1.7.7


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

* [PATCH BlueZ 2/7] Remove CCC for read by group
  2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 1/7] Add storage functions to deal with CCC Claudio Takahasi
@ 2011-10-13 14:43 ` Claudio Takahasi
  2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 3/7] Remove CCC for read by type Claudio Takahasi
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Claudio Takahasi @ 2011-10-13 14:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Read by group is used to discover all primary services. Client
Characteristic Configuration is not applied to service definition.
---
 src/attrib-server.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index 9ba5f74..25fe8b3 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -314,7 +314,6 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
 
 	last_handle = end;
 	for (l = database, groups = NULL, cur = NULL; l; l = l->next) {
-		struct attribute *client_attr;
 
 		a = l->data;
 
@@ -344,10 +343,6 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
 		status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
 								a->read_reqs);
 
-		client_attr = client_cfg_attribute(channel, a, a->data, a->len);
-		if (client_attr)
-			a = client_attr;
-
 		if (status == 0x00 && a->read_cb)
 			status = a->read_cb(a, a->cb_user_data);
 
-- 
1.7.7


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

* [PATCH BlueZ 3/7] Remove CCC for read by type
  2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 1/7] Add storage functions to deal with CCC Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 2/7] Remove CCC for read by group Claudio Takahasi
@ 2011-10-13 14:43 ` Claudio Takahasi
  2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 4/7] Add CCC persistence in attrib server Claudio Takahasi
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Claudio Takahasi @ 2011-10-13 14:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Read by type is never used to iterate through attributes related to
Client Characteristic Configuration or any other descriptor.
---
 src/attrib-server.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index 25fe8b3..b66943e 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -415,7 +415,6 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
 					ATT_ECODE_INVALID_HANDLE, pdu, len);
 
 	for (l = database, length = 0, types = NULL; l; l = l->next) {
-		struct attribute *client_attr;
 
 		a = l->data;
 
@@ -431,10 +430,6 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
 		status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
 								a->read_reqs);
 
-		client_attr = client_cfg_attribute(channel, a, a->data, a->len);
-		if (client_attr)
-			a = client_attr;
-
 		if (status == 0x00 && a->read_cb)
 			status = a->read_cb(a, a->cb_user_data);
 
-- 
1.7.7


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

* [PATCH BlueZ 4/7] Add CCC persistence in attrib server
  2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
                   ` (2 preceding siblings ...)
  2011-10-13 14:43 ` [PATCH BlueZ 3/7] Remove CCC for read by type Claudio Takahasi
@ 2011-10-13 14:43 ` Claudio Takahasi
  2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 5/7] Remove notification and indication from server Claudio Takahasi
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Claudio Takahasi @ 2011-10-13 14:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds storage of the Client Characteristic Configuration
attribute value. CCC is readable with no authentication/authorization.
Writable with authentication and authorization defined by a higher layer
specification or implementation specific.
---
 src/attrib-server.c |  161 +++++++++++++--------------------------------------
 1 files changed, 41 insertions(+), 120 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index b66943e..fbd9944 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -44,6 +44,7 @@
 #include "hcid.h"
 #include "att.h"
 #include "gattrib.h"
+#include "storage.h"
 
 #include "attrib-server.h"
 
@@ -52,7 +53,6 @@ static GSList *database = NULL;
 struct gatt_channel {
 	bdaddr_t src;
 	bdaddr_t dst;
-	GSList *configs;
 	GSList *notify;
 	GSList *indicate;
 	GAttrib *attrib;
@@ -87,6 +87,10 @@ static bt_uuid_t snd_uuid = {
 			.type = BT_UUID16,
 			.value.u16 = GATT_SND_SVC_UUID
 };
+static bt_uuid_t ccc_uuid = {
+			.type = BT_UUID16,
+			.value.u16 = GATT_CLIENT_CHARAC_CFG_UUID
+};
 
 static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t end)
 {
@@ -193,99 +197,6 @@ static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
 	return 0;
 }
 
-static uint8_t client_set_notifications(struct attribute *attr,
-							gpointer user_data)
-{
-	struct gatt_channel *channel = user_data;
-	struct attribute *last_chr_val = NULL;
-	uint16_t cfg_val;
-	uint8_t props;
-	bt_uuid_t uuid;
-	GSList *l;
-
-	cfg_val = att_get_u16(attr->data);
-
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	for (l = database, props = 0; l != NULL; l = l->next) {
-		struct attribute *a = l->data;
-		static uint16_t handle = 0;
-
-		if (a->handle >= attr->handle)
-			break;
-
-		if (bt_uuid_cmp(&a->uuid, &uuid) == 0) {
-			props = att_get_u8(&a->data[0]);
-			handle = att_get_u16(&a->data[1]);
-			continue;
-		}
-
-		if (handle && a->handle == handle)
-			last_chr_val = a;
-	}
-
-	if (last_chr_val == NULL)
-		return 0;
-
-	if ((cfg_val & 0x0001) && !(props & ATT_CHAR_PROPER_NOTIFY))
-		return ATT_ECODE_WRITE_NOT_PERM;
-
-	if ((cfg_val & 0x0002) && !(props & ATT_CHAR_PROPER_INDICATE))
-		return ATT_ECODE_WRITE_NOT_PERM;
-
-	if (cfg_val & 0x0001)
-		channel->notify = g_slist_append(channel->notify, last_chr_val);
-	else
-		channel->notify = g_slist_remove(channel->notify, last_chr_val);
-
-	if (cfg_val & 0x0002)
-		channel->indicate = g_slist_append(channel->indicate,
-								last_chr_val);
-	else
-		channel->indicate = g_slist_remove(channel->indicate,
-								last_chr_val);
-
-	return 0;
-}
-
-static struct attribute *client_cfg_attribute(struct gatt_channel *channel,
-						struct attribute *orig_attr,
-						const uint8_t *value, int vlen)
-{
-	guint handle = orig_attr->handle;
-	bt_uuid_t uuid;
-	GSList *l;
-
-	bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
-	if (bt_uuid_cmp(&orig_attr->uuid, &uuid) != 0)
-		return NULL;
-
-	/* Value is unchanged, not need to create a private copy yet */
-	if (vlen == orig_attr->len && memcmp(orig_attr->data, value, vlen) == 0)
-		return orig_attr;
-
-	l = g_slist_find_custom(channel->configs, GUINT_TO_POINTER(handle),
-								handle_cmp);
-	if (!l) {
-		struct attribute *a;
-
-		/* Create a private copy of the Client Characteristic
-		 * Configuration attribute */
-		a = g_new0(struct attribute, 1);
-		*a = *orig_attr;
-		a->len = vlen;
-		a->data = g_memdup(value, vlen);
-		a->write_cb = client_set_notifications;
-		a->cb_user_data = channel;
-
-		channel->configs = g_slist_insert_sorted(channel->configs, a,
-								attribute_cmp);
-
-		return a;
-	}
-
-	return l->data;
-}
-
 static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
 						uint16_t end, bt_uuid_t *uuid,
 						uint8_t *pdu, int len)
@@ -644,9 +555,10 @@ static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
 static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 							uint8_t *pdu, int len)
 {
-	struct attribute *a, *client_attr;
+	struct attribute *a;
 	uint8_t status;
 	GSList *l;
+	uint16_t cccval;
 	guint h = handle;
 
 	l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
@@ -656,11 +568,16 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 
 	a = l->data;
 
-	status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
+	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) == 0 &&
+		read_device_ccc(&channel->src, &channel->dst,
+					handle, &cccval) == 0) {
+		uint8_t config[2];
 
-	client_attr = client_cfg_attribute(channel, a, a->data, a->len);
-	if (client_attr)
-		a = client_attr;
+		att_put_u16(cccval, config);
+		return enc_read_resp(config, sizeof(config), pdu, len);
+	}
+
+	status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
 
 	if (status == 0x00 && a->read_cb)
 		status = a->read_cb(a, a->cb_user_data);
@@ -675,9 +592,10 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
 					uint16_t offset, uint8_t *pdu, int len)
 {
-	struct attribute *a, *client_attr;
+	struct attribute *a;
 	uint8_t status;
 	GSList *l;
+	uint16_t cccval;
 	guint h = handle;
 
 	l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
@@ -691,11 +609,17 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
 		return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle,
 					ATT_ECODE_INVALID_OFFSET, pdu, len);
 
-	status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
+	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) == 0 &&
+		read_device_ccc(&channel->src, &channel->dst,
+					handle, &cccval) == 0) {
+		uint8_t config[2];
 
-	client_attr = client_cfg_attribute(channel, a, a->data, a->len);
-	if (client_attr)
-		a = client_attr;
+		att_put_u16(cccval, config);
+		return enc_read_blob_resp(config, sizeof(config), offset,
+								pdu, len);
+	}
+
+	status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
 
 	if (status == 0x00 && a->read_cb)
 		status = a->read_cb(a, a->cb_user_data);
@@ -711,7 +635,7 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
 						const uint8_t *value, int vlen,
 						uint8_t *pdu, int len)
 {
-	struct attribute *a, *client_attr;
+	struct attribute *a;
 	uint8_t status;
 	GSList *l;
 	guint h = handle;
@@ -728,22 +652,20 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
 		return enc_error_resp(ATT_OP_WRITE_REQ, handle, status, pdu,
 									len);
 
-	client_attr = client_cfg_attribute(channel, a, value, vlen);
-	if (client_attr)
-		a = client_attr;
-	else
-		attrib_db_update(a->handle, NULL, value, vlen, &a);
+	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) != 0) {
 
-	if (a->write_cb) {
-		status = a->write_cb(a, a->cb_user_data);
-		if (status)
-			return enc_error_resp(ATT_OP_WRITE_REQ, handle, status,
-								pdu, len);
-	}
+		attrib_db_update(handle, NULL, value, vlen, NULL);
 
-	DBG("Notifications: %d, indications: %d",
-					g_slist_length(channel->notify),
-					g_slist_length(channel->indicate));
+		if (a->write_cb) {
+			status = a->write_cb(a, a->cb_user_data);
+			if (status)
+				return enc_error_resp(ATT_OP_WRITE_REQ, handle,
+							status, pdu, len);
+		}
+	} else {
+		uint16_t cccval = att_get_u16(value);
+		write_device_ccc(&channel->src, &channel->dst, handle, cccval);
+	}
 
 	return enc_write_resp(pdu, len);
 }
@@ -777,7 +699,6 @@ static void channel_free(struct gatt_channel *channel)
 {
 	g_slist_free(channel->notify);
 	g_slist_free(channel->indicate);
-	g_slist_free_full(channel->configs, attrib_free);
 	g_attrib_unref(channel->attrib);
 
 	g_free(channel);
-- 
1.7.7


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

* [PATCH BlueZ 5/7] Remove notification and indication from server
  2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
                   ` (3 preceding siblings ...)
  2011-10-13 14:43 ` [PATCH BlueZ 4/7] Add CCC persistence in attrib server Claudio Takahasi
@ 2011-10-13 14:43 ` Claudio Takahasi
  2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 6/7] Remove CCC entries when device is removed Claudio Takahasi
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Claudio Takahasi @ 2011-10-13 14:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Upper layer should handle notification and indication since there are
profiles especific constraints including timeouts and attributes values
that should read only before sending it.
---
 src/attrib-server.c |   46 ----------------------------------------------
 1 files changed, 0 insertions(+), 46 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index fbd9944..523a835 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -53,8 +53,6 @@ static GSList *database = NULL;
 struct gatt_channel {
 	bdaddr_t src;
 	bdaddr_t dst;
-	GSList *notify;
-	GSList *indicate;
 	GAttrib *attrib;
 	guint mtu;
 	gboolean le;
@@ -697,8 +695,6 @@ static void attrib_free(void *data)
 
 static void channel_free(struct gatt_channel *channel)
 {
-	g_slist_free(channel->notify);
-	g_slist_free(channel->indicate);
 	g_attrib_unref(channel->attrib);
 
 	g_free(channel);
@@ -937,46 +933,6 @@ static void confirm_event(GIOChannel *io, void *user_data)
 	return;
 }
 
-static void attrib_notify_clients(struct attribute *attr)
-{
-	guint handle = attr->handle;
-	GSList *l;
-
-	for (l = clients; l; l = l->next) {
-		struct gatt_channel *channel = l->data;
-
-		/* Notification */
-		if (g_slist_find_custom(channel->notify,
-					GUINT_TO_POINTER(handle), handle_cmp)) {
-			uint8_t pdu[ATT_MAX_MTU];
-			uint16_t len;
-
-			len = enc_notification(attr->handle, attr->data,
-						attr->len, pdu, channel->mtu);
-			if (len == 0)
-				continue;
-
-			g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
-							NULL, NULL, NULL);
-		}
-
-		/* Indication */
-		if (g_slist_find_custom(channel->indicate,
-					GUINT_TO_POINTER(handle), handle_cmp)) {
-			uint8_t pdu[ATT_MAX_MTU];
-			uint16_t len;
-
-			len = enc_indication(attr->handle, attr->data,
-						attr->len, pdu, channel->mtu);
-			if (len == 0)
-				return;
-
-			g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
-							NULL, NULL, NULL);
-		}
-	}
-}
-
 static gboolean register_core_services(void)
 {
 	uint8_t atval[256];
@@ -1237,8 +1193,6 @@ int attrib_db_update(uint16_t handle, bt_uuid_t *uuid, const uint8_t *value,
 	if (attr)
 		*attr = a;
 
-	attrib_notify_clients(a);
-
 	return 0;
 }
 
-- 
1.7.7


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

* [PATCH BlueZ 6/7] Remove CCC entries when device is removed
  2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
                   ` (4 preceding siblings ...)
  2011-10-13 14:43 ` [PATCH BlueZ 5/7] Remove notification and indication from server Claudio Takahasi
@ 2011-10-13 14:43 ` Claudio Takahasi
  2011-11-07 14:00   ` [PATCH BlueZ v2 " Claudio Takahasi
  2011-10-13 14:43 ` [PATCH BlueZ 7/7] Add generic function to delete by pattern Claudio Takahasi
  2011-11-07 13:59 ` [PATCH BlueZ v2 0/7] CCC persistence Claudio Takahasi
  7 siblings, 1 reply; 17+ messages in thread
From: Claudio Takahasi @ 2011-10-13 14:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

---
 src/storage.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/src/storage.c b/src/storage.c
index 082a046..1bd86d0 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -1194,6 +1194,22 @@ int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba)
 
 	g_slist_free_full(match.keys, g_free);
 
+	/* Deleting all CCC values of a given address */
+	memset(&match, 0, sizeof(match));
+	match.pattern = address;
+
+	create_filename(filename, PATH_MAX, sba, "ccc");
+	err = textfile_foreach(filename, filter_keys, &match);
+	if (err < 0)
+		return err;
+
+	for (l = match.keys; l; l = l->next) {
+		const char *key = l->data;
+		textfile_del(filename, key);
+	}
+
+	g_slist_free_full(match.keys, g_free);
+
 	return 0;
 }
 
-- 
1.7.7


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

* [PATCH BlueZ 7/7] Add generic function to delete by pattern
  2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
                   ` (5 preceding siblings ...)
  2011-10-13 14:43 ` [PATCH BlueZ 6/7] Remove CCC entries when device is removed Claudio Takahasi
@ 2011-10-13 14:43 ` Claudio Takahasi
  2011-11-07 14:00   ` [PATCH BlueZ v2 " Claudio Takahasi
  2011-11-07 13:59 ` [PATCH BlueZ v2 0/7] CCC persistence Claudio Takahasi
  7 siblings, 1 reply; 17+ messages in thread
From: Claudio Takahasi @ 2011-10-13 14:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Remove entries of textfile if the key has the prefix defined by the
pattern string.
---
 src/storage.c |   66 ++++++++++++++++++++------------------------------------
 1 files changed, 24 insertions(+), 42 deletions(-)

diff --git a/src/storage.c b/src/storage.c
index 1bd86d0..3aa1b7f 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -1139,76 +1139,58 @@ int write_device_services(const bdaddr_t *sba, const bdaddr_t *dba,
 static void filter_keys(char *key, char *value, void *data)
 {
 	struct match *match = data;
-	const char *address = match->pattern;
 
-	/* Each key contains: MAC#handle*/
-	if (strncasecmp(key, address, 17) == 0)
+	if (strncasecmp(key, match->pattern, strlen(match->pattern)) == 0)
 		match->keys = g_slist_append(match->keys, g_strdup(key));
 }
 
-int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba)
+static void delete_by_pattern(const char *filename, char *pattern)
 {
-	GSList *l;
 	struct match match;
-	char filename[PATH_MAX + 1], address[18];
+	GSList *l;
 	int err;
 
-	create_filename(filename, PATH_MAX, sba, "primary");
-
-	memset(address, 0, sizeof(address));
-	ba2str(dba, address);
-
-	err = textfile_del(filename, address);
-	if (err < 0)
-		return err;
-
-	/* Deleting all characteristics of a given address */
 	memset(&match, 0, sizeof(match));
-	match.pattern = address;
+	match.pattern = pattern;
 
-	create_filename(filename, PATH_MAX, sba, "characteristic");
 	err = textfile_foreach(filename, filter_keys, &match);
 	if (err < 0)
-		return err;
+		goto done;
 
 	for (l = match.keys; l; l = l->next) {
 		const char *key = l->data;
 		textfile_del(filename, key);
 	}
 
+done:
 	g_slist_free_full(match.keys, g_free);
+}
 
-	/* Deleting all attributes values of a given address */
-	memset(&match, 0, sizeof(match));
-	match.pattern = address;
+int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba)
+{
+	char filename[PATH_MAX + 1], address[18];
+	int err;
 
-	create_filename(filename, PATH_MAX, sba, "attributes");
-	err = textfile_foreach(filename, filter_keys, &match);
+	create_filename(filename, PATH_MAX, sba, "primary");
+
+	memset(address, 0, sizeof(address));
+	ba2str(dba, address);
+
+	err = textfile_del(filename, address);
 	if (err < 0)
 		return err;
 
-	for (l = match.keys; l; l = l->next) {
-		const char *key = l->data;
-		textfile_del(filename, key);
-	}
+	/* Deleting all characteristics of a given address */
+	create_filename(filename, PATH_MAX, sba, "characteristic");
+	delete_by_pattern(filename, address);
 
-	g_slist_free_full(match.keys, g_free);
+	/* Deleting all attributes values of a given address */
+	create_filename(filename, PATH_MAX, sba, "attributes");
+	delete_by_pattern(filename, address);
 
 	/* Deleting all CCC values of a given address */
-	memset(&match, 0, sizeof(match));
-	match.pattern = address;
-
 	create_filename(filename, PATH_MAX, sba, "ccc");
-	err = textfile_foreach(filename, filter_keys, &match);
-	if (err < 0)
-		return err;
-
-	for (l = match.keys; l; l = l->next) {
-		const char *key = l->data;
-		textfile_del(filename, key);
-	}
-
-	g_slist_free_full(match.keys, g_free);
+	delete_by_pattern(filename, address);
 
 	return 0;
 }
-- 
1.7.7


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

* [PATCH BlueZ v2 0/7] CCC persistence
  2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
                   ` (6 preceding siblings ...)
  2011-10-13 14:43 ` [PATCH BlueZ 7/7] Add generic function to delete by pattern Claudio Takahasi
@ 2011-11-07 13:59 ` Claudio Takahasi
  2011-11-14 18:54   ` Johan Hedberg
  7 siblings, 1 reply; 17+ messages in thread
From: Claudio Takahasi @ 2011-11-07 13:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Changes from previous version: rebase only

The following patches implement the storage of the Client Characteristic
Configuration: controls notification & indication.

Bonding verification is coming in the next patch series.

Based on the requirements of the available profiles attrib server will
require some changes. The future plan is to move attribute values to
plugins (eg: time) and keep only the attribute declaration in the attrib
server.

Claudio Takahasi (6):
  Remove CCC for read by group
  Remove CCC for read by type
  Add CCC persistence in attrib server
  Remove notification and indication from server
  Remove CCC entries when device is removed
  Add generic function to delete by pattern

Vinicius Costa Gomes (1):
  Add storage functions to deal with CCC

 src/attrib-server.c |  217 ++++++++++-----------------------------------------
 src/storage.c       |  100 +++++++++++++++++-------
 src/storage.h       |    4 +
 3 files changed, 116 insertions(+), 205 deletions(-)

-- 
1.7.7.2


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

* [PATCH BlueZ v2 1/7] Add storage functions to deal with CCC
  2011-10-13 14:43 ` [PATCH BlueZ 1/7] Add storage functions to deal with CCC Claudio Takahasi
@ 2011-11-07 13:59   ` Claudio Takahasi
  0 siblings, 0 replies; 17+ messages in thread
From: Claudio Takahasi @ 2011-11-07 13:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

From: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>

CCC (Client Characteristic Configuration) is used to allow configuration
whether to send updates about an characteristic value.
---
 src/storage.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 src/storage.h |    4 ++++
 2 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/src/storage.c b/src/storage.c
index cc0213b..babe7c7 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -1263,3 +1263,47 @@ int read_device_attributes(const bdaddr_t *sba, textfile_cb func, void *data)
 
 	return textfile_foreach(filename, func, data);
 }
+
+int read_device_ccc(bdaddr_t *local, bdaddr_t *peer, uint16_t handle,
+							uint16_t *value)
+{
+	char filename[PATH_MAX + 1], addr[18], key[23];
+	char *str;
+	unsigned int config;
+	int err = 0;
+
+	create_filename(filename, PATH_MAX, local, "ccc");
+
+	ba2str(peer, addr);
+	snprintf(key, sizeof(key), "%17s#%04X", addr, handle);
+
+	str = textfile_caseget(filename, key);
+	if (str == NULL)
+		return -ENOENT;
+
+	if (sscanf(str, "%04X", &config) != 1)
+		err = -ENOENT;
+	else
+		*value = config;
+
+	free(str);
+
+	return err;
+}
+
+int write_device_ccc(bdaddr_t *local, bdaddr_t *peer, uint16_t handle,
+							uint16_t value)
+{
+	char filename[PATH_MAX + 1], addr[18], key[23], config[5];
+
+	create_filename(filename, PATH_MAX, local, "ccc");
+
+	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+	ba2str(peer, addr);
+
+	snprintf(key, sizeof(key), "%17s#%04X", addr, handle);
+	snprintf(config, sizeof(config), "%04X", value);
+
+	return textfile_put(filename, key, config);
+}
diff --git a/src/storage.h b/src/storage.h
index dbe717f..1cb3637 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -83,6 +83,10 @@ char *read_device_characteristics(const bdaddr_t *sba, const bdaddr_t *dba,
 int write_device_attribute(const bdaddr_t *sba, const bdaddr_t *dba,
                                         uint16_t handle, const char *chars);
 int read_device_attributes(const bdaddr_t *sba, textfile_cb func, void *data);
+int read_device_ccc(bdaddr_t *local, bdaddr_t *peer, uint16_t handle,
+							uint16_t *value);
+int write_device_ccc(bdaddr_t *local, bdaddr_t *peer, uint16_t handle,
+							uint16_t value);
 
 #define PNP_UUID		"00001200-0000-1000-8000-00805f9b34fb"
 
-- 
1.7.7.2


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

* [PATCH BlueZ v2 2/7] Remove CCC for read by group
  2011-10-13 14:43 ` [PATCH BlueZ 2/7] Remove CCC for read by group Claudio Takahasi
@ 2011-11-07 13:59   ` Claudio Takahasi
  0 siblings, 0 replies; 17+ messages in thread
From: Claudio Takahasi @ 2011-11-07 13:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Read by group is used to discover all primary services. Client
Characteristic Configuration is not applied to service definition.
---
 src/attrib-server.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index e412061..a996884 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -314,7 +314,6 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
 
 	last_handle = end;
 	for (l = database, groups = NULL, cur = NULL; l; l = l->next) {
-		struct attribute *client_attr;
 
 		a = l->data;
 
@@ -344,10 +343,6 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
 		status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
 								a->read_reqs);
 
-		client_attr = client_cfg_attribute(channel, a, a->data, a->len);
-		if (client_attr)
-			a = client_attr;
-
 		if (status == 0x00 && a->read_cb)
 			status = a->read_cb(a, a->cb_user_data);
 
-- 
1.7.7.2


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

* [PATCH BlueZ v2 3/7] Remove CCC for read by type
  2011-10-13 14:43 ` [PATCH BlueZ 3/7] Remove CCC for read by type Claudio Takahasi
@ 2011-11-07 13:59   ` Claudio Takahasi
  0 siblings, 0 replies; 17+ messages in thread
From: Claudio Takahasi @ 2011-11-07 13:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Read by type is never used to iterate through attributes related to
Client Characteristic Configuration or any other descriptor.
---
 src/attrib-server.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index a996884..b2e218c 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -415,7 +415,6 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
 					ATT_ECODE_INVALID_HANDLE, pdu, len);
 
 	for (l = database, length = 0, types = NULL; l; l = l->next) {
-		struct attribute *client_attr;
 
 		a = l->data;
 
@@ -431,10 +430,6 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
 		status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
 								a->read_reqs);
 
-		client_attr = client_cfg_attribute(channel, a, a->data, a->len);
-		if (client_attr)
-			a = client_attr;
-
 		if (status == 0x00 && a->read_cb)
 			status = a->read_cb(a, a->cb_user_data);
 
-- 
1.7.7.2


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

* [PATCH BlueZ v2 4/7] Add CCC persistence in attrib server
  2011-10-13 14:43 ` [PATCH BlueZ 4/7] Add CCC persistence in attrib server Claudio Takahasi
@ 2011-11-07 13:59   ` Claudio Takahasi
  0 siblings, 0 replies; 17+ messages in thread
From: Claudio Takahasi @ 2011-11-07 13:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds storage of the Client Characteristic Configuration
attribute value. CCC is readable with no authentication/authorization.
Writable with authentication and authorization defined by a higher layer
specification or implementation specific.
---
 src/attrib-server.c |  161 +++++++++++++--------------------------------------
 1 files changed, 41 insertions(+), 120 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index b2e218c..5bb0dab 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -44,6 +44,7 @@
 #include "hcid.h"
 #include "att.h"
 #include "gattrib.h"
+#include "storage.h"
 
 #include "attrib-server.h"
 
@@ -52,7 +53,6 @@ static GSList *database = NULL;
 struct gatt_channel {
 	bdaddr_t src;
 	bdaddr_t dst;
-	GSList *configs;
 	GSList *notify;
 	GSList *indicate;
 	GAttrib *attrib;
@@ -87,6 +87,10 @@ static bt_uuid_t snd_uuid = {
 			.type = BT_UUID16,
 			.value.u16 = GATT_SND_SVC_UUID
 };
+static bt_uuid_t ccc_uuid = {
+			.type = BT_UUID16,
+			.value.u16 = GATT_CLIENT_CHARAC_CFG_UUID
+};
 
 static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t end)
 {
@@ -193,99 +197,6 @@ static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
 	return 0;
 }
 
-static uint8_t client_set_notifications(struct attribute *attr,
-							gpointer user_data)
-{
-	struct gatt_channel *channel = user_data;
-	struct attribute *last_chr_val = NULL;
-	uint16_t cfg_val;
-	uint8_t props;
-	bt_uuid_t uuid;
-	GSList *l;
-
-	cfg_val = att_get_u16(attr->data);
-
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	for (l = database, props = 0; l != NULL; l = l->next) {
-		struct attribute *a = l->data;
-		static uint16_t handle = 0;
-
-		if (a->handle >= attr->handle)
-			break;
-
-		if (bt_uuid_cmp(&a->uuid, &uuid) == 0) {
-			props = att_get_u8(&a->data[0]);
-			handle = att_get_u16(&a->data[1]);
-			continue;
-		}
-
-		if (handle && a->handle == handle)
-			last_chr_val = a;
-	}
-
-	if (last_chr_val == NULL)
-		return 0;
-
-	if ((cfg_val & 0x0001) && !(props & ATT_CHAR_PROPER_NOTIFY))
-		return ATT_ECODE_WRITE_NOT_PERM;
-
-	if ((cfg_val & 0x0002) && !(props & ATT_CHAR_PROPER_INDICATE))
-		return ATT_ECODE_WRITE_NOT_PERM;
-
-	if (cfg_val & 0x0001)
-		channel->notify = g_slist_append(channel->notify, last_chr_val);
-	else
-		channel->notify = g_slist_remove(channel->notify, last_chr_val);
-
-	if (cfg_val & 0x0002)
-		channel->indicate = g_slist_append(channel->indicate,
-								last_chr_val);
-	else
-		channel->indicate = g_slist_remove(channel->indicate,
-								last_chr_val);
-
-	return 0;
-}
-
-static struct attribute *client_cfg_attribute(struct gatt_channel *channel,
-						struct attribute *orig_attr,
-						const uint8_t *value, int vlen)
-{
-	guint handle = orig_attr->handle;
-	bt_uuid_t uuid;
-	GSList *l;
-
-	bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
-	if (bt_uuid_cmp(&orig_attr->uuid, &uuid) != 0)
-		return NULL;
-
-	/* Value is unchanged, not need to create a private copy yet */
-	if (vlen == orig_attr->len && memcmp(orig_attr->data, value, vlen) == 0)
-		return orig_attr;
-
-	l = g_slist_find_custom(channel->configs, GUINT_TO_POINTER(handle),
-								handle_cmp);
-	if (!l) {
-		struct attribute *a;
-
-		/* Create a private copy of the Client Characteristic
-		 * Configuration attribute */
-		a = g_new0(struct attribute, 1);
-		*a = *orig_attr;
-		a->len = vlen;
-		a->data = g_memdup(value, vlen);
-		a->write_cb = client_set_notifications;
-		a->cb_user_data = channel;
-
-		channel->configs = g_slist_insert_sorted(channel->configs, a,
-								attribute_cmp);
-
-		return a;
-	}
-
-	return l->data;
-}
-
 static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
 						uint16_t end, bt_uuid_t *uuid,
 						uint8_t *pdu, int len)
@@ -644,9 +555,10 @@ static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
 static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 							uint8_t *pdu, int len)
 {
-	struct attribute *a, *client_attr;
+	struct attribute *a;
 	uint8_t status;
 	GSList *l;
+	uint16_t cccval;
 	guint h = handle;
 
 	l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
@@ -656,11 +568,16 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 
 	a = l->data;
 
-	status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
+	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) == 0 &&
+		read_device_ccc(&channel->src, &channel->dst,
+					handle, &cccval) == 0) {
+		uint8_t config[2];
 
-	client_attr = client_cfg_attribute(channel, a, a->data, a->len);
-	if (client_attr)
-		a = client_attr;
+		att_put_u16(cccval, config);
+		return enc_read_resp(config, sizeof(config), pdu, len);
+	}
+
+	status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
 
 	if (status == 0x00 && a->read_cb)
 		status = a->read_cb(a, a->cb_user_data);
@@ -675,9 +592,10 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
 static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
 					uint16_t offset, uint8_t *pdu, int len)
 {
-	struct attribute *a, *client_attr;
+	struct attribute *a;
 	uint8_t status;
 	GSList *l;
+	uint16_t cccval;
 	guint h = handle;
 
 	l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
@@ -691,11 +609,17 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
 		return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle,
 					ATT_ECODE_INVALID_OFFSET, pdu, len);
 
-	status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
+	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) == 0 &&
+		read_device_ccc(&channel->src, &channel->dst,
+					handle, &cccval) == 0) {
+		uint8_t config[2];
 
-	client_attr = client_cfg_attribute(channel, a, a->data, a->len);
-	if (client_attr)
-		a = client_attr;
+		att_put_u16(cccval, config);
+		return enc_read_blob_resp(config, sizeof(config), offset,
+								pdu, len);
+	}
+
+	status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
 
 	if (status == 0x00 && a->read_cb)
 		status = a->read_cb(a, a->cb_user_data);
@@ -711,7 +635,7 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
 						const uint8_t *value, int vlen,
 						uint8_t *pdu, int len)
 {
-	struct attribute *a, *client_attr;
+	struct attribute *a;
 	uint8_t status;
 	GSList *l;
 	guint h = handle;
@@ -728,22 +652,20 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
 		return enc_error_resp(ATT_OP_WRITE_REQ, handle, status, pdu,
 									len);
 
-	client_attr = client_cfg_attribute(channel, a, value, vlen);
-	if (client_attr)
-		a = client_attr;
-	else
-		attrib_db_update(a->handle, NULL, value, vlen, &a);
+	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) != 0) {
 
-	if (a->write_cb) {
-		status = a->write_cb(a, a->cb_user_data);
-		if (status)
-			return enc_error_resp(ATT_OP_WRITE_REQ, handle, status,
-								pdu, len);
-	}
+		attrib_db_update(handle, NULL, value, vlen, NULL);
 
-	DBG("Notifications: %d, indications: %d",
-					g_slist_length(channel->notify),
-					g_slist_length(channel->indicate));
+		if (a->write_cb) {
+			status = a->write_cb(a, a->cb_user_data);
+			if (status)
+				return enc_error_resp(ATT_OP_WRITE_REQ, handle,
+							status, pdu, len);
+		}
+	} else {
+		uint16_t cccval = att_get_u16(value);
+		write_device_ccc(&channel->src, &channel->dst, handle, cccval);
+	}
 
 	return enc_write_resp(pdu, len);
 }
@@ -777,7 +699,6 @@ static void channel_free(struct gatt_channel *channel)
 {
 	g_slist_free(channel->notify);
 	g_slist_free(channel->indicate);
-	g_slist_free_full(channel->configs, attrib_free);
 	g_attrib_unref(channel->attrib);
 
 	g_free(channel);
-- 
1.7.7.2


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

* [PATCH BlueZ v2 5/7] Remove notification and indication from server
  2011-10-13 14:43 ` [PATCH BlueZ 5/7] Remove notification and indication from server Claudio Takahasi
@ 2011-11-07 13:59   ` Claudio Takahasi
  0 siblings, 0 replies; 17+ messages in thread
From: Claudio Takahasi @ 2011-11-07 13:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Upper layer should handle notification and indication since there are
profiles especific constraints including timeouts and attributes values
that should read only before sending it.
---
 src/attrib-server.c |   46 ----------------------------------------------
 1 files changed, 0 insertions(+), 46 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index 5bb0dab..b84b01d 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -53,8 +53,6 @@ static GSList *database = NULL;
 struct gatt_channel {
 	bdaddr_t src;
 	bdaddr_t dst;
-	GSList *notify;
-	GSList *indicate;
 	GAttrib *attrib;
 	guint mtu;
 	gboolean le;
@@ -697,8 +695,6 @@ static void attrib_free(void *data)
 
 static void channel_free(struct gatt_channel *channel)
 {
-	g_slist_free(channel->notify);
-	g_slist_free(channel->indicate);
 	g_attrib_unref(channel->attrib);
 
 	g_free(channel);
@@ -937,46 +933,6 @@ static void confirm_event(GIOChannel *io, void *user_data)
 	return;
 }
 
-static void attrib_notify_clients(struct attribute *attr)
-{
-	guint handle = attr->handle;
-	GSList *l;
-
-	for (l = clients; l; l = l->next) {
-		struct gatt_channel *channel = l->data;
-
-		/* Notification */
-		if (g_slist_find_custom(channel->notify,
-					GUINT_TO_POINTER(handle), handle_cmp)) {
-			uint8_t pdu[ATT_MAX_MTU];
-			uint16_t len;
-
-			len = enc_notification(attr->handle, attr->data,
-						attr->len, pdu, channel->mtu);
-			if (len == 0)
-				continue;
-
-			g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
-							NULL, NULL, NULL);
-		}
-
-		/* Indication */
-		if (g_slist_find_custom(channel->indicate,
-					GUINT_TO_POINTER(handle), handle_cmp)) {
-			uint8_t pdu[ATT_MAX_MTU];
-			uint16_t len;
-
-			len = enc_indication(attr->handle, attr->data,
-						attr->len, pdu, channel->mtu);
-			if (len == 0)
-				return;
-
-			g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
-							NULL, NULL, NULL);
-		}
-	}
-}
-
 static gboolean register_core_services(void)
 {
 	uint8_t atval[256];
@@ -1237,8 +1193,6 @@ int attrib_db_update(uint16_t handle, bt_uuid_t *uuid, const uint8_t *value,
 	if (attr)
 		*attr = a;
 
-	attrib_notify_clients(a);
-
 	return 0;
 }
 
-- 
1.7.7.2


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

* [PATCH BlueZ v2 6/7] Remove CCC entries when device is removed
  2011-10-13 14:43 ` [PATCH BlueZ 6/7] Remove CCC entries when device is removed Claudio Takahasi
@ 2011-11-07 14:00   ` Claudio Takahasi
  0 siblings, 0 replies; 17+ messages in thread
From: Claudio Takahasi @ 2011-11-07 14:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

---
 src/storage.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/src/storage.c b/src/storage.c
index babe7c7..e001987 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -1195,6 +1195,22 @@ int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba)
 
 	g_slist_free_full(match.keys, g_free);
 
+	/* Deleting all CCC values of a given address */
+	memset(&match, 0, sizeof(match));
+	match.pattern = address;
+
+	create_filename(filename, PATH_MAX, sba, "ccc");
+	err = textfile_foreach(filename, filter_keys, &match);
+	if (err < 0)
+		return err;
+
+	for (l = match.keys; l; l = l->next) {
+		const char *key = l->data;
+		textfile_del(filename, key);
+	}
+
+	g_slist_free_full(match.keys, g_free);
+
 	return 0;
 }
 
-- 
1.7.7.2


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

* [PATCH BlueZ v2 7/7] Add generic function to delete by pattern
  2011-10-13 14:43 ` [PATCH BlueZ 7/7] Add generic function to delete by pattern Claudio Takahasi
@ 2011-11-07 14:00   ` Claudio Takahasi
  0 siblings, 0 replies; 17+ messages in thread
From: Claudio Takahasi @ 2011-11-07 14:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Remove entries of textfile if the key has the prefix defined by the
pattern string.
---
 src/storage.c |   66 ++++++++++++++++++++------------------------------------
 1 files changed, 24 insertions(+), 42 deletions(-)

diff --git a/src/storage.c b/src/storage.c
index e001987..7471b0f 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -1140,76 +1140,58 @@ int write_device_services(const bdaddr_t *sba, const bdaddr_t *dba,
 static void filter_keys(char *key, char *value, void *data)
 {
 	struct match *match = data;
-	const char *address = match->pattern;
 
-	/* Each key contains: MAC#handle*/
-	if (strncasecmp(key, address, 17) == 0)
+	if (strncasecmp(key, match->pattern, strlen(match->pattern)) == 0)
 		match->keys = g_slist_append(match->keys, g_strdup(key));
 }
 
-int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba)
+static void delete_by_pattern(const char *filename, char *pattern)
 {
-	GSList *l;
 	struct match match;
-	char filename[PATH_MAX + 1], address[18];
+	GSList *l;
 	int err;
 
-	create_filename(filename, PATH_MAX, sba, "primary");
-
-	memset(address, 0, sizeof(address));
-	ba2str(dba, address);
-
-	err = textfile_del(filename, address);
-	if (err < 0)
-		return err;
-
-	/* Deleting all characteristics of a given address */
 	memset(&match, 0, sizeof(match));
-	match.pattern = address;
+	match.pattern = pattern;
 
-	create_filename(filename, PATH_MAX, sba, "characteristic");
 	err = textfile_foreach(filename, filter_keys, &match);
 	if (err < 0)
-		return err;
+		goto done;
 
 	for (l = match.keys; l; l = l->next) {
 		const char *key = l->data;
 		textfile_del(filename, key);
 	}
 
+done:
 	g_slist_free_full(match.keys, g_free);
+}
 
-	/* Deleting all attributes values of a given address */
-	memset(&match, 0, sizeof(match));
-	match.pattern = address;
+int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba)
+{
+	char filename[PATH_MAX + 1], address[18];
+	int err;
 
-	create_filename(filename, PATH_MAX, sba, "attributes");
-	err = textfile_foreach(filename, filter_keys, &match);
+	create_filename(filename, PATH_MAX, sba, "primary");
+
+	memset(address, 0, sizeof(address));
+	ba2str(dba, address);
+
+	err = textfile_del(filename, address);
 	if (err < 0)
 		return err;
 
-	for (l = match.keys; l; l = l->next) {
-		const char *key = l->data;
-		textfile_del(filename, key);
-	}
+	/* Deleting all characteristics of a given address */
+	create_filename(filename, PATH_MAX, sba, "characteristic");
+	delete_by_pattern(filename, address);
 
-	g_slist_free_full(match.keys, g_free);
+	/* Deleting all attributes values of a given address */
+	create_filename(filename, PATH_MAX, sba, "attributes");
+	delete_by_pattern(filename, address);
 
 	/* Deleting all CCC values of a given address */
-	memset(&match, 0, sizeof(match));
-	match.pattern = address;
-
 	create_filename(filename, PATH_MAX, sba, "ccc");
-	err = textfile_foreach(filename, filter_keys, &match);
-	if (err < 0)
-		return err;
-
-	for (l = match.keys; l; l = l->next) {
-		const char *key = l->data;
-		textfile_del(filename, key);
-	}
-
-	g_slist_free_full(match.keys, g_free);
+	delete_by_pattern(filename, address);
 
 	return 0;
 }
-- 
1.7.7.2


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

* Re: [PATCH BlueZ v2 0/7] CCC persistence
  2011-11-07 13:59 ` [PATCH BlueZ v2 0/7] CCC persistence Claudio Takahasi
@ 2011-11-14 18:54   ` Johan Hedberg
  0 siblings, 0 replies; 17+ messages in thread
From: Johan Hedberg @ 2011-11-14 18:54 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth

HI Claudio,

On Mon, Nov 07, 2011, Claudio Takahasi wrote:
> Changes from previous version: rebase only
> 
> The following patches implement the storage of the Client Characteristic
> Configuration: controls notification & indication.
> 
> Bonding verification is coming in the next patch series.
> 
> Based on the requirements of the available profiles attrib server will
> require some changes. The future plan is to move attribute values to
> plugins (eg: time) and keep only the attribute declaration in the attrib
> server.
> 
> Claudio Takahasi (6):
>   Remove CCC for read by group
>   Remove CCC for read by type
>   Add CCC persistence in attrib server
>   Remove notification and indication from server
>   Remove CCC entries when device is removed
>   Add generic function to delete by pattern
> 
> Vinicius Costa Gomes (1):
>   Add storage functions to deal with CCC
> 
>  src/attrib-server.c |  217 ++++++++++-----------------------------------------
>  src/storage.c       |  100 +++++++++++++++++-------
>  src/storage.h       |    4 +
>  3 files changed, 116 insertions(+), 205 deletions(-)

Applied. Thanks.

Johan

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

end of thread, other threads:[~2011-11-14 18:54 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-13 14:43 [PATCH BlueZ 0/7] CCC persistence Claudio Takahasi
2011-10-13 14:43 ` [PATCH BlueZ 1/7] Add storage functions to deal with CCC Claudio Takahasi
2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
2011-10-13 14:43 ` [PATCH BlueZ 2/7] Remove CCC for read by group Claudio Takahasi
2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
2011-10-13 14:43 ` [PATCH BlueZ 3/7] Remove CCC for read by type Claudio Takahasi
2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
2011-10-13 14:43 ` [PATCH BlueZ 4/7] Add CCC persistence in attrib server Claudio Takahasi
2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
2011-10-13 14:43 ` [PATCH BlueZ 5/7] Remove notification and indication from server Claudio Takahasi
2011-11-07 13:59   ` [PATCH BlueZ v2 " Claudio Takahasi
2011-10-13 14:43 ` [PATCH BlueZ 6/7] Remove CCC entries when device is removed Claudio Takahasi
2011-11-07 14:00   ` [PATCH BlueZ v2 " Claudio Takahasi
2011-10-13 14:43 ` [PATCH BlueZ 7/7] Add generic function to delete by pattern Claudio Takahasi
2011-11-07 14:00   ` [PATCH BlueZ v2 " Claudio Takahasi
2011-11-07 13:59 ` [PATCH BlueZ v2 0/7] CCC persistence Claudio Takahasi
2011-11-14 18:54   ` Johan Hedberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox