feat(ble_mesh): Use a separate file for heartbeat handling

This commit is contained in:
Liu Linyan 2023-09-28 10:44:06 +08:00 committed by BOT
parent 2472c62fff
commit 5de452e12a
12 changed files with 434 additions and 379 deletions

View File

@ -487,6 +487,7 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/core/friend.c"
"esp_ble_mesh/core/health_cli.c"
"esp_ble_mesh/core/health_srv.c"
"esp_ble_mesh/core/heartbeat.c"
"esp_ble_mesh/core/local.c"
"esp_ble_mesh/core/lpn.c"
"esp_ble_mesh/core/main.c"

View File

@ -37,6 +37,7 @@
#include "proxy_client.h"
#include "prov_pvnr.h"
#include "pvnr_mgmt.h"
#include "heartbeat.h"
#if CONFIG_BLE_MESH_CFG_CLI
#include "mesh/cfg_cli.h"
@ -2550,14 +2551,14 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
act = ESP_BLE_MESH_PROVISIONER_ENABLE_HEARTBEAT_RECV_COMP_EVT;
param.provisioner_enable_heartbeat_recv_comp.enable = arg->enable_heartbeat_recv.enable;
param.provisioner_enable_heartbeat_recv_comp.err_code =
bt_mesh_provisioner_recv_heartbeat(arg->enable_heartbeat_recv.enable ?
btc_ble_mesh_provisioner_recv_heartbeat_cb : NULL);
bt_mesh_pvnr_register_hb_recv_cb(arg->enable_heartbeat_recv.enable ?
btc_ble_mesh_provisioner_recv_heartbeat_cb : NULL);
break;
case BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE:
act = ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE_COMP_EVT;
param.provisioner_set_heartbeat_filter_type_comp.type = arg->set_heartbeat_filter_type.type;
param.provisioner_set_heartbeat_filter_type_comp.err_code =
bt_mesh_provisioner_set_heartbeat_filter_type(arg->set_heartbeat_filter_type.type);
bt_mesh_pvnr_set_hb_recv_filter_type(arg->set_heartbeat_filter_type.type);
break;
case BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_INFO:
act = ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_INFO_COMP_EVT;
@ -2565,9 +2566,9 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
param.provisioner_set_heartbeat_filter_info_comp.hb_src = arg->set_heartbeat_filter_info.hb_src;
param.provisioner_set_heartbeat_filter_info_comp.hb_dst = arg->set_heartbeat_filter_info.hb_dst;
param.provisioner_set_heartbeat_filter_info_comp.err_code =
bt_mesh_provisioner_set_heartbeat_filter_info(arg->set_heartbeat_filter_info.op,
arg->set_heartbeat_filter_info.hb_src,
arg->set_heartbeat_filter_info.hb_dst);
bt_mesh_pvnr_set_hb_recv_filter_info(arg->set_heartbeat_filter_info.op,
arg->set_heartbeat_filter_info.hb_src,
arg->set_heartbeat_filter_info.hb_dst);
break;
#endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
#if CONFIG_BLE_MESH_SETTINGS

View File

