Merge branch 'feat/ble_mesh_long_package_support' into 'master'

feat(ble_mesh): long packet mode support

Closes BLERP-2273

See merge request espressif/esp-idf!39175
This commit is contained in:
Island
2025-10-13 14:25:55 +08:00
23 changed files with 1694 additions and 192 deletions
+80
View File
@@ -41,6 +41,86 @@ if BLE_MESH
help
This option to enable BLE Mesh using some BLE 5.0 APIs.
menuconfig BLE_MESH_EXT_ADV
bool "Enable extended advertising for BLE Mesh"
depends on BLE_MESH_USE_BLE_50
default n
help
Enable broadcasting of BLE Mesh messages using BLE 5.0 extended advertising.
This allows control of extended advertising parameters (e.g., PHY selection)
while maintaining standard BLE Mesh packet length.
config BLE_MESH_EXT_ADV_BUF_COUNT
int "Number of extended advertising buffers"
depends on BLE_MESH_EXT_ADV
range 6 256
default 60
help
Number of buffer slots allocated for extended advertising packets.
config BLE_MESH_EXT_RELAY_ADV_BUF_COUNT
int "Number of extended relay advertising buffers"
depends on BLE_MESH_EXT_ADV
depends on BLE_MESH_RELAY
range 0 256
default 60
help
Number of buffer slots allocated for extended advertising packets used in message relay.
menuconfig BLE_MESH_LONG_PACKET
bool "Enable non-standard long packet mode for BLE Mesh"
depends on BLE_MESH_EXT_ADV
default n
help
Enable extended-length advertising packets for BLE Mesh using BLE 5.0 extended advertising.
This overrides the standard BLE Mesh packet length limitations.
config BLE_MESH_LONG_PACKET_ADV_LEN
int "Maximum advertising payload length"
depends on BLE_MESH_LONG_PACKET
range 30 249
default 105
help
Maximum payload length for extended advertising packets (bytes).
Range: 30-249 bytes.
Default: 105.
Note: Maximum access payload = (LENGTH - 17) × SEGMENT_COUNT
- Transmission: Uses BLE_MESH_LONG_PACKET_TX_SEG_CNT
- Reception: Uses BLE_MESH_LONG_PACKET_RX_SEG_CNT
config BLE_MESH_LONG_PACKET_ADV_BUF_COUNT
int "Long packet advertising buffer count"
depends on BLE_MESH_LONG_PACKET
default 20
help
Number of advertising buffers allocated for long packet transmissions.
config BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT
int "Long packet relay buffer count"
depends on BLE_MESH_LONG_PACKET
depends on BLE_MESH_RELAY
default 20
help
Number of advertising buffers allocated for relay long packets.
config BLE_MESH_LONG_PACKET_TX_SEG_CNT
int "Maximum transmission segments per message"
depends on BLE_MESH_LONG_PACKET
range 1 BLE_MESH_TX_SEG_MAX if BLE_MESH_TX_SEG_MAX < BLE_MESH_LONG_PACKET_ADV_BUF_COUNT
range 1 BLE_MESH_LONG_PACKET_ADV_BUF_COUNT if BLE_MESH_TX_SEG_MAX >= BLE_MESH_LONG_PACKET_ADV_BUF_COUNT
default 20
help
Maximum number of segments for outgoing long packet messages.
Upper bound: min(BLE_MESH_TX_SEG_MAX, BLE_MESH_LONG_PACKET_ADV_BUF_COUNT)
config BLE_MESH_LONG_PACKET_RX_SEG_CNT
int "Maximum reception segments per message"
depends on BLE_MESH_LONG_PACKET
range 1 BLE_MESH_LONG_PACKET_ADV_BUF_COUNT
default 20
help
Maximum number of segments supported for receiving long packet messages.
config BLE_MESH_ADV_INST_ID
depends on BLE_MESH_USE_BLE_50
int "Extended adv instance for Mesh normal packets"
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -30,8 +30,55 @@ static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model,
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
if (ctx && ctx->addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
BT_ERR("Invalid destination address 0x0000");
if (ctx) {
if (ctx->addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
BT_ERR("Invalid destination address 0x0000");
return ESP_ERR_INVALID_ARG;
}
if (ctx->enh.adv_cfg_used &&
ctx->enh.adv_cfg.channel_map & BIT(3)) {
BT_ERR("Invalid channel map 0x%04x: bit 3 is reserved", ctx->enh.adv_cfg.channel_map);
return ESP_ERR_INVALID_ARG;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (ctx->enh.ext_adv_cfg_used) {
if (ctx->enh.ext_adv_cfg.primary_phy == ESP_BLE_MESH_ADV_PHY_CODED) {
BT_ERR("Primary phy can't be set to coded phy");
return ESP_ERR_INVALID_ARG;
}
if (ctx->enh.ext_adv_cfg.primary_phy == ESP_BLE_MESH_ADV_PHY_UNASSIGNED) {
ctx->enh.ext_adv_cfg.primary_phy = ESP_BLE_MESH_ADV_PHY_DEFAULT;
}
if (ctx->enh.ext_adv_cfg.secondary_phy == ESP_BLE_MESH_ADV_PHY_UNASSIGNED) {
ctx->enh.ext_adv_cfg.secondary_phy = ESP_BLE_MESH_ADV_PHY_DEFAULT;
}
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (ctx->enh.long_pkt_cfg_used &&
(ctx->enh.long_pkt_cfg != ESP_BLE_MESH_LONG_PACKET_FORCE &&
ctx->enh.long_pkt_cfg != ESP_BLE_MESH_LONG_PACKET_PREFER)) {
BT_ERR("Invalid long packet configuration %d (expected FORCE=1 or PREFER=2)",
ctx->enh.long_pkt_cfg);
}
if (ctx->enh.long_pkt_cfg_used && (op_len + length + mic_len > ESP_BLE_MESH_EXT_SDU_MAX_LEN)) {
BT_ERR("The length(%d) exceeds the maximum length supported by the long packet", length);
return ESP_ERR_INVALID_ARG;
}
if (((!ctx->enh.long_pkt_cfg_used) && op_len + length + mic_len > MIN(ESP_BLE_MESH_SDU_MAX_LEN, ESP_BLE_MESH_TX_SDU_MAX))) {
BT_ERR("Too large data length %d", length);
return ESP_ERR_INVALID_ARG;
}
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
#endif /* CONFIG_BLE_MESH_EXT_ADV */
} // if (ctx)
if (op_len + length + mic_len > MIN(ESP_BLE_MESH_SDU_MAX_LEN, ESP_BLE_MESH_TX_SDU_MAX)) {
BT_ERR("Too large data length %d", length);
return ESP_ERR_INVALID_ARG;
}
@@ -70,11 +117,6 @@ static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model,
ESP_BLE_MESH_MIC_LONG : ESP_BLE_MESH_MIC_SHORT;
}
if (op_len + length + mic_len > MIN(ESP_BLE_MESH_SDU_MAX_LEN, ESP_BLE_MESH_TX_SDU_MAX)) {
BT_ERR("Too large data length %d", length);
return ESP_ERR_INVALID_ARG;
}
if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) {
bt_mesh_model_msg_init(model->pub->msg, opcode);
net_buf_simple_add_mem(model->pub->msg, data, length);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -20,6 +20,12 @@ extern "C" {
/*!< The maximum length of a BLE Mesh message, including Opcode, Payload and TransMIC */
#define ESP_BLE_MESH_SDU_MAX_LEN 384
#if CONFIG_BLE_MESH_LONG_PACKET
/* Extended SDU maximum length (included Opcode, Payload and TransMIC) calculation:
* SEGMENT_COUNT × (ADV_PAYLOAD_LEN - 17 bytes overhead)
* 17 bytes = 9 bytes mesh network header + 4 bytes transport overhead + 4 bytes NetMIC */
#define ESP_BLE_MESH_EXT_SDU_MAX_LEN (CONFIG_BLE_MESH_LONG_PACKET_TX_SEG_CNT * (CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN - 17))
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
/*!< Length of a short Mesh MIC. */
#define ESP_BLE_MESH_MIC_SHORT 4
@@ -613,6 +619,166 @@ struct esp_ble_mesh_model {
*/
#define ESP_BLE_MESH_MODEL_NONE ((esp_ble_mesh_model_t []){})
#if CONFIG_BLE_MESH_USE_BLE_50
#define ESP_BLE_MESH_ADV_CHAN_UNASSIGNED (0)
#define ESP_BLE_MESH_ADV_CHAN_37 BIT(0)
#define ESP_BLE_MESH_ADV_CHAN_38 BIT(1)
#define ESP_BLE_MESH_ADV_CHAN_39 BIT(2)
#define ESP_BLE_MESH_DEFAULT_CHANNEL_MAP (ESP_BLE_MESH_ADV_CHAN_37| \
ESP_BLE_MESH_ADV_CHAN_38| \
ESP_BLE_MESH_ADV_CHAN_39)
#define ESP_BLE_MESH_ADV_PHY_UNASSIGNED (0)
#define ESP_BLE_MESH_ADV_PHY_1M (1)
#define ESP_BLE_MESH_ADV_PHY_2M (2)
#define ESP_BLE_MESH_ADV_PHY_CODED (3)
#define ESP_BLE_MESH_ADV_PHY_DEFAULT ESP_BLE_MESH_ADV_PHY_1M
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
/**
* Enhanced configuration for Mesh messages with legacy advertising
*/
typedef struct {
/**
* Advertising interval in milliseconds.
* If set to 0, the Mesh protocol stack's xmit parameters are used.
* If set to another value (e.g., 10), the advertising interval will be 10 ms.
*/
uint32_t adv_itvl;
/**
* Number of advertising per packet.
* If set to 0, the Mesh protocol stack's xmit parameters are used.
* If set to another value (e.g., 3), the number of advertising per packet will be 3.
*/
uint8_t adv_cnt;
/**
* Advertising channel map.
* If set to 0, the protocol stack uses default channels.
* If set to another value (e.g., ESP_BLE_MESH_ADV_CHAN_37),
* the advertising channel map will be 0x01, the advertising
* packet will only advertise on channel 37.
*/
uint8_t channel_map;
} esp_ble_mesh_adv_cfg_t;
#if CONFIG_BLE_MESH_EXT_ADV
/** Enhanced configuration for Mesh messages with extended advertising */
typedef struct {
/**
* Primary PHY for advertising (ESP_BLE_MESH_ADV_PHY_1M or
* ESP_BLE_MESH_ADV_PHY_CODED).
* When using coded PHY, receivers must use coded scanning.
*/
uint8_t primary_phy;
/**
* Secondary PHY for advertising (ESP_BLE_MESH_ADV_PHY_1M,
* ESP_BLE_MESH_ADV_PHY_2M, or ESP_BLE_MESH_ADV_PHY_CODED).
* When using coded PHY, receivers must use coded scanning.
*/
uint8_t secondary_phy;
/**
* Include TX power in advertising packets (0: disabled, 1: enabled).
* Allows receivers/relays to maintain original transmission power.
*/
uint8_t include_tx_power:1;
/** Transmission power level (in dBm) */
int8_t tx_power;
} esp_ble_mesh_ext_adv_cfg_t;
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#if CONFIG_BLE_MESH_LONG_PACKET
/** Force this message to use long packet format */
#define ESP_BLE_MESH_LONG_PACKET_FORCE (1)
/**
* Whether to use the long packet mode will be chosen by the protocol stack,
* which currently makes the decision based on message length.
* Advertising using the standard BLE Mesh protocol when possible.
* Switch to long packet mode for advertising when the standard BLE
* Mesh protocol cannot be used.
*/
#define ESP_BLE_MESH_LONG_PACKET_PREFER (2)
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
/** Enhanced message advertising parameters */
typedef struct {
/**
* Use custom advertising parameters (0: disabled, 1: enabled).
* When enabled, `adv_cfg` parameters override stack defaults.
*/
uint8_t adv_cfg_used:1;
#if CONFIG_BLE_MESH_EXT_ADV
/**
* Use extended advertising parameters (0: disabled, 1: enabled).
* When enabled, `ext_adv_cfg` parameters override stack defaults.
*/
uint8_t ext_adv_cfg_used:1;
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#if CONFIG_BLE_MESH_LONG_PACKET
/**
* Control long packet usage (0: disabled, 1: enabled).
* When disabled, the protocol stack cannot use long packets to
* send this message.
*/
uint8_t long_pkt_cfg_used:1;
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
/** Standard advertising parameters */
esp_ble_mesh_adv_cfg_t adv_cfg;
#if CONFIG_BLE_MESH_EXT_ADV
/** Extended advertising parameters */
esp_ble_mesh_ext_adv_cfg_t ext_adv_cfg;
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#if CONFIG_BLE_MESH_LONG_PACKET
/**
* Long packet configuration:
* - ESP_BLE_MESH_LONG_PACKET_FORCE
* - ESP_BLE_MESH_LONG_PACKET_PREFER
*/
uint8_t long_pkt_cfg:2;
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
} esp_ble_mesh_msg_enh_params_t;
#define ESP_BLE_MESH_ADV_CFG_NULL ((esp_ble_mesh_adv_cfg_t){0})
#define ESP_BLE_MESH_EXT_ADV_CFG_NULL ((esp_ble_mesh_ext_adv_cfg_t){0})
#define ESP_BLE_MESH_ADV_CFG_DEFAULT \
((esp_ble_mesh_adv_cfg_t){\
.adv_itvl= 0, \
.adv_cnt = 0, \
.channel_map = ESP_BLE_MESH_DEFAULT_CHANNEL_MAP, \
})
#define ESP_BLE_MESH_EXT_ADV_CFG_DEFAULT \
((esp_ble_mesh_ext_adv_cfg_t){ \
.primary_phy = ESP_BLE_MESH_ADV_PHY_1M, \
.secondary_phy = ESP_BLE_MESH_ADV_PHY_1M, \
.tx_power = 0x7f, \
.include_tx_power = false,\
})
#if CONFIG_BLE_MESH_LONG_PACKET
#define ESP_BLE_MESH_LONG_PACKET_DEF_ENH_SET(ADV_CFG, EXT_ADV_CFG, LONG_PACKET_CFG) \
((esp_ble_mesh_msg_enh_params_t){ \
.adv_cfg_used = true,\
.adv_cfg = ADV_CFG, \
.ext_adv_cfg_used = true, \
.ext_adv_cfg = EXT_ADV_CFG, \
.long_pkt_cfg_used = true, \
.long_pkt_cfg = LONG_PACKET_CFG, \
})
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
/** Message sending context.
* This structure is associated with struct bt_mesh_msg_ctx in mesh_access.h
*/
@@ -664,6 +830,9 @@ typedef struct {
/** Indicate if the message is sent by a node server model, no need to be initialized before sending message */
bool srv_send __attribute__((deprecated));
/** Enhanced message advertising parameters */
esp_ble_mesh_msg_enh_params_t enh;
} esp_ble_mesh_msg_ctx_t;
/** Provisioning properties & capabilities.
@@ -2950,6 +2950,8 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg)
.msg_timeout = arg->model_send.msg_timeout,
};
memcpy(&param.ctx.enh, &arg->model_send.ctx->enh, sizeof(bt_mesh_msg_enh_params_t));
err = bt_mesh_client_send_msg(&param, buf, arg->model_send.need_rsp,
btc_ble_mesh_client_model_timeout_cb);
bt_mesh_free_buf(buf);
+20 -1
View File
@@ -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
*/
@@ -29,6 +29,11 @@
#define BLE_MESH_SDU_MAX_LEN 384
/* Extended SDU maximum length (message length + TransMIC size) calculation:
* 32 segments maximum × (249 bytes max PDU - 17 bytes overhead)
* 17 bytes = 9 bytes mesh header + 4 bytes transport overhead + 4-byte NetMIC */
#define BLE_MESH_EXT_SDU_MAX_LEN (32*(249-17))
extern const struct bt_mesh_comp *comp_0;
static uint16_t dev_primary_addr;
@@ -973,10 +978,24 @@ static int model_send(struct bt_mesh_model *model,
return -EINVAL;
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (msg->len > MIN(BLE_MESH_EXT_TX_SDU_MAX, BLE_MESH_EXT_SDU_MAX_LEN) - BLE_MESH_MIC_SHORT) {
BT_ERR("Too big ext message (len %d)", msg->len);
return -EMSGSIZE;
}
if ((msg->len <= MIN(BLE_MESH_EXT_TX_SDU_MAX, BLE_MESH_EXT_SDU_MAX_LEN) - BLE_MESH_MIC_SHORT) &&
(msg->len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SDU_MAX_LEN) - BLE_MESH_MIC_SHORT) &&
!tx->ctx->enh.long_pkt_cfg_used) {
BT_ERR("Extended message length %d requires long packet mode, but long_pkt_cfg_used is false", msg->len);
return -EMSGSIZE;
}
#else
if (msg->len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SDU_MAX_LEN) - BLE_MESH_MIC_SHORT) {
BT_ERR("Too big message (len %d)", msg->len);
return -EMSGSIZE;
}
#endif
if (!implicit_bind && !model_has_key(model, tx->ctx->app_idx)) {
BT_ERR("Model not bound to AppKey 0x%04x", tx->ctx->app_idx);
+46 -7
View File
@@ -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
*/
@@ -60,6 +60,7 @@ static inline int adv_send(struct net_buf *buf)
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;
@@ -69,10 +70,20 @@ static inline int adv_send(struct net_buf *buf)
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
if (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) {
#endif
adv_int = MAX(ADV_ITVL_MIN,
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
(adv_int + 10);
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",
BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int,
@@ -86,10 +97,38 @@ static inline int adv_send(struct net_buf *buf)
param.interval_min = ADV_SCAN_UNIT(adv_int);
param.interval_max = param.interval_min;
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_USE_BLE_50
param.adv_duration = duration;
param.adv_count = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1;
#if CONFIG_BLE_MESH_EXT_ADV
if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_PROV ||
BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_DATA ||
BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_RELAY_DATA
#if CONFIG_BLE_MESH_LONG_PACKET
|| BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_LONG_PROV
|| BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_LONG_DATA
|| BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_LONG_RELAY_DATA
#endif
) {
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;
}
param.adv_duration = duration;
param.adv_count = adv_cnt;
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX
if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) {
+213 -12
View File
@@ -35,6 +35,36 @@ struct bt_mesh_adv_queue relay_adv_queue;
#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
@@ -48,8 +78,10 @@ NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT,
bt_mesh_friend_adv_t frnd_adv_pool[FRIEND_BUF_COUNT];
struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx)
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;
}
@@ -154,11 +186,58 @@ int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type)
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
struct bt_mesh_adv *adv_alloc(int id)
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];
@@ -357,12 +436,8 @@ struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type,
BT_DBG("pool %p, buf_count %d, uinit_count %d, ref %d",
buf->pool, pool->buf_count, pool->uninit_count, buf->ref);
adv = adv_types[type].pool_allocator(net_buf_id(buf));
adv = adv_types[type].pool_allocator(net_buf_id(buf), type);
BLE_MESH_ADV(buf) = adv;
(void)memset(adv, 0, sizeof(*adv));
adv->type = type;
bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock);
return buf;
}
@@ -476,8 +551,10 @@ bool bt_mesh_ignore_relay_packet(uint32_t timestamp)
return ((interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false);
}
static struct bt_mesh_adv *relay_adv_alloc(int id)
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];
}
@@ -531,21 +608,58 @@ uint16_t bt_mesh_get_stored_relay_count(void)
return (uint16_t)uxQueueMessagesWaiting(relay_adv_queue.q.handle);
}
static ALWAYS_INLINE
uint16_t ble_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, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT,
bt_mesh_adv_queue_init(&relay_adv_queue, ble_mesh_relay_adv_buf_count_get(),
ble_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 */
#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_INS,
CONFIG_BLE_MESH_RELAY_ADV_INST_ID);
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA);
#if CONFIG_BLE_MESH_EXT_ADV
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA);
#if CONFIG_BLE_MESH_LONG_PACKET
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_EXT_LONG_RELAY_DATA);
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#else
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA);
#endif
#if CONFIG_BLE_MESH_EXT_ADV
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA);
#if CONFIG_BLE_MESH_LONG_PACKET
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, 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 */
}
@@ -554,14 +668,33 @@ 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
#if CONFIG_BLE_MESH_USE_BLE_50
#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE
bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA);
#if CONFIG_BLE_MESH_EXT_ADV
bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA);
#if CONFIG_BLE_MESH_LONG_PACKET
bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, 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_INS);
#else
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA);
#endif
#if CONFIG_BLE_MESH_EXT_ADV
bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA);
#if CONFIG_BLE_MESH_LONG_PACKET
bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, 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);
@@ -597,6 +730,27 @@ void bt_mesh_frnd_adv_deinit(void)
}
#endif /* CONFIG_BLE_MESH_FRIEND */
static ALWAYS_INLINE
uint16_t ble_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
#endif
#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
#endif
return adv_count;
}
void bt_mesh_adv_task_init(void adv_thread(void *p))
{
if (!adv_thread) {
@@ -625,7 +779,7 @@ void bt_mesh_adv_task_init(void adv_thread(void *p))
void bt_mesh_adv_common_init(void)
{
bt_mesh_r_mutex_create(&adv_buf_alloc_lock);
bt_mesh_adv_queue_init(&adv_queue, BLE_MESH_ADV_QUEUE_SIZE, bt_mesh_task_post);
bt_mesh_adv_queue_init(&adv_queue, ble_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);
@@ -636,7 +790,21 @@ void bt_mesh_adv_common_init(void)
#if CONFIG_BLE_MESH_USE_BLE_50
bt_mesh_adv_inst_init(BLE_MESH_ADV_INS, 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
/**
@@ -651,7 +819,21 @@ void bt_mesh_adv_common_init(void)
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_DATA);
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BEACON);
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_URI);
#if CONFIG_BLE_MESH_EXT_ADV
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_PROV);
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_DATA);
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA);
#endif
#if CONFIG_BLE_MESH_LONG_PACKET
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_PROV);
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_DATA);
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF
bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, 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
@@ -677,6 +859,25 @@ void bt_mesh_adv_common_deinit(void)
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_INS);
+51 -18
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -48,9 +48,6 @@ extern "C" {
#define BLE_MESH_ADV_INS_UNUSED 0xFF
/* We reserve one queue item for bt_mesh_adv_update() */
#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1)
struct bt_mesh_adv {
const struct bt_mesh_send_cb *cb;
void *cb_data;
@@ -60,8 +57,23 @@ struct bt_mesh_adv {
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)
@@ -110,14 +122,6 @@ typedef struct bt_mesh_msg {
uint32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */
} bt_mesh_msg_t;
typedef struct bt_mesh_adv *(*bt_mesh_pool_allocator_t)(int id);
typedef void (*bt_mesh_adv_queue_send_cb_t)(bt_mesh_msg_t *msg, uint32_t timeout, bool front);
struct bt_mesh_adv_queue {
bt_mesh_queue_t q;
bt_mesh_adv_queue_send_cb_t send;
};
struct bt_mesh_adv_inst {
uint8_t id;
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
@@ -132,6 +136,16 @@ struct bt_mesh_adv_inst {
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
@@ -155,15 +169,20 @@ typedef enum {
BLE_MESH_BUF_REF_MAX,
} bt_mesh_buf_ref_flag_t;
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;
};
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
@@ -174,6 +193,20 @@ static const uint8_t adv_type[] = {
[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);
@@ -255,7 +288,7 @@ void bt_mesh_relay_adv_deinit(void);
#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */
#if CONFIG_BLE_MESH_FRIEND
struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int id);
struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int id, enum bt_mesh_adv_type type);
struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void);
void bt_mesh_frnd_adv_init(void);
#if CONFIG_BLE_MESH_DEINIT
+3 -1
View File
@@ -30,8 +30,10 @@ static struct bt_mesh_ble_adv_tx ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front);
static struct bt_mesh_adv *ble_adv_alloc(int id)
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];
}
@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA
* SPDX-FileCopyrightText: 2015-2016 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
*/
@@ -240,9 +240,19 @@ void bt_mesh_ble_ext_adv_report(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report)
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
}
#if CONFIG_BLE_MESH_LONG_PACKET
static struct {
struct bt_mesh_adv_report adv_rpt;
uint8_t adv_data_len;
uint8_t adv_data[2 + CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN];
} adv_report_cache;
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
static bool bt_mesh_scan_result_process(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report)
{
struct bt_mesh_adv_report adv_rpt = {0};
uint8_t *adv_data = NULL;
uint8_t adv_data_len = 0;
assert(ext_adv_report);
@@ -251,23 +261,31 @@ static bool bt_mesh_scan_result_process(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report)
adv_rpt.primary_phy = ext_adv_report->primary_phy;
adv_rpt.secondary_phy = ext_adv_report->secondry_phy;
adv_rpt.rssi = ext_adv_report->rssi;
adv_rpt.tx_power = ext_adv_report->tx_power;
adv_data = ext_adv_report->adv_data;
adv_data_len = ext_adv_report->adv_data_len;
#if !CONFIG_BLE_MESH_EXT_ADV
if (!(ext_adv_report->event_type & BTM_BLE_ADV_LEGACY_MASK)) {
return false;
}
if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) {
return false;
}
#endif
BT_DBG("Recv adv report type %04x", ext_adv_report->event_type);
if (ext_adv_report->adv_data_len > BLE_MESH_GAP_ADV_MAX_LEN) {
return false;
}
switch (ext_adv_report->event_type) {
case BLE_MESH_ADV_IND:
case BLE_MESH_ADV_DIRECT_IND:
case BLE_MESH_ADV_SCAN_IND:
case BLE_MESH_ADV_NONCONN_IND:
case BLE_MESH_ADV_SCAN_RSP:
#if CONFIG_BLE_MESH_EXT_ADV
case BLE_MESH_EXT_ADV_NONCONN_IND:
#endif
adv_rpt.adv_type = ext_adv_report->event_type;
break;
default:
@@ -275,10 +293,51 @@ static bool bt_mesh_scan_result_process(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report)
break;
}
#if CONFIG_BLE_MESH_LONG_PACKET
switch (ext_adv_report->data_status) {
case BTM_BLE_EXT_ADV_DATA_COMPLETE:
if (adv_report_cache.adv_data_len) {
memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len,
ext_adv_report->adv_data, ext_adv_report->adv_data_len);
adv_report_cache.adv_data_len += ext_adv_report->adv_data_len;
adv_data = adv_report_cache.adv_data;
adv_data_len = adv_report_cache.adv_data_len;
adv_report_cache.adv_data_len = 0;
}
break;
case BTM_BLE_EXT_ADV_DATA_INCOMPLETE:
if ((adv_report_cache.adv_data_len + ext_adv_report->adv_data_len) > BLE_MESH_GAP_ADV_MAX_LEN) {
adv_report_cache.adv_data_len = 0;
return false;
}
if (adv_report_cache.adv_data_len == 0) {
memcpy(&adv_report_cache.adv_rpt, &adv_rpt, sizeof(struct bt_mesh_adv_report));
}
memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len,
ext_adv_report->adv_data, ext_adv_report->adv_data_len);
adv_report_cache.adv_data_len += ext_adv_report->adv_data_len;
/* To avoid discarding user's packets,
* it is assumed here that this packet
* is not mesh's packet */
return false;
case BTM_BLE_EXT_ADV_DATA_TRUNCATED:
if (adv_report_cache.adv_data_len) {
memset(&adv_report_cache, 0, sizeof(adv_report_cache));
}
return false;
default:
assert(0);
}
#else /* CONFIG_BLE_MESH_LONG_PACKET */
if (ext_adv_report->data_status != BTM_BLE_EXT_ADV_DATA_COMPLETE) {
return false;
}
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
if (bt_mesh_scan_dev_found_cb) {
net_buf_simple_init_with_data(&adv_rpt.adv_data, ext_adv_report->adv_data, ext_adv_report->adv_data_len);
net_buf_simple_init_with_data(&adv_rpt.adv_data, adv_data, adv_data_len);
bt_mesh_scan_dev_found_cb(&adv_rpt);
if (adv_rpt.adv_data.len != ext_adv_report->adv_data_len) {
if (adv_rpt.adv_data.len != adv_data_len) {
/* The advertising data has been processed by Mesh Protocol */
return true;
}
@@ -430,7 +489,7 @@ static int set_adv_data(uint16_t hci_op, const struct bt_mesh_adv_data *ad, size
for (i = 0; i < ad_len; i++) {
/* Check if ad fit in the remaining buffer */
if (param.len + ad[i].data_len + 2 > 31) {
if (param.len + ad[i].data_len + 2 > sizeof(param.data)) {
return -EINVAL;
}
@@ -593,6 +652,11 @@ static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARC
#endif
#if CONFIG_BLE_MESH_USE_BLE_50
static struct {
bool set;
tBTA_DM_BLE_GAP_EXT_ADV_PARAMS param;
} last_param[BLE_MESH_ADV_INS_TYPES_NUM];
int bt_le_ext_adv_start(const uint8_t inst_id,
const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *ad, size_t ad_len,
@@ -624,11 +688,10 @@ int bt_le_ext_adv_start(const uint8_t inst_id,
ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_SCAN;
} else {
if (param->primary_phy == BLE_MESH_ADV_PHY_1M &&
param->secondary_phy == BLE_MESH_ADV_PHY_1M) {
ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN;
} else {
BT_ERR("Unsupported PHY: pri %d sec %d",param->primary_phy, param->secondary_phy);
return -EINVAL;
param->secondary_phy == BLE_MESH_ADV_PHY_1M &&
param->include_tx_power == false &&
ad->data_len <= 29) {
ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN;
}
}
@@ -648,12 +711,16 @@ int bt_le_ext_adv_start(const uint8_t inst_id,
ext_adv_params.sid = inst_id;
ext_adv_params.max_skip = 0;
ext_adv_params.tx_power = 0x7F;
ext_adv_params.tx_power = param->tx_power;
ext_adv_params.scan_req_notif = false;
ext_adv_params.primary_phy = param->primary_phy;
ext_adv_params.secondary_phy = param->secondary_phy;
ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL;
ext_adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39;
ext_adv_params.channel_map = param->channel_map;
if (param->include_tx_power) {
ext_adv_params.type |= BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_INCLUDE_TX_PWR;
}
interval = param->interval_min;
@@ -674,8 +741,18 @@ int bt_le_ext_adv_start(const uint8_t inst_id,
ext_adv_params.interval_min = interval;
ext_adv_params.interval_max = interval;
/* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */
BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params);
if (memcmp(&ext_adv_params, &last_param[inst_id].param, sizeof(tBTA_DM_BLE_GAP_EXT_ADV_PARAMS))) {
if (last_param[inst_id].set) {
BTA_DmBleGapExtAdvSetRemove(inst_id);
}
last_param[inst_id].set = true;
/* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */
BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params);
memcpy(&last_param[inst_id].param, &ext_adv_params, sizeof(tBTA_DM_BLE_GAP_EXT_ADV_PARAMS));
}
err = set_adv_data(BLE_MESH_HCI_OP_SET_ADV_DATA, inst_id, ad, ad_len);
if (err) {
@@ -723,7 +800,6 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *sd, size_t sd_len)
{
tBTA_START_ADV_CMPL_CBACK *p_start_adv_cb = NULL;
tBTM_BLE_ADV_CHNL_MAP channel_map = 0U;
tBLE_ADDR_TYPE addr_type_own = 0U;
tBLE_BD_ADDR p_dir_bda = {0};
tBTM_BLE_AFP adv_fil_pol = 0U;
@@ -787,7 +863,6 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
addr_type_own = BLE_MESH_ADDR_PUBLIC;
#endif
channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39;
adv_fil_pol = BLE_MESH_AP_SCAN_CONN_ALL;
p_start_adv_cb = start_adv_completed_cb;
@@ -810,7 +885,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
BLE_MESH_BTM_CHECK_STATUS(
BTM_BleSetAdvParamsAll(interval, interval, adv_type,
addr_type_own, &p_dir_bda,
channel_map, adv_fil_pol, p_start_adv_cb));
param->channel_map, adv_fil_pol, p_start_adv_cb));
BLE_MESH_BTM_CHECK_STATUS(BTM_BleStartAdv());
#if BLE_MESH_DEV
@@ -891,7 +966,7 @@ int bt_mesh_ble_ext_adv_start(const uint8_t inst_id,
ext_adv_params.primary_phy = BLE_MESH_ADV_PHY_1M;
ext_adv_params.secondary_phy = BLE_MESH_ADV_PHY_1M;
ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL;
ext_adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39;
ext_adv_params.channel_map = BLE_MESH_ADV_CHAN_37 | BLE_MESH_ADV_CHAN_38 | BLE_MESH_ADV_CHAN_39;
if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID ||
param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID ||
@@ -939,7 +1014,7 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param,
}
}
channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39;
channel_map = BLE_MESH_ADV_CHAN_37 | BLE_MESH_ADV_CHAN_38 | BLE_MESH_ADV_CHAN_39;
adv_fil_pol = BLE_MESH_AP_SCAN_CONN_ALL;
if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID ||
param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID ||
+55 -11
View File
@@ -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
*/
@@ -56,13 +56,30 @@ static inline int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration
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));
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
@@ -76,14 +93,38 @@ static inline int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration
#endif
case BLE_MESH_ADV_BEACON:
case BLE_MESH_ADV_URI: {
adv_int = MAX(ADV_ITVL_MIN,
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
(adv_int + 10);
#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",
BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int,
duration);
adv_cnt, adv_int, duration);
ad.type = adv_type[BLE_MESH_ADV(buf)->type];
ad.data_len = buf->len;
@@ -94,10 +135,13 @@ static inline int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration
param.interval_max = param.interval_min;
param.adv_duration = duration;
param.adv_count = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1;
param.adv_count = adv_cnt;
param.primary_phy = BLE_MESH_ADV_PHY_1M;
param.secondary_phy = BLE_MESH_ADV_PHY_1M;
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) {
@@ -4,7 +4,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
*/
@@ -154,6 +154,49 @@ struct bt_mesh_elem {
#define BLE_MESH_MODEL_ID_MBT_SRV 0x1400
#define BLE_MESH_MODEL_ID_MBT_CLI 0x1401
typedef struct {
uint32_t adv_itvl;
uint8_t adv_cnt;
uint8_t channel_map;
} ble_mesh_adv_cfg_t;
#if CONFIG_BLE_MESH_EXT_ADV
typedef struct {
uint8_t primary_phy;
uint8_t secondary_phy;
uint8_t include_tx_power:1;
int8_t tx_power;
} ble_mesh_ext_adv_cfg_t;
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#if CONFIG_BLE_MESH_LONG_PACKET
#define BLE_MESH_LONG_PACKET_FORCE (1)
#define BLE_MESH_LONG_PACKET_PREFER (2)
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
typedef struct {
uint8_t adv_cfg_used : 1;
#if CONFIG_BLE_MESH_EXT_ADV
uint8_t ext_adv_cfg_used : 1;
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#if CONFIG_BLE_MESH_LONG_PACKET
uint8_t long_pkt_cfg_used : 1;
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
ble_mesh_adv_cfg_t adv_cfg;
#if CONFIG_BLE_MESH_EXT_ADV
ble_mesh_ext_adv_cfg_t ext_adv_cfg;
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#if CONFIG_BLE_MESH_LONG_PACKET
/**
* Long packets will be used for broadcasting
* only if this flag is set and the traditional
* packet length (380 bytes) cannot be used.
*/
uint8_t long_pkt_cfg : 2;
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
} bt_mesh_msg_enh_params_t;
/** Message sending context. */
struct bt_mesh_msg_ctx {
/** NetKey Index of the subnet to send the message on. */
@@ -204,6 +247,8 @@ struct bt_mesh_msg_ctx {
/** Change by Espressif, if the message is sent by a server
* model. Not used for receiving message. */
bool srv_send __attribute__((deprecated));
bt_mesh_msg_enh_params_t enh;
};
struct bt_mesh_model_op {
@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA
* SPDX-FileCopyrightText: 2015-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
*/
@@ -77,11 +77,17 @@ extern "C" {
#endif
#endif /* CONFIG_BT_NIMBLE_ENABLED */
#if CONFIG_BLE_MESH_LONG_PACKET
#define BLE_MESH_GAP_ADV_MAX_LEN (2 + CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN)
#else
#define BLE_MESH_GAP_ADV_MAX_LEN 31
#endif
#define BLE_MESH_GATT_DEF_MTU_SIZE 23
#if CONFIG_BLE_MESH_USE_BLE_50
#define BLE_MESH_TX_POWER_INCLUDE_DEFAULT false
#define BLE_MESH_TX_POWER_DEFAULT 0x7f
#define BLE_MESH_ADV_PHY_UNASSIGNED 0
#define BLE_MESH_ADV_PHY_1M 1
#define BLE_MESH_ADV_PHY_2M 2
@@ -91,6 +97,8 @@ extern "C" {
#define BLE_MESH_ADV_PHY_OPTION_PREFER_S8 2
#define BLE_MESH_ADV_PHY_OPTION_REQUIRE_S2 3
#define BLE_MESH_ADV_PHY_OPTION_REQUIRE_S8 4
#define BLE_MESH_ADV_PRI_PHY_DEFAULT BLE_MESH_ADV_PHY_1M
#define BLE_MESH_ADV_SEC_PHY_DEFAULT BLE_MESH_ADV_PHY_1M
#endif
/* BD ADDR types */
@@ -112,6 +120,9 @@ extern "C" {
#define BLE_MESH_ADV_SCAN_RSP 0x04
#else
/* Bluetooth Core Spec 6.0, Vol 4, Part E, 7.7.65.13 */
#if CONFIG_BLE_MESH_EXT_ADV
#define BLE_MESH_EXT_ADV_NONCONN_IND (0)
#endif
#define BLE_MESH_ADV_IND (0x13)
#define BLE_MESH_ADV_DIRECT_IND (0x15)
#define BLE_MESH_ADV_SCAN_IND (0x12)
@@ -120,10 +131,15 @@ extern "C" {
#define BLE_MESH_ADV_SCAN_RSP (0x1b)
#endif
#define BLE_MESH_ADV_ITVL_DEFAULT (0)
#define BLE_MESH_ADV_CNT_DEFAULT (0)
/* advertising channel map */
#define BLE_MESH_ADV_CHNL_37 BIT(0)
#define BLE_MESH_ADV_CHNL_38 BIT(1)
#define BLE_MESH_ADV_CHNL_39 BIT(2)
#define BLE_MESH_ADV_CHAN_UNASSIGNED (0)
#define BLE_MESH_ADV_CHAN_37 BIT(0)
#define BLE_MESH_ADV_CHAN_38 BIT(1)
#define BLE_MESH_ADV_CHAN_39 BIT(2)
#define BLE_MESH_ADV_CHAN_DEFAULT (BLE_MESH_ADV_CHAN_39|BLE_MESH_ADV_CHAN_38|BLE_MESH_ADV_CHAN_37)
/* Advertising filter policy */
#define BLE_MESH_AP_SCAN_CONN_ALL 0x00
@@ -472,6 +488,8 @@ struct bt_mesh_adv_param {
/** Maximum Advertising Interval (N * 0.625) */
uint16_t interval_max;
uint8_t channel_map;
#if CONFIG_BLE_MESH_USE_BLE_50
/** Maximum Advertising Duration (N * 0.625) */
uint16_t adv_duration;
@@ -484,6 +502,10 @@ struct bt_mesh_adv_param {
/** Advertising Secondary PHY */
uint8_t secondary_phy;
int8_t tx_power;
uint8_t include_tx_power : 1;
#endif
};
@@ -577,6 +599,8 @@ struct bt_mesh_adv_report {
/* Secondary advertising PHY */
uint8_t secondary_phy;
uint8_t tx_power;
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
};
@@ -112,7 +112,11 @@ struct bt_mesh_hci_cp_set_adv_param {
#define BLE_MESH_HCI_OP_SET_ADV_DATA BLE_MESH_OP(BLE_MESH_OGF_LE, 0x0008)
struct bt_mesh_hci_cp_set_adv_data {
uint8_t len;
#if CONFIG_BLE_MESH_LONG_PACKET
uint8_t data[2 + CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN];
#else
uint8_t data[31];
#endif
} __attribute__((packed));
#define BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA BLE_MESH_OP(BLE_MESH_OGF_LE, 0x0009)
+76 -16
View File
@@ -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
*/
@@ -27,7 +27,6 @@
#include "fast_prov.h"
#include "prov_node.h"
#include "test.h"
#include "fast_prov.h"
#include "proxy_client.h"
#include "proxy_server.h"
#include "pvnr_mgmt.h"
@@ -1674,7 +1673,27 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
*/
#if !CONFIG_BLE_MESH_RELAY_ADV_BUF
buf = bt_mesh_adv_create(BLE_MESH_ADV_DATA, K_NO_WAIT);
#if CONFIG_BLE_MESH_EXT_ADV
if (rx->ctx.enh.ext_adv_cfg_used) {
#if CONFIG_BLE_MESH_LONG_PACKET
if (rx->ctx.enh.long_pkt_cfg) {
buf = bt_mesh_adv_create(BLE_MESH_ADV_EXT_LONG_RELAY_DATA, K_NO_WAIT);
} else
#endif
{
buf = bt_mesh_adv_create(BLE_MESH_ADV_EXT_DATA, K_NO_WAIT);
}
if (buf) {
EXT_ADV(buf)->primary_phy = rx->ctx.enh.ext_adv_cfg.primary_phy;
EXT_ADV(buf)->secondary_phy = rx->ctx.enh.ext_adv_cfg.secondary_phy;
EXT_ADV(buf)->include_tx_power = rx->ctx.enh.ext_adv_cfg.include_tx_power;
EXT_ADV(buf)->tx_power = rx->ctx.enh.ext_adv_cfg.tx_power;
}
} else
#endif
{
buf = bt_mesh_adv_create(BLE_MESH_ADV_DATA, K_NO_WAIT);
}
#else
/* Check if the number of relay packets in queue is too large, if so
* use minimum relay retransmit value for later relay packets.
@@ -1682,7 +1701,27 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
if (bt_mesh_get_stored_relay_count() >= BLE_MESH_MAX_STORED_RELAY_COUNT) {
xmit = BLE_MESH_TRANSMIT(0, 20);
}
buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_RELAY_DATA, K_NO_WAIT);
#if CONFIG_BLE_MESH_EXT_ADV
if (rx->ctx.enh.ext_adv_cfg_used) {
#if CONFIG_BLE_MESH_LONG_PACKET
if (rx->ctx.enh.long_pkt_cfg) {
buf = bt_mesh_adv_create(BLE_MESH_ADV_EXT_LONG_RELAY_DATA, K_NO_WAIT);
} else
#endif
{
buf = bt_mesh_adv_create(BLE_MESH_ADV_EXT_DATA, K_NO_WAIT);
}
if (buf) {
EXT_ADV(buf)->primary_phy = rx->ctx.enh.ext_adv_cfg.primary_phy;
EXT_ADV(buf)->secondary_phy = rx->ctx.enh.ext_adv_cfg.secondary_phy;
EXT_ADV(buf)->include_tx_power = rx->ctx.enh.ext_adv_cfg.include_tx_power;
EXT_ADV(buf)->tx_power = rx->ctx.enh.ext_adv_cfg.tx_power;
}
} else
#endif
{
buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_RELAY_DATA, K_NO_WAIT);
}
#endif
if (!buf) {
@@ -1922,33 +1961,42 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data,
struct bt_mesh_net_rx *rx,
enum bt_mesh_net_if net_if)
{
NET_BUF_SIMPLE_DEFINE(buf, 29);
struct net_buf_simple_state state = {0};
struct net_buf_simple *buf = NULL;
assert(rx);
BT_DBG("rssi %d net_if %u", rx->ctx.recv_rssi, net_if);
if (data->len > (BLE_MESH_GAP_ADV_MAX_LEN - 2)) {
BT_ERR("Invalid net message length %d", data->len);
return;
}
if (!ready_to_recv()) {
return;
}
if (bt_mesh_net_decode(data, net_if, rx, &buf)) {
buf = bt_mesh_alloc_buf(data->len);
if (!buf) {
BT_ERR("Alloc net msg buffer failed");
return;
}
BT_DBG("rssi %d net_if %u", rx->ctx.recv_rssi, net_if);
if (bt_mesh_net_decode(data, net_if, rx, buf)) {
goto free_net_msg_buf;
}
if (ignore_net_msg(rx->ctx.addr, rx->ctx.recv_dst)) {
return;
goto free_net_msg_buf;
}
/* Save the state so the buffer can later be relayed */
net_buf_simple_save(&buf, &state);
net_buf_simple_save(buf, &state);
BT_BQB(BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_NODE | \
BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_NET,
"\nNetRecv: ctl: %d, src: %d, dst: %d, ttl: %d, data: 0x%s",
rx->ctl, rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_ttl,
bt_hex(buf.data + BLE_MESH_NET_HDR_LEN, buf.len - BLE_MESH_NET_HDR_LEN));
bt_hex(buf->data + BLE_MESH_NET_HDR_LEN, buf->len - BLE_MESH_NET_HDR_LEN));
/* If trying to handle a message with DST set to all-directed-forwarding-nodes,
* we need to make sure the directed forwarding functionality is enabled in the
@@ -1958,6 +2006,15 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data,
bt_mesh_fixed_direct_match(rx->sub, rx->ctx.recv_dst) ||
bt_mesh_elem_find(rx->ctx.recv_dst));
#if CONFIG_BLE_MESH_LONG_PACKET
/* It should be noted that if the length of buf
* is less than or equal to 29, it still may be the
* last segment for a long packet, But if the bit
* is set, it must be part of the long packet*/
rx->ctx.enh.long_pkt_cfg_used = (buf->len >= 29);
rx->ctx.enh.long_pkt_cfg = BLE_MESH_LONG_PACKET_FORCE;
#endif
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
#if CONFIG_BLE_MESH_PRB_SRV
bt_mesh_private_gatt_proxy_state_get() != BLE_MESH_PRIVATE_GATT_PROXY_ENABLED &&
@@ -1968,7 +2025,7 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data,
if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_DISABLED &&
!rx->local_match) {
BT_INFO("Proxy is disabled; ignoring message");
return;
goto free_net_msg_buf;
}
/* If the Directed Proxy Server receives a valid Network PDU from the Directed
@@ -1995,7 +2052,7 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data,
* credentials. Remove it from the message cache so that we accept
* it again in the future.
*/
if (bt_mesh_trans_recv(&buf, rx) == -EAGAIN) {
if (bt_mesh_trans_recv(buf, rx) == -EAGAIN) {
BT_WARN("Removing rejected message from Network Message Cache");
msg_cache[rx->msg_cache_idx].src = BLE_MESH_ADDR_UNASSIGNED;
/* Rewind the next index now that we're not using this entry */
@@ -2011,9 +2068,12 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data,
&& !rx->replay_msg
#endif
)) {
net_buf_simple_restore(&buf, &state);
bt_mesh_net_relay(&buf, rx);
net_buf_simple_restore(buf, &state);
bt_mesh_net_relay(buf, rx);
}
free_net_msg_buf:
bt_mesh_free(buf);
}
static void ivu_refresh(struct k_work *work)
+9 -1
View File
@@ -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
*/
@@ -473,6 +473,14 @@ static inline void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi,
enum bt_mesh_net_if net_if)
{
struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi };
#if CONFIG_BLE_MESH_EXT_ADV
rx.ctx.enh.adv_cfg_used = false;
rx.ctx.enh.ext_adv_cfg_used = false;
#if CONFIG_BLE_MESH_LONG_PACKET
rx.ctx.enh.long_pkt_cfg_used = (data->len >= 29);
rx.ctx.enh.long_pkt_cfg = BLE_MESH_LONG_PACKET_FORCE;
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
#endif /* CONFIG_BLE_MESH_EXT_ADV */
bt_mesh_generic_net_recv(data, &rx, net_if);
}
@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA
* SPDX-FileCopyrightText: 2015-2016 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
*/
@@ -494,6 +494,14 @@ void bt_mesh_ble_ext_adv_report(struct ble_gap_ext_disc_desc *desc)
}
#endif
#if CONFIG_BLE_MESH_LONG_PACKET
static struct {
struct bt_mesh_adv_report adv_rpt;
uint8_t adv_data_len;
uint8_t adv_data[2 + CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN];
} adv_report_cache;
#endif
int disc_cb(struct ble_gap_event *event, void *arg)
{
#if CONFIG_BLE_MESH_USE_BLE_50
@@ -517,29 +525,84 @@ int disc_cb(struct ble_gap_event *event, void *arg)
#if CONFIG_BLE_MESH_USE_BLE_50
case BLE_GAP_EVENT_EXT_DISC: {
struct bt_mesh_adv_report adv_rpt = {0};
uint8_t *adv_data = NULL;
uint8_t adv_data_len = 0;
desc = &event->ext_disc;
if (desc->length_data > BLE_MESH_GAP_ADV_MAX_LEN) {
/* @todo: bt_mesh_ble_ext_adv_report and transfer
* to user have functional duplication */
goto report_to_user;
}
memcpy(&adv_rpt.addr, &desc->addr, sizeof(bt_mesh_addr_t));
adv_rpt.rssi = desc->rssi;
adv_rpt.adv_type = desc->props;
adv_rpt.primary_phy = desc->prim_phy;
adv_rpt.secondary_phy = desc->sec_phy;
adv_rpt.tx_power = desc->tx_power;
adv_data = (uint8_t *)desc->data;
adv_data_len = desc->length_data;
net_buf_simple_init_with_data(&adv_rpt.adv_data, (void *)desc->data, desc->length_data);
#if CONFIG_BLE_MESH_LONG_PACKET
switch (desc->data_status) {
case BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE:
if (adv_report_cache.adv_data_len) {
memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len,
desc->data, desc->length_data);
adv_report_cache.adv_data_len += desc->length_data;
adv_data = adv_report_cache.adv_data;
adv_data_len = adv_report_cache.adv_data_len;
adv_report_cache.adv_data_len = 0;
}
break;
case BLE_GAP_EXT_ADV_DATA_STATUS_INCOMPLETE:
if ((adv_report_cache.adv_data_len + desc->length_data) > BLE_MESH_GAP_ADV_MAX_LEN) {
adv_report_cache.adv_data_len = 0;
return false;
}
if (adv_report_cache.adv_data_len == 0) {
memcpy(&adv_report_cache.adv_rpt, &adv_rpt, sizeof(struct bt_mesh_adv_report));
}
memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len,
desc->data, desc->length_data);
adv_report_cache.adv_data_len += desc->length_data;
/* To avoid discarding user's packets,
* it is assumed here that this packet
* is not mesh's packet */
goto report_to_user;
case BLE_GAP_EXT_ADV_DATA_STATUS_TRUNCATED:
if (adv_report_cache.adv_data_len) {
memset(&adv_report_cache, 0, sizeof(adv_report_cache));
}
goto report_to_user;
default:
assert(0);
}
#else /* CONFIG_BLE_MESH_LONG_PACKET */
if (desc->data_status != BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE) {
goto report_to_user;
}
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
net_buf_simple_init_with_data(&adv_rpt.adv_data, (void *)adv_data, adv_data_len);
if (bt_mesh_scan_dev_found_cb) {
/* TODO: Support Scan Response data length for NimBLE host */
if (desc->props & BLE_HCI_ADV_LEGACY_MASK) {
if (desc->props & BLE_HCI_ADV_LEGACY_MASK ||
(IS_ENABLED(CONFIG_BLE_MESH_EXT_ADV) &&
desc->props == BLE_MESH_EXT_ADV_NONCONN_IND)) {
bt_mesh_scan_dev_found_cb(&adv_rpt);
}
}
/* Mesh didn't process that data */
if (adv_rpt.adv_data.len == desc->length_data) {
bt_mesh_ble_ext_adv_report(desc);
if (adv_rpt.adv_data.len == adv_data_len) {
goto report_to_user;
}
break;
report_to_user:
bt_mesh_ble_ext_adv_report(desc);
break;
}
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
@@ -1101,6 +1164,11 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
#endif /* CONFIG_BLE_MESH_NODE */
#if CONFIG_BLE_MESH_USE_BLE_50
static struct {
bool set;
struct ble_gap_ext_adv_params param;
} last_param[BLE_MESH_ADV_INS_TYPES_NUM];
int bt_le_ext_adv_start(const uint8_t inst_id,
const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *ad, size_t ad_len,
@@ -1125,7 +1193,7 @@ int bt_le_ext_adv_start(const uint8_t inst_id,
return -EALREADY;
}
#endif
buf = bt_mesh_calloc(ad_len * BLE_HS_ADV_MAX_SZ);
buf = bt_mesh_calloc(ad_len * BLE_MESH_GAP_ADV_MAX_LEN);
if (!buf) {
BT_ERR("ad buffer alloc failed");
return -ENOMEM;
@@ -1201,16 +1269,19 @@ int bt_le_ext_adv_start(const uint8_t inst_id,
adv_params.legacy_pdu = true;
} else {
if (param->primary_phy == BLE_MESH_ADV_PHY_1M &&
param->secondary_phy == BLE_MESH_ADV_PHY_1M) {
adv_params.legacy_pdu = true;
param->secondary_phy == BLE_MESH_ADV_PHY_1M &&
param->include_tx_power == false &&
ad->data_len <= 29) {
adv_params.legacy_pdu = true;
}
}
adv_params.sid = inst_id;
adv_params.primary_phy = param->primary_phy;
adv_params.secondary_phy = param->secondary_phy;
adv_params.tx_power = 0x7F; // tx power will be selected by controller
adv_params.tx_power = param->tx_power;
adv_params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
adv_params.include_tx_power = param->include_tx_power;
interval = param->interval_min;
@@ -1230,10 +1301,23 @@ int bt_le_ext_adv_start(const uint8_t inst_id,
adv_params.itvl_min = interval;
adv_params.itvl_max = interval;
err = ble_gap_ext_adv_configure(inst_id, &adv_params, NULL, gap_event_cb, NULL);
if (err != 0) {
BT_ERR("Advertising config failed: err %d", err);
return err;
if (memcmp(&adv_params, &last_param[inst_id].param,
sizeof(struct ble_gap_ext_adv_params))) {
if (last_param[inst_id].set) {
err = ble_gap_ext_adv_remove(inst_id);
if (err != 0 && err != BLE_HS_EALREADY) {
BT_ERR("Advertising rm failed: err %d", err);
return err;
}
}
last_param[inst_id].set = true;
err = ble_gap_ext_adv_configure(inst_id, &adv_params, NULL, gap_event_cb, NULL);
if (err != 0) {
BT_ERR("Advertising config failed: err %d", err);
return err;
}
memcpy(&last_param[inst_id].param, &adv_params, sizeof(struct ble_gap_ext_adv_params));
}
err = ble_gap_ext_adv_set_data(inst_id, data);
@@ -1358,6 +1442,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
adv_params.itvl_min = interval;
adv_params.itvl_max = interval;
adv_params.channel_map = param->channel_map;
again:
err = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params,
@@ -1460,7 +1545,7 @@ int bt_mesh_ble_ext_adv_start(const uint8_t inst_id,
adv_params.itvl_min = param->interval;
adv_params.itvl_max = param->interval;
adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39;
adv_params.channel_map = BLE_MESH_ADV_CHAN_37 | BLE_MESH_ADV_CHAN_38 | BLE_MESH_ADV_CHAN_39;
adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL;
adv_params.primary_phy = BLE_MESH_ADV_PHY_1M;
adv_params.secondary_phy = BLE_MESH_ADV_PHY_1M;
@@ -1581,7 +1666,7 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param,
}
adv_params.itvl_min = param->interval;
adv_params.itvl_max = param->interval;
adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39;
adv_params.channel_map = BLE_MESH_ADV_CHAN_37 | BLE_MESH_ADV_CHAN_38 | BLE_MESH_ADV_CHAN_39;
adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL;
adv_params.high_duty_cycle = (param->adv_type == BLE_MESH_ADV_DIRECT_IND) ? true : false;
@@ -56,11 +56,14 @@ static const struct bt_mesh_adv_param slow_adv_param = {
.options = ADV_OPT,
.interval_min = BLE_MESH_GAP_ADV_SLOW_INT_MIN,
.interval_max = BLE_MESH_GAP_ADV_SLOW_INT_MAX,
.channel_map = BLE_MESH_ADV_CHAN_DEFAULT,
#if CONFIG_BLE_MESH_USE_BLE_50
.primary_phy = BLE_MESH_ADV_PHY_1M,
.secondary_phy = BLE_MESH_ADV_PHY_1M,
.adv_duration = 0,
.adv_count = 0,
.tx_power = 0x7f,
.include_tx_power = false,
#endif
};
@@ -68,11 +71,14 @@ static const struct bt_mesh_adv_param fast_adv_param = {
.options = ADV_OPT,
.interval_min = BLE_MESH_GAP_ADV_FAST_INT_MIN_0,
.interval_max = BLE_MESH_GAP_ADV_FAST_INT_MAX_0,
.channel_map = BLE_MESH_ADV_CHAN_DEFAULT,
#if CONFIG_BLE_MESH_USE_BLE_50
.primary_phy = BLE_MESH_ADV_PHY_1M,
.secondary_phy = BLE_MESH_ADV_PHY_1M,
.adv_duration = 0,
.adv_count = 0,
.tx_power = 0x7f,
.include_tx_power = false,
#endif
};
+23 -2
View File
@@ -424,7 +424,11 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt)
net_buf_simple_save(buf, &buf_state);
if (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND &&
if (
#if CONFIG_BLE_MESH_LONG_PACKET
adv_rpt->adv_type != 0 &&
#endif
adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND &&
adv_rpt->adv_type != BLE_MESH_ADV_IND
#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
&& adv_rpt->adv_type != BLE_MESH_ADV_SCAN_RSP
@@ -490,7 +494,11 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt)
buf->len = len - 1;
if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE ||
type == BLE_MESH_DATA_MESH_BEACON) && (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND)) {
type == BLE_MESH_DATA_MESH_BEACON) && (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND
#if CONFIG_BLE_MESH_EXT_ADV
&& adv_rpt->adv_type != BLE_MESH_EXT_ADV_NONCONN_IND
#endif
)) {
BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_rpt->adv_type);
return;
}
@@ -500,6 +508,19 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt)
struct bt_mesh_net_rx rx = {
.ctx.recv_rssi = adv_rpt->rssi,
};
#if CONFIG_BLE_MESH_EXT_ADV
if (adv_rpt->adv_type == BLE_MESH_EXT_ADV_NONCONN_IND) {
rx.ctx.enh.ext_adv_cfg_used = true;
rx.ctx.enh.ext_adv_cfg.primary_phy = adv_rpt->primary_phy;
rx.ctx.enh.ext_adv_cfg.secondary_phy = adv_rpt->secondary_phy;
if (adv_rpt->tx_power == 0x7f) {
rx.ctx.enh.ext_adv_cfg.include_tx_power = false;
} else {
rx.ctx.enh.ext_adv_cfg.include_tx_power = true;
}
rx.ctx.enh.ext_adv_cfg.tx_power = adv_rpt->tx_power;
}
#endif /* CONFIG_BLE_MESH_EXT_ADV */
bt_mesh_generic_net_recv(buf, &rx, BLE_MESH_NET_IF_ADV);
break;
#if CONFIG_BLE_MESH_PB_ADV
+277 -37
View File
@@ -77,8 +77,16 @@ _Static_assert(CONFIG_BLE_MESH_ADV_BUF_COUNT >= (CONFIG_BLE_MESH_TX_SEG_MAX + 3)
/* How long to wait for available buffers before giving up */
#define BUF_TIMEOUT K_NO_WAIT
struct seg_info {
uint8_t ctl:1; /* Control message */
#if CONFIG_BLE_MESH_LONG_PACKET
uint8_t long_pkt:1; /* Long packet */
#endif
};
static struct seg_tx {
struct bt_mesh_subnet *sub;
// @todo: select the max one between large seg max and normal seg max
struct net_buf *seg[CONFIG_BLE_MESH_TX_SEG_MAX];
uint64_t seq_auth;
uint16_t dst;
@@ -100,10 +108,11 @@ static struct seg_tx {
static struct seg_rx {
struct bt_mesh_subnet *sub;
uint64_t seq_auth;
uint8_t seg_n:5,
uint16_t seg_n:5,
ctl:1,
in_use:1,
obo:1;
obo:1,
ext:1;
uint8_t hdr;
uint8_t ttl;
uint16_t src;
@@ -112,14 +121,20 @@ static struct seg_rx {
uint32_t last;
struct k_delayed_work ack_timer;
struct net_buf_simple buf;
} seg_rx[CONFIG_BLE_MESH_RX_SEG_MSG_COUNT] = {
[0 ... (CONFIG_BLE_MESH_RX_SEG_MSG_COUNT - 1)] = {
.buf.size = CONFIG_BLE_MESH_RX_SDU_MAX,
},
};
} seg_rx[CONFIG_BLE_MESH_RX_SEG_MSG_COUNT];
static uint8_t seg_rx_buf_data[(CONFIG_BLE_MESH_RX_SEG_MSG_COUNT *
CONFIG_BLE_MESH_RX_SDU_MAX)];
#if CONFIG_BLE_MESH_LONG_PACKET
/* @todo: could merge ext_seg_rx into seg_rx */
static struct seg_rx ext_seg_rx[CONFIG_BLE_MESH_LONG_PACKET_RX_SEG_CNT];
static uint8_t ext_seg_rx_buf_data[(CONFIG_BLE_MESH_LONG_PACKET_RX_SEG_CNT *
BLE_MESH_EXT_RX_SDU_MAX)];
#endif
static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
const uint8_t *hdr, const uint64_t *seq_auth,
uint8_t seg_n);
static bt_mesh_mutex_t seg_rx_lock;
@@ -236,15 +251,47 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu,
{
struct net_buf *buf = NULL;
enum bt_mesh_adv_type adv_type = BLE_MESH_ADV_DATA;
BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u",
tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->len);
buf = bt_mesh_adv_create(BLE_MESH_ADV_DATA, BUF_TIMEOUT);
#if CONFIG_BLE_MESH_EXT_ADV
#if CONFIG_BLE_MESH_LONG_PACKET
if (tx->ctx->enh.long_pkt_cfg_used &&
(tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE ||
(tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
sdu->len > (BLE_MESH_SDU_UNSEG_MAX + 4)))) {
adv_type = BLE_MESH_ADV_EXT_LONG_DATA;
} else
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
{
if (tx->ctx->enh.ext_adv_cfg_used) {
adv_type = BLE_MESH_ADV_EXT_DATA;
}
}
#endif /* CONFIG_BLE_MESH_EXT_ADV */
buf = bt_mesh_adv_create(adv_type, BUF_TIMEOUT);
if (!buf) {
BT_ERR("Out of network buffers");
return -ENOBUFS;
}
if (tx->ctx->enh.adv_cfg_used) {
BLE_MESH_ADV(buf)->channel_map = tx->ctx->enh.adv_cfg.channel_map;
BLE_MESH_ADV(buf)->adv_cnt = tx->ctx->enh.adv_cfg.adv_cnt;
BLE_MESH_ADV(buf)->adv_itvl = tx->ctx->enh.adv_cfg.adv_itvl;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (tx->ctx->enh.ext_adv_cfg_used) {
EXT_ADV(buf)->primary_phy = tx->ctx->enh.ext_adv_cfg.primary_phy;
EXT_ADV(buf)->secondary_phy = tx->ctx->enh.ext_adv_cfg.secondary_phy;
EXT_ADV(buf)->include_tx_power = tx->ctx->enh.ext_adv_cfg.include_tx_power;
EXT_ADV(buf)->tx_power = tx->ctx->enh.ext_adv_cfg.tx_power;
}
#endif
net_buf_reserve(buf, BLE_MESH_NET_HDR_LEN);
if (ctl_op) {
@@ -287,13 +334,21 @@ send:
return bt_mesh_net_send(tx, buf, cb, cb_data);
}
static inline uint8_t seg_len(bool ctl)
static inline uint8_t seg_len(struct seg_info *si)
{
if (ctl) {
return BLE_MESH_CTL_SEG_SDU_MAX;
if (si->ctl) {
return
#if CONFIG_BLE_MESH_LONG_PACKET
si->long_pkt ? BLE_MESH_EXT_CTL_SEG_SDU_MAX :
#endif
BLE_MESH_CTL_SEG_SDU_MAX;
}
return BLE_MESH_APP_SEG_SDU_MAX;
return
#if CONFIG_BLE_MESH_LONG_PACKET
si->long_pkt ? BLE_MESH_EXT_APP_SEG_SDU_MAX :
#endif
BLE_MESH_APP_SEG_SDU_MAX;
}
bool bt_mesh_tx_in_progress(void)
@@ -311,7 +366,14 @@ bool bt_mesh_tx_in_progress(void)
static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx)
{
bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 3U, BLE_MESH_BUF_REF_SMALL);
/* If the data is sent to itself, then last seg's ref count be equal to 3 */
if (((IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) ||
(IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en())) &&
(bt_mesh_fixed_group_match(tx->dst) || bt_mesh_elem_find(tx->dst))) {
bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 4U, BLE_MESH_BUF_REF_SMALL);
} else {
bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 3U, BLE_MESH_BUF_REF_SMALL);
}
/**
* When cancelling a segment that is still in the adv sending queue, `tx->seg_pending`
@@ -512,7 +574,9 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
const struct bt_mesh_send_cb *cb, void *cb_data,
const uint8_t *ctl_op)
{
enum bt_mesh_adv_type adv_type = BLE_MESH_ADV_DATA;
struct seg_tx *tx = NULL;
struct seg_info si = {0};
uint16_t seq_zero = 0U;
uint8_t seg_hdr = 0U;
uint8_t seg_o = 0U;
@@ -544,16 +608,28 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
}
if (ctl_op) {
si.ctl = 1;
seg_hdr = TRANS_CTL_HDR(*ctl_op, 1);
} else if (net_tx->ctx->app_idx == BLE_MESH_KEY_DEV) {
si.ctl = 0;
seg_hdr = SEG_HDR(0, 0);
} else {
si.ctl = 0;
seg_hdr = SEG_HDR(1, net_tx->aid);
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (net_tx->ctx->enh.long_pkt_cfg_used &&
(net_tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE ||
(net_tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
sdu->len > BLE_MESH_TX_SDU_MAX))) {
si.long_pkt = 1;
}
#endif
tx->dst = net_tx->ctx->addr;
if (sdu->len) {
tx->seg_n = (sdu->len - 1) / seg_len(!!ctl_op);
tx->seg_n = (sdu->len - 1) / seg_len(&si);
} else {
tx->seg_n = 0;
}
@@ -594,14 +670,43 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
for (seg_o = 0U; sdu->len; seg_o++) {
struct net_buf *seg = NULL;
uint16_t len = 0U;
seg = bt_mesh_adv_create(BLE_MESH_ADV_DATA, BUF_TIMEOUT);
#if CONFIG_BLE_MESH_LONG_PACKET
if (si.long_pkt) {
adv_type = BLE_MESH_ADV_EXT_LONG_DATA;
} else
#endif
{
#if CONFIG_BLE_MESH_EXT_ADV
if (net_tx->ctx->enh.ext_adv_cfg_used) {
adv_type = BLE_MESH_ADV_EXT_DATA;
} else
#endif
{
adv_type = BLE_MESH_ADV_DATA;
}
}
seg = bt_mesh_adv_create(adv_type, BUF_TIMEOUT);
if (!seg) {
BT_ERR("Out of segment buffers");
err = -ENOBUFS;
break;
}
if (net_tx->ctx->enh.adv_cfg_used) {
BLE_MESH_ADV(seg)->channel_map = net_tx->ctx->enh.adv_cfg.channel_map;
BLE_MESH_ADV(seg)->adv_cnt = net_tx->ctx->enh.adv_cfg.adv_cnt;
BLE_MESH_ADV(seg)->adv_itvl = net_tx->ctx->enh.adv_cfg.adv_itvl;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (net_tx->ctx->enh.ext_adv_cfg_used) {
EXT_ADV(seg)->primary_phy = net_tx->ctx->enh.ext_adv_cfg.primary_phy;
EXT_ADV(seg)->secondary_phy = net_tx->ctx->enh.ext_adv_cfg.secondary_phy;
EXT_ADV(seg)->include_tx_power = net_tx->ctx->enh.ext_adv_cfg.include_tx_power;
EXT_ADV(seg)->tx_power = net_tx->ctx->enh.ext_adv_cfg.tx_power;
}
#endif /* CONFIG_BLE_MESH_EXT_ADV */
net_buf_reserve(seg, BLE_MESH_NET_HDR_LEN);
net_buf_add_u8(seg, seg_hdr);
@@ -609,7 +714,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
net_buf_add_u8(seg, (((seq_zero & 0x3f) << 2) | (seg_o >> 3)));
net_buf_add_u8(seg, ((seg_o & 0x07) << 5) | tx->seg_n);
len = MIN(sdu->len, seg_len(!!ctl_op));
len = MIN(sdu->len, seg_len(&si));
net_buf_add_mem(seg, net_buf_simple_pull_mem(sdu, len), len);
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
@@ -694,9 +799,22 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
return -EINVAL;
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (tx->ctx->enh.long_pkt_cfg_used == true &&
(tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE ||
tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER) &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
} else {
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
}
#else
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
#endif
BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx,
tx->ctx->app_idx, tx->ctx->addr);
@@ -794,7 +912,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr,
/* Use bt_mesh_alloc_buf() instead of NET_BUF_SIMPLE_DEFINE to avoid
* causing btu task stack overflow.
*/
sdu = bt_mesh_alloc_buf(CONFIG_BLE_MESH_RX_SDU_MAX - BLE_MESH_MIC_SHORT);
sdu = bt_mesh_alloc_buf(buf->len);
if (!sdu) {
BT_ERR("%s, Out of memory", __func__);
return -ENOMEM;
@@ -1342,19 +1460,34 @@ static void seg_ack(struct k_work *work)
bt_mesh_seg_rx_unlock();
}
static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
static inline uint16_t sdu_len_max(uint8_t seg_n,uint16_t seg_len)
{
return ((seg_n + 1) * seg_len(ctl) <= CONFIG_BLE_MESH_RX_SDU_MAX);
return ((seg_n + 1) * seg_len);
}
static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
const uint64_t *seq_auth)
static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n, uint16_t buf_len)
{
struct seg_info si = {
.ctl = ctl,
};
#if CONFIG_BLE_MESH_LONG_PACKET
if ((sdu_len_max(seg_n, buf_len) > CONFIG_BLE_MESH_RX_SDU_MAX)) {
si.long_pkt = 1;
return ((seg_n + 1) * seg_len(&si) <= BLE_MESH_EXT_RX_SDU_MAX);
}
#endif
return ((seg_n + 1) * seg_len(&si) <= CONFIG_BLE_MESH_RX_SDU_MAX);
}
static struct seg_rx *seg_rx_find_with_buf(struct bt_mesh_net_rx *net_rx,
const uint64_t *seq_auth,
struct seg_rx *rx_buf,
uint16_t rx_buf_size )
{
int i;
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i];
for (i = 0; i < rx_buf_size; i++) {
struct seg_rx *rx = &rx_buf[i];
if (rx->src != net_rx->ctx.addr ||
rx->dst != net_rx->ctx.recv_dst) {
continue;
@@ -1387,6 +1520,64 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
return NULL;
}
static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
const uint64_t *seq_auth)
{
#if CONFIG_BLE_MESH_LONG_PACKET
struct seg_rx *rx = NULL;
rx = seg_rx_find_with_buf(net_rx, seq_auth, seg_rx, ARRAY_SIZE(seg_rx));
if (rx) {
if (likely(!net_rx->ctx.enh.long_pkt_cfg_used)) {
return rx;
}
if (rx->seq_auth != *seq_auth) {
return rx;
}
/* The first received segment that is possible is the last segment.
* The segment information is stored in seg_rx, so it needs to be
* confirmed in seg_rx.
* This will only happen when the last segment is received
* */
assert(rx->block == BIT(rx->seg_n));
assert(rx->ctl == net_rx->ctl);
struct seg_info si = {
.ctl = net_rx->ctl,
.long_pkt = 0,
};
/* @note: This situation will not occur in theory.
* If it occurs, please check the reason carefully */
if (rx->buf.len <= (rx->seg_n * seg_len(&si))) {
BT_ERR("Incorrect packet length, the rx will be reset");
seg_rx_reset(rx, true);
return NULL;
}
/* Copy the information in seg_rx into ext_seg_rx */
struct seg_rx *ext_rx = seg_rx_alloc(net_rx, &(rx->hdr), seq_auth, rx->seg_n);
uint16_t last_seg_len = rx->buf.len - (rx->seg_n * seg_len(&si));
uint8_t *last_seg = rx->buf.data + (rx->seg_n * seg_len(&si));
/* Update to long packet length */
si.long_pkt = 1;
ext_rx->buf.len = rx->seg_n * seg_len(&si) + last_seg_len;
ext_rx->block = rx->block;
ext_rx->obo = rx->obo;
memcpy(ext_rx->buf.data + (rx->seg_n * seg_len(&si)), last_seg, last_seg_len);
seg_rx_reset(rx, true);
return ext_rx;
}
return seg_rx_find_with_buf(net_rx, seq_auth, ext_seg_rx, ARRAY_SIZE(ext_seg_rx));
#else
return seg_rx_find_with_buf(net_rx, seq_auth, seg_rx, ARRAY_SIZE(seg_rx));
#endif
}
static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
const uint8_t *hdr, uint8_t seg_n)
{
@@ -1413,9 +1604,25 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
uint8_t seg_n)
{
int i;
/* By default, traditional seg_rx is used for allocation.
* If the first segment received is the last segment of
* the long packet, and its length is the length of the traditional packet,
* Since it is impossible to determine whether it is a long packet
* under the current situation, can only copy the rx information
* into the ext_rx buffer when the next segment received and can be
* confirmed to be a long packet*/
struct seg_rx *seg_rx_buf = seg_rx;
uint16_t rx_buf_size = ARRAY_SIZE(seg_rx);
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i];
#if CONFIG_BLE_MESH_LONG_PACKET
if (net_rx->ctx.enh.long_pkt_cfg_used) {
seg_rx_buf = ext_seg_rx;
rx_buf_size = ARRAY_SIZE(ext_seg_rx);
}
#endif
for (i = 0; i < rx_buf_size; i++) {
struct seg_rx *rx = &seg_rx_buf[i];
if (rx->in_use) {
continue;
@@ -1432,7 +1639,11 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
rx->src = net_rx->ctx.addr;
rx->dst = net_rx->ctx.recv_dst;
rx->block = 0U;
#if CONFIG_BLE_MESH_LONG_PACKET
rx->ext = (seg_rx_buf == ext_seg_rx);
#else
rx->ext = 0;
#endif
BT_DBG("New RX context. Block Complete 0x%08x",
BLOCK_COMPLETE(seg_n));
@@ -1483,6 +1694,14 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
return -EINVAL;
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (buf->len > BLE_MESH_EXT_APP_SEG_SDU_MAX) {
BT_ERR("The seg length(%d) exceeds the maximum seg length(%d) supported",
buf->len, BLE_MESH_EXT_APP_SEG_SDU_MAX);
return -EINVAL;
}
#endif
/* According to Mesh 1.0 specification:
* "The SeqAuth is composed of the IV Index and the sequence number
* (SEQ) of the first segment"
@@ -1543,7 +1762,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
}
/* Bail out early if we're not ready to receive such a large SDU */
if (!sdu_len_is_ok(net_rx->ctl, seg_n)) {
if (!sdu_len_is_ok(net_rx->ctl, seg_n, buf->len)) {
BT_ERR("Too big incoming SDU length");
send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
net_rx->ctx.send_ttl, seq_auth, 0,
@@ -1586,17 +1805,26 @@ found_rx:
return -EALREADY;
}
struct seg_info si = {
.ctl = rx->ctl,
#if CONFIG_BLE_MESH_LONG_PACKET
.long_pkt = rx->ext,
#endif
};
/* All segments, except the last one, must either have 8 bytes of
* payload (for 64bit Net MIC) or 12 bytes of payload (for 32bit
* Net MIC).
*/
if (seg_o == seg_n) {
/* Set the expected final buffer length */
rx->buf.len = seg_n * seg_len(rx->ctl) + buf->len;
BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(rx->ctl),
buf->len, rx->buf.len);
rx->buf.len = seg_n * seg_len(&si) + buf->len;
if (rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX) {
if ((!rx->ext && rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX)
#if CONFIG_BLE_MESH_LONG_PACKET
|| (rx->ext && rx->buf.len > BLE_MESH_EXT_RX_SDU_MAX)
#endif
) {
BT_ERR("Too large SDU len");
send_ack(net_rx->sub, net_rx->ctx.recv_dst,
net_rx->ctx.addr, net_rx->ctx.send_ttl,
@@ -1605,8 +1833,9 @@ found_rx:
return -EMSGSIZE;
}
} else {
if (buf->len != seg_len(rx->ctl)) {
BT_ERR("Incorrect segment size for message type");
if (buf->len != seg_len(&si)) {
BT_ERR("Incorrect segment size for message type %d %d len %d except %d",
rx->ext, rx->ctl, buf->len, seg_len(&si));
return -EINVAL;
}
}
@@ -1620,9 +1849,9 @@ found_rx:
}
/* Location in buffer can be calculated based on seg_o & rx->ctl */
memcpy(rx->buf.data + (seg_o * seg_len(rx->ctl)), buf->data, buf->len);
memcpy(rx->buf.data + (seg_o * seg_len(&si)), buf->data, buf->len);
BT_INFO("Seg %u/%u received", seg_o, seg_n);
BT_INFO("Seg %u/%u received",seg_o, seg_n);
/* Mark segment as received */
rx->block |= BIT(seg_o);
@@ -1804,11 +2033,22 @@ void bt_mesh_trans_init(void)
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
k_delayed_work_init(&seg_rx[i].ack_timer, seg_ack);
seg_rx[i].buf.size = CONFIG_BLE_MESH_RX_SDU_MAX;
seg_rx[i].buf.__buf = (seg_rx_buf_data +
(i * CONFIG_BLE_MESH_RX_SDU_MAX));
seg_rx[i].buf.data = seg_rx[i].buf.__buf;
}
#if CONFIG_BLE_MESH_LONG_PACKET
for (i = 0; i < ARRAY_SIZE(ext_seg_rx); i++) {
k_delayed_work_init(&ext_seg_rx[i].ack_timer, seg_ack);
ext_seg_rx[i].buf.size = CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN;
ext_seg_rx[i].buf.__buf = (ext_seg_rx_buf_data +
(i * CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN));
ext_seg_rx[i].buf.data = ext_seg_rx[i].buf.__buf;
}
#endif
bt_mesh_mutex_create(&seg_rx_lock);
}
+277 -30
View File
@@ -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
*/
@@ -55,6 +55,13 @@ _Static_assert(CONFIG_BLE_MESH_ADV_BUF_COUNT >= (CONFIG_BLE_MESH_TX_SEG_MAX + 3)
/* How long to wait for available buffers before giving up */
#define BUF_TIMEOUT K_NO_WAIT
struct seg_info {
uint8_t ctl:1; /* Control message */
#if CONFIG_BLE_MESH_LONG_PACKET
uint8_t long_pkt:1; /* Long packet */
#endif
};
static struct seg_tx {
struct bt_mesh_subnet *sub;
struct net_buf *seg[CONFIG_BLE_MESH_TX_SEG_MAX];
@@ -95,7 +102,8 @@ static struct seg_rx {
in_use:1,
obo:1,
new_seg:1, /* Indicate if a new segment is just received */
sarc:2; /* SAR ACK Retransmissions Count */
sarc:2, /* SAR ACK Retransmissions Count */
ext:1;
uint8_t hdr;
uint8_t ttl;
uint16_t src;
@@ -114,11 +122,22 @@ static struct seg_rx {
static uint8_t seg_rx_buf_data[(CONFIG_BLE_MESH_RX_SEG_MSG_COUNT *
CONFIG_BLE_MESH_RX_SDU_MAX)];
#if CONFIG_BLE_MESH_LONG_PACKET
/* @todo: could merge ext_seg_rx into seg_rx */
static struct seg_rx ext_seg_rx[CONFIG_BLE_MESH_LONG_PACKET_RX_SEG_CNT];
static uint8_t ext_seg_rx_buf_data[(CONFIG_BLE_MESH_LONG_PACKET_RX_SEG_CNT *
BLE_MESH_EXT_RX_SDU_MAX)];
#endif
static const struct bt_mesh_send_cb seg_sent_cb;
static bt_mesh_mutex_t seg_tx_lock;
static bt_mesh_mutex_t seg_rx_lock;
static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
const uint8_t *hdr, const uint64_t *seq_auth,
uint8_t seg_n);
static inline void bt_mesh_seg_tx_lock(void)
{
bt_mesh_r_mutex_lock(&seg_tx_lock);
@@ -263,16 +282,48 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu,
const uint8_t *ctl_op)
{
struct net_buf *buf = NULL;
enum bt_mesh_adv_type adv_type = BLE_MESH_ADV_DATA;
BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u",
tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->len);
buf = bt_mesh_adv_create(BLE_MESH_ADV_DATA, BUF_TIMEOUT);
#if CONFIG_BLE_MESH_EXT_ADV
#if CONFIG_BLE_MESH_LONG_PACKET
if (tx->ctx->enh.long_pkt_cfg_used &&
(tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE ||
(tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
sdu->len > (BLE_MESH_SDU_UNSEG_MAX + 4)))) {
adv_type = BLE_MESH_ADV_EXT_LONG_DATA;
} else
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
{
if (tx->ctx->enh.ext_adv_cfg_used) {
adv_type = BLE_MESH_ADV_EXT_DATA;
}
}
#endif /* CONFIG_BLE_MESH_EXT_ADV */
buf = bt_mesh_adv_create(adv_type, BUF_TIMEOUT);
if (!buf) {
BT_ERR("Out of network buffers");
return -ENOBUFS;
}
if (tx->ctx->enh.adv_cfg_used) {
BLE_MESH_ADV(buf)->channel_map = tx->ctx->enh.adv_cfg.channel_map;
BLE_MESH_ADV(buf)->adv_cnt = tx->ctx->enh.adv_cfg.adv_cnt;
BLE_MESH_ADV(buf)->adv_itvl = tx->ctx->enh.adv_cfg.adv_itvl;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (tx->ctx->enh.ext_adv_cfg_used) {
EXT_ADV(buf)->primary_phy = tx->ctx->enh.ext_adv_cfg.primary_phy;
EXT_ADV(buf)->secondary_phy = tx->ctx->enh.ext_adv_cfg.secondary_phy;
EXT_ADV(buf)->include_tx_power = tx->ctx->enh.ext_adv_cfg.include_tx_power;
EXT_ADV(buf)->tx_power = tx->ctx->enh.ext_adv_cfg.tx_power;
}
#endif
net_buf_reserve(buf, BLE_MESH_NET_HDR_LEN);
if (ctl_op) {
@@ -315,13 +366,21 @@ send:
return bt_mesh_net_send(tx, buf, cb, cb_data);
}
static inline uint8_t seg_len(bool ctl)
static inline uint8_t seg_len(struct seg_info *si)
{
if (ctl) {
return BLE_MESH_CTL_SEG_SDU_MAX;
if (si->ctl) {
return
#if CONFIG_BLE_MESH_LONG_PACKET
si->long_pkt ? BLE_MESH_EXT_CTL_SEG_SDU_MAX :
#endif
BLE_MESH_CTL_SEG_SDU_MAX;
}
return BLE_MESH_APP_SEG_SDU_MAX;
return
#if CONFIG_BLE_MESH_LONG_PACKET
si->long_pkt ? BLE_MESH_EXT_APP_SEG_SDU_MAX :
#endif
BLE_MESH_APP_SEG_SDU_MAX;
}
bool bt_mesh_tx_in_progress(void)
@@ -812,7 +871,9 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
const struct bt_mesh_send_cb *cb, void *cb_data,
const uint8_t *ctl_op)
{
enum bt_mesh_adv_type adv_type = BLE_MESH_ADV_DATA;
struct seg_tx *tx = NULL;
struct seg_info si = {0};
uint16_t seq_zero = 0U;
uint8_t seg_o = 0U;
int err = 0;
@@ -863,12 +924,25 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
tx->sub = net_tx->sub;
tx->seq_auth = SEQ_AUTH(BLE_MESH_NET_IVI_TX, bt_mesh.seq);
if (ctl_op) {
si.ctl = true;
tx->hdr = TRANS_CTL_HDR(*ctl_op, 1);
} else if (net_tx->ctx->app_idx == BLE_MESH_KEY_DEV) {
si.ctl = false;
tx->hdr = SEG_HDR(0, 0);
} else {
si.ctl = false;
tx->hdr = SEG_HDR(1, net_tx->aid);
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (net_tx->ctx->enh.long_pkt_cfg_used &&
((net_tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
sdu->len > BLE_MESH_TX_SDU_MAX) ||
net_tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE)) {
si.long_pkt = 1;
}
#endif
tx->src = net_tx->src;
tx->dst = net_tx->ctx->addr;
tx->app_idx = net_tx->ctx->app_idx;
@@ -883,7 +957,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
tx->tag = net_tx->ctx->send_tag;
tx->len = sdu->len;
if (sdu->len) {
tx->seg_n = (sdu->len - 1) / seg_len(!!ctl_op);
tx->seg_n = (sdu->len - 1) / seg_len(&si);
} else {
tx->seg_n = 0;
}
@@ -933,13 +1007,45 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
struct net_buf *seg = NULL;
uint16_t len = 0U;
seg = bt_mesh_adv_create(BLE_MESH_ADV_DATA, BUF_TIMEOUT);
#if CONFIG_BLE_MESH_LONG_PACKET
if (si.long_pkt) {
adv_type = BLE_MESH_ADV_EXT_LONG_DATA;
BT_INFO("use ext long adv data");
} else
#endif
{
#if CONFIG_BLE_MESH_EXT_ADV
if (net_tx->ctx->enh.ext_adv_cfg_used) {
adv_type = BLE_MESH_ADV_EXT_DATA;
BT_INFO("use ext adv data");
} else
#endif
{
adv_type = BLE_MESH_ADV_DATA;
}
}
seg = bt_mesh_adv_create(adv_type, BUF_TIMEOUT);
if (!seg) {
BT_ERR("Out of segment buffers");
seg_tx_reset(tx);
return -ENOBUFS;
}
if (net_tx->ctx->enh.adv_cfg_used) {
BLE_MESH_ADV(seg)->channel_map = net_tx->ctx->enh.adv_cfg.channel_map;
BLE_MESH_ADV(seg)->adv_cnt = net_tx->ctx->enh.adv_cfg.adv_cnt;
BLE_MESH_ADV(seg)->adv_itvl = net_tx->ctx->enh.adv_cfg.adv_itvl;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (net_tx->ctx->enh.ext_adv_cfg_used) {
EXT_ADV(seg)->primary_phy = net_tx->ctx->enh.ext_adv_cfg.primary_phy;
EXT_ADV(seg)->secondary_phy = net_tx->ctx->enh.ext_adv_cfg.secondary_phy;
EXT_ADV(seg)->include_tx_power = net_tx->ctx->enh.ext_adv_cfg.include_tx_power;
EXT_ADV(seg)->tx_power = net_tx->ctx->enh.ext_adv_cfg.tx_power;
}
#endif
net_buf_reserve(seg, BLE_MESH_NET_HDR_LEN);
net_buf_add_u8(seg, tx->hdr);
@@ -947,7 +1053,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
net_buf_add_u8(seg, (((seq_zero & 0x3f) << 2) | (seg_o >> 3)));
net_buf_add_u8(seg, ((seg_o & 0x07) << 5) | tx->seg_n);
len = MIN(sdu->len, seg_len(!!ctl_op));
len = MIN(sdu->len, seg_len(&si));
net_buf_add_mem(seg, net_buf_simple_pull_mem(sdu, len), len);
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
@@ -1044,9 +1150,22 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
return -EINVAL;
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (tx->ctx->enh.long_pkt_cfg_used == true &&
(tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE ||
tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER) &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
} else {
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
}
#else
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
#endif
BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx,
tx->ctx->app_idx, tx->ctx->addr);
@@ -1144,7 +1263,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr,
/* Use bt_mesh_alloc_buf() instead of NET_BUF_SIMPLE_DEFINE to avoid
* causing btu task stack overflow.
*/
sdu = bt_mesh_alloc_buf(CONFIG_BLE_MESH_RX_SDU_MAX - BLE_MESH_MIC_SHORT);
sdu = bt_mesh_alloc_buf(buf->len);
if (!sdu) {
BT_ERR("%s, Out of memory", __func__);
return -ENOMEM;
@@ -1843,9 +1962,23 @@ static void discard_msg(struct k_work *work)
seg_rx_reset(rx, false);
}
static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
static inline uint16_t sdu_len_max(uint8_t seg_n,uint16_t seg_len)
{
return ((seg_n + 1) * seg_len(ctl) <= CONFIG_BLE_MESH_RX_SDU_MAX);
return ((seg_n + 1) * seg_len);
}
static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n, uint16_t buf_len)
{
struct seg_info si = {
.ctl = ctl,
};
#if CONFIG_BLE_MESH_LONG_PACKET
if ((sdu_len_max(seg_n, buf_len) > CONFIG_BLE_MESH_RX_SDU_MAX)) {
si.long_pkt = 1;
return ((seg_n + 1) * seg_len(&si) <= BLE_MESH_EXT_RX_SDU_MAX);
}
#endif
return ((seg_n + 1) * seg_len(&si) <= CONFIG_BLE_MESH_RX_SDU_MAX);
}
static void seg_rx_reset_pending(struct bt_mesh_net_rx *net_rx,
@@ -1867,22 +2000,93 @@ static void seg_rx_reset_pending(struct bt_mesh_net_rx *net_rx,
}
}
static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
const uint64_t *seq_auth)
static struct seg_rx *seg_rx_find_with_buf(struct bt_mesh_net_rx *net_rx,
const uint64_t *seq_auth,
struct seg_rx *rx_buf,
uint16_t rx_buf_size )
{
for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i];
for (size_t i = 0; i < rx_buf_size; i++) {
struct seg_rx *rx = &rx_buf[i];
if (rx->src == net_rx->ctx.addr &&
rx->dst == net_rx->ctx.recv_dst &&
rx->seq_auth >= *seq_auth) {
return rx;
rx->dst == net_rx->ctx.recv_dst) {
if (rx->seq_auth >= *seq_auth) {
return rx;
}
/* Received a new packet when the old packet was not fully obtained */
BT_WARN("Duplicate SDU from src 0x%04x auth 0x%04x", net_rx->ctx.addr, rx->seq_auth);
/* Clear out the old context since the sender
* has apparently started sending a new SDU.
*/
seg_rx_reset(rx, true);
/* Return non-match so caller can re-allocate */
return NULL;
}
}
return NULL;
}
static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
const uint64_t *seq_auth)
{
#if CONFIG_BLE_MESH_LONG_PACKET
struct seg_rx *rx = NULL;
rx = seg_rx_find_with_buf(net_rx, seq_auth, seg_rx, ARRAY_SIZE(seg_rx));
if (rx) {
if (likely(!net_rx->ctx.enh.long_pkt_cfg_used)) {
return rx;
}
if (rx->seq_auth != *seq_auth) {
return rx;
}
/* The first received segment that is possible is the last segment.
* The segment information is stored in seg_rx, so it needs to be
* confirmed in seg_rx */
/* This will only happen when the last segment is received */
assert(rx->block == BIT(rx->seg_n));
assert(rx->ctl == net_rx->ctl);
struct seg_info si = {
.ctl = net_rx->ctl,
.long_pkt = 0,
};
/* @note: This situation will not occur in theory.
* If it occurs, please check the reason carefully */
if (rx->buf.len <= (rx->seg_n * seg_len(&si))) {
BT_ERR("Incorrect packet length, the rx will be reset");
seg_rx_reset(rx, true);
return NULL;
}
/* Copy the information in seg_rx into ext_seg_rx */
struct seg_rx *ext_rx = seg_rx_alloc(net_rx, &(rx->hdr), seq_auth, rx->seg_n);
uint16_t last_seg_len = rx->buf.len - (rx->seg_n * seg_len(&si));
uint8_t *last_seg = rx->buf.data + (rx->seg_n * seg_len(&si));
/* Update to long packet length */
si.long_pkt = 1;
ext_rx->buf.len = rx->seg_n * seg_len(&si) + last_seg_len;
ext_rx->block = rx->block;
ext_rx->obo = rx->obo;
memcpy(ext_rx->buf.data + (rx->seg_n * seg_len(&si)), last_seg, last_seg_len);
seg_rx_reset(rx, true);
return ext_rx;
}
return seg_rx_find_with_buf(net_rx, seq_auth, ext_seg_rx, ARRAY_SIZE(ext_seg_rx));
#else
return seg_rx_find_with_buf(net_rx, seq_auth, seg_rx, ARRAY_SIZE(seg_rx));
#endif
}
static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
const uint8_t *hdr, uint8_t seg_n)
{
@@ -1905,8 +2109,25 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
{
int err = 0;
for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i];
/* By default, traditional seg_rx is used for allocation.
* If the first segment received is the last segment of
* the long packet, and its length is the length of the traditional packet,
* Since it is impossible to determine whether it is a long packet
* under the current situation, can only copy the rx information
* into the ext_rx buffer when the next segment received and can be
* confirmed to be a long packet*/
struct seg_rx *seg_rx_buf = seg_rx;
uint16_t rx_buf_size = ARRAY_SIZE(seg_rx);
#if CONFIG_BLE_MESH_LONG_PACKET
if (net_rx->ctx.enh.long_pkt_cfg_used) {
seg_rx_buf = ext_seg_rx;
rx_buf_size = ARRAY_SIZE(ext_seg_rx);
}
#endif
for (size_t i = 0; i < rx_buf_size; i++) {
struct seg_rx *rx = &seg_rx_buf[i];
if (rx->in_use) {
continue;
@@ -1939,7 +2160,11 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
rx->dst = net_rx->ctx.recv_dst;
rx->block = 0U;
rx->last_ack = 0;
#if CONFIG_BLE_MESH_LONG_PACKET
rx->ext = (seg_rx_buf == ext_seg_rx);
#else
rx->ext = 0;
#endif
BT_DBG("New RX context. Block Complete 0x%08x",
BLOCK_COMPLETE(seg_n));
@@ -2062,7 +2287,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
}
/* Bail out early if we're not ready to receive such a large SDU */
if (!sdu_len_is_ok(net_rx->ctl, seg_n)) {
if (!sdu_len_is_ok(net_rx->ctl, seg_n, buf->len)) {
BT_ERR("Too big incoming SDU length");
send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
net_rx->ctx.send_ttl, seq_auth, 0,
@@ -2109,6 +2334,13 @@ found_rx:
return -EALREADY;
}
struct seg_info si = {
.ctl = rx->ctl,
#if CONFIG_BLE_MESH_LONG_PACKET
.long_pkt = rx->ext,
#endif
};
/* All segments, except the last one, must either have 8 bytes of
* payload (for 64bit Net MIC) or 12 bytes of payload (for 32bit
* Net MIC).
@@ -2116,9 +2348,9 @@ found_rx:
*/
if (seg_o == seg_n) {
/* Set the expected final buffer length */
rx->buf.len = seg_n * seg_len(rx->ctl) + buf->len;
rx->buf.len = seg_n * seg_len(&si) + buf->len;
BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(rx->ctl),
BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(&si),
buf->len, rx->buf.len);
/* This should not happen, since we have made sure the whole
@@ -2126,7 +2358,11 @@ found_rx:
* But if the peer device sends the segments of a segmented
* message with different CTL, then the following could happen.
*/
if (rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX) {
if ((!rx->ext && rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX)
#if CONFIG_BLE_MESH_LONG_PACKET
|| (rx->ext && rx->buf.len > BLE_MESH_EXT_RX_SDU_MAX)
#endif
) {
BT_ERR("Too large SDU len %u/%u", rx->buf.len,
CONFIG_BLE_MESH_RX_SDU_MAX);
@@ -2138,14 +2374,14 @@ found_rx:
return -EMSGSIZE;
}
} else {
if (buf->len != seg_len(rx->ctl)) {
if (buf->len != seg_len(&si)) {
BT_ERR("Incorrect segment size for message type");
return -EINVAL;
}
}
/* Location in buffer can be calculated based on seg_o & rx->ctl */
memcpy(rx->buf.data + (seg_o * seg_len(rx->ctl)), buf->data, buf->len);
memcpy(rx->buf.data + (seg_o * seg_len(&si)), buf->data, buf->len);
BT_INFO("Seg %u/%u received", seg_o, seg_n);
@@ -2342,13 +2578,24 @@ void bt_mesh_tx_reset_single(uint16_t dst)
void bt_mesh_trans_init(void)
{
size_t i;
bt_mesh_sar_init();
for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) {
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
seg_rx[i].buf.__buf = (seg_rx_buf_data + (i * CONFIG_BLE_MESH_RX_SDU_MAX));
seg_rx[i].buf.data = seg_rx[i].buf.__buf;
}
#if CONFIG_BLE_MESH_LONG_PACKET
for (i = 0; i < ARRAY_SIZE(ext_seg_rx); i++) {
ext_seg_rx[i].buf.size = CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN;
ext_seg_rx[i].buf.__buf = (ext_seg_rx_buf_data +
(i * CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN));
ext_seg_rx[i].buf.data = ext_seg_rx[i].buf.__buf;
}
#endif
bt_mesh_r_mutex_create(&seg_tx_lock);
bt_mesh_r_mutex_create(&seg_rx_lock);
}
+50 -3
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 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
*/
@@ -17,11 +17,58 @@ extern "C" {
#endif
#define TRANS_SEQ_AUTH_NVAL 0xffffffffffffffff
#if CONFIG_BLE_MESH_LONG_PACKET
#include "adv.h"
/**
* Advertising Packet Length: 29 bytes
*
* Network Layer:
* - Network Header: 9 bytes
* - NetMIC: 4 bytes (for unsegmented messages), 8 bytes (for segmented messages)
*
* Lower Transport PDU:
* - Unsegmented:
* - Header: 1 byte
* - Payload: up to 15 bytes
* - Segmented:
* - Header: 4 bytes
* - Payload: up to 12 bytes per segment
*
* Upper Transport PDU (Access Messages):
* - Unsegmented:
* - TransMIC: 4 bytes
* - Max Access Payload: 11 bytes
* - Segmented:
* - TransMIC size depends on ASZMIC flag:
* - 4-byte TransMIC: Max payload = (32 segments * 12 bytes) - 4 = 380 bytes
* - 8-byte TransMIC: Max payload = (32 segments * 12 bytes) - 8 = 376 bytes
*
* Extended Advertising (ADV) Support:
* - If ADV length is increased to 249 bytes:
* - Max access payload = 32 * (249 - 17) - 8 = 7416 bytes
* - (17 bytes = Network Header + Segment Header + TransMIC)
*
* Reliability Consideration:
* - To achieve an expected valid message ratio of x,
* the minimum ADV packet length should be:
* min_adv_len = 21 / (1 - x)
* Example:
* For >80% success rate (x = 0.8), min_adv_len = 105 bytes
*/
#define BLE_MESH_EXT_SDU_UNSEG_MAX (CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN - 18)
#define BLE_MESH_EXT_CTL_SEG_SDU_MAX (CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN - 21)
#define BLE_MESH_EXT_APP_SEG_SDU_MAX (CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN - 17)
#define BLE_MESH_EXT_TX_SDU_MAX (CONFIG_BLE_MESH_LONG_PACKET_TX_SEG_CNT * BLE_MESH_EXT_APP_SEG_SDU_MAX)
#define BLE_MESH_EXT_RX_SDU_MAX (CONFIG_BLE_MESH_LONG_PACKET_RX_SEG_CNT * BLE_MESH_EXT_APP_SEG_SDU_MAX)
#endif
#define BLE_MESH_SDU_UNSEG_MAX 11
#define BLE_MESH_MSG_UNSEG_MAX (BLE_MESH_SDU_UNSEG_MAX + BLE_MESH_MIC_SHORT)
#define BLE_MESH_CTL_SEG_SDU_MAX 8
/** Maximum size of an access message segment (in octets). */
#define BLE_MESH_APP_SEG_SDU_MAX 12
#define BLE_MESH_TX_SDU_MAX (CONFIG_BLE_MESH_TX_SEG_MAX * 12)
#define BLE_MESH_TX_SDU_MAX MAX(BLE_MESH_MSG_UNSEG_MAX, (CONFIG_BLE_MESH_TX_SEG_MAX * 12))
#define BLE_MESH_RX_SDU_MAX MAX(BLE_MESH_MSG_UNSEG_MAX, (BLE_MESH_APP_SEG_SDU_MAX * 32))
#define TRANS_SEQ_ZERO_MASK ((uint16_t)BIT_MASK(13))
#define TRANS_CTL_OP_MASK ((uint8_t)BIT_MASK(7))
@@ -201,7 +201,16 @@ static int32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx,
*/
seg_rtx_num = bt_mesh_get_seg_rtx_num();
seg_rtx_to = bt_mesh_get_seg_rtx_timeout(ctx->addr, ctx->send_ttl);
seg_count = (msg->len + mic_size - 1) / 12U + 1U;
#if CONFIG_BLE_MESH_LONG_PACKET
if (ctx->enh.long_pkt_cfg &&
msg->len > BLE_MESH_TX_SDU_MAX) {
seg_count = (msg->len + mic_size - 1) / BLE_MESH_EXT_APP_SEG_SDU_MAX + 1U;
} else
#endif
{
seg_count = (msg->len + mic_size - 1) / 12U + 1U;
}
duration = bt_mesh_get_adv_duration(ctx);