diff options
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.c | 188 |
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) |