All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv4 00/15] Refactor reading attributes type
@ 2014-05-15 13:02 Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 01/15] shared/gatt: Extend gatt_db_read function Marcin Kraglak
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

Changes in v4:
 - fixed function names and coding style issues
 - Added macros with state of reading operation: READ_INIT,
        READ_PENDING and READ_DONE and READ_FAILED

Jakub Tyszkowski (1):
  android/gatt: Add find by type and value handler

Marcin Kraglak (14):
  shared/gatt: Extend gatt_db_read function
  android/gatt: Refactor ATT read operations
  shared/gatt: Modify gatt_db_read_by_type to return handles only
  android/gatt: Change handling read_by_type requests
  shared/gatt: Remove unused structure
  shared/gatt: Modify gatt_db_find_information to return list of handles
  shared/gatt: Add helper function to get attribute type
  android/gatt: Change handling of find_information requests
  shared/gatt: Remove unused structure
  shared/gatt: Add function to get end group handle
  shared/gatt: Retun list of handles in gatt_db_read_by_group_type
  android/gatt: Change handling of read_by_group_type requests
  shared/gatt: Remove unused structure
  shared/gatt: Make 'find_by_type_value' callback compatible

 android/gatt.c       | 667 +++++++++++++++++++++++++++++++++++++++------------
 src/shared/gatt-db.c | 135 ++++++-----
 src/shared/gatt-db.h |  38 +--
 3 files changed, 591 insertions(+), 249 deletions(-)

-- 
1.9.0


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

* [PATCHv4 01/15] shared/gatt: Extend gatt_db_read function
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 02/15] android/gatt: Refactor ATT read operations Marcin Kraglak
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

If value exists in database, return pointer to it instead of returning
false. It is needed because some attributes don't have read_cb callback
and their value can be read directly from database.
---
 android/gatt.c       |  3 ++-
 src/shared/gatt-db.c | 24 +++++++++++++++++++++---
 src/shared/gatt-db.h |  3 ++-
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index ebda377..67a1330 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -4116,7 +4116,8 @@ static uint8_t read_request(const uint8_t *cmd, uint16_t cmd_len,
 		return ATT_ECODE_REQ_NOT_SUPP;
 	}
 
-	if (!gatt_db_read(gatt_db, handle, offset, cmd[0], &dev->bdaddr))
+	if (!gatt_db_read(gatt_db, handle, offset, cmd[0], &dev->bdaddr, NULL,
+									NULL))
 		return ATT_ECODE_UNLIKELY;
 
 	return 0;
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index ebfd586..41db7d2 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -684,12 +684,16 @@ static bool find_service_for_handle(const void *data, const void *user_data)
 }
 
 bool gatt_db_read(struct gatt_db *db, uint16_t handle, uint16_t offset,
-				uint8_t att_opcode, bdaddr_t *bdaddr)
+				uint8_t att_opcode, bdaddr_t *bdaddr,
+				uint8_t **value, int *length)
 {
 	struct gatt_db_service *service;
 	uint16_t service_handle;
 	struct gatt_db_attribute *a;
 
+	if (!value || !length)
+		return false;
+
 	service = queue_find(db->services, find_service_for_handle,
 						INT_TO_PTR(handle));
 	if (!service)
@@ -698,10 +702,24 @@ bool gatt_db_read(struct gatt_db *db, uint16_t handle, uint16_t offset,
 	service_handle = service->attributes[0]->handle;
 
 	a = service->attributes[handle - service_handle];
-	if (!a || !a->read_func)
+	if (!a)
 		return false;
 
-	a->read_func(handle, offset, att_opcode, bdaddr, a->user_data);
+	/*
+	 * We call callback, and set length to -1, to notify user that callback
+	 * has been called. Otherwise we set length to value length in database.
+	 */
+	if (a->read_func) {
+		*value = NULL;
+		*length = -1;
+		a->read_func(handle, offset, att_opcode, bdaddr, a->user_data);
+	} else {
+		if (offset > a->value_len)
+			return false;
+
+		*value = &a->value[offset];
+		*length = a->value_len - offset;
+	}
 
 	return true;
 }
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index f704b8e..62bac41 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -106,7 +106,8 @@ void gatt_db_find_information(struct gatt_db *db, uint16_t start_handle,
 							struct queue *queue);
 
 bool gatt_db_read(struct gatt_db *db, uint16_t handle, uint16_t offset,
-					uint8_t att_opcode, bdaddr_t *bdaddr);
+					uint8_t att_opcode, bdaddr_t *bdaddr,
+					uint8_t **value, int *length);
 
 bool gatt_db_write(struct gatt_db *db, uint16_t handle, uint16_t offset,
 					const uint8_t *value, size_t len,
-- 
1.9.0


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

* [PATCHv4 02/15] android/gatt: Refactor ATT read operations
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 01/15] shared/gatt: Extend gatt_db_read function Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 03/15] shared/gatt: Modify gatt_db_read_by_type to return handles only Marcin Kraglak
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

This changes device info and gap services callbacks to use response queue.
It will allow them work with plain read and read by type as well.

This starts transition to single response data queue, which should be
filled by various read type functions and processed in one place. This
will unify the way that responses are send, regardless of data source
(value taken directly from database, returned by read callback or sent
from upper layers asynchronously).

We will also introduce 'getter' type functions, using handles to
retrieve data from database. This will make various read and find
operations return handles instead of their own custom structures,
different for every operation performed.
---
 android/gatt.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 208 insertions(+), 34 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 67a1330..74b321d 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -156,6 +156,8 @@ struct gatt_device {
 
 	int ref;
 	int conn_cnt;
+
+	struct queue *pending_requests;
 };
 
 struct app_connection {
@@ -753,6 +755,25 @@ static void disconnect_notify_by_device(void *data, void *user_data)
 		send_app_connect_notify(conn, GATT_FAILURE);
 }
 
+#define READ_INIT -3
+#define READ_PENDING -2
+#define READ_FAILED -1
+
+struct pending_request {
+	uint16_t handle;
+	int length;
+	uint8_t *value;
+	uint16_t offset;
+};
+
+static void destroy_pending_request(void *data)
+{
+	struct pending_request *entry = data;
+
+	free(entry->value);
+	free(entry);
+}
+
 static void destroy_device(void *data)
 {
 	struct gatt_device *dev = data;
@@ -761,6 +782,7 @@ static void destroy_device(void *data)
 		return;
 
 	queue_destroy(dev->services, destroy_service);
+	queue_destroy(dev->pending_requests, destroy_pending_request);
 
 	free(dev);
 }
@@ -1143,6 +1165,13 @@ static struct gatt_device *create_device(const bdaddr_t *addr)
 		return NULL;
 	}
 
+	dev->pending_requests = queue_new();
+	if (!dev->pending_requests) {
+		error("gatt: Failed to allocate memory for client");
+		destroy_device(dev);
+		return NULL;
+	}
+
 	if (!queue_push_head(gatt_devices, dev)) {
 		error("gatt: Cannot push device to queue");
 		destroy_device(dev);
@@ -3387,6 +3416,118 @@ failed:
 				HAL_OP_GATT_SERVER_ADD_INC_SERVICE, status);
 }
 
