linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/3] att: Add prepare write support
@ 2012-07-27 20:29 Eder Ruiz Maria
  2012-07-27 20:29 ` [PATCH BlueZ 2/3] att: Add encode/decode execute " Eder Ruiz Maria
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Eder Ruiz Maria @ 2012-07-27 20:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

Add functions for encoding/decoding Prepare Write Request and
Response PDUs.
---
 attrib/att.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 attrib/att.h |    5 +++++
 2 files changed, 60 insertions(+)

diff --git a/attrib/att.c b/attrib/att.c
index 0550ac1..acfb4e0 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -974,3 +974,58 @@ uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu)
 
 	return min_len;
 }
+
+uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
+			const uint8_t *value, int vlen, uint8_t *pdu, int len)
+{
+	const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle) +
+								sizeof(offset);
+
+	if (pdu == NULL)
+		return 0;
+
+	if (len < min_len)
+		return 0;
+
+	if (vlen > len - min_len)
+		vlen = len - min_len;
+
+	pdu[0] = ATT_OP_PREP_WRITE_REQ;
+	att_put_u16(handle, &pdu[1]);
+	att_put_u16(offset, &pdu[3]);
+
+	if (vlen > 0) {
+		memcpy(&pdu[5], value, vlen);
+		return min_len + vlen;
+	}
+
+	return min_len;
+}
+
+uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
+				uint16_t *offset, uint8_t *value, int *vlen)
+{
+	const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle) +
+								sizeof(*offset);
+
+	if (pdu == NULL)
+		return 0;
+
+	if (handle == NULL || offset == NULL || value == NULL || vlen == NULL)
+		return 0;
+
+	if (len < min_len)
+		return 0;
+
+	if (pdu[0] != ATT_OP_PREP_WRITE_REQ)
+		return 0;
+
+	*handle = att_get_u16(&pdu[1]);
+	*offset = att_get_u16(&pdu[3]);
+	*vlen = len - min_len;
+	if (*vlen > 0)
+		memcpy(value, pdu + min_len, *vlen);
+
+	return len;
+}
+
diff --git a/attrib/att.h b/attrib/att.h
index 1c1102a..ec03be9 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -256,3 +256,8 @@ uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, int len);
 uint16_t dec_mtu_req(const uint8_t *pdu, int len, uint16_t *mtu);
 uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, int len);
 uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu);
+
+uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
+			const uint8_t *value, int vlen, uint8_t *pdu, int len);
+uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
+				uint16_t *offset, uint8_t *value, int *vlen);
-- 
1.7.9.5


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

* [PATCH BlueZ 2/3] att: Add encode/decode execute write support
  2012-07-27 20:29 [PATCH BlueZ 1/3] att: Add prepare write support Eder Ruiz Maria
@ 2012-07-27 20:29 ` Eder Ruiz Maria
  2012-07-27 20:29 ` [PATCH BlueZ 3/3] gatt: Add support to GATT Write Long Characteristic Eder Ruiz Maria
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Eder Ruiz Maria @ 2012-07-27 20:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

Add functions for encoding/decoding Execute Write Request and
Response PDUs.
---
 attrib/att.c |   34 ++++++++++++++++++++++++++++++++++
 attrib/att.h |    2 ++
 2 files changed, 36 insertions(+)

diff --git a/attrib/att.c b/attrib/att.c
index acfb4e0..20a8efa 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -1029,3 +1029,37 @@ uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
 	return len;
 }
 
+uint16_t enc_exec_write_req(uint8_t flags, uint8_t *pdu, int len)
+{
+	const uint16_t min_len = sizeof(pdu[0]) + sizeof(flags);
+
+	if (pdu == NULL)
+		return 0;
+
+	if (len < min_len)
+		return 0;
+
+	if (flags > 1)
+		return 0;
+
+	pdu[0] = ATT_OP_EXEC_WRITE_REQ;
+	pdu[1] = flags;
+
+	return min_len;
+}
+
+uint16_t dec_exec_write_resp(const uint8_t *pdu, int len)
+{
+	const uint16_t min_len = sizeof(pdu[0]);
+
+	if (pdu == NULL)
+		return 0;
+
+	if (len < min_len)
+		return 0;
+
+	if (pdu[0] != ATT_OP_EXEC_WRITE_RESP)
+		return 0;
+
+	return len;
+}
diff --git a/attrib/att.h b/attrib/att.h
index ec03be9..64d22ca 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -261,3 +261,5 @@ uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
 			const uint8_t *value, int vlen, uint8_t *pdu, int len);
 uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
 				uint16_t *offset, uint8_t *value, int *vlen);
+uint16_t enc_exec_write_req(uint8_t flags, uint8_t *pdu, int len);
+uint16_t dec_exec_write_resp(const uint8_t *pdu, int len);
-- 
1.7.9.5


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

* [PATCH BlueZ 3/3] gatt: Add support to GATT Write Long Characteristic
  2012-07-27 20:29 [PATCH BlueZ 1/3] att: Add prepare write support Eder Ruiz Maria
  2012-07-27 20:29 ` [PATCH BlueZ 2/3] att: Add encode/decode execute " Eder Ruiz Maria
