All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Implement Compound GATT Procedures and Long Reads
@ 2011-01-05  0:01 Brian Gix
  2011-01-05  0:01 ` [PATCH 1/2] Fix g_attrib_send() to include a new ID parameter Brian Gix
  2011-01-05  0:01 ` [PATCH 2/2] Fix gatt_read_char() to support long Attrib Values Brian Gix
  0 siblings, 2 replies; 6+ messages in thread
From: Brian Gix @ 2011-01-05  0:01 UTC (permalink / raw)
  Cc: claudio.takahasi, padovan, rshaffer, linux-bluetooth

These two patches implement Compound GATT procedures, so that they
are executed atomically, and in the order that they are invoked,
regardless of whether they can be performed in a single or multiple
ATT Req/Resp transaction.

Patch 1 adds an ID parameter to g_attrib_send which shall be Zero for the
first ATT transaction, and shall be the previously returned ID for all
subsequent ATT transactions for that GATT procedure.  The underlying
code will enqueue the requested pkt at the Tail of the queue for Zero
ID'd pkts, and at the Head of the queue for non-zero (continuation)
pkts. The queue is then only services (next item sent) after the
callbacks have been made, to allow any continuation pkts to be created.


Patch 2 then uses this new feature of g_attrib_send to implement
support for Long Attribute Reads (using READ_BLOB).



-- 
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

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

* [PATCH 1/2] Fix g_attrib_send() to include a new ID parameter
  2011-01-05  0:01 [PATCH 0/2] Implement Compound GATT Procedures and Long Reads Brian Gix
@ 2011-01-05  0:01 ` Brian Gix
  2011-01-06 17:17   ` Claudio Takahasi
  2011-01-05  0:01 ` [PATCH 2/2] Fix gatt_read_char() to support long Attrib Values Brian Gix
  1 sibling, 1 reply; 6+ messages in thread
From: Brian Gix @ 2011-01-05  0:01 UTC (permalink / raw)
  Cc: claudio.takahasi, padovan, rshaffer, linux-bluetooth, Brian Gix

Overall purpose of change is to enable a GATT procedure to be
	executed atomically, even if it requires multiple ATT
	request/response transactions.

Fix g_attrib_send() to include an ID parameter, if the pkt to
	be sent should be added to the Head of the pkt queue.
	If the ID is Zero, legacy functionality is maintained,
	and the pkt will be added at the tail of the queuer, and
	a new ID will be generated, and returned to the caller. If
	ID is non-zero, the pkt will be added to the head of the
	queue, with the ID value requested, which will also be
	returned to the caller.

Fix received_data() to not service the send queue until after the
	received data has been processed by calling the cmd->func()
	callback, to allow the callback to insert another pkt on
	the head of the queue.

Fix all callers of g_attrib_send() to include new parameter.
---
 attrib/client.c     |    2 +-
 attrib/gatt.c       |   12 ++++++------
 attrib/gattrib.c    |   22 +++++++++++++++-------
 attrib/gattrib.h    |    7 ++++---
 attrib/gatttool.c   |    2 +-
 src/attrib-server.c |    2 +-
 6 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 10bbf7d..4301082 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -295,7 +295,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
 	switch (pdu[0]) {
 	case ATT_OP_HANDLE_IND:
 		olen = enc_confirmation(opdu, sizeof(opdu));
-		g_attrib_send(gatt->attrib, opdu[0], opdu, olen,
+		g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen,
 						NULL, NULL, NULL);
 	case ATT_OP_HANDLE_NOTIFY:
 		if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index bca8b49..320759f 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -68,7 +68,7 @@ guint gatt_discover_primary(GAttrib *attrib, uint16_t start, uint16_t end,
 	if (plen == 0)
 		return 0;
 
-	return g_attrib_send(attrib, op, pdu, plen, func, user_data, NULL);
+	return g_attrib_send(attrib, 0, op, pdu, plen, func, user_data, NULL);
 }
 
 guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
@@ -93,7 +93,7 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
 	if (plen == 0)
 		return 0;
 
-	return g_attrib_send(attrib, ATT_OP_READ_BY_TYPE_REQ,
+	return g_attrib_send(attrib, 0, ATT_OP_READ_BY_TYPE_REQ,
 					pdu, plen, func, user_data, NULL);
 }
 
@@ -104,7 +104,7 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
 	guint16 plen;
 
 	plen = enc_read_req(handle, pdu, sizeof(pdu));
-	return g_attrib_send(attrib, ATT_OP_READ_REQ, pdu, plen, func,
+	return g_attrib_send(attrib, 0, ATT_OP_READ_REQ, pdu, plen, func,
 							user_data, NULL);
 }
 
@@ -115,7 +115,7 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
 	guint16 plen;
 
 	plen = enc_write_req(handle, value, vlen, pdu, sizeof(pdu));
-	return g_attrib_send(attrib, ATT_OP_WRITE_REQ, pdu, plen, func,
+	return g_attrib_send(attrib, 0, ATT_OP_WRITE_REQ, pdu, plen, func,
 							user_data, NULL);
 }
 
@@ -129,7 +129,7 @@ guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
 	if (plen == 0)
 		return 0;
 
-	return g_attrib_send(attrib, ATT_OP_FIND_INFO_REQ, pdu, plen, func,
+	return g_attrib_send(attrib, 0, ATT_OP_FIND_INFO_REQ, pdu, plen, func,
 							user_data, NULL);
 }
 
@@ -140,6 +140,6 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
 	guint16 plen;
 
 	plen = enc_write_cmd(handle, value, vlen, pdu, sizeof(pdu));
-	return g_attrib_send(attrib, ATT_OP_WRITE_CMD, pdu, plen, NULL,
+	return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, pdu, plen, NULL,
 							user_data, notify);
 }
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 9268001..79ee2e9 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -286,6 +286,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 	uint8_t buf[512], status;
 	gsize len;
 	GIOStatus iostat;
+	gboolean qempty;
 
 	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
 		attrib->read_watch = 0;
@@ -333,8 +334,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 	status = 0;
 
 done:
-	if (attrib->queue && g_queue_is_empty(attrib->queue) == FALSE)
-		wake_up_sender(attrib);
+	qempty = attrib->queue == NULL || g_queue_is_empty(attrib->queue);
 
 	if (cmd) {
 		if (cmd->func)
@@ -343,6 +343,9 @@ done:
 		command_destroy(cmd);
 	}
 
+	if (!qempty)
+		wake_up_sender(attrib);
+
 	return TRUE;
 }
 
@@ -368,9 +371,9 @@ GAttrib *g_attrib_new(GIOChannel *io)
 	return g_attrib_ref(attrib);
 }
 
-guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
-				guint16 len, GAttribResultFunc func,
-				gpointer user_data, GDestroyNotify notify)
+guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
+		const guint8 *pdu, guint16 len, GAttribResultFunc func,
+		gpointer user_data, GDestroyNotify notify)
 {
 	struct command *c;
 
@@ -386,9 +389,14 @@ guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
 	c->func = func;
 	c->user_data = user_data;
 	c->notify = notify;
-	c->id = ++attrib->next_cmd_id;
 
-	g_queue_push_tail(attrib->queue, c);
+	if (id) {
+		c->id = id;
+		g_queue_push_head(attrib->queue, c);
+	} else {
+		c->id = ++attrib->next_cmd_id;
+		g_queue_push_tail(attrib->queue, c);
+	}
 
 	if (g_queue_get_length(attrib->queue) == 1)
 		wake_up_sender(attrib);
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index 0940289..1a966a7 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -50,9 +50,10 @@ gboolean g_attrib_set_disconnect_function(GAttrib *attrib,
 gboolean g_attrib_set_destroy_function(GAttrib *attrib,
 		GDestroyNotify destroy, gpointer user_data);
 
-guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
-				guint16 len, GAttribResultFunc func,
-				gpointer user_data, GDestroyNotify notify);
+guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
+			const guint8 *pdu, guint16 len, GAttribResultFunc func,
+			gpointer user_data, GDestroyNotify notify);
+
 gboolean g_attrib_cancel(GAttrib *attrib, guint id);
 gboolean g_attrib_cancel_all(GAttrib *attrib);
 
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index a234e36..a6f92db 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -272,7 +272,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 	olen = enc_confirmation(opdu, sizeof(opdu));
 
 	if (olen > 0)
-		g_attrib_send(attrib, opdu[0], opdu, olen, NULL, NULL, NULL);
+		g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
 }
 
 static gboolean listen_start(gpointer user_data)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index cbc01ee..aee2ace 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -694,7 +694,7 @@ done:
 	if (status)
 		length = enc_error_resp(ipdu[0], 0x0000, status, opdu, channel->mtu);
 
-	g_attrib_send(channel->attrib, opdu[0], opdu, length,
+	g_attrib_send(channel->attrib, 0, opdu[0], opdu, length,
 							NULL, NULL, NULL);
 }
 
-- 
1.7.1
-- 
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

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

* [PATCH 2/2] Fix gatt_read_char() to support long Attrib Values
  2011-01-05  0:01 [PATCH 0/2] Implement Compound GATT Procedures and Long Reads Brian Gix
  2011-01-05  0:01 ` [PATCH 1/2] Fix g_attrib_send() to include a new ID parameter Brian Gix