+static void send_dev_pending_response(struct gatt_device *device,
+								uint8_t opcode)
+{
+	uint8_t rsp[ATT_DEFAULT_LE_MTU];
+	struct pending_request *val;
+	uint16_t len = 0;
+	uint8_t error = 0;
+
+	switch (opcode) {
+	case ATT_OP_READ_BLOB_REQ:
+		val = queue_pop_head(device->pending_requests);
+		if (!val || val->length == READ_FAILED) {
+			error = ATT_ECODE_ATTR_NOT_FOUND;
+			goto done;
+		}
+
+		len = enc_read_blob_resp(val->value, val->length, val->offset,
+							rsp, sizeof(rsp));
+		destroy_pending_request(val);
+		break;
+	case ATT_OP_READ_REQ:
+		val = queue_pop_head(device->pending_requests);
+		if (!val || val->length == READ_FAILED) {
+			error = ATT_ECODE_ATTR_NOT_FOUND;
+			goto done;
+		}
+
+		len = enc_read_resp(val->value, val->length, rsp, sizeof(rsp));
+		destroy_pending_request(val);
+		break;
+	default:
+		break;
+	}
+
+done:
+	if (!len)
+		len = enc_error_resp(opcode, 0x0000, error, rsp,
+							ATT_DEFAULT_LE_MTU);
+
+	g_attrib_send(device->attrib, 0, rsp, len, NULL, NULL, NULL);
+
+	queue_remove_all(device->pending_requests, NULL, NULL,
+						destroy_pending_request);
+}
+
+struct request_processing_data {
+	uint8_t opcode;
+	struct gatt_device *device;
+};
+
+static bool match_pending_dev_request(const void *data, const void *user_data)
+{
+	const struct pending_request *pending_request = data;
+
+	return pending_request->length == READ_PENDING;
+}
+
+static bool match_dev_request_by_handle(const void *data, const void *user_data)
+{
+	const struct pending_request *handle_data = data;
+	uint16_t handle = PTR_TO_UINT(user_data);
+
+	return handle_data->handle == handle;
+}
+
+static void read_requested_attributes(void *data, void *user_data)
+{
+	struct pending_request *resp_data = data;
+	struct request_processing_data *process_data = user_data;
+	uint8_t *value;
+	int value_len;
+
+	if (!gatt_db_read(gatt_db, resp_data->handle,
+						resp_data->offset,
+						process_data->opcode,
+						&process_data->device->bdaddr,
+						&value, &value_len))
+		resp_data->length = READ_FAILED;
+
+	/* We have value here already if no callback will be called */
+	if (value_len > -1) {
+		resp_data->value = malloc0(value_len);
+		if (!resp_data->value) {
+			/* If data cannot be copied, act like when read fails */
+			resp_data->length = READ_FAILED;
+			return;
+		}
+
+		memcpy(resp_data->value, value, value_len);
+		resp_data->length = value_len;
+	} else {
+		resp_data->length = READ_PENDING;
+	}
+}
+
+static void process_dev_pending_requests(struct gatt_device *device,
+							uint8_t att_opcode)
+{
+	struct request_processing_data process_data;
+
+	process_data.device = device;
+	process_data.opcode = att_opcode;
+
+	/* Process pending requests and prepare response */
+	queue_foreach(device->pending_requests, read_requested_attributes,
+								&process_data);
+
+	if (!queue_find(device->pending_requests,
+					match_pending_dev_request, NULL))
+		send_dev_pending_response(device, att_opcode);
+}
+
 static void send_gatt_response(uint8_t opcode, uint16_t handle,
 					uint16_t offset, uint8_t status,
 					uint16_t len, const uint8_t *data,
@@ -4096,7 +4237,8 @@ static uint8_t read_request(const uint8_t *cmd, uint16_t cmd_len,
 {
 	uint16_t handle;
 	uint16_t len;
-	uint16_t offset = 0;
+	uint16_t offset;
+	struct pending_request *data;
 
 	DBG("");
 
@@ -4110,15 +4252,26 @@ static uint8_t read_request(const uint8_t *cmd, uint16_t cmd_len,
 		len = dec_read_req(cmd, cmd_len, &handle);
 		if (!len)
 			return ATT_ECODE_INVALID_PDU;
+		offset = 0;
 		break;
 	default:
 		error("gatt: Unexpected read type 0x%02x", cmd[0]);
 		return ATT_ECODE_REQ_NOT_SUPP;
 	}
 
-	if (!gatt_db_read(gatt_db, handle, offset, cmd[0], &dev->bdaddr, NULL,
-									NULL))
-		return ATT_ECODE_UNLIKELY;
+	data = new0(struct pending_request, 1);
+	if (!data)
+		return ATT_ECODE_INSUFF_RESOURCES;
+
+	data->offset = offset;
+	data->handle = handle;
+	data->length = READ_INIT;
+	if (!queue_push_tail(dev->pending_requests, data)) {
+		free(data);
+		return ATT_ECODE_INSUFF_RESOURCES;
+	}
+
+	process_dev_pending_requests(dev, cmd[0]);
 
 	return 0;
 }
@@ -4319,9 +4472,6 @@ static void att_handler(const uint8_t *ipdu, uint16_t len, gpointer user_data)
 	case ATT_OP_READ_REQ:
 	case ATT_OP_READ_BLOB_REQ:
 		status = read_request(ipdu, len, dev);
-		if (!status)
-			/* Response will be sent in callback */
-			return;
 		break;
 	case ATT_OP_MTU_REQ:
 		status = mtu_att_handle(ipdu, len, opdu, sizeof(opdu), dev,
@@ -4364,7 +4514,8 @@ done:
 		length = enc_error_resp(ipdu[0], 0x0000, status, opdu,
 							ATT_DEFAULT_LE_MTU);
 
-	g_attrib_send(dev->attrib, 0, opdu, length, NULL, NULL, NULL);
+	if (length)
+		g_attrib_send(dev->attrib, 0, opdu, length, NULL, NULL, NULL);
 }
 
 static void create_listen_connections(void *data, void *user_data)
@@ -4465,8 +4616,7 @@ static struct gap_srvc_handles gap_srvc_data;
 static void gap_read_cb(uint16_t handle, uint16_t offset, uint8_t att_opcode,
 					bdaddr_t *bdaddr, void *user_data)
 {
-	uint8_t pdu[ATT_DEFAULT_LE_MTU];
-	uint16_t len;
+	struct pending_request *entry;
 	struct gatt_device *dev;
 
 	DBG("");
@@ -4477,33 +4627,46 @@ static void gap_read_cb(uint16_t handle, uint16_t offset, uint8_t att_opcode,
 		return;
 	}
 
+	entry = queue_find(dev->pending_requests, match_dev_request_by_handle,
+							UINT_TO_PTR(handle));
+	if (!entry)
+		return;
+
 	if (handle == gap_srvc_data.dev_name) {
 		const char *name = bt_get_adapter_name();
 
-		len = enc_read_resp((uint8_t *)name, strlen(name),
-							pdu, sizeof(pdu));
-		goto done;
-	}
+		entry->value = malloc0(strlen(name));
+		if (!entry->value) {
+			queue_remove(dev->pending_requests, entry);
+			free(entry);
+			return;
+		}
 
-	if (handle == gap_srvc_data.appear) {
-		uint8_t val[2];
-		put_le16(APPEARANCE_GENERIC_PHONE, val);
-		len = enc_read_resp(val, sizeof(val), pdu, sizeof(pdu));
-		goto done;
-	}
+		entry->length = strlen(name);
+		memcpy(entry->value, bt_get_adapter_name(), entry->length);
+	} else if (handle == gap_srvc_data.appear) {
+		entry->value = malloc0(2);
+		if (!entry->value) {
+			queue_remove(dev->pending_requests, entry);
+			free(entry);
+			return;
+		}
 
-	if (handle == gap_srvc_data.priv) {
-		uint8_t val = PERIPHERAL_PRIVACY_DISABLE;
-		len = enc_read_resp(&val, sizeof(val), pdu, sizeof(pdu));
-		goto done;
-	}
+		put_le16(APPEARANCE_GENERIC_PHONE, entry->value);
+		entry->length = sizeof(uint8_t) * 2;
+	} else if (handle == gap_srvc_data.priv) {
+		entry->value = malloc0(1);
+		if (!entry->value) {
+			queue_remove(dev->pending_requests, entry);
+			free(entry);
+			return;
+		}
 
-	error("gatt: Unknown handle 0x%02x", handle);
-	len = enc_error_resp(ATT_OP_READ_REQ, handle,
-					ATT_ECODE_UNLIKELY, pdu, sizeof(pdu));
+		*entry->value = PERIPHERAL_PRIVACY_DISABLE;
+		entry->length = sizeof(uint8_t);
+	}
 
-done:
-	g_attrib_send(dev->attrib, 0, pdu, len, NULL, NULL, NULL);
+	entry->offset = offset;
 }
 
 static void register_gap_service(void)
@@ -4567,10 +4730,9 @@ static void device_info_read_cb(uint16_t handle, uint16_t offset,
 					uint8_t att_opcode, bdaddr_t *bdaddr,
 					void *user_data)
 {
-	uint8_t pdu[ATT_DEFAULT_LE_MTU];
+	struct pending_request *entry;
 	struct gatt_device *dev;
 	char *buf = user_data;
-	uint16_t len;
 
 	dev = find_device_by_addr(bdaddr);
 	if (!dev) {
@@ -4578,9 +4740,21 @@ static void device_info_read_cb(uint16_t handle, uint16_t offset,
 		return;
 	}
 
-	len = enc_read_resp((uint8_t *) buf, strlen(buf), pdu, sizeof(pdu));
+	entry = queue_find(dev->pending_requests, match_dev_request_by_handle,
+							UINT_TO_PTR(handle));
+	if (!entry)
+		return;
+
+	entry->value = malloc0(strlen(buf));
+	if (!entry->value) {
+		queue_remove(dev->pending_requests, entry);
+		free(entry);
+		return;
+	}
 
-	g_attrib_send(dev->attrib, 0, pdu, len, NULL, NULL, NULL);
+	entry->length = strlen(buf);
+	memcpy(entry->value, buf, entry->length);
+	entry->offset = offset;
 }
 
 static void register_device_info_service(void)
-- 
1.9.0


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

* [PATCHv4 03/15] shared/gatt: Modify gatt_db_read_by_type to return handles only
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 01/15] shared/gatt: Extend gatt_db_read function Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 02/15] android/gatt: Refactor ATT read operations Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 04/15] android/gatt: Change handling read_by_type requests Marcin Kraglak
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

For now read_by_type function will just return handles of found attributes.
---
 src/shared/gatt-db.c | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 41db7d2..d5fa17d 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -564,7 +564,6 @@ static void read_by_type(void *data, void *user_data)
 	struct read_by_type_data *search_data = user_data;
 	struct gatt_db_service *service = data;
 	struct gatt_db_attribute *attribute;
-	struct gatt_db_handle_value *value;
 	int i;
 
 	if (!service->active)
@@ -584,18 +583,8 @@ static void read_by_type(void *data, void *user_data)
 		if (bt_uuid_cmp(&search_data->uuid, &attribute->uuid))
 			continue;
 
-		value = malloc0(sizeof(struct gatt_db_handle_value) +
-							attribute->value_len);
-		if (!value)
-			return;
-
-		value->handle = attribute->handle;
-		value->length = attribute->value_len;
-		if (attribute->value_len)
-			memcpy(value->value, attribute->value, value->length);
-
-		if (!queue_push_tail(search_data->queue, value))
-			free(value);
+		queue_push_tail(search_data->queue,
+						UINT_TO_PTR(attribute->handle));
 	}
 }
 
-- 
1.9.0


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

* [PATCHv4 04/15] android/gatt: Change handling read_by_type requests
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (2 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 03/15] shared/gatt: Modify gatt_db_read_by_type to return handles only Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 05/15] shared/gatt: Remove unused structure Marcin Kraglak
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

