feat(ble_mesh): alignment to release/v6.0

This commit is contained in:
luoxu
2026-01-20 15:39:39 +08:00
parent 3e64bdb5eb
commit b640f05f6a
86 changed files with 6226 additions and 2143 deletions
+52 -19
View File
@@ -36,7 +36,6 @@ set(common_include_dirs
set(ble_mesh_include_dirs
"esp_ble_mesh/common/include"
"esp_ble_mesh/common/tinycrypt/include"
"esp_ble_mesh/core"
"esp_ble_mesh/core/include"
"esp_ble_mesh/core/storage"
@@ -49,6 +48,10 @@ set(ble_mesh_include_dirs
"esp_ble_mesh/api"
)
set(ble_mesh_tinycrypt_dirs
"esp_ble_mesh/common/tinycrypt/include"
)
set(ble_mesh_v11_include_dirs
"esp_ble_mesh/lib/include"
"esp_ble_mesh/v1.1/api/core/include"
@@ -540,33 +543,32 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/btc/btc_ble_mesh_prov.c"
"esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c"
"esp_ble_mesh/common/tinycrypt/src/aes_decrypt.c"
"esp_ble_mesh/common/tinycrypt/src/aes_encrypt.c"
"esp_ble_mesh/common/tinycrypt/src/cbc_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ccm_mode.c"
"esp_ble_mesh/common/tinycrypt/src/cmac_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ctr_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ctr_prng.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_dh.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_dsa.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_platform_specific.c"
"esp_ble_mesh/common/tinycrypt/src/ecc.c"
"esp_ble_mesh/common/tinycrypt/src/hmac_prng.c"
"esp_ble_mesh/common/tinycrypt/src/hmac.c"
"esp_ble_mesh/common/tinycrypt/src/sha256.c"
"esp_ble_mesh/common/tinycrypt/src/utils.c"
"esp_ble_mesh/common/atomic.c"
"esp_ble_mesh/common/buf.c"
"esp_ble_mesh/common/common.c"
"esp_ble_mesh/common/kernel.c"
"esp_ble_mesh/common/mutex.c"
"esp_ble_mesh/common/queue.c"
"esp_ble_mesh/common/timer.c"
"esp_ble_mesh/common/utils.c"
"esp_ble_mesh/core/storage/settings_nvs.c"
"esp_ble_mesh/common/utils.c")
# Select crypto implementation based on config
if(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT OR
CONFIG_BT_SMP_CRYPTO_STACK_NATIVE)
list(APPEND srcs "esp_ble_mesh/common/crypto_tc.c")
elseif(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
if(CONFIG_MBEDTLS_VER_4_X_SUPPORT)
list(APPEND srcs "esp_ble_mesh/common/crypto_psa.c")
else()
list(APPEND srcs "esp_ble_mesh/common/crypto_mbedtls.c")
endif()
endif()
list(APPEND srcs "esp_ble_mesh/core/storage/settings_nvs.c"
"esp_ble_mesh/core/storage/settings_uid.c"
"esp_ble_mesh/core/storage/settings.c"
"esp_ble_mesh/core/access.c"
"esp_ble_mesh/core/adv.c"
"esp_ble_mesh/core/adv_common.c"
"esp_ble_mesh/core/beacon.c"
"esp_ble_mesh/core/cfg_cli.c"
"esp_ble_mesh/core/cfg_srv.c"
@@ -603,6 +605,27 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/models/server/state_binding.c"
"esp_ble_mesh/models/server/state_transition.c"
"esp_ble_mesh/models/server/time_scene_server.c")
if(CONFIG_BT_SMP_CRYPTO_STACK_NATIVE)
list(APPEND include_dirs ${ble_mesh_tinycrypt_dirs})
list(APPEND srcs
"esp_ble_mesh/common/tinycrypt/src/aes_decrypt.c"
"esp_ble_mesh/common/tinycrypt/src/aes_encrypt.c"
"esp_ble_mesh/common/tinycrypt/src/cbc_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ccm_mode.c"
"esp_ble_mesh/common/tinycrypt/src/cmac_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ctr_mode.c"
"esp_ble_mesh/common/tinycrypt/src/ctr_prng.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_dh.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_dsa.c"
"esp_ble_mesh/common/tinycrypt/src/ecc_platform_specific.c"
"esp_ble_mesh/common/tinycrypt/src/ecc.c"
"esp_ble_mesh/common/tinycrypt/src/hmac_prng.c"
"esp_ble_mesh/common/tinycrypt/src/hmac.c"
"esp_ble_mesh/common/tinycrypt/src/sha256.c"
"esp_ble_mesh/common/tinycrypt/src/utils.c")
endif()
if(CONFIG_BLE_MESH_V11_SUPPORT)
list(APPEND include_dirs ${ble_mesh_v11_include_dirs})
@@ -650,6 +673,16 @@ if(CONFIG_BT_ENABLED)
else()
list(APPEND srcs "esp_ble_mesh/core/transport.c")
endif()
if(CONFIG_BLE_MESH_SUPPORT_MULTI_ADV)
list(APPEND srcs "esp_ble_mesh/core/ext_adv.c")
else()
list(APPEND srcs "esp_ble_mesh/core/adv.c")
endif()
if(CONFIG_BLE_MESH_SUPPORT_BLE_ADV)
list(APPEND srcs "esp_ble_mesh/core/ble_adv.c")
endif()
endif()
if(CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT)
+1 -1
View File
@@ -265,7 +265,7 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
#endif /* CONFIG_BLE_MESH_DFD_CLI */
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50
[BTC_PID_BLE_MESH_BLE_COEX] = {btc_ble_mesh_ble_call_handler, btc_ble_mesh_ble_cb_handler },
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 */
#endif /* #if CONFIG_BLE_MESH */
#if (BLE_FEAT_ISO_EN == TRUE)
[BTC_PID_ISO_BLE] = {btc_iso_ble_call_handler, btc_iso_ble_cb_handler },
+177 -4
View File
@@ -22,14 +22,170 @@ if BLE_MESH
for mesh packets. And this could help avoid collision of
advertising packets.
config BLE_MESH_USE_UNIFIED_CRYPTO
bool "Use the unified BLE tinycrypt implementation"
depends on !BT_LE_CRYPTO_STACK_MBEDTLS && !BT_NIMBLE_CRYPTO_STACK_MBEDTLS
default y if BT_SMP_CRYPTO_STACK_TINYCRYPT
default n
help
Enable this option to use the unified BLE tinycrypt solution
instead of the default one in BLE Mesh stack.
menuconfig BLE_MESH_USE_BLE_50
bool "Support using BLE 5.0 APIs for BLE Mesh"
depends on BLE_MESH_EXPERIMENTAL
select BT_NIMBLE_50_FEATURE_SUPPORT if BT_NIMBLE_ENABLED
select BT_NIMBLE_EXT_ADV if BT_NIMBLE_ENABLED
select BT_BLE_50_FEATURES_SUPPORTED if BT_BLUEDROID_ENABLED
select BT_LE_50_FEATURE_SUPPORT if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2
default n
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"
default 0
range 0 3
help
Extended ADV instance used by Mesh normal advertising packets.
menuconfig BLE_MESH_SUPPORT_MULTI_ADV
bool "Support using multiple adv instance for BLE Mesh"
depends on BLE_MESH_USE_BLE_50
default n
help
Enable this option to support using multiple adv instance while running BLE Mesh.
config BLE_MESH_PROXY_ADV_INST_ID
int "Extended adv instance for Mesh proxy packets"
depends on BLE_MESH_PROXY
depends on (BLE_MESH_PB_GATT || BLE_MESH_GATT_PROXY_SERVER)
depends on BLE_MESH_SUPPORT_MULTI_ADV
default 1
range 0 3
help
Extended ADV instance used by Mesh proxy advertising packets.
menuconfig BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE
bool "Use separate extended adv instance for Mesh relay packets"
depends on BLE_MESH_SUPPORT_MULTI_ADV
depends on BLE_MESH_RELAY_ADV_BUF
default n
help
Enable this option to support using a separate extended ADV instance for Mesh relay packets.
config BLE_MESH_RELAY_ADV_INST_ID
int "Extended adv instance for Mesh relay packets"
depends on BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE
default 2
range 0 3
help
Extended ADV instance used by Mesh relay advertising packets.
menuconfig BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
bool "Use separate extended adv instance for BLE normal packets"
depends on BLE_MESH_SUPPORT_MULTI_ADV
depends on BLE_MESH_SUPPORT_BLE_ADV
default n
help
Enable this option to support using a separate extended ADV instance for normal BLE advertising packets.
config BLE_MESH_BLE_ADV_INST_ID
int "Extended adv instance for normal BLE packets"
depends on BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
default 3
range 0 3
help
Extended ADV instance used by normal BLE advertising packets.
config BLE_MESH_USE_DUPLICATE_SCAN
bool "Support Duplicate Scan in BLE Mesh"
select BTDM_BLE_SCAN_DUPL if IDF_TARGET_ESP32
select BTDM_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32
select BT_CTRL_BLE_SCAN_DUPL if IDF_TARGET_ESP32C3
select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3
select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6
select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32H2
select BT_CTRL_BLE_SCAN_DUPL if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3
select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3
select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 || IDF_TARGET_ESP32C61 || IDF_TARGET_ESP32C5
select BT_NIMBLE_VS_SUPPORT if BT_NIMBLE_ENABLED
default y
help
@@ -417,6 +573,13 @@ if BLE_MESH
will store the solicitation src and solicitation sequence number of
the received Solicitation PDU message.
config BLE_MESH_PROXY_CLI_SRV_COEXIST
bool "Support Proxy Client and Proxy Server coexistence"
depends on BLE_MESH_EXPERIMENTAL
default n
help
Enable this option to support the coexistence of proxy client and proxy server.
config BLE_MESH_GATT_PROXY_CLIENT
bool "BLE Mesh GATT Proxy Client"
select BLE_MESH_PROXY
@@ -1459,24 +1622,32 @@ if BLE_MESH
config BLE_MESH_GENERIC_SERVER
bool "Generic server models"
# This configuration has been disabled by default since IDF v5.4
# (commit b0367f5f2f6519e9e7594b4d79192a916b275004).
default y
help
Enable support for Generic server models.
config BLE_MESH_SENSOR_SERVER
bool "Sensor server models"
# This configuration has been disabled by default since IDF v5.4
# (commit b0367f5f2f6519e9e7594b4d79192a916b275004).
default y
help
Enable support for Sensor server models.
config BLE_MESH_TIME_SCENE_SERVER
bool "Time and Scenes server models"
# This configuration has been disabled by default since IDF v5.4
# (commit b0367f5f2f6519e9e7594b4d79192a916b275004).
default y
help
Enable support for Time and Scenes server models.
config BLE_MESH_LIGHTING_SERVER
bool "Lighting server models"
# This configuration has been disabled by default since IDF v5.4
# (commit b0367f5f2f6519e9e7594b4d79192a916b275004).
default y
help
Enable support for Lighting server models.
@@ -1898,5 +2069,7 @@ if BLE_MESH
Make BLE Mesh Experimental features visible.
Experimental features list:
- CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG
- CONFIG_BLE_MESH_USE_BLE_50
- CONFIG_BLE_MESH_PROXY_CLI_SRV_COEXIST
endif # BLE_MESH
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,14 +12,14 @@
#include "btc_ble_mesh_ble.h"
#include "esp_ble_mesh_ble_api.h"
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT
#if (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50)
esp_err_t esp_ble_mesh_register_ble_callback(esp_ble_mesh_ble_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_BLE_MESH_BLE_COEX, callback) == 0 ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */
#endif /* (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) */
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param,
@@ -100,3 +100,23 @@ esp_err_t esp_ble_mesh_stop_ble_scanning(void)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
esp_err_t esp_ble_mesh_scan_params_update(esp_ble_mesh_scan_param_t *scan_param)
{
btc_ble_mesh_ble_args_t arg = {0};
btc_msg_t msg = {0};
if (!scan_param) {
return ESP_FAIL;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_BLE_MESH_BLE_COEX;
msg.act = BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS;
arg.scan_params.scan_interval = scan_param->scan_interval;
arg.scan_params.uncoded_scan_window = scan_param->uncoded_scan_window;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_ble_args_t), NULL, NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -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-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,6 +9,10 @@
#include "esp_ble_mesh_defs.h"
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED
#include "host/ble_gap.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -20,9 +24,38 @@ typedef enum {
ESP_BLE_MESH_START_BLE_SCANNING_COMP_EVT, /*!< Start BLE scanning completion event */
ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT, /*!< Stop BLE scanning completion event */
ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT, /*!< Scanning BLE advertising packets event */
ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT, /*!< Scan parameters update completion event */
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED
ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT, /*!< NIMBLE GAP event */
#endif /* CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED */
ESP_BLE_MESH_BLE_EVT_MAX,
} esp_ble_mesh_ble_cb_event_t;
/** Context of BLE advertising report. */
typedef struct {
uint8_t addr[6]; /*!< Device address */
uint8_t addr_type; /*!< Device address type */
#if CONFIG_BLE_MESH_USE_BLE_50
uint8_t adv_type __attribute__((deprecated("`event_type` should be used to determine the advertising type"))); /*!< advertising type */
#else
uint8_t adv_type; /*!< Advertising type */
#endif
uint8_t *data; /*!< Advertising data */
uint16_t length; /*!< Advertising data length */
int8_t rssi; /*!< RSSI of the advertising packet */
#if CONFIG_BLE_MESH_USE_BLE_50
uint8_t event_type; /*!< Extended advertising event type */
uint8_t primary_phy; /*!< Extended advertising primary PHY */
uint8_t secondary_phy; /*!< Extended advertising secondary PHY */
uint8_t sid; /*!< Extended advertising set ID */
uint8_t tx_power; /*!< Extended advertising TX power */
uint8_t dir_addr_type; /*!< Direct address type */
uint8_t dir_addr[6]; /*!< Direct address */
uint8_t data_status; /*!< Data type */
uint16_t per_adv_interval; /*!< Periodic advertising interval */
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
} esp_ble_mesh_ble_adv_rpt_t;
/** BLE operation callback parameters */
typedef union {
/**
@@ -52,16 +85,27 @@ typedef union {
int err_code; /*!< Indicate the result of stopping BLE scanning */
} stop_ble_scan_comp; /*!< Event parameters of ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT */
/**
* @brief ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT
* @brief Event parameters of ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT
*/
struct {
uint8_t addr[6]; /*!< Device address */
uint8_t addr_type; /*!< Device address type */
uint8_t adv_type; /*!< Advertising data type */
uint8_t *data; /*!< Advertising data */
uint16_t length; /*!< Advertising data length */
int8_t rssi; /*!< RSSI of the advertising packet */
} scan_ble_adv_pkt; /*!< Event parameters of ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT */
esp_ble_mesh_ble_adv_rpt_t scan_ble_adv_pkt;
/**
* @brief Event parameter of ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT
*/
struct ble_mesh_scan_params_update_comp_param {
int err_code; /*!< Indicates the result of updating scan parameters */
} scan_params_update_comp; /*!< Event parameter of ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT */
#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED
/**
* @brief Event parameters of ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT
* @note The execution environment of this event is different
* from other BLE Mesh events, as it runs in the NimBLE Host's
* execution environment.
*/
struct ble_mesh_nimble_gap_event_evt_param {
struct ble_gap_event event; /*!< GAP event parameters for NimBLE Host */
void *arg; /*!< User parameters */
} nimble_gap_evt; /*!< Event parameters of ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT */
#endif /* CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED */
} esp_ble_mesh_ble_cb_param_t;
/**
@@ -175,6 +219,33 @@ esp_err_t esp_ble_mesh_start_ble_scanning(esp_ble_mesh_ble_scan_param_t *param);
*/
esp_err_t esp_ble_mesh_stop_ble_scanning(void);
/**
* @brief Update BLE Mesh scan parameters.
*
* @note
* 1. This function shall be used after ESP BLE Mesh is initialized!
* Parameters `scan_interval` and `uncoded_scan_window` must both
* be multiples of 8.
*
* 2. If the config BLE_MESH_USE_BLE_50 is enabled, within the scan_interval:
* - If uncoded_scan_window is not zero, the scan_interval is divided into
* two parts:
* - uncoded_scan_window: Used for performing uncoded scanning.
* - (scan_interval - uncoded_scan_window): The remaining time is
* used for coded scanning (coded_scan).
* - If uncoded_scan_window is set to 0, it means the entire scan_interval
* is used for coded scanning.
* - If uncoded_scan_window is equal to scan_interval, it means the entire
* scan_interval is used for uncoded scanning.
*
* @param[in] scan_param: Scan parameters
*
* @return
* - ESP_OK: Success
* - ESP_FAIL: Invalid parameters or unable transfer this command to the stack
*/
esp_err_t esp_ble_mesh_scan_params_update(esp_ble_mesh_scan_param_t *scan_param);
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -67,9 +67,9 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers);
* So as an unprovisioned device, it should use this function to input
* the Public Key exchanged through the out-of-band mechanism.
*
* @param[in] pub_key_x: Unprovisioned device's Public Key X
* @param[in] pub_key_y: Unprovisioned device's Public Key Y
* @param[in] private_key: Unprovisioned device's Private Key
* @param[in] pub_key_x: Unprovisioned device's Public Key X(Little Endian)
* @param[in] pub_key_y: Unprovisioned device's Public Key Y(Little Endian)
* @param[in] private_key: Unprovisioned device's Private Key(Little Endian)
*
* @return ESP_OK on success or error code otherwise.
*/
@@ -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
@@ -415,6 +421,29 @@ typedef struct {
bool erase_flash; /*!< Indicate if erasing flash when deinit mesh stack */
} esp_ble_mesh_deinit_param_t;
/** Scan parameters */
typedef struct {
/**
* Scan interval.
*
* Range: 0x0004 to 0x4000.
*
* Time = N * 0.625 ms. Time Range: 2.5 ms to 10.24 s
*/
uint16_t scan_interval;
/**
* Uncoded Scan window.
*
* Time scanned on uncoded PHY within a scan interval.
*
* Range: 0x0004 to 0x4000.
*
* Time = N * 0.625 ms. Time Range: 2.5 ms to 10.24 s
*/
uint16_t uncoded_scan_window;
} esp_ble_mesh_scan_param_t;
/** Format of Unicast Address Range */
typedef struct {
uint16_t len_present:1, /*!< Indicate the presence or absence of the RangeLength field */
@@ -590,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
*/
@@ -641,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.
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,8 +13,9 @@
#include "mesh/adapter.h"
#include "esp_ble_mesh_ble_api.h"
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT
#if (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50)
static inline void btc_ble_mesh_ble_cb_to_app(esp_ble_mesh_ble_cb_event_t event,
esp_ble_mesh_ble_cb_param_t *param);
static void btc_ble_mesh_ble_copy_req_data(btc_msg_t *msg, void *p_dst, void *p_src)
{
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
@@ -29,6 +30,7 @@ static void btc_ble_mesh_ble_copy_req_data(btc_msg_t *msg, void *p_dst, void *p_
switch (msg->act) {
case ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT:
if (p_src_data->scan_ble_adv_pkt.data && p_src_data->scan_ble_adv_pkt.length) {
memcpy(&p_dst_data->scan_ble_adv_pkt, &p_src_data->scan_ble_adv_pkt, sizeof(p_src_data->scan_ble_adv_pkt));
p_dst_data->scan_ble_adv_pkt.length = p_src_data->scan_ble_adv_pkt.length;
p_dst_data->scan_ble_adv_pkt.data = bt_mesh_calloc(p_src_data->scan_ble_adv_pkt.length);
if (p_dst_data->scan_ble_adv_pkt.data) {
@@ -86,26 +88,34 @@ static void btc_ble_mesh_ble_callback(esp_ble_mesh_ble_cb_param_t *cb_params, ui
btc_ble_mesh_ble_copy_req_data, btc_ble_mesh_ble_free_req_data);
}
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
void bt_mesh_ble_scan_cb_evt_to_btc(const bt_mesh_addr_t *addr,
uint8_t adv_type, uint8_t data[],
uint16_t length, int8_t rssi)
#if CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50
void bt_mesh_ble_nimble_evt_to_btc(struct ble_gap_event *event, void *arg)
{
esp_ble_mesh_ble_cb_param_t param = {0};
if (addr == NULL) {
if (event == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
memcpy(param.scan_ble_adv_pkt.addr, addr->val, sizeof(addr->val));
param.scan_ble_adv_pkt.addr_type = addr->type;
if (data && length) {
param.scan_ble_adv_pkt.data = data;
param.scan_ble_adv_pkt.length = length;
memcpy(&param.nimble_gap_evt.event, event, sizeof(struct ble_gap_event));
param.nimble_gap_evt.arg = arg;
btc_ble_mesh_ble_cb_to_app(ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT, &param);
}
#endif /* CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 */
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
void bt_mesh_ble_scan_cb_evt_to_btc(bt_mesh_ble_adv_report_t *adv_report)
{
esp_ble_mesh_ble_cb_param_t param = {0};
if (adv_report == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
param.scan_ble_adv_pkt.adv_type = adv_type;
param.scan_ble_adv_pkt.rssi = rssi;
memcpy(&param.scan_ble_adv_pkt, adv_report, sizeof(bt_mesh_ble_adv_report_t));
btc_ble_mesh_ble_callback(&param, ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT);
}
@@ -157,6 +167,14 @@ void btc_ble_mesh_ble_call_handler(btc_msg_t *msg)
btc_ble_mesh_ble_callback(&param, ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT);
break;
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
case BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS:
struct bt_mesh_scan_param scan_param = {
.interval = arg->scan_params.scan_interval,
.window = arg->scan_params.uncoded_scan_window,
};
param.scan_params_update_comp.err_code = bt_mesh_scan_param_update(&scan_param);
btc_ble_mesh_ble_callback(&param, ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT);
break;
default:
return;
}
@@ -191,5 +209,4 @@ void btc_ble_mesh_ble_cb_handler(btc_msg_t *msg)
btc_ble_mesh_ble_free_req_data(msg);
}
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */
#endif /* (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) */
@@ -30,6 +30,7 @@
#endif /* CONFIG_BLE_MESH_V11_SUPPORT */
#include "adv.h"
#include "scan.h"
#include "mesh/kernel.h"
#include "mesh/proxy.h"
#include "mesh.h"
@@ -3028,6 +3029,9 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg)
.ctx.send_tag = arg->model_send.ctx->send_tag,
.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);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -16,6 +16,30 @@
extern "C" {
#endif
typedef struct {
uint8_t addr[6]; /*!< Device address */
uint8_t addr_type; /*!< Device address type */
#if CONFIG_BLE_MESH_USE_BLE_50
uint8_t adv_type __attribute__((deprecated("`event_type` should be used to determine the advertising type"))); /*!< advertising type */
#else
uint8_t adv_type; /*!< Advertising type */
#endif
uint8_t *data; /*!< Advertising data */
uint16_t length; /*!< Advertising data length */
int8_t rssi; /*!< RSSI of the advertising packet */
#if CONFIG_BLE_MESH_USE_BLE_50
uint8_t event_type; /*!< Extended advertising event type */
uint8_t primary_phy; /*!< Extended advertising primary PHY */
uint8_t secondary_phy; /*!< Extended advertising secondary PHY */
uint8_t sid; /*!< Extended advertising set ID */
uint8_t tx_power; /*!< Extended advertising TX power */
uint8_t dir_addr_type; /*!< Direct address type */
uint8_t dir_addr[6]; /*!< Direct address */
uint8_t data_status; /*!< Data type */
uint16_t per_adv_interval; /*!< Periodic advertising interval */
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
} bt_mesh_ble_adv_report_t;
typedef union {
struct {
esp_ble_mesh_ble_adv_param_t param;
@@ -30,6 +54,10 @@ typedef union {
struct {
/* RFU */
} stop_ble_scan;
struct ble_mesh_scan_params {
uint16_t scan_interval;
uint16_t uncoded_scan_window;
} scan_params;
} btc_ble_mesh_ble_args_t;
typedef enum {
@@ -37,11 +65,14 @@ typedef enum {
BTC_BLE_MESH_ACT_STOP_BLE_ADV,
BTC_BLE_MESH_ACT_START_BLE_SCAN,
BTC_BLE_MESH_ACT_STOP_BLE_SCAN,
BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS,
} btc_ble_mesh_ble_act_t;
void bt_mesh_ble_scan_cb_evt_to_btc(const bt_mesh_addr_t *addr,
uint8_t adv_type, uint8_t data[],
uint16_t length, int8_t rssi);
void bt_mesh_ble_scan_cb_evt_to_btc(bt_mesh_ble_adv_report_t *adv_report);
#if CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50
void bt_mesh_ble_nimble_evt_to_btc(struct ble_gap_event *event, void *arg);
#endif /* CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 */
void btc_ble_mesh_ble_call_handler(btc_msg_t *msg);
@@ -33,6 +33,27 @@ static inline void btc_ble_mesh_msg_ctx_copy(struct bt_mesh_msg_ctx *dst,
dst->send_ttl = src->send_ttl;
dst->send_cred = src->send_cred;
dst->send_tag = src->send_tag;
if (src->enh.adv_cfg_used) {
dst->enh.adv_cfg_used = src->enh.adv_cfg_used;
dst->enh.adv_cfg.adv_cnt = src->enh.adv_cfg.adv_cnt;
dst->enh.adv_cfg.adv_itvl = src->enh.adv_cfg.adv_itvl;
dst->enh.adv_cfg.channel_map = src->enh.adv_cfg.channel_map;
}
#if CONFIG_BLE_MESH_EXT_ADV
if (src->enh.ext_adv_cfg_used) {
dst->enh.ext_adv_cfg_used = src->enh.ext_adv_cfg_used;
dst->enh.ext_adv_cfg.primary_phy = src->enh.ext_adv_cfg.primary_phy;
dst->enh.ext_adv_cfg.secondary_phy = src->enh.ext_adv_cfg.secondary_phy;
dst->enh.ext_adv_cfg.include_tx_power = src->enh.ext_adv_cfg.include_tx_power;
dst->enh.ext_adv_cfg.tx_power = src->enh.ext_adv_cfg.tx_power;
}
#if CONFIG_BLE_MESH_LONG_PACKET
if (src->enh.long_pkt_cfg_used) {
dst->enh.long_pkt_cfg_used = src->enh.long_pkt_cfg_used;
dst->enh.long_pkt_cfg = src->enh.long_pkt_cfg;
}
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
#endif /* CONFIG_BLE_MESH_EXT_ADV */
}
static inline void btc_ble_mesh_set_client_common_param(esp_ble_mesh_client_common_param_t *input,
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -0,0 +1,543 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "esp_random.h"
#include "mbedtls/aes.h"
#include "mbedtls/cmac.h"
#include "mbedtls/md.h"
#include "mbedtls/ecp.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/ccm.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mesh/common.h"
#include "mesh/crypto.h"
#include "mesh/trace.h"
#include "mesh/config.h"
/* ECC key storage
*
* MbedTLS functions expect BIG-ENDIAN format.
*/
static struct {
bool is_ready;
uint8_t private_key[PRIV_KEY_SIZE]; /* Big-endian */
uint8_t public_key[PUB_KEY_SIZE]; /* Big-endian */
} dh_pair;
int bt_mesh_crypto_init(void)
{
memset(&dh_pair, 0, sizeof(dh_pair));
dh_pair.is_ready = false;
return 0;
}
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16])
{
mbedtls_aes_context ctx;
int ret;
mbedtls_aes_init(&ctx);
ret = mbedtls_aes_setkey_enc(&ctx, key->key, 128);
if (ret != 0) {
mbedtls_aes_free(&ctx);
return -EIO;
}
ret = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, plaintext, enc_data);
mbedtls_aes_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
mbedtls_ccm_context ctx;
int ret;
mbedtls_ccm_init(&ctx);
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key->key, 128);
if (ret != 0) {
mbedtls_ccm_free(&ctx);
return -EIO;
}
ret = mbedtls_ccm_encrypt_and_tag(&ctx, len, nonce, 13, aad, aad_len,
plaintext, enc_data, enc_data + len, mic_size);
mbedtls_ccm_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
mbedtls_ccm_context ctx;
int ret;
mbedtls_ccm_init(&ctx);
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key->key, 128);
if (ret != 0) {
mbedtls_ccm_free(&ctx);
return -EIO;
}
ret = mbedtls_ccm_auth_decrypt(&ctx, len, nonce, 13, aad, aad_len,
enc_data, plaintext, enc_data + len, mic_size);
mbedtls_ccm_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct bt_mesh_key mesh_key;
memcpy(mesh_key.key, key, 16);
return bt_mesh_ccm_encrypt(&mesh_key, nonce, plaintext, len, aad, aad_len,
enc_data, mic_size);
}
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct bt_mesh_key mesh_key;
memcpy(mesh_key.key, key, 16);
return bt_mesh_ccm_decrypt(&mesh_key, nonce, enc_data, len, aad, aad_len,
plaintext, mic_size);
}
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16])
{
return bt_mesh_aes_cmac_raw_key(key->key, sg, sg_len, mac);
}
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
mbedtls_cipher_context_t ctx;
const mbedtls_cipher_info_t *info;
int ret;
info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
if (info == NULL) {
return -EIO;
}
mbedtls_cipher_init(&ctx);
ret = mbedtls_cipher_setup(&ctx, info);
if (ret != 0) {
mbedtls_cipher_free(&ctx);
return -EIO;
}
ret = mbedtls_cipher_cmac_starts(&ctx, key, 128);
if (ret != 0) {
mbedtls_cipher_free(&ctx);
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
ret = mbedtls_cipher_cmac_update(&ctx, sg->data, sg->len);
if (ret != 0) {
mbedtls_cipher_free(&ctx);
return -EIO;
}
}
ret = mbedtls_cipher_cmac_finish(&ctx, mac);
mbedtls_cipher_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32])
{
mbedtls_md_context_t ctx;
const mbedtls_md_info_t *info;
int ret;
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
if (info == NULL) {
return -EIO;
}
mbedtls_md_init(&ctx);
ret = mbedtls_md_setup(&ctx, info, 1); /* 1 = HMAC mode */
if (ret != 0) {
mbedtls_md_free(&ctx);
return -EIO;
}
ret = mbedtls_md_hmac_starts(&ctx, key, 32);
if (ret != 0) {
mbedtls_md_free(&ctx);
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
ret = mbedtls_md_hmac_update(&ctx, sg->data, sg->len);
if (ret != 0) {
mbedtls_md_free(&ctx);
return -EIO;
}
}
ret = mbedtls_md_hmac_finish(&ctx, mac);
mbedtls_md_free(&ctx);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_pub_key_gen(void)
{
mbedtls_ecp_group grp;
mbedtls_mpi d;
mbedtls_ecp_point Q;
uint8_t private_key_be[PRIV_KEY_SIZE];
uint8_t public_key_be[PUB_KEY_SIZE];
int ret;
int err;
dh_pair.is_ready = false;
do {
err = bt_mesh_rand(dh_pair.private_key, sizeof(dh_pair.private_key));
if (err) {
BT_ERR("Failed to generate random private key");
return err;
}
/* Ensure the private key is valid (non-zero last bytes in LE) */
} while (dh_pair.private_key[0] == 0 &&
dh_pair.private_key[1] == 0);
mbedtls_ecp_group_init(&grp);
mbedtls_mpi_init(&d);
mbedtls_ecp_point_init(&Q);
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
goto cleanup;
}
/* Read private key into MPI (MbedTLS expects big-endian) */
ret = mbedtls_mpi_read_binary(&d, dh_pair.private_key, PRIV_KEY_SIZE);
if (ret != 0) {
goto cleanup;
}
/* Compute public key: Q = d * G */
ret = mbedtls_ecp_mul(&grp, &Q, &d, &grp.G, NULL, NULL);
if (ret != 0) {
goto cleanup;
}
/* Export public key point in big-endian */
ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(X), dh_pair.public_key, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(Y), dh_pair.public_key + 32, 32);
if (ret != 0) {
goto cleanup;
}
dh_pair.is_ready = true;
cleanup:
mbedtls_ecp_group_free(&grp);
mbedtls_mpi_free(&d);
mbedtls_ecp_point_free(&Q);
return ret == 0 ? 0 : -EIO;
}
const uint8_t *bt_mesh_pub_key_get_raw(void)
{
if (!dh_pair.is_ready) {
if (bt_mesh_pub_key_gen() != 0) {
return NULL;
}
}
return dh_pair.public_key;
}
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
{
mbedtls_ecp_group grp;
mbedtls_mpi d;
mbedtls_ecp_point Q;
int ret;
dh_pair.is_ready = false;
memcpy(dh_pair.private_key, pri_key, PRIV_KEY_SIZE);
/* Compute public key from private key */
mbedtls_ecp_group_init(&grp);
mbedtls_mpi_init(&d);
mbedtls_ecp_point_init(&Q);
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&d, pri_key, PRIV_KEY_SIZE);
if (ret != 0) {
goto cleanup;
}
/* Compute public key: Q = d * G (no RNG needed for deterministic computation) */
ret = mbedtls_ecp_mul(&grp, &Q, &d, &grp.G, NULL, NULL);
if (ret != 0) {
goto cleanup;
}
/* Export public key point in big-endian */
ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(X), dh_pair.public_key, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_write_binary(&Q.MBEDTLS_PRIVATE(Y), dh_pair.public_key + 32, 32);
if (ret != 0) {
goto cleanup;
}
BT_DBG("Pubkey:%s", bt_hex(dh_pair.public_key, PUB_KEY_SIZE));
BT_DBG("Privkey:%s", bt_hex(dh_pair.private_key, PRIV_KEY_SIZE));
dh_pair.is_ready = true;
cleanup:
mbedtls_ecp_group_free(&grp);
mbedtls_mpi_free(&d);
mbedtls_ecp_point_free(&Q);
}
bool bt_mesh_check_public_key_raw(const uint8_t key[64])
{
mbedtls_ecp_group grp;
mbedtls_ecp_point Q;
uint8_t pub_key_be[PUB_KEY_SIZE];
int ret;
mbedtls_ecp_group_init(&grp);
mbedtls_ecp_point_init(&Q);
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&Q.MBEDTLS_PRIVATE(X), dh_pair.public_key, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&Q.MBEDTLS_PRIVATE(Y), dh_pair.public_key + 32, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_lset(&Q.MBEDTLS_PRIVATE(Z), 1);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_ecp_check_pubkey(&grp, &Q);
cleanup:
mbedtls_ecp_group_free(&grp);
mbedtls_ecp_point_free(&Q);
return ret == 0;
}
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
mbedtls_ecp_group grp;
mbedtls_mpi d;
mbedtls_ecp_point Q;
mbedtls_ecp_point result;
int ret;
mbedtls_ecp_group_init(&grp);
mbedtls_mpi_init(&d);
mbedtls_ecp_point_init(&Q);
mbedtls_ecp_point_init(&result);
ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&d, priv_key ? priv_key : dh_pair.private_key, PRIV_KEY_SIZE);
if (ret != 0) {
goto cleanup;
}
/* Load public key point */
ret = mbedtls_mpi_read_binary(&Q.MBEDTLS_PRIVATE(X), dh_pair.public_key, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_read_binary(&Q.MBEDTLS_PRIVATE(Y), dh_pair.public_key + 32, 32);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_mpi_lset(&Q.MBEDTLS_PRIVATE(Z), 1);
if (ret != 0) {
goto cleanup;
}
/* Check the peer's public key */
ret = mbedtls_ecp_check_pubkey(&grp, &Q);
if (ret != 0) {
goto cleanup;
}
/* Calculate shared secret: result = d * Q (no RNG needed for deterministic computation) */
ret = mbedtls_ecp_mul(&grp, &result, &d, &Q, NULL, NULL);
if (ret != 0) {
goto cleanup;
}
/* Export X coordinate as DH key (big-endian) */
ret = mbedtls_mpi_write_binary(&result.MBEDTLS_PRIVATE(X), dhkey, DH_KEY_SIZE);
cleanup:
mbedtls_ecp_group_free(&grp);
mbedtls_mpi_free(&d);
mbedtls_ecp_point_free(&Q);
mbedtls_ecp_point_free(&result);
return ret == 0 ? 0 : -EIO;
}
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out)
{
(void)type; /* Not used for non-PSA implementation */
memcpy(out->key, in, 16);
return 0;
}
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in)
{
memcpy(out, in->key, 16);
return 0;
}
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src)
{
memcpy(dst, src, sizeof(struct bt_mesh_key));
}
int bt_mesh_key_destroy(const struct bt_mesh_key *key)
{
(void)key; /* No cleanup needed for non-PSA implementation */
return 0;
}
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key)
{
return memcmp(raw_key, key->key, 16);
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
mbedtls_aes_context ctx;
uint8_t tmp[16];
int ret;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
mbedtls_aes_init(&ctx);
/* Swap key bytes (LE to BE) */
sys_memcpy_swap(tmp, key, 16);
ret = mbedtls_aes_setkey_enc(&ctx, tmp, 128);
if (ret != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
/* Swap plaintext bytes and encrypt */
sys_memcpy_swap(tmp, plaintext, 16);
ret = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, tmp, enc_data);
mbedtls_aes_free(&ctx);
if (ret != 0) {
return -EINVAL;
}
/* Swap result bytes (BE to LE) */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
mbedtls_aes_context ctx;
int ret;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
mbedtls_aes_init(&ctx);
ret = mbedtls_aes_setkey_enc(&ctx, key, 128);
if (ret != 0) {
mbedtls_aes_free(&ctx);
return -EINVAL;
}
ret = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, plaintext, enc_data);
mbedtls_aes_free(&ctx);
if (ret != 0) {
return -EINVAL;
}
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
@@ -0,0 +1,713 @@
/*
* SPDX-FileCopyrightText: 2023 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "esp_random.h"
#include "psa/crypto.h"
#include "mesh/common.h"
#include "mesh/crypto.h"
#include "mesh/trace.h"
#include "mesh/config.h"
/* PSA Key ID range for BLE Mesh */
#define BT_MESH_PSA_KEY_ID_MIN 0x0001A000
#define BT_MESH_PSA_KEY_ID_RANGE_SIZE \
(2 * CONFIG_BLE_MESH_SUBNET_COUNT + 2 * CONFIG_BLE_MESH_APP_KEY_COUNT + 2)
/* Internal DH key pair storage
*
* PSA functions expect BIG-ENDIAN format.
*/
static struct {
bool is_ready;
psa_key_id_t priv_key_id;
uint8_t public_key[PUB_KEY_SIZE + 1]; /* Big-endian, PSA format: 0x04 + X + Y */
} dh_pair;
/* Bitmap for tracking allocated key IDs */
static uint32_t pst_keys[(BT_MESH_PSA_KEY_ID_RANGE_SIZE + 31) / 32];
static psa_key_id_t keyid_alloc(void)
{
for (int i = 0; i < BT_MESH_PSA_KEY_ID_RANGE_SIZE; i++) {
int word = i / 32;
int bit = i % 32;
if (!(pst_keys[word] & (1U << bit))) {
pst_keys[word] |= (1U << bit);
return BT_MESH_PSA_KEY_ID_MIN + i;
}
}
return PSA_KEY_ID_NULL;
}
static int keyid_free(psa_key_id_t key_id)
{
if (key_id >= BT_MESH_PSA_KEY_ID_MIN &&
key_id < BT_MESH_PSA_KEY_ID_MIN + BT_MESH_PSA_KEY_ID_RANGE_SIZE) {
int idx = key_id - BT_MESH_PSA_KEY_ID_MIN;
int word = idx / 32;
int bit = idx % 32;
pst_keys[word] &= ~(1U << bit);
return 0;
}
return -EIO;
}
static void keyid_assign(psa_key_id_t key_id)
{
if (key_id >= BT_MESH_PSA_KEY_ID_MIN &&
key_id < BT_MESH_PSA_KEY_ID_MIN + BT_MESH_PSA_KEY_ID_RANGE_SIZE) {
int idx = key_id - BT_MESH_PSA_KEY_ID_MIN;
int word = idx / 32;
int bit = idx % 32;
pst_keys[word] |= (1U << bit);
}
}
int bt_mesh_crypto_init(void)
{
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
BT_ERR("PSA crypto init failed: %d", status);
return -EIO;
}
dh_pair.is_ready = false;
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
memset(pst_keys, 0, sizeof(pst_keys));
return 0;
}
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16])
{
size_t output_len;
psa_status_t status;
status = psa_cipher_encrypt(key->key, PSA_ALG_ECB_NO_PADDING,
plaintext, 16, enc_data, 16, &output_len);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA cipher encrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
size_t output_len;
psa_status_t status;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, mic_size);
status = psa_aead_encrypt(key->key, alg, nonce, 13, aad, aad_len,
plaintext, len, enc_data, len + mic_size, &output_len);
if (status != PSA_SUCCESS || output_len != len + mic_size) {
BT_ERR("PSA AEAD encrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
size_t output_len;
psa_status_t status;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, mic_size);
status = psa_aead_decrypt(key->key, alg, nonce, 13, aad, aad_len,
enc_data, len + mic_size, plaintext, len, &output_len);
if (status != PSA_SUCCESS || output_len != len) {
BT_ERR("PSA AEAD decrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct bt_mesh_key mesh_key;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CCM, key, &mesh_key);
if (err) {
return err;
}
err = bt_mesh_ccm_encrypt(&mesh_key, nonce, plaintext, len, aad, aad_len,
enc_data, mic_size);
psa_destroy_key(mesh_key.key);
return err;
}
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct bt_mesh_key mesh_key;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CCM, key, &mesh_key);
if (err) {
return err;
}
err = bt_mesh_ccm_decrypt(&mesh_key, nonce, enc_data, len, aad, aad_len,
plaintext, mic_size);
psa_destroy_key(mesh_key.key);
return err;
}
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16])
{
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_status_t status;
size_t mac_len;
status = psa_mac_sign_setup(&operation, key->key, PSA_ALG_CMAC);
if (status != PSA_SUCCESS) {
BT_ERR("PSA MAC setup failed: %d", status);
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
status = psa_mac_update(&operation, sg->data, sg->len);
if (status != PSA_SUCCESS) {
psa_mac_abort(&operation);
BT_ERR("PSA MAC update failed: %d", status);
return -EIO;
}
}
status = psa_mac_sign_finish(&operation, mac, 16, &mac_len);
if (status != PSA_SUCCESS || mac_len != 16) {
BT_ERR("PSA MAC finish failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
struct bt_mesh_key key_id;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CMAC, key, &key_id);
if (err) {
return err;
}
err = bt_mesh_aes_cmac_mesh_key(&key_id, sg, sg_len, mac);
psa_destroy_key(key_id.key);
return err;
}
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32])
{
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
size_t mac_len;
int err = 0;
/* Import HMAC key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, key, 32, &key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import HMAC key failed: %d", status);
return -EIO;
}
psa_reset_key_attributes(&attributes);
status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
if (status != PSA_SUCCESS) {
BT_ERR("PSA HMAC setup failed: %d", status);
err = -EIO;
goto end;
}
for (; sg_len; sg_len--, sg++) {
status = psa_mac_update(&operation, sg->data, sg->len);
if (status != PSA_SUCCESS) {
psa_mac_abort(&operation);
BT_ERR("PSA HMAC update failed: %d", status);
err = -EIO;
goto end;
}
}
status = psa_mac_sign_finish(&operation, mac, 32, &mac_len);
if (status != PSA_SUCCESS || mac_len != 32) {
BT_ERR("PSA HMAC finish failed: %d", status);
err = -EIO;
}
end:
psa_destroy_key(key_id);
return err;
}
int bt_mesh_pub_key_gen(void)
{
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
uint8_t private_key[PRIV_KEY_SIZE];
size_t key_len;
int err;
/* Destroy any existing key */
if (dh_pair.priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
}
dh_pair.is_ready = false;
/* Generate a random private key (in little-endian format for storage) */
do {
err = bt_mesh_rand(private_key, sizeof(private_key));
if (err) {
BT_ERR("Failed to generate random private key");
return err;
}
/* Ensure the private key is valid (non-zero first bytes in BE) */
} while (private_key[0] == 0 && private_key[1] == 0);
/* Configure key attributes for ECDH with P-256 */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attributes, 256);
/* Import the private key */
status = psa_import_key(&key_attributes, private_key, sizeof(private_key),
&dh_pair.priv_key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
psa_reset_key_attributes(&key_attributes);
return -EIO;
}
/* Export public key (PSA computes it from the private key) */
status = psa_export_public_key(dh_pair.priv_key_id, dh_pair.public_key,
sizeof(dh_pair.public_key), &key_len);
if (status != PSA_SUCCESS || key_len != PUB_KEY_SIZE + 1) {
BT_ERR("PSA export public key failed: %d", status);
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
psa_reset_key_attributes(&key_attributes);
return -EIO;
}
dh_pair.is_ready = true;
psa_reset_key_attributes(&key_attributes);
return 0;
}
const uint8_t *bt_mesh_pub_key_get_raw(void)
{
if (!dh_pair.is_ready) {
if (bt_mesh_pub_key_gen() != 0) {
return NULL;
}
}
return &dh_pair.public_key[1];
}
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
size_t key_len;
/* Destroy any existing key */
if (dh_pair.priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
}
dh_pair.is_ready = false;
/* Import the provided private key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, pri_key, PRIV_KEY_SIZE, &dh_pair.priv_key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
psa_reset_key_attributes(&attributes);
return;
}
/* Export public key (PSA computes it from the private key) */
status = psa_export_public_key(dh_pair.priv_key_id, dh_pair.public_key,
sizeof(dh_pair.public_key), &key_len);
if (status != PSA_SUCCESS || key_len != PUB_KEY_SIZE + 1) {
BT_ERR("PSA export public key failed: %d", status);
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
psa_reset_key_attributes(&attributes);
return;
}
BT_DBG("Pubkey:%s", bt_hex(&dh_pair.public_key[1], PUB_KEY_SIZE));
BT_DBG("Privkey:%s", bt_hex(pri_key, PRIV_KEY_SIZE));
dh_pair.is_ready = true;
psa_reset_key_attributes(&attributes);
}
bool bt_mesh_check_public_key_raw(const uint8_t key[64])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
uint8_t pub_be[PUB_KEY_SIZE + 1];
/* PSA requires 0x04 prefix for uncompressed point */
pub_be[0] = 0x04;
/* Convert from little-endian to big-endian */
memcpy(&pub_be[1], key, 32);
memcpy(&pub_be[33], key + 32, 32);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, pub_be, sizeof(pub_be), &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
return false;
}
psa_destroy_key(key_id);
return true;
}
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
psa_key_id_t priv_key_id = PSA_KEY_ID_NULL;
uint8_t public_key_be[PUB_KEY_SIZE + 1];
psa_status_t status;
size_t dh_key_len;
int err = 0;
if (priv_key) {
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
/* Import custom private key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, priv_key, PRIV_KEY_SIZE, &priv_key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
return -EIO;
}
} else {
priv_key_id = dh_pair.priv_key_id;
}
/* Prepare public key with 0x04 prefix in big-endian format */
public_key_be[0] = 0x04;
/* Convert from little-endian to big-endian */
memcpy(public_key_be + 1, pub_key, 32);
memcpy(public_key_be + 33, pub_key + 32, 32);
/* Calculate shared secret */
status = psa_raw_key_agreement(PSA_ALG_ECDH, priv_key_id, public_key_be,
PUB_KEY_SIZE + 1, dhkey, DH_KEY_SIZE, &dh_key_len);
if (status != PSA_SUCCESS || dh_key_len != DH_KEY_SIZE) {
BT_ERR("PSA ECDH failed: %d", status);
err = -EIO;
}
if (priv_key && priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(priv_key_id);
}
return err;
}
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out)
{
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
psa_key_id_t key_id = PSA_KEY_ID_NULL;
switch (type) {
case BT_MESH_KEY_TYPE_ECB:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECB_NO_PADDING);
break;
case BT_MESH_KEY_TYPE_CCM:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes,
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4));
break;
case BT_MESH_KEY_TYPE_CMAC:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_CMAC);
break;
case BT_MESH_KEY_TYPE_NET:
#if CONFIG_BT_SETTINGS
key_id = keyid_alloc();
if (key_id == PSA_KEY_ID_NULL) {
return -ENOMEM;
}
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&key_attributes, key_id);
#else
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
#endif
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_EXPORT);
break;
case BT_MESH_KEY_TYPE_APP:
case BT_MESH_KEY_TYPE_DEV:
#if CONFIG_BT_SETTINGS
key_id = keyid_alloc();
if (key_id == PSA_KEY_ID_NULL) {
return -ENOMEM;
}
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&key_attributes, key_id);
#else
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
#endif
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&key_attributes,
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4));
break;
default:
return -EINVAL;
}
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&key_attributes, 128);
status = psa_import_key(&key_attributes, in, 16, &out->key);
if (status == PSA_ERROR_ALREADY_EXISTS) {
BT_WARN("Key 0x%04x already exists, destroying and reimporting", key_id);
psa_destroy_key(key_id);
status = psa_import_key(&key_attributes, in, 16, &out->key);
}
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
if (key_id != PSA_KEY_ID_NULL) {
keyid_free(key_id);
}
return -EIO;
}
return 0;
}
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in)
{
size_t data_length;
psa_status_t status;
status = psa_export_key(in->key, out, 16, &data_length);
if (status != PSA_SUCCESS || data_length != 16) {
BT_ERR("PSA export key failed: %d", status);
return -EIO;
}
return 0;
}
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src)
{
memcpy(dst, src, sizeof(struct bt_mesh_key));
#if CONFIG_BT_SETTINGS
keyid_assign(dst->key);
#endif
}
int bt_mesh_key_destroy(const struct bt_mesh_key *key)
{
psa_status_t status;
status = psa_destroy_key(key->key);
if (status != PSA_SUCCESS) {
BT_ERR("PSA destroy key failed: %d", status);
return -EIO;
}
#if CONFIG_BT_SETTINGS
return keyid_free(key->key);
#else
return 0;
#endif
}
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key)
{
uint8_t out[16];
int err;
err = bt_mesh_key_export(out, key);
if (err) {
return err;
}
return memcmp(out, raw_key, 16);
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
uint8_t tmp[16];
size_t output_len;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
/* Swap key bytes (LE to BE) */
sys_memcpy_swap(tmp, key, 16);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
status = psa_import_key(&attributes, tmp, 16, &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
return -EINVAL;
}
/* Swap plaintext bytes and encrypt */
sys_memcpy_swap(tmp, plaintext, 16);
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
tmp, 16, enc_data, 16, &output_len);
psa_destroy_key(key_id);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA encrypt failed: %d", status);
return -EINVAL;
}
/* Swap result bytes (BE to LE) */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
size_t output_len;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
status = psa_import_key(&attributes, key, 16, &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
return -EINVAL;
}
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
plaintext, 16, enc_data, 16, &output_len);
psa_destroy_key(key_id);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA encrypt failed: %d", status);
return -EINVAL;
}
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
#if 0
int bt_mesh_rand(void *buf, size_t len)
{
psa_status_t status;
if (buf == NULL || len == 0) {
return -EINVAL;
}
status = psa_generate_random(buf, len);
return status == PSA_SUCCESS ? 0 : -EIO;
}
#endif
@@ -0,0 +1,342 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileCopyrightText: 2023 Nordic Semiconductor ASA
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "esp_random.h"
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/cmac_mode.h>
#include <tinycrypt/ccm_mode.h>
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_dh.h>
#include <tinycrypt/hmac.h>
#include "mesh/common.h"
#include "mesh/crypto.h"
#include "mesh/trace.h"
/* Internal DH key pair storage
*
* TinyCrypt's uECC functions expect BIG-ENDIAN format.
*/
static struct {
bool is_ready;
uint8_t private_key[PRIV_KEY_SIZE]; /* Big-endian */
uint8_t public_key[PUB_KEY_SIZE]; /* Big-endian */
} dh_pair;
int bt_mesh_crypto_init(void)
{
memset(&dh_pair, 0, sizeof(dh_pair));
dh_pair.is_ready = false;
return 0;
}
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16])
{
struct tc_aes_key_sched_struct sched;
if (tc_aes128_set_encrypt_key(&sched, key->key) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_aes_encrypt(enc_data, plaintext, &sched) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct tc_ccm_mode_struct ccm;
struct tc_aes_key_sched_struct sched;
if (tc_aes128_set_encrypt_key(&sched, key->key) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_ccm_config(&ccm, &sched, nonce, 13, mic_size) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_ccm_generation_encryption(enc_data, len + mic_size, aad, aad_len,
plaintext, len, &ccm) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct tc_ccm_mode_struct ccm;
struct tc_aes_key_sched_struct sched;
if (tc_aes128_set_encrypt_key(&sched, key->key) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_ccm_config(&ccm, &sched, nonce, 13, mic_size) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_ccm_decryption_verification(plaintext, len, aad, aad_len,
enc_data, len + mic_size, &ccm) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct bt_mesh_key mesh_key;
memcpy(mesh_key.key, key, 16);
return bt_mesh_ccm_encrypt(&mesh_key, nonce, plaintext, len, aad, aad_len,
enc_data, mic_size);
}
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct bt_mesh_key mesh_key;
memcpy(mesh_key.key, key, 16);
return bt_mesh_ccm_decrypt(&mesh_key, nonce, enc_data, len, aad, aad_len,
plaintext, mic_size);
}
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
struct tc_aes_key_sched_struct sched;
struct tc_cmac_struct state;
if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
if (tc_cmac_update(&state, sg->data, sg->len) == TC_CRYPTO_FAIL) {
return -EIO;
}
}
if (tc_cmac_final(mac, &state) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16])
{
return bt_mesh_aes_cmac_raw_key(key->key, sg, sg_len, mac);
}
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32])
{
struct tc_hmac_state_struct h;
if (tc_hmac_set_key(&h, key, 32) == TC_CRYPTO_FAIL) {
return -EIO;
}
if (tc_hmac_init(&h) == TC_CRYPTO_FAIL) {
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
if (tc_hmac_update(&h, sg->data, sg->len) == TC_CRYPTO_FAIL) {
return -EIO;
}
}
if (tc_hmac_final(mac, 32, &h) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
int bt_mesh_pub_key_gen(void)
{
int rc;
/* Generate a random private key */
do {
rc = bt_mesh_rand(dh_pair.private_key, sizeof(dh_pair.private_key));
if (rc) {
BT_ERR("Failed to generate random private key");
return rc;
}
/* Ensure the private key is valid (first bytes in BE shall be non-zero) */
} while (dh_pair.private_key[0] == 0 &&
dh_pair.private_key[1] == 0);
/* Compute the public key from the private key */
rc = uECC_compute_public_key(dh_pair.private_key, dh_pair.public_key, uECC_secp256r1());
if (rc != TC_CRYPTO_SUCCESS) {
dh_pair.is_ready = false;
BT_ERR("Failed to compute public key");
return -EIO;
}
dh_pair.is_ready = true;
return 0;
}
const uint8_t *bt_mesh_pub_key_get_raw(void)
{
if (!dh_pair.is_ready) {
if (bt_mesh_pub_key_gen() != 0) {
return NULL;
}
}
return dh_pair.public_key;
}
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
{
int rc;
memcpy(dh_pair.private_key, pri_key, PRIV_KEY_SIZE);
/* Compute the public key from the provided private key */
rc = uECC_compute_public_key(dh_pair.private_key, dh_pair.public_key, uECC_secp256r1());
if (rc != TC_CRYPTO_SUCCESS) {
dh_pair.is_ready = false;
BT_ERR("Failed to compute public key from private key");
return;
}
BT_DBG("Pubkey:%s", bt_hex(dh_pair.public_key, PUB_KEY_SIZE));
BT_DBG("Privkey:%s", bt_hex(dh_pair.private_key, PRIV_KEY_SIZE));
dh_pair.is_ready = true;
}
bool bt_mesh_check_public_key_raw(const uint8_t key[64])
{
return uECC_valid_public_key(key, uECC_secp256r1()) == 0;
}
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
if (uECC_valid_public_key(pub_key, uECC_secp256r1()) != 0) {
BT_ERR("Public key is not valid");
return -EIO;
}
if (uECC_shared_secret(pub_key, priv_key ? priv_key : dh_pair.private_key,
dhkey, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) {
BT_ERR("DHKey generation failed");
return -EIO;
}
return 0;
}
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out)
{
(void)type; /* Type is not used for TinyCrypt, just store raw key */
memcpy(out->key, in, 16);
return 0;
}
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in)
{
memcpy(out, in->key, 16);
return 0;
}
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src)
{
memcpy(dst->key, src->key, 16);
}
int bt_mesh_key_destroy(const struct bt_mesh_key *key)
{
(void)key; /* Nothing to destroy for TinyCrypt */
return 0;
}
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key)
{
return memcmp(raw_key, key->key, 16);
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
struct tc_aes_key_sched_struct sched;
uint8_t tmp[16];
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
/* Swap key bytes (LE to BE) */
sys_memcpy_swap(tmp, key, 16);
if (tc_aes128_set_encrypt_key(&sched, tmp) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
/* Swap plaintext bytes (LE to BE) */
sys_memcpy_swap(tmp, plaintext, 16);
if (tc_aes_encrypt(enc_data, tmp, &sched) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
/* Swap result bytes (BE to LE) */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
struct tc_aes_key_sched_struct sched;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
if (tc_aes128_set_encrypt_key(&sched, key) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
if (tc_aes_encrypt(enc_data, plaintext, &sched) == TC_CRYPTO_FAIL) {
return -EINVAL;
}
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
@@ -13,6 +13,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "esp_attr.h"
#include "esp_heap_caps.h"
@@ -22,6 +23,7 @@
#include "mesh/trace.h"
#include "mesh/mutex.h"
#include "mesh/access.h"
#include "mesh/crypto.h"
#ifdef __cplusplus
extern "C" {
@@ -0,0 +1,514 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileCopyrightText: 2023 Nordic Semiconductor ASA
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_CRYPTO_H_
#define _BLE_MESH_CRYPTO_H_
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "mesh/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Key sizes */
#define PRIV_KEY_SIZE 32
#define PUB_KEY_SIZE 64
#define DH_KEY_SIZE 32
/**
* @brief Crypto module endianness definitions
*
* BLE Mesh protocol uses big-endian format for ECC operations.
* These macros define whether the underlying crypto implementation
* expects big-endian or little-endian input.
*
* - BT_MESH_CRYPTO_ENDIAN_BIG: Module expects big-endian (TinyCrypt, MbedTLS, PSA)
* - BT_MESH_CRYPTO_ENDIAN_LITTLE: Module expects little-endian (future implementations)
*/
#define BT_MESH_CRYPTO_ENDIAN_BIG 0
#define BT_MESH_CRYPTO_ENDIAN_LITTLE 1
/**
* @brief Current crypto module endianness
*
* This macro should be defined by the crypto implementation.
* Default is big-endian (matching TinyCrypt, MbedTLS, PSA).
*/
#ifndef BT_MESH_CRYPTO_ENDIAN
#define BT_MESH_CRYPTO_ENDIAN BT_MESH_CRYPTO_ENDIAN_BIG
#endif
/**
* @brief Parameter conversion macros for endianness handling
*
* These macros automatically handle byte order conversion between
* BLE Mesh's big-endian format and the crypto module's expected format.
*
* For public keys (64 bytes = X + Y), the X and Y coordinates must be
* swapped separately, not as a single 64-byte block.
*/
#if (BT_MESH_CRYPTO_ENDIAN == BT_MESH_CRYPTO_ENDIAN_LITTLE)
/* Little-endian mode: need byte order conversion */
#define CRYPTO_PARAM_DECLARE(name, size) \
uint8_t _##name[size]
#define CRYPTO_PARAM_IN(name, size) \
sys_memcpy_swap(_##name, name, size)
#define CRYPTO_PARAM_OUT(name, size) \
sys_memcpy_swap((uint8_t *)(name), _##name, size)
#define CRYPTO_PARAM(name) (_##name)
/* Public key (64 bytes) needs special handling: swap X and Y separately */
#define CRYPTO_PARAM_PUBKEY_IN(name) \
do { \
sys_memcpy_swap(_##name, name, 32); \
sys_memcpy_swap(_##name + 32, (name) + 32, 32); \
} while (0)
#define CRYPTO_PARAM_PUBKEY_OUT(name) \
do { \
sys_memcpy_swap((uint8_t *)(name), _##name, 32); \
sys_memcpy_swap((uint8_t *)(name) + 32, _##name + 32, 32); \
} while (0)
#else /* BT_MESH_CRYPTO_ENDIAN_BIG */
/* Big-endian mode: no conversion needed, use original parameters directly */
#define CRYPTO_PARAM_DECLARE(name, size) \
(void)0
#define CRYPTO_PARAM_IN(name, size) \
(void)0
#define CRYPTO_PARAM_OUT(name, size) \
(void)0
#define CRYPTO_PARAM(name) (name)
#define CRYPTO_PARAM_PUBKEY_IN(name) \
(void)0
#define CRYPTO_PARAM_PUBKEY_OUT(name) \
(void)0
#endif /* BT_MESH_CRYPTO_ENDIAN */
/**
* @brief Scatter-Gather data structure for cryptographic operations
*/
struct bt_mesh_sg {
const void *data;
size_t len;
};
/**
* @brief Mesh key type enumeration
*/
enum bt_mesh_key_type {
BT_MESH_KEY_TYPE_ECB, /**< AES-ECB encryption/decryption */
BT_MESH_KEY_TYPE_CCM, /**< AES-CCM AEAD */
BT_MESH_KEY_TYPE_CMAC, /**< AES-CMAC */
BT_MESH_KEY_TYPE_NET, /**< Network key */
BT_MESH_KEY_TYPE_APP, /**< Application key */
BT_MESH_KEY_TYPE_DEV, /**< Device key */
};
/**
* @brief Mesh key structure
*
* For TinyCrypt/MbedTLS: stores raw key bytes
* For PSA: stores PSA key ID
*/
struct bt_mesh_key {
#if CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS && CONFIG_MBEDTLS_VER_4_X_SUPPORT
uint32_t key; /* PSA key ID */
#else
uint8_t key[16]; /* Raw key bytes */
#endif
};
/**
* @brief Initialize the cryptographic subsystem
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_crypto_init(void);
/**
* @brief AES-ECB encryption (big-endian)
*
* @param key Pointer to mesh key structure
* @param plaintext 16-byte plaintext
* @param enc_data 16-byte output buffer for encrypted data
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16]);
/**
* @brief AES-CCM encryption
*
* @param key Pointer to mesh key structure
* @param nonce 13-byte nonce
* @param plaintext Input plaintext
* @param len Length of plaintext
* @param aad Additional authenticated data
* @param aad_len Length of AAD
* @param enc_data Output buffer (must be len + mic_size bytes)
* @param mic_size Size of MIC (4, 8, or 16 bytes)
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size);
/**
* @brief AES-CCM decryption
*
* @param key Pointer to mesh key structure
* @param nonce 13-byte nonce
* @param enc_data Encrypted data with MIC
* @param len Length of plaintext (without MIC)
* @param aad Additional authenticated data
* @param aad_len Length of AAD
* @param plaintext Output buffer for plaintext
* @param mic_size Size of MIC (4, 8, or 16 bytes)
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size);
/**
* @brief AES-CCM encryption using raw key bytes
*
* @param key 16-byte raw key
* @param nonce 13-byte nonce
* @param plaintext Input plaintext
* @param len Length of plaintext
* @param aad Additional authenticated data
* @param aad_len Length of AAD
* @param enc_data Output buffer (must be len + mic_size bytes)
* @param mic_size Size of MIC (4, 8, or 16 bytes)
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size);
/**
* @brief AES-CCM decryption using raw key bytes
*
* @param key 16-byte raw key
* @param nonce 13-byte nonce
* @param enc_data Encrypted data with MIC
* @param len Length of plaintext (without MIC)
* @param aad Additional authenticated data
* @param aad_len Length of AAD
* @param plaintext Output buffer for plaintext
* @param mic_size Size of MIC (4, 8, or 16 bytes)
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size);
/**
* @brief AES-CMAC using mesh key structure
*
* @param key Pointer to mesh key structure
* @param sg Scatter-gather list of input data
* @param sg_len Number of scatter-gather entries
* @param mac 16-byte output buffer for MAC
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16]);
/**
* @brief AES-CMAC using raw key bytes
*
* @param key 16-byte raw key
* @param sg Scatter-gather list of input data
* @param sg_len Number of scatter-gather entries
* @param mac 16-byte output buffer for MAC
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16]);
/**
* @brief AES-CMAC with single data input (convenience wrapper)
*/
static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
size_t len, uint8_t mac[16])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_aes_cmac_raw_key(key, &sg, 1, mac);
}
/**
* @brief HMAC-SHA256 using raw key bytes
*
* @param key 32-byte raw key
* @param sg Scatter-gather list of input data
* @param sg_len Number of scatter-gather entries
* @param mac 32-byte output buffer for MAC
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32]);
/**
* @brief HMAC-SHA256 with single data input (convenience wrapper)
*/
static inline int bt_mesh_sha256_hmac_one(const uint8_t key[32], const void *m,
size_t len, uint8_t mac[32])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_sha256_hmac_raw_key(key, &sg, 1, mac);
}
/* ============================================================================
* Internal Low-Level ECC APIs
* ============================================================================
* These functions operate in the crypto module's native byte order.
* Do NOT call these directly - use the public wrapper functions below.
*/
const uint8_t *bt_mesh_pub_key_get_raw(void);
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32]);
bool bt_mesh_check_public_key_raw(const uint8_t key[64]);
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey);
/* ============================================================================
* Public ECC APIs (with automatic endianness conversion)
* ============================================================================
* All public key and DHKey parameters use big-endian format (BLE Mesh protocol).
* For little-endian crypto modules, conversion is handled automatically.
*/
/**
* @brief Generate a new ECC public key pair
*
* Generates a new P-256 key pair for ECDH operations.
* The private key is stored internally.
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_pub_key_gen(void);
/**
* @brief Get the current public key (raw pointer)
*
* Returns pointer to the internal public key storage.
* Note: The byte order depends on crypto module's native format.
* Use bt_mesh_pub_key_copy() to get big-endian format.
*
* @return Pointer to 64-byte public key, or NULL if not ready
*/
#define bt_mesh_pub_key_get() bt_mesh_pub_key_get_raw()
/**
* @brief Copy current public key to user buffer (big-endian output)
*
* Copies the public key to the provided buffer, converting to big-endian
* format (BLE Mesh protocol format) if necessary.
*
* @param buf 64-byte output buffer for public key (big-endian output)
*
* @return 0 on success, -EAGAIN if public key not ready
*/
static inline int bt_mesh_pub_key_copy(uint8_t *buf)
{
const uint8_t *key = bt_mesh_pub_key_get_raw();
if (key == NULL || buf == NULL) {
return -EAGAIN;
}
#if (BT_MESH_CRYPTO_ENDIAN == BT_MESH_CRYPTO_ENDIAN_LITTLE)
/* Swap X and Y coordinates separately to big-endian */
sys_memcpy_swap(buf, key, 32);
sys_memcpy_swap(buf + 32, key + 32, 32);
#else
memcpy(buf, key, PUB_KEY_SIZE);
#endif
return 0;
}
/**
* @brief Set a custom private key
*
* @param pri_key 32-byte private key (big-endian, BLE Mesh format)
*/
static inline void bt_mesh_set_private_key(const uint8_t pri_key[32])
{
CRYPTO_PARAM_DECLARE(pri_key, PRIV_KEY_SIZE);
CRYPTO_PARAM_IN(pri_key, PRIV_KEY_SIZE);
bt_mesh_set_private_key_raw(CRYPTO_PARAM(pri_key));
}
/**
* @brief Check if a public key is valid
*
* Verifies that the given public key is a valid point on the P-256 curve.
*
* @param key 64-byte public key (X || Y, big-endian, BLE Mesh format)
*
* @return true if valid, false otherwise
*/
static inline bool bt_mesh_check_public_key(const uint8_t key[64])
{
CRYPTO_PARAM_DECLARE(key, PUB_KEY_SIZE);
CRYPTO_PARAM_PUBKEY_IN(key);
return bt_mesh_check_public_key_raw(CRYPTO_PARAM(key));
}
/**
* @brief Generate ECDH shared secret (DHKey)
*
* @param pub_key 64-byte remote public key (X || Y, big-endian, BLE Mesh format)
* @param priv_key 32-byte private key (NULL to use internal key)
* @param dhkey 32-byte output buffer for shared secret (big-endian output)
*
* @return 0 on success, negative error code otherwise
*/
static inline int bt_mesh_dhkey_gen(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
int rc;
CRYPTO_PARAM_DECLARE(pub_key, PUB_KEY_SIZE);
CRYPTO_PARAM_DECLARE(priv_key, PRIV_KEY_SIZE);
CRYPTO_PARAM_DECLARE(dhkey, DH_KEY_SIZE);
/* Public key: swap X and Y coordinates separately */
CRYPTO_PARAM_PUBKEY_IN(pub_key);
if (priv_key != NULL) {
CRYPTO_PARAM_IN(priv_key, PRIV_KEY_SIZE);
}
rc = bt_mesh_dhkey_gen_raw(CRYPTO_PARAM(pub_key),
priv_key ? CRYPTO_PARAM(priv_key) : NULL,
CRYPTO_PARAM(dhkey));
if (rc) {
return rc;
}
CRYPTO_PARAM_OUT(dhkey, DH_KEY_SIZE);
return rc;
}
#define bt_mesh_dh_key_gen(pubkey, dhkey) bt_mesh_dhkey_gen(pubkey, NULL, dhkey)
/**
* @brief Import a raw key into mesh key structure
*
* @param type Key type (determines key usage)
* @param in 16-byte raw key
* @param out Output mesh key structure
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out);
/**
* @brief Export raw key bytes from mesh key structure
*
* @param out 16-byte output buffer
* @param in Input mesh key structure
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in);
/**
* @brief Assign (copy) a mesh key
*
* @param dst Destination mesh key
* @param src Source mesh key
*/
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src);
/**
* @brief Destroy a mesh key
*
* Releases any resources associated with the key.
*
* @param key Mesh key to destroy
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_key_destroy(const struct bt_mesh_key *key);
/**
* @brief Compare a raw key with a mesh key
*
* @param raw_key 16-byte raw key
* @param key Mesh key structure to compare
*
* @return 0 if equal, non-zero otherwise
*/
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key);
/**
* @brief AES encryption (little-endian byte order)
*
* The key and plaintext are byte-swapped before encryption,
* and the result is byte-swapped after encryption.
*
* @param key 16-byte key
* @param plaintext 16-byte plaintext
* @param enc_data 16-byte output buffer
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
/**
* @brief AES encryption (big-endian byte order)
*
* Standard AES-ECB encryption without byte swapping.
*
* @param key 16-byte key
* @param plaintext 16-byte plaintext
* @param enc_data 16-byte output buffer
*
* @return 0 on success, negative error code otherwise
*/
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_CRYPTO_H_ */
@@ -8,6 +8,7 @@
#ifndef _BLE_MESH_KERNEL_H_
#define _BLE_MESH_KERNEL_H_
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
@@ -22,7 +23,7 @@ extern "C" {
#ifdef CONFIG_BT_BLUEDROID_ENABLED
#ifdef CONFIG_BT_BLUEDROID_PINNED_TO_CORE
#define BLE_MESH_ADV_TASK_CORE (CONFIG_BT_BLUEDROID_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
#define BLE_MESH_ADV_TASK_CORE (CONFIG_BT_BLUEDROID_PINNED_TO_CORE < CONFIG_FREERTOS_NUMBER_OF_CORES ? CONFIG_BT_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
#else
#define BLE_MESH_ADV_TASK_CORE (0)
#endif
@@ -30,7 +31,7 @@ extern "C" {
#ifdef CONFIG_BT_NIMBLE_ENABLED
#ifdef CONFIG_BT_NIMBLE_PINNED_TO_CORE
#define BLE_MESH_ADV_TASK_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY)
#define BLE_MESH_ADV_TASK_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < CONFIG_FREERTOS_NUMBER_OF_CORES ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY)
#else
#define BLE_MESH_ADV_TASK_CORE (0)
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -32,6 +32,11 @@ void bt_mesh_r_mutex_free(bt_mesh_mutex_t *mutex);
void bt_mesh_r_mutex_lock(bt_mesh_mutex_t *mutex);
void bt_mesh_r_mutex_unlock(bt_mesh_mutex_t *mutex);
void bt_mesh_c_semaphore_create(bt_mesh_mutex_t *mutex, int max, int init);
void bt_mesh_c_semaphore_free(bt_mesh_mutex_t *mutex);
void bt_mesh_c_semaphore_give(bt_mesh_mutex_t *mutex);
void bt_mesh_c_semaphore_take(bt_mesh_mutex_t *mutex, uint32_t timeout);
void bt_mesh_alarm_lock(void);
void bt_mesh_alarm_unlock(void);
@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_MESH_QUEUE_H_
#define _BLE_MESH_QUEUE_H_
#include "mesh/kernel.h"
#include "mesh/slist.h"
#include "mesh/atomic.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
QueueHandle_t handle;
#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
StaticQueue_t *buffer;
uint8_t *storage;
#endif
} bt_mesh_queue_t;
int bt_mesh_queue_init(bt_mesh_queue_t *queue, uint16_t queue_size, uint8_t item_size);
int bt_mesh_queue_deinit(bt_mesh_queue_t *queue);
#ifdef __cplusplus
}
#endif
#endif /* _BLE_MESH_QUEUE_H_ */
@@ -292,7 +292,7 @@ extern "C" {
* { MY_PWM0 , MY_PWM1 }
*
* @param LEN The length of the sequence. Must be an integer literal less
* than 255.
* than 255 (ref: utils_loops.h).
* @param F A macro function that accepts at least two arguments:
* <tt>F(i, ...)</tt>. @p F is called repeatedly in the expansion.
* Its first argument @p i is the index in the sequence, and
+52 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -125,6 +125,57 @@ void bt_mesh_r_mutex_unlock(bt_mesh_mutex_t *mutex)
}
}
void bt_mesh_c_semaphore_free(bt_mesh_mutex_t *mutex)
{
bt_mesh_mutex_free(mutex);
}
void bt_mesh_c_semaphore_create(bt_mesh_mutex_t *mutex, int max, int init)
{
if (!mutex) {
BT_ERR("Create, invalid mutex");
return;
}
#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL
mutex->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT
mutex->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#endif
__ASSERT(mutex->buffer, "Failed to create counting semaphore buffer");
mutex->mutex = xSemaphoreCreateCountingStatic(max, init, mutex->buffer);
__ASSERT(mutex->mutex, "Failed to create static counting semaphore");
#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */
mutex->mutex = xSemaphoreCreateCounting(max, init);
__ASSERT(mutex->mutex, "Failed to create counting semaphore");
#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */
}
void bt_mesh_c_semaphore_take(bt_mesh_mutex_t *mutex, uint32_t timeout)
{
if (!mutex) {
BT_ERR("Lock, invalid counting semaphore");
return;
}
if (mutex->mutex) {
xSemaphoreTake(mutex->mutex, timeout / portTICK_PERIOD_MS);
}
}
void bt_mesh_c_semaphore_give(bt_mesh_mutex_t *mutex)
{
if (!mutex) {
BT_ERR("Unlock, invalid counting semaphore");
return;
}
if (mutex->mutex) {
xSemaphoreGive(mutex->mutex);
}
}
void bt_mesh_alarm_lock(void)
{
bt_mesh_mutex_lock(&alarm_lock);
+48
View File
@@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh/common.h"
#include "mesh/queue.h"
int bt_mesh_queue_init(bt_mesh_queue_t *queue, uint16_t queue_size, uint8_t item_size)
{
__ASSERT(queue && queue_size && item_size, "Invalid queue init parameters");
#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
queue->handle = xQueueCreate(queue_size, item_size);
__ASSERT(queue->handle, "Failed to create queue");
#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */
#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL
queue->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT
queue->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#endif
__ASSERT(queue->buffer, "Failed to create queue buffer");
#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL
queue->storage = heap_caps_calloc_prefer(1, (queue_size * item_size), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT
queue->storage = heap_caps_calloc_prefer(1, (queue_size * item_size), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#endif
__ASSERT(queue->storage, "Failed to create queue storage");
queue->handle = xQueueCreateStatic(queue_size, item_size, (uint8_t*)queue->storage, queue->buffer);
__ASSERT(queue->handle, "Failed to create static queue");
#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */
return 0;
}
int bt_mesh_queue_deinit(bt_mesh_queue_t *queue)
{
__ASSERT(queue, "Invalid queue init parameters");
vQueueDelete(queue->handle);
queue->handle = NULL;
#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC
heap_caps_free(queue->buffer);
queue->buffer = NULL;
heap_caps_free(queue->storage);
queue->storage = NULL;
#endif
return 0;
}
+19
View File
@@ -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;
@@ -1085,10 +1090,24 @@ static int model_send(const 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);
File diff suppressed because it is too large Load Diff
+8 -81
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,102 +10,29 @@
#ifndef _ADV_H_
#define _ADV_H_
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
#include "ext_adv.h"
#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
#include "mesh/atomic.h"
#include "mesh/access.h"
#include "mesh/adapter.h"
#include "mesh/utils.h"
#include "adv_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Maximum advertising data payload for a single data type */
#define BLE_MESH_ADV_DATA_SIZE 29
/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */
#define BLE_MESH_ADV_USER_DATA_SIZE 4
#define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf))
#define BLE_MESH_ADV_BUSY(buf) (BLE_MESH_ADV(buf)->busy)
uint16_t bt_mesh_pdu_duration(uint8_t xmit);
typedef struct bt_mesh_msg {
bool relay; /* Flag indicates if the packet is a relayed one */
void *arg; /* Pointer to the struct net_buf */
uint16_t src; /* Source address for relay packets */
uint16_t dst; /* Destination address for relay packets */
uint32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */
} bt_mesh_msg_t;
enum bt_mesh_adv_type {
BLE_MESH_ADV_PROV,
BLE_MESH_ADV_DATA,
BLE_MESH_ADV_BEACON,
BLE_MESH_ADV_URI,
BLE_MESH_ADV_BLE,
BLE_MESH_ADV_PROXY_SOLIC,
BLE_MESH_ADV_TYPES_NUM,
};
struct bt_mesh_adv {
const struct bt_mesh_send_cb *cb;
void *cb_data;
uint8_t type:3;
bt_mesh_atomic_t busy;
uint8_t xmit;
};
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout);
typedef enum {
BLE_MESH_BUF_REF_EQUAL,
BLE_MESH_BUF_REF_SMALL,
BLE_MESH_BUF_REF_MAX,
} bt_mesh_buf_ref_flag_t;
void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf,
uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag);
struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
bt_mesh_adv_alloc_t get_id,
enum bt_mesh_adv_type type,
int32_t timeout);
void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool);
void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit,
const struct bt_mesh_send_cb *cb,
void *cb_data);
struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout);
void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit,
uint16_t src, uint16_t dst,
const struct bt_mesh_send_cb *cb,
void *cb_data);
uint16_t bt_mesh_get_stored_relay_count(void);
void bt_mesh_adv_update(void);
void bt_mesh_adv_init(void);
void bt_mesh_adv_deinit(void);
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *data, uint8_t *index);
int bt_mesh_stop_ble_advertising(uint8_t index);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
#endif /* _ADV_H_ */
@@ -55,6 +55,29 @@ static bt_mesh_ext_adv_t ext_long_relay_adv_pool[CONFIG_BLE_MESH_LONG_PACKET_REL
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
#endif /* CONFIG_BLE_MESH_EXT_ADV */
const uint8_t adv_type[] = {
[BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV,
[BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
#if CONFIG_BLE_MESH_EXT_ADV
[BLE_MESH_ADV_EXT_PROV] = BLE_MESH_DATA_MESH_PROV,
[BLE_MESH_ADV_EXT_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
[BLE_MESH_ADV_EXT_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
#if CONFIG_BLE_MESH_LONG_PACKET
[BLE_MESH_ADV_EXT_LONG_PROV] = BLE_MESH_DATA_MESH_PROV,
[BLE_MESH_ADV_EXT_LONG_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
[BLE_MESH_ADV_EXT_LONG_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#if CONFIG_BLE_MESH_FRIEND
[BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE,
#endif
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
[BLE_MESH_ADV_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
#endif
[BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON,
[BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI,
};
static inline void init_adv_with_defaults(struct bt_mesh_adv *adv,
enum bt_mesh_adv_type type)
{
+20 -38
View File
@@ -48,6 +48,9 @@ extern "C" {
#define BLE_MESH_ADV_INST_UNUSED 0xFF
/* Flags for struct bt_mesh_adv */
#define BLE_MESH_ADV_FLAG_SKIP_START_CB BIT(0) /* Skip start callback (already called by GATT) */
struct bt_mesh_adv {
const struct bt_mesh_send_cb *cb;
void *cb_data;
@@ -61,6 +64,7 @@ struct bt_mesh_adv {
uint32_t adv_itvl;
uint8_t adv_cnt;
uint8_t channel_map;
uint8_t flags; /* See BLE_MESH_ADV_FLAG_* */
};
#if CONFIG_BLE_MESH_USE_BLE_50
@@ -171,29 +175,7 @@ typedef enum {
BLE_MESH_BUF_REF_MAX,
} bt_mesh_buf_ref_flag_t;
static const uint8_t adv_type[] = {
[BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV,
[BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
#if CONFIG_BLE_MESH_EXT_ADV
[BLE_MESH_ADV_EXT_PROV] = BLE_MESH_DATA_MESH_PROV,
[BLE_MESH_ADV_EXT_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
[BLE_MESH_ADV_EXT_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
#if CONFIG_BLE_MESH_LONG_PACKET
[BLE_MESH_ADV_EXT_LONG_PROV] = BLE_MESH_DATA_MESH_PROV,
[BLE_MESH_ADV_EXT_LONG_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
[BLE_MESH_ADV_EXT_LONG_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
#endif /* CONFIG_BLE_MESH_LONG_PACKET */
#endif /* CONFIG_BLE_MESH_EXT_ADV */
#if CONFIG_BLE_MESH_FRIEND
[BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE,
#endif
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
[BLE_MESH_ADV_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE,
#endif
[BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON,
[BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI,
};
extern const uint8_t adv_type[];
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);
@@ -214,22 +196,22 @@ static inline TickType_t K_WAIT(int32_t val)
return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS);
}
static inline void adv_send_start(uint16_t duration, int err,
const struct bt_mesh_send_cb *cb,
void *cb_data)
{
if (cb && cb->start) {
cb->start(duration, err, cb_data);
}
}
#define BLE_MESH_SEND_START_CB(_buf, _duration, _err, _cb, _cb_data) \
do { \
if (!(BLE_MESH_ADV(_buf)->flags & BLE_MESH_ADV_FLAG_SKIP_START_CB)) { \
if ((_cb) && (_cb)->start) { \
(_cb)->start((_duration), (_err), (_cb_data)); \
} \
BLE_MESH_ADV(_buf)->flags |= BLE_MESH_ADV_FLAG_SKIP_START_CB; \
} \
} while (0)
static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
void *cb_data)
{
if (cb && cb->end) {
cb->end(err, cb_data);
}
}
#define BLE_MESH_SEND_END_CB(_err, _cb, _cb_data) \
do { \
if ((_cb) && (_cb)->end) { \
(_cb)->end((_err), (_cb_data)); \
} \
} while (0)
struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void);
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+54
View File
@@ -0,0 +1,54 @@
/* Bluetooth Mesh */
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLE_ADV_H_
#define _BLE_ADV_H_
#include "mesh/atomic.h"
#include "mesh/access.h"
#include "mesh/adapter.h"
#include "mesh/utils.h"
#include "adv_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
enum {
TIMER_INIT, /* Resend timer is initialized */
NUM_FLAGS,
};
struct bt_mesh_ble_adv_tx {
struct bt_mesh_ble_adv_param param;
struct net_buf *buf;
struct k_delayed_work resend;
BLE_MESH_ATOMIC_DEFINE(flags, NUM_FLAGS);
};
int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *data, uint8_t *index);
int bt_mesh_stop_ble_advertising(uint8_t index);
void bt_mesh_ble_adv_init(void);
#if CONFIG_BLE_MESH_DEINIT
void bt_mesh_ble_adv_deinit(void);
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* _BLE_ADV_H_ */
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+4 -349
View File
@@ -11,12 +11,6 @@
#include <stdbool.h>
#include <errno.h>
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/cmac_mode.h>
#include <tinycrypt/hmac.h>
#include <tinycrypt/sha256.h>
#include "crypto.h"
#include "mesh/config.h"
#include "mesh/common.h"
@@ -29,29 +23,7 @@
#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4)
#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
struct tc_aes_key_sched_struct sched = {0};
struct tc_cmac_struct state = {0};
if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
if (tc_cmac_update(&state, sg->data,
sg->len) == TC_CRYPTO_FAIL) {
return -EIO;
}
}
if (tc_cmac_final(mac, &state) == TC_CRYPTO_FAIL) {
return -EIO;
}
return 0;
}
/* bt_mesh_aes_cmac is now mapped to bt_mesh_aes_cmac_raw_key from common crypto module */
int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
const char *info, uint8_t okm[16])
@@ -199,326 +171,9 @@ int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16])
return bt_mesh_k1(n, 16, salt, id128, out);
}
static int bt_mesh_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_msg, size_t msg_len,
const uint8_t *aad, size_t aad_len,
uint8_t *out_msg, size_t mic_size)
{
uint8_t msg[16] = {0}, pmsg[16] = {0}, cmic[16] = {0},
cmsg[16] = {0}, Xn[16] = {0}, mic[16] = {0};
uint16_t last_blk = 0U, blk_cnt = 0U;
size_t i = 0U, j = 0U;
int err = 0;
if (msg_len < 1 || aad_len >= 0xff00) {
return -EINVAL;
}
/* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(0x0000, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmic);
if (err) {
return err;
}
/* X_0 = e(AppKey, 0x09 || nonce || length) */
if (mic_size == sizeof(uint64_t)) {
pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
} else {
pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
}
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(msg_len, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* If AAD is being used to authenticate, include it here */
if (aad_len) {
sys_put_be16(aad_len, pmsg);
for (i = 0; i < sizeof(uint16_t); i++) {
pmsg[i] = Xn[i] ^ pmsg[i];
}
j = 0;
aad_len += sizeof(uint16_t);
while (aad_len > 16) {
do {
pmsg[i] = Xn[i] ^ aad[j];
i++, j++;
} while (i < 16);
aad_len -= 16;
i = 0;
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
for (; i < aad_len; i++, j++) {
pmsg[i] = Xn[i] ^ aad[j];
}
for (i = aad_len; i < 16; i++) {
pmsg[i] = Xn[i];
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
last_blk = msg_len % 16;
blk_cnt = (msg_len + 15) / 16;
if (!last_blk) {
last_blk = 16U;
}
for (j = 0; j < blk_cnt; j++) {
if (j + 1 == blk_cnt) {
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(j + 1, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmsg);
if (err) {
return err;
}
/* Encrypted = Payload[0-15] ^ C_1 */
for (i = 0; i < last_blk; i++) {
msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
}
memcpy(out_msg + (j * 16), msg, last_blk);
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
for (i = 0; i < last_blk; i++) {
pmsg[i] = Xn[i] ^ msg[i];
}
for (i = last_blk; i < 16; i++) {
pmsg[i] = Xn[i] ^ 0x00;
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* MIC = C_mic ^ X_1 */
for (i = 0; i < sizeof(mic); i++) {
mic[i] = cmic[i] ^ Xn[i];
}
} else {
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(j + 1, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmsg);
if (err) {
return err;
}
/* Encrypted = Payload[0-15] ^ C_1 */
for (i = 0; i < 16; i++) {
msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
}
memcpy(out_msg + (j * 16), msg, 16);
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
for (i = 0; i < 16; i++) {
pmsg[i] = Xn[i] ^ msg[i];
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
}
if (memcmp(mic, enc_msg + msg_len, mic_size)) {
return -EBADMSG;
}
return 0;
}
static int bt_mesh_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *msg, size_t msg_len,
const uint8_t *aad, size_t aad_len,
uint8_t *out_msg, size_t mic_size)
{
uint8_t pmsg[16] = {0}, cmic[16] = {0}, cmsg[16] = {0},
mic[16] = {0}, Xn[16] = {0};
uint16_t blk_cnt = 0U, last_blk = 0U;
size_t i = 0U, j = 0U;
int err = 0;
BT_DBG("CCMEncrypt");
BT_DBG("Key %s", bt_hex(key, 16));
BT_DBG("Nonce %s", bt_hex(nonce, 13));
BT_DBG("Len %u: %s", msg_len, bt_hex(msg, msg_len));
BT_DBG("AADLen %u MicSize %u", aad_len, mic_size);
/* Unsupported AAD size */
if (aad_len >= 0xff00) {
return -EINVAL;
}
/* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(0x0000, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmic);
if (err) {
return err;
}
/* X_0 = e(AppKey, 0x09 || nonce || length) */
if (mic_size == sizeof(uint64_t)) {
pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
} else {
pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
}
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(msg_len, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* If AAD is being used to authenticate, include it here */
if (aad_len) {
sys_put_be16(aad_len, pmsg);
for (i = 0; i < sizeof(uint16_t); i++) {
pmsg[i] = Xn[i] ^ pmsg[i];
}
j = 0;
aad_len += sizeof(uint16_t);
while (aad_len > 16) {
do {
pmsg[i] = Xn[i] ^ aad[j];
i++, j++;
} while (i < 16);
aad_len -= 16;
i = 0;
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
for (; i < aad_len; i++, j++) {
pmsg[i] = Xn[i] ^ aad[j];
}
for (i = aad_len; i < 16; i++) {
pmsg[i] = Xn[i];
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
}
last_blk = msg_len % 16;
blk_cnt = (msg_len + 15) / 16;
if (!last_blk) {
last_blk = 16U;
}
for (j = 0; j < blk_cnt; j++) {
if (j + 1 == blk_cnt) {
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
for (i = 0; i < last_blk; i++) {
pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
}
for (i = last_blk; i < 16; i++) {
pmsg[i] = Xn[i] ^ 0x00;
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* MIC = C_mic ^ X_1 */
for (i = 0; i < sizeof(mic); i++) {
mic[i] = cmic[i] ^ Xn[i];
}
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(j + 1, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmsg);
if (err) {
return err;
}
/* Encrypted = Payload[0-15] ^ C_1 */
for (i = 0; i < last_blk; i++) {
out_msg[(j * 16) + i] =
msg[(j * 16) + i] ^ cmsg[i];
}
} else {
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
for (i = 0; i < 16; i++) {
pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
}
err = bt_mesh_encrypt_be(key, pmsg, Xn);
if (err) {
return err;
}
/* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
pmsg[0] = 0x01;
memcpy(pmsg + 1, nonce, 13);
sys_put_be16(j + 1, pmsg + 14);
err = bt_mesh_encrypt_be(key, pmsg, cmsg);
if (err) {
return err;
}
/* Encrypted = Payload[0-15] ^ C_N */
for (i = 0; i < 16; i++) {
out_msg[(j * 16) + i] =
msg[(j * 16) + i] ^ cmsg[i];
}
}
}
memcpy(out_msg + msg_len, mic, mic_size);
return 0;
}
/* Use the unified crypto module for CCM operations */
#define bt_mesh_ccm_decrypt bt_mesh_ccm_decrypt_raw_key
#define bt_mesh_ccm_encrypt bt_mesh_ccm_encrypt_raw_key
#if CONFIG_BLE_MESH_PROXY
static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu,
+6 -15
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
*/
@@ -12,26 +12,17 @@
#include <string.h>
#include "mesh/buf.h"
#include "mesh/crypto.h" /* Include common crypto API */
#ifdef __cplusplus
extern "C" {
#endif
struct bt_mesh_sg {
const void *data;
size_t len;
};
/* Map bt_mesh_aes_cmac to bt_mesh_aes_cmac_raw_key from common crypto module.
* struct bt_mesh_sg is defined in mesh/crypto.h */
#define bt_mesh_aes_cmac bt_mesh_aes_cmac_raw_key
int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16]);
static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
size_t len, uint8_t mac[16])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_aes_cmac(key, &sg, 1, mac);
}
/* bt_mesh_aes_cmac_one is defined as inline in mesh/crypto.h */
static inline bool bt_mesh_s1(const char *m, uint8_t salt[16])
{
+3 -3
View File
@@ -181,7 +181,7 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration)
break;
}
adv_send_start(duration, err, cb, cb_data);
BLE_MESH_SEND_START_CB(buf, duration, err, cb, cb_data);
if (err) {
BT_ERR("Start advertising failed: err %d", err);
return err;
@@ -381,8 +381,8 @@ static uint32_t received_adv_evts_handle(uint32_t recv_evts)
} else
#endif
{
adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb,
BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data);
BLE_MESH_SEND_END_CB(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb,
BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data);
bt_mesh_adv_buf_ref_debug(__func__, adv_insts[i].sending_buf, 4U, BLE_MESH_BUF_REF_SMALL);
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+6 -26
View File
@@ -27,14 +27,6 @@
#ifdef CONFIG_BLE_MESH_FRIEND
/* We reserve one extra buffer for each friendship, since we need to be able
* to resend the last sent PDU, which sits separately outside of the queue.
*/
#define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \
CONFIG_BLE_MESH_FRIEND_LPN_COUNT)
#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), struct friend_adv, adv)
/* PDUs from Friend to the LPN should only be transmitted once with the
* smallest possible interval (20ms).
*
@@ -57,14 +49,6 @@ struct friend_pdu_info {
uint32_t iv_index;
};
NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT,
BLE_MESH_ADV_DATA_SIZE, NULL);
static struct friend_adv {
struct bt_mesh_adv adv;
uint16_t app_idx;
} adv_pool[FRIEND_BUF_COUNT];
enum {
BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL,
BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT,
@@ -83,12 +67,6 @@ static struct bt_mesh_subnet *friend_subnet_get(uint16_t net_idx)
return bt_mesh_subnet_get(net_idx);
}
static struct bt_mesh_adv *adv_alloc(int id)
{
adv_pool[id].app_idx = BLE_MESH_KEY_UNUSED;
return &adv_pool[id].adv;
}
static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr)
{
BT_INFO("IsLPNUnicast, LPN 0x%04x NumElem %u Addr 0x%04x",
@@ -401,8 +379,9 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd,
{
struct net_buf *buf = NULL;
buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc,
BLE_MESH_ADV_DATA, K_NO_WAIT);
BT_DBG("CreatFrndPDU");
buf = bt_mesh_adv_create(BLE_MESH_ADV_FRIEND, K_NO_WAIT);
if (!buf) {
return NULL;
}
@@ -1420,6 +1399,8 @@ int bt_mesh_friend_init(void)
}
}
bt_mesh_frnd_adv_init();
friend_init = true;
return 0;
@@ -1448,8 +1429,7 @@ int bt_mesh_friend_deinit(void)
k_delayed_work_free(&frnd->clear.timer);
}
bt_mesh_unref_buf_from_pool(&friend_buf_pool);
memset(adv_pool, 0, sizeof(adv_pool));
bt_mesh_frnd_adv_deinit();
friend_init = false;
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -162,6 +162,49 @@ struct bt_mesh_elem {
#define BLE_MESH_MODEL_ID_MBT_SRV BLE_MESH_MODEL_ID_BLOB_SRV
#define BLE_MESH_MODEL_ID_MBT_CLI BLE_MESH_MODEL_ID_BLOB_CLI
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. */
@@ -212,6 +255,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 {
@@ -356,7 +401,7 @@ struct bt_mesh_model_op {
* @return Mesh transmit value that can be used e.g. for the default
* values of the configuration model data.
*/
#define BLE_MESH_TRANSMIT(count, int_ms) ((count) | ((((int_ms) / 10) - 1) << 3))
#define BLE_MESH_TRANSMIT(count, int_ms) ((uint8_t)(count) | ((((int_ms) / 10) - 1) << 3))
/** @def BLE_MESH_TRANSMIT_COUNT
*
@@ -15,24 +15,79 @@
#include "mesh/utils.h"
#include "mesh/uuid.h"
#include "mesh/buf.h"
#include "mesh/crypto.h"
#ifdef __cplusplus
extern "C" {
#endif
/* BLE Mesh Max Connection Count */
/**
* The maximum number of connection count is limited by
* the resources allocated by both the host and the controller
* components, so the actual number of available connections
* is the minimum of the resources from both.
*
* On the C3/S3 platform, the controller uses the macro `CONFIG_BT_CTRL_BLE_MAX_ACT`,
* but adv and scan also occupy this resource, so the actual number of available
* connections is (CONFIG_BT_CTRL_BLE_MAX_ACT - adv instance count - scan).
* However, the macro allocation on the host is entirely for connections,
* so on the C3/S3 platform, the maximum number of connectable devices should
* be determined by the configuration at the host minus the number of
* advertising instances and scan from the controller's configuration.
*/
#ifdef CONFIG_BT_BLUEDROID_ENABLED
#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS
#if CONFIG_IDF_TARGET_ESP32
#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_ACL_CONNECTIONS, CONFIG_BTDM_CTRL_BLE_MAX_CONN)
#elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3)
#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_ACL_CONNECTIONS, (CONFIG_BT_CTRL_BLE_MAX_ACT - 2))
#elif (CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || \
CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61)
#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_ACL_CONNECTIONS, CONFIG_BT_LE_MAX_CONNECTIONS)
#else
/* default setting */
#define BLE_MESH_MAX_CONN 1
#endif
#endif /* CONFIG_BT_BLUEDROID_ENABLED */
#ifdef CONFIG_BT_NIMBLE_ENABLED
#if CONFIG_IDF_TARGET_ESP32
#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_NIMBLE_MAX_CONNECTIONS, CONFIG_BTDM_CTRL_BLE_MAX_CONN)
#elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3)
#define BLE_MESH_MAX_CONN MIN(CONFIG_BT_NIMBLE_MAX_CONNECTIONS, (CONFIG_BT_CTRL_BLE_MAX_ACT - 2))
#elif (CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || \
CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61)
#define BLE_MESH_MAX_CONN CONFIG_BT_NIMBLE_MAX_CONNECTIONS
#else
/* default setting */
#define BLE_MESH_MAX_CONN 1
#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_GAP_ADV_MAX_LEN 31
#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
#define BLE_MESH_ADV_PHY_CODED 3
#define BLE_MESH_ADV_PHY_OPTION_NO_PREFER 0
#define BLE_MESH_ADV_PHY_OPTION_PREFER_S2 1
#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 */
#define BLE_MESH_ADDR_PUBLIC 0x00
#define BLE_MESH_ADDR_RANDOM 0x01
@@ -43,16 +98,35 @@ extern "C" {
#define BLE_MESH_ADDR_LEN 0x06
/* Advertising types */
#if !CONFIG_BLE_MESH_USE_BLE_50
#define BLE_MESH_ADV_IND 0x00
#define BLE_MESH_ADV_DIRECT_IND 0x01
#define BLE_MESH_ADV_SCAN_IND 0x02
#define BLE_MESH_ADV_NONCONN_IND 0x03
#define BLE_MESH_ADV_DIRECT_IND_LOW_DUTY 0x04
#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)
#define BLE_MESH_ADV_NONCONN_IND (0x10)
#define BLE_MESH_ADV_DIRECT_IND_LOW_DUTY (0x1b)
#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
@@ -400,6 +474,45 @@ 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;
/** Advertising Packages Number */
uint16_t adv_count;
/** Advertising Primary PHY */
uint8_t primary_phy;
/** Advertising Secondary PHY */
uint8_t secondary_phy;
int8_t tx_power;
uint8_t include_tx_power : 1;
#endif
};
#define ADV_TASK_ADV_INST_EVT(inst_id) BIT(inst_id)
enum bt_mesh_adv_inst_type {
BLE_MESH_ADV_INST,
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
BLE_MESH_ADV_PROXY_INST,
#endif
#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE
BLE_MESH_RELAY_ADV_INST,
#endif
#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE
BLE_MESH_BLE_ADV_INST,
#endif
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
BLE_MESH_ADV_INST_TYPES_NUM,
};
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
@@ -441,7 +554,7 @@ struct bt_mesh_scan_param {
/** Scan interval (N * 0.625 ms) */
uint16_t interval;
/** Scan window (N * 0.625 ms) */
/** Uncoded phy Scan window (N * 0.625 ms) */
uint16_t window;
/** BLE scan filter policy */
@@ -453,21 +566,40 @@ struct bt_mesh_conn {
bt_mesh_atomic_t ref;
};
/* BLE Mesh advertising report */
struct bt_mesh_adv_report {
/* Advertiser LE address and type. */
bt_mesh_addr_t addr;
/* Strength of advertiser signal. */
int8_t rssi;
/* Type of advertising response from advertiser. */
uint8_t adv_type;
/* Buffer containing advertiser data. */
struct net_buf_simple adv_data;
#if CONFIG_BLE_MESH_USE_BLE_50
/* Primary advertising PHY */
uint8_t primary_phy;
/* Secondary advertising PHY */
uint8_t secondary_phy;
uint8_t tx_power;
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
};
/** @typedef bt_mesh_scan_cb_t
* @brief Callback type for reporting LE scan results.
*
* A function of this type is given to the bt_le_scan_start() function
* and will be called for any discovered LE device.
*
* @param addr Advertiser LE address and type.
* @param rssi Strength of advertiser signal.
* @param adv_type Type of advertising response from advertiser.
* @param data Buffer containing advertiser data.
* @param scan_rsp_len Scan Response data length.
* @param adv_rpt: BLE Mesh advertising report.
*/
typedef void bt_mesh_scan_cb_t(const bt_mesh_addr_t *addr, int8_t rssi,
uint8_t adv_type, struct net_buf_simple *buf,
uint8_t scan_rsp_len);
typedef void bt_mesh_scan_cb_t(struct bt_mesh_adv_report *adv_rpt);
/* @typedef bt_mesh_dh_key_cb_t
* @brief Callback type for DH Key calculation.
@@ -684,6 +816,21 @@ struct bt_mesh_gatt_attr {
int bt_mesh_host_init(void);
int bt_mesh_host_deinit(void);
#if CONFIG_BLE_MESH_USE_BLE_50
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,
const struct bt_mesh_adv_data *sd, size_t sd_len);
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
int bt_mesh_ble_ext_adv_start(const uint8_t inst_id,
const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *adv_data);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
int bt_le_ext_adv_stop(uint8_t inst_id);
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
int bt_le_adv_start(const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *ad, size_t ad_len,
const struct bt_mesh_adv_data *sd, size_t sd_len);
@@ -691,9 +838,10 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *data);
#endif
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
int bt_le_adv_stop(void);
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t cb);
@@ -785,20 +933,6 @@ void bt_mesh_gatt_deinit(void);
void bt_mesh_adapt_init(void);
void bt_mesh_set_private_key(const uint8_t pri_key[32]);
const uint8_t *bt_mesh_pub_key_get(void);
bool bt_mesh_check_public_key(const uint8_t key[64]);
int bt_mesh_dh_key_gen(const uint8_t remote_pub_key[64], uint8_t dhkey[32]);
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
enum {
BLE_MESH_EXCEP_LIST_SUB_CODE_ADD = 0,
BLE_MESH_EXCEP_LIST_SUB_CODE_REMOVE,
@@ -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)
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+185 -84
View File
@@ -13,6 +13,7 @@
#include "crypto.h"
#include "adv.h"
#include "net.h"
#include "scan.h"
#include "mesh.h"
#include "lpn.h"
@@ -26,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"
@@ -36,7 +36,7 @@
#endif /* CONFIG_BLE_MESH_V11_SUPPORT */
/* Minimum valid Mesh Network PDU length. The Network headers
* themselves take up 9 bytes. After that there is a minumum of 1 byte
* themselves take up 9 bytes. After that there is a minimum of 1 byte
* payload for both CTL=1 and CTL=0 PDUs (smallest OpCode is 1 byte). CTL=1
* PDUs must use a 64-bit (8 byte) NetMIC, whereas CTL=0 PDUs have at least
* a 32-bit (4 byte) NetMIC and AppMIC giving again a total of 8 bytes.
@@ -896,6 +896,9 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
uint16_t dst = 0U;
int err = 0;
/* The variable is not used when proxy server or proxy client is disabled. */
ARG_UNUSED(dst);
BT_DBG("NetResend");
BT_DBG("NetIdx 0x%04x NewKey %u Len %u Tag 0x%02x",
sub->net_idx, new_key, buf->len, tx_tag);
@@ -970,18 +973,22 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
return err;
}
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
bt_mesh_proxy_server_relay(&buf->b, dst) &&
BLE_MESH_ADDR_IS_UNICAST(dst)) {
/* TODO:
* Find a way to determine how the message was sent previously
* during a retransmission, to avoid ineffective advertising.
*/
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
if (bt_mesh_proxy_server_relay(&buf->b, dst) &&
BLE_MESH_ADDR_IS_UNICAST(dst) &&
bt_mesh_proxy_server_find_client_by_addr(dst)) {
send_cb_finalize(cb, cb_data);
return 0;
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) &&
bt_mesh_proxy_client_relay(&buf->b, dst)) {
send_cb_finalize(cb, cb_data);
return 0;
}
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
bt_mesh_proxy_client_relay(&buf->b, dst);
#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
bt_mesh_adv_send(buf, BLE_MESH_ADV(buf)->xmit, cb, cb_data);
@@ -1107,6 +1114,7 @@ static void bt_mesh_net_adv_xmit_update(struct bt_mesh_net_tx *tx)
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
const struct bt_mesh_send_cb *send_cb = cb;
uint8_t bearer = BLE_MESH_ALL_BEARERS;
int err = 0;
@@ -1173,31 +1181,50 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
* shall drop all messages secured using the friendship security
* credentials."
*/
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
(bearer & BLE_MESH_GATT_BEARER) &&
(tx->ctx->send_ttl != 1U ||
bt_mesh_tag_relay(tx->ctx->send_tag)) &&
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
if ((bearer & BLE_MESH_GATT_BEARER) &&
(tx->ctx->send_ttl != 1U || bt_mesh_tag_relay(tx->ctx->send_tag)) &&
tx->ctx->send_cred != BLE_MESH_FRIENDSHIP_CRED) {
if (bt_mesh_proxy_server_relay(&buf->b, tx->ctx->addr) &&
BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
/* Notify completion if this only went
* through the Mesh Proxy.
/* When the destination address is identified as a proxy client
* address, the message will be sent only to the proxy client.
* This action will enhance the efficiency of the proxy server
* in sending data packets.
*
* It should be noted that this approach does not significantly
* reduce the number of advertising packets in the air, as other
* proxy clients may receive the message and resend it through
* a advertising method.
*/
if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) {
send_cb_finalize(cb, cb_data);
if (bt_mesh_proxy_server_find_client_by_addr(tx->ctx->addr)) {
BT_DBG("ProxyClientFound");
err = 0;
send_cb_finalize(send_cb, cb_data);
send_cb = NULL;
goto done;
}
/* Finalize transmission if this only went through GATT bearer */
if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) {
send_cb_finalize(send_cb, cb_data);
send_cb = NULL;
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
/* This message will not be transmitted by proxy client */
if (!bt_mesh_proxy_client_get_conn_count()) {
BT_DBG("ProxyClientNoConn");
goto done;
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
}
}
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) &&
(bearer & BLE_MESH_GATT_BEARER) &&
(tx->ctx->send_ttl != 1U ||
bt_mesh_tag_relay(tx->ctx->send_tag)) &&
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
if ((bearer & BLE_MESH_GATT_BEARER) &&
(tx->ctx->send_ttl != 1U || bt_mesh_tag_relay(tx->ctx->send_tag)) &&
tx->ctx->send_cred != BLE_MESH_FRIENDSHIP_CRED) {
if (bt_mesh_proxy_client_relay(&buf->b, tx->ctx->addr)) {
BT_DBG("ProxyClientRelay");
@@ -1207,45 +1234,49 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
* connection has been created with Proxy Client, here we will
* use advertising bearer for the messages.
*/
send_cb_finalize(cb, cb_data);
if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) {
send_cb_finalize(send_cb, cb_data);
send_cb = NULL;
goto done;
}
err = 0;
goto done;
/* GATT bearer sends faster than ADV bearer, so the remote node
* may receive the message and respond before ADV bearer starts.
* To avoid issues where the start callback hasn't been called
* when the response arrives, we call the start callback here
* immediately after GATT bearer sends successfully. The ADV
* bearer will skip start callback since the flag is set.
*/
BLE_MESH_SEND_START_CB(buf, 0, 0, send_cb, cb_data);
}
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
/* Deliver to local network interface if necessary */
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->ctx->addr) || bt_mesh_elem_find(tx->ctx->addr))) {
/**
* If the target address isn't a unicast address, then the callback function
* will be called by `adv task` in place of here, to avoid the callback function
* being called twice.
/* If the target address isn't a unicast address, then the callback
* function will be called by mesh adv task instead of called here
* to avoid the callback function being called twice.
* See BLEMESH24-76 for more details.
*/
if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
if (cb && cb->start) {
cb->start(0, 0, cb_data);
}
BLE_MESH_SEND_START_CB(buf, 0, 0, send_cb, cb_data);
net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
if (cb && cb->end) {
cb->end(0, cb_data);
if (send_cb && send_cb->end) {
send_cb->end(0, cb_data);
}
bt_mesh_net_local();
err = 0;
goto done;
} else {
net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
bt_mesh_net_local();
}
err = 0;
net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
bt_mesh_net_local();
}
if ((bearer & BLE_MESH_ADV_BEARER) &&
@@ -1264,8 +1295,6 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
bt_mesh_net_adv_xmit_update(tx);
bt_mesh_adv_send(buf, tx->xmit, cb, cb_data);
err = 0;
goto done;
}
@@ -1740,16 +1769,56 @@ 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);
#else
#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 /* CONFIG_BLE_MESH_LONG_PACKET */
{
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 /* CONFIG_BLE_MESH_EXT_ADV */
{
buf = bt_mesh_adv_create(BLE_MESH_ADV_DATA, K_NO_WAIT);
}
#else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */
/* Check if the number of relay packets in queue is too large, if so
* use minimum relay retransmit value for later relay packets.
*/
if (bt_mesh_get_stored_relay_count() >= MAX_STORED_RELAY_COUNT) {
xmit = BLE_MESH_TRANSMIT(0, 20);
}
buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_DATA, K_NO_WAIT);
#endif
#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 /* CONFIG_BLE_MESH_LONG_PACKET */
{
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 /* CONFIG_BLE_MESH_EXT_ADV */
{
buf = bt_mesh_adv_create(BLE_MESH_ADV_RELAY_DATA, K_NO_WAIT);
}
#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */
if (!buf) {
BT_INFO("Out of relay buffers");
@@ -1816,8 +1885,8 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
* shall drop all messages secured using the friendship security
* credentials.
*/
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
(bearer & BLE_MESH_GATT_BEARER) &&
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
if ((bearer & BLE_MESH_GATT_BEARER) &&
((bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED &&
cred != BLE_MESH_FRIENDSHIP_CRED) ||
#if CONFIG_BLE_MESH_PRB_SRV
@@ -1827,11 +1896,15 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED)) {
if (bt_mesh_proxy_server_relay(&buf->b, rx->ctx.recv_dst) &&
BLE_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) {
/* Not relay if only GATT bearer is chosen or found Proxy Client */
if (((bearer & (~BLE_MESH_GATT_BEARER)) == 0) ||
bt_mesh_proxy_server_find_client_by_addr(rx->ctx.recv_dst)) {
BT_DBG("ProxyNotRelay");
goto done;
}
}
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */
if (((bearer & BLE_MESH_ADV_BEARER) && relay_to_adv(rx->net_if)) ||
netkey_changed ||
@@ -1988,60 +2061,85 @@ static bool ignore_net_msg(uint16_t src, uint16_t dst)
return false;
}
void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi,
enum bt_mesh_net_if net_if)
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 bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi };
struct net_buf_simple_state state = {0};
struct net_buf_simple *buf = NULL;
BT_DBG("rssi %d net_if %u", 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;
}
if (ignore_net_msg(rx.ctx.addr, rx.ctx.recv_dst)) {
return;
BT_DBG("rssi %d net_if %u", rx->ctx.recv_rssi, net_if);
if (bt_mesh_net_decode(data, net_if, rx, buf)) {
BT_DBG("DecodeFailed");
goto free_net_msg_buf;
}
BT_DBG("NetRecv, Src 0x%04x Dst 0x%04x Rssi %d NetIf %u",
rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_rssi, net_if);
if (ignore_net_msg(rx->ctx.addr, rx->ctx.recv_dst)) {
BT_DBG("IgnoreNetMsg");
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_DBG("NetRecv, Src 0x%04x Dst 0x%04x Rssi %d NetIf %u",
rx.ctx.addr, rx.ctx.recv_dst, rx.ctx.recv_rssi, net_if);
rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_rssi, net_if);
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));
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));
/* 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
* corresponding subnet.
*/
rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) ||
bt_mesh_fixed_direct_match(rx.sub, rx.ctx.recv_dst) ||
bt_mesh_elem_find(rx.ctx.recv_dst));
rx->local_match = (bt_mesh_fixed_group_match(rx->ctx.recv_dst) ||
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 &&
#endif /* CONFIG_BLE_MESH_PRB_SRV */
net_if == BLE_MESH_NET_IF_PROXY) {
bt_mesh_proxy_server_addr_add(data, rx.ctx.addr);
BT_DBG("ProxyServerAddrAdd");
bt_mesh_proxy_server_addr_add(data, rx->ctx.addr);
if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_DISABLED &&
!rx.local_match) {
!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
@@ -2052,12 +2150,12 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi,
* tag the Network PDU with the immutable-credentials tag.
*/
#if CONFIG_BLE_MESH_DF_SRV
if (rx.sub->directed_proxy == BLE_MESH_DIRECTED_PROXY_ENABLED &&
rx.sub->use_directed == BLE_MESH_PROXY_USE_DIRECTED_ENABLED &&
!bt_mesh_addr_in_uar(&rx.sub->proxy_client_uar, rx.ctx.addr) &&
!bt_mesh_proxy_server_find_client_by_addr(rx.ctx.addr)) {
rx.ctx.recv_tag |= BLE_MESH_TAG_IMMUTABLE_CRED;
if (rx->sub->directed_proxy == BLE_MESH_DIRECTED_PROXY_ENABLED &&
rx->sub->use_directed == BLE_MESH_PROXY_USE_DIRECTED_ENABLED &&
!bt_mesh_addr_in_uar(&rx->sub->proxy_client_uar, rx->ctx.addr) &&
!bt_mesh_proxy_server_find_client_by_addr(rx->ctx.addr)) {
BT_DBG("ImmutableCredTag");
rx->ctx.recv_tag |= BLE_MESH_TAG_IMMUTABLE_CRED;
}
#endif /* CONFIG_BLE_MESH_DF_SRV */
}
@@ -2069,25 +2167,28 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi,
* 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;
msg_cache[rx->msg_cache_idx].src = BLE_MESH_ADDR_UNASSIGNED;
/* Rewind the next index now that we're not using this entry */
msg_cache_next = rx.msg_cache_idx;
msg_cache_next = rx->msg_cache_idx;
}
/* Relay if this was a group/virtual address, or if the destination
* was neither a local element nor an LPN we're Friends for.
*/
if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) ||
(!rx.local_match && !rx.friend_match
if (!BLE_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst) ||
(!rx->local_match && !rx->friend_match
#if CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG
&& !rx.replay_msg
&& !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)
+19 -2
View File
@@ -465,8 +465,25 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi,
enum bt_mesh_net_if net_if);
void bt_mesh_generic_net_recv(struct net_buf_simple *data,
struct bt_mesh_net_rx *rx,
enum bt_mesh_net_if net_if);
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 = {0};
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);
}
bool bt_mesh_primary_subnet_exist(void);
File diff suppressed because it is too large Load Diff
+20 -18
View File
@@ -616,7 +616,7 @@ int bt_mesh_input_string(const char *str)
static void send_pub_key(void)
{
const uint8_t *key = NULL;
uint8_t pub_key[64] = {0};
uint8_t dhkey[32] = {0};
PROV_BUF(buf, 65);
@@ -625,8 +625,8 @@ static void send_pub_key(void)
* buffer as a temporary storage location. The validating
* of the remote public key is finished when it is received.
*/
sys_memcpy_swap(buf.data, &prov_link.conf_inputs[17], 32);
sys_memcpy_swap(&buf.data[32], &prov_link.conf_inputs[49], 32);
memcpy(buf.data, &prov_link.conf_inputs[17], 32);
memcpy(&buf.data[32], &prov_link.conf_inputs[49], 32);
if (bt_mesh_dh_key_gen(buf.data, dhkey)) {
BT_ERR("Unable to generate DHKey");
@@ -634,26 +634,25 @@ static void send_pub_key(void)
return;
}
sys_memcpy_swap(prov_link.dhkey, dhkey, 32);
memcpy(prov_link.dhkey, dhkey, 32);
BT_DBG("DHkey: %s", bt_hex(prov_link.dhkey, 32));
bt_mesh_atomic_set_bit(prov_link.flags, HAVE_DHKEY);
key = bt_mesh_pub_key_get();
if (!key) {
if (bt_mesh_pub_key_copy(pub_key)) {
BT_ERR("No public key available");
close_link(PROV_ERR_UNEXP_ERR);
return;
}
BT_DBG("Local Public Key: %s", bt_hex(key, 64));
BT_DBG("Local Public Key: %s", bt_hex(pub_key, 64));
bt_mesh_prov_buf_init(&buf, PROV_PUB_KEY);
/* Swap X and Y halves independently to big-endian */
sys_memcpy_swap(net_buf_simple_add(&buf, 32), key, 32);
sys_memcpy_swap(net_buf_simple_add(&buf, 32), &key[32], 32);
/* Public key is already in big-endian format from bt_mesh_pub_key_copy() */
memcpy(net_buf_simple_add(&buf, 32), pub_key, 32);
memcpy(net_buf_simple_add(&buf, 32), &pub_key[32], 32);
memcpy(&prov_link.conf_inputs[81], &buf.data[1], 64);
@@ -673,8 +672,8 @@ static int bt_mesh_calc_dh_key(void)
/* Copy remote key in little-endian for generating DHKey.
* X and Y halves are swapped independently.
*/
sys_memcpy_swap(&pub_key[0], &prov_link.conf_inputs[17], 32);
sys_memcpy_swap(&pub_key[32], &prov_link.conf_inputs[49], 32);
memcpy(&pub_key[0], &prov_link.conf_inputs[17], 32);
memcpy(&pub_key[32], &prov_link.conf_inputs[49], 32);
if (bt_mesh_dh_key_gen(pub_key, dhkey)) {
BT_ERR("Unable to generate DHKey");
@@ -682,7 +681,7 @@ static int bt_mesh_calc_dh_key(void)
return -EIO;
}
sys_memcpy_swap(prov_link.dhkey, dhkey, 32);
memcpy(prov_link.dhkey, dhkey, 32);
BT_DBG("DHkey: %s", bt_hex(prov_link.dhkey, 32));
@@ -704,6 +703,8 @@ int bt_mesh_set_oob_pub_key(const uint8_t pub_key_x[32],
const uint8_t pub_key_y[32],
const uint8_t pri_key[32])
{
uint8_t privkey[32] = {0};
if (!pub_key_x || !pub_key_y || !pri_key) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
@@ -715,7 +716,8 @@ int bt_mesh_set_oob_pub_key(const uint8_t pub_key_x[32],
*/
sys_memcpy_swap(&prov_link.conf_inputs[81], pub_key_x, 32);
sys_memcpy_swap(&prov_link.conf_inputs[81] + 32, pub_key_y, 32);
bt_mesh_set_private_key(pri_key);
sys_memcpy_swap(privkey, pri_key, 32);
bt_mesh_set_private_key(privkey);
bt_mesh_atomic_set_bit(prov_link.flags, OOB_PUB_KEY);
@@ -1509,6 +1511,9 @@ int bt_mesh_pb_gatt_close(struct bt_mesh_conn *conn, uint8_t reason)
if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) {
prov_link.pb_remote_cbd = true;
prov_link.pb_remote_reset = true;
/* @todo: the close reason is disconnect reason, not the
* link close reason, should change it to link close reason?
*/
prov_link.pb_remote_close(&prov_link, reason);
}
#endif
@@ -1555,8 +1560,6 @@ static void protocol_timeout(struct k_work *work)
int bt_mesh_prov_init(void)
{
const uint8_t *key = NULL;
if (bt_mesh_prov_get() == NULL) {
BT_ERR("No provisioning context provided");
return -EINVAL;
@@ -1571,8 +1574,7 @@ int bt_mesh_prov_init(void)
__ASSERT(bt_mesh_prov_get()->uuid, "Device UUID not initialized");
key = bt_mesh_pub_key_get();
if (!key) {
if (bt_mesh_pub_key_gen()) {
BT_ERR("Failed to generate public key");
return -EIO;
}
+10 -13
View File
@@ -1764,8 +1764,8 @@ static void prov_gen_dh_key(struct bt_mesh_prov_link *link)
/* Copy public key in little-endian for generating DHKey.
* X and Y halves are swapped independently.
*/
sys_memcpy_swap(&pub_key[0], &link->conf_inputs[81], 32);
sys_memcpy_swap(&pub_key[32], &link->conf_inputs[113], 32);
memcpy(&pub_key[0], &link->conf_inputs[81], 32);
memcpy(&pub_key[32], &link->conf_inputs[113], 32);
if (bt_mesh_dh_key_gen(pub_key, dhkey)) {
BT_ERR("Failed to generate DHKey");
@@ -1773,7 +1773,7 @@ static void prov_gen_dh_key(struct bt_mesh_prov_link *link)
return;
}
sys_memcpy_swap(link->dhkey, dhkey, 32);
memcpy(link->dhkey, dhkey, 32);
BT_DBG("DHKey: %s", bt_hex(link->dhkey, 32));
@@ -1847,23 +1847,22 @@ static void prov_gen_dh_key(struct bt_mesh_prov_link *link)
static void send_pub_key(struct bt_mesh_prov_link *link)
{
const uint8_t *key = NULL;
uint8_t pub_key[64] = {0};
PROV_BUF(buf, 65);
key = bt_mesh_pub_key_get();
if (!key) {
if (bt_mesh_pub_key_copy(pub_key)) {
BT_ERR("No public key available");
close_link(link, CLOSE_REASON_FAILED);
return;
}
BT_DBG("Local Public Key: %s", bt_hex(key, 64));
BT_DBG("Local Public Key: %s", bt_hex(pub_key, 64));
bt_mesh_prov_buf_init(&buf, PROV_PUB_KEY);
/* Swap X and Y halves independently to big-endian */
sys_memcpy_swap(net_buf_simple_add(&buf, 32), key, 32);
sys_memcpy_swap(net_buf_simple_add(&buf, 32), &key[32], 32);
/* Public key is already in big-endian format from bt_mesh_pub_key_copy() */
memcpy(net_buf_simple_add(&buf, 32), pub_key, 32);
memcpy(net_buf_simple_add(&buf, 32), &pub_key[32], 32);
/* Store provisioner public key value in conf_inputs */
memcpy(&link->conf_inputs[17], &buf.data[1], 64);
@@ -2819,7 +2818,6 @@ static void protocol_timeout(struct k_work *work)
int bt_mesh_provisioner_prov_init(void)
{
const uint8_t *key = NULL;
int i;
if (bt_mesh_prov_get() == NULL) {
@@ -2827,8 +2825,7 @@ int bt_mesh_provisioner_prov_init(void)
return -EINVAL;
}
key = bt_mesh_pub_key_get();
if (!key) {
if (bt_mesh_pub_key_gen()) {
BT_ERR("Failed to generate Public Key");
return -EIO;
}
@@ -893,6 +893,25 @@ int bt_mesh_proxy_client_disconnect(uint8_t conn_handle)
return 0;
}
uint16_t bt_mesh_proxy_client_get_conn_count(void)
{
uint16_t count = 0;
for (size_t i = 0; i < ARRAY_SIZE(servers); i++) {
struct bt_mesh_proxy_server *server = &servers[i];
if (!server->conn || server->conn_type != CLI_PROXY) {
continue;
}
count++;
}
BT_DBG("ProxyClientGetConnCount, Count %u", count);
return count;
}
bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst)
{
bool send = false;
@@ -104,6 +104,8 @@ int bt_mesh_proxy_client_disconnect(uint8_t conn_handle);
bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub, bool private);
uint16_t bt_mesh_proxy_client_get_conn_count(void);
bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst);
int bt_mesh_proxy_client_cfg_send(uint8_t conn_handle, uint16_t net_idx,
+97 -18
View File
@@ -29,12 +29,16 @@
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
#if !CONFIG_BLE_MESH_BQB_TEST
#if !CONFIG_BLE_MESH_BQB_TEST && !CONFIG_BLE_MESH_PROXY_CLI_SRV_COEXIST && !CONFIG_BLE_MESH_RPR_SRV
/* Not support enabling Proxy Client and Proxy Server simultaneously */
_Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)),
"Not support Proxy Server and Proxy Client simultaneously");
#endif
#if CONFIG_BLE_MESH_USE_BLE_50
static uint8_t proxy_adv_inst = BLE_MESH_ADV_INST_UNUSED;
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
#define ADV_OPT (BLE_MESH_ADV_OPT_CONNECTABLE | BLE_MESH_ADV_OPT_ONE_TIME)
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER && \
@@ -52,12 +56,30 @@ 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
};
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
};
static bool proxy_adv_enabled;
@@ -164,6 +186,13 @@ static void proxy_sar_timeout(struct k_work *work)
bt_mesh_gatts_disconnect(client->conn, 0x13);
}
void bt_mesh_proxy_server_adv_flag_set(bool enable)
{
BT_DBG("ProxyServerAdvFlagSet, Enable %u/%u", proxy_adv_enabled, enable);
proxy_adv_enabled = enable;
}
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
/* The following callbacks are used to notify proper information
* to the application layer.
@@ -900,7 +929,9 @@ static void proxy_connected(struct bt_mesh_conn *conn, uint8_t err)
conn_count++;
/* Since we use ADV_OPT_ONE_TIME */
proxy_adv_enabled = false;
#if !CONFIG_BLE_MESH_USE_BLE_50
bt_mesh_proxy_server_adv_flag_set(false);
#endif /* !CONFIG_BLE_MESH_USE_BLE_50 */
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX
/* Before re-enabling advertising, stop advertising
@@ -1104,7 +1135,6 @@ int bt_mesh_proxy_server_prov_enable(void)
}
}
return 0;
}
@@ -1572,14 +1602,19 @@ static int node_id_adv(struct bt_mesh_subnet *sub)
memcpy(proxy_svc_data + 3, tmp + 8, 8);
proxy_sd_len = gatt_proxy_adv_create(&proxy_sd);
err = bt_le_adv_start(&fast_adv_param, node_id_ad,
ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len);
#if CONFIG_BLE_MESH_USE_BLE_50
err = bt_le_ext_adv_start(proxy_adv_inst, &fast_adv_param, node_id_ad,
ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len);
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
err = bt_le_adv_start(&fast_adv_param, node_id_ad,
ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len);
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
if (err) {
BT_WARN("Failed to advertise using Node ID (err %d)", err);
return err;
}
proxy_adv_enabled = true;
bt_mesh_proxy_server_adv_flag_set(true);
return 0;
}
@@ -1598,14 +1633,19 @@ static int net_id_adv(struct bt_mesh_subnet *sub)
memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8);
proxy_sd_len = gatt_proxy_adv_create(&proxy_sd);
err = bt_le_adv_start(&slow_adv_param, net_id_ad,
ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len);
#if CONFIG_BLE_MESH_USE_BLE_50
err = bt_le_ext_adv_start(proxy_adv_inst, &slow_adv_param, net_id_ad,
ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len);
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
err = bt_le_adv_start(&slow_adv_param, net_id_ad,
ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len);
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
if (err) {
BT_WARN("Failed to advertise using Network ID (err %d)", err);
return err;
}
proxy_adv_enabled = true;
bt_mesh_proxy_server_adv_flag_set(true);
return 0;
}
@@ -1681,7 +1721,7 @@ static int private_node_id_adv(struct bt_mesh_subnet *sub)
return err;
}
proxy_adv_enabled = true;
bt_mesh_proxy_server_adv_flag_set(true);
return 0;
}
@@ -1731,7 +1771,7 @@ static int private_net_id_adv(struct bt_mesh_subnet *sub)
return err;
}
proxy_adv_enabled = true;
bt_mesh_proxy_server_adv_flag_set(true);
return 0;
}
@@ -1855,6 +1895,7 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
&& sub->private_node_id == BLE_MESH_PRIVATE_NODE_IDENTITY_STOPPED
#endif /* CONFIG_BLE_MESH_PRB_SRV */
) {
/* advertising node identity forever */
if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) {
net_id_adv(sub);
}
@@ -1980,11 +2021,19 @@ static int32_t solic_adv_private_net_id(void)
int32_t bt_mesh_proxy_server_adv_start(void)
{
BT_DBG("ProxyServerAdvStart");
if (gatt_svc == MESH_GATT_NONE) {
BT_DBG("GattSvcNone");
return K_FOREVER;
}
#if CONFIG_BLE_MESH_USE_BLE_50
if (proxy_adv_inst == BLE_MESH_ADV_INST_UNUSED) {
BT_DBG("ProxyAdvInstUnused");
return K_FOREVER;
}
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
#if CONFIG_BLE_MESH_PB_GATT
BT_DBG("ProvFastAdv %u", prov_fast_adv);
@@ -1993,7 +2042,7 @@ int32_t bt_mesh_proxy_server_adv_start(void)
}
if (!bt_mesh_is_provisioned()) {
const struct bt_mesh_adv_param *param;
const struct bt_mesh_adv_param *param = NULL;
struct bt_mesh_adv_data prov_sd[2];
size_t prov_sd_len;
@@ -2007,9 +2056,14 @@ int32_t bt_mesh_proxy_server_adv_start(void)
prov_sd_len = gatt_prov_adv_create(prov_sd);
#if CONFIG_BLE_MESH_USE_BLE_50
if (bt_le_ext_adv_start(proxy_adv_inst, param, prov_ad, ARRAY_SIZE(prov_ad),
prov_sd, prov_sd_len) == 0) {
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad),
prov_sd, prov_sd_len) == 0) {
proxy_adv_enabled = true;
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
bt_mesh_proxy_server_adv_flag_set(true);
/* Advertise 60 seconds using fast interval */
if (prov_fast_adv) {
@@ -2039,25 +2093,38 @@ int32_t bt_mesh_proxy_server_adv_start(void)
}
#endif /* GATT_PROXY */
/* used to indicate proxy advertising could be stopped */
return K_FOREVER;
}
void bt_mesh_proxy_server_adv_stop(void)
int bt_mesh_proxy_server_adv_stop(void)
{
int err = 0;
BT_DBG("ProxyServerAdvStop, Enabled %u", proxy_adv_enabled);
if (!proxy_adv_enabled) {
return;
return -EALREADY;
}
#if CONFIG_BLE_MESH_USE_BLE_50
if (proxy_adv_inst == BLE_MESH_ADV_INST_UNUSED) {
BT_ERR("Proxy adv inst is not initialized!");
return -EINVAL;
}
err = bt_le_ext_adv_stop(proxy_adv_inst);
#else /* CONFIG_BLE_MESH_USE_BLE_50 */
err = bt_le_adv_stop();
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
if (err) {
BT_ERR("Failed to stop advertising (err %d)", err);
} else {
proxy_adv_enabled = false;
return -EINVAL;
}
bt_mesh_proxy_server_adv_flag_set(false);
return 0;
}
static struct bt_mesh_conn_cb conn_callbacks = {
@@ -2071,6 +2138,14 @@ int bt_mesh_proxy_server_init(void)
BT_DBG("ProxyServerInit");
#if CONFIG_BLE_MESH_USE_BLE_50
#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV
proxy_adv_inst = CONFIG_BLE_MESH_PROXY_ADV_INST_ID;
#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
proxy_adv_inst = CONFIG_BLE_MESH_ADV_INST_ID;
#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
bt_mesh_gatts_service_register(&proxy_svc);
#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */
@@ -2113,7 +2188,11 @@ int bt_mesh_proxy_server_deinit(void)
BT_DBG("ProxyServerDeinit");
proxy_adv_enabled = false;
#if CONFIG_BLE_MESH_USE_BLE_50
proxy_adv_inst = BLE_MESH_ADV_INST_UNUSED;
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
bt_mesh_proxy_server_adv_flag_set(false);
gatt_svc = MESH_GATT_NONE;
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
@@ -12,6 +12,7 @@
#include "net.h"
#include "mesh/adapter.h"
#include "adv.h"
#ifdef __cplusplus
extern "C" {
@@ -94,7 +95,7 @@ void bt_mesh_proxy_server_beacon_send(struct bt_mesh_subnet *sub);
struct net_buf_simple *bt_mesh_proxy_server_get_buf(void);
int32_t bt_mesh_proxy_server_adv_start(void);
void bt_mesh_proxy_server_adv_stop(void);
int bt_mesh_proxy_server_adv_stop(void);
void bt_mesh_proxy_server_update_net_id_rand(void);
void bt_mesh_proxy_server_update_net_id_rand_stop(void);
@@ -117,6 +118,7 @@ void bt_mesh_proxy_server_identity_stop(struct bt_mesh_subnet *sub);
bool bt_mesh_proxy_server_relay(struct net_buf_simple *buf, uint16_t dst);
void bt_mesh_proxy_server_addr_add(struct net_buf_simple *buf, uint16_t addr);
void bt_mesh_proxy_server_adv_flag_set(bool enable);
int bt_mesh_proxy_server_init(void);
int bt_mesh_proxy_server_deinit(void);
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+172 -53
View File
@@ -41,6 +41,22 @@
#define PROXY_SVC_DATA_LEN_PRIVATE_NET_ID 0x11
#define PROXY_SVC_DATA_LEN_PRIVATE_NODE_ID 0x11
static struct bt_mesh_scan_param scan_param = {
#if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
.type = BLE_MESH_SCAN_ACTIVE,
#else /* CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */
.type = BLE_MESH_SCAN_PASSIVE,
#endif /* CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */
#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE,
#else /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE,
#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */
.interval = SCAN_INTERVAL,
.window = SCAN_WINDOW,
.scan_fil_policy = BLE_MESH_SP_ADV_ALL,
};
#if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV)
static const bt_mesh_addr_t *unprov_dev_addr;
static uint8_t current_adv_type;
@@ -385,14 +401,33 @@ int bt_mesh_stop_ble_scan(void)
return 0;
}
bool bt_mesh_ble_scan_state_get(void)
{
BT_DBG("BLEScanEn %u", ble_scan_en);
return ble_scan_en;
}
static void inline callback_ble_adv_pkt(const bt_mesh_addr_t *addr,
uint8_t adv_type, uint8_t data[],
uint16_t length, int8_t rssi)
{
#if !CONFIG_BLE_MESH_USE_BLE_50
bt_mesh_ble_adv_report_t adv_rpt = {0};
if (ble_scan_en) {
memcpy(adv_rpt.addr, addr->val, BD_ADDR_LEN);
adv_rpt.addr_type = addr->type;
adv_rpt.adv_type = adv_type;
adv_rpt.length = length;
adv_rpt.data = length ? data : NULL;
adv_rpt.rssi = rssi;
BT_DBG("CallbackBLEAdvPkt, AdvType 0x%02x Len %u", adv_type, length);
bt_mesh_ble_scan_cb_evt_to_btc(addr, adv_type, data, length, rssi);
bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt);
}
#endif /* !CONFIG_BLE_MESH_USE_BLE_50 */
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
@@ -416,11 +451,11 @@ static bool rpr_ext_scan_handle_adv_pkt(const bt_mesh_addr_t *addr,
}
#endif /* CONFIG_BLE_MESH_RPR_SRV */
static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
int8_t rssi, uint8_t adv_type,
struct net_buf_simple *buf,
uint8_t scan_rsp_len)
static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt)
{
struct net_buf_simple *buf = &adv_rpt->adv_data;
struct net_buf_simple_state buf_state = {0};
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \
CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \
@@ -432,10 +467,26 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
uint16_t adv_len = buf->len;
#endif /* (CONFIG_BLE_MESH_RPR_SRV || CONFIG_BLE_MESH_SUPPORT_BLE_SCAN) */
if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) {
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
net_buf_simple_save(buf, &buf_state);
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_EXT_ADV
&& adv_rpt->adv_type != BLE_MESH_EXT_ADV_NONCONN_IND
#endif
#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
&& adv_rpt->adv_type != BLE_MESH_ADV_SCAN_RSP
#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */
) {
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
net_buf_simple_restore(buf, &buf_state);
return;
}
@@ -443,9 +494,24 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len));
#if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV)
unprov_dev_addr = addr;
current_adv_type = adv_type;
#endif
unprov_dev_addr = &adv_rpt->addr;
current_adv_type = adv_rpt->adv_type;
#endif /* (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) */
#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
if (adv_rpt->adv_type == BLE_MESH_ADV_SCAN_RSP) {
/* scan response is only visible for remote provisioning extend scan */
if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) {
return;
}
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
net_buf_simple_restore(buf, &buf_state);
}
#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */
while (buf->len > 1) {
struct net_buf_simple_state state;
@@ -456,8 +522,10 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
/* Check for early termination */
if (len == 0U) {
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
net_buf_simple_restore(buf, &buf_state);
return;
}
@@ -465,8 +533,10 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
BT_DBG("MalformedAD");
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
net_buf_simple_restore(buf, &buf_state);
return;
}
@@ -476,15 +546,37 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
buf->len = len - 1;
if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE ||
type == BLE_MESH_DATA_MESH_BEACON) && (adv_type != BLE_MESH_ADV_NONCONN_IND)) {
BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_type);
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
#if CONFIG_BLE_MESH_EXT_ADV
&& adv_rpt->adv_type != BLE_MESH_EXT_ADV_NONCONN_IND
#endif
)) {
BT_DBG("IgnorePkt, Type 0x%02x AdvType 0x%02x", type, adv_rpt->adv_type);
return;
}
switch (type) {
case BLE_MESH_DATA_MESH_MESSAGE:
bt_mesh_net_recv(buf, rssi, BLE_MESH_NET_IF_ADV);
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
@@ -500,7 +592,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
#endif /* CONFIG_BLE_MESH_PB_ADV */
case BLE_MESH_DATA_MESH_BEACON:
bt_mesh_beacon_recv(buf, rssi);
bt_mesh_beacon_recv(buf, adv_rpt->rssi);
break;
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
@@ -512,8 +604,10 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
BT_DBG("Adv Flags mismatch, ignore this adv pkt");
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
net_buf_simple_restore(buf, &buf_state);
return;
}
break;
@@ -523,7 +617,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
BT_DBG("Adv Service UUID mismatch, ignore this adv pkt");
#if CONFIG_BLE_MESH_RPR_SRV
if (rpr_ext_scan_handle_adv_pkt(addr, adv_data, adv_len)) {
if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) {
/* If handled as extended scan report successfully, then not
* notify to the application layer as normal BLE adv packet.
*/
@@ -532,14 +626,16 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
#endif /* CONFIG_BLE_MESH_RPR_SRV */
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
net_buf_simple_restore(buf, &buf_state);
return;
}
break;
case BLE_MESH_DATA_SVC_DATA16:
handle_adv_service_data(buf, addr, uuid, rssi);
handle_adv_service_data(buf, &adv_rpt->addr, uuid, adv_rpt->rssi);
break;
#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \
@@ -548,7 +644,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
default:
#if CONFIG_BLE_MESH_RPR_SRV
if (rpr_ext_scan_handle_adv_pkt(addr, adv_data, adv_len)) {
if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) {
/* If handled as extended scan report successfully, then not
* notify to the application layer as normal BLE adv packet.
*/
@@ -557,44 +653,22 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr,
#endif /* CONFIG_BLE_MESH_RPR_SRV */
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi);
#endif
callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
net_buf_simple_restore(buf, &buf_state);
return;
}
net_buf_simple_restore(buf, &state);
net_buf_simple_pull(buf, len);
}
#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
if (scan_rsp_len != 0) {
/**
* scan response is only visible for remote provisioning extend scan.
*/
rpr_ext_scan_handle_adv_pkt(addr, adv_data + adv_len, scan_rsp_len);
}
#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */
}
int bt_mesh_scan_enable(void)
{
int err = 0;
struct bt_mesh_scan_param scan_param = {
#if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN
.type = BLE_MESH_SCAN_ACTIVE,
#else
.type = BLE_MESH_SCAN_PASSIVE,
#endif
#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE,
#else
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE,
#endif
.interval = SCAN_INTERVAL,
.window = SCAN_WINDOW,
.scan_fil_policy = BLE_MESH_SP_ADV_ALL,
};
BT_DBG("ScanEnable");
err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
@@ -621,6 +695,51 @@ int bt_mesh_scan_disable(void)
return 0;
}
int bt_mesh_scan_param_update(struct bt_mesh_scan_param *param)
{
int err = 0;
if (param == NULL ||
param->interval == 0 ||
param->interval < param->window) {
BT_ERR("InvalidScanParam");
return -EINVAL;
}
BT_DBG("ScanParamUpdate, Type %u Interval %u Window %u",
param->type, param->interval, param->window);
scan_param.interval = param->interval;
scan_param.window = param->window;
err = bt_le_scan_stop();
if (err) {
if (err == -EALREADY) {
BT_INFO("New scan parameters will take effect after scan starts");
return 0;
}
BT_ERR("StopScanFailed, Err %d", err);
return err;
}
/* Since the user only needs to set the scan interval and scan window,
* only the interval and window parameters in the `param` are correct.
*
* For the aforementioned reason, when updating the scan parameters,
* the other parameters also need to be set correctly, and these other
* parameters are saved in the `scan_param`. Therefore, `scan_param`
* must be used instead of `param` here.
*/
err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
if (err && err != -EALREADY) {
BT_ERR("StartScanFailed, Err %d", err);
return err;
}
return 0;
}
#if CONFIG_BLE_MESH_TEST_USE_WHITE_LIST
int bt_mesh_scan_with_wl_enable(void)
{
+7 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -33,16 +33,22 @@ int bt_mesh_scan_enable(void);
int bt_mesh_scan_disable(void);
int bt_mesh_scan_param_update(struct bt_mesh_scan_param *scan_param);
int bt_mesh_scan_with_wl_enable(void);
struct bt_mesh_ble_scan_param {
uint32_t duration;
};
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
int bt_mesh_start_ble_scan(struct bt_mesh_ble_scan_param *param);
int bt_mesh_stop_ble_scan(void);
bool bt_mesh_ble_scan_state_get(void);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+300 -38
View File
@@ -77,8 +77,16 @@ _Static_assert(CONFIG_BLE_MESH_ADV_BUF_COUNT >= (CONFIG_BLE_MESH_TX_SEG_MAX + 3)
SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) : \
SEG_RETRANSMIT_TIMEOUT_GROUP)
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;
@@ -173,17 +188,49 @@ 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("SendUnseg");
BT_DBG("Src 0x%04x Dst 0x%04x AppIdx 0x%04x CtlOp 0x%02x SduLen %u",
tx->src, tx->ctx->addr, tx->ctx->app_idx,
ctl_op ? *ctl_op : 0xFF, 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) {
@@ -229,15 +276,27 @@ 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)
{
BT_DBG("Ctl %u", ctl);
uint8_t len = 0;
if (ctl) {
return BLE_MESH_CTL_SEG_SDU_MAX;
if (si->ctl) {
len =
#if CONFIG_BLE_MESH_LONG_PACKET
si->long_pkt ? BLE_MESH_EXT_CTL_SEG_SDU_MAX :
#endif
BLE_MESH_CTL_SEG_SDU_MAX;
} else {
len =
#if CONFIG_BLE_MESH_LONG_PACKET
si->long_pkt ? BLE_MESH_EXT_APP_SEG_SDU_MAX :
#endif
BLE_MESH_APP_SEG_SDU_MAX;
}
return BLE_MESH_APP_SEG_SDU_MAX;
BT_DBG("SegLen %u", len);
return len;
}
bool bt_mesh_tx_in_progress(void)
@@ -258,7 +317,14 @@ bool bt_mesh_tx_in_progress(void)
static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx)
{
BT_DBG("SegTxDone, SegIdx %u", 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,
* the `tx->seg_pending` must be decremented by one.
@@ -487,7 +553,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;
@@ -523,16 +591,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;
}
@@ -574,14 +654,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);
@@ -589,7 +698,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)) {
@@ -686,9 +795,25 @@ 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) {
if (tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
} else if (tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
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;
}
}
#else
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
#endif
BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Dst 0x%04x",
tx->sub->net_idx, tx->ctx->app_idx, tx->ctx->addr);
@@ -787,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;
@@ -1359,18 +1484,43 @@ 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);
BT_DBG("IsSduLenOK,Len:%u,SegN:%u", seg_len, seg_n);
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,
};
BT_DBG("IsSduLenOK, CTL %u SegN %u", ctl, seg_n);
#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];
BT_DBG("SegRxFind, SeqAuth 0x%llx", *seq_auth);
for (i = 0; i < rx_buf_size; i++) {
struct seg_rx *rx = &rx_buf[i];
BT_DBG("Seg%u/%u: Src 0x%04x Dst 0x%04x SeqAuth 0x%llx",
i, rx->seg_n, rx->src, rx->dst, rx->seq_auth);
if (rx->src != net_rx->ctx.addr ||
rx->dst != net_rx->ctx.recv_dst) {
@@ -1404,6 +1554,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)
{
@@ -1432,9 +1640,27 @@ 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
BT_DBG("SegRxAlloc, SegN %u", seg_n);
for (i = 0; i < rx_buf_size; i++) {
struct seg_rx *rx = &seg_rx_buf[i];
if (rx->in_use) {
continue;
@@ -1451,7 +1677,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));
@@ -1504,6 +1734,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"
@@ -1567,7 +1805,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,
@@ -1611,18 +1849,30 @@ 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) {
BT_ERR("Too large SDU len");
BT_DBG("Target len %u * %u + %u = %u",
seg_n, seg_len(&si), buf->len, rx->buf.len);
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", rx->buf.len);
send_ack(net_rx->sub, net_rx->ctx.recv_dst,
net_rx->ctx.addr, net_rx->ctx.send_ttl,
seq_auth, 0, rx->obo);
@@ -1632,8 +1882,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;
}
}
@@ -1647,9 +1898,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);
@@ -1845,11 +2096,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 = BLE_MESH_EXT_RX_SDU_MAX;
ext_seg_rx[i].buf.__buf = (ext_seg_rx_buf_data +
(i * BLE_MESH_EXT_RX_SDU_MAX));
ext_seg_rx[i].buf.data = ext_seg_rx[i].buf.__buf;
}
#endif
bt_mesh_mutex_create(&seg_rx_lock);
}
+263 -57
View File
@@ -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);
@@ -235,18 +254,50 @@ 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("SendUnseg");
BT_DBG("Src 0x%04x Dst 0x%04x AppIdx 0x%04x CtlOp 0x%02x SduLen %u",
tx->src, tx->ctx->addr, tx->ctx->app_idx,
ctl_op ? *ctl_op : 0xFF, 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) {
@@ -292,15 +343,27 @@ 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)
{
BT_DBG("Ctl %u", ctl);
uint8_t len = 0;
if (ctl) {
return BLE_MESH_CTL_SEG_SDU_MAX;
if (si->ctl) {
len =
#if CONFIG_BLE_MESH_LONG_PACKET
si->long_pkt ? BLE_MESH_EXT_CTL_SEG_SDU_MAX :
#endif
BLE_MESH_CTL_SEG_SDU_MAX;
} else {
len =
#if CONFIG_BLE_MESH_LONG_PACKET
si->long_pkt ? BLE_MESH_EXT_APP_SEG_SDU_MAX :
#endif
BLE_MESH_APP_SEG_SDU_MAX;
}
return BLE_MESH_APP_SEG_SDU_MAX;
BT_DBG("SegLen %u", len);
return len;
}
bool bt_mesh_tx_in_progress(void)
@@ -847,7 +910,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;
@@ -903,12 +968,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;
@@ -923,7 +1001,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;
}
@@ -976,13 +1054,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);
@@ -990,7 +1100,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)) {
@@ -1096,9 +1206,25 @@ 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) {
if (tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
} else if (tx->ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
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;
}
}
#else
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_tag |= BLE_MESH_TAG_SEND_SEGMENTED;
}
#endif
BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Dst 0x%04x",
tx->sub->net_idx, tx->ctx->app_idx, tx->ctx->addr);
@@ -1197,7 +1323,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;
@@ -1934,10 +2060,28 @@ 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)
{
BT_DBG("IsSduLenOK,Len:%u,SegN:%u", seg_len, seg_n);
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,
};
BT_DBG("IsSduLenOK, CTL %u SegN %u", ctl, seg_n);
#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,
@@ -1961,26 +2105,97 @@ 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 )
{
BT_DBG("SegRxFind, SeqAuth 0x%llx", *seq_auth);
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];
BT_DBG("Seg%u/%u: Src 0x%04x Dst 0x%04x SeqAuth 0x%llx",
i,rx->seg_n, rx->src, rx->dst, rx->seq_auth);
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)
{
@@ -2005,14 +2220,6 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
{
int err = 0;
<<<<<<< HEAD
<<<<<<< HEAD
for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i];
=======
<<<<<<< HEAD
=======
>>>>>>> 9fc4381f187 (fix(ble_mesh): resolve miscellaneous logging issues)
/* 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,
@@ -2033,14 +2240,7 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
for (size_t i = 0; i < rx_buf_size; i++) {
struct seg_rx *rx = &seg_rx_buf[i];
<<<<<<< HEAD
for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i];
>>>>>>> 7652269a401 (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh)
>>>>>>> bdcd87e62fa (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh)
=======
BT_DBG("SegRxAlloc, SegN %u", seg_n);
>>>>>>> 9fc4381f187 (fix(ble_mesh): resolve miscellaneous logging issues)
if (rx->in_use) {
continue;
@@ -2073,7 +2273,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));
@@ -2199,7 +2403,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,
@@ -2249,6 +2453,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).
@@ -2256,17 +2467,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;
<<<<<<< HEAD
<<<<<<< HEAD
BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(rx->ctl),
=======
<<<<<<< HEAD
=======
>>>>>>> 9fc4381f187 (fix(ble_mesh): resolve miscellaneous logging issues)
BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(&si),
>>>>>>> bdcd87e62fa (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh)
buf->len, rx->buf.len);
/* This should not happen, since we have made sure the whole
@@ -2274,19 +2477,11 @@ found_rx:
* But if the peer device sends the segments of a segmented
* message with different CTL, then the following could happen.
*/
<<<<<<< HEAD
<<<<<<< HEAD
if (rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX) {
=======
<<<<<<< HEAD
=======
>>>>>>> 9fc4381f187 (fix(ble_mesh): resolve miscellaneous logging issues)
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
) {
>>>>>>> bdcd87e62fa (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh)
BT_ERR("Too large SDU len %u/%u", rx->buf.len,
CONFIG_BLE_MESH_RX_SDU_MAX);
@@ -2299,14 +2494,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);
@@ -2517,13 +2712,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 = BLE_MESH_EXT_RX_SDU_MAX;
ext_seg_rx[i].buf.__buf = (ext_seg_rx_buf_data +
(i * BLE_MESH_EXT_RX_SDU_MAX));
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
*/
@@ -18,11 +18,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))
+7 -30
View File
@@ -35,8 +35,6 @@
#include "lpn.h"
#include "rpl.h"
#include "foundation.h"
#include <tinycrypt/hmac.h>
#include <tinycrypt/sha256.h>
#include "mesh/buf.h"
#include "mesh/slist.h"
#include "mesh/config.h"
@@ -85,19 +83,19 @@
uint8_t __meshlib_var_BLE_MESH_ADV_PROV = BLE_MESH_ADV_PROV;
uint8_t __meshlib_var_BLE_MESH_ADV_DATA = BLE_MESH_ADV_DATA;
#if CONFIG_BLE_MESH_FRIEND
uint8_t __meshlib_var_BLE_MESH_ADV_FRIEND = BLE_MESH_ADV_DATA;
uint8_t __meshlib_var_BLE_MESH_ADV_FRIEND = BLE_MESH_ADV_FRIEND;
#endif
#if CONFIG_BLE_MESH_RELAY_ADV_BUF
uint8_t __meshlib_var_BLE_MESH_ADV_RELAY_DATA = BLE_MESH_ADV_DATA;
uint8_t __meshlib_var_BLE_MESH_ADV_RELAY_DATA = BLE_MESH_ADV_RELAY_DATA;
#endif
uint8_t __meshlib_var_BLE_MESH_ADV_BEACON = BLE_MESH_ADV_BEACON;
uint8_t __meshlib_var_BLE_MESH_ADV_URI = BLE_MESH_ADV_URI;
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
uint8_t __meshlib_var_BLE_MESH_ADV_BLE = BLE_MESH_ADV_BLE;
#endif
#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX
uint8_t __meshlib_var_BLE_MESH_ADV_PROXY_SOLIC = BLE_MESH_ADV_PROXY_SOLIC;
#endif
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
uint8_t __meshlib_var_BLE_MESH_ADV_BLE = BLE_MESH_ADV_BLE;
#endif
uint8_t __meshlib_var_BLE_MESH_ADV_TYPES_NUM = BLE_MESH_ADV_TYPES_NUM;
/* Sys utilities */
@@ -562,24 +560,9 @@ int bt_mesh_ext_net_decrypt(const uint8_t key[16], struct net_buf_simple *buf,
return bt_mesh_net_decrypt(key, buf, iv_index, proxy, proxy_solic);
}
int bt_mesh_ext_tc_hmac_set_key(void *ctx, const uint8_t *key, unsigned int key_size)
int bt_mesh_ext_hmac_sha_256(const uint8_t key[32], struct bt_mesh_sg *sg, size_t sg_len, uint8_t mac[32])
{
return tc_hmac_set_key(ctx, key, key_size);
}
int bt_mesh_ext_tc_hmac_init(void *ctx)
{
return tc_hmac_init(ctx);
}
int bt_mesh_ext_tc_hmac_update(void *ctx, const void *data, unsigned int data_length)
{
return tc_hmac_update(ctx, data, data_length);
}
int bt_mesh_ext_tc_hmac_final(uint8_t *tag, unsigned int taglen, void *ctx)
{
return tc_hmac_final(tag, taglen, ctx);
return bt_mesh_sha256_hmac_raw_key(key, sg, sg_len, mac);
}
/* Mutex */
@@ -4274,12 +4257,6 @@ static const bt_mesh_ext_config_t bt_mesh_ext_cfg = {
.struct_addr_off_val = offsetof(bt_mesh_addr_t, val),
.struct_sg_size = sizeof(struct bt_mesh_sg),
.struct_sg_off_len = offsetof(struct bt_mesh_sg, len),
.struct_tc_sha256_state = sizeof(struct tc_sha256_state_struct),
.struct_tc_sha256_off_bits_hashed = offsetof(struct tc_sha256_state_struct, bits_hashed),
.struct_tc_sha256_off_leftover = offsetof(struct tc_sha256_state_struct, leftover),
.struct_tc_sha256_off_leftover_offset = offsetof(struct tc_sha256_state_struct, leftover_offset),
.struct_tc_hmac_state_size = sizeof(struct tc_hmac_state_struct),
.struct_tc_hmac_state_off_key = offsetof(struct tc_hmac_state_struct, key),
.btc_ble_mesh_evt_agg_client_send_timeout = BTC_BLE_MESH_EVT_AGG_CLIENT_SEND_TIMEOUT,
.btc_ble_mesh_evt_agg_client_recv_rsp = BTC_BLE_MESH_EVT_AGG_CLIENT_RECV_RSP,
@@ -183,12 +183,28 @@ static int32_t client_calc_timeout(struct bt_mesh_msg_ctx *ctx,
{
int32_t seg_rtx_to = 0, duration = 0, time = 0;
uint8_t seg_count = 0, seg_rtx_num = 0;
bool need_seg = false;
bool need_seg = bt_mesh_tag_send_segmented(ctx->send_tag);
uint8_t mic_size = 0;
if (msg->len > BLE_MESH_SDU_UNSEG_MAX ||
bt_mesh_tag_send_segmented(ctx->send_tag)) {
need_seg = true; /* Needs segmentation */
if (!need_seg) {
#if CONFIG_BLE_MESH_LONG_PACKET
if (ctx->enh.long_pkt_cfg_used == true) {
if ((ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_FORCE &&
msg->len > BLE_MESH_EXT_SDU_UNSEG_MAX) ||
(ctx->enh.long_pkt_cfg == BLE_MESH_LONG_PACKET_PREFER &&
msg->len > BLE_MESH_SDU_UNSEG_MAX)) {
need_seg = true; /* Needs segmentation */
}
} else {
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
need_seg = true; /* Needs segmentation */
}
}
#else
if (msg->len > BLE_MESH_SDU_UNSEG_MAX) {
need_seg = true; /* Needs segmentation */
}
#endif
}
mic_size = (need_seg && ctx->send_szmic == BLE_MESH_SEG_SZMIC_LONG &&
@@ -203,7 +219,16 @@ static int32_t 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 = client_get_adv_duration(ctx);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -186,6 +186,8 @@ struct esp_ble_mesh_blob_xfer {
esp_ble_mesh_blob_xfer_mode_t mode; /*!< BLOB transfer mode. */
uint8_t block_size_log; /*!< Logarithmic representation of the block size. */
uint16_t chunk_size; /*!< Base chunk size. May be smaller for the last chunk. */
/* Enhanced parameters for message context in blob chunks */
esp_ble_mesh_msg_enh_params_t chunk_enh_params;
};
/** BLOB transfer data block. */
@@ -782,6 +782,8 @@ struct esp_ble_mesh_dfu_cli_xfer_blob_params {
uint8_t block_size_log;
/** Base chunk size. May be smaller for the last chunk. */
uint16_t chunk_size;
/* Enhanced parameters for message context in blob chunks */
esp_ble_mesh_msg_enh_params_t chunk_enh_params;
};
/** Firmware Update Client transfer parameters */
@@ -185,7 +185,7 @@ static void btc_ble_mesh_dfu_client_free_req_data(btc_msg_t *msg)
}
if (msg->act >= ESP_BLE_MESH_DFU_CLIENT_EVT_MAX) {
BT_ERR("%s, Invalid event %d", __func, msg->act);
BT_ERR("%s, Invalid event %d", __func__, msg->act);
return;
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -1236,9 +1236,14 @@ int bt_mesh_dfu_cli_send(struct bt_mesh_dfu_cli *cli,
cli->xfer.flags = 0U;
if (xfer->blob_params) {
cli->xfer.flags |= FLAG_SKIP_CAPS_GET;
cli->xfer.blob.block_size_log = xfer->blob_params->block_size_log;
cli->xfer.blob.chunk_size = xfer->blob_params->chunk_size;
if (xfer->blob_params->block_size_log &&
xfer->blob_params->chunk_size) {
cli->xfer.flags |= FLAG_SKIP_CAPS_GET;
cli->xfer.blob.block_size_log = xfer->blob_params->block_size_log;
cli->xfer.blob.chunk_size = xfer->blob_params->chunk_size;
}
memcpy(&cli->xfer.blob.chunk_enh_params, &xfer->blob_params->chunk_enh_params,
sizeof(bt_mesh_msg_enh_params_t));
}
/* Phase will be set based on target status messages: */
@@ -243,6 +243,8 @@ struct bt_mesh_dfu_cli_xfer_blob_params {
uint8_t block_size_log;
/** Base chunk size. May be smaller for the last chunk. */
uint16_t chunk_size;
/* Enhanced parameters for message context in blob chunks */
bt_mesh_msg_enh_params_t chunk_enh_params;
};
/** Firmware Update Client transfer parameters: */
@@ -141,6 +141,8 @@ struct bt_mesh_blob_xfer {
uint8_t block_size_log;
/** Base chunk size. May be smaller for the last chunk. */
uint16_t chunk_size;
/* Enhanced parameters for message context in blob chunks */
bt_mesh_msg_enh_params_t chunk_enh_params;
};
/** BLOB stream interaction mode. */
@@ -34,19 +34,37 @@
#define BLOB_CHUNK_SIZE_MAX(sdu_max) ((sdu_max) - BLOB_CHUNK_SDU_OVERHEAD)
#define BLOB_CHUNK_SDU_LEN(chunk_size) (BLOB_CHUNK_SDU_OVERHEAD + (chunk_size))
#if CONFIG_BLE_MESH_LONG_PACKET
#if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \
CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_EXT_RX_SDU_MAX)
#define BLOB_RX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_EXT_RX_SDU_MAX)
#else
#define BLOB_RX_CHUNK_SIZE CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE
#endif
#else // CONFIG_BLE_MESH_LONG_PACKET
#if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \
CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_RX_SDU_MAX)
#define BLOB_RX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_RX_SDU_MAX)
#else
#define BLOB_RX_CHUNK_SIZE CONFIG_BLE_MESH_RX_BLOB_CHUNK_SIZE
#endif
#endif
#if CONFIG_BLE_MESH_LONG_PACKET
#if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \
CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_EXT_TX_SDU_MAX)
#define BLOB_TX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_EXT_TX_SDU_MAX)
#else
#define BLOB_TX_CHUNK_SIZE CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE
#endif
#else // CONFIG_BLE_MESH_LONG_PACKET
#if CONFIG_BLE_MESH_ALIGN_CHUNK_SIZE_TO_MAX_SEGMENT || \
CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE > BLOB_CHUNK_SIZE_MAX(BLE_MESH_TX_SDU_MAX)
#define BLOB_TX_CHUNK_SIZE BLOB_CHUNK_SIZE_MAX(BLE_MESH_TX_SDU_MAX)
#else
#define BLOB_TX_CHUNK_SIZE CONFIG_BLE_MESH_TX_BLOB_CHUNK_SIZE
#endif
#endif // CONFIG_BLE_MESH_LONG_PACKET
/* Utility macros for calculating log2 of a number at compile time.
* Used to determine the log2 representation of the block size, which
+21 -1
View File
@@ -18,6 +18,8 @@
#if CONFIG_BLE_MESH_BLOB_CLI
#define CHUNK_SIZE_MAX BLOB_TX_CHUNK_SIZE
#define TARGETS_FOR_EACH(cli, target) \
SYS_SLIST_FOR_EACH_CONTAINER((sys_slist_t *)&(cli)->inputs->targets, \
target, n)
@@ -49,7 +51,8 @@ _Static_assert((BLOB_BLOCK_STATUS_MSG_MAXLEN + BLE_MESH_MODEL_OP_LEN(BT_MESH_BLO
BLE_MESH_MIC_SHORT) <= BLE_MESH_RX_SDU_MAX,
"The BLOB Block Status message does not fit into the maximum incoming SDU size.");
NET_BUF_SIMPLE_DEFINE_STATIC(chunk_buf, BLE_MESH_TX_SDU_MAX);
NET_BUF_SIMPLE_DEFINE_STATIC(chunk_buf, BLOB_CHUNK_SDU_LEN(CHUNK_SIZE_MAX));
static bool chunk_sending;
struct block_status {
enum bt_mesh_blob_status status;
@@ -591,6 +594,12 @@ static int tx(struct bt_mesh_blob_cli *cli, uint16_t addr,
.addr = addr,
.send_ttl = cli->inputs->ttl,
};
if (chunk_sending) {
memcpy(&ctx.enh, &cli->xfer->chunk_enh_params,
sizeof(bt_mesh_msg_enh_params_t));
}
int err;
err = bt_mesh_model_send((struct bt_mesh_model *)cli->mod, &ctx, buf, &end_cb, cli);
@@ -615,6 +624,10 @@ static void send_end(int err, void *user_data)
{
struct bt_mesh_blob_cli *cli = user_data;
if (chunk_sending) {
chunk_sending = false;
}
if (!cli->tx.ctx.is_inited) {
return;
}
@@ -642,7 +655,12 @@ static void xfer_start_tx(struct bt_mesh_blob_cli *cli, uint16_t dst)
net_buf_simple_add_le64(&buf, cli->xfer->id);
net_buf_simple_add_le32(&buf, cli->xfer->size);
net_buf_simple_add_u8(&buf, cli->xfer->block_size_log);
#if CONFIG_BLE_MESH_LONG_PACKET
/* todo: could let user select methold */
net_buf_simple_add_le16(&buf, BLE_MESH_EXT_TX_SDU_MAX);
#else
net_buf_simple_add_le16(&buf, BLE_MESH_TX_SDU_MAX);
#endif
tx(cli, dst, &buf);
}
@@ -959,6 +977,8 @@ static void chunk_send(struct bt_mesh_blob_cli *cli)
chunk_size(cli->xfer, &cli->block, cli->chunk_idx));
cli->state = BT_MESH_BLOB_CLI_STATE_BLOCK_SEND;
chunk_sending = true;
blob_cli_broadcast(cli, &ctx);
}
@@ -25,7 +25,11 @@
#if CONFIG_BLE_MESH_BLOB_SRV
#if CONFIG_BLE_MESH_LONG_PACKET
#define MTU_SIZE_MAX (BLE_MESH_EXT_RX_SDU_MAX - BLE_MESH_MIC_SHORT)
#else
#define MTU_SIZE_MAX (BLE_MESH_RX_SDU_MAX - BLE_MESH_MIC_SHORT)
#endif
/* The Receive BLOB Timeout Timer */
#define SERVER_TIMEOUT_SECS(srv) (10 * (1 + (srv)->state.timeout_base))
+1
View File
@@ -29,6 +29,7 @@ INPUT = \
$(PROJECT_PATH)/components/bootloader_support/include/esp_flash_encrypt.h \
$(PROJECT_PATH)/components/esp_coex/include/esp_coexist.h \
$(PROJECT_PATH)/components/bt/common/api/include/api/esp_blufi_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_common_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h \
$(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h \
@@ -71,6 +71,9 @@ Reading of Local Data Information
.. include-build-file:: inc/esp_ble_mesh_local_data_operation_api.inc
Coexist with BLE
.. include-build-file:: inc/esp_ble_mesh_ble_api.inc
Low Power Operation (Updating)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -29,6 +29,7 @@ Mesh 核心
* 私有信标
* 子网桥
* 次要增强
* 设备固件更新(预览)
* 多个客户端模型同时运行
* 支持多个客户端模型同时向不同节点发送数据包
@@ -155,6 +155,23 @@ esp_err_t bluetooth_init(void)
/* XXX Need to have template for store */
ble_store_config_init();
#if CONFIG_BLE_MESH_USE_BLE_50
/**
* On the NimBLE host, once any of the discovery,
* advertising, or connection is enabled, it is
* no longer possible to register GATT services.
*
* Once the NimBLE host is started, it will call
* the registered sync callback. Since it is
* uncertain what the user will do in the sync
* callback, GATT services should be registered
* before starting the NimBLE.
*/
extern void bt_mesh_gatts_svcs_add(void);
bt_mesh_gatts_svcs_add();
#endif /* CONFIG_BLE_MESH_USE_BLE_50 */
nimble_port_freertos_init(mesh_host_task);
xSemaphoreTake(mesh_sem, portMAX_DELAY);