@ 2011-01-05  0:01 ` Brian Gix
  2011-01-06 17:31   ` Claudio Takahasi
  1 sibling, 1 reply; 6+ messages in thread
From: Brian Gix @ 2011-01-05  0:01 UTC (permalink / raw)
  Cc: claudio.takahasi, padovan, rshaffer, linux-bluetooth, Brian Gix

Fix gatt_read_char() to support long Attribute Values by recognizing
	that results longer that 21 octets may include data beyond
	what has been returned with the first read. Extra data is
	obtained by issuing READ_BLOB requests until either a
	result is returned shorter than 22 octets, or an error
	is recieved indicating that no further data is available.
	The API for this function has not changed.
---
 attrib/gatt.c |  134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/attrib/gatt.c b/attrib/gatt.c
index 320759f..304c2b1 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -97,15 +97,145 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
 					pdu, plen, func, user_data, NULL);
 }
 
+struct read_long_data {
+	GAttrib *attrib;
+	GAttribResultFunc func;
+	gpointer user_data;
+	guint8 *buffer;
+	guint16 size;
+	guint16 handle;
+	guint id;
+	guint8 ref;
+};
+
+static void read_long_destroy(gpointer user_data)
+{
+	struct read_long_data *long_read = user_data;
+
+	if (--long_read->ref)
+		return;
+
+	if (long_read->buffer != NULL)
+		g_free(long_read->buffer);
+
+	g_free(long_read);
+}
+
+static void read_blob_helper(guint8 status, const guint8 *rpdu, guint16 rlen,
+							gpointer user_data)
+{
+	struct read_long_data *long_read = user_data;
+	uint8_t pdu[ATT_DEFAULT_MTU];
+	guint8 *tmp;
+	guint16 plen;
+	guint id;
+
+	if (status == ATT_ECODE_ATTR_NOT_LONG ||
+					status == ATT_ECODE_INVALID_OFFSET) {
+		status = 0;
+		goto done;
+	}
+
+	if (status != 0 || rlen == 1)
+		goto done;
+
+	tmp = g_try_realloc(long_read->buffer, long_read->size + rlen - 1);
+
+	if (tmp == NULL) {
+		status = ATT_ECODE_INSUFF_RESOURCES;
+		goto done;
+	}
+
+	memcpy(&tmp[long_read->size], &rpdu[1], rlen - 1);
+	long_read->buffer = tmp;
+	long_read->size += rlen - 1;
+
+	if (rlen < ATT_DEFAULT_MTU)
+		goto done;
+
+	plen = enc_read_blob_req(long_read->handle, long_read->size - 1,
+							pdu, sizeof(pdu));
+	id = g_attrib_send(long_read->attrib, long_read->id,
+				ATT_OP_READ_BLOB_REQ, pdu, plen,
+				read_blob_helper, long_read, read_long_destroy);
+
+	if (id != 0) {
+		long_read->ref++;
+		return;
+	}
+
+	status = ATT_ECODE_IO;
+
+done:
+	long_read->func(status, long_read->buffer, long_read->size,
+							long_read->user_data);
+}
+
+static void read_char_helper(guint8 status, const guint8 *rpdu,
+					guint16 rlen, gpointer user_data)
+{
+	struct read_long_data *long_read = user_data;
+	uint8_t pdu[ATT_DEFAULT_MTU];
+	guint16 plen;
+	guint id;
+
+	if (status != 0 || rlen < ATT_DEFAULT_MTU)
+		goto done;
+
+	long_read->buffer = g_malloc(rlen);
+
+	if (long_read->buffer == NULL)
+		goto done;
+
+	memcpy(long_read->buffer, rpdu, rlen);
+	long_read->size = rlen;
+
+	plen = enc_read_blob_req(long_read->handle, rlen - 1, pdu, sizeof(pdu));
+	id = g_attrib_send(long_read->attrib, long_read->id,
+			ATT_OP_READ_BLOB_REQ, pdu, plen, read_blob_helper,
+			long_read, read_long_destroy);
+
+	if (id != 0) {
+		long_read->ref++;
+		return;
+	}
+
+	status = ATT_ECODE_IO;
+
+done:
+	long_read->func(status, rpdu, rlen, long_read->user_data);
+}
+
 guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
 							gpointer user_data)
 {
 	uint8_t pdu[ATT_DEFAULT_MTU];
 	guint16 plen;
+	guint id;
+	struct read_long_data *long_read;
+
+	long_read = g_try_new0(struct read_long_data, 1);
+
+	if (long_read == NULL)
+		return 0;
+
+	long_read->attrib = attrib;
+	long_read->func = func;
+	long_read->user_data = user_data;
+	long_read->handle = handle;
 
 	plen = enc_read_req(handle, pdu, sizeof(pdu));
-	return g_attrib_send(attrib, 0, ATT_OP_READ_REQ, pdu, plen, func,
-							user_data, NULL);
+	id = g_attrib_send(attrib, 0, ATT_OP_READ_REQ, pdu, plen,
+				read_char_helper, long_read, read_long_destroy);
+
+	if (id == 0)
+		g_free(long_read);
+	else {
+		long_read->ref++;
+		long_read->id = id;
+	}
+
+	return id;
 }
 
 guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