For now list of handles is returned from database so we should read each
attribute's value. It uses new way of handling requests from remote
devices.
---
 android/gatt.c | 99 ++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 65 insertions(+), 34 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 74b321d..9b28b16 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -3425,6 +3425,52 @@ static void send_dev_pending_response(struct gatt_device *device,
 	uint8_t error = 0;
 
 	switch (opcode) {
+	case ATT_OP_READ_BY_TYPE_REQ: {
+		struct att_data_list *adl;
+		int iterator = 0;
+		int length;
+		struct queue *temp;
+
+
+		temp = queue_new();
+		if (!temp)
+			goto done;
+
+		val = queue_pop_head(device->pending_requests);
+		if (!val) {
+			queue_destroy(temp, NULL);
+			error = ATT_ECODE_ATTR_NOT_FOUND;
+			goto done;
+		}
+
+		length = val->length;
+
+		while (val && val->length == length) {
+			queue_push_tail(temp, val);
+			val = queue_pop_head(device->pending_requests);
+		}
+
+		adl = att_data_list_alloc(queue_length(temp), sizeof(uint16_t) +
+									length);
+
+		val = queue_pop_head(temp);
+		while (val) {
+			uint8_t *value = adl->data[iterator++];
+
+			put_le16(val->handle, value);
+			memcpy(&value[2], val->value, val->length);
+
+			destroy_pending_request(val);
+			val = queue_pop_head(temp);
+		}
+
+		len = enc_read_by_type_resp(adl, rsp, sizeof(rsp));
+
+		att_data_list_free(adl);
+		queue_destroy(temp, destroy_pending_request);
+
+		break;
+	}
 	case ATT_OP_READ_BLOB_REQ:
 		val = queue_pop_head(device->pending_requests);
 		if (!val || val->length == READ_FAILED) {
@@ -4090,19 +4136,6 @@ static void copy_to_att_list(void *data, void *user_data)
 	memcpy(&value[4], group->value, group->len);
 }
 
-static void copy_to_att_list_type(void *data, void *user_data)
-{
-	struct copy_att_list_data *l = user_data;
-	struct gatt_db_handle_value *hdl_val = data;
-	uint8_t *value;
-
-	value = l->adl->data[l->iterator++];
-
-	put_le16(hdl_val->handle, value);
-
-	memcpy(&value[2], hdl_val->value, hdl_val->length);
-}
-
 static void copy_to_att_list_info(void *data, void *user_data)
 {
 	struct copy_att_list_data *l = user_data;
@@ -4180,16 +4213,12 @@ static uint8_t read_by_group_type(const uint8_t *cmd, uint16_t cmd_len,
 }
 
 static uint8_t read_by_type(const uint8_t *cmd, uint16_t cmd_len,
-						uint8_t *rsp, size_t rsp_size,
-						uint16_t *length)
+						struct gatt_device *device)
 {
 	uint16_t start, end;
 	uint16_t len;
 	bt_uuid_t uuid;
 	struct queue *q;
-	struct att_data_list *adl;
-	struct copy_att_list_data l;
-	struct gatt_db_handle_value *h;
 
 	DBG("");
 
@@ -4208,26 +4237,28 @@ static uint8_t read_by_type(const uint8_t *cmd, uint16_t cmd_len,
 		return ATT_ECODE_ATTR_NOT_FOUND;
 	}
 
-	len = queue_length(q);
-	h = queue_peek_tail(q);
+	while (queue_peek_head(q)) {
+		struct pending_request *data;
+		uint16_t handle = PTR_TO_UINT(queue_pop_head(q));
 
-	/* Element here is handle + value*/
-	adl = att_data_list_alloc(len, sizeof(uint16_t) + h->length);
-	if (!adl) {
-		queue_destroy(q, free);
-		return ATT_ECODE_INSUFF_RESOURCES;
-	}
+		data = new0(struct pending_request, 1);
+		if (!data) {
+			queue_destroy(q, NULL);
+			return ATT_ECODE_INSUFF_RESOURCES;
+		}
 
-	l.iterator = 0;
-	l.adl = adl;
+		data->handle = handle;
+		queue_push_tail(device->pending_requests, data);
+	}
 
-	queue_foreach(q, copy_to_att_list_type, &l);
+	queue_destroy(q, NULL);
 
-	len = enc_read_by_type_resp(adl, rsp, rsp_size);
-	*length = len;
+	process_dev_pending_requests(device, ATT_OP_READ_BY_TYPE_REQ);
 
-	att_data_list_free(adl);
-	queue_destroy(q, free);
+	/* We send immediate if no data left to be filled by async callbacks */
+	if (!queue_find(device->pending_requests, match_pending_dev_request,
+									NULL))
+		send_dev_pending_response(device, ATT_OP_READ_BY_TYPE_REQ);
 
 	return 0;
 }
@@ -4467,7 +4498,7 @@ static void att_handler(const uint8_t *ipdu, uint16_t len, gpointer user_data)
 								&length);
 		break;
 	case ATT_OP_READ_BY_TYPE_REQ:
-		status = read_by_type(ipdu, len, opdu, sizeof(opdu), &length);
+		status = read_by_type(ipdu, len, dev);
 		break;
 	case ATT_OP_READ_REQ:
 	case ATT_OP_READ_BLOB_REQ:
-- 
1.9.0


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

* [PATCHv4 05/15] shared/gatt: Remove unused structure
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (3 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 04/15] android/gatt: Change handling read_by_type requests Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 06/15] shared/gatt: Modify gatt_db_find_information to return list of handles Marcin Kraglak
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

This structure is no longer used in gatt_db implementation.
---
 src/shared/gatt-db.h | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 62bac41..4f8b1df 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -85,12 +85,6 @@ void gatt_db_find_by_type_value(struct gatt_db *db, uint16_t start_handle,
 							uint16_t length,
 							struct queue *queue);
 
-struct gatt_db_handle_value {
-	uint16_t handle;
-	uint16_t length;
-	uint8_t value[0];
-};
-
 void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle,
 							uint16_t end_handle,
 							const bt_uuid_t type,
-- 
1.9.0


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

* [PATCHv4 06/15] shared/gatt: Modify gatt_db_find_information to return list of handles
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (4 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 05/15] shared/gatt: Remove unused structure Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 07/15] shared/gatt: Add helper function to get attribute type Marcin Kraglak
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

For now this function will return list of found handles.
---
 src/shared/gatt-db.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index d5fa17d..cb63754 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -614,7 +614,6 @@ static void find_information(void *data, void *user_data)
 	struct find_information_data *search_data = user_data;
 	struct gatt_db_service *service = data;
 	struct gatt_db_attribute *attribute;
-	struct gatt_db_find_information *value;
 	int i;
 
 	if (!service->active)
@@ -636,14 +635,8 @@ static void find_information(void *data, void *user_data)
 		if (attribute->handle > search_data->end_handle)
 			return;
 
-		value = new0(struct gatt_db_find_information, 1);
-		if (!value)
-			return;
-
-		value->handle = attribute->handle;
-		value->uuid = attribute->uuid;
-		if (!queue_push_tail(search_data->queue, value))
-			free(value);
+		queue_push_tail(search_data->queue,
+						UINT_TO_PTR(attribute->handle));
 	}
 }
 
-- 
1.9.0


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

* [PATCHv4 07/15] shared/gatt: Add helper function to get attribute type
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (5 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 06/15] shared/gatt: Modify gatt_db_find_information to return list of handles Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 08/15] android/gatt: Change handling of find_information requests Marcin Kraglak
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

This will return uuid with attribute type or NULL if attribute was not
found in database.
---
 src/shared/gatt-db.c | 21 +++++++++++++++++++++
 src/shared/gatt-db.h |  3 +++
 2 files changed, 24 insertions(+)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index cb63754..0cca86f 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -730,3 +730,24 @@ bool gatt_db_write(struct gatt_db *db, uint16_t handle, uint16_t offset,
 
 	return true;
 }
+
+const bt_uuid_t *gatt_db_get_attribute_type(struct gatt_db *db,
+							uint16_t handle)
+{
+	struct gatt_db_service *service;
+	struct gatt_db_attribute *attribute;
+	uint16_t service_handle;
+
+	service = queue_find(db->services, find_service_for_handle,
+						INT_TO_PTR(handle));
+	if (!service)
+		return NULL;
+
+	service_handle = service->attributes[0]->handle;
+
+	attribute = service->attributes[handle - service_handle];
+	if (!attribute)
+		return NULL;
+
+	return &attribute->uuid;
+}
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 4f8b1df..02d564b 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -106,3 +106,6 @@ bool gatt_db_read(struct gatt_db *db, uint16_t handle, uint16_t offset,
 bool gatt_db_write(struct gatt_db *db, uint16_t handle, uint16_t offset,
 					const uint8_t *value, size_t len,
 					uint8_t att_opcode, bdaddr_t *bdaddr);
+
+const bt_uuid_t *gatt_db_get_attribute_type(struct gatt_db *db,
+							uint16_t handle);
-- 
1.9.0


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

* [PATCHv4 08/15] android/gatt: Change handling of find_information requests
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (6 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 07/15] shared/gatt: Add helper function to get attribute type Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 09/15] shared/gatt: Remove unused structure Marcin Kraglak
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

