Diff between 7f0a643d5416b25d06821db784de268d2962362b and 9260107b158ddd9677ccfe1c7968f62eb988fa92

Changed Files

File Additions Deletions Status
mesh/prov-acceptor.c +55 -33 modified
mesh/provision.h +1 -0 modified

Full Patch

diff --git a/mesh/prov-acceptor.c b/mesh/prov-acceptor.c
index 0dbb84f..f579a14 100644
--- a/mesh/prov-acceptor.c
+++ b/mesh/prov-acceptor.c
@@ -42,26 +42,15 @@ static const uint16_t expected_pdu_size[] = {
 
 #define BEACON_TYPE_UNPROVISIONED		0x00
 
+struct deferred_cmd {
+	uint16_t len;
+	uint8_t cmd[];
+};
+
 static const uint8_t pkt_filter = MESH_AD_TYPE_PROVISION;
 static const uint8_t bec_filter[] = {MESH_AD_TYPE_BEACON,
 						BEACON_TYPE_UNPROVISIONED};
 
-enum acp_state {
-	ACP_PROV_IDLE = 0,
-	ACP_PROV_CAPS_SENT,
-	ACP_PROV_CAPS_ACKED,
-	ACP_PROV_KEY_SENT,
-	ACP_PROV_KEY_ACKED,
-	ACP_PROV_INP_CMPLT_SENT,
-	ACP_PROV_INP_CMPLT_ACKED,
-	ACP_PROV_CONF_SENT,
-	ACP_PROV_CONF_ACKED,
-	ACP_PROV_RAND_SENT,
-	ACP_PROV_RAND_ACKED,
-	ACP_PROV_CMPLT_SENT,
-	ACP_PROV_FAIL_SENT,
-};
-
 #define MAT_REMOTE_PUBLIC	0x01
 #define MAT_LOCAL_PRIVATE	0x02
 #define MAT_RAND_AUTH		0x04
@@ -70,12 +59,13 @@ enum acp_state {
 struct mesh_prov_acceptor {
 	mesh_prov_acceptor_complete_func_t cmplt;
 	prov_trans_tx_t trans_tx;
+	struct l_queue *ob;
 	void *agent;
 	void *caller_data;
 	void *trans_data;
 	struct l_timeout *timeout;
 	uint32_t to_secs;
-	enum acp_state	state;
+	uint8_t out_opcode;
 	uint8_t transport;
 	uint8_t material;
 	uint8_t expected;
@@ -99,6 +89,7 @@ static void acceptor_free(void)
 		return;
 
 	l_timeout_remove(prov->timeout);
+	l_queue_destroy(prov->ob, l_free);
 
 	mesh_send_cancel(bec_filter, sizeof(bec_filter));
 	mesh_send_cancel(&pkt_filter, sizeof(pkt_filter));
@@ -126,6 +117,21 @@ static void acp_prov_close(void *user_data, uint8_t reason)
 	acceptor_free();
 }
 
+static void prov_send(struct mesh_prov_acceptor *prov, void *cmd, uint16_t len)
+{
+	struct deferred_cmd *defer;
+
+	if (prov->out_opcode == PROV_NONE) {
+		prov->out_opcode = *(uint8_t *) cmd;
+		prov->trans_tx(prov->trans_data, cmd, len);
+	} else {
+		defer = l_malloc(len + sizeof(struct deferred_cmd));
+		defer->len = len;
+		memcpy(defer->cmd, cmd, len);
+		l_queue_push_tail(prov->ob, defer);
+	}
+}
+
 static void prov_to(struct l_timeout *timeout, void *user_data)
 {
 	struct mesh_prov_acceptor *rx_prov = user_data;
@@ -140,7 +146,7 @@ static void prov_to(struct l_timeout *timeout, void *user_data)
 	if (prov->cmplt && prov->trans_tx) {
 		prov->cmplt(prov->caller_data, PROV_ERR_TIMEOUT, NULL);
 		prov->cmplt = NULL;
-		prov->trans_tx(prov->trans_data, fail_code, 2);
+		prov_send(prov, fail_code, 2);
 		prov->timeout = l_timeout_create(1, prov_to, prov, NULL);
 		return;
 	}
@@ -258,7 +264,7 @@ static void number_cb(void *user_data, int err, uint32_t number)
 	if (err) {
 		msg.opcode = PROV_FAILED;
 		msg.reason = PROV_ERR_UNEXPECTED_ERR;
-		prov->trans_tx(prov->trans_data, &msg, sizeof(msg));
+		prov_send(prov, &msg, sizeof(msg));
 		return;
 	}
 
@@ -267,7 +273,7 @@ static void number_cb(void *user_data, int err, uint32_t number)
 	l_put_be32(number, prov->rand_auth_workspace + 44);
 	prov->material |= MAT_RAND_AUTH;
 	msg.opcode = PROV_INP_CMPLT;
-	prov->trans_tx(prov->trans_data, &msg.opcode, 1);
+	prov_send(prov, &msg.opcode, 1);
 }
 
 static void static_cb(void *user_data, int err, uint8_t *key, uint32_t len)
@@ -281,7 +287,7 @@ static void static_cb(void *user_data, int err, uint8_t *key, uint32_t len)
 	if (err || !key || len != 16) {
 		msg.opcode = PROV_FAILED;
 		msg.reason = PROV_ERR_UNEXPECTED_ERR;
-		prov->trans_tx(prov->trans_data, &msg, sizeof(msg));
+		prov_send(prov, &msg, sizeof(msg));
 		return;
 	}
 
@@ -292,7 +298,7 @@ static void static_cb(void *user_data, int err, uint8_t *key, uint32_t len)
 
 	if (prov->conf_inputs.start.auth_action == PROV_ACTION_IN_ALPHA) {
 		msg.opcode = PROV_INP_CMPLT;
-		prov->trans_tx(prov->trans_data, &msg.opcode, 1);
+		prov_send(prov, &msg.opcode, 1);
 	}
 }
 
@@ -307,7 +313,7 @@ static void priv_key_cb(void *user_data, int err, uint8_t *key, uint32_t len)
 	if (err || !key || len != 32) {
 		msg.opcode = PROV_FAILED;
 		msg.reason = PROV_ERR_UNEXPECTED_ERR;
-		prov->trans_tx(prov->trans_data, &msg, sizeof(msg));
+		prov_send(prov, &msg, sizeof(msg));
 		return;
 	}
 
@@ -326,7 +332,7 @@ static void priv_key_cb(void *user_data, int err, uint8_t *key, uint32_t len)
 		if (!acp_credentials(prov)) {
 			msg.opcode = PROV_FAILED;
 			msg.reason = PROV_ERR_UNEXPECTED_ERR;
-			prov->trans_tx(prov->trans_data, &msg, sizeof(msg));
+			prov_send(prov, &msg, sizeof(msg));
 		}
 	}
 }