-- 
1.7.1
-- 
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

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

* Re: [PATCH 1/2] Fix g_attrib_send() to include a new ID parameter
  2011-01-05  0:01 ` [PATCH 1/2] Fix g_attrib_send() to include a new ID parameter Brian Gix
@ 2011-01-06 17:17   ` Claudio Takahasi
  0 siblings, 0 replies; 6+ messages in thread
From: Claudio Takahasi @ 2011-01-06 17:17 UTC (permalink / raw)
  To: Brian Gix; +Cc: padovan, rshaffer, linux-bluetooth

Hi Brian,

On Tue, Jan 4, 2011 at 9:01 PM, Brian Gix <bgix@codeaurora.org> wrote:
> Overall purpose of change is to enable a GATT procedure to be
>        executed atomically, even if it requires multiple ATT
>        request/response transactions.
>
> Fix g_attrib_send() to include an ID parameter, if the pkt to
>        be sent should be added to the Head of the pkt queue.
>        If the ID is Zero, legacy functionality is maintained,
>        and the pkt will be added at the tail of the queuer, and
>        a new ID will be generated, and returned to the caller. If
>        ID is non-zero, the pkt will be added to the head of the
>        queue, with the ID value requested, which will also be
>        returned to the caller.
>
> Fix received_data() to not service the send queue until after the
>        received data has been processed by calling the cmd->func()
>        callback, to allow the callback to insert another pkt on
>        the head of the queue.
>

We don't use tabs in the comments.

> Fix all callers of g_attrib_send() to include new parameter.
> ---
>  attrib/client.c     |    2 +-
>  attrib/gatt.c       |   12 ++++++------
>  attrib/gattrib.c    |   22 +++++++++++++++-------
>  attrib/gattrib.h    |    7 ++++---
>  attrib/gatttool.c   |    2 +-
>  src/attrib-server.c |    2 +-
>  6 files changed, 28 insertions(+), 19 deletions(-)
>
> diff --git a/attrib/client.c b/attrib/client.c
> index 10bbf7d..4301082 100644
> --- a/attrib/client.c
> +++ b/attrib/client.c
> @@ -295,7 +295,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
>        switch (pdu[0]) {
>        case ATT_OP_HANDLE_IND:
>                olen = enc_confirmation(opdu, sizeof(opdu));
> -               g_attrib_send(gatt->attrib, opdu[0], opdu, olen,
> +               g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen,
>                                                NULL, NULL, NULL);
>        case ATT_OP_HANDLE_NOTIFY:
>                if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
> diff --git a/attrib/gatt.c b/attrib/gatt.c
> index bca8b49..320759f 100644
> --- a/attrib/gatt.c
> +++ b/attrib/gatt.c
> @@ -68,7 +68,7 @@ guint gatt_discover_primary(GAttrib *attrib, uint16_t start, uint16_t end,
>        if (plen == 0)
>                return 0;
>
> -       return g_attrib_send(attrib, op, pdu, plen, func, user_data, NULL);
> +       return g_attrib_send(attrib, 0, op, pdu, plen, func, user_data, NULL);
>  }
>
>  guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
> @@ -93,7 +93,7 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
>        if (plen == 0)
>                return 0;
>
> -       return g_attrib_send(attrib, ATT_OP_READ_BY_TYPE_REQ,
> +       return g_attrib_send(attrib, 0, ATT_OP_READ_BY_TYPE_REQ,
>                                        pdu, plen, func, user_data, NULL);
>  }
>
> @@ -104,7 +104,7 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
>        guint16 plen;
>
>        plen = enc_read_req(handle, pdu, sizeof(pdu));
> -       return g_attrib_send(attrib, ATT_OP_READ_REQ, pdu, plen, func,
> +       return g_attrib_send(attrib, 0, ATT_OP_READ_REQ, pdu, plen, func,
>                                                        user_data, NULL);
>  }
>
> @@ -115,7 +115,7 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
>        guint16 plen;
>
>        plen = enc_write_req(handle, value, vlen, pdu, sizeof(pdu));
> -       return g_attrib_send(attrib, ATT_OP_WRITE_REQ, pdu, plen, func,
> +       return g_attrib_send(attrib, 0, ATT_OP_WRITE_REQ, pdu, plen, func,
>                                                        user_data, NULL);
>  }
>
> @@ -129,7 +129,7 @@ guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
>        if (plen == 0)
>                return 0;
>
> -       return g_attrib_send(attrib, ATT_OP_FIND_INFO_REQ, pdu, plen, func,
> +       return g_attrib_send(attrib, 0, ATT_OP_FIND_INFO_REQ, pdu, plen, func,
>                                                        user_data, NULL);
>  }
>
> @@ -140,6 +140,6 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
>        guint16 plen;
>
>        plen = enc_write_cmd(handle, value, vlen, pdu, sizeof(pdu));
> -       return g_attrib_send(attrib, ATT_OP_WRITE_CMD, pdu, plen, NULL,
> +       return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, pdu, plen, NULL,
>                                                        user_data, notify);
>  }
> diff --git a/attrib/gattrib.c b/attrib/gattrib.c
> index 9268001..79ee2e9 100644
> --- a/attrib/gattrib.c
> +++ b/attrib/gattrib.c
> @@ -286,6 +286,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
>        uint8_t buf[512], status;
>        gsize len;
>        GIOStatus iostat;
> +       gboolean qempty;
>
>        if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
>                attrib->read_watch = 0;
> @@ -333,8 +334,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
>        status = 0;
>
>  done:
> -       if (attrib->queue && g_queue_is_empty(attrib->queue) == FALSE)
> -               wake_up_sender(attrib);
> +       qempty = attrib->queue == NULL || g_queue_is_empty(attrib->queue);
>
>        if (cmd) {
>                if (cmd->func)
> @@ -343,6 +343,9 @@ done:
>                command_destroy(cmd);
>        }
>
> +       if (!qempty)
> +               wake_up_sender(attrib);
> +
>        return TRUE;
>  }
>
> @@ -368,9 +371,9 @@ GAttrib *g_attrib_new(GIOChannel *io)
>        return g_attrib_ref(attrib);
>  }
>
> -guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> -                               guint16 len, GAttribResultFunc func,
> -                               gpointer user_data, GDestroyNotify notify)
> +guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
> +               const guint8 *pdu, guint16 len, GAttribResultFunc func,
> +               gpointer user_data, GDestroyNotify notify)
Missing tab here.

