summaryrefslogtreecommitdiff
path: root/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/mynewt-nimble/nimble/host/mesh/src/access.c')
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/access.c188
1 files changed, 90 insertions, 98 deletions
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
index ff8e9999..da077182 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
@@ -26,7 +26,7 @@
#endif
static const struct bt_mesh_comp *dev_comp;
-static u16_t dev_primary_addr;
+static uint16_t dev_primary_addr;
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
struct bt_mesh_elem *elem,
@@ -53,7 +53,7 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
}
}
-s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
+int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
{
int period;
@@ -89,10 +89,10 @@ s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
}
}
-static s32_t next_period(struct bt_mesh_model *mod)
+static int32_t next_period(struct bt_mesh_model *mod)
{
struct bt_mesh_model_pub *pub = mod->pub;
- u32_t elapsed, period;
+ uint32_t elapsed, period;
period = bt_mesh_model_pub_period_get(mod);
if (!period) {
@@ -115,7 +115,7 @@ static s32_t next_period(struct bt_mesh_model *mod)
static void publish_sent(int err, void *user_data)
{
struct bt_mesh_model *mod = user_data;
- s32_t delay;
+ int32_t delay;
BT_DBG("err %d", err);
@@ -131,7 +131,7 @@ static void publish_sent(int err, void *user_data)
}
}
-static void publish_start(u16_t duration, int err, void *user_data)
+static void publish_start(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_model *mod = user_data;
struct bt_mesh_model_pub *pub = mod->pub;
@@ -156,30 +156,18 @@ static int publish_retransmit(struct bt_mesh_model *mod)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_model_pub *pub = mod->pub;
- struct bt_mesh_app_key *key;
struct bt_mesh_msg_ctx ctx = {
.addr = pub->addr,
.send_ttl = pub->ttl,
+ .app_idx = pub->key,
};
struct bt_mesh_net_tx tx = {
.ctx = &ctx,
.src = bt_mesh_model_elem(mod)->addr,
- .xmit = bt_mesh_net_transmit_get(),
.friend_cred = pub->cred,
};
int err;
- key = bt_mesh_app_key_find(pub->key);
- if (!key) {
- err = -EADDRNOTAVAIL;
- goto done;
- }
-
- tx.sub = bt_mesh_subnet_get(key->net_idx);
-
- ctx.net_idx = key->net_idx;
- ctx.app_idx = key->app_idx;
-
net_buf_simple_init(sdu, 0);
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
@@ -187,15 +175,22 @@ static int publish_retransmit(struct bt_mesh_model *mod)
err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod);
-done:
os_mbuf_free_chain(sdu);
return err;
}
+static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub)
+{
+ /* Cancel all retransmits for this publish attempt */
+ pub->count = 0U;
+ /* Make sure the publish timer gets reset */
+ publish_sent(err, pub->mod);
+}
+
static void mod_publish(struct ble_npl_event *work)
{
struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work);
- s32_t period_ms;
+ int32_t period_ms;
int err;
BT_DBG("");
@@ -227,7 +222,10 @@ static void mod_publish(struct ble_npl_event *work)
err = pub->update(pub->mod);
if (err) {
- BT_ERR("Failed to update publication message");
+ /* Cancel this publish attempt. */
+ BT_DBG("Update failed, skipping publish (err: %d)", err);
+ pub->period_start = k_uptime_get_32();
+ publish_retransmit_end(err, pub);
return;
}
@@ -242,7 +240,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
return &dev_comp->elem[mod->elem_idx];
}
-struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx)
+struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx)
{
struct bt_mesh_elem *elem;
@@ -274,6 +272,11 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
int i;
+ int *err = user_data;
+
+ if (*err) {
+ return;
+ }
if (mod->pub) {
mod->pub->mod = mod;
@@ -293,12 +296,14 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
}
if (mod->cb && mod->cb->init) {
- mod->cb->init(mod);
+ *err = mod->cb->init(mod);
}
}
int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
{
+ int err;
+
/* There must be at least one element */
if (!comp->elem_count) {
return -EINVAL;
@@ -306,12 +311,13 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
dev_comp = comp;
- bt_mesh_model_foreach(mod_init, NULL);
+ err = 0;
+ bt_mesh_model_foreach(mod_init, &err);
- return 0;
+ return err;
}
-void bt_mesh_comp_provision(u16_t addr)
+void bt_mesh_comp_provision(uint16_t addr)
{
int i;
@@ -334,16 +340,14 @@ void bt_mesh_comp_unprovision(void)
BT_DBG("");
dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
-
- bt_mesh_model_foreach(mod_init, NULL);
}
-u16_t bt_mesh_primary_addr(void)
+uint16_t bt_mesh_primary_addr(void)
{
return dev_primary_addr;
}
-static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
+static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr)
{
int i;
@@ -357,13 +361,13 @@ static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
}
struct find_group_visitor_ctx {
- u16_t *entry;
+ uint16_t *entry;
struct bt_mesh_model *mod;
- u16_t addr;
+ uint16_t addr;
};
static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *user_data)
+ uint32_t depth, void *user_data)
{
struct find_group_visitor_ctx *ctx = user_data;
@@ -380,7 +384,7 @@ static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
return BT_MESH_WALK_CONTINUE;
}
-u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
+uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr)
{
struct find_group_visitor_ctx ctx = {
.mod = *mod,
@@ -396,10 +400,10 @@ u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
}
static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
- u16_t group_addr)
+ uint16_t group_addr)
{
struct bt_mesh_model *model;
- u16_t *match;
+ uint16_t *match;
int i;
for (i = 0; i < elem->model_count; i++) {
@@ -423,9 +427,9 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
return NULL;
}
-struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
+struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
{
- u16_t index;
+ uint16_t index;
if (BT_MESH_ADDR_IS_UNICAST(addr)) {
index = (addr - dev_comp->elem[0].addr);
@@ -447,12 +451,12 @@ struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
return NULL;
}
-u8_t bt_mesh_elem_count(void)
+uint8_t bt_mesh_elem_count(void)
{
return dev_comp->elem_count;
}
-static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
+static bool model_has_key(struct bt_mesh_model *mod, uint16_t key)
{
int i;
@@ -467,22 +471,26 @@ static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
return false;
}
-static bool model_has_dst(struct bt_mesh_model *mod, u16_t dst)
+static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst)
{
if (BT_MESH_ADDR_IS_UNICAST(dst)) {
return (dev_comp->elem[mod->elem_idx].addr == dst);
} else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst)) {
- return bt_mesh_model_find_group(&mod, dst);
+ return !!bt_mesh_model_find_group(&mod, dst);
}
- return (mod->elem_idx == 0 && bt_mesh_fixed_group_match(dst));
+ /* If a message with a fixed group address is sent to the access layer,
+ * the lower layers have already confirmed that we are subscribing to
+ * it. All models on the primary element should receive the message.
+ */
+ return mod->elem_idx == 0;
}
static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
- u8_t model_count, u32_t opcode,
+ uint8_t model_count, uint32_t opcode,
struct bt_mesh_model **model)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < model_count; i++) {
const struct bt_mesh_model_op *op;
@@ -500,7 +508,7 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
return NULL;
}
-static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
+static int get_opcode(struct os_mbuf *buf, uint32_t *opcode)
{
switch (buf->om_data[0] >> 6) {
case 0x00:
@@ -527,6 +535,10 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
}
*opcode = net_buf_simple_pull_u8(buf) << 16;
+ /* Using LE for the CID since the model layer is defined as
+ * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
+ * will declare the opcode in this way.
+ */
*opcode |= net_buf_simple_pull_le16(buf);
return 0;
}
@@ -534,29 +546,12 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
CODE_UNREACHABLE;
}
-bool bt_mesh_fixed_group_match(u16_t addr)
-{
- /* Check for fixed group addresses */
- switch (addr) {
- case BT_MESH_ADDR_ALL_NODES:
- return true;
- case BT_MESH_ADDR_PROXIES:
- return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
- case BT_MESH_ADDR_FRIENDS:
- return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
- case BT_MESH_ADDR_RELAYS:
- return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
- default:
- return false;
- }
-}
-
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_model *models, *model;
const struct bt_mesh_model_op *op;
- u32_t opcode;
- u8_t count;
+ uint32_t opcode;
+ uint8_t count;
int i;
BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
@@ -615,7 +610,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
}
}
-void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
+void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode)
{
net_buf_simple_init(msg, 0);
@@ -628,6 +623,10 @@ void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
break;
case 3:
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
+ /* Using LE for the CID since the model layer is defined as
+ * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
+ * will declare the opcode in this way.
+ */
net_buf_simple_add_le16(msg, opcode & 0xffff);
break;
default:
@@ -674,11 +673,8 @@ int bt_mesh_model_send(struct bt_mesh_model *model,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
struct bt_mesh_net_tx tx = {
- .sub = bt_mesh_subnet_get(ctx->net_idx),
.ctx = ctx,
.src = bt_mesh_model_elem(model)->addr,
- .xmit = bt_mesh_net_transmit_get(),
- .friend_cred = 0,
};
return model_send(model, &tx, false, msg, cb, cb_data);
@@ -688,13 +684,15 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_model_pub *pub = model->pub;
- struct bt_mesh_app_key *key;
struct bt_mesh_msg_ctx ctx = {
+ .addr = pub->addr,
+ .send_ttl = pub->ttl,
+ .send_rel = pub->send_rel,
+ .app_idx = pub->key,
};
struct bt_mesh_net_tx tx = {
.ctx = &ctx,
.src = bt_mesh_model_elem(model)->addr,
- .xmit = bt_mesh_net_transmit_get(),
};
int err;
@@ -710,12 +708,6 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
goto done;
}
- key = bt_mesh_app_key_find(pub->key);
- if (!key) {
- err = -EADDRNOTAVAIL;
- goto done;
- }
-
if (pub->msg->om_len + 4 > BT_MESH_TX_SDU_MAX) {
BT_ERR("Message does not fit maximum SDU size");
err = -EMSGSIZE;
@@ -730,13 +722,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
net_buf_simple_init(sdu, 0);
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
- ctx.addr = pub->addr;
- ctx.send_ttl = pub->ttl;
- ctx.net_idx = key->net_idx;
- ctx.app_idx = key->app_idx;
-
tx.friend_cred = pub->cred;
- tx.sub = bt_mesh_subnet_get(ctx.net_idx),
pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
@@ -745,10 +731,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
if (err) {
- /* Don't try retransmissions for this publish attempt */
- pub->count = 0;
- /* Make sure the publish timer gets reset */
- publish_sent(err, model);
+ publish_retransmit_end(err, pub);
}
done:
@@ -757,9 +740,9 @@ done:
}
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
- u16_t company, u16_t id)
+ uint16_t company, uint16_t id)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < elem->vnd_model_count; i++) {
if (elem->vnd_models[i].vnd.company == company &&
@@ -772,9 +755,9 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
}
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
- u16_t id)
+ uint16_t id)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < elem->model_count; i++) {
if (elem->models[i].id == id) {
@@ -802,29 +785,38 @@ struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod)
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
- u32_t depth,
+ uint32_t depth,
void *user_data),
void *user_data)
{
struct bt_mesh_model *m = root;
- u32_t depth = 0;
+ int depth = 0;
+ /* 'skip' is set to true when we ascend from child to parent node.
+ * In that case, we want to skip calling the callback on the parent
+ * node and we don't want to descend onto a child node as those
+ * nodes have already been visited.
+ */
+ bool skip = false;
do {
- if (cb(m, depth, user_data) == BT_MESH_WALK_STOP) {
+ if (!skip &&
+ cb(m, (uint32_t)depth, user_data) == BT_MESH_WALK_STOP) {
return;
}
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
- if (m->extends) {
+ if (!skip && m->extends) {
m = m->extends;
depth++;
} else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) {
- m = m->next->next;
+ m = m->next;
depth--;
+ skip = true;
} else {
m = m->next;
+ skip = false;
}
#endif
- } while (m && m != root);
+ } while (m && depth > 0);
}
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)