@@ -339,9 +345,8 @@ static void send_caps(struct mesh_prov_acceptor *prov)
 	memcpy(&msg.caps, &prov->conf_inputs.caps,
 			sizeof(prov->conf_inputs.caps));
 
-	prov->state = ACP_PROV_CAPS_SENT;
 	prov->expected = PROV_START;
-	prov->trans_tx(prov->trans_data, &msg, sizeof(msg));
+	prov_send(prov, &msg, sizeof(msg));
 }
 
 static void send_pub_key(struct mesh_prov_acceptor *prov)
@@ -350,7 +355,7 @@ static void send_pub_key(struct mesh_prov_acceptor *prov)
 
 	msg.opcode = PROV_PUB_KEY;
 	memcpy(msg.pub_key, prov->conf_inputs.dev_pub_key, sizeof(msg.pub_key));
-	prov->trans_tx(prov->trans_data, &msg, sizeof(msg));
+	prov_send(prov, &msg, sizeof(msg));
 }
 
 static bool send_conf(struct mesh_prov_acceptor *prov)
@@ -365,7 +370,7 @@ static bool send_conf(struct mesh_prov_acceptor *prov)
 	if (!memcmp(msg.conf, prov->confirm, sizeof(msg.conf)))
 		return false;
 
-	prov->trans_tx(prov->trans_data, &msg, sizeof(msg));
+	prov_send(prov, &msg, sizeof(msg));
 	return true;
 }
 
@@ -375,7 +380,7 @@ static void send_rand(struct mesh_prov_acceptor *prov)
 
 	msg.opcode = PROV_RANDOM;
 	memcpy(msg.rand, prov->rand_auth_workspace, sizeof(msg.rand));
-	prov->trans_tx(prov->trans_data, &msg, sizeof(msg));
+	prov_send(prov, &msg, sizeof(msg));
 }
 
 static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
@@ -614,8 +619,7 @@ static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
 
 		if (result) {
 			prov->rand_auth_workspace[0] = PROV_COMPLETE;
-			prov->trans_tx(prov->trans_data,
-					prov->rand_auth_workspace, 1);
+			prov_send(prov, prov->rand_auth_workspace, 1);
 			goto cleanup;
 		} else {
 			fail.reason = PROV_ERR_UNEXPECTED_ERR;
@@ -638,7 +642,7 @@ static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
 
 failure:
 	fail.opcode = PROV_FAILED;
-	prov->trans_tx(prov->trans_data, &fail, sizeof(fail));
+	prov_send(prov, &fail, sizeof(fail));
 	if (prov->cmplt)
 		prov->cmplt(prov->caller_data, fail.reason, NULL);
 	prov->cmplt = NULL;
@@ -652,7 +656,23 @@ cleanup:
 
 static void acp_prov_ack(void *user_data, uint8_t msg_num)
 {
-	/* TODO: Handle PB-ADV Ack */
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	struct deferred_cmd *deferred;
+
+	if (rx_prov != prov)
+		return;
+
+	if (prov->out_opcode == PROV_NONE)
+		return;
+
+	prov->out_opcode = PROV_NONE;
+
+	deferred = l_queue_pop_head(prov->ob);
+	if (!deferred)
+		return;
+
+	prov_send(prov, deferred->cmd, deferred->len);
+	l_free(deferred);
 }
 
 
@@ -680,7 +700,9 @@ bool acceptor_start(uint8_t num_ele, uint8_t uuid[16],
 	prov->to_secs = timeout;
 	prov->agent = agent;
 	prov->cmplt = complete_cb;
+	prov->ob = l_queue_new();
 	prov->previous = -1;
+	prov->out_opcode = PROV_NONE;
 	prov->caller_data = caller_data;
 
 	caps = mesh_agent_get_caps(agent);
diff --git a/mesh/provision.h b/mesh/provision.h
index 1a11b69..1634c4d 100644
--- a/mesh/provision.h
+++ b/mesh/provision.h
@@ -38,6 +38,7 @@ struct mesh_agent;
 #define PROV_DATA	0x07
 #define PROV_COMPLETE	0x08
 #define PROV_FAILED	0x09
+#define PROV_NONE	0xFF
 
 /* Spec defined Error Codes */
 #define PROV_ERR_SUCCESS		0x00