mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(ble_mesh): alignment to release/v6.0
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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(¶m.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, ¶m);
|
||||
}
|
||||
#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(¶m.scan_ble_adv_pkt, adv_report, sizeof(bt_mesh_ble_adv_report_t));
|
||||
|
||||
btc_ble_mesh_ble_callback(¶m, 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(¶m, 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(¶m, 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(¶m.ctx.enh, &arg->model_send.ctx->enh, sizeof(bt_mesh_msg_enh_params_t));
|
||||
|
||||
err = bt_mesh_client_send_msg(¶m, 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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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])
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,
|
||||
|
||||
Submodule components/bt/esp_ble_mesh/lib/lib updated: 70cbef2ed7...e44762384e
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 核心
|
||||
* 私有信标
|
||||
* 子网桥
|
||||
* 次要增强
|
||||
* 设备固件更新(预览)
|
||||
|
||||
* 多个客户端模型同时运行
|
||||
* 支持多个客户端模型同时向不同节点发送数据包
|
||||
|
||||
+17
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user