>  {
>        struct command *c;
>
> @@ -386,9 +389,14 @@ guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
>        c->func = func;
>        c->user_data = user_data;
>        c->notify = notify;
> -       c->id = ++attrib->next_cmd_id;
>
> -       g_queue_push_tail(attrib->queue, c);
> +       if (id) {
> +               c->id = id;
> +               g_queue_push_head(attrib->queue, c);
> +       } else {
> +               c->id = ++attrib->next_cmd_id;
> +               g_queue_push_tail(attrib->queue, c);
> +       }
>
>        if (g_queue_get_length(attrib->queue) == 1)
>                wake_up_sender(attrib);
> diff --git a/attrib/gattrib.h b/attrib/gattrib.h
> index 0940289..1a966a7 100644
> --- a/attrib/gattrib.h
> +++ b/attrib/gattrib.h
> @@ -50,9 +50,10 @@ gboolean g_attrib_set_disconnect_function(GAttrib *attrib,
>  gboolean g_attrib_set_destroy_function(GAttrib *attrib,
>                GDestroyNotify destroy, gpointer user_data);
>
> -guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
> -                               guint16 len, GAttribResultFunc func,
> -                               gpointer user_data, GDestroyNotify notify);
> +guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
> +                       const guint8 *pdu, guint16 len, GAttribResultFunc func,
> +                       gpointer user_data, GDestroyNotify notify);
> +
Missing tab here.

>  gboolean g_attrib_cancel(GAttrib *attrib, guint id);
>  gboolean g_attrib_cancel_all(GAttrib *attrib);
>
> diff --git a/attrib/gatttool.c b/attrib/gatttool.c
> index a234e36..a6f92db 100644
> --- a/attrib/gatttool.c
> +++ b/attrib/gatttool.c
> @@ -272,7 +272,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
>        olen = enc_confirmation(opdu, sizeof(opdu));
>
>        if (olen > 0)
> -               g_attrib_send(attrib, opdu[0], opdu, olen, NULL, NULL, NULL);
> +               g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
>  }
>
>  static gboolean listen_start(gpointer user_data)
> diff --git a/src/attrib-server.c b/src/attrib-server.c
> index cbc01ee..aee2ace 100644
> --- a/src/attrib-server.c
> +++ b/src/attrib-server.c
> @@ -694,7 +694,7 @@ done:
>        if (status)
>                length = enc_error_resp(ipdu[0], 0x0000, status, opdu, channel->mtu);
>
> -       g_attrib_send(channel->attrib, opdu[0], opdu, length,
> +       g_attrib_send(channel->attrib, 0, opdu[0], opdu, length,
>                                                        NULL, NULL, NULL);
>  }
>
> --
> 1.7.1
> --
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
>

We need only to avoid calling g_attrib_send outside gatt.c passing id
!=0, otherwise it may break the commands sequence.
Could you please change the the attribute server adding a service with
long attributes?

Regards,
Claudio.

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

* Re: [PATCH 2/2] Fix gatt_read_char() to support long Attrib Values
  2011-01-05  0:01 ` [PATCH 2/2] Fix gatt_read_char() to support long Attrib Values Brian Gix
@ 2011-01-06 17:31   ` Claudio Takahasi
  0 siblings, 0 replies; 6+ messages in thread
From: Claudio Takahasi @ 2011-01-06 17:31 UTC (permalink / raw)
  To: Brian Gix; +Cc: padovan, rshaffer, linux-bluetooth