@ 2012-07-27 20:29 ` Eder Ruiz Maria
  2012-07-29  1:47 ` [PATCH BlueZ 1/3] att: Add prepare write support Sergio Correia
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Eder Ruiz Maria @ 2012-07-27 20:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

Extending the function gatt_write_char for support GATT Write Long
Characteristics. MTU is checked and if the payload does not fit,
the prepare and execute write are used to do the transaction.
---
 attrib/att.h         |    4 ++
 attrib/gatt.c        |  109 +++++++++++++++++++++++++++++++++++++++++++++++---
 attrib/gatttool.c    |    2 +-
 attrib/interactive.c |    2 +-
 4 files changed, 110 insertions(+), 7 deletions(-)

diff --git a/attrib/att.h b/attrib/att.h
index 64d22ca..e7a29cb 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -92,6 +92,10 @@
 #define ATT_CID					4
 #define ATT_PSM					31
 
+/* Flags for Execute Write Request Operation */
+#define ATT_CANCEL_ALL_PREP_WRITES              0x00
+#define ATT_WRITE_ALL_PREP_WRITES               0x01
+
 struct att_data_list {
 	uint16_t num;
 	uint16_t len;
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 6f9a11d..b7eb736 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -520,21 +520,120 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, uint16_t offset,
 	return id;
 }
 
+struct write_long_data {
+	GAttrib *attrib;
+	GAttribResultFunc func;
+	gpointer user_data;
+	guint16 handle;
+	uint16_t offset;
+	uint8_t *value;
+	int vlen;
+};
+
+static guint execute_write(GAttrib *attrib, uint8_t flags,
+				GAttribResultFunc func, gpointer user_data)
+{
+	uint8_t *buf;
+	int buflen;
+	guint16 plen;
+
+	buf = g_attrib_get_buffer(attrib, &buflen);
+	plen = enc_exec_write_req(flags, buf, buflen);
+	if (plen == 0)
+		return 0;
+
+	return g_attrib_send(attrib, 0, buf[0], buf, plen, func, user_data,
+									NULL);
+}
+
+static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
+			uint8_t *value, int vlen, GAttribResultFunc func,
+			gpointer user_data);
+
+static void prepare_write_cb(guint8 status, const guint8 *rpdu,
+					guint16 rlen, gpointer user_data)
+{
+	struct write_long_data *long_write = user_data;
+
+	if (status != 0) {
+		long_write->func(status, rpdu, rlen, long_write->user_data);
+		return;
+	}
+
+	/* Skip Prepare Write Response PDU header (5 bytes) */
+	long_write->offset += rlen - 5;
+
+	if (long_write->offset == long_write->vlen){
+		execute_write(long_write->attrib, ATT_WRITE_ALL_PREP_WRITES,
+				long_write->func, long_write->user_data);
+		g_free(long_write->value);
+		g_free(long_write);
+
+		return;
+	}
+
+	prepare_write(long_write->attrib, long_write->handle,
+		long_write->offset, long_write->value, long_write->vlen,
+		long_write->func, long_write);
+}
+
+static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
+			uint8_t *value, int vlen, GAttribResultFunc func,
+			gpointer user_data)
+{
+	guint16 plen;
+	int buflen;
+	uint8_t *buf;
+
+	buf = g_attrib_get_buffer(attrib, &buflen);
+
+	plen = enc_prep_write_req(handle, offset, &value[offset], vlen - offset,
+								buf, buflen);
+	if (plen == 0)
+		return 0;
+
+	return g_attrib_send(attrib, 0, buf[0], buf, plen, prepare_write_cb,
+							user_data, NULL);
+}
+
 guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
 			int vlen, GAttribResultFunc func, gpointer user_data)
 {
 	uint8_t *buf;
 	int buflen;
 	guint16 plen;
+	struct write_long_data *long_write;
 
 	buf = g_attrib_get_buffer(attrib, &buflen);
-	if (func)
-		plen = enc_write_req(handle, value, vlen, buf, buflen);
-	else
-		plen = enc_write_cmd(handle, value, vlen, buf, buflen);
 
-	return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
+	/* Only use Write Request/Command if payload fits on a single transfer,
+	 * including 3 bytes for the header. */
+	if (vlen <= buflen - 3) {
+		if (func)
+			plen = enc_write_req(handle, value, vlen, buf,
+								buflen);
+		else
+			plen = enc_write_cmd(handle, value, vlen, buf,
+								buflen);
+
+		return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
 							user_data, NULL);
+	}
+
+	/* Write Long Characteristic Values */
+	long_write = g_try_new0(struct write_long_data, 1);
+	if (long_write == NULL)
+		return 0;
+
+	long_write->attrib = attrib;
+	long_write->func = func;
+	long_write->user_data = user_data;
+	long_write->handle = handle;
+	long_write->value = g_memdup(value,vlen);
+	long_write->vlen = vlen;
+
+	return prepare_write(attrib, handle, long_write->offset, value, vlen,
+							func, long_write);
 }
 
 guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 1f23522..a11ca9f 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -371,7 +371,7 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
 		goto done;
 	}
 
