diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 517ad949f36..bfeb7e80e9a 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -168,6 +168,13 @@ config BT_MESH_PROXY_FILTER_SIZE endif # BT_CONN +config BT_MESH_ACCESS_LAYER_MSG + bool "Enable direct Bluetooth message access layer messages" + help + This option allows the applicaiton to directly access + Bluetooth access layer messages without the need to + instantiate Bluetooth mesh models. + config BT_MESH_SELF_TEST bool "Perform self-tests" help diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index 16717fdcfac..cec98380c5f 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -48,6 +48,7 @@ struct mod_pub_val { static const struct bt_mesh_comp *dev_comp; static uint16_t dev_primary_addr; +static void (*msg_cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf); void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, @@ -486,24 +487,67 @@ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr) { uint16_t index; + if (!BT_MESH_ADDR_IS_UNICAST(addr)) { + return NULL; + } + + index = addr - dev_comp->elem[0].addr; + if (index >= dev_comp->elem_count) { + return NULL; + } + + return &dev_comp->elem[index]; +} + +bool bt_mesh_has_addr(uint16_t addr) +{ + uint16_t index; + if (BT_MESH_ADDR_IS_UNICAST(addr)) { - index = (addr - dev_comp->elem[0].addr); - if (index < dev_comp->elem_count) { - return &dev_comp->elem[index]; - } else { - return NULL; - } + return bt_mesh_elem_find(addr) != NULL; + } + + if (IS_ENABLED(CONFIG_BT_MESH_ACCESS_LAYER_MSG) && msg_cb) { + return true; } for (index = 0; index < dev_comp->elem_count; index++) { struct bt_mesh_elem *elem = &dev_comp->elem[index]; if (bt_mesh_elem_find_group(elem, addr)) { - return elem; + return true; } } - return NULL; + return false; +} + +#if defined(CONFIG_BT_MESH_ACCESS_LAYER_MSG) +void bt_mesh_msg_cb_set(void (*cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf)) +{ + msg_cb = cb; +} +#endif + +int bt_mesh_msg_send(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, uint16_t src_addr, + const struct bt_mesh_send_cb *cb, void *cb_data) +{ + struct bt_mesh_net_tx tx = { + .ctx = ctx, + .src = src_addr, + }; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx.ctx->net_idx, + tx.ctx->app_idx, tx.ctx->addr); + BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len)); + + if (!bt_mesh_is_provisioned()) { + BT_ERR("Local node is not yet provisioned"); + return -EAGAIN; + } + + return bt_mesh_trans_send(&tx, buf, cb, cb_data); } uint8_t bt_mesh_elem_count(void) @@ -677,32 +721,22 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) (void)op->func(model, &rx->ctx, buf); net_buf_simple_restore(buf, &state); } + + if (IS_ENABLED(CONFIG_BT_MESH_ACCESS_LAYER_MSG) && msg_cb) { + msg_cb(opcode, &rx->ctx, buf); + } } int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *msg, const struct bt_mesh_send_cb *cb, void *cb_data) { - struct bt_mesh_net_tx tx = { - .ctx = ctx, - .src = bt_mesh_model_elem(model)->addr, - }; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx.ctx->net_idx, - tx.ctx->app_idx, tx.ctx->addr); - BT_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len)); - - if (!bt_mesh_is_provisioned()) { - BT_ERR("Local node is not yet provisioned"); - return -EAGAIN; - } - - if (!model_has_key(model, tx.ctx->app_idx)) { - BT_ERR("Model not bound to AppKey 0x%04x", tx.ctx->app_idx); + if (!model_has_key(model, ctx->app_idx)) { + BT_ERR("Model not bound to AppKey 0x%04x", ctx->app_idx); return -EINVAL; } - return bt_mesh_trans_send(&tx, msg, cb, cb_data); + return bt_mesh_msg_send(ctx, msg, bt_mesh_model_elem(model)->addr, cb, cb_data); } int bt_mesh_model_publish(struct bt_mesh_model *model) diff --git a/subsys/bluetooth/mesh/access.h b/subsys/bluetooth/mesh/access.h index ae61256b04d..855a9ee168e 100644 --- a/subsys/bluetooth/mesh/access.h +++ b/subsys/bluetooth/mesh/access.h @@ -14,9 +14,11 @@ void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count); uint8_t bt_mesh_elem_count(void); -/* Find local element based on unicast or group address */ +/* Find local element based on unicast address */ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); +bool bt_mesh_has_addr(uint16_t addr); + 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, @@ -52,3 +54,26 @@ void bt_mesh_model_bind_store(struct bt_mesh_model *mod); void bt_mesh_model_sub_store(struct bt_mesh_model *mod); void bt_mesh_model_pub_store(struct bt_mesh_model *mod); void bt_mesh_model_settings_commit(void); + +/** @brief Register a callback function hook for mesh model messages. + * + * Register a callback function to act as a hook for recieving mesh model layer messages + * directly to the application without having instantiated the relevant models. + * + * @param cb A pointer to the callback function. + */ +void bt_mesh_msg_cb_set(void (*cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf)); + +/** @brief Send a mesh model message. + * + * Send a mesh model layer message out into the mesh network without having instantiated + * the relevant mesh models. + * + * @param ctx The Bluetooth mesh message context. + * @param buf The message payload. + * + * @return 0 on success or negative error code on failure. + */ +int bt_mesh_msg_send(struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf, uint16_t src_addr, + const struct bt_mesh_send_cb *cb, void *cb_data); diff --git a/subsys/bluetooth/mesh/app_keys.c b/subsys/bluetooth/mesh/app_keys.c index a0353e194fb..84b564fdd9c 100644 --- a/subsys/bluetooth/mesh/app_keys.c +++ b/subsys/bluetooth/mesh/app_keys.c @@ -460,7 +460,7 @@ int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx, } if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE && - !bt_mesh_elem_find(ctx->addr)) { + !bt_mesh_has_addr(ctx->addr)) { struct bt_mesh_cdb_node *node; if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) { diff --git a/subsys/bluetooth/mesh/friend.c b/subsys/bluetooth/mesh/friend.c index c7cfe19debe..993325a1255 100644 --- a/subsys/bluetooth/mesh/friend.c +++ b/subsys/bluetooth/mesh/friend.c @@ -472,7 +472,7 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf, src = sys_get_be16(&buf->data[5]); - if (bt_mesh_elem_find(src)) { + if (bt_mesh_has_addr(src)) { uint32_t seq; if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) { @@ -1034,7 +1034,7 @@ init_friend: frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, frnd->poll_to); if (BT_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) && - !bt_mesh_elem_find(frnd->clear.frnd)) { + !bt_mesh_has_addr(frnd->clear.frnd)) { clear_procedure_start(frnd); } @@ -1402,7 +1402,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, * this rx function. These packets have already been added to the * queue, and should be ignored. */ - if (bt_mesh_elem_find(rx->ctx.addr)) { + if (bt_mesh_has_addr(rx->ctx.addr)) { return; } diff --git a/subsys/bluetooth/mesh/net.c b/subsys/bluetooth/mesh/net.c index 07891731cf5..16aa1187d11 100644 --- a/subsys/bluetooth/mesh/net.c +++ b/subsys/bluetooth/mesh/net.c @@ -499,7 +499,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, /* Deliver to local network interface if necessary */ if (bt_mesh_fixed_group_match(tx->ctx->addr) || - bt_mesh_elem_find(tx->ctx->addr)) { + bt_mesh_has_addr(tx->ctx->addr)) { err = loopback(tx, buf->data, buf->len); /* Local unicast messages should not go out to network */ @@ -599,7 +599,7 @@ static bool net_decrypt(struct bt_mesh_net_rx *rx, struct net_buf_simple *in, return false; } - if (bt_mesh_elem_find(rx->ctx.addr)) { + if (bt_mesh_has_addr(rx->ctx.addr)) { BT_DBG("Dropping locally originated packet"); return false; } @@ -804,7 +804,7 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, net_buf_simple_save(&buf, &state); rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) || - bt_mesh_elem_find(rx.ctx.recv_dst)); + bt_mesh_has_addr(rx.ctx.recv_dst)); if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && net_if == BT_MESH_NET_IF_PROXY) {