SGkgQnJpYW4sCgpPbiBUdWUsIEphbiA0LCAyMDExIGF0IDk6MDEgUE0sIEJyaWFuIEdpeCA8Ymdp
eEBjb2RlYXVyb3JhLm9yZz4gd3JvdGU6Cj4gRml4IGdhdHRfcmVhZF9jaGFyKCkgdG8gc3VwcG9y
dCBsb25nIEF0dHJpYnV0ZSBWYWx1ZXMgYnkgcmVjb2duaXppbmcKPiDCoCDCoCDCoCDCoHRoYXQg
cmVzdWx0cyBsb25nZXIgdGhhdCAyMSBvY3RldHMgbWF5IGluY2x1ZGUgZGF0YSBiZXlvbmQKPiDC
oCDCoCDCoCDCoHdoYXQgaGFzIGJlZW4gcmV0dXJuZWQgd2l0aCB0aGUgZmlyc3QgcmVhZC4gRXh0
cmEgZGF0YSBpcwo+IMKgIMKgIMKgIMKgb2J0YWluZWQgYnkgaXNzdWluZyBSRUFEX0JMT0IgcmVx
dWVzdHMgdW50aWwgZWl0aGVyIGEKPiDCoCDCoCDCoCDCoHJlc3VsdCBpcyByZXR1cm5lZCBzaG9y
dGVyIHRoYW4gMjIgb2N0ZXRzLCBvciBhbiBlcnJvcgo+IMKgIMKgIMKgIMKgaXMgcmVjaWV2ZWQg
aW5kaWNhdGluZyB0aGF0IG5vIGZ1cnRoZXIgZGF0YSBpcyBhdmFpbGFibGUuCj4gwqAgwqAgwqAg
wqBUaGUgQVBJIGZvciB0aGlzIGZ1bmN0aW9uIGhhcyBub3QgY2hhbmdlZC4KTm8gdGFicyBoZXJl
LgoKPiAtLS0KPiDCoGF0dHJpYi9nYXR0LmMgfCDCoDEzNCArKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy0KPiDCoDEgZmlsZXMgY2hhbmdlZCwg
MTMyIGluc2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0pCj4KPiBkaWZmIC0tZ2l0IGEvYXR0cmli
L2dhdHQuYyBiL2F0dHJpYi9nYXR0LmMKPiBpbmRleCAzMjA3NTlmLi4zMDRjMmIxIDEwMDY0NAo+
IC0tLSBhL2F0dHJpYi9nYXR0LmMKPiArKysgYi9hdHRyaWIvZ2F0dC5jCj4gQEAgLTk3LDE1ICs5
NywxNDUgQEAgZ3VpbnQgZ2F0dF9yZWFkX2NoYXJfYnlfdXVpZChHQXR0cmliICphdHRyaWIsIHVp
bnQxNl90IHN0YXJ0LCB1aW50MTZfdCBlbmQsCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwZHUsIHBsZW4sIGZ1bmMsIHVzZXJfZGF0
YSwgTlVMTCk7Cj4gwqB9Cj4KPiArc3RydWN0IHJlYWRfbG9uZ19kYXRhIHsKPiArIMKgIMKgIMKg
IEdBdHRyaWIgKmF0dHJpYjsKPiArIMKgIMKgIMKgIEdBdHRyaWJSZXN1bHRGdW5jIGZ1bmM7Cj4g
KyDCoCDCoCDCoCBncG9pbnRlciB1c2VyX2RhdGE7Cj4gKyDCoCDCoCDCoCBndWludDggKmJ1ZmZl
cjsKPiArIMKgIMKgIMKgIGd1aW50MTYgc2l6ZTsKPiArIMKgIMKgIMKgIGd1aW50MTYgaGFuZGxl
Owo+ICsgwqAgwqAgwqAgZ3VpbnQgaWQ7Cj4gKyDCoCDCoCDCoCBndWludDggcmVmOwo+ICt9Owo+
ICsKPiArc3RhdGljIHZvaWQgcmVhZF9sb25nX2Rlc3Ryb3koZ3BvaW50ZXIgdXNlcl9kYXRhKQo+
ICt7Cj4gKyDCoCDCoCDCoCBzdHJ1Y3QgcmVhZF9sb25nX2RhdGEgKmxvbmdfcmVhZCA9IHVzZXJf
ZGF0YTsKPiArCj4gKyDCoCDCoCDCoCBpZiAoLS1sb25nX3JlYWQtPnJlZikKPiArIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIHJldHVybjsKdXNlIGdfYXRvbWljX2ludF9kZWNfYW5kX3Rlc3QKCj4gKwo+
ICsgwqAgwqAgwqAgaWYgKGxvbmdfcmVhZC0+YnVmZmVyICE9IE5VTEwpCj4gKyDCoCDCoCDCoCDC
oCDCoCDCoCDCoCBnX2ZyZWUobG9uZ19yZWFkLT5idWZmZXIpOwo+ICsKPiArIMKgIMKgIMKgIGdf
ZnJlZShsb25nX3JlYWQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCByZWFkX2Jsb2JfaGVscGVy
KGd1aW50OCBzdGF0dXMsIGNvbnN0IGd1aW50OCAqcnBkdSwgZ3VpbnQxNiBybGVuLAo+ICsgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgZ3BvaW50ZXIgdXNlcl9kYXRhKQo+ICt7Cj4gKyDCoCDCoCDC
oCBzdHJ1Y3QgcmVhZF9sb25nX2RhdGEgKmxvbmdfcmVhZCA9IHVzZXJfZGF0YTsKPiArIMKgIMKg
IMKgIHVpbnQ4X3QgcGR1W0FUVF9ERUZBVUxUX01UVV07Cj4gKyDCoCDCoCDCoCBndWludDggKnRt
cDsKPiArIMKgIMKgIMKgIGd1aW50MTYgcGxlbjsKPiArIMKgIMKgIMKgIGd1aW50IGlkOwo+ICsK
PiArIMKgIMKgIMKgIGlmIChzdGF0dXMgPT0gQVRUX0VDT0RFX0FUVFJfTk9UX0xPTkcgfHwKPiAr
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IHN0YXR1cyA9PSBBVFRfRUNPREVfSU5WQUxJRF9PRkZTRVQpIHsKPiArIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIHN0YXR1cyA9IDA7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBnb3RvIGRvbmU7Cj4g
KyDCoCDCoCDCoCB9Cj4gKwo+ICsgwqAgwqAgwqAgaWYgKHN0YXR1cyAhPSAwIHx8IHJsZW4gPT0g
MSkKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGdvdG8gZG9uZTsKPiArCj4gKyDCoCDCoCDCoCB0
bXAgPSBnX3RyeV9yZWFsbG9jKGxvbmdfcmVhZC0+YnVmZmVyLCBsb25nX3JlYWQtPnNpemUgKyBy
bGVuIC0gMSk7Cj4gKwo+ICsgwqAgwqAgwqAgaWYgKHRtcCA9PSBOVUxMKSB7Cj4gKyDCoCDCoCDC
oCDCoCDCoCDCoCDCoCBzdGF0dXMgPSBBVFRfRUNPREVfSU5TVUZGX1JFU09VUkNFUzsKPiArIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIGdvdG8gZG9uZTsKPiArIMKgIMKgIMKgIH0KPiArCj4gKyDCoCDC
oCDCoCBtZW1jcHkoJnRtcFtsb25nX3JlYWQtPnNpemVdLCAmcnBkdVsxXSwgcmxlbiAtIDEpOwo+
ICsgwqAgwqAgwqAgbG9uZ19yZWFkLT5idWZmZXIgPSB0bXA7Cj4gKyDCoCDCoCDCoCBsb25nX3Jl
YWQtPnNpemUgKz0gcmxlbiAtIDE7Ck1heWJlIHVzaW5nIEdCeXRlQXJyYXkgd2lsbCBtYWtlIHlv
dXIgY29kZSBzaW1wbGVyLgoKPiArCj4gKyDCoCDCoCDCoCBpZiAocmxlbiA8IEFUVF9ERUZBVUxU
X01UVSkKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGdvdG8gZG9uZTsKCkZvciBub3cgaXQgaXMg
ZmluZSBmb3IgdGVzdGluZy4gQnV0IGl0IG5lZWRzIHRvIGJlIGZpeGVkIGxhdGVyLCBNVFUKY2Fu
IGNoYW5nZSBhZnRlciB0aGUgTVRVIG5lZ290aWF0aW9uLCB0aGUgbmV3IHZhbHVlIGNvdWxkIGJl
IGFjY2Vzc2VkCnVzaW5nIGEgZ2V0c29ja29wdCwgcGFzc2luZyB0aGUgdmFsdWUgdG8gZ2F0dF8q
IGZ1bmN0aW9ucyBvciB1c2luZyBhCkdBdHRyaWIgZnVuY3Rpb24uCgo+ICsKPiArIMKgIMKgIMKg
IHBsZW4gPSBlbmNfcmVhZF9ibG9iX3JlcShsb25nX3JlYWQtPmhhbmRsZSwgbG9uZ19yZWFkLT5z
aXplIC0gMSwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHBkdSwgc2l6ZW9mKHBkdSkpOwo+
ICsgwqAgwqAgwqAgaWQgPSBnX2F0dHJpYl9zZW5kKGxvbmdfcmVhZC0+YXR0cmliLCBsb25nX3Jl
YWQtPmlkLAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
QVRUX09QX1JFQURfQkxPQl9SRVEsIHBkdSwgcGxlbiwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHJlYWRfYmxvYl9oZWxwZXIsIGxvbmdfcmVhZCwgcmVh
ZF9sb25nX2Rlc3Ryb3kpOwo+ICsKPiArIMKgIMKgIMKgIGlmIChpZCAhPSAwKSB7Cj4gKyDCoCDC
oCDCoCDCoCDCoCDCoCDCoCBsb25nX3JlYWQtPnJlZisrOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgcmV0dXJuOwo+ICsgwqAgwqAgwqAgfQo+ICsKPiArIMKgIMKgIMKgIHN0YXR1cyA9IEFUVF9F
Q09ERV9JTzsKPiArCj4gK2RvbmU6Cj4gKyDCoCDCoCDCoCBsb25nX3JlYWQtPmZ1bmMoc3RhdHVz
LCBsb25nX3JlYWQtPmJ1ZmZlciwgbG9uZ19yZWFkLT5zaXplLAo+ICsgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgbG9uZ19yZWFkLT51c2VyX2RhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBy
ZWFkX2NoYXJfaGVscGVyKGd1aW50OCBzdGF0dXMsIGNvbnN0IGd1aW50OCAqcnBkdSwKPiArIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGd1
aW50MTYgcmxlbiwgZ3BvaW50ZXIgdXNlcl9kYXRhKQo+ICt7Cj4gKyDCoCDCoCDCoCBzdHJ1Y3Qg
cmVhZF9sb25nX2RhdGEgKmxvbmdfcmVhZCA9IHVzZXJfZGF0YTsKPiArIMKgIMKgIMKgIHVpbnQ4
X3QgcGR1W0FUVF9ERUZBVUxUX01UVV07Cj4gKyDCoCDCoCDCoCBndWludDE2IHBsZW47Cj4gKyDC
oCDCoCDCoCBndWludCBpZDsKPiArCj4gKyDCoCDCoCDCoCBpZiAoc3RhdHVzICE9IDAgfHwgcmxl
biA8IEFUVF9ERUZBVUxUX01UVSkKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGdvdG8gZG9uZTsK
PiArCj4gKyDCoCDCoCDCoCBsb25nX3JlYWQtPmJ1ZmZlciA9IGdfbWFsbG9jKHJsZW4pOwo+ICsK
PiArIMKgIMKgIMKgIGlmIChsb25nX3JlYWQtPmJ1ZmZlciA9PSBOVUxMKQo+ICsgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgZ290byBkb25lOwo+ICsKPiArIMKgIMKgIMKgIG1lbWNweShsb25nX3JlYWQt
PmJ1ZmZlciwgcnBkdSwgcmxlbik7Cj4gKyDCoCDCoCDCoCBsb25nX3JlYWQtPnNpemUgPSBybGVu
Owo+ICsKPiArIMKgIMKgIMKgIHBsZW4gPSBlbmNfcmVhZF9ibG9iX3JlcShsb25nX3JlYWQtPmhh
bmRsZSwgcmxlbiAtIDEsIHBkdSwgc2l6ZW9mKHBkdSkpOwo+ICsgwqAgwqAgwqAgaWQgPSBnX2F0
dHJpYl9zZW5kKGxvbmdfcmVhZC0+YXR0cmliLCBsb25nX3JlYWQtPmlkLAo+ICsgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgQVRUX09QX1JFQURfQkxPQl9SRVEsIHBkdSwgcGxlbiwg
cmVhZF9ibG9iX2hlbHBlciwKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGxv
bmdfcmVhZCwgcmVhZF9sb25nX2Rlc3Ryb3kpOwo+ICsKPiArIMKgIMKgIMKgIGlmIChpZCAhPSAw
KSB7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBsb25nX3JlYWQtPnJlZisrOwpVc2UgZ19hdG9t
aWNfaW50X3ggZnVuY3Rpb24KCgo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuOwo+ICsg
wqAgwqAgwqAgfQo+ICsKPiArIMKgIMKgIMKgIHN0YXR1cyA9IEFUVF9FQ09ERV9JTzsKPiArCj4g
K2RvbmU6Cj4gKyDCoCDCoCDCoCBsb25nX3JlYWQtPmZ1bmMoc3RhdHVzLCBycGR1LCBybGVuLCBs
b25nX3JlYWQtPnVzZXJfZGF0YSk7Cj4gK30KPiArCj4gwqBndWludCBnYXR0X3JlYWRfY2hhcihH
QXR0cmliICphdHRyaWIsIHVpbnQxNl90IGhhbmRsZSwgR0F0dHJpYlJlc3VsdEZ1bmMgZnVuYywK
PiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGdwb2ludGVyIHVzZXJfZGF0YSkKPiDCoHsKPiDC
oCDCoCDCoCDCoHVpbnQ4X3QgcGR1W0FUVF9ERUZBVUxUX01UVV07Cj4gwqAgwqAgwqAgwqBndWlu
dDE2IHBsZW47Cj4gKyDCoCDCoCDCoCBndWludCBpZDsKPiArIMKgIMKgIMKgIHN0cnVjdCByZWFk
X2xvbmdfZGF0YSAqbG9uZ19yZWFkOwo+ICsKPiArIMKgIMKgIMKgIGxvbmdfcmVhZCA9IGdfdHJ5
X25ldzAoc3RydWN0IHJlYWRfbG9uZ19kYXRhLCAxKTsKPiArCj4gKyDCoCDCoCDCoCBpZiAobG9u
Z19yZWFkID09IE5VTEwpCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4gMDsKPiArCj4g
KyDCoCDCoCDCoCBsb25nX3JlYWQtPmF0dHJpYiA9IGF0dHJpYjsKPiArIMKgIMKgIMKgIGxvbmdf
cmVhZC0+ZnVuYyA9IGZ1bmM7Cj4gKyDCoCDCoCDCoCBsb25nX3JlYWQtPnVzZXJfZGF0YSA9IHVz
ZXJfZGF0YTsKPiArIMKgIMKgIMKgIGxvbmdfcmVhZC0+aGFuZGxlID0gaGFuZGxlOwo+Cj4gwqAg
wqAgwqAgwqBwbGVuID0gZW5jX3JlYWRfcmVxKGhhbmRsZSwgcGR1LCBzaXplb2YocGR1KSk7Cj4g
LSDCoCDCoCDCoCByZXR1cm4gZ19hdHRyaWJfc2VuZChhdHRyaWIsIDAsIEFUVF9PUF9SRUFEX1JF
USwgcGR1LCBwbGVuLCBmdW5jLAo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdXNlcl9kYXRh
LCBOVUxMKTsKPiArIMKgIMKgIMKgIGlkID0gZ19hdHRyaWJfc2VuZChhdHRyaWIsIDAsIEFUVF9P
UF9SRUFEX1JFUSwgcGR1LCBwbGVuLAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgcmVhZF9jaGFyX2hlbHBlciwgbG9uZ19yZWFkLCByZWFkX2xvbmdfZGVz
dHJveSk7Cj4gKwo+ICsgwqAgwqAgwqAgaWYgKGlkID09IDApCj4gKyDCoCDCoCDCoCDCoCDCoCDC
oCDCoCBnX2ZyZWUobG9uZ19yZWFkKTsKPiArIMKgIMKgIMKgIGVsc2Ugewo+ICsgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgbG9uZ19yZWFkLT5yZWYrKzsKc2FtZSBoZXJlLgoKQ2xhdWRpbwo+ICsgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgbG9uZ19yZWFkLT5pZCA9IGlkOwo+ICsgwqAgwqAgwqAgfQo+ICsK
PiArIMKgIMKgIMKgIHJldHVybiBpZDsKPiDCoH0KPgo+IMKgZ3VpbnQgZ2F0dF93cml0ZV9jaGFy
KEdBdHRyaWIgKmF0dHJpYiwgdWludDE2X3QgaGFuZGxlLCB1aW50OF90ICp2YWx1ZSwKPiAtLQo+
IDEuNy4xCj4gLS0KPiBCcmlhbiBHaXgKPiBiZ2l4QGNvZGVhdXJvcmEub3JnCj4gRW1wbG95ZWUg
b2YgUXVhbGNvbW0gSW5ub3ZhdGlvbiBDZW50ZXIsIEluYy4KPiBRdWFsY29tbSBJbm5vdmF0aW9u
IENlbnRlciwgSW5jLiBpcyBhIG1lbWJlciBvZiBDb2RlIEF1cm9yYSBGb3J1bQo+Cg==

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

