Bluetooth: Mesh: Added support for application access to mesh messages

Added bt_mesh_msg_send() which can be used by the application to
directly send model layer messages without local instantiation of
related models. Also added bt_mesh_msg_cb_set() which allows the
application to recieve mesh model layer messages without local
instantiation of related models.

Added bt_mesh_has_addr() which returns a bool. For unicast addresses,
this returns whether or not bt_mesh_elem_find() was successfull. If the
above mentioned bt_mesh_msg_cb_set() has been used by the application to
set a message callback, this returns true so that the stack attempts to
push every model message up to the application via the callback. If no
callback has been set, group addresses are searched to see if the stack
should pass the message up the stack to an instantiated model.

These changes allow applications that do not or can not instantiate
models to interface with models in a mesh network. This is applicable to
applications which act as a Bluetooth mesh gateway, sniffer, debugger,
network monitoring, non-mesh relay/extender, etc.

In app_keys.c friend.c net.c bt_mesh_elem_find() is used only to
determine the existance of an address. The full return value of
bt_mesh_elem_find() is unecessary and so was replaced by the above
mentioned bt_mesh_has_addr() function in these instances.

Simplified bt_mesh_elem_find() by removing the search through group
address. Since the above mentioned bt_mesh_has_addr() function handles
instances where group addresses must be searched, it was no longer
necessary to preform this search in this function.

Signed-off-by: Bud Wandinger <bud@budkoembedded.ca>
This commit is contained in:
Bud Wandinger 2021-05-29 13:18:10 -06:00 committed by Christopher Friedt
commit 7a2b248b98
6 changed files with 99 additions and 33 deletions

View file

@ -168,6 +168,13 @@ config BT_MESH_PROXY_FILTER_SIZE
endif # BT_CONN 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 config BT_MESH_SELF_TEST
bool "Perform self-tests" bool "Perform self-tests"
help help

View file

@ -48,6 +48,7 @@ struct mod_pub_val {
static const struct bt_mesh_comp *dev_comp; static const struct bt_mesh_comp *dev_comp;
static uint16_t dev_primary_addr; 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, void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
struct bt_mesh_elem *elem, struct bt_mesh_elem *elem,
@ -486,24 +487,67 @@ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
{ {
uint16_t index; uint16_t index;
if (BT_MESH_ADDR_IS_UNICAST(addr)) { 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 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)) {
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++) { for (index = 0; index < dev_comp->elem_count; index++) {
struct bt_mesh_elem *elem = &dev_comp->elem[index]; struct bt_mesh_elem *elem = &dev_comp->elem[index];
if (bt_mesh_elem_find_group(elem, addr)) { 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) 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); (void)op->func(model, &rx->ctx, buf);
net_buf_simple_restore(buf, &state); 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, int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *msg, struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data) const struct bt_mesh_send_cb *cb, void *cb_data)
{ {
struct bt_mesh_net_tx tx = { if (!model_has_key(model, ctx->app_idx)) {
.ctx = ctx, BT_ERR("Model not bound to AppKey 0x%04x", ctx->app_idx);
.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);
return -EINVAL; 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) int bt_mesh_model_publish(struct bt_mesh_model *model)

View file

@ -14,9 +14,11 @@ void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count);
uint8_t bt_mesh_elem_count(void); 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); 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); struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod);
void bt_mesh_model_tree_walk(struct bt_mesh_model *root, void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, 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_sub_store(struct bt_mesh_model *mod);
void bt_mesh_model_pub_store(struct bt_mesh_model *mod); void bt_mesh_model_pub_store(struct bt_mesh_model *mod);
void bt_mesh_model_settings_commit(void); 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);

View file

@ -460,7 +460,7 @@ int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
} }
if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE && 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; struct bt_mesh_cdb_node *node;
if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) { if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) {

View file

@ -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]); src = sys_get_be16(&buf->data[5]);
if (bt_mesh_elem_find(src)) { if (bt_mesh_has_addr(src)) {
uint32_t seq; uint32_t seq;
if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) { 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); frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, frnd->poll_to);
if (BT_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) && 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); 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 * this rx function. These packets have already been added to the
* queue, and should be ignored. * queue, and should be ignored.
*/ */
if (bt_mesh_elem_find(rx->ctx.addr)) { if (bt_mesh_has_addr(rx->ctx.addr)) {
return; return;
} }

View file

@ -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 */ /* Deliver to local network interface if necessary */
if (bt_mesh_fixed_group_match(tx->ctx->addr) || 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); err = loopback(tx, buf->data, buf->len);
/* Local unicast messages should not go out to network */ /* 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; return false;
} }
if (bt_mesh_elem_find(rx->ctx.addr)) { if (bt_mesh_has_addr(rx->ctx.addr)) {
BT_DBG("Dropping locally originated packet"); BT_DBG("Dropping locally originated packet");
return false; 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); net_buf_simple_save(&buf, &state);
rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) || 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) && if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
net_if == BT_MESH_NET_IF_PROXY) { net_if == BT_MESH_NET_IF_PROXY) {