-	if (!dec_write_resp(pdu, plen)) {
+	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
 		g_printerr("Protocol error\n");
 		goto done;
 	}
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 3657798..6cd8bd5 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -588,7 +588,7 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
 		return;
 	}
 
-	if (!dec_write_resp(pdu, plen)) {
+	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
 		printf("Protocol error\n");
 		return;
 	}
-- 
1.7.9.5


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

* Re: [PATCH BlueZ 1/3] att: Add prepare write support
  2012-07-27 20:29 [PATCH BlueZ 1/3] att: Add prepare write support Eder Ruiz Maria
  2012-07-27 20:29 ` [PATCH BlueZ 2/3] att: Add encode/decode execute " Eder Ruiz Maria
  2012-07-27 20:29 ` [PATCH BlueZ 3/3] gatt: Add support to GATT Write Long Characteristic Eder Ruiz Maria
@ 2012-07-29  1:47 ` Sergio Correia
  2012-07-30 10:35   ` Anderson Lizardo
  2012-07-30 10:55 ` Johan Hedberg
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Sergio Correia @ 2012-07-29  1:47 UTC (permalink / raw)
  To: Eder Ruiz Maria; +Cc: linux-bluetooth

Hi Eder,

On Fri, Jul 27, 2012 at 4:29 PM, Eder Ruiz Maria
<eder.ruiz@openbossa.org> wrote:
> Add functions for encoding/decoding Prepare Write Request and
> Response PDUs.
> ---
>  attrib/att.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  attrib/att.h |    5 +++++
>  2 files changed, 60 insertions(+)
>
> diff --git a/attrib/att.c b/attrib/att.c
> index 0550ac1..acfb4e0 100644
> --- a/attrib/att.c
> +++ b/attrib/att.c
> @@ -974,3 +974,58 @@ uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu)
>
>         return min_len;
>  }
> +
> +uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
> +                       const uint8_t *value, int vlen, uint8_t *pdu, int len)
> +{
> +       const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle) +
> +                                                               sizeof(offset);
> +
> +       if (pdu == NULL)
> +               return 0;
> +
> +       if (len < min_len)
> +               return 0;

maybe it would be better to check the above conditions in a single if statement?

[...]

> +uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
> +                               uint16_t *offset, uint8_t *value, int *vlen)
> +{
> +       const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle) +
> +                                                               sizeof(*offset);
> +
> +       if (pdu == NULL)
> +               return 0;
> +
> +       if (handle == NULL || offset == NULL || value == NULL || vlen == NULL)
> +               return 0;
> +
> +       if (len < min_len)
> +               return 0;
> +
> +       if (pdu[0] != ATT_OP_PREP_WRITE_REQ)
> +               return 0;

same with the above sanity checking.
The other patches in this series could also do the same, assuming it's
the preferred way.

> +
> +       *handle = att_get_u16(&pdu[1]);
> +       *offset = att_get_u16(&pdu[3]);
> +       *vlen = len - min_len;
> +       if (*vlen > 0)
> +               memcpy(value, pdu + min_len, *vlen);
> +
> +       return len;
> +}
> +
> diff --git a/attrib/att.h b/attrib/att.h
> index 1c1102a..ec03be9 100644
> --- a/attrib/att.h
> +++ b/attrib/att.h
> @@ -256,3 +256,8 @@ uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, int len);
>  uint16_t dec_mtu_req(const uint8_t *pdu, int len, uint16_t *mtu);
>  uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, int len);
>  uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu);
> +
> +uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
> +                       const uint8_t *value, int vlen, uint8_t *pdu, int len);
> +uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
> +                               uint16_t *offset, uint8_t *value, int *vlen);
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH BlueZ 1/3] att: Add prepare write support
  2012-07-29  1:47 ` [PATCH BlueZ 1/3] att: Add prepare write support Sergio Correia