This uses new version of gatt_db_find_information function which
returns list of handles.
---
 android/gatt.c | 66 ++++++++++++++++++++--------------------------------------
 1 file changed, 22 insertions(+), 44 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 9b28b16..83c2485 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -4136,31 +4136,6 @@ static void copy_to_att_list(void *data, void *user_data)
 	memcpy(&value[4], group->value, group->len);
 }
 
-static void copy_to_att_list_info(void *data, void *user_data)
-{
-	struct copy_att_list_data *l = user_data;
-	struct gatt_db_find_information *info = data;
-	uint8_t *value;
-
-	value = l->adl->data[l->iterator++];
-
-	put_le16(info->handle, value);
-
-	switch (info->uuid.type) {
-	case BT_UUID16:
-		memcpy(&value[2], &info->uuid.value.u16,
-						bt_uuid_len(&info->uuid));
-		break;
-	case BT_UUID128:
-		memcpy(&value[2], &info->uuid.value.u128,
-						bt_uuid_len(&info->uuid));
-		break;
-	default:
-		error("gatt: Unexpected UUID type");
-		break;
-	}
-}
-
 static uint8_t read_by_group_type(const uint8_t *cmd, uint16_t cmd_len,
 						uint8_t *rsp, size_t rsp_size,
 						uint16_t *length)
@@ -4357,12 +4332,9 @@ static uint8_t find_info_handle(const uint8_t *cmd, uint16_t cmd_len,
 						uint16_t *length)
 {
 	struct queue *q;
-	struct gatt_db_find_information *last_element;
-	struct copy_att_list_data l;
 	struct att_data_list *adl;
+	int iterator = 0;
 	uint16_t start, end;
-	uint16_t num;
-	uint8_t format;
 	uint16_t len;
 
 	DBG("");
@@ -4383,29 +4355,35 @@ static uint8_t find_info_handle(const uint8_t *cmd, uint16_t cmd_len,
 	}
 
 	len = queue_length(q);
+	adl = att_data_list_alloc(len, 2 * sizeof(uint16_t));
+	if (!adl) {
+		queue_destroy(q, NULL);
+		return ATT_ECODE_INSUFF_RESOURCES;
+	}
+
+	while (queue_peek_head(q)) {
+		uint8_t *value;
+		const bt_uuid_t *type;
+		uint16_t handle = PTR_TO_UINT(queue_pop_head(q));
 
-	last_element = queue_peek_head(q);
+		type = gatt_db_get_attribute_type(gatt_db, handle);
+		if (!type)
+			break;
+
+		value = adl->data[iterator++];
+
+		put_le16(handle, value);
+		memcpy(&value[2], &type->value.u16, bt_uuid_len(type));
 
-	if (last_element->uuid.type == BT_UUID16) {
-		num = sizeof(uint16_t);
-		format = ATT_FIND_INFO_RESP_FMT_16BIT;
-	} else {
-		num = sizeof(uint128_t);
-		format = ATT_FIND_INFO_RESP_FMT_128BIT;
 	}
 
-	adl = att_data_list_alloc(len, num + sizeof(uint16_t));
 	if (!adl) {
-		queue_destroy(q, free);
+		queue_destroy(q, NULL);
 		return ATT_ECODE_INSUFF_RESOURCES;
 	}
 
-	l.iterator = 0;
-	l.adl = adl;
-
-	queue_foreach(q, copy_to_att_list_info, &l);
-
-	len = enc_find_info_resp(format, adl, rsp, rsp_size);
+	len = enc_find_info_resp(ATT_FIND_INFO_RESP_FMT_16BIT, adl, rsp,
+								rsp_size);
 	if (!len)
 		return ATT_ECODE_UNLIKELY;
 
-- 
1.9.0


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

* [PATCHv4 09/15] shared/gatt: Remove unused structure
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (7 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 08/15] android/gatt: Change handling of find_information requests Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 10/15] shared/gatt: Add function to get end group handle Marcin Kraglak
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

This structure is no longer used.
---
 src/shared/gatt-db.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 02d564b..24bce21 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -90,11 +90,6 @@ void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle,
 							const bt_uuid_t type,
 							struct queue *queue);
 
-struct gatt_db_find_information {
-	uint16_t handle;
-	bt_uuid_t uuid;
-};
-
 void gatt_db_find_information(struct gatt_db *db, uint16_t start_handle,
 							uint16_t end_handle,
 							struct queue *queue);
-- 
1.9.0


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

* [PATCHv4 10/15] shared/gatt: Add function to get end group handle
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (8 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 09/15] shared/gatt: Remove unused structure Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 11/15] shared/gatt: Retun list of handles in gatt_db_read_by_group_type Marcin Kraglak
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

This function will return end group handle or zero if attribute
not found.
---
 src/shared/gatt-db.c | 12 ++++++++++++
 src/shared/gatt-db.h |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 0cca86f..2ac9f2d 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -751,3 +751,15 @@ const bt_uuid_t *gatt_db_get_attribute_type(struct gatt_db *db,
 
 	return &attribute->uuid;
 }
+
+uint16_t gatt_db_get_end_handle(struct gatt_db *db, uint16_t handle)
+{
+	struct gatt_db_service *service;
+
+	service = queue_find(db->services, find_service_for_handle,
+						INT_TO_PTR(handle));
+	if (!service)
+		return 0;
+
+	return service->attributes[0]->handle + service->num_handles - 1;
+}
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 24bce21..1a18fb7 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -104,3 +104,5 @@ bool gatt_db_write(struct gatt_db *db, uint16_t handle, uint16_t offset,
 
 const bt_uuid_t *gatt_db_get_attribute_type(struct gatt_db *db,
 							uint16_t handle);
+
+uint16_t gatt_db_get_end_handle(struct gatt_db *db, uint16_t handle);
-- 
1.9.0


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

* [PATCHv4 11/15] shared/gatt: Retun list of handles in gatt_db_read_by_group_type
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (9 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 10/15] shared/gatt: Add function to get end group handle Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 12/15] android/gatt: Change handling of read_by_group_type requests Marcin Kraglak
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

Fom now return list of handles instead of specific data.
---
 src/shared/gatt-db.c | 16 ++--------------
 src/shared/gatt-db.h |  1 -
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 2ac9f2d..25661c7 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -423,7 +423,6 @@ static void read_by_group_type(void *data, void *user_data)
 {
 	struct read_by_group_type_data *search_data = user_data;
 	struct gatt_db_service *service = data;
-	struct gatt_db_group *group;
 
 	if (!service->active)
 		return;
@@ -448,19 +447,8 @@ static void read_by_group_type(void *data, void *user_data)
 		return;
 	}
 
