[RFC 1/2] Add g_attrib_send_seq()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add g_attrib_send_seq() as an extension to g_attrib_send().
 	g_attrib_send_seq() functionally queues an entire
 	"GATT Procedure" as defined in the BT Core v4.0.
 	The intention is that the full procedure is run
 	to completion before the next GATT Procedure is
 	started. Subsequent ATT requests to a continuing
 	procedure are added to the head of the Attrib queue.

Fix g_attrib_send() to be the degenerative case of g_attrib_send_seq()
	This function now chains to g_attrib_send_seq() with arguments
	indicating that it is *not* a compound (multi-step) GATT
	procedure, but rather that the entire procedure is performed
	with a single ATT opcode request/response.

Fix received_data() to recognize that incoming response is (or isn't)
	part of a compound Procedure, so that it waits for additional
	requests before servicing the Attrib queue.
---
 attrib/gattrib.c |   44 ++++++++++++++++++++++++++++++++++++--------
 attrib/gattrib.h |    4 ++++
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index eace01b..8ef5d92 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -58,6 +58,7 @@ struct command {
 	guint16 len;
 	guint8 expected;
 	gboolean sent;
+	gboolean compound;
 	GAttribResultFunc func;
 	gpointer user_data;
 	GDestroyNotify notify;
@@ -285,6 +286,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 	uint8_t buf[512], status;
 	gsize len;
 	GIOStatus iostat;
+	gboolean compound = FALSE;
 
 	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
 		attrib->read_watch = 0;
@@ -319,6 +321,8 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 		return attrib->events != NULL;
 	}
 
+	compound = cmd->compound;
+
 	if (buf[0] == ATT_OP_ERROR) {
 		status = buf[4];
 		goto done;
@@ -332,7 +336,8 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 	status = 0;
 
 done:
-	if (attrib->queue && g_queue_is_empty(attrib->queue) == FALSE)
+	if (!compound && attrib->queue &&
+			g_queue_is_empty(attrib->queue) == FALSE)
 		wake_up_sender(attrib);
 
 	if (cmd) {
@@ -340,6 +345,11 @@ done:
 			cmd->func(status, buf, len, cmd->user_data);
 
 		command_destroy(cmd);
+
+		if (compound && attrib->queue &&
+			g_queue_is_empty(attrib->queue) == FALSE)
+			wake_up_sender(attrib);
+
 	}
 
 	return TRUE;
@@ -367,12 +377,16 @@ 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_seq(GAttrib *attrib, gboolean compound, guint id,
+				guint8 opcode, const guint8 *pdu, guint16 len,
+				GAttribResultFunc func, gpointer user_data,
+				GDestroyNotify notify)
 {
 	struct command *c;
 
+	if (attrib == NULL || attrib->queue == NULL)
+		return 0;
+
 	c = g_try_new0(struct command, 1);
 	if (c == NULL)
 		return 0;
@@ -385,16 +399,30 @@ 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;
+	c->compound = compound;
 
-	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);
+		if (g_queue_get_length(attrib->queue) == 1)
+			wake_up_sender(attrib);
+	}
 
 	return c->id;
 }
 
+guint g_attrib_send(GAttrib *attrib, guint8 opcode, const guint8 *pdu,
+				guint16 len, GAttribResultFunc func,
+				gpointer user_data, GDestroyNotify notify)
+{
+	return g_attrib_send_seq(attrib, FALSE, 0, opcode,
+				pdu, len, func, user_data, notify);
+}
+
 static gint command_cmp_by_id(gconstpointer a, gconstpointer b)
 {
 	const struct command *cmd = a;
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index 0940289..ade21bc 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -53,6 +53,10 @@ gboolean g_attrib_set_destroy_function(GAttrib *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_seq(GAttrib *attrib, gboolean compound, 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);
 
-- 
1.7.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux