All of lore.kernel.org
 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 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.