mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(ble_mesh): Miscellaneous update for BLE Mesh
This commit is contained in:
@@ -616,19 +616,17 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c"
|
||||
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c"
|
||||
"esp_ble_mesh/lib/ext.c")
|
||||
|
||||
if(CONFIG_BLE_MESH_SAR_ENHANCEMENT)
|
||||
list(APPEND srcs "esp_ble_mesh/core/transport.enh.c")
|
||||
else()
|
||||
list(APPEND srcs "esp_ble_mesh/core/transport.c")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"esp_ble_mesh/core/transport.c")
|
||||
list(APPEND srcs "esp_ble_mesh/core/transport.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
if(CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT)
|
||||
list(APPEND srcs
|
||||
"porting/npl/freertos/src/npl_os_freertos.c"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Intel Corporation
|
||||
* SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -112,7 +112,7 @@ static int32_t next_period(struct bt_mesh_model *mod)
|
||||
|
||||
if (!pub) {
|
||||
BT_ERR("Model has no publication support");
|
||||
return -ENOTSUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
period = bt_mesh_model_pub_period_get(mod);
|
||||
@@ -1366,3 +1366,71 @@ struct bt_mesh_app_key *bt_mesh_rx_appkey_get(size_t index)
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
@@ -264,10 +264,16 @@ static inline TickType_t K_WAIT(int32_t val)
|
||||
static void adv_thread(void *p)
|
||||
{
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
QueueHandle_t relay_adv_handle = NULL;
|
||||
QueueSetMemberHandle_t handle = NULL;
|
||||
#endif
|
||||
bt_mesh_msg_t msg = {0};
|
||||
struct net_buf **buf = NULL;
|
||||
bt_mesh_msg_t msg = {0};
|
||||
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
relay_adv_handle = relay_adv_handle_get();
|
||||
assert(relay_adv_handle);
|
||||
#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */
|
||||
|
||||
buf = (struct net_buf **)(&msg.arg);
|
||||
|
||||
|
||||
@@ -0,0 +1,896 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Intel Corporation
|
||||
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "adv_common.h"
|
||||
#include "net.h"
|
||||
#include "ble_adv.h"
|
||||
|
||||
NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT,
|
||||
BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
|
||||
static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT];
|
||||
|
||||
static struct bt_mesh_adv_queue adv_queue;
|
||||
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT,
|
||||
BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
|
||||
static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT];
|
||||
struct bt_mesh_adv_queue relay_adv_queue;
|
||||
|
||||
#define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6)
|
||||
#define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF
|
||||
|
||||
#endif
|
||||
|
||||
static bt_mesh_mutex_t adv_buf_alloc_lock;
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
NET_BUF_POOL_DEFINE(ext_adv_buf_pool, CONFIG_BLE_MESH_EXT_ADV_BUF_COUNT,
|
||||
BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
static bt_mesh_ext_adv_t ext_adv_pool[CONFIG_BLE_MESH_EXT_ADV_BUF_COUNT];
|
||||
#if CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT
|
||||
NET_BUF_POOL_DEFINE(ext_relay_adv_buf_pool, CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT,
|
||||
BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
static bt_mesh_ext_adv_t ext_relay_adv_pool[CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT];
|
||||
#endif /* CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT */
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
NET_BUF_POOL_DEFINE(ext_long_adv_buf_pool, CONFIG_BLE_MESH_LONG_PACKET_TX_SEG_CNT,
|
||||
CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN, BLE_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
static bt_mesh_ext_adv_t ext_long_adv_pool[CONFIG_BLE_MESH_LONG_PACKET_TX_SEG_CNT];
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT
|
||||
NET_BUF_POOL_DEFINE(ext_long_relay_adv_buf_pool, CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT,
|
||||
CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN, BLE_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
static bt_mesh_ext_adv_t ext_long_relay_adv_pool[CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT];
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT */
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
|
||||
static inline void init_adv_with_defaults(struct bt_mesh_adv *adv,
|
||||
enum bt_mesh_adv_type type)
|
||||
{
|
||||
memset(adv, 0, sizeof(struct bt_mesh_adv));
|
||||
adv->type = type;
|
||||
adv->adv_itvl = BLE_MESH_ADV_ITVL_DEFAULT;
|
||||
adv->adv_cnt = BLE_MESH_ADV_CNT_DEFAULT;
|
||||
adv->channel_map = BLE_MESH_ADV_CHAN_DEFAULT;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_FRIEND
|
||||
/* We reserve one extra buffer for each friendship, since we need to be able
|
||||
* to resend the last sent PDU, which sits separately outside of the queue.
|
||||
*/
|
||||
#define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \
|
||||
CONFIG_BLE_MESH_FRIEND_LPN_COUNT)
|
||||
|
||||
NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT,
|
||||
BLE_MESH_ADV_DATA_SIZE, NULL);
|
||||
|
||||
static bt_mesh_friend_adv_t frnd_adv_pool[FRIEND_BUF_COUNT];
|
||||
#endif
|
||||
|
||||
struct bt_mesh_adv_task {
|
||||
TaskHandle_t handle;
|
||||
#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \
|
||||
(CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \
|
||||
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY)
|
||||
StaticTask_t *task;
|
||||
StackType_t *stack;
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct bt_mesh_adv_task adv_task;
|
||||
static struct bt_mesh_adv_type_manager adv_types[BLE_MESH_ADV_TYPES_NUM];
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
static struct bt_mesh_adv_inst adv_insts[] = {
|
||||
[BLE_MESH_ADV_INST] = {
|
||||
.id = CONFIG_BLE_MESH_ADV_INST_ID,
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
.busy = false,
|
||||
#endif
|
||||
},
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
|
||||
CONFIG_BLE_MESH_GATT_PROXY_SERVER
|
||||
[BLE_MESH_ADV_PROXY_INST] = {
|
||||
.id = CONFIG_BLE_MESH_PROXY_ADV_INST_ID,
|
||||
.busy = false,
|
||||
},
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE
|
||||
[BLE_MESH_RELAY_ADV_INST] = {
|
||||
.id = CONFIG_BLE_MESH_RELAY_ADV_INST_ID,
|
||||
.busy = false,
|
||||
},
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
|
||||
[BLE_MESH_BLE_ADV_INST] = {
|
||||
.id = CONFIG_BLE_MESH_BLE_ADV_INST_ID,
|
||||
.busy = false,
|
||||
},
|
||||
#endif
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
|
||||
};
|
||||
|
||||
static struct bt_mesh_adv_inst *find_adv_inst_with_inst_id(uint8_t id)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(adv_insts); i++) {
|
||||
if (adv_insts[i].id == id) {
|
||||
return &adv_insts[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_adv_inst *bt_mesh_get_adv_insts_set(void)
|
||||
{
|
||||
return adv_insts;
|
||||
}
|
||||
|
||||
bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id)
|
||||
{
|
||||
return (find_adv_inst_with_inst_id(adv_inst_id) != NULL);
|
||||
}
|
||||
|
||||
int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id)
|
||||
{
|
||||
if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) {
|
||||
BT_ERR("Invalid instance type %d", inst_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inst_id == BLE_MESH_ADV_INS_UNUSED) {
|
||||
BT_ERR("Invalid instance id %d", inst_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adv_insts[inst_type].id = inst_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type)
|
||||
{
|
||||
if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) {
|
||||
BT_ERR("Invalid instance type %d", inst_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bt_le_ext_adv_stop(adv_insts[inst_type].id);
|
||||
|
||||
adv_insts[inst_type].id = BLE_MESH_ADV_INS_UNUSED;
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
adv_insts[inst_type].spt_mask = 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
|
||||
static struct bt_mesh_adv *adv_alloc(int id, enum bt_mesh_adv_type type)
|
||||
{
|
||||
init_adv_with_defaults(&adv_pool[id], type);
|
||||
return &adv_pool[id];
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
struct bt_mesh_adv *ext_adv_alloc(int id, enum bt_mesh_adv_type type)
|
||||
{
|
||||
init_adv_with_defaults(&ext_adv_pool[id].adv, type);
|
||||
ext_adv_pool[id].primary_phy = BLE_MESH_ADV_PRI_PHY_DEFAULT;
|
||||
ext_adv_pool[id].secondary_phy = BLE_MESH_ADV_SEC_PHY_DEFAULT;
|
||||
ext_adv_pool[id].include_tx_power = BLE_MESH_TX_POWER_INCLUDE_DEFAULT;
|
||||
ext_adv_pool[id].tx_power = BLE_MESH_TX_POWER_DEFAULT;
|
||||
return &ext_adv_pool[id].adv;
|
||||
}
|
||||
#if CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT
|
||||
struct bt_mesh_adv *ext_relay_adv_alloc(int id, enum bt_mesh_adv_type type)
|
||||
{
|
||||
init_adv_with_defaults(&ext_relay_adv_pool[id].adv, type);
|
||||
ext_relay_adv_pool[id].primary_phy = BLE_MESH_ADV_PRI_PHY_DEFAULT;
|
||||
ext_relay_adv_pool[id].secondary_phy = BLE_MESH_ADV_SEC_PHY_DEFAULT;
|
||||
ext_relay_adv_pool[id].include_tx_power = BLE_MESH_TX_POWER_INCLUDE_DEFAULT;
|
||||
ext_relay_adv_pool[id].tx_power = BLE_MESH_TX_POWER_DEFAULT;
|
||||
return &ext_relay_adv_pool[id].adv;
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
struct bt_mesh_adv *ext_long_adv_alloc(int id, enum bt_mesh_adv_type type)
|
||||
{
|
||||
init_adv_with_defaults(&ext_long_adv_pool[id].adv, type);
|
||||
ext_long_adv_pool[id].primary_phy = BLE_MESH_ADV_PRI_PHY_DEFAULT;
|
||||
ext_long_adv_pool[id].secondary_phy = BLE_MESH_ADV_SEC_PHY_DEFAULT;
|
||||
ext_long_adv_pool[id].include_tx_power = BLE_MESH_TX_POWER_INCLUDE_DEFAULT;
|
||||
ext_long_adv_pool[id].tx_power = BLE_MESH_TX_POWER_DEFAULT;
|
||||
return &ext_long_adv_pool[id].adv;
|
||||
}
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT
|
||||
struct bt_mesh_adv *ext_long_relay_adv_alloc(int id, enum bt_mesh_adv_type type)
|
||||
{
|
||||
init_adv_with_defaults(&ext_long_relay_adv_pool[id].adv, type);
|
||||
ext_long_relay_adv_pool[id].primary_phy = BLE_MESH_ADV_PRI_PHY_DEFAULT;
|
||||
ext_long_relay_adv_pool[id].secondary_phy = BLE_MESH_ADV_SEC_PHY_DEFAULT;
|
||||
ext_long_relay_adv_pool[id].include_tx_power = BLE_MESH_TX_POWER_INCLUDE_DEFAULT;
|
||||
ext_long_relay_adv_pool[id].tx_power = BLE_MESH_TX_POWER_DEFAULT;
|
||||
return &ext_long_relay_adv_pool[id].adv;
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT */
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
|
||||
struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type)
|
||||
{
|
||||
return &adv_types[adv_type];
|
||||
}
|
||||
|
||||
void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf,
|
||||
uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag)
|
||||
{
|
||||
if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case BLE_MESH_BUF_REF_EQUAL:
|
||||
if (buf->ref != ref_cmp) {
|
||||
BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp);
|
||||
}
|
||||
break;
|
||||
case BLE_MESH_BUF_REF_SMALL:
|
||||
if (buf->ref >= ref_cmp) {
|
||||
BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
void bt_mesh_adv_inst_type_add(enum bt_mesh_adv_inst_type inst_type,
|
||||
enum bt_mesh_adv_type adv_type)
|
||||
{
|
||||
if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) {
|
||||
BT_ERR("Invalid instance type %d", inst_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (adv_type >= BLE_MESH_ADV_TYPES_NUM) {
|
||||
BT_ERR("Invalid adv type %d", adv_type);
|
||||
return;
|
||||
}
|
||||
|
||||
adv_insts[inst_type].spt_mask |= BIT(adv_type);
|
||||
}
|
||||
|
||||
void bt_mesh_adv_inst_type_rm(enum bt_mesh_adv_inst_type inst_type,
|
||||
enum bt_mesh_adv_type adv_type)
|
||||
{
|
||||
if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) {
|
||||
BT_ERR("Invalid instance type %d", inst_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (adv_type >= BLE_MESH_ADV_TYPES_NUM) {
|
||||
BT_ERR("Invalid adv type %d", adv_type);
|
||||
return;
|
||||
}
|
||||
|
||||
adv_insts[inst_type].spt_mask &= ~BIT(adv_type);
|
||||
}
|
||||
|
||||
void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type,
|
||||
enum bt_mesh_adv_type adv_type)
|
||||
{
|
||||
if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) {
|
||||
BT_ERR("Invalid instance type %d", inst_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (adv_type >= BLE_MESH_ADV_TYPES_NUM) {
|
||||
BT_ERR("Invalid adv type %d", adv_type);
|
||||
return;
|
||||
}
|
||||
|
||||
adv_insts[inst_type].spt_mask = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, uint16_t queue_size,
|
||||
bt_mesh_adv_queue_send_cb_t cb)
|
||||
{
|
||||
if (!adv_queue || !queue_size || !cb) {
|
||||
BT_ERR("Invalid param %s", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bt_mesh_queue_init(&adv_queue->q, queue_size, sizeof(bt_mesh_msg_t));
|
||||
|
||||
adv_queue->send = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue)
|
||||
{
|
||||
if (!adv_queue) {
|
||||
BT_ERR("Invalid param %s", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bt_mesh_queue_deinit(&adv_queue->q);
|
||||
|
||||
adv_queue->send = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type,
|
||||
struct bt_mesh_adv_queue *adv_queue,
|
||||
struct net_buf_pool *buf_pool,
|
||||
bt_mesh_pool_allocator_t adv_alloc)
|
||||
{
|
||||
if (adv_type >= BLE_MESH_ADV_TYPES_NUM) {
|
||||
BT_ERR("%s Invalid adv type %d",__func__, adv_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!adv_queue || !buf_pool || !adv_alloc) {
|
||||
BT_ERR("Invalid parameters %s", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
adv_types[adv_type].adv_q = adv_queue;
|
||||
adv_types[adv_type].pool = buf_pool;
|
||||
adv_types[adv_type].pool_allocator = adv_alloc;
|
||||
}
|
||||
|
||||
void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type)
|
||||
{
|
||||
if (adv_type >= BLE_MESH_ADV_TYPES_NUM) {
|
||||
BT_ERR("%s Invalid adv type %d",__func__, adv_type);
|
||||
return;
|
||||
}
|
||||
|
||||
adv_types[adv_type].adv_q = NULL;
|
||||
adv_types[adv_type].pool = NULL;
|
||||
adv_types[adv_type].pool_allocator = NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
int bt_mesh_adv_task_wakeup(uint32_t evt)
|
||||
{
|
||||
xTaskNotify(adv_task.handle, evt, eSetBits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bt_mesh_adv_task_wait(uint32_t wait_bits, uint32_t timeout, uint32_t *notify)
|
||||
{
|
||||
return (xTaskNotifyWait(wait_bits, UINT32_MAX, notify, K_WAIT(timeout)) == pdTRUE);
|
||||
}
|
||||
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
bool bt_mesh_adv_task_wait(uint32_t timeout)
|
||||
{
|
||||
vTaskDelay(K_WAIT(timeout));
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
|
||||
uint16_t bt_mesh_pdu_duration(uint8_t xmit)
|
||||
{
|
||||
uint16_t duration = 0U;
|
||||
uint16_t adv_int = 0U;
|
||||
|
||||
adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit));
|
||||
duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10);
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, int32_t timeout)
|
||||
{
|
||||
struct bt_mesh_adv *adv = NULL;
|
||||
struct net_buf *buf = NULL;
|
||||
|
||||
if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) {
|
||||
BT_WARN("Refusing to allocate buffer while suspended");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (type >= BLE_MESH_ADV_TYPES_NUM) {
|
||||
BT_ERR("%s, Invalid adv type %u", __func__, type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (adv_types[type].pool == NULL || adv_types[type].pool_allocator == NULL) {
|
||||
BT_ERR("Uninitialized adv type %d", type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bt_mesh_r_mutex_lock(&adv_buf_alloc_lock);
|
||||
|
||||
buf = net_buf_alloc(adv_types[type].pool, timeout);
|
||||
if (!buf) {
|
||||
bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock);
|
||||
BT_WARN("Buf alloc failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BT_DBG("pool %p, buf_count %d, uinit_count %d, ref %d",
|
||||
adv_types[type].pool, adv_types[type].pool->buf_count,
|
||||
adv_types[type].pool->uninit_count, buf->ref);
|
||||
|
||||
adv = adv_types[type].pool_allocator(net_buf_id(buf), type);
|
||||
BLE_MESH_ADV(buf) = adv;
|
||||
bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool)
|
||||
{
|
||||
if (pool == NULL) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < pool->buf_count; i++) {
|
||||
struct net_buf *buf = &pool->__bufs[i];
|
||||
if (buf->ref > 1U) {
|
||||
buf->ref = 1U;
|
||||
}
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_unref_buf(bt_mesh_msg_t *msg)
|
||||
{
|
||||
struct net_buf *buf = msg->arg;
|
||||
|
||||
if (buf) {
|
||||
bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0);
|
||||
if (buf->ref > 1U) {
|
||||
buf->ref = 1U;
|
||||
}
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit,
|
||||
const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data, uint16_t src,
|
||||
uint16_t dst, bool front)
|
||||
{
|
||||
bt_mesh_msg_t msg = {
|
||||
.relay = false, /* useless flag in multi-instance mode */
|
||||
};
|
||||
|
||||
BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len,
|
||||
bt_hex(buf->data, buf->len));
|
||||
|
||||
BLE_MESH_ADV(buf)->cb = cb;
|
||||
BLE_MESH_ADV(buf)->cb_data = cb_data;
|
||||
bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1);
|
||||
BLE_MESH_ADV(buf)->xmit = xmit;
|
||||
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||
|
||||
msg.arg = (void *)net_buf_ref(buf);
|
||||
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_RELAY_DATA) {
|
||||
msg.relay = true;
|
||||
msg.src = src;
|
||||
msg.dst = dst;
|
||||
msg.timestamp = k_uptime_get_32();
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q);
|
||||
assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q->send);
|
||||
|
||||
adv_types[BLE_MESH_ADV(buf)->type].adv_q->send(&msg, portMAX_DELAY, front);
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
bt_mesh_adv_task_wakeup(ADV_TASK_PKT_SEND_EVT);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void)
|
||||
{
|
||||
return &adv_queue;
|
||||
}
|
||||
|
||||
void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front)
|
||||
{
|
||||
if (adv_queue.q.handle == NULL) {
|
||||
BT_ERR("Invalid adv queue");
|
||||
return;
|
||||
}
|
||||
|
||||
if (front) {
|
||||
if (xQueueSendToFront(adv_queue.q.handle, msg, timeout) != pdTRUE) {
|
||||
BT_ERR("Failed to send item to adv queue front");
|
||||
bt_mesh_unref_buf(msg);
|
||||
}
|
||||
} else {
|
||||
if (xQueueSend(adv_queue.q.handle, msg, timeout) != pdTRUE) {
|
||||
BT_ERR("Failed to send item to adv queue back");
|
||||
bt_mesh_unref_buf(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
bool bt_mesh_ignore_relay_packet(uint32_t timestamp)
|
||||
{
|
||||
uint32_t now = k_uptime_get_32();
|
||||
uint32_t interval = 0U;
|
||||
|
||||
if (now >= timestamp) {
|
||||
interval = now - timestamp;
|
||||
} else {
|
||||
interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1;
|
||||
}
|
||||
|
||||
return ((interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false);
|
||||
}
|
||||
|
||||
static struct bt_mesh_adv *relay_adv_alloc(int id, enum bt_mesh_adv_type type)
|
||||
{
|
||||
memset(&relay_adv_pool[id], 0, sizeof(struct bt_mesh_adv));
|
||||
init_adv_with_defaults(&relay_adv_pool[id], type);
|
||||
return &relay_adv_pool[id];
|
||||
}
|
||||
|
||||
static void bt_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front)
|
||||
{
|
||||
bt_mesh_msg_t old_msg = {0};
|
||||
|
||||
ARG_UNUSED(front);
|
||||
|
||||
if (relay_adv_queue.q.handle == NULL) {
|
||||
BT_ERR("Invalid relay queue");
|
||||
return;
|
||||
}
|
||||
|
||||
if (xQueueSend(relay_adv_queue.q.handle, msg, timeout) == pdTRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If failed to send packet to the relay queue(queue is full), we will
|
||||
* remove the oldest packet in the queue and put the new one into it.
|
||||
*/
|
||||
if (uxQueueMessagesWaiting(relay_adv_queue.q.handle)) {
|
||||
BT_INFO("Full queue, remove the oldest relay packet");
|
||||
/* Remove the oldest relay packet from queue */
|
||||
if (xQueueReceive(relay_adv_queue.q.handle, &old_msg, K_NO_WAIT) != pdTRUE) {
|
||||
BT_ERR("Failed to remove item from relay queue");
|
||||
bt_mesh_unref_buf(msg);
|
||||
return;
|
||||
}
|
||||
/* Unref buf used for the oldest relay packet */
|
||||
bt_mesh_unref_buf(&old_msg);
|
||||
/* Send the latest relay packet to queue */
|
||||
if (xQueueSend(relay_adv_queue.q.handle, msg, K_NO_WAIT) != pdTRUE) {
|
||||
BT_ERR("Failed to send item to relay queue");
|
||||
bt_mesh_unref_buf(msg);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
BT_WARN("Empty queue, but failed to send the relay packet");
|
||||
bt_mesh_unref_buf(msg);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t bt_mesh_get_stored_relay_count(void)
|
||||
{
|
||||
return (uint16_t)uxQueueMessagesWaiting(relay_adv_queue.q.handle);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE
|
||||
uint16_t bt_mesh_relay_adv_buf_count_get(void)
|
||||
{
|
||||
uint16_t relay_adv_count = 2 + CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT;
|
||||
|
||||
#if CONFIG_BLE_MESH_EXT_ADV && CONFIG_BLE_MESH_RELAY
|
||||
relay_adv_count += CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT;
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET && CONFIG_BLE_MESH_RELAY
|
||||
relay_adv_count += CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT;
|
||||
#endif
|
||||
return relay_adv_count;
|
||||
}
|
||||
|
||||
void bt_mesh_relay_adv_init(void)
|
||||
{
|
||||
bt_mesh_adv_queue_init(&relay_adv_queue, bt_mesh_relay_adv_buf_count_get(),
|
||||
bt_mesh_relay_task_post);
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_RELAY_DATA, &relay_adv_queue,
|
||||
&relay_adv_buf_pool, &relay_adv_alloc);
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_RELAY_DATA, &relay_adv_queue,
|
||||
&ext_adv_buf_pool, &ext_relay_adv_alloc);
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET && CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_LONG_RELAY_DATA, &relay_adv_queue,
|
||||
&ext_long_relay_adv_buf_pool, ext_long_relay_adv_alloc);
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET && CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE
|
||||
bt_mesh_adv_inst_init(BLE_MESH_RELAY_ADV_INST,
|
||||
CONFIG_BLE_MESH_RELAY_ADV_INST_ID);
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_RELAY_DATA);
|
||||
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
#else /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
|
||||
#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
}
|
||||
#if CONFIG_BLE_MESH_DEINIT
|
||||
void bt_mesh_relay_adv_deinit(void)
|
||||
{
|
||||
bt_mesh_adv_queue_deinit(&relay_adv_queue);
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
bt_mesh_adv_inst_deinit(BLE_MESH_RELAY_ADV_INST);
|
||||
#else /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA);
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
|
||||
#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool);
|
||||
memset(relay_adv_pool, 0, sizeof(relay_adv_pool));
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_DEINIT */
|
||||
#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */
|
||||
|
||||
#if CONFIG_BLE_MESH_FRIEND
|
||||
static struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx, enum bt_mesh_adv_type type)
|
||||
{
|
||||
memset(&frnd_adv_pool[idx].adv, 0, sizeof(struct bt_mesh_adv));
|
||||
init_adv_with_defaults(&frnd_adv_pool[idx].adv, type);
|
||||
frnd_adv_pool[idx].app_idx = BLE_MESH_KEY_UNUSED;
|
||||
return &frnd_adv_pool[idx].adv;
|
||||
}
|
||||
|
||||
void bt_mesh_frnd_adv_init(void)
|
||||
{
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_FRIEND, &adv_queue, &friend_buf_pool, bt_mesh_frnd_adv_buf_get);
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_FRIEND);
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
|
||||
}
|
||||
|
||||
void bt_mesh_frnd_adv_deinit(void)
|
||||
{
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_FRIEND);
|
||||
|
||||
#if CONFIG_BLE_MESH_FRIEND && CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_FRIEND);
|
||||
#endif /* CONFIG_BLE_MESH_FRIEND */
|
||||
|
||||
bt_mesh_unref_buf_from_pool(&friend_buf_pool);
|
||||
memset(frnd_adv_pool, 0, sizeof(frnd_adv_pool));
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_FRIEND */
|
||||
|
||||
static ALWAYS_INLINE
|
||||
uint16_t bt_mesh_adv_buf_count_get(void)
|
||||
{
|
||||
uint16_t adv_count = 2 + CONFIG_BLE_MESH_ADV_BUF_COUNT;
|
||||
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
adv_count += CONFIG_BLE_MESH_EXT_ADV_BUF_COUNT;
|
||||
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY
|
||||
adv_count += CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT;
|
||||
#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
adv_count += CONFIG_BLE_MESH_LONG_PACKET_ADV_BUF_COUNT;
|
||||
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY
|
||||
adv_count += CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT;
|
||||
#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY */
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
|
||||
#if (CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \
|
||||
!(CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE))
|
||||
adv_count += CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT;
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
|
||||
|
||||
return adv_count;
|
||||
}
|
||||
|
||||
void bt_mesh_adv_task_init(void adv_thread(void *p))
|
||||
{
|
||||
if (!adv_thread) {
|
||||
BT_ERR("Invalid param %s", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \
|
||||
(CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \
|
||||
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY)
|
||||
adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
assert(adv_task.task);
|
||||
|
||||
adv_task.stack = heap_caps_calloc_prefer(1, BLE_MESH_ADV_TASK_STACK_SIZE * sizeof(StackType_t),
|
||||
2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT,
|
||||
MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
assert(adv_task.stack);
|
||||
|
||||
adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME,
|
||||
BLE_MESH_ADV_TASK_STACK_SIZE, NULL,
|
||||
BLE_MESH_ADV_TASK_PRIO, adv_task.stack,
|
||||
adv_task.task, BLE_MESH_ADV_TASK_CORE);
|
||||
assert(adv_task.handle);
|
||||
#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */
|
||||
int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL,
|
||||
BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE);
|
||||
assert(ret == pdTRUE);
|
||||
#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */
|
||||
}
|
||||
|
||||
void bt_mesh_adv_common_init(void)
|
||||
{
|
||||
bt_mesh_r_mutex_create(&adv_buf_alloc_lock);
|
||||
bt_mesh_adv_queue_init(&adv_queue, bt_mesh_adv_buf_count_get(), bt_mesh_task_post);
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_PROV, &adv_queue, &adv_buf_pool, adv_alloc);
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_DATA, &adv_queue, &adv_buf_pool, adv_alloc);
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_BEACON, &adv_queue, &adv_buf_pool, adv_alloc);
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_URI, &adv_queue, &adv_buf_pool, adv_alloc);
|
||||
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_PROXY_SOLIC, &adv_queue, &adv_buf_pool, adv_alloc);
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
bt_mesh_adv_inst_init(BLE_MESH_ADV_INST, CONFIG_BLE_MESH_ADV_INST_ID);
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_PROV, &adv_queue, &ext_adv_buf_pool, ext_adv_alloc);
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_DATA, &adv_queue, &ext_adv_buf_pool, ext_adv_alloc);
|
||||
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_RELAY_DATA, &adv_queue, &ext_relay_adv_buf_pool, ext_relay_adv_alloc);
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_LONG_PROV, &adv_queue, &ext_long_adv_buf_pool, ext_long_adv_alloc);
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_LONG_DATA, &adv_queue, &ext_long_adv_buf_pool, ext_long_adv_alloc);
|
||||
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_LONG_RELAY_DATA, &adv_queue, &ext_long_relay_adv_buf_pool, ext_long_relay_adv_alloc);
|
||||
#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT */
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
/**
|
||||
* Due to the limitation of the sequence number in the network layer,
|
||||
* it is not possible to use multiple advertising instances to process
|
||||
* data from the same message queue when sending mesh packets.
|
||||
*
|
||||
* Therefore, shall to check whether there are duplicates in the queue
|
||||
* buffer corresponding to each advertising instance.
|
||||
*/
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_PROV);
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_DATA);
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_BEACON);
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_URI);
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_PROV);
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_DATA);
|
||||
#if CONFIG_BLE_MESH_RELAY && !CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA);
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_PROV);
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_DATA);
|
||||
#if CONFIG_BLE_MESH_RELAY && !CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
|
||||
#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_DEINIT
|
||||
void bt_mesh_adv_task_deinit(void)
|
||||
{
|
||||
vTaskDelete(adv_task.handle);
|
||||
adv_task.handle = NULL;
|
||||
|
||||
#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \
|
||||
(CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \
|
||||
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY)
|
||||
heap_caps_free(adv_task.stack);
|
||||
adv_task.stack = NULL;
|
||||
heap_caps_free(adv_task.task);
|
||||
adv_task.task = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bt_mesh_adv_common_deinit(void)
|
||||
{
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_PROV);
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_DATA);
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_BEACON);
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_URI);
|
||||
|
||||
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_PROXY_SOLIC);
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_PROV);
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_DATA);
|
||||
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_RELAY_DATA);
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_LONG_PROV);
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_LONG_DATA);
|
||||
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
|
||||
#endif
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
|
||||
bt_mesh_adv_queue_deinit(&adv_queue);
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
bt_mesh_adv_inst_deinit(BLE_MESH_ADV_INST);
|
||||
#endif
|
||||
|
||||
bt_mesh_unref_buf_from_pool(&adv_buf_pool);
|
||||
memset(adv_pool, 0, sizeof(adv_pool));
|
||||
bt_mesh_r_mutex_free(&adv_buf_alloc_lock);
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_DEINIT */
|
||||
@@ -0,0 +1,352 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Intel Corporation
|
||||
* SPDX-FileContributor: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _ADV_COMMON_H_
|
||||
#define _ADV_COMMON_H_
|
||||
|
||||
#include "mesh/common.h"
|
||||
#include "mesh/atomic.h"
|
||||
#include "mesh/access.h"
|
||||
#include "mesh/adapter.h"
|
||||
#include "mesh/queue.h"
|
||||
#include "mesh/timer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Pre-5.0 controllers enforce a minimum interval of 100ms
|
||||
* whereas 5.0+ controllers can go down to 20ms.
|
||||
*/
|
||||
#if CONFIG_BLE_MESH_HCI_5_0
|
||||
#define ADV_ITVL_MIN 20
|
||||
#else
|
||||
#define ADV_ITVL_MIN 100
|
||||
#endif
|
||||
|
||||
/* Convert from ms to 0.625ms units */
|
||||
#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5)
|
||||
/* Convert from 0.625ms units to interval(ms) */
|
||||
#define ADV_SCAN_INT(val) ((val) * 5 / 8)
|
||||
|
||||
/* Maximum advertising data payload for a single data type */
|
||||
#define BLE_MESH_ADV_DATA_SIZE 29
|
||||
|
||||
/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */
|
||||
#define BLE_MESH_ADV_USER_DATA_SIZE 4
|
||||
|
||||
#define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf))
|
||||
#define BLE_MESH_ADV_BUSY(buf) (BLE_MESH_ADV(buf)->busy)
|
||||
|
||||
#define BLE_MESH_MSG_NET_BUF(msg) ((struct net_buf *)(msg->arg))
|
||||
|
||||
#define BLE_MESH_ADV_INST_UNUSED 0xFF
|
||||
|
||||
struct bt_mesh_adv {
|
||||
const struct bt_mesh_send_cb *cb;
|
||||
void *cb_data;
|
||||
|
||||
uint8_t type;
|
||||
|
||||
bt_mesh_atomic_t busy;
|
||||
|
||||
uint8_t xmit;
|
||||
|
||||
uint32_t adv_itvl;
|
||||
uint8_t adv_cnt;
|
||||
uint8_t channel_map;
|
||||
};
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
#define EXT_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), bt_mesh_ext_adv_t, adv)
|
||||
typedef struct {
|
||||
struct bt_mesh_adv adv;
|
||||
uint8_t primary_phy;
|
||||
uint8_t secondary_phy;
|
||||
uint8_t include_tx_power:1;
|
||||
int8_t tx_power;
|
||||
} bt_mesh_ext_adv_t;
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_FRIEND
|
||||
|
||||
#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), bt_mesh_friend_adv_t, adv)
|
||||
|
||||
typedef struct {
|
||||
struct bt_mesh_adv adv;
|
||||
uint16_t app_idx;
|
||||
} bt_mesh_friend_adv_t;
|
||||
|
||||
#endif
|
||||
|
||||
enum {
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
ADV_TASK_MESH_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_ADV_INST_ID),
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
|
||||
CONFIG_BLE_MESH_GATT_PROXY_SERVER
|
||||
ADV_TASK_PROX_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_PROXY_ADV_INST_ID),
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE
|
||||
ADV_TASK_RELAY_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_RELAY_ADV_INST_ID),
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
|
||||
ADV_TASK_BLE_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_BLE_ADV_INST_ID),
|
||||
#endif
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
|
||||
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
|
||||
CONFIG_BLE_MESH_GATT_PROXY_SERVER
|
||||
ADV_TASK_PROXY_ADV_UPD_EVT = BIT(30),
|
||||
#endif
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
ADV_TASK_PKT_SEND_EVT = BIT(31),
|
||||
ADV_TASK_EVT_MAX,
|
||||
};
|
||||
|
||||
uint16_t bt_mesh_pdu_duration(uint8_t xmit);
|
||||
|
||||
typedef struct bt_mesh_msg {
|
||||
bool relay; /* Flag indicates if the packet is a relayed one */
|
||||
void *arg; /* Pointer to the struct net_buf */
|
||||
uint16_t src; /* Source address for relay packets */
|
||||
uint16_t dst; /* Destination address for relay packets */
|
||||
uint32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */
|
||||
} bt_mesh_msg_t;
|
||||
|
||||
struct bt_mesh_adv_inst {
|
||||
uint8_t id;
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
bool busy;
|
||||
struct net_buf *sending_buf;
|
||||
|
||||
/* Indicate which adv_type is supported by this instance */
|
||||
uint32_t spt_mask;
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
|
||||
};
|
||||
|
||||
enum bt_mesh_adv_type {
|
||||
BLE_MESH_ADV_PROV,
|
||||
BLE_MESH_ADV_DATA,
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
BLE_MESH_ADV_EXT_PROV,
|
||||
BLE_MESH_ADV_EXT_DATA,
|
||||
BLE_MESH_ADV_EXT_RELAY_DATA,
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
BLE_MESH_ADV_EXT_LONG_PROV,
|
||||
BLE_MESH_ADV_EXT_LONG_DATA,
|
||||
BLE_MESH_ADV_EXT_LONG_RELAY_DATA,
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
#if CONFIG_BLE_MESH_FRIEND
|
||||
BLE_MESH_ADV_FRIEND,
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
BLE_MESH_ADV_RELAY_DATA,
|
||||
#endif
|
||||
BLE_MESH_ADV_BEACON,
|
||||
BLE_MESH_ADV_URI,
|
||||
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX
|
||||
BLE_MESH_ADV_PROXY_SOLIC,
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
BLE_MESH_ADV_BLE,
|
||||
#endif
|
||||
BLE_MESH_ADV_TYPES_NUM,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
BLE_MESH_BUF_REF_EQUAL,
|
||||
BLE_MESH_BUF_REF_SMALL,
|
||||
BLE_MESH_BUF_REF_MAX,
|
||||
} bt_mesh_buf_ref_flag_t;
|
||||
|
||||
|
||||
static const uint8_t adv_type[] = {
|
||||
[BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV,
|
||||
[BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
[BLE_MESH_ADV_EXT_PROV] = BLE_MESH_DATA_MESH_PROV,
|
||||
[BLE_MESH_ADV_EXT_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
|
||||
[BLE_MESH_ADV_EXT_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
[BLE_MESH_ADV_EXT_LONG_PROV] = BLE_MESH_DATA_MESH_PROV,
|
||||
[BLE_MESH_ADV_EXT_LONG_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
|
||||
[BLE_MESH_ADV_EXT_LONG_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
#if CONFIG_BLE_MESH_FRIEND
|
||||
[BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE,
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
[BLE_MESH_ADV_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
|
||||
#endif
|
||||
[BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON,
|
||||
[BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI,
|
||||
};
|
||||
|
||||
typedef struct bt_mesh_adv *(*bt_mesh_pool_allocator_t)(int id, enum bt_mesh_adv_type type);
|
||||
typedef void (*bt_mesh_adv_queue_send_cb_t)(bt_mesh_msg_t *msg, uint32_t timeout, bool front);
|
||||
|
||||
struct bt_mesh_adv_type_manager {
|
||||
struct bt_mesh_adv_queue *adv_q;
|
||||
struct net_buf_pool *pool;
|
||||
bt_mesh_pool_allocator_t pool_allocator;
|
||||
};
|
||||
|
||||
struct bt_mesh_adv_queue {
|
||||
bt_mesh_queue_t q;
|
||||
bt_mesh_adv_queue_send_cb_t send;
|
||||
};
|
||||
|
||||
static inline TickType_t K_WAIT(int32_t val)
|
||||
{
|
||||
return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static inline void adv_send_start(uint16_t duration, int err,
|
||||
const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
if (cb && cb->start) {
|
||||
cb->start(duration, err, cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
if (cb && cb->end) {
|
||||
cb->end(err, cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void);
|
||||
|
||||
struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, int32_t timeout);
|
||||
|
||||
static inline struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout)
|
||||
{
|
||||
return bt_mesh_adv_create_from_pool(type, timeout);
|
||||
}
|
||||
|
||||
void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf,
|
||||
uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag);
|
||||
|
||||
struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgmt_get(enum bt_mesh_adv_type adv_type);
|
||||
|
||||
void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit,
|
||||
const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data, uint16_t src,
|
||||
uint16_t dst, bool front);
|
||||
|
||||
static inline void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit,
|
||||
const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, false);
|
||||
}
|
||||
|
||||
void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool);
|
||||
void bt_mesh_unref_buf(bt_mesh_msg_t *msg);
|
||||
|
||||
int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue,
|
||||
uint16_t queue_size,
|
||||
bt_mesh_adv_queue_send_cb_t cb);
|
||||
|
||||
int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue);
|
||||
|
||||
void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type,
|
||||
struct bt_mesh_adv_queue *adv_queue,
|
||||
struct net_buf_pool *buf_pool,
|
||||
bt_mesh_pool_allocator_t adv_alloc);
|
||||
|
||||
void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type);
|
||||
|
||||
void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front);
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
struct bt_mesh_adv_inst * bt_mesh_get_adv_insts_set(void);
|
||||
bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id);
|
||||
int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id);
|
||||
int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type);
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
void bt_mesh_adv_inst_type_add(enum bt_mesh_adv_inst_type inst_type,
|
||||
enum bt_mesh_adv_type adv_type);
|
||||
|
||||
void bt_mesh_adv_inst_type_rm(enum bt_mesh_adv_inst_type inst_type,
|
||||
enum bt_mesh_adv_type adv_type);
|
||||
|
||||
void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type,
|
||||
enum bt_mesh_adv_type adv_type);
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
void bt_mesh_relay_adv_init(void);
|
||||
bool bt_mesh_ignore_relay_packet(uint32_t timestamp);
|
||||
|
||||
static inline void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit,
|
||||
uint16_t src, uint16_t dst,
|
||||
const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, src, dst, false);
|
||||
};
|
||||
|
||||
uint16_t bt_mesh_get_stored_relay_count(void);
|
||||
|
||||
#if CONFIG_BLE_MESH_DEINIT
|
||||
void bt_mesh_relay_adv_deinit(void);
|
||||
#endif
|
||||
#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */
|
||||
|
||||
#if CONFIG_BLE_MESH_FRIEND
|
||||
void bt_mesh_frnd_adv_init(void);
|
||||
#if CONFIG_BLE_MESH_DEINIT
|
||||
void bt_mesh_frnd_adv_deinit(void);
|
||||
#endif /* CONFIG_BLE_MESH_DEINIT */
|
||||
#endif /* CONFIG_BLE_MESH_FRIEND */
|
||||
|
||||
void bt_mesh_adv_task_init(void adv_thread(void *p));
|
||||
void bt_mesh_adv_common_init(void);
|
||||
|
||||
#if CONFIG_BLE_MESH_DEINIT
|
||||
void bt_mesh_adv_task_deinit(void);
|
||||
void bt_mesh_adv_common_deinit(void);
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
int bt_mesh_adv_task_wakeup(uint32_t evt);
|
||||
bool bt_mesh_adv_task_wait(uint32_t wait_bits, TickType_t timeout, uint32_t *notify);
|
||||
#else
|
||||
bool bt_mesh_adv_task_wait(uint32_t timeout);
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
static inline void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data, bool front)
|
||||
{
|
||||
bt_mesh_generic_adv_send(buf, 0, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, front);
|
||||
}
|
||||
|
||||
int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
|
||||
const struct bt_mesh_ble_adv_data *data, uint8_t *index);
|
||||
|
||||
int bt_mesh_stop_ble_advertising(uint8_t index);
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ADV_COMMON_H_ */
|
||||
@@ -0,0 +1,331 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Intel Corporation
|
||||
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ble_adv.h"
|
||||
#include "mesh/common.h"
|
||||
#include "mesh/buf.h"
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
|
||||
/* Use independent ble adv queue only if multi adv instance is used */
|
||||
static struct bt_mesh_adv_queue ble_adv_queue;
|
||||
static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front);
|
||||
#endif
|
||||
|
||||
static struct bt_mesh_adv_queue *p_ble_adv_queue;
|
||||
|
||||
/* length + advertising data + length + scan response data */
|
||||
NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT,
|
||||
((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
|
||||
static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
|
||||
|
||||
static struct bt_mesh_ble_adv_tx ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
|
||||
|
||||
#define SEND_BLE_ADV_INFINITE 0xFFFF
|
||||
|
||||
static struct bt_mesh_adv *ble_adv_alloc(int id, enum bt_mesh_adv_type type)
|
||||
{
|
||||
memset(&ble_adv_pool[id], 0, sizeof(struct bt_mesh_adv));
|
||||
ble_adv_pool[id].type = type;
|
||||
return &ble_adv_pool[id];
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
|
||||
/* A separate post function is required only when using a separate queue */
|
||||
static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front)
|
||||
{
|
||||
BT_DBG("%s", __func__);
|
||||
|
||||
if (p_ble_adv_queue->q.handle == NULL) {
|
||||
BT_ERR("Invalid adv queue");
|
||||
return;
|
||||
}
|
||||
|
||||
if (front) {
|
||||
if (xQueueSendToFront(p_ble_adv_queue->q.handle, msg, timeout) != pdTRUE) {
|
||||
BT_ERR("Failed to send item to adv queue front");
|
||||
bt_mesh_unref_buf(msg);
|
||||
}
|
||||
} else {
|
||||
if (xQueueSend(p_ble_adv_queue->q.handle, msg, timeout) != pdTRUE) {
|
||||
BT_ERR("Failed to send item to adv queue back");
|
||||
bt_mesh_unref_buf(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ble_adv_tx_reset(struct bt_mesh_ble_adv_tx *tx, bool unref)
|
||||
{
|
||||
if (tx->buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) {
|
||||
k_delayed_work_free(&tx->resend);
|
||||
}
|
||||
bt_mesh_atomic_set(tx->flags, 0);
|
||||
memset(&tx->param, 0, sizeof(tx->param));
|
||||
bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->buf), 0);
|
||||
if (unref) {
|
||||
net_buf_unref(tx->buf);
|
||||
}
|
||||
tx->buf = NULL;
|
||||
}
|
||||
|
||||
static void ble_adv_send_start(uint16_t duration, int err, void *cb_data)
|
||||
{
|
||||
struct bt_mesh_ble_adv_tx *tx = cb_data;
|
||||
|
||||
BT_DBG("%s, duration %d, err %d", __func__, duration, err);
|
||||
|
||||
/* If failed to send BLE adv packet, and param->count is not 0
|
||||
* which means the timer has been initialized, here we need to
|
||||
* free the timer.
|
||||
*/
|
||||
if (err) {
|
||||
ble_adv_tx_reset(tx, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void ble_adv_send_end(int err, void *cb_data)
|
||||
{
|
||||
struct bt_mesh_ble_adv_tx *tx = cb_data;
|
||||
|
||||
BT_DBG("%s, err %d", __func__, err);
|
||||
|
||||
if (err) {
|
||||
ble_adv_tx_reset(tx, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tx->param.count) {
|
||||
if (tx->param.period) {
|
||||
k_delayed_work_submit(&tx->resend, tx->param.period);
|
||||
} else {
|
||||
k_work_submit(&tx->resend.work);
|
||||
}
|
||||
} else {
|
||||
ble_adv_tx_reset(tx, true);
|
||||
}
|
||||
}
|
||||
|
||||
static struct bt_mesh_send_cb ble_adv_send_cb = {
|
||||
.start = ble_adv_send_start,
|
||||
.end = ble_adv_send_end,
|
||||
};
|
||||
|
||||
static void ble_adv_resend(struct k_work *work)
|
||||
{
|
||||
struct bt_mesh_ble_adv_tx *tx = CONTAINER_OF(work, struct bt_mesh_ble_adv_tx, resend.work);
|
||||
bool front = false;
|
||||
|
||||
if (tx->buf == NULL) {
|
||||
/* The advertising has been cancelled */
|
||||
return;
|
||||
}
|
||||
|
||||
front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false;
|
||||
bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front);
|
||||
|
||||
if (tx->param.count == SEND_BLE_ADV_INFINITE) {
|
||||
/* Send the BLE advertising packet infinitely */
|
||||
return;
|
||||
}
|
||||
|
||||
if (tx->param.count > 0U) {
|
||||
tx->param.count--;
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
|
||||
const struct bt_mesh_ble_adv_data *data, uint8_t *index)
|
||||
{
|
||||
struct bt_mesh_ble_adv_tx *tx = NULL;
|
||||
struct net_buf *buf = NULL;
|
||||
bool front = false;
|
||||
|
||||
if (param == NULL || index == NULL) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->adv_type != BLE_MESH_ADV_DIRECT_IND &&
|
||||
(param->interval < 0x20 || param->interval > 0x4000)) {
|
||||
BT_ERR("Invalid adv interval 0x%04x", param->interval);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
|
||||
BT_ERR("Invalid adv type 0x%02x", param->adv_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) {
|
||||
BT_ERR("Invalid own addr type 0x%02x", param->own_addr_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID ||
|
||||
param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID ||
|
||||
param->adv_type == BLE_MESH_ADV_DIRECT_IND ||
|
||||
param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) &&
|
||||
param->peer_addr_type > BLE_MESH_ADDR_RANDOM) {
|
||||
BT_ERR("Invalid peer addr type 0x%02x", param->peer_addr_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) {
|
||||
BT_ERR("Invalid adv data length (adv %d, scan rsp %d)",
|
||||
data->adv_data_len, data->scan_rsp_data_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) {
|
||||
BT_ERR("Invalid adv priority %d", param->priority);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->duration < ADV_SCAN_INT(param->interval)) {
|
||||
BT_ERR("Too small duration %dms", param->duration);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = bt_mesh_adv_create(BLE_MESH_ADV_BLE, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
BT_ERR("No empty ble adv buffer");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
/* Set advertising data and scan response data */
|
||||
memset(buf->data, 0, buf->size);
|
||||
if (data) {
|
||||
net_buf_add_u8(buf, data->adv_data_len);
|
||||
if (data->adv_data_len) {
|
||||
net_buf_add_mem(buf, data->adv_data, data->adv_data_len);
|
||||
}
|
||||
net_buf_add_u8(buf, data->scan_rsp_data_len);
|
||||
if (data->scan_rsp_data_len) {
|
||||
net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len);
|
||||
}
|
||||
}
|
||||
|
||||
*index = net_buf_id(buf);
|
||||
tx = &ble_adv_tx[*index];
|
||||
tx->buf = buf;
|
||||
memcpy(&tx->param, param, sizeof(tx->param));
|
||||
|
||||
front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false;
|
||||
bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front);
|
||||
if (param->count) {
|
||||
if (k_delayed_work_init(&tx->resend, ble_adv_resend)) {
|
||||
/* If failed to create a timer, the BLE adv packet will be
|
||||
* sent only once. Just give a warning here, and since the
|
||||
* BLE adv packet can be sent, return 0 here.
|
||||
*/
|
||||
BT_WARN("Send BLE adv packet only once");
|
||||
tx->param.count = 0;
|
||||
net_buf_unref(buf);
|
||||
return 0;
|
||||
}
|
||||
bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT);
|
||||
} else {
|
||||
/* Send the BLE advertising packet only once */
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_stop_ble_advertising(uint8_t index)
|
||||
{
|
||||
struct bt_mesh_ble_adv_tx *tx = NULL;
|
||||
bool unref = true;
|
||||
|
||||
if (index >= ARRAY_SIZE(ble_adv_tx)) {
|
||||
BT_ERR("Invalid adv index %d", index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tx = &ble_adv_tx[index];
|
||||
|
||||
if (tx->buf == NULL) {
|
||||
BT_WARN("Already stopped, index %d", index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* busy 1, ref 1; busy 1, ref 2;
|
||||
* busy 0, ref 0; busy 0, ref 1;
|
||||
*/
|
||||
|
||||
if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf)) &&
|
||||
tx->buf->ref == 1U) {
|
||||
unref = false;
|
||||
}
|
||||
ble_adv_tx_reset(tx, unref);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bt_mesh_adv_queue *bt_mesh_ble_adv_queue_get(void)
|
||||
{
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
|
||||
bt_mesh_adv_queue_init(&ble_adv_queue, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, bt_mesh_ble_task_post);
|
||||
return &ble_adv_queue;
|
||||
#else
|
||||
return bt_mesh_adv_queue_get();
|
||||
#endif
|
||||
}
|
||||
|
||||
void bt_mesh_ble_adv_init(void)
|
||||
{
|
||||
p_ble_adv_queue = bt_mesh_ble_adv_queue_get();
|
||||
bt_mesh_adv_type_init(BLE_MESH_ADV_BLE, p_ble_adv_queue, &ble_adv_buf_pool, ble_adv_alloc);
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
|
||||
bt_mesh_adv_inst_init(BLE_MESH_BLE_ADV_INST, CONFIG_BLE_MESH_BLE_ADV_INST_ID);
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_BLE_ADV_INST, BLE_MESH_ADV_BLE);
|
||||
#else
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_BLE);
|
||||
#endif
|
||||
#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_DEINIT
|
||||
void bt_mesh_ble_adv_deinit(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) {
|
||||
ble_adv_tx_reset(&ble_adv_tx[i], false);
|
||||
}
|
||||
bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool);
|
||||
memset(ble_adv_pool, 0, sizeof(ble_adv_pool));
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
|
||||
/* In other cases, ble_adv queue is an adv queue,
|
||||
* so ble does not need to deinit separately */
|
||||
bt_mesh_adv_queue_deinit(p_ble_adv_queue);
|
||||
#endif
|
||||
bt_mesh_adv_type_deinit(BLE_MESH_ADV_BLE);
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
|
||||
bt_mesh_adv_inst_deinit(BLE_MESH_BLE_ADV_INST);
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_BLE_ADV_INST, BLE_MESH_ADV_BLE);
|
||||
#else
|
||||
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
|
||||
bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_BLE);
|
||||
#endif
|
||||
#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_DEINIT */
|
||||
@@ -0,0 +1,454 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Intel Corporation
|
||||
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mesh/kernel.h"
|
||||
#include "mesh.h"
|
||||
#include "mesh/hci.h"
|
||||
#include "mesh/common.h"
|
||||
#include "mesh/ffs.h"
|
||||
#include "ext_adv.h"
|
||||
#include "beacon.h"
|
||||
#include "prov_common.h"
|
||||
#include "foundation.h"
|
||||
#include "proxy_server.h"
|
||||
#include "proxy_client.h"
|
||||
#include "prov_pvnr.h"
|
||||
#include "mesh/adapter.h"
|
||||
|
||||
#include "adv_common.h"
|
||||
#include "ble_adv.h"
|
||||
|
||||
static struct bt_mesh_adv_inst *adv_insts;
|
||||
|
||||
static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration)
|
||||
{
|
||||
struct net_buf *buf = inst->sending_buf;
|
||||
const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb;
|
||||
void *cb_data = BLE_MESH_ADV(buf)->cb_data;
|
||||
struct bt_mesh_adv_param param = {0};
|
||||
uint16_t duration = 0U, adv_int = 0U;
|
||||
uint8_t adv_cnt = 0;
|
||||
struct bt_mesh_adv_data ad = {0};
|
||||
int err = 0;
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
uint8_t is_ext_adv = false;
|
||||
#endif
|
||||
|
||||
BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type,
|
||||
buf->len, bt_hex(buf->data, buf->len));
|
||||
|
||||
switch (BLE_MESH_ADV(buf)->type) {
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
case BLE_MESH_ADV_EXT_PROV:
|
||||
case BLE_MESH_ADV_EXT_DATA:
|
||||
case BLE_MESH_ADV_EXT_RELAY_DATA:
|
||||
#if CONFIG_BLE_MESH_LONG_PACKET
|
||||
case BLE_MESH_ADV_EXT_LONG_PROV:
|
||||
case BLE_MESH_ADV_EXT_LONG_DATA:
|
||||
case BLE_MESH_ADV_EXT_LONG_RELAY_DATA:
|
||||
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
|
||||
{
|
||||
is_ext_adv = true;
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_EXT_ADV */
|
||||
case BLE_MESH_ADV_PROV:
|
||||
case BLE_MESH_ADV_DATA:
|
||||
#if CONFIG_BLE_MESH_FRIEND
|
||||
case BLE_MESH_ADV_FRIEND:
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
case BLE_MESH_ADV_RELAY_DATA:
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX
|
||||
case BLE_MESH_ADV_PROXY_SOLIC:
|
||||
#endif
|
||||
case BLE_MESH_ADV_BEACON:
|
||||
case BLE_MESH_ADV_URI: {
|
||||
#if CONFIG_BLE_MESH_EXT_ADV
|
||||
if (is_ext_adv) {
|
||||
param.primary_phy = EXT_ADV(buf)->primary_phy;
|
||||
param.secondary_phy = EXT_ADV(buf)->secondary_phy;
|
||||
param.include_tx_power = EXT_ADV(buf)->include_tx_power;
|
||||
param.tx_power = EXT_ADV(buf)->tx_power;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
param.primary_phy = BLE_MESH_ADV_PRI_PHY_DEFAULT;
|
||||
param.secondary_phy = BLE_MESH_ADV_SEC_PHY_DEFAULT;
|
||||
param.include_tx_power = BLE_MESH_TX_POWER_INCLUDE_DEFAULT;
|
||||
param.tx_power = BLE_MESH_TX_POWER_DEFAULT;
|
||||
}
|
||||
|
||||
if (BLE_MESH_ADV(buf)->adv_itvl != BLE_MESH_ADV_ITVL_DEFAULT) {
|
||||
adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_ADV(buf)->adv_itvl);
|
||||
} else {
|
||||
adv_int = MAX(ADV_ITVL_MIN,
|
||||
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
|
||||
}
|
||||
|
||||
if (BLE_MESH_ADV(buf)->adv_cnt != BLE_MESH_ADV_CNT_DEFAULT) {
|
||||
adv_cnt = BLE_MESH_ADV(buf)->adv_cnt;
|
||||
} else {
|
||||
adv_cnt = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1;
|
||||
}
|
||||
|
||||
duration = adv_cnt * (adv_int + 10);
|
||||
|
||||
BT_DBG("count %u interval %ums duration %ums",
|
||||
adv_cnt, adv_int, duration);
|
||||
|
||||
ad.type = adv_type[BLE_MESH_ADV(buf)->type];
|
||||
ad.data_len = buf->len;
|
||||
ad.data = buf->data;
|
||||
|
||||
param.options = 0U;
|
||||
param.interval_min = ADV_SCAN_UNIT(adv_int);
|
||||
param.interval_max = param.interval_min;
|
||||
|
||||
param.adv_duration = duration;
|
||||
param.adv_count = adv_cnt;
|
||||
|
||||
if (BLE_MESH_ADV(buf)->channel_map) {
|
||||
param.channel_map = BLE_MESH_ADV(buf)->channel_map;
|
||||
} else {
|
||||
param.channel_map = BLE_MESH_ADV_CHAN_DEFAULT;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX
|
||||
if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) {
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||
struct bt_mesh_adv_data solic_ad[2] = {
|
||||
BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18),
|
||||
BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len),
|
||||
};
|
||||
err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL);
|
||||
err = bt_le_ext_adv_start(inst->id, ¶m, &ad, 1, NULL, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
case BLE_MESH_ADV_BLE:
|
||||
struct bt_mesh_ble_adv_data data = {0};
|
||||
struct bt_mesh_ble_adv_tx *tx = cb_data;
|
||||
|
||||
if (tx == NULL) {
|
||||
BT_ERR("Invalid adv user data");
|
||||
net_buf_unref(buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_DBG("interval %dms, duration %dms, period %dms, count %d",
|
||||
ADV_SCAN_INT(tx->param.interval), tx->param.duration,
|
||||
tx->param.period, tx->param.count);
|
||||
|
||||
data.adv_data_len = tx->buf->data[0];
|
||||
if (data.adv_data_len) {
|
||||
memcpy(data.adv_data, tx->buf->data + 1, data.adv_data_len);
|
||||
}
|
||||
data.scan_rsp_data_len = tx->buf->data[data.adv_data_len + 1];
|
||||
if (data.scan_rsp_data_len) {
|
||||
memcpy(data.scan_rsp_data, tx->buf->data + data.adv_data_len + 2, data.scan_rsp_data_len);
|
||||
}
|
||||
duration = tx->param.duration;
|
||||
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||
|
||||
err = bt_mesh_ble_ext_adv_start(inst->id, &tx->param, &data);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
BT_ERR("Error Type");
|
||||
break;
|
||||
}
|
||||
|
||||
adv_send_start(duration, err, cb, cb_data);
|
||||
if (err) {
|
||||
BT_ERR("Start advertising failed: err %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
*adv_duration = duration;
|
||||
BT_DBG("Advertising started. %u ms", duration);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t *msg)
|
||||
{
|
||||
while(uxQueueMessagesWaiting(msg_queue->handle)) {
|
||||
xQueueReceive(msg_queue->handle, msg, K_WAIT(K_FOREVER));
|
||||
|
||||
/* In the previous adv task design, only the *buf of messages pushed to the queue
|
||||
* by adv_update would be empty, but in the new design, there is a new processing
|
||||
* method for adv_update's messages, so *buf here cannot be empty.
|
||||
*/
|
||||
assert(msg->arg);
|
||||
|
||||
/* If the message is cancelled for advertising, then continue to retrieve the next
|
||||
* message from that queue.
|
||||
*/
|
||||
if (!bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(BLE_MESH_MSG_NET_BUF(msg)), 1, 0)) {
|
||||
bt_mesh_adv_buf_ref_debug(__func__, BLE_MESH_MSG_NET_BUF(msg), 1U, BLE_MESH_BUF_REF_EQUAL);
|
||||
/* Cancel the adv task's reference to this data packet.
|
||||
* Tips:
|
||||
* The reference of buffer by adv_task occurs when the buffer is pushed into
|
||||
* the queue.
|
||||
*/
|
||||
net_buf_unref(BLE_MESH_MSG_NET_BUF(msg));
|
||||
|
||||
/* Avoid reading the last message in the queue, which could lead to pointing
|
||||
* to an invalid buffer due to the absence of other messages in the queue.
|
||||
*/
|
||||
msg->arg = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
/* If the relay message should be ignored, then continue to retrieve the next message
|
||||
* from that queue.
|
||||
*/
|
||||
if (msg->relay && bt_mesh_ignore_relay_packet(msg->timestamp)) {
|
||||
/* If the interval between "current time - msg.timestamp" is bigger than
|
||||
* BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent.
|
||||
*/
|
||||
BT_DBG("Ignore relay packet");
|
||||
net_buf_unref(BLE_MESH_MSG_NET_BUF(msg));
|
||||
msg->arg = NULL;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg->arg == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int activate_idle_adv_instance(uint32_t *update_evts, uint16_t *min_duration)
|
||||
{
|
||||
uint16_t cur_min_duration = K_FOREVER;
|
||||
enum bt_mesh_adv_type adv_type = 0;
|
||||
bt_mesh_queue_t *msg_queue = NULL;
|
||||
uint16_t duration = K_FOREVER;
|
||||
bt_mesh_msg_t msg = {0};
|
||||
uint32_t spt_mask = 0;
|
||||
uint32_t evts = 0;
|
||||
|
||||
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
|
||||
CONFIG_BLE_MESH_GATT_PROXY_SERVER
|
||||
if (!adv_insts[BLE_MESH_ADV_PROXY_INST].busy) {
|
||||
BT_DBG("Mesh Proxy Advertising start");
|
||||
duration = bt_mesh_proxy_server_adv_start();
|
||||
if (duration < cur_min_duration) {
|
||||
cur_min_duration = duration;
|
||||
}
|
||||
adv_insts[BLE_MESH_ADV_PROXY_INST].busy = true;
|
||||
evts |= ADV_TASK_ADV_INST_EVT(adv_insts[BLE_MESH_ADV_PROXY_INST].id);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = BLE_MESH_ADV_INST; i < BLE_MESH_ADV_INST_TYPES_NUM; i++) {
|
||||
struct bt_mesh_adv_inst *instance = &adv_insts[i];
|
||||
|
||||
if (instance->busy
|
||||
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
|
||||
CONFIG_BLE_MESH_GATT_PROXY_SERVER
|
||||
|| unlikely(instance->id == CONFIG_BLE_MESH_PROXY_ADV_INST_ID)
|
||||
#endif
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spt_mask = instance->spt_mask;
|
||||
adv_type = 0;
|
||||
|
||||
while(spt_mask) {
|
||||
adv_type = find_lsb_set(spt_mask) - 1;
|
||||
spt_mask &= ~BIT(adv_type);
|
||||
msg_queue = &(bt_mesh_adv_types_mgmt_get(adv_type)->adv_q->q);
|
||||
|
||||
/* If no new message in the queue, the *buf (aka: msg.arg) will be empty */
|
||||
if (find_valid_msg_from_queue(msg_queue, &msg)) {
|
||||
BT_DBG("no valid message for instance %d", instance->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
instance->sending_buf = (struct net_buf *)msg.arg;
|
||||
if (adv_send(instance, &duration)) {
|
||||
BT_ERR("adv start failed");
|
||||
/* When this adv instance fails to broadcast, it could be due to some
|
||||
* persistent issues, such as incorrect adv parameter settings, or it
|
||||
* could be due to some temporary issues, such as memory allocation
|
||||
* failure.
|
||||
*
|
||||
* Therefore, it is advisable to skip subsequent queue reads for this
|
||||
* instance and attempt to broadcast subsequent data again next time,
|
||||
* rather than disabling the adv instance.
|
||||
*/
|
||||
net_buf_unref(instance->sending_buf);
|
||||
instance->sending_buf = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (duration < cur_min_duration) {
|
||||
cur_min_duration = duration;
|
||||
}
|
||||
|
||||
instance->busy = true;
|
||||
evts |= ADV_TASK_ADV_INST_EVT(adv_insts[i].id);
|
||||
|
||||
/* Must be nullified to avoid affecting the next adv instance's judgment
|
||||
* on whether the message queue is empty.
|
||||
*/
|
||||
msg.arg = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*min_duration = cur_min_duration;
|
||||
*update_evts |= evts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t received_adv_evts_handle(uint32_t recv_evts)
|
||||
{
|
||||
if (!recv_evts) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; recv_evts && i < BLE_MESH_ADV_INST_TYPES_NUM; i++) {
|
||||
uint32_t evt = ADV_TASK_ADV_INST_EVT(adv_insts[i].id);
|
||||
|
||||
if (recv_evts & evt) {
|
||||
recv_evts &= ~evt;
|
||||
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
|
||||
CONFIG_BLE_MESH_GATT_PROXY_SERVER
|
||||
if (unlikely(i == BLE_MESH_ADV_PROXY_INST)) {
|
||||
BT_DBG("Mesh Proxy Advertising auto stop");
|
||||
bt_mesh_proxy_server_adv_flag_set(false);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* adv_send_end maybe*/
|
||||
adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data);
|
||||
bt_mesh_adv_buf_ref_debug(__func__, adv_insts[i].sending_buf, 4U, BLE_MESH_BUF_REF_SMALL);
|
||||
net_buf_unref(adv_insts[i].sending_buf);
|
||||
adv_insts[i].sending_buf = NULL;
|
||||
}
|
||||
adv_insts[i].busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
return recv_evts;
|
||||
}
|
||||
|
||||
static void adv_thread(void *p)
|
||||
{
|
||||
uint16_t adv_duration = K_FOREVER;
|
||||
uint32_t recv_evts = 0;
|
||||
uint32_t wait_evts = 0;
|
||||
|
||||
BT_DBG("%s, starts", __func__);
|
||||
|
||||
while (1) {
|
||||
adv_duration = K_FOREVER;
|
||||
wait_evts |= ADV_TASK_PKT_SEND_EVT;
|
||||
|
||||
activate_idle_adv_instance(&wait_evts, &adv_duration);
|
||||
|
||||
bt_mesh_adv_task_wait(wait_evts, adv_duration, &recv_evts);
|
||||
|
||||
wait_evts &= ~recv_evts;
|
||||
|
||||
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
|
||||
CONFIG_BLE_MESH_GATT_PROXY_SERVER
|
||||
if (recv_evts & ADV_TASK_PROXY_ADV_UPD_EVT) {
|
||||
adv_insts[BLE_MESH_ADV_PROXY_INST].busy = false;
|
||||
recv_evts &= ~ADV_TASK_PROXY_ADV_UPD_EVT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The `recv_evts == ADV_TASK_PKT_SEND_EVT` indicates that new packets
|
||||
* have been put into the queue, and the advertising instances started
|
||||
* previously have not yet been stopped.
|
||||
*/
|
||||
if (recv_evts == ADV_TASK_PKT_SEND_EVT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (recv_evts & ADV_TASK_PKT_SEND_EVT) {
|
||||
recv_evts &= ~ADV_TASK_PKT_SEND_EVT;
|
||||
}
|
||||
|
||||
recv_evts = received_adv_evts_handle(recv_evts);
|
||||
|
||||
if (recv_evts) {
|
||||
BT_ERR("Remain evts %08x to handle", recv_evts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_adv_update(void)
|
||||
{
|
||||
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
|
||||
CONFIG_BLE_MESH_GATT_PROXY_SERVER
|
||||
BT_DBG("Mesh Proxy Advertising stopped manually");
|
||||
bt_mesh_proxy_server_adv_stop();
|
||||
if (adv_insts[BLE_MESH_ADV_PROXY_INST].busy) {
|
||||
bt_mesh_adv_task_wakeup(ADV_TASK_PROXY_ADV_UPD_EVT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void bt_mesh_adv_init(void)
|
||||
{
|
||||
bt_mesh_adv_common_init();
|
||||
|
||||
adv_insts = bt_mesh_get_adv_insts_set();
|
||||
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
bt_mesh_relay_adv_init();
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
bt_mesh_ble_adv_init();
|
||||
#endif
|
||||
|
||||
bt_mesh_adv_task_init(adv_thread);
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_DEINIT
|
||||
void bt_mesh_adv_deinit(void)
|
||||
{
|
||||
bt_mesh_adv_task_deinit();
|
||||
|
||||
bt_mesh_adv_common_deinit();
|
||||
|
||||
adv_insts = NULL;
|
||||
|
||||
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
|
||||
bt_mesh_relay_adv_deinit();
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
bt_mesh_ble_adv_deinit();
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_DEINIT */
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Bluetooth Mesh */
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Intel Corporation
|
||||
* SPDX-FileContributor: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _EXT_ADV_H_
|
||||
#define _EXT_ADV_H_
|
||||
|
||||
#include "mesh/atomic.h"
|
||||
#include "mesh/access.h"
|
||||
#include "mesh/adapter.h"
|
||||
#include "mesh/queue.h"
|
||||
#include "adv_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void bt_mesh_adv_update(void);
|
||||
|
||||
void bt_mesh_adv_init(void);
|
||||
void bt_mesh_adv_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EXT_ADV_H_ */
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA
|
||||
* SPDX-FileCopyrightText: 2015-2017 Intel Corporation
|
||||
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -553,7 +553,7 @@ struct bt_mesh_gatt_attr {
|
||||
* @param len Length of data to read
|
||||
* @param offset Offset to start reading from
|
||||
*
|
||||
* @return Number fo bytes read, or in case of an error
|
||||
* @return Number of bytes read, or in case of an error
|
||||
* BLE_MESH_GATT_ERR() with a specific ATT error code.
|
||||
*/
|
||||
ssize_t (*read)(struct bt_mesh_conn *conn,
|
||||
|
||||
@@ -1560,8 +1560,13 @@ static int private_node_id_adv(struct bt_mesh_subnet *sub)
|
||||
memcpy(proxy_svc_data + 3, tmp + 8, 8);
|
||||
proxy_sd_len = gatt_proxy_adv_create(&proxy_sd);
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
err = bt_le_ext_adv_start(proxy_adv_inst, &fast_adv_param, private_node_id_ad,
|
||||
ARRAY_SIZE(private_node_id_ad), &proxy_sd, proxy_sd_len);
|
||||
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
err = bt_le_adv_start(&fast_adv_param, private_node_id_ad,
|
||||
ARRAY_SIZE(private_node_id_ad), &proxy_sd, proxy_sd_len);
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
if (err) {
|
||||
BT_WARN("Failed to advertise with Private Node ID (err %d)", err);
|
||||
return err;
|
||||
@@ -1604,8 +1609,13 @@ static int private_net_id_adv(struct bt_mesh_subnet *sub)
|
||||
|
||||
proxy_sd_len = gatt_proxy_adv_create(&proxy_sd);
|
||||
|
||||
#if CONFIG_BLE_MESH_USE_BLE_50
|
||||
err = bt_le_ext_adv_start(proxy_adv_inst, &fast_adv_param, private_net_id_ad,
|
||||
ARRAY_SIZE(private_net_id_ad), &proxy_sd, proxy_sd_len);
|
||||
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
err = bt_le_adv_start(&fast_adv_param, private_net_id_ad,
|
||||
ARRAY_SIZE(private_net_id_ad), &proxy_sd, proxy_sd_len);
|
||||
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
if (err) {
|
||||
BT_WARN("Failed to advertise with Private Net ID (err %d)", err);
|
||||
return err;
|
||||
|
||||
@@ -99,21 +99,21 @@ int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6],
|
||||
if (!memcmp(unprov_dev_info_fifo.info[idx].addr, addr, 6)) {
|
||||
if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS) {
|
||||
return 0;
|
||||
} else {
|
||||
memcpy(uuid, unprov_dev_info_fifo.info[idx].uuid, 16);
|
||||
*adv_type = unprov_dev_info_fifo.info[idx].adv_type;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(uuid, unprov_dev_info_fifo.info[idx].uuid, 16);
|
||||
*adv_type = unprov_dev_info_fifo.info[idx].adv_type;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!memcmp(unprov_dev_info_fifo.info[idx].uuid, uuid, 16)) {
|
||||
if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS) {
|
||||
return 0;
|
||||
} else {
|
||||
memcpy(addr, unprov_dev_info_fifo.info[idx].addr, 6);
|
||||
*adv_type = unprov_dev_info_fifo.info[idx].adv_type;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(addr, unprov_dev_info_fifo.info[idx].addr, 6);
|
||||
*adv_type = unprov_dev_info_fifo.info[idx].adv_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cnt++;
|
||||
|
||||
@@ -162,74 +162,6 @@ int32_t bt_mesh_get_seg_rtx_timeout(uint16_t dst, uint8_t ttl)
|
||||
return SEG_RETRANSMIT_TIMEOUT_UNICAST(&tx);
|
||||
}
|
||||
|
||||
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_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,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data,
|
||||
const uint8_t *ctl_op)
|
||||
@@ -380,7 +312,6 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err)
|
||||
|
||||
static void schedule_retransmit(struct seg_tx *tx)
|
||||
{
|
||||
bt_mesh_seg_tx_lock(tx);
|
||||
/* It's possible that a segment broadcast hasn't finished,
|
||||
* but the tx are already released. Only the seg_pending
|
||||
* of this segment remains unprocessed. So, here, we
|
||||
@@ -388,27 +319,29 @@ static void schedule_retransmit(struct seg_tx *tx)
|
||||
* destination (dst) is unassigned, and then process
|
||||
* the seg_pending of this segment.
|
||||
* See BLEMESH25-92 for details */
|
||||
|
||||
bt_mesh_seg_tx_lock(tx);
|
||||
|
||||
if (tx->dst == BLE_MESH_ADDR_UNASSIGNED) {
|
||||
if (tx->seg_pending) {
|
||||
tx->seg_pending--;
|
||||
}
|
||||
bt_mesh_seg_tx_unlock(tx);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (--tx->seg_pending) {
|
||||
bt_mesh_seg_tx_unlock(tx);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BLE_MESH_ADDR_IS_UNICAST(tx->dst) && !tx->attempts) {
|
||||
BT_INFO("Complete tx sdu to group");
|
||||
seg_tx_complete(tx, 0);
|
||||
bt_mesh_seg_tx_unlock(tx);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&tx->rtx_timer, SEG_RETRANSMIT_TIMEOUT(tx));
|
||||
|
||||
end:
|
||||
bt_mesh_seg_tx_unlock(tx);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Intel Corporation
|
||||
* SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -190,74 +190,6 @@ uint32_t bt_mesh_seg_ack_period(void)
|
||||
return (uint32_t)(val * bt_mesh_seg_rx_interval());
|
||||
}
|
||||
|
||||
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_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,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data,
|
||||
const uint8_t *ctl_op)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#define HCI_TIME_FOR_START_ADV K_MSEC(5) /* Three adv related hci commands may take 4 ~ 5ms */
|
||||
|
||||
static bt_mesh_client_node_t *bt_mesh_client_pick_node(sys_slist_t *list, uint16_t tx_dst)
|
||||
static bt_mesh_client_node_t *client_pick_node(sys_slist_t *list, uint16_t tx_dst)
|
||||
{
|
||||
bt_mesh_client_node_t *node = NULL;
|
||||
sys_snode_t *cur = NULL;
|
||||
@@ -86,7 +86,7 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model *
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((node = bt_mesh_client_pick_node(&data->queue, ctx->addr)) == NULL) {
|
||||
if ((node = client_pick_node(&data->queue, ctx->addr)) == NULL) {
|
||||
BT_DBG("Unexpected status message 0x%08x", ctx->recv_op);
|
||||
if (cli->publish_status && need_pub) {
|
||||
cli->publish_status(ctx->recv_op, model, ctx, buf);
|
||||
@@ -113,32 +113,8 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model *
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool bt_mesh_client_check_node_in_list(sys_slist_t *list, uint16_t tx_dst)
|
||||
{
|
||||
bt_mesh_client_node_t *node = NULL;
|
||||
sys_snode_t *cur = NULL;
|
||||
|
||||
bt_mesh_list_lock();
|
||||
if (sys_slist_is_empty(list)) {
|
||||
bt_mesh_list_unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (cur = sys_slist_peek_head(list);
|
||||
cur != NULL; cur = sys_slist_peek_next(cur)) {
|
||||
node = (bt_mesh_client_node_t *)cur;
|
||||
if (node->ctx.addr == tx_dst) {
|
||||
bt_mesh_list_unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bt_mesh_list_unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t bt_mesh_client_get_status_op(const bt_mesh_client_op_pair_t *op_pair,
|
||||
int size, uint32_t opcode)
|
||||
static uint32_t client_get_status_op(const bt_mesh_client_op_pair_t *op_pair,
|
||||
int size, uint32_t opcode)
|
||||
{
|
||||
if (!op_pair || size == 0) {
|
||||
return 0;
|
||||
@@ -155,7 +131,7 @@ static uint32_t bt_mesh_client_get_status_op(const bt_mesh_client_op_pair_t *op_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t bt_mesh_get_adv_duration(struct bt_mesh_msg_ctx *ctx)
|
||||
static int32_t client_get_adv_duration(struct bt_mesh_msg_ctx *ctx)
|
||||
{
|
||||
uint16_t duration = 0, adv_int = 0;
|
||||
uint8_t xmit = 0;
|
||||
@@ -177,9 +153,9 @@ static int32_t bt_mesh_get_adv_duration(struct bt_mesh_msg_ctx *ctx)
|
||||
return (int32_t)duration;
|
||||
}
|
||||
|
||||
static int32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *msg,
|
||||
uint32_t opcode, int32_t timeout)
|
||||
static int32_t client_calc_timeout(struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *msg,
|
||||
uint32_t opcode, int32_t timeout)
|
||||
{
|
||||
int32_t seg_rtx_to = 0, duration = 0, time = 0;
|
||||
uint8_t seg_count = 0, seg_rtx_num = 0;
|
||||
@@ -203,7 +179,7 @@ static int32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx,
|
||||
seg_rtx_to = bt_mesh_get_seg_rtx_timeout(ctx->addr, ctx->send_ttl);
|
||||
seg_count = (msg->len + mic_size - 1) / 12U + 1U;
|
||||
|
||||
duration = bt_mesh_get_adv_duration(ctx);
|
||||
duration = client_get_adv_duration(ctx);
|
||||
|
||||
/* Currently only consider the time consumption of the same segmented
|
||||
* messages, but if there are other messages between any two retrans-
|
||||
@@ -309,7 +285,7 @@ int bt_mesh_client_send_msg(bt_mesh_client_common_param_t *param,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bt_mesh_client_check_node_in_list(&internal->queue, param->ctx.addr)) {
|
||||
if (client_pick_node(&internal->queue, param->ctx.addr)) {
|
||||
BT_ERR("Busy sending message to DST 0x%04x", param->ctx.addr);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -324,14 +300,15 @@ int bt_mesh_client_send_msg(bt_mesh_client_common_param_t *param,
|
||||
memcpy(&node->ctx, ¶m->ctx, sizeof(struct bt_mesh_msg_ctx));
|
||||
node->model = param->model;
|
||||
node->opcode = param->opcode;
|
||||
node->op_pending = bt_mesh_client_get_status_op(client->op_pair, client->op_pair_size, param->opcode);
|
||||
node->op_pending = client_get_status_op(client->op_pair, client->op_pair_size, param->opcode);
|
||||
if (node->op_pending == 0U) {
|
||||
BT_ERR("Status opcode not found in op_pair list, opcode 0x%08x", param->opcode);
|
||||
bt_mesh_free(node);
|
||||
return -EINVAL;
|
||||
}
|
||||
node->timeout = bt_mesh_client_calc_timeout(¶m->ctx, msg, param->opcode,
|
||||
param->msg_timeout ? param->msg_timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT);
|
||||
node->timeout = client_calc_timeout(¶m->ctx, msg, param->opcode,
|
||||
(param->msg_timeout ? param->msg_timeout :
|
||||
CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT));
|
||||
|
||||
if (k_delayed_work_init(&node->timer, timer_handler)) {
|
||||
BT_ERR("Failed to create a timer");
|
||||
|
||||
Reference in New Issue
Block a user