@@ -40,7 +40,8 @@ typedef enum {
MESH_AGENT_REQUEST_IN_ALPHA,
MESH_AGENT_REQUEST_STATIC_OOB,
MESH_AGENT_REQUEST_PRIVATE_KEY,
- MESH_AGENT_REQUEST_PUBLIC_KEY
+ MESH_AGENT_REQUEST_PUBLIC_KEY,
+ MESH_AGENT_REQUEST_CAPABILITIES,
} agent_request_type_t;
struct agent_request {
@@ -158,6 +159,25 @@ static void parse_oob_info(struct mesh_agent_prov_caps *caps,
}
}
+static void parse_properties(struct mesh_agent *agent,
+ struct l_dbus_message_iter *properties)
+{
+ const char *key, *uri_string;
+ struct l_dbus_message_iter variant;
+
+ while (l_dbus_message_iter_next_entry(properties, &key, &variant)) {
+ if (!strcmp(key, "Capabilities")) {
+ parse_prov_caps(&agent->caps, &variant);
+ } else if (!strcmp(key, "URI")) {
+ l_dbus_message_iter_get_variant(&variant, "s",
+ &uri_string);
+ /* TODO: compute hash */
+ } else if (!strcmp(key, "OutOfBandInfo")) {
+ parse_oob_info(&agent->caps, &variant);
+ }
+ }
+}
+
static void agent_free(void *agent_data)
{
struct mesh_agent *agent = agent_data;
@@ -193,6 +213,7 @@ static void agent_free(void *agent_data)
case MESH_AGENT_REQUEST_VIBRATE:
case MESH_AGENT_REQUEST_OUT_NUMERIC:
case MESH_AGENT_REQUEST_OUT_ALPHA:
+ case MESH_AGENT_REQUEST_CAPABILITIES:
simple_cb = agent->req->cb;
simple_cb(req->user_data, err);
default:
@@ -235,26 +256,13 @@ struct mesh_agent *mesh_agent_create(const char *path, const char *owner,
struct l_dbus_message_iter *properties)
{
struct mesh_agent *agent;
- const char *key, *uri_string;
- struct l_dbus_message_iter variant;
agent = l_new(struct mesh_agent, 1);
-
- while (l_dbus_message_iter_next_entry(properties, &key, &variant)) {
- if (!strcmp(key, "Capabilities")) {
- parse_prov_caps(&agent->caps, &variant);
- } else if (!strcmp(key, "URI")) {
- l_dbus_message_iter_get_variant(&variant, "s",
- &uri_string);
- /* TODO: compute hash */
- } else if (!strcmp(key, "OutOfBandInfo")) {
- parse_oob_info(&agent->caps, &variant);
- }
- }
-
agent->owner = l_strdup(owner);
agent->path = l_strdup(path);
+ parse_properties(agent, properties);
+
l_queue_push_tail(agents, agent);
return agent;
@@ -289,13 +297,76 @@ static int get_reply_error(struct l_dbus_message *reply)
if (l_dbus_message_is_error(reply)) {
l_dbus_message_get_error(reply, &name, &desc);
- l_error("Agent failed output action (%s), %s", name, desc);
+ l_error("Agent failed (%s), %s", name, desc);
return MESH_ERROR_FAILED;
}
return MESH_ERROR_NONE;
}
+static void properties_reply(struct l_dbus_message *reply, void *user_data)
+{
+ struct mesh_agent *agent = user_data;
+ struct agent_request *req;
+ mesh_agent_cb_t cb;
+ struct l_dbus_message_iter properties;
+ int err;
+
+ if (!l_queue_find(agents, simple_match, agent) || !agent->req)
+ return;
+
+ req = agent->req;
+
+ err = get_reply_error(reply);
+
+ if (err != MESH_ERROR_NONE)
+ goto fail;
+
+ if (!l_dbus_message_get_arguments(reply, "a{sv}", &properties)) {
+ err = MESH_ERROR_FAILED;
+ goto fail;
+ }
+
+ parse_properties(agent, &properties);
+fail:
+ if (req->cb)
+ {
+ cb = req->cb;
+ cb(req->user_data, err);
+ }
+
+ l_dbus_message_unref(req->msg);
+ l_free(req);
+ agent->req = NULL;
+}
+
+void mesh_agent_refresh(struct mesh_agent *agent, mesh_agent_cb_t cb,
+ void *user_data)
+{
+ struct l_dbus *dbus = dbus_get_bus();
+ struct l_dbus_message *msg;
+ struct l_dbus_message_builder *builder;
+
+ agent->req = create_request(MESH_AGENT_REQUEST_CAPABILITIES, (void *)cb,
+ user_data);
+
+ msg = l_dbus_message_new_method_call(dbus, agent->owner, agent->path,
+ L_DBUS_INTERFACE_PROPERTIES,
+ "GetAll");
+
+ builder = l_dbus_message_builder_new(msg);
+ l_dbus_message_builder_append_basic(builder, 's',
+ MESH_PROVISION_AGENT_INTERFACE);
+ l_dbus_message_builder_finalize(builder);
+ l_dbus_message_builder_destroy(builder);
+
+ l_dbus_send_with_reply(dbus_get_bus(), msg, properties_reply, agent,
+ NULL);
+
+ agent->req->msg = l_dbus_message_ref(msg);
+}
+
+
static void simple_reply(struct l_dbus_message *reply, void *user_data)
{
struct mesh_agent *agent = user_data;
@@ -42,6 +42,8 @@ void mesh_agent_init(void);
void mesh_agent_cleanup(void);
struct mesh_agent *mesh_agent_create(const char *path, const char *owner,
struct l_dbus_message_iter *properties);
+void mesh_agent_refresh(struct mesh_agent *agent, mesh_agent_cb_t cb,
+ void *user_data);
void mesh_agent_remove(struct mesh_agent *agent);
void mesh_agent_cancel(struct mesh_agent *agent);
@@ -81,6 +81,9 @@ static void free_pending_add_call()
l_dbus_remove_watch(dbus_get_bus(),
add_pending->disc_watch);
+ if (add_pending->msg)
+ l_dbus_message_unref(add_pending->msg);
+
l_free(add_pending);
add_pending = NULL;
}
@@ -212,6 +215,23 @@ static bool add_data_get(void *user_data, uint8_t num_ele)
return true;
}
+static void add_start(void *user_data, int err)
+{
+ struct l_dbus_message *reply;
+
+ l_info("Start callback");
+
+ if (err == MESH_ERROR_NONE)
+ reply = l_dbus_message_new_method_return(add_pending->msg);
+ else
+ reply = dbus_error(add_pending->msg, MESH_ERROR_FAILED,
+ "Failed to start provisioning initiator");
+
+ l_dbus_send(dbus_get_bus(), reply);
+
+ add_pending->msg = NULL;
+}
+
static struct l_dbus_message *add_node_call(struct l_dbus *dbus,
struct l_dbus_message *msg,
void *user_data)
@@ -243,6 +263,7 @@ static struct l_dbus_message *add_node_call(struct l_dbus *dbus,
/* Invoke Prov Initiator */
add_pending = l_new(struct add_data, 1);
+ add_pending->msg = l_dbus_message_ref(msg);
memcpy(add_pending->uuid, uuid, 16);
add_pending->node = node;
add_pending->agent = node_get_agent(node);
@@ -255,20 +276,14 @@ static struct l_dbus_message *add_node_call(struct l_dbus *dbus,
goto fail;
}
-
- if (!initiator_start(PB_ADV, uuid, 99, 60, add_pending->agent,
- add_data_get, add_cmplt, node, add_pending)) {
- reply = dbus_error(msg, MESH_ERROR_FAILED,
- "Failed to start provisioning initiator");
- goto fail;
- }
+ initiator_start(PB_ADV, uuid, 99, 60, add_pending->agent, add_start,
+ add_data_get, add_cmplt, node, add_pending);
add_pending->disc_watch = l_dbus_add_disconnect_watch(dbus,
node_get_owner(node),
prov_disc_cb, NULL, NULL);
- return l_dbus_message_new_method_return(msg);
-
+ return NULL;
fail:
l_free(add_pending);
add_pending = NULL;
@@ -36,6 +36,7 @@
#include "mesh/pb-adv.h"
#include "mesh/mesh.h"
#include "mesh/agent.h"
+#include "mesh/error.h"
/* Quick size sanity check */
static const uint16_t expected_pdu_size[] = {
@@ -77,6 +78,7 @@ enum int_state {
#define MAT_SECRET (MAT_REMOTE_PUBLIC | MAT_LOCAL_PRIVATE)
struct mesh_prov_initiator {
+ mesh_prov_initiator_start_func_t start_cb;
mesh_prov_initiator_complete_func_t complete_cb;
mesh_prov_initiator_data_req_func_t data_req_cb;
prov_trans_tx_t trans_tx;
@@ -102,6 +104,7 @@ struct mesh_prov_initiator {
uint8_t private_key[32];
uint8_t secret[32];
uint8_t rand_auth_workspace[48];
+ uint8_t uuid[16];
};
static struct mesh_prov_initiator *prov = NULL;
@@ -814,17 +817,45 @@ static void int_prov_ack(void *user_data, uint8_t msg_num)
}
}
+static void initiator_open_cb(void *user_data, int err)
+{
+ bool result;
+
+ if (!prov)
+ return;
+
+ if (err != MESH_ERROR_NONE)
+ goto fail;
+
+ /* Always register for PB-ADV */
+ result = pb_adv_reg(true, int_prov_open, int_prov_close, int_prov_rx,
+ int_prov_ack, prov->uuid, prov);
+
+ if (!result) {
+ err = MESH_ERROR_FAILED;
+ goto fail;
+ }
+
+ if (!prov)
+ return;
+
+ prov->start_cb(prov->caller_data, MESH_ERROR_NONE);
+ return;
+fail:
+ prov->start_cb(prov->caller_data, err);
+ initiator_free();
+}
+
bool initiator_start(enum trans_type transport,
uint8_t uuid[16],
uint16_t max_ele,
uint32_t timeout, /* in seconds from mesh.conf */
struct mesh_agent *agent,
+ mesh_prov_initiator_start_func_t start_cb,
mesh_prov_initiator_data_req_func_t data_req_cb,
mesh_prov_initiator_complete_func_t complete_cb,
void *node, void *caller_data)
{
- bool result;
-
/* Invoked from Add() method in mesh-api.txt, to add a
* remote unprovisioned device network.
*/
@@ -837,19 +868,15 @@ bool initiator_start(enum trans_type transport,
prov->node = node;
prov->agent = agent;
prov->complete_cb = complete_cb;
+ prov->start_cb = start_cb;
prov->data_req_cb = data_req_cb;
prov->caller_data = caller_data;
prov->previous = -1;
+ memcpy(prov->uuid, uuid, 16);
- /* Always register for PB-ADV */
- result = pb_adv_reg(true, int_prov_open, int_prov_close, int_prov_rx,
- int_prov_ack, uuid, prov);
-
- if (result)
- return true;
+ mesh_agent_refresh(prov->agent, initiator_open_cb, prov);
- initiator_free();
- return false;
+ return true;
}
void initiator_cancel(void *user_data)
@@ -100,6 +100,8 @@ typedef bool (*mesh_prov_acceptor_complete_func_t)(void *user_data,
uint8_t status,
struct mesh_prov_node_info *info);
+typedef void (*mesh_prov_initiator_start_func_t)(void *user_data, int err);
+
typedef bool (*mesh_prov_initiator_data_req_func_t)(void *user_data,
uint8_t num_elem);
@@ -120,6 +122,7 @@ bool initiator_start(enum trans_type transport,
uint16_t max_ele,
uint32_t timeout, /* in seconds from mesh.conf */
struct mesh_agent *agent,
+ mesh_prov_initiator_start_func_t start_cb,
mesh_prov_initiator_data_req_func_t data_req_cb,
mesh_prov_initiator_complete_func_t complete_cb,
void *node, void *caller_data);