@ -28,6 +28,7 @@
#include "proxy_server.h"
#include "mesh/main.h"
#include "mesh/common.h"
#include "heartbeat.h"
#include "mesh_v1.1/utils.h"
@ -3565,41 +3566,6 @@ void bt_mesh_cfg_reset(bool store)
(void)memset(labels, 0, sizeof(labels));
}
void bt_mesh_heartbeat(uint16_t src, uint16_t dst, uint8_t hops, uint16_t feat)
{
struct bt_mesh_cfg_srv *cfg = conf;
if (!cfg) {
BT_WARN("No configuration server context available");
return;
}
if (src != cfg->hb_sub.src || dst != cfg->hb_sub.dst) {
BT_WARN("No subscription for received heartbeat");
return;
}
if (k_uptime_get() > cfg->hb_sub.expiry) {
BT_WARN("Heartbeat subscription period expired");
return;
}
cfg->hb_sub.min_hops = MIN(cfg->hb_sub.min_hops, hops);
cfg->hb_sub.max_hops = MAX(cfg->hb_sub.max_hops, hops);
if (cfg->hb_sub.count < 0xffff) {
cfg->hb_sub.count++;
}
BT_DBG("src 0x%04x dst 0x%04x hops %u min %u max %u count %u", src,
dst, hops, cfg->hb_sub.min_hops, cfg->hb_sub.max_hops,
cfg->hb_sub.count);
if (cfg->hb_sub.func) {
cfg->hb_sub.func(hops, feat);
}
}
uint8_t bt_mesh_net_transmit_get(void)
{
if (conf) {

View File

@ -266,8 +266,6 @@ void bt_mesh_mod_sub_reset(bool store);
void bt_mesh_cfg_reset(bool store);
void bt_mesh_heartbeat(uint16_t src, uint16_t dst, uint8_t hops, uint16_t feat);
void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time);
struct label *get_label(uint16_t index);

View File

@ -0,0 +1,298 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "lpn.h"
#include "mesh.h"
#include "mesh/main.h"
#include "access.h"
#include "foundation.h"
#include "transport.h"
#include "heartbeat.h"
#include "mesh/cfg_srv.h"
static uint16_t hb_sub_dst = BLE_MESH_ADDR_UNASSIGNED;
void bt_mesh_set_hb_sub_dst(uint16_t addr)
{
hb_sub_dst = addr;
}
uint16_t bt_mesh_get_hb_sub_dst(void)
{
return hb_sub_dst;
}
void bt_mesh_heartbeat_recv(uint16_t src, uint16_t dst, uint8_t hops, uint16_t feat)
{
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
if (cfg == NULL) {
BT_WARN("No configuration server context available");
return;
}
if (src != cfg->hb_sub.src || dst != cfg->hb_sub.dst) {
BT_WARN("No subscription for received heartbeat");
return;
}
if (k_uptime_get() > cfg->hb_sub.expiry) {
BT_WARN("Heartbeat subscription period expired");
return;
}
cfg->hb_sub.min_hops = MIN(cfg->hb_sub.min_hops, hops);
cfg->hb_sub.max_hops = MAX(cfg->hb_sub.max_hops, hops);
if (cfg->hb_sub.count < 0xffff) {
cfg->hb_sub.count++;
}
BT_DBG("src 0x%04x dst 0x%04x hops %u min %u max %u count %u", src,
dst, hops, cfg->hb_sub.min_hops, cfg->hb_sub.max_hops,
cfg->hb_sub.count);
if (cfg->hb_sub.func) {
cfg->hb_sub.func(hops, feat);
}
}
void bt_mesh_heartbeat_send(void)
{
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
uint16_t feat = 0U;
struct __attribute__((packed)) {
uint8_t init_ttl;
uint16_t feat;
} hb;
struct bt_mesh_msg_ctx ctx = {
.net_idx = cfg->hb_pub.net_idx,
.app_idx = BLE_MESH_KEY_UNUSED,
.addr = cfg->hb_pub.dst,
.send_ttl = cfg->hb_pub.ttl,
.send_cred = BLE_MESH_FLOODING_CRED,
};
struct bt_mesh_net_tx tx = {
.sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx),
.ctx = &ctx,
.src = bt_mesh_model_elem(cfg->model)->addr,
.xmit = bt_mesh_net_transmit_get(),
};
/* Do nothing if heartbeat publication is not enabled */
if (cfg->hb_pub.dst == BLE_MESH_ADDR_UNASSIGNED) {
return;
}
hb.init_ttl = cfg->hb_pub.ttl;
if (bt_mesh_relay_get() == BLE_MESH_RELAY_ENABLED) {
feat |= BLE_MESH_FEAT_RELAY;
}
if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) {
feat |= BLE_MESH_FEAT_PROXY;
}
if (bt_mesh_friend_get() == BLE_MESH_FRIEND_ENABLED) {
feat |= BLE_MESH_FEAT_FRIEND;
}
if (bt_mesh_lpn_established()) {
feat |= BLE_MESH_FEAT_LOW_POWER;
}
hb.feat = sys_cpu_to_be16(feat);
BT_INFO("InitTTL %u feat 0x%04x", cfg->hb_pub.ttl, feat);
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
NULL, NULL);
}
#if CONFIG_BLE_MESH_PROVISIONER_RECV_HB
#define HEARTBEAT_FILTER_ACCEPTLIST 0x00
#define HEARTBEAT_FILTER_REJECTLIST 0x01
#define HEARTBEAT_FILTER_ADD 0x00
#define HEARTBEAT_FILTER_REMOVE 0x01
static struct heartbeat_recv {
struct heartbeat_filter {
uint16_t src; /* Heartbeat SRC (unicast address) */
uint16_t dst; /* Heartbeat DST (unicast address or group address) */
} filter[CONFIG_BLE_MESH_PROVISIONER_RECV_HB_FILTER_SIZE];
uint8_t type; /* Heartbeat filter type */
bt_mesh_pvnr_hb_recv_cb_t cb; /* Heartbeat receive callback */
} hb_rx;
int bt_mesh_pvnr_register_hb_recv_cb(bt_mesh_pvnr_hb_recv_cb_t cb)
{
memset(&hb_rx, 0, sizeof(hb_rx));
/* Start with an empty rejectlist, which means all heartbeat messages will be reported */
hb_rx.type = HEARTBEAT_FILTER_REJECTLIST;
hb_rx.cb = cb;
return 0;
}
int bt_mesh_pvnr_set_hb_recv_filter_type(uint8_t type)
{
if (type > HEARTBEAT_FILTER_REJECTLIST) {
BT_ERR("Invalid heartbeat filter type 0x%02x", type);
return -EINVAL;
}
/* If the heartbeat filter type is different with previous one,
* clear the existing filter entries.
*/
if (hb_rx.type != type) {
memset(&hb_rx, 0, offsetof(struct heartbeat_recv, cb));
hb_rx.type = type;
}
return 0;
}
static int hb_filter_alloc(uint16_t src, uint16_t dst)
{
int i;
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (filter->src == BLE_MESH_ADDR_UNASSIGNED &&
filter->dst == BLE_MESH_ADDR_UNASSIGNED) {
filter->src = src;
filter->dst = dst;
return 0;
}
}
BT_ERR("Heartbeat filter is full!");
return -ENOMEM;
}
static int hb_filter_add(uint16_t src, uint16_t dst)
{
int i;
if (!(BLE_MESH_ADDR_IS_UNICAST(src) &&
(BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)))) {
BT_ERR("Invalid filter address, src 0x%04x, dst 0x%04x", src, dst);
return -EINVAL;
}
/* Check if filter entries with the same src or dst exist. */
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (filter->src == src && filter->dst == dst) {
BT_WARN("Filter already exists, src 0x%04x dst 0x%04x", filter->src, filter->dst);
return 0;
}
}
return hb_filter_alloc(src, dst);
}
static int hb_filter_remove(uint16_t src, uint16_t dst)
{
int i;
if (!(BLE_MESH_ADDR_IS_UNICAST(src) &&
(BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)))) {
BT_ERR("Invalid filter address, src 0x%04x, dst 0x%04x", src, dst);
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (filter->src == src && filter->dst == dst) {
memset(filter, 0, sizeof(struct heartbeat_filter));
}
}
return 0;
}
int bt_mesh_pvnr_set_hb_recv_filter_info(uint8_t op, uint16_t src, uint16_t dst)
{
switch (op) {
case HEARTBEAT_FILTER_ADD:
return hb_filter_add(src, dst);
case HEARTBEAT_FILTER_REMOVE:
return hb_filter_remove(src, dst);
default:
BT_ERR("Invalid heartbeat filter opcode 0x%02x", op);
return -EINVAL;
}
}
static bool filter_with_rejectlist(uint16_t hb_src, uint16_t hb_dst)
{
int i;
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (hb_src == filter->src && hb_dst == filter->dst) {
return true;
}
}
return false;
}
static bool filter_with_acceptlist(uint16_t hb_src, uint16_t hb_dst)
{
int i;
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (hb_src == filter->src && hb_dst == filter->dst) {
return false;
}
}
return true;
}
void bt_mesh_pvnr_heartbeat_recv(uint16_t hb_src, uint16_t hb_dst,
uint8_t init_ttl, uint8_t rx_ttl,
uint8_t hops, uint16_t feat, int8_t rssi)
{
if (hb_rx.cb == NULL) {
BT_DBG("Receiving heartbeat is not enabled");
return;
}
if (hb_rx.type == HEARTBEAT_FILTER_REJECTLIST) {
if (filter_with_rejectlist(hb_src, hb_dst)) {
BT_INFO("Filtered by rejectlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
return;
}
} else {
if (filter_with_acceptlist(hb_src, hb_dst)) {
BT_INFO("Filtered by acceptlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
return;
}
}
if (hb_rx.cb) {
hb_rx.cb(hb_src, hb_dst, init_ttl, rx_ttl, hops, feat, rssi);
}
}
#endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */

View File

@ -0,0 +1,43 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _HEARTBEAT_H_
#define _HEARTBEAT_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void bt_mesh_set_hb_sub_dst(uint16_t addr);
uint16_t bt_mesh_get_hb_sub_dst(void);
void bt_mesh_heartbeat_recv(uint16_t src, uint16_t dst, uint8_t hops, uint16_t feat);
void bt_mesh_heartbeat_send(void);
typedef void (* bt_mesh_pvnr_hb_recv_cb_t)(uint16_t hb_src, uint16_t hb_dst,
uint8_t init_ttl, uint8_t rx_ttl,
uint8_t hops, uint16_t feat, int8_t rssi);
int bt_mesh_pvnr_register_hb_recv_cb(bt_mesh_pvnr_hb_recv_cb_t cb);
int bt_mesh_pvnr_set_hb_recv_filter_type(uint8_t filter_type);
int bt_mesh_pvnr_set_hb_recv_filter_info(uint8_t op, uint16_t src, uint16_t dst);
void bt_mesh_pvnr_heartbeat_recv(uint16_t hb_src, uint16_t hb_dst,
uint8_t init_ttl, uint8_t rx_ttl,
uint8_t hops, uint16_t feat, int8_t rssi);
#ifdef __cplusplus
}
#endif
#endif /* _HEARTBEAT_H_ */

View File

@ -21,6 +21,7 @@
#include "foundation.h"
#include "mesh/main.h"
#include "mesh/cfg_srv.h"
#include "heartbeat.h"
#include "mesh_v1.1/utils.h"

View File

@ -1435,181 +1435,4 @@ int bt_mesh_provisioner_store_node_info(struct bt_mesh_node *node)
}
#endif /* CONFIG_BLE_MESH_TEST_AUTO_ENTER_NETWORK */
#if CONFIG_BLE_MESH_PROVISIONER_RECV_HB
#define HEARTBEAT_FILTER_ACCEPTLIST 0x00
#define HEARTBEAT_FILTER_REJECTLIST 0x01
#define HEARTBEAT_FILTER_ADD 0x00
#define HEARTBEAT_FILTER_REMOVE 0x01
static struct heartbeat_recv {
struct heartbeat_filter {
uint16_t src; /* Heartbeat source address (unicast address) */
uint16_t dst; /* Heartbeat destination address (unicast address or group address) */
} filter[CONFIG_BLE_MESH_PROVISIONER_RECV_HB_FILTER_SIZE];
uint8_t type; /* Heartbeat filter type */
bt_mesh_heartbeat_recv_cb_t cb; /* Heartbeat receive callback */
} hb_rx;
int bt_mesh_provisioner_recv_heartbeat(bt_mesh_heartbeat_recv_cb_t cb)
{
memset(&hb_rx, 0, sizeof(hb_rx));
/* Start with an empty rejectlist, which means all heartbeat messages will be reported */
hb_rx.type = HEARTBEAT_FILTER_REJECTLIST;
hb_rx.cb = cb;
return 0;
}
int bt_mesh_provisioner_set_heartbeat_filter_type(uint8_t type)
{
if (type > HEARTBEAT_FILTER_REJECTLIST) {
BT_ERR("Invalid heartbeat filter type 0x%02x", type);
return -EINVAL;
}
/* If the heartbeat filter type is different with previous one,
* clear the existing filter entries.
*/
if (hb_rx.type != type) {
memset(&hb_rx, 0, offsetof(struct heartbeat_recv, cb));
hb_rx.type = type;
}
return 0;
}
static int hb_filter_alloc(uint16_t src, uint16_t dst)
{
int i;
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (filter->src == BLE_MESH_ADDR_UNASSIGNED &&
filter->dst == BLE_MESH_ADDR_UNASSIGNED) {
filter->src = src;
filter->dst = dst;
return 0;
}
}
BT_ERR("Heartbeat filter is full!");
return -ENOMEM;
}
static int hb_filter_add(uint16_t src, uint16_t dst)
{
int i;
if (!(BLE_MESH_ADDR_IS_UNICAST(src) &&
(BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)))) {
BT_ERR("Invalid filter address, src 0x%04x, dst 0x%04x", src, dst);
return -EINVAL;
}
/* Check if filter entries with the same src or dst exist. */
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (filter->src == src && filter->dst == dst) {
BT_WARN("Filter already exists, src 0x%04x dst 0x%04x", filter->src, filter->dst);
return 0;
}
}
return hb_filter_alloc(src, dst);
}
static int hb_filter_remove(uint16_t src, uint16_t dst)
{
int i;
if (!(BLE_MESH_ADDR_IS_UNICAST(src) &&
(BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)))) {
BT_ERR("Invalid filter address, src 0x%04x, dst 0x%04x", src, dst);
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (filter->src == src && filter->dst == dst) {
memset(filter, 0, sizeof(struct heartbeat_filter));
}
}
return 0;
}
int bt_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, uint16_t src, uint16_t dst)
{
switch (op) {
case HEARTBEAT_FILTER_ADD:
return hb_filter_add(src, dst);
case HEARTBEAT_FILTER_REMOVE:
return hb_filter_remove(src, dst);
default:
BT_ERR("Invalid heartbeat filter opcode 0x%02x", op);
return -EINVAL;
}
}
static bool filter_with_rejectlist(uint16_t hb_src, uint16_t hb_dst)
{
int i;
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (hb_src == filter->src && hb_dst == filter->dst) {
return true;
}
}
return false;
}
static bool filter_with_acceptlist(uint16_t hb_src, uint16_t hb_dst)
{
int i;
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (hb_src == filter->src && hb_dst == filter->dst) {
return false;
}
}
return true;
}
void bt_mesh_provisioner_heartbeat(uint16_t hb_src, uint16_t hb_dst,
uint8_t init_ttl, uint8_t rx_ttl,
uint8_t hops, uint16_t feat, int8_t rssi)
{
if (hb_rx.cb == NULL) {
BT_DBG("Receiving heartbeat is not enabled");
return;
}
if (hb_rx.type == HEARTBEAT_FILTER_REJECTLIST) {
if (filter_with_rejectlist(hb_src, hb_dst)) {
BT_INFO("Filtered by rejectlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
return;
}
} else {
if (filter_with_acceptlist(hb_src, hb_dst)) {
BT_INFO("Filtered by acceptlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
return;
}
}
if (hb_rx.cb) {
hb_rx.cb(hb_src, hb_dst, init_ttl, rx_ttl, hops, feat, rssi);
}
}
#endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
#endif /* CONFIG_BLE_MESH_PROVISIONER */

View File

@ -113,20 +113,6 @@ int bt_mesh_provisioner_local_net_key_del(uint16_t net_idx, bool store);
int bt_mesh_provisioner_bind_local_model_app_idx(uint16_t elem_addr, uint16_t mod_id,
uint16_t cid, uint16_t app_idx);
typedef void (* bt_mesh_heartbeat_recv_cb_t)(uint16_t hb_src, uint16_t hb_dst,
uint8_t init_ttl, uint8_t rx_ttl,
uint8_t hops, uint16_t feat, int8_t rssi);
int bt_mesh_provisioner_recv_heartbeat(bt_mesh_heartbeat_recv_cb_t cb);
int bt_mesh_provisioner_set_heartbeat_filter_type(uint8_t filter_type);
int bt_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, uint16_t src, uint16_t dst);
void bt_mesh_provisioner_heartbeat(uint16_t hb_src, uint16_t hb_dst,
uint8_t init_ttl, uint8_t rx_ttl,
uint8_t hops, uint16_t feat, int8_t rssi);
int bt_mesh_provisioner_store_node_info(struct bt_mesh_node *node);
#ifdef __cplusplus

View File

@ -24,6 +24,7 @@
#include "fast_prov.h"
#include "mesh/common.h"
#include "mesh/cfg_srv.h"
#include "heartbeat.h"
#include "mesh_v1.1/utils.h"
@ -116,8 +117,6 @@ static struct seg_rx {
static uint8_t seg_rx_buf_data[(CONFIG_BLE_MESH_RX_SEG_MSG_COUNT *
CONFIG_BLE_MESH_RX_SDU_MAX)];
static uint16_t hb_sub_dst = BLE_MESH_ADDR_UNASSIGNED;
static bt_mesh_mutex_t seg_tx_lock;
static bt_mesh_mutex_t seg_rx_lock;
@ -141,12 +140,12 @@ static inline void bt_mesh_seg_rx_unlock(void)
bt_mesh_mutex_unlock(&seg_rx_lock);
}
uint8_t bt_mesh_get_seg_retrans_num(void)
uint8_t bt_mesh_get_seg_rtx_num(void)
{
return SEG_RETRANSMIT_ATTEMPTS;
}
int32_t bt_mesh_get_seg_retrans_timeout(uint8_t ttl)
int32_t bt_mesh_get_seg_rtx_timeout(uint8_t ttl)
{
/* This function will be used when a client model sending an
* acknowledged message. And if the dst of a message is not
@ -160,9 +159,72 @@ int32_t bt_mesh_get_seg_retrans_timeout(uint8_t ttl)
return SEG_RETRANSMIT_TIMEOUT_UNICAST(&tx);
}
void bt_mesh_set_hb_sub_dst(uint16_t addr)
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx)
{
hb_sub_dst = addr;
if (bt_mesh_is_provisioned()) {
#if CONFIG_BLE_MESH_NODE
if (!IS_ENABLED(CONFIG_BLE_MESH_FAST_PROV)) {
for (int i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED &&
bt_mesh.app_keys[i].app_idx == app_idx) {
return &bt_mesh.app_keys[i];
}
}
} else {
return bt_mesh_fast_prov_app_key_find(app_idx);
}
#endif
} else if (bt_mesh_is_provisioner_en()) {
#if CONFIG_BLE_MESH_PROVISIONER
for (int i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) {
if (bt_mesh.p_app_keys[i] &&
bt_mesh.p_app_keys[i]->net_idx != BLE_MESH_KEY_UNUSED &&
bt_mesh.p_app_keys[i]->app_idx == app_idx) {
return bt_mesh.p_app_keys[i];
}
}
#endif
}
return NULL;
}
int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx,
const uint8_t **key, uint8_t *aid, uint16_t dst)
{
struct bt_mesh_app_key *app_key = NULL;
if (app_idx == BLE_MESH_KEY_DEV) {
*key = bt_mesh_dev_key_get(dst);
if (!*key) {
BT_ERR("DevKey of 0x%04x not found", dst);
return -EINVAL;
}
*aid = 0U;
return 0;
}
if (!subnet) {
BT_ERR("Invalid subnet");
return -EINVAL;
}
app_key = bt_mesh_app_key_get(app_idx);
if (!app_key) {
BT_ERR("AppKey 0x%04x not found", app_idx);
return -ENOENT;
}
if (subnet->kr_phase == BLE_MESH_KR_PHASE_2 && app_key->updated) {
*key = app_key->keys[1].val;
*aid = app_key->keys[1].id;
} else {
*key = app_key->keys[0].val;
*aid = app_key->keys[0].id;
}
return 0;
}
static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu,
@ -575,36 +637,6 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
return 0;
}
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx)
{
if (bt_mesh_is_provisioned()) {
#if CONFIG_BLE_MESH_NODE
if (!IS_ENABLED(CONFIG_BLE_MESH_FAST_PROV)) {
for (int i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED &&
bt_mesh.app_keys[i].app_idx == app_idx) {
return &bt_mesh.app_keys[i];
}
}
} else {
return bt_mesh_fast_prov_app_key_find(app_idx);
}
#endif
} else if (bt_mesh_is_provisioner_en()) {
#if CONFIG_BLE_MESH_PROVISIONER
for (int i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) {
if (bt_mesh.p_app_keys[i] &&
bt_mesh.p_app_keys[i]->net_idx != BLE_MESH_KEY_UNUSED &&
bt_mesh.p_app_keys[i]->app_idx == app_idx) {
return bt_mesh.p_app_keys[i];
}
}
#endif
}
return NULL;
}
int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
@ -945,7 +977,7 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx,
}
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned() &&
rx->ctx.recv_dst != hb_sub_dst) {
rx->ctx.recv_dst != bt_mesh_get_hb_sub_dst()) {
BT_WARN("Ignoring heartbeat to non-subscribed destination");
return 0;
}
@ -956,15 +988,15 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx,
hops = (init_ttl - rx->ctx.recv_ttl + 1);
BT_INFO("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x",
rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
(hops == 1U) ? "" : "s", feat);
rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
(hops == 1U) ? "" : "s", feat);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
bt_mesh_heartbeat_recv(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
} else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER_RECV_HB) && bt_mesh_is_provisioner_en()) {
bt_mesh_provisioner_heartbeat(rx->ctx.addr, rx->ctx.recv_dst,
init_ttl, rx->ctx.recv_ttl,
hops, feat, rx->ctx.recv_rssi);
bt_mesh_pvnr_heartbeat_recv(rx->ctx.addr, rx->ctx.recv_dst,
init_ttl, rx->ctx.recv_ttl,
hops, feat, rx->ctx.recv_rssi);
}
return 0;
@ -1563,6 +1595,7 @@ found_rx:
*pdu_type = BLE_MESH_FRIEND_PDU_COMPLETE;
k_delayed_work_cancel(&rx->ack);
send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
@ -1756,94 +1789,3 @@ void bt_mesh_trans_deinit(bool erase)
bt_mesh_mutex_free(&seg_rx_lock);
}
#endif /* CONFIG_BLE_MESH_DEINIT */
void bt_mesh_heartbeat_send(void)
{
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
uint16_t feat = 0U;
struct __attribute__((packed)) {
uint8_t init_ttl;
uint16_t feat;
} hb;
struct bt_mesh_msg_ctx ctx = {
.net_idx = cfg->hb_pub.net_idx,
.app_idx = BLE_MESH_KEY_UNUSED,
.addr = cfg->hb_pub.dst,
.send_ttl = cfg->hb_pub.ttl,
.send_cred = BLE_MESH_FLOODING_CRED,
};
struct bt_mesh_net_tx tx = {
.sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx),
.ctx = &ctx,
.src = bt_mesh_model_elem(cfg->model)->addr,
.xmit = bt_mesh_net_transmit_get(),
};
/* Do nothing if heartbeat publication is not enabled */
if (cfg->hb_pub.dst == BLE_MESH_ADDR_UNASSIGNED) {
return;
}
hb.init_ttl = cfg->hb_pub.ttl;
if (bt_mesh_relay_get() == BLE_MESH_RELAY_ENABLED) {
feat |= BLE_MESH_FEAT_RELAY;
}
if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) {
feat |= BLE_MESH_FEAT_PROXY;
}
if (bt_mesh_friend_get() == BLE_MESH_FRIEND_ENABLED) {
feat |= BLE_MESH_FEAT_FRIEND;
}
if (bt_mesh_lpn_established()) {
feat |= BLE_MESH_FEAT_LOW_POWER;
}
hb.feat = sys_cpu_to_be16(feat);
BT_INFO("InitTTL %u feat 0x%04x", cfg->hb_pub.ttl, feat);
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
NULL, NULL);
}
int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx,
const uint8_t **key, uint8_t *aid, uint16_t dst)
{
struct bt_mesh_app_key *app_key = NULL;
if (app_idx == BLE_MESH_KEY_DEV) {
*key = bt_mesh_dev_key_get(dst);
if (!*key) {
BT_ERR("DevKey of 0x%04x not found", dst);
return -EINVAL;
}
*aid = 0U;
return 0;
}
if (!subnet) {
BT_ERR("Invalid subnet");
return -EINVAL;
}
app_key = bt_mesh_app_key_get(app_idx);
if (!app_key) {
BT_ERR("AppKey 0x%04x not found", app_idx);
return -ENOENT;
}
if (subnet->kr_phase == BLE_MESH_KR_PHASE_2 && app_key->updated) {
*key = app_key->keys[1].val;
*aid = app_key->keys[1].id;
} else {
*key = app_key->keys[0].val;
*aid = app_key->keys[0].id;
}
return 0;
}