-	group = malloc0(sizeof(struct gatt_db_group) +
-					service->attributes[0]->value_len);
-	if (!group)
-		return;
-
-	group->len = service->attributes[0]->value_len;
-	memcpy(group->value, service->attributes[0]->value, group->len);
-	group->handle = service->attributes[0]->handle;
-	group->end_group = service->attributes[0]->handle +
-						service->num_handles - 1;
-
-	if (!queue_push_tail(search_data->queue, group))
-		free(group);
+	queue_push_tail(search_data->queue,
+			UINT_TO_PTR(service->attributes[0]->handle));
 }
 
 void gatt_db_read_by_group_type(struct gatt_db *db, uint16_t start_handle,
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 1a18fb7..6ec7e22 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -67,7 +67,6 @@ struct gatt_db_group {
 	uint8_t value[0];
 };
 
-/* Returns queue with struct gatt_db_group */
 void gatt_db_read_by_group_type(struct gatt_db *db, uint16_t start_handle,
 							uint16_t end_handle,
 							const bt_uuid_t type,
-- 
1.9.0


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

* [PATCHv4 12/15] android/gatt: Change handling of read_by_group_type requests
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (10 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 11/15] shared/gatt: Retun list of handles in gatt_db_read_by_group_type Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 13/15] shared/gatt: Remove unused structure Marcin Kraglak
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

Use modified version of gatt_db_read_by_group_type which return list
of handles instead of specific data.
---
 android/gatt.c | 126 +++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 87 insertions(+), 39 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 83c2485..2dbf085 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -3492,6 +3492,56 @@ static void send_dev_pending_response(struct gatt_device *device,
 		len = enc_read_resp(val->value, val->length, rsp, sizeof(rsp));
 		destroy_pending_request(val);
 		break;
+	case ATT_OP_READ_BY_GROUP_REQ: {
+		struct att_data_list *adl;
+		int iterator = 0;
+		int length;
+		struct queue *temp;
+
+		temp = queue_new();
+		if (!temp)
+			goto done;
+
+		val = queue_pop_head(device->pending_requests);
+		if (!val) {
+			queue_destroy(temp, NULL);
+			error = ATT_ECODE_ATTR_NOT_FOUND;
+			goto done;
+		}
+
+		length = val->length;
+
+		while (val && val->length == length) {
+			queue_push_tail(temp, val);
+			val = queue_pop_head(device->pending_requests);
+		}
+
+		adl = att_data_list_alloc(queue_length(temp),
+						2 * sizeof(uint16_t) + length);
+
+		val = queue_pop_head(temp);
+		while (val) {
+			uint8_t *value = adl->data[iterator++];
+			uint16_t end_handle;
+
+			end_handle = gatt_db_get_end_handle(gatt_db,
+								val->handle);
+
+			put_le16(val->handle, value);
+			put_le16(end_handle, &value[2]);
+			memcpy(&value[4], val->value, val->length);
+
+			destroy_pending_request(val);
+			val = queue_pop_head(temp);
+		}
+
+		len = enc_read_by_grp_resp(adl, rsp, sizeof(rsp));
+
+		att_data_list_free(adl);
+		queue_destroy(temp, destroy_pending_request);
+
+		break;
+	}
 	default:
 		break;
 	}
@@ -4117,36 +4167,16 @@ static const struct ipc_handler cmd_handlers[] = {
 		sizeof(struct hal_cmd_gatt_server_send_response) },
 };
 
-struct copy_att_list_data {
-	int iterator;
-	struct att_data_list *adl;
-};
-
-static void copy_to_att_list(void *data, void *user_data)
-{
-	struct copy_att_list_data *l = user_data;
-	struct gatt_db_group *group = data;
-	uint8_t *value;
-
-	value = l->adl->data[l->iterator++];
-
-	put_le16(group->handle, value);
-	put_le16(group->end_group, &value[2]);
-
-	memcpy(&value[4], group->value, group->len);
-}
 
 static uint8_t read_by_group_type(const uint8_t *cmd, uint16_t cmd_len,
 						uint8_t *rsp, size_t rsp_size,
-						uint16_t *length)
+						uint16_t *length,
+						struct gatt_device *device)
 {
 	uint16_t start, end;
-	uint16_t len;
+	int len;
 	bt_uuid_t uuid;
 	struct queue *q;
-	struct att_data_list *adl;
-	struct copy_att_list_data l;
-	struct gatt_db_group *d;
 
 	len = dec_read_by_grp_req(cmd, cmd_len, &start, &end, &uuid);
 	if (!len)
@@ -4163,26 +4193,44 @@ static uint8_t read_by_group_type(const uint8_t *cmd, uint16_t cmd_len,
 		return ATT_ECODE_ATTR_NOT_FOUND;
 	}
 
-	len = queue_length(q);
-	d = queue_peek_head(q);
+	while (queue_peek_head(q)) {
+		uint16_t handle = PTR_TO_UINT(queue_pop_head(q));
+		uint8_t *value;
+		int value_len;
+		struct pending_request *entry;
 
-	/* Element contains start/end handle + size of uuid */
-	adl = att_data_list_alloc(len, 2 * sizeof(uint16_t) + d->len);
-	if (!adl) {
-		queue_destroy(q, free);
-		return ATT_ECODE_INSUFF_RESOURCES;
-	}
+		entry = new0(struct pending_request, 1);
+		if (!entry) {
+			queue_destroy(q, destroy_pending_request);
+			return ATT_ECODE_UNLIKELY;
+		}
 
-	l.iterator = 0;
-	l.adl = adl;
+		entry->handle = handle;
 
-	queue_foreach(q, copy_to_att_list, &l);
+		if (!gatt_db_read(gatt_db, handle, 0, ATT_OP_READ_BY_GROUP_REQ,
+					&device->bdaddr, &value, &value_len))
+			break;
 
-	len = enc_read_by_grp_resp(adl, rsp, rsp_size);
-	*length = len;
+		entry->value = malloc0(value_len);
+		if (!entry->value) {
+			queue_destroy(q, destroy_pending_request);
+			return ATT_ECODE_UNLIKELY;
+		}
 
-	att_data_list_free(adl);
-	queue_destroy(q, free);
+		memcpy(entry->value, value, value_len);
+		entry->length = value_len;
+
+		if (!queue_push_tail(device->pending_requests, entry)) {
+			queue_remove_all(device->pending_requests, NULL, NULL,
+						destroy_pending_request);
+			queue_destroy(q, NULL);
+			return ATT_ECODE_UNLIKELY;
+		}
+	}
+
+	queue_destroy(q, NULL);
+
+	send_dev_pending_response(device, cmd[0]);
 
 	return 0;
 }
@@ -4473,7 +4521,7 @@ static void att_handler(const uint8_t *ipdu, uint16_t len, gpointer user_data)
 	switch (ipdu[0]) {
 	case ATT_OP_READ_BY_GROUP_REQ:
 		status = read_by_group_type(ipdu, len, opdu, sizeof(opdu),
-								&length);
+								&length, dev);
 		break;
 	case ATT_OP_READ_BY_TYPE_REQ:
 		status = read_by_type(ipdu, len, dev);
-- 
1.9.0


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

* [PATCHv4 13/15] shared/gatt: Remove unused structure
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (11 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 12/15] android/gatt: Change handling of read_by_group_type requests Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 14/15] shared/gatt: Make 'find_by_type_value' callback compatible Marcin Kraglak
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

This structure is no longer used.
---
 src/shared/gatt-db.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 6ec7e22..529abd0 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -60,13 +60,6 @@ uint16_t gatt_db_add_included_service(struct gatt_db *db, uint16_t handle,
 bool gatt_db_service_set_active(struct gatt_db *db, uint16_t handle,
 								bool active);
 
-struct gatt_db_group {
-	uint16_t handle;
-	uint16_t end_group;
-	uint16_t len;
-	uint8_t value[0];
-};
-
 void gatt_db_read_by_group_type(struct gatt_db *db, uint16_t start_handle,
 							uint16_t end_handle,
 							const bt_uuid_t type,
-- 
1.9.0


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

* [PATCHv4 14/15] shared/gatt: Make 'find_by_type_value' callback compatible
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (12 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 13/15] shared/gatt: Remove unused structure Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 13:02 ` [PATCHv4 15/15] android/gatt: Add find by type and value handler Marcin Kraglak
  2014-05-15 14:34 ` [PATCHv4 00/15] Refactor reading attributes type Szymon Janc
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth

'Find by type and value' was handling only values written directly to
database and not those returned by callbacks or by Android Framework.
This replaces it with 'find by type' and leaves value verification to
the user.
---
 src/shared/gatt-db.c | 36 +++++++-----------------------------
 src/shared/gatt-db.h | 11 ++---------
 2 files changed, 9 insertions(+), 38 deletions(-)

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 25661c7..d9f63be 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -473,16 +473,13 @@ struct find_by_type_value_data {
 	bt_uuid_t uuid;
 	uint16_t start_handle;
 	uint16_t end_handle;
-	uint16_t value_length;
-	const uint8_t *value;
 };
 
-static void find_by_type_value(void *data, void *user_data)
+static void find_by_type(void *data, void *user_data)
 {
 	struct find_by_type_value_data *search_data = user_data;
 	struct gatt_db_service *service = data;
 	struct gatt_db_attribute *attribute;
-	struct gatt_db_range *range;
 	int i;
 
 	if (!service->active)
@@ -501,43 +498,24 @@ static void find_by_type_value(void *data, void *user_data)
 		if (bt_uuid_cmp(&search_data->uuid, &attribute->uuid))
 			continue;
 
-		if (attribute->value_len != search_data->value_length)
-			continue;
-
-		if (!memcmp(attribute->value, search_data->value,
-							attribute->value_len))
-			continue;
-
-		range = new0(struct gatt_db_range, 1);
-		if (!range)
-			return;
-
-		range->handle = attribute->handle;
-		range->end_group = service->attributes[0]->handle +
-						service->num_handles - 1;
-
-		if (!queue_push_tail(search_data->queue, range))
-			free(range);
+		queue_push_tail(search_data->queue,
+						UINT_TO_PTR(attribute->handle));
 	}
 }
 
-void gatt_db_find_by_type_value(struct gatt_db *db, uint16_t start_handle,
+void gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
 							uint16_t end_handle,
-							const bt_uuid_t type,
-							const uint8_t *value,
-							uint16_t length,
+							const bt_uuid_t *type,
 							struct queue *queue)
 {
 	struct find_by_type_value_data data;
 
-	data.uuid = type;
+	data.uuid = *type;
 	data.start_handle = start_handle;
 	data.end_handle = end_handle;
 	data.queue = queue;
-	data.value_length = length;
-	data.value = value;
 
-	queue_foreach(db->services, find_by_type_value, &data);
+	queue_foreach(db->services, find_by_type, &data);
 }
 
 struct read_by_type_data {
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 529abd0..3d46730 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
@@ -65,16 +65,9 @@ void gatt_db_read_by_group_type(struct gatt_db *db, uint16_t start_handle,
 							const bt_uuid_t type,
 							struct queue *queue);
 
-struct gatt_db_range {
-	uint16_t handle;
-	uint16_t end_group;
-};
-
-void gatt_db_find_by_type_value(struct gatt_db *db, uint16_t start_handle,
+void gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
 							uint16_t end_handle,
-							const bt_uuid_t type,
-							const uint8_t *value,
-							uint16_t length,
+							const bt_uuid_t *type,
 							struct queue *queue);
 
 void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle,
-- 
1.9.0


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

* [PATCHv4 15/15] android/gatt: Add find by type and value handler
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (13 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 14/15] shared/gatt: Make 'find_by_type_value' callback compatible Marcin Kraglak
@ 2014-05-15 13:02 ` Marcin Kraglak
  2014-05-15 14:34 ` [PATCHv4 00/15] Refactor reading attributes type Szymon Janc
  15 siblings, 0 replies; 17+ messages in thread
From: Marcin Kraglak @ 2014-05-15 13:02 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jakub Tyszkowski

From: Jakub Tyszkowski <jakub.tyszkowski@tieto.com>

As from database point of view there are two data sources (db entry,
and callbacks), we need to perform 'find by type' in databse and filter
out entries with not matching values, before sending.
---
 android/gatt.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 133 insertions(+), 2 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 2dbf085..e892571 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -764,6 +764,9 @@ struct pending_request {
 	int length;
 	uint8_t *value;
 	uint16_t offset;
+
+	uint8_t *filter_value;
+	uint16_t filter_vlen;
 };
 
 static void destroy_pending_request(void *data)
@@ -771,6 +774,7 @@ static void destroy_pending_request(void *data)
 	struct pending_request *entry = data;
 
 	free(entry->value);
+	free(entry->filter_value);
 	free(entry);
 }
 
@@ -3416,6 +3420,21 @@ failed:
 				HAL_OP_GATT_SERVER_ADD_INC_SERVICE, status);
 }
 
+static bool is_service(const bt_uuid_t *type)
+{
+	bt_uuid_t uuid;
+
+	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+	if (!bt_uuid_cmp(&uuid, type))
+		return true;
+
+	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
+	if (!bt_uuid_cmp(&uuid, type))
+		return true;
+
+	return false;
+}
+
 static void send_dev_pending_response(struct gatt_device *device,
 								uint8_t opcode)
 {
@@ -3542,6 +3561,55 @@ static void send_dev_pending_response(struct gatt_device *device,
 
 		break;
 	}
+	case ATT_OP_FIND_BY_TYPE_REQ: {
+		GSList *list = NULL;
+
+		val = queue_pop_head(device->pending_requests);
+		while (val) {
+			struct att_range *range;
+			const bt_uuid_t *type;
+
+			/* Its find by type and value - filter by value here */
+			if ((val->length != val->filter_vlen) ||
+				memcmp(val->value, val->filter_value,
+								val->length)) {
+
+				destroy_pending_request(val);
+				val = queue_pop_head(device->pending_requests);
+				continue;
+			}
+
+			range = new0(struct att_range, 1);
+			if (!range) {
+				destroy_pending_request(val);
+				error = ATT_ECODE_INSUFF_RESOURCES;
+				break;
+			}
+
+			range->start = val->handle;
+			range->end = range->start;
+
+			/* Get proper end handle if its group type */
+			type = gatt_db_get_attribute_type(gatt_db, val->handle);
+			if (is_service(type))
+				range->end = gatt_db_get_end_handle(gatt_db,
+								val->handle);
+
+			list = g_slist_append(list, range);
+
+			destroy_pending_request(val);
+			val = queue_pop_head(device->pending_requests);
+		}
+
+		if (list && !error)
+			len = enc_find_by_type_resp(list, rsp, sizeof(rsp));
+		else
+			error = ATT_ECODE_ATTR_NOT_FOUND;
+
+		g_slist_free_full(list, free);
+
+		break;
+	}
 	default:
 		break;
 	}
@@ -4167,7 +4235,6 @@ static const struct ipc_handler cmd_handlers[] = {
 		sizeof(struct hal_cmd_gatt_server_send_response) },
 };
 
-
 static uint8_t read_by_group_type(const uint8_t *cmd, uint16_t cmd_len,
 						uint8_t *rsp, size_t rsp_size,
 						uint16_t *length,
@@ -4442,6 +4509,68 @@ static uint8_t find_info_handle(const uint8_t *cmd, uint16_t cmd_len,
 	return 0;
 }
 
+static uint8_t find_by_type_request(const uint8_t *cmd, uint16_t cmd_len,
+						struct gatt_device *device)
+{
+	uint8_t search_value[ATT_DEFAULT_LE_MTU];
+	size_t search_vlen;
+	uint16_t start, end;
+	uint16_t handle;
+	struct queue *q;
+	bt_uuid_t uuid;
+	uint16_t len;
+
+	DBG("");
+
+	len = dec_find_by_type_req(cmd, cmd_len, &start, &end, &uuid,
+						search_value, &search_vlen);
+	if (!len)
+		return ATT_ECODE_INVALID_PDU;
+
+	q = queue_new();
+	if (!q)
+		return ATT_ECODE_UNLIKELY;
+
+	gatt_db_find_by_type(gatt_db, start, end, &uuid, q);
+
+	handle = PTR_TO_UINT(queue_pop_head(q));
+	while (handle) {
+		struct pending_request *data;
+
+		data = new0(struct pending_request, 1);
+		if (!data) {
+			queue_destroy(q, NULL);
+			return ATT_ECODE_INSUFF_RESOURCES;
+		}
+
+		data->filter_value = malloc0(search_vlen);
+		if (!data) {
+			destroy_pending_request(data);
+			queue_destroy(q, NULL);
+			return ATT_ECODE_INSUFF_RESOURCES;
+		}
+
+		data->handle = handle;
+		data->filter_vlen = search_vlen;
+		memcpy(data->filter_value, search_value, search_vlen);
+
+		queue_push_tail(device->pending_requests, data);
+
+		handle = PTR_TO_UINT(queue_pop_head(q));
+	}
+
+	queue_destroy(q, NULL);
+
+	process_dev_pending_requests(device, ATT_OP_FIND_BY_TYPE_REQ);
+
+	/* Send if no response_data elements left to be filled by callbacks */
+	if (!queue_find(device->pending_requests, match_pending_dev_request,
+									NULL))
+		send_dev_pending_response(device, cmd[0]);
+
+	return 0;
+}
+
 static uint8_t write_cmd_request(const uint8_t *cmd, uint16_t cmd_len,
 						struct gatt_device *dev)
 {
@@ -4553,9 +4682,11 @@ static void att_handler(const uint8_t *ipdu, uint16_t len, gpointer user_data)
 		if (!status)
 			return;
 		break;
+	case ATT_OP_FIND_BY_TYPE_REQ:
+		status = find_by_type_request(ipdu, len, dev);
+		break;
 	case ATT_OP_EXEC_WRITE_REQ:
 		/* TODO */
-	case ATT_OP_FIND_BY_TYPE_REQ:
 	case ATT_OP_HANDLE_CNF:
 	case ATT_OP_HANDLE_IND:
 	case ATT_OP_HANDLE_NOTIFY:
-- 
1.9.0


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

* Re: [PATCHv4 00/15] Refactor reading attributes type
  2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
                   ` (14 preceding siblings ...)
  2014-05-15 13:02 ` [PATCHv4 15/15] android/gatt: Add find by type and value handler Marcin Kraglak
@ 2014-05-15 14:34 ` Szymon Janc
  15 siblings, 0 replies; 17+ messages in thread
From: Szymon Janc @ 2014-05-15 14:34 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth

Hi Marcin,

On Thursday 15 of May 2014 15:02:22 Marcin Kraglak wrote:
> Changes in v4:
>  - fixed function names and coding style issues
>  - Added macros with state of reading operation: READ_INIT,
>         READ_PENDING and READ_DONE and READ_FAILED
> 
> Jakub Tyszkowski (1):
>   android/gatt: Add find by type and value handler
> 
> Marcin Kraglak (14):
>   shared/gatt: Extend gatt_db_read function
>   android/gatt: Refactor ATT read operations
>   shared/gatt: Modify gatt_db_read_by_type to return handles only
>   android/gatt: Change handling read_by_type requests
>   shared/gatt: Remove unused structure
>   shared/gatt: Modify gatt_db_find_information to return list of handles
>   shared/gatt: Add helper function to get attribute type
>   android/gatt: Change handling of find_information requests
>   shared/gatt: Remove unused structure
>   shared/gatt: Add function to get end group handle
>   shared/gatt: Retun list of handles in gatt_db_read_by_group_type
>   android/gatt: Change handling of read_by_group_type requests
>   shared/gatt: Remove unused structure
>   shared/gatt: Make 'find_by_type_value' callback compatible
> 
>  android/gatt.c       | 667 +++++++++++++++++++++++++++++++++++++++------------
>  src/shared/gatt-db.c | 135 ++++++-----
>  src/shared/gatt-db.h |  38 +--
>  3 files changed, 591 insertions(+), 249 deletions(-)
> 

All patches (v5 of 2/15) are now applied, thanks a lot.

-- 
Best regards, 
Szymon Janc

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

end of thread, other threads:[~2014-05-15 14:34 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-15 13:02 [PATCHv4 00/15] Refactor reading attributes type Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 01/15] shared/gatt: Extend gatt_db_read function Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 02/15] android/gatt: Refactor ATT read operations Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 03/15] shared/gatt: Modify gatt_db_read_by_type to return handles only Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 04/15] android/gatt: Change handling read_by_type requests Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 05/15] shared/gatt: Remove unused structure Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 06/15] shared/gatt: Modify gatt_db_find_information to return list of handles Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 07/15] shared/gatt: Add helper function to get attribute type Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 08/15] android/gatt: Change handling of find_information requests Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 09/15] shared/gatt: Remove unused structure Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 10/15] shared/gatt: Add function to get end group handle Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 11/15] shared/gatt: Retun list of handles in gatt_db_read_by_group_type Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 12/15] android/gatt: Change handling of read_by_group_type requests Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 13/15] shared/gatt: Remove unused structure Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 14/15] shared/gatt: Make 'find_by_type_value' callback compatible Marcin Kraglak
2014-05-15 13:02 ` [PATCHv4 15/15] android/gatt: Add find by type and value handler Marcin Kraglak
2014-05-15 14:34 ` [PATCHv4 00/15] Refactor reading attributes type Szymon Janc

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.