@ 2012-07-30 10:35   ` Anderson Lizardo
  0 siblings, 0 replies; 10+ messages in thread
From: Anderson Lizardo @ 2012-07-30 10:35 UTC (permalink / raw)
  To: Sergio Correia; +Cc: Eder Ruiz Maria, linux-bluetooth

Hi Sergio,

On Sat, Jul 28, 2012 at 9:47 PM, Sergio Correia <lists@uece.net> wrote:
>> +uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
>> +                       const uint8_t *value, int vlen, uint8_t *pdu, int len)
>> +{
>> +       const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle) +
>> +                                                               sizeof(offset);
>> +
>> +       if (pdu == NULL)
>> +               return 0;
>> +
>> +       if (len < min_len)
>> +               return 0;
>
> maybe it would be better to check the above conditions in a single if statement?

I think Eder is following the same style from the other similar
functions in the same file. I would suggest leaving these patches as
is and instead sending a separate patch changing this in all
functions, as a refactoring patch.

My two cents,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

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

* Re: [PATCH BlueZ 1/3] att: Add prepare write support
  2012-07-27 20:29 [PATCH BlueZ 1/3] att: Add prepare write support Eder Ruiz Maria
                   ` (2 preceding siblings ...)
  2012-07-29  1:47 ` [PATCH BlueZ 1/3] att: Add prepare write support Sergio Correia
@ 2012-07-30 10:55 ` Johan Hedberg
  2012-07-30 17:34 ` [PATCH BlueZ v2 " Eder Ruiz Maria
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Johan Hedberg @ 2012-07-30 10:55 UTC (permalink / raw)
  To: Eder Ruiz Maria; +Cc: linux-bluetooth

Hi Eder,

On Fri, Jul 27, 2012, Eder Ruiz Maria wrote:
> Add functions for encoding/decoding Prepare Write Request and
> Response PDUs.
> ---
>  attrib/att.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  attrib/att.h |    5 +++++
>  2 files changed, 60 insertions(+)

This doesn't apply:

Applying: att: Add prepare write support
/home/jh/src/bluez/.git/rebase-apply/patch:68: new blank line at EOF.
+
fatal: 1 line adds whitespace errors.
Patch failed at 0001 att: Add prepare write support

Please fix (including other potentially similar issues in the other patches)
and resend. Thanks.

Johan

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

* [PATCH BlueZ v2 1/3] att: Add prepare write support
  2012-07-27 20:29 [PATCH BlueZ 1/3] att: Add prepare write support Eder Ruiz Maria
                   ` (3 preceding siblings ...)
  2012-07-30 10:55 ` Johan Hedberg
@ 2012-07-30 17:34 ` Eder Ruiz Maria
  2012-08-15  9:27   ` Johan Hedberg
  2012-07-30 17:38 ` [PATCH BlueZ v2 2/3] att: Add encode/decode execute " Eder Ruiz Maria
  2012-07-30 17:38 ` [PATCH BlueZ v2 3/3] gatt: Add support to GATT Write Long Characteristic Eder Ruiz Maria
  6 siblings, 1 reply; 10+ messages in thread
From: Eder Ruiz Maria @ 2012-07-30 17:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

Add functions for encoding/decoding Prepare Write Request and
Response PDUs.
---
 attrib/att.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 attrib/att.h |    5 +++++
 2 files changed, 59 insertions(+)

diff --git a/attrib/att.c b/attrib/att.c
index 0550ac1..790ec3a 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -974,3 +974,57 @@ uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu)
 
 	return min_len;
 }
+
+uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
+			const uint8_t *value, int vlen, uint8_t *pdu, int len)
+{
+	const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle) +
+								sizeof(offset);
+
+	if (pdu == NULL)
+		return 0;
+
+	if (len < min_len)
+		return 0;
+
+	if (vlen > len - min_len)
+		vlen = len - min_len;
+
+	pdu[0] = ATT_OP_PREP_WRITE_REQ;
+	att_put_u16(handle, &pdu[1]);
+	att_put_u16(offset, &pdu[3]);
+
+	if (vlen > 0) {
+		memcpy(&pdu[5], value, vlen);
+		return min_len + vlen;
+	}
+
+	return min_len;
+}
+
+uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
+				uint16_t *offset, uint8_t *value, int *vlen)
+{
+	const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle) +
+								sizeof(*offset);
+
+	if (pdu == NULL)
+		return 0;
+
+	if (handle == NULL || offset == NULL || value == NULL || vlen == NULL)
+		return 0;
+
+	if (len < min_len)
+		return 0;
+
+	if (pdu[0] != ATT_OP_PREP_WRITE_REQ)
+		return 0;
+
+	*handle = att_get_u16(&pdu[1]);
+	*offset = att_get_u16(&pdu[3]);
+	*vlen = len - min_len;
+	if (*vlen > 0)
+		memcpy(value, pdu + min_len, *vlen);
+
+	return len;
+}
diff --git a/attrib/att.h b/attrib/att.h
index 1c1102a..ec03be9 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -256,3 +256,8 @@ uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, int len);
 uint16_t dec_mtu_req(const uint8_t *pdu, int len, uint16_t *mtu);
 uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, int len);
 uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu);
+
+uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
+			const uint8_t *value, int vlen, uint8_t *pdu, int len);
+uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
+				uint16_t *offset, uint8_t *value, int *vlen);
-- 
1.7.9.5


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

* [PATCH BlueZ v2 2/3] att: Add encode/decode execute write support
  2012-07-27 20:29 [PATCH BlueZ 1/3] att: Add prepare write support Eder Ruiz Maria
                   ` (4 preceding siblings ...)
  2012-07-30 17:34 ` [PATCH BlueZ v2 " Eder Ruiz Maria
@ 2012-07-30 17:38 ` Eder Ruiz Maria
  2012-07-30 17:38 ` [PATCH BlueZ v2 3/3] gatt: Add support to GATT Write Long Characteristic Eder Ruiz Maria
  6 siblings, 0 replies; 10+ messages in thread
From: Eder Ruiz Maria @ 2012-07-30 17:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

Add functions for encoding/decoding Execute Write Request and
Response PDUs.
---
 attrib/att.c |   35 +++++++++++++++++++++++++++++++++++
 attrib/att.h |    2 ++
 2 files changed, 37 insertions(+)

diff --git a/attrib/att.c b/attrib/att.c
index 790ec3a..20a8efa 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -1028,3 +1028,38 @@ uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
 
 	return len;
 }
+
+uint16_t enc_exec_write_req(uint8_t flags, uint8_t *pdu, int len)
+{
+	const uint16_t min_len = sizeof(pdu[0]) + sizeof(flags);
+
+	if (pdu == NULL)
+		return 0;
+
+	if (len < min_len)
+		return 0;
+
+	if (flags > 1)
+		return 0;
+
+	pdu[0] = ATT_OP_EXEC_WRITE_REQ;
+	pdu[1] = flags;
+
+	return min_len;
+}
+
+uint16_t dec_exec_write_resp(const uint8_t *pdu, int len)
+{
+	const uint16_t min_len = sizeof(pdu[0]);
+
+	if (pdu == NULL)
+		return 0;
+
+	if (len < min_len)
+		return 0;
+
+	if (pdu[0] != ATT_OP_EXEC_WRITE_RESP)
+		return 0;
+
+	return len;
+}
diff --git a/attrib/att.h b/attrib/att.h
index ec03be9..64d22ca 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -261,3 +261,5 @@ uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
 			const uint8_t *value, int vlen, uint8_t *pdu, int len);
 uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
 				uint16_t *offset, uint8_t *value, int *vlen);
+uint16_t enc_exec_write_req(uint8_t flags, uint8_t *pdu, int len);
+uint16_t dec_exec_write_resp(const uint8_t *pdu, int len);
-- 
1.7.9.5


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

* [PATCH BlueZ v2 3/3] gatt: Add support to GATT Write Long Characteristic
  2012-07-27 20:29 [PATCH BlueZ 1/3] att: Add prepare write support Eder Ruiz Maria
                   ` (5 preceding siblings ...)
  2012-07-30 17:38 ` [PATCH BlueZ v2 2/3] att: Add encode/decode execute " Eder Ruiz Maria
@ 2012-07-30 17:38 ` Eder Ruiz Maria
  6 siblings, 0 replies; 10+ messages in thread
