linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Łukasz Rymanowski" <lukasz.rymanowski@codecoup.pl>
To: linux-bluetooth@vger.kernel.org
Cc: "Łukasz Rymanowski" <lukasz.rymanowski@codecoup.pl>
Subject: [PATCH v3 6/9] shared/gatt-server: Add support for long write
Date: Fri, 18 Mar 2016 14:08:15 +0100	[thread overview]
Message-ID: <1458306498-28151-7-git-send-email-lukasz.rymanowski@codecoup.pl> (raw)
In-Reply-To: <1458306498-28151-1-git-send-email-lukasz.rymanowski@codecoup.pl>

With this patch long write and nested long write reliable is supported.
GATT server is responsible now to do aggregation of prep write data
for long write session.
Note: We consider long write as the consequtive prepare writes with
continues offsets.

E.g. 1

prep_write: handle 1, offset 0, value_len 10
prep_write: handle 2, offset 0, value_len 10
prep_write: handle 1, offset 10, value_len 10
prep_write: handle 2, offset 10, value_len 10

Will result with following calles to app:

exec_write: handle 1: offset 0, value_len 20
exec_write: handle 2: offset 0, value_len 20

E.g. 2

prep_write: handle 1, offset 0, value_len 10
prep_write: handle 1, offset 2, value_len 5
prep_write: handle 2, offset 0, value_len 10
prep_write: handle 2, offset 4, value_len 5

Will result with following calles to app:

exec_write: handle 1: offset 0, value_len 10
exec_write: handle 1: offset 2, value_len 5
exec_write: handle 2: offset 0, value_len 10
exec_write: handle 2: offset 4, value_len 5
---
 src/shared/gatt-server.c | 85 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 71 insertions(+), 14 deletions(-)

diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index c41273a..0904336 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -1088,6 +1088,63 @@ error:
 	bt_att_send_error_rsp(server->att, opcode, 0, ecode);
 }
 
+static bool match_attribute_handle(const void *data, const void *match_data)
+{
+	const struct prep_write_data *prep_data = data;
+
+	return prep_data->handle == PTR_TO_UINT(match_data);
+}
+
+static bool create_and_store_prep_data(struct bt_gatt_server *server,
+						uint16_t handle, uint16_t offset,
+						uint16_t length, uint8_t *value)
+{
+	struct prep_write_data *prep_data;
+
+	prep_data = new0(struct prep_write_data, 1);
+	prep_data->length = length;
+	if (prep_data->length) {
+		prep_data->value = malloc(prep_data->length);
+		if (!prep_data->value) {
+			return false;
+		}
+
+		memcpy(prep_data->value, value, prep_data->length);
+	}
+
+	prep_data->server = server;
+	prep_data->handle = handle;
+	prep_data->offset = offset;
+
+	queue_push_tail(server->prep_queue, prep_data);
+
+	return true;
+}
+
+static bool make_aggregation_of_long_write_data(struct bt_gatt_server *server,
+					struct prep_write_data *prep_data,
+					uint16_t handle, uint16_t length,
+					uint8_t *value)
+{
+	uint8_t *buf;
+	uint16_t new_len;
+
+	new_len = prep_data->length + length;
+
+	buf = malloc(new_len);
+	if (!buf)
+		return false;
+
+	memcpy(buf, prep_data->value, prep_data->length);
+	memcpy(buf + prep_data->length, value, length);
+
+	free(prep_data->value);
+	prep_data->value = buf;
+	prep_data->length = new_len;
+
+	return true;
+}
+
 static void prep_write_cb(uint8_t opcode, const void *pdu,
 					uint16_t length, void *user_data)
 {
@@ -1097,6 +1154,7 @@ static void prep_write_cb(uint8_t opcode, const void *pdu,
 	uint16_t offset;
 	struct gatt_db_attribute *attr;
 	uint8_t ecode;
+	bool success;
 
 	if (length < 4) {
 		ecode = BT_ATT_ERROR_INVALID_PDU;
@@ -1126,22 +1184,21 @@ static void prep_write_cb(uint8_t opcode, const void *pdu,
 	if (ecode)
 		goto error;
 
-	prep_data = new0(struct prep_write_data, 1);
-	prep_data->length = length - 4;
-	if (prep_data->length) {
-		prep_data->value = malloc(prep_data->length);
-		if (!prep_data->value) {
-			ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
-			goto error;
-		}
-	}
+	prep_data = queue_find(server->prep_queue, match_attribute_handle,
+							UINT_TO_PTR(handle));
 
-	prep_data->server = server;
-	prep_data->handle = handle;
-	prep_data->offset = offset;
-	memcpy(prep_data->value, pdu + 4, prep_data->length);
+	if (prep_data && offset == prep_data->length + prep_data->offset)
+		success = make_aggregation_of_long_write_data(server, prep_data,
+							handle, length - 4,
+							&((uint8_t *) pdu)[4]);
+	else
+		success = create_and_store_prep_data(server, handle, offset,
+					length - 4, &((uint8_t *) pdu)[4]);
 
-	queue_push_tail(server->prep_queue, prep_data);
+	if (!success) {
+		ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
+		goto error;
+	}
 
 	bt_att_send(server->att, BT_ATT_OP_PREP_WRITE_RSP, pdu, length, NULL,
 								NULL, NULL);
-- 
2.5.0


  parent reply	other threads:[~2016-03-18 13:08 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-18 13:08 [PATCH v3 0/9] shared/gatt: Couple fixes and improvements Łukasz Rymanowski
2016-03-18 13:08 ` [PATCH v3 1/9] unit/test-gatt: Fix long write testcases Łukasz Rymanowski
2016-03-18 13:08 ` [PATCH v3 2/9] unit/test-gatt: Modify small-db Łukasz Rymanowski
2016-03-18 13:08 ` [PATCH v3 3/9] unit/test-gatt: Extend large-db Łukasz Rymanowski
2016-03-18 13:08 ` [PATCH v3 4/9] unit/test-gatt: Fix long write test Łukasz Rymanowski
2016-03-18 13:08 ` [PATCH v3 5/9] shared/gatt-server: Fix handle error on execute write Łukasz Rymanowski
2016-03-18 13:08 ` Łukasz Rymanowski [this message]
2016-03-22 15:03   ` [PATCH v3 6/9] shared/gatt-server: Add support for long write Luiz Augusto von Dentz
2016-03-25 14:15     ` Łukasz Rymanowski
2016-03-18 13:08 ` [PATCH v3 7/9] shared/gatt-server: Support for reliable session nested with long Łukasz Rymanowski
2016-03-18 13:08 ` [PATCH v3 8/9] shared/gatt-db: Add API to get extended prop Łukasz Rymanowski
2016-03-18 13:08 ` [PATCH v3 9/9] shared/gatt-server: Check for ext. charact. prop. on reliable session Łukasz Rymanowski
2016-03-22 14:57 ` [PATCH v3 0/9] shared/gatt: Couple fixes and improvements Luiz Augusto von Dentz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1458306498-28151-7-git-send-email-lukasz.rymanowski@codecoup.pl \
    --to=lukasz.rymanowski@codecoup.pl \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).