* [PATCH 1/2] Fix g_attrib_send() to include a new ID parameter
  2011-01-07  0:39 [PATCH 0/2] Implement Compound GATT procedures, Long Reads Brian Gix
@ 2011-01-07  0:39 ` Brian Gix
  0 siblings, 0 replies; 6+ messages in thread
From: Brian Gix @ 2011-01-07  0:39 UTC (permalink / raw)
  Cc: vinicius.gomes, claudio.takahasi, johan.hedberg, padovan,
	linux-bluetooth, Brian Gix

Overall purpose of change is to enable a GATT procedure to be
executed atomically, even if it requires multiple ATT
request/response transactions.

Fix g_attrib_send() to include an ID parameter, if the pkt to
be sent should be added to the Head of the pkt queue.  If the
ID is Zero, legacy functionality is maintained, and the pkt will
be added at the tail of the queuer, and a new ID will be generated,
and returned to the caller. If ID is non-zero, the pkt will be
added to the head of the queue, with the ID value requested, which
will also be returned to the caller.

Fix received_data() to not service the send queue until after the
received data has been processed by calling the cmd->func()
callback, to allow the callback to insert another pkt on the head
of the queue.

Fix all callers of g_attrib_send() to include new parameter.
---
 attrib/client.c     |    2 +-
 attrib/gatt.c       |   12 ++++++------
 attrib/gattrib.c    |   22 +++++++++++++++-------
 attrib/gattrib.h    |    7 ++++---
 attrib/gatttool.c   |    2 +-
 src/attrib-server.c |    2 +-
 6 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 644cd62..7f72348 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -295,7 +295,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
 	switch (pdu[0]) {
 	case ATT_OP_HANDLE_IND:
 		olen = enc_confirmation(opdu, sizeof(opdu));
-		g_attrib_send(gatt->attrib, opdu[0], opdu, olen,
+		g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen,
 						NULL, NULL, NULL);
 	case ATT_OP_HANDLE_NOTIFY:
 		if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index bca8b49..320759f 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -68,7 +68,7 @@ guint gatt_discover_primary(GAttrib *attrib, uint16_t start, uint16_t end,
 	if (plen == 0)
 		return 0;
 
-	return g_attrib_send(attrib, op, pdu, plen, func, user_data, NULL);
+	return g_attrib_send(attrib, 0, op, pdu, plen, func, user_data, NULL);
 }
 
 guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
@@ -93,7 +93,7 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
 	if (plen == 0)
 		return 0;
 
-	return g_attrib_send(attrib, ATT_OP_READ_BY_TYPE_REQ,
+	return g_attrib_send(attrib, 0, ATT_OP_READ_BY_TYPE_REQ,
 					pdu, plen, func, user_data, NULL);
 }
 
@@ -104,7 +104,7 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
 	guint16 plen;
 
 	plen = enc_read_req(handle, pdu, sizeof(pdu));
-	return g_attrib_send(attrib, ATT_OP_READ_REQ, pdu, plen, func,
+	return g_attrib_send(attrib, 0, ATT_OP_READ_REQ, pdu, plen, func,
 							user_data, NULL);
 }
 
@@ -115,7 +115,7 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
 	guint16 plen;
 
 	plen = enc_write_req(handle, value, vlen, pdu, sizeof(pdu));
-	return g_attrib_send(attrib, ATT_OP_WRITE_REQ, pdu, plen, func,
+	return g_attrib_send(attrib, 0, ATT_OP_WRITE_REQ, pdu, plen, func,
 							user_data, NULL);
 }
 
@@ -129,7 +129,7 @@ guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
 	if (plen == 0)
 		return 0;
 
-	return g_attrib_send(attrib, ATT_OP_FIND_INFO_REQ, pdu, plen, func,
+	return g_attrib_send(attrib, 0, ATT_OP_FIND_INFO_REQ, pdu, plen, func,
 							user_data, NULL);
 }
 
@@ -140,6 +140,6 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
 	guint16 plen;
 
 	plen = enc_write_cmd(handle, value, vlen, pdu, sizeof(pdu));
-	return g_attrib_send(attrib, ATT_OP_WRITE_CMD, pdu, plen, NULL,
+	return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, pdu, plen, NULL,
 							user_data, notify);
 }
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index dd7b1d7..779a471 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -294,6 +294,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 	uint8_t buf[512], status;
 	gsize len;
 	GIOStatus iostat;
+	gboolean qempty;
 
 	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
 		attrib->read_watch = 0;
@@ -341,8 +342,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 	status = 0;
 
 done:
-	if (attrib->queue && g_queue_is_empty(attrib->queue) == FALSE)
-		wake_up_sender(attrib);
+	qempty = attrib->queue == NULL || g_queue_is_empty(attrib->queue);
 
 	if (cmd) {
 		if (cmd->func)
@@ -351,6 +351,9 @@ done:
 		command_destroy(cmd);
 	}
 
+	if (!qempty)
+		wake_up_sender(attrib);
+
 	return TRUE;
 }
 
@@ -376,9 +379,9 @@ GAttrib *g_attrib_new(GIOChannel *io)
 	return g_attrib_ref(attrib);
 }
 
-guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
-				guint16 len, GAttribResultFunc func,
-				gpointer user_data, GDestroyNotify notify)
+guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
+			const guint8 *pdu, guint16 len, GAttribResultFunc func,
+			gpointer user_data, GDestroyNotify notify)
 {
 	struct command *c;
 
@@ -394,9 +397,14 @@ guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
 	c->func = func;
 	c->user_data = user_data;
 	c->notify = notify;
-	c->id = ++attrib->next_cmd_id;
 
-	g_queue_push_tail(attrib->queue, c);
+	if (id) {
+		c->id = id;
+		g_queue_push_head(attrib->queue, c);
+	} else {
+		c->id = ++attrib->next_cmd_id;
+		g_queue_push_tail(attrib->queue, c);
+	}
 
 	if (g_queue_get_length(attrib->queue) == 1)
 		wake_up_sender(attrib);
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index 5c50bc9..f25208d 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -52,9 +52,10 @@ gboolean g_attrib_set_disconnect_function(GAttrib *attrib,
 gboolean g_attrib_set_destroy_function(GAttrib *attrib,
 		GDestroyNotify destroy, gpointer user_data);
 
-guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
-				guint16 len, GAttribResultFunc func,
-				gpointer user_data, GDestroyNotify notify);
+guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
+			const guint8 *pdu, guint16 len, GAttribResultFunc func,
+			gpointer user_data, GDestroyNotify notify);
+
 gboolean g_attrib_cancel(GAttrib *attrib, guint id);
 gboolean g_attrib_cancel_all(GAttrib *attrib);
 
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index a234e36..a6f92db 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -272,7 +272,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 	olen = enc_confirmation(opdu, sizeof(opdu));
 
 	if (olen > 0)
-		g_attrib_send(attrib, opdu[0], opdu, olen, NULL, NULL, NULL);
+		g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
 }
 
 static gboolean listen_start(gpointer user_data)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index cbc01ee..aee2ace 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -694,7 +694,7 @@ done:
 	if (status)
 		length = enc_error_resp(ipdu[0], 0x0000, status, opdu, channel->mtu);
 
-	g_attrib_send(channel->attrib, opdu[0], opdu, length,
+	g_attrib_send(channel->attrib, 0, opdu[0], opdu, length,
 							NULL, NULL, NULL);
 }
 
-- 
1.7.1
-- 
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

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

end of thread, other threads:[~2011-01-07  0:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-05  0:01 [PATCH 0/2] Implement Compound GATT Procedures and Long Reads Brian Gix
2011-01-05  0:01 ` [PATCH 1/2] Fix g_attrib_send() to include a new ID parameter Brian Gix
2011-01-06 17:17   ` Claudio Takahasi
2011-01-05  0:01 ` [PATCH 2/2] Fix gatt_read_char() to support long Attrib Values Brian Gix
2011-01-06 17:31   ` Claudio Takahasi
2011-01-07  0:39 [PATCH 0/2] Implement Compound GATT procedures, Long Reads Brian Gix
2011-01-07  0:39 ` [PATCH 1/2] Fix g_attrib_send() to include a new ID parameter Brian Gix

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.