From: Eder Ruiz Maria @ 2012-07-30 17:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

Extending the function gatt_write_char for support GATT Write Long
Characteristics. MTU is checked and if the payload does not fit,
the prepare and execute write are used to do the transaction.
---
 attrib/att.h         |    4 ++
 attrib/gatt.c        |  109 +++++++++++++++++++++++++++++++++++++++++++++++---
 attrib/gatttool.c    |    2 +-
 attrib/interactive.c |    2 +-
 4 files changed, 110 insertions(+), 7 deletions(-)

diff --git a/attrib/att.h b/attrib/att.h
index 64d22ca..e7a29cb 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -92,6 +92,10 @@
 #define ATT_CID					4
 #define ATT_PSM					31
 
+/* Flags for Execute Write Request Operation */
+#define ATT_CANCEL_ALL_PREP_WRITES              0x00
+#define ATT_WRITE_ALL_PREP_WRITES               0x01
+
 struct att_data_list {
 	uint16_t num;
 	uint16_t len;
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 6f9a11d..b7eb736 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -520,21 +520,120 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, uint16_t offset,
 	return id;
 }
 
+struct write_long_data {
+	GAttrib *attrib;
+	GAttribResultFunc func;
+	gpointer user_data;
+	guint16 handle;
+	uint16_t offset;
+	uint8_t *value;
+	int vlen;
+};
+
+static guint execute_write(GAttrib *attrib, uint8_t flags,
+				GAttribResultFunc func, gpointer user_data)
+{
+	uint8_t *buf;
+	int buflen;
+	guint16 plen;
+
+	buf = g_attrib_get_buffer(attrib, &buflen);
+	plen = enc_exec_write_req(flags, buf, buflen);
+	if (plen == 0)
+		return 0;
+
+	return g_attrib_send(attrib, 0, buf[0], buf, plen, func, user_data,
+									NULL);
+}
+
+static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
+			uint8_t *value, int vlen, GAttribResultFunc func,
+			gpointer user_data);
+
+static void prepare_write_cb(guint8 status, const guint8 *rpdu,
+					guint16 rlen, gpointer user_data)
+{
+	struct write_long_data *long_write = user_data;
+
+	if (status != 0) {
+		long_write->func(status, rpdu, rlen, long_write->user_data);
+		return;
+	}
+
+	/* Skip Prepare Write Response PDU header (5 bytes) */
+	long_write->offset += rlen - 5;
+
+	if (long_write->offset == long_write->vlen){
+		execute_write(long_write->attrib, ATT_WRITE_ALL_PREP_WRITES,
+				long_write->func, long_write->user_data);
+		g_free(long_write->value);
+		g_free(long_write);
+
+		return;
+	}
+
+	prepare_write(long_write->attrib, long_write->handle,
+		long_write->offset, long_write->value, long_write->vlen,
+		long_write->func, long_write);
+}
+
+static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
+			uint8_t *value, int vlen, GAttribResultFunc func,
+			gpointer user_data)
+{
+	guint16 plen;
+	int buflen;
+	uint8_t *buf;
+
+	buf = g_attrib_get_buffer(attrib, &buflen);
+
+	plen = enc_prep_write_req(handle, offset, &value[offset], vlen - offset,
+								buf, buflen);
+	if (plen == 0)
+		return 0;
+
+	return g_attrib_send(attrib, 0, buf[0], buf, plen, prepare_write_cb,
+							user_data, NULL);
+}
+
 guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
 			int vlen, GAttribResultFunc func, gpointer user_data)
 {
 	uint8_t *buf;
 	int buflen;
 	guint16 plen;
+	struct write_long_data *long_write;
 
 	buf = g_attrib_get_buffer(attrib, &buflen);
-	if (func)
-		plen = enc_write_req(handle, value, vlen, buf, buflen);
-	else
-		plen = enc_write_cmd(handle, value, vlen, buf, buflen);
 
-	return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
+	/* Only use Write Request/Command if payload fits on a single transfer,
+	 * including 3 bytes for the header. */
+	if (vlen <= buflen - 3) {
+		if (func)
+			plen = enc_write_req(handle, value, vlen, buf,
+								buflen);
+		else
+			plen = enc_write_cmd(handle, value, vlen, buf,
+								buflen);
+
+		return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
 							user_data, NULL);
+	}
+
+	/* Write Long Characteristic Values */
+	long_write = g_try_new0(struct write_long_data, 1);
+	if (long_write == NULL)
+		return 0;
+
+	long_write->attrib = attrib;
+	long_write->func = func;
+	long_write->user_data = user_data;
+	long_write->handle = handle;
+	long_write->value = g_memdup(value,vlen);
+	long_write->vlen = vlen;
+
+	return prepare_write(attrib, handle, long_write->offset, value, vlen,
+							func, long_write);
 }
 
 guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 1f23522..a11ca9f 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -371,7 +371,7 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
 		goto done;
 	}
 