View File

@ -94,14 +94,15 @@ struct bt_mesh_ctl_friend_sub_confirm {
uint8_t xact;
} __attribute__((packed));
uint8_t bt_mesh_get_seg_retrans_num(void);
uint8_t bt_mesh_get_seg_rtx_num(void);
int32_t bt_mesh_get_seg_retrans_timeout(uint8_t ttl);
void bt_mesh_set_hb_sub_dst(uint16_t addr);
int32_t bt_mesh_get_seg_rtx_timeout(uint8_t ttl);
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx);
int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx,
const uint8_t **key, uint8_t *aid, uint16_t dst);
bool bt_mesh_tx_in_progress(void);
void bt_mesh_rx_reset(void);
@ -121,11 +122,6 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx);
void bt_mesh_trans_init(void);
void bt_mesh_trans_deinit(bool erase);
void bt_mesh_heartbeat_send(void);
int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx,
const uint8_t **key, uint8_t *aid, uint16_t dst);
#ifdef __cplusplus
}
#endif

View File

@ -197,8 +197,8 @@ static int32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx,
/* Based on the message length, calculate how many segments are needed.
* All the messages sent from here are access messages.
*/
seg_rtx_num = bt_mesh_get_seg_retrans_num();
seg_rtx_to = bt_mesh_get_seg_retrans_timeout(ctx->send_ttl);
seg_rtx_num = bt_mesh_get_seg_rtx_num();
seg_rtx_to = bt_mesh_get_seg_rtx_timeout(ctx->send_ttl);
seg_count = (msg->len + mic_size - 1) / 12U + 1U;
duration = bt_mesh_get_adv_duration(ctx);