-	if (!dec_write_resp(pdu, plen)) {
+	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
 		g_printerr("Protocol error\n");
 		goto done;
 	}
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 3657798..6cd8bd5 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -588,7 +588,7 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
 		return;
 	}
 
-	if (!dec_write_resp(pdu, plen)) {
+	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
 		printf("Protocol error\n");
 		return;
 	}
-- 
1.7.9.5


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

* Re: [PATCH BlueZ v2 1/3] att: Add prepare write support
  2012-07-30 17:34 ` [PATCH BlueZ v2 " Eder Ruiz Maria
@ 2012-08-15  9:27   ` Johan Hedberg
  0 siblings, 0 replies; 10+ messages in thread
From: Johan Hedberg @ 2012-08-15  9:27 UTC (permalink / raw)
  To: Eder Ruiz Maria; +Cc: linux-bluetooth

Hi Eder,

On Mon, Jul 30, 2012, Eder Ruiz Maria wrote:
> Add functions for encoding/decoding Prepare Write Request and
> Response PDUs.
> ---
>  attrib/att.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  attrib/att.h |    5 +++++
>  2 files changed, 59 insertions(+)

All three patches have been applied. Thanks.

I also went ahead and finally updated the entire attrib code base to use
proper size_t, ssize_t, off_t etc variables where appropriate. This
means that any unapplied attrib patches may need rebasing (and fixing to
follow the same convention).

Johan

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

end of thread, other threads:[~2012-08-15  9:27 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-27 20:29 [PATCH BlueZ 1/3] att: Add prepare write support Eder Ruiz Maria
2012-07-27 20:29 ` [PATCH BlueZ 2/3] att: Add encode/decode execute " Eder Ruiz Maria
2012-07-27 20:29 ` [PATCH BlueZ 3/3] gatt: Add support to GATT Write Long Characteristic Eder Ruiz Maria
2012-07-29  1:47 ` [PATCH BlueZ 1/3] att: Add prepare write support Sergio Correia
2012-07-30 10:35   ` Anderson Lizardo
2012-07-30 10:55 ` Johan Hedberg
2012-07-30 17:34 ` [PATCH BlueZ v2 " Eder Ruiz Maria
2012-08-15  9:27   ` Johan Hedberg
2012-07-30 17:38 ` [PATCH BlueZ v2 2/3] att: Add encode/decode execute " Eder Ruiz Maria
2012-07-30 17:38 ` [PATCH BlueZ v2 3/3] gatt: Add support to GATT Write Long Characteristic Eder Ruiz Maria

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