From b640f05f6afef51498ee4e795eacf800906d25e5 Mon Sep 17 00:00:00 2001 From: luoxu Date: Tue, 20 Jan 2026 15:39:39 +0800 Subject: [PATCH] feat(ble_mesh): alignment to release/v6.0 --- components/bt/CMakeLists.txt | 71 +- components/bt/common/btc/core/btc_task.c | 2 +- components/bt/esp_ble_mesh/Kconfig.in | 181 ++- .../api/core/esp_ble_mesh_ble_api.c | 26 +- .../api/core/esp_ble_mesh_common_api.c | 2 +- .../api/core/esp_ble_mesh_networking_api.c | 58 +- .../api/core/include/esp_ble_mesh_ble_api.h | 91 +- .../include/esp_ble_mesh_provisioning_api.h | 8 +- .../bt/esp_ble_mesh/api/esp_ble_mesh_defs.h | 192 +++ .../bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c | 51 +- .../bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c | 4 + .../btc/include/btc_ble_mesh_ble.h | 39 +- .../btc/include/btc_ble_mesh_model_common.h | 21 + .../btc/include/btc_ble_mesh_prov.h | 2 +- .../bt/esp_ble_mesh/common/crypto_mbedtls.c | 543 +++++++++ .../bt/esp_ble_mesh/common/crypto_psa.c | 713 +++++++++++ components/bt/esp_ble_mesh/common/crypto_tc.c | 342 ++++++ .../esp_ble_mesh/common/include/mesh/common.h | 2 + .../esp_ble_mesh/common/include/mesh/crypto.h | 514 ++++++++ .../esp_ble_mesh/common/include/mesh/kernel.h | 5 +- .../esp_ble_mesh/common/include/mesh/mutex.h | 7 +- .../esp_ble_mesh/common/include/mesh/queue.h | 33 + .../esp_ble_mesh/common/include/mesh/utils.h | 2 +- components/bt/esp_ble_mesh/common/mutex.c | 53 +- components/bt/esp_ble_mesh/common/queue.c | 48 + components/bt/esp_ble_mesh/core/access.c | 19 + components/bt/esp_ble_mesh/core/adv.c | 899 +++----------- components/bt/esp_ble_mesh/core/adv.h | 89 +- components/bt/esp_ble_mesh/core/adv_common.c | 23 + components/bt/esp_ble_mesh/core/adv_common.h | 58 +- components/bt/esp_ble_mesh/core/beacon.c | 2 +- components/bt/esp_ble_mesh/core/ble_adv.h | 54 + .../core/bluedroid_host/adapter.c | 866 ++++++++++---- components/bt/esp_ble_mesh/core/cfg_cli.c | 2 +- components/bt/esp_ble_mesh/core/cfg_srv.c | 2 +- components/bt/esp_ble_mesh/core/crypto.c | 353 +----- components/bt/esp_ble_mesh/core/crypto.h | 21 +- components/bt/esp_ble_mesh/core/ext_adv.c | 6 +- components/bt/esp_ble_mesh/core/ext_adv.h | 2 +- components/bt/esp_ble_mesh/core/fast_prov.c | 2 +- components/bt/esp_ble_mesh/core/friend.c | 32 +- components/bt/esp_ble_mesh/core/health_cli.c | 2 +- components/bt/esp_ble_mesh/core/health_srv.c | 2 +- components/bt/esp_ble_mesh/core/heartbeat.c | 2 +- .../esp_ble_mesh/core/include/mesh/access.h | 47 +- .../esp_ble_mesh/core/include/mesh/adapter.h | 194 ++- .../bt/esp_ble_mesh/core/include/mesh/hci.h | 4 + components/bt/esp_ble_mesh/core/local.c | 2 +- components/bt/esp_ble_mesh/core/main.c | 2 +- components/bt/esp_ble_mesh/core/net.c | 269 +++-- components/bt/esp_ble_mesh/core/net.h | 21 +- .../esp_ble_mesh/core/nimble_host/adapter.c | 1064 +++++++++++++---- components/bt/esp_ble_mesh/core/prov_node.c | 38 +- components/bt/esp_ble_mesh/core/prov_pvnr.c | 23 +- .../bt/esp_ble_mesh/core/proxy_client.c | 19 + .../bt/esp_ble_mesh/core/proxy_client.h | 2 + .../bt/esp_ble_mesh/core/proxy_server.c | 115 +- .../bt/esp_ble_mesh/core/proxy_server.h | 4 +- components/bt/esp_ble_mesh/core/rpl.c | 2 +- components/bt/esp_ble_mesh/core/scan.c | 225 +++- components/bt/esp_ble_mesh/core/scan.h | 8 +- .../esp_ble_mesh/core/storage/settings_nvs.c | 2 +- components/bt/esp_ble_mesh/core/test.c | 2 +- components/bt/esp_ble_mesh/core/transport.c | 338 +++++- .../bt/esp_ble_mesh/core/transport.enh.c | 320 ++++- components/bt/esp_ble_mesh/core/transport.h | 53 +- components/bt/esp_ble_mesh/lib/ext.c | 37 +- components/bt/esp_ble_mesh/lib/lib | 2 +- .../models/client/client_common.c | 35 +- .../api/core/esp_ble_mesh_rpr_model_api.c | 2 +- .../core/include/esp_ble_mesh_rpr_model_api.h | 2 +- .../include/esp_ble_mesh_blob_model_api.h | 2 + .../include/esp_ble_mesh_dfu_model_api.h | 2 + .../v1.1/btc/btc_ble_mesh_dfu_model.c | 2 +- .../v1.1/btc/btc_ble_mesh_rpr_model.c | 2 +- .../v1.1/btc/include/btc_ble_mesh_rpr_model.h | 2 +- components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c | 11 +- .../v1.1/include/mesh_v1.1/dfu/dfu_cli.h | 2 + .../v1.1/include/mesh_v1.1/mbt/blob.h | 2 + components/bt/esp_ble_mesh/v1.1/mbt/blob.h | 18 + .../bt/esp_ble_mesh/v1.1/mbt/blob_cli.c | 22 +- .../bt/esp_ble_mesh/v1.1/mbt/blob_srv.c | 4 + docs/doxygen/Doxyfile | 1 + .../api-reference/bluetooth/esp-ble-mesh.rst | 3 + .../esp-ble-mesh/ble-mesh-feature-list.rst | 1 + .../example_init/ble_mesh_example_init.c | 17 + 86 files changed, 6226 insertions(+), 2143 deletions(-) create mode 100644 components/bt/esp_ble_mesh/common/crypto_mbedtls.c create mode 100644 components/bt/esp_ble_mesh/common/crypto_psa.c create mode 100644 components/bt/esp_ble_mesh/common/crypto_tc.c create mode 100644 components/bt/esp_ble_mesh/common/include/mesh/crypto.h create mode 100644 components/bt/esp_ble_mesh/common/include/mesh/queue.h create mode 100644 components/bt/esp_ble_mesh/common/queue.c create mode 100644 components/bt/esp_ble_mesh/core/ble_adv.h diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 5e2fac0a74..33df48eaec 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -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) diff --git a/components/bt/common/btc/core/btc_task.c b/components/bt/common/btc/core/btc_task.c index 451c255f9f..1666b9d439 100644 --- a/components/bt/common/btc/core/btc_task.c +++ b/components/bt/common/btc/core/btc_task.c @@ -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 }, diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index 61b48898a1..a108305030 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -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 diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c index 559528e8ad..fcba1f4b51 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c @@ -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); +} diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c index 8212878608..eaa1868133 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c index 4f6b46196a..daa7e00ab0 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c @@ -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); diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h index 6818ba18ae..cdada119b4 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h @@ -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 diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h index 58ad280468..a603689769 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h @@ -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. */ diff --git a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index f546f63d8e..01ade02668 100644 --- a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -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. diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c index ead6c2cc02..ac397aeb18 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c @@ -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) */ diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index e48d45e8a4..49ae1d5dda 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -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); diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h index 8c63002a2a..e5d21df0d0 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h @@ -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); diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_model_common.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_model_common.h index d1bf15d22b..66507a1bb2 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_model_common.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_model_common.h @@ -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, diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h index f27779270f..741a6b313d 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h @@ -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 */ diff --git a/components/bt/esp_ble_mesh/common/crypto_mbedtls.c b/components/bt/esp_ble_mesh/common/crypto_mbedtls.c new file mode 100644 index 0000000000..4491fe779a --- /dev/null +++ b/components/bt/esp_ble_mesh/common/crypto_mbedtls.c @@ -0,0 +1,543 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#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; +} diff --git a/components/bt/esp_ble_mesh/common/crypto_psa.c b/components/bt/esp_ble_mesh/common/crypto_psa.c new file mode 100644 index 0000000000..340c027c39 --- /dev/null +++ b/components/bt/esp_ble_mesh/common/crypto_psa.c @@ -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 +#include + +#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 diff --git a/components/bt/esp_ble_mesh/common/crypto_tc.c b/components/bt/esp_ble_mesh/common/crypto_tc.c new file mode 100644 index 0000000000..24c8752c2a --- /dev/null +++ b/components/bt/esp_ble_mesh/common/crypto_tc.c @@ -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 +#include + +#include "esp_random.h" + +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/components/bt/esp_ble_mesh/common/include/mesh/common.h b/components/bt/esp_ble_mesh/common/include/mesh/common.h index a1cfa673a2..19482bd378 100644 --- a/components/bt/esp_ble_mesh/common/include/mesh/common.h +++ b/components/bt/esp_ble_mesh/common/include/mesh/common.h @@ -13,6 +13,7 @@ #include #include +#include #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" { diff --git a/components/bt/esp_ble_mesh/common/include/mesh/crypto.h b/components/bt/esp_ble_mesh/common/include/mesh/crypto.h new file mode 100644 index 0000000000..5029866ab0 --- /dev/null +++ b/components/bt/esp_ble_mesh/common/include/mesh/crypto.h @@ -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 +#include +#include + +#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_ */ diff --git a/components/bt/esp_ble_mesh/common/include/mesh/kernel.h b/components/bt/esp_ble_mesh/common/include/mesh/kernel.h index 8496fcec5a..a24772a47d 100644 --- a/components/bt/esp_ble_mesh/common/include/mesh/kernel.h +++ b/components/bt/esp_ble_mesh/common/include/mesh/kernel.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 diff --git a/components/bt/esp_ble_mesh/common/include/mesh/mutex.h b/components/bt/esp_ble_mesh/common/include/mesh/mutex.h index ee89750029..0cc47eb01a 100644 --- a/components/bt/esp_ble_mesh/common/include/mesh/mutex.h +++ b/components/bt/esp_ble_mesh/common/include/mesh/mutex.h @@ -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); diff --git a/components/bt/esp_ble_mesh/common/include/mesh/queue.h b/components/bt/esp_ble_mesh/common/include/mesh/queue.h new file mode 100644 index 0000000000..021c99ba67 --- /dev/null +++ b/components/bt/esp_ble_mesh/common/include/mesh/queue.h @@ -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_ */ diff --git a/components/bt/esp_ble_mesh/common/include/mesh/utils.h b/components/bt/esp_ble_mesh/common/include/mesh/utils.h index 4a543a2abd..4ef522ee32 100644 --- a/components/bt/esp_ble_mesh/common/include/mesh/utils.h +++ b/components/bt/esp_ble_mesh/common/include/mesh/utils.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: * F(i, ...). @p F is called repeatedly in the expansion. * Its first argument @p i is the index in the sequence, and diff --git a/components/bt/esp_ble_mesh/common/mutex.c b/components/bt/esp_ble_mesh/common/mutex.c index 6c3b2bf6f7..3a3dedb80d 100644 --- a/components/bt/esp_ble_mesh/common/mutex.c +++ b/components/bt/esp_ble_mesh/common/mutex.c @@ -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); diff --git a/components/bt/esp_ble_mesh/common/queue.c b/components/bt/esp_ble_mesh/common/queue.c new file mode 100644 index 0000000000..1fc3d66a61 --- /dev/null +++ b/components/bt/esp_ble_mesh/common/queue.c @@ -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; +} diff --git a/components/bt/esp_ble_mesh/core/access.c b/components/bt/esp_ble_mesh/core/access.c index 30214ee982..2f70e64eea 100644 --- a/components/bt/esp_ble_mesh/core/access.c +++ b/components/bt/esp_ble_mesh/core/access.c @@ -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); diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index 5f58c2058b..e35d34c993 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -23,148 +23,26 @@ #include "proxy_client.h" #include "prov_pvnr.h" #include "mesh/adapter.h" +#include "adv_common.h" +#include "ble_adv.h" -/* Convert from ms to 0.625ms units */ -#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) -/* Convert from 0.625ms units to interval(ms) */ -#define ADV_SCAN_INT(val) ((val) * 5 / 8) - -/* Pre-5.0 controllers enforce a minimum interval of 100ms - * whereas 5.0+ controllers can go down to 20ms. - */ -#if CONFIG_BLE_MESH_HCI_5_0 -#define ADV_ITVL_MIN 20 -#else -#define ADV_ITVL_MIN 100 -#endif - -static const uint8_t adv_type[] = { - [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, - [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE, - [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, - [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, -}; - -NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT, - BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); - -static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT]; - -struct bt_mesh_queue { - QueueHandle_t handle; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - StaticQueue_t *buffer; - uint8_t *storage; -#endif -}; - -static struct bt_mesh_queue adv_queue; -static bt_mesh_mutex_t adv_buf_alloc_lock; - -/* We reserve one queue item for bt_mesh_adv_update() */ -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1) -#else -#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1) -#endif +static struct bt_mesh_adv_queue *adv_queue; #if CONFIG_BLE_MESH_RELAY_ADV_BUF -NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, - BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); - -static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT]; - -static struct bt_mesh_queue relay_queue; -#define BLE_MESH_RELAY_QUEUE_SIZE CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT - static QueueSetHandle_t mesh_queue_set; -#define BLE_MESH_QUEUE_SET_SIZE (BLE_MESH_ADV_QUEUE_SIZE + BLE_MESH_RELAY_QUEUE_SIZE) - -#define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6) -#define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF - -static bool ignore_relay_packet(uint32_t timestamp); +#define BLE_MESH_QUEUE_SET_SIZE (bt_mesh_adv_buf_count_get() + bt_mesh_relay_adv_buf_count_get()) #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -/* length + advertising data + length + scan response data */ -NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, - ((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL); - -static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; - -enum { - TIMER_INIT, /* Resend timer is initialized */ - NUM_FLAGS, -}; - -static struct 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); -} ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; - -#define SEND_BLE_ADV_INFINITE 0xFFFF - -#if CONFIG_BLE_MESH_DEINIT -static void bt_mesh_ble_adv_deinit(void); -#endif /* CONFIG_BLE_MESH_DEINIT */ -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ - -struct bt_mesh_adv_task { - TaskHandle_t handle; -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - StaticTask_t *task; - StackType_t *stack; -#endif -}; - -static struct bt_mesh_adv_task adv_task; - -static struct bt_mesh_adv *adv_alloc(int id) -{ - return &adv_pool[id]; -} - -static inline void adv_send_start(uint16_t duration, int err, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->start) { - cb->start(duration, err, cb_data); - } -} - -static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->end) { - cb->end(err, cb_data); - } -} - -uint16_t bt_mesh_pdu_duration(uint8_t xmit) -{ - uint16_t duration = 0U; - uint16_t adv_int = 0U; - - adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit)); - duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); - - return duration; -} - -static inline int adv_send(struct net_buf *buf) +static int adv_send(struct net_buf *buf) { const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; void *cb_data = BLE_MESH_ADV(buf)->cb_data; struct bt_mesh_adv_param param = {0}; uint16_t duration = 0U, adv_int = 0U; + uint8_t adv_cnt = 0; struct bt_mesh_adv_data ad = {0}; int err = 0; + bool start_cb_called = (BLE_MESH_ADV(buf)->flags & BLE_MESH_ADV_FLAG_SKIP_START_CB); BT_DBG("LegacyAdvSend, Type %u", BLE_MESH_ADV(buf)->type); BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); @@ -172,10 +50,20 @@ static inline int adv_send(struct net_buf *buf) #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV if (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) { #endif - adv_int = MAX(ADV_ITVL_MIN, - BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit)); - duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) * - (adv_int + 10); + if (BLE_MESH_ADV(buf)->adv_itvl != BLE_MESH_ADV_ITVL_DEFAULT) { + adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_ADV(buf)->adv_itvl); + } else { + adv_int = MAX(ADV_ITVL_MIN, + BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit)); + } + + if (BLE_MESH_ADV(buf)->adv_cnt != BLE_MESH_ADV_CNT_DEFAULT) { + adv_cnt = BLE_MESH_ADV(buf)->adv_cnt; + } else { + adv_cnt = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1; + } + + duration = adv_cnt * (adv_int + 10); BT_DBG("count %u interval %ums duration %ums", BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int, @@ -189,6 +77,39 @@ static inline int adv_send(struct net_buf *buf) param.interval_min = ADV_SCAN_UNIT(adv_int); param.interval_max = param.interval_min; + if (BLE_MESH_ADV(buf)->channel_map) { + param.channel_map = BLE_MESH_ADV(buf)->channel_map; + } else { + param.channel_map = BLE_MESH_ADV_CHAN_DEFAULT; + } +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_EXT_ADV + if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_PROV || + BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_DATA || + BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_RELAY_DATA +#if CONFIG_BLE_MESH_LONG_PACKET + || BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_LONG_PROV + || BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_LONG_DATA + || BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_EXT_LONG_RELAY_DATA +#endif + ) { + param.primary_phy = EXT_ADV(buf)->primary_phy; + param.secondary_phy = EXT_ADV(buf)->secondary_phy; + param.include_tx_power = EXT_ADV(buf)->include_tx_power; + param.tx_power = EXT_ADV(buf)->tx_power; + } else +#endif + { + param.primary_phy = BLE_MESH_ADV_PRI_PHY_DEFAULT; + param.secondary_phy = BLE_MESH_ADV_SEC_PHY_DEFAULT; + param.include_tx_power = BLE_MESH_TX_POWER_INCLUDE_DEFAULT; + param.tx_power = BLE_MESH_TX_POWER_DEFAULT; + } + + param.adv_duration = duration; + param.adv_count = adv_cnt; +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) { bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); @@ -197,17 +118,31 @@ static inline int adv_send(struct net_buf *buf) BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18), BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len), }; + +#if CONFIG_BLE_MESH_USE_BLE_50 + param.primary_phy = BLE_MESH_ADV_PHY_1M; + param.secondary_phy = BLE_MESH_ADV_PHY_1M; + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } else #endif /* CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX */ { bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL); + +#if CONFIG_BLE_MESH_USE_BLE_50 + param.primary_phy = BLE_MESH_ADV_PHY_1M; + param.secondary_phy = BLE_MESH_ADV_PHY_1M; + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, &ad, 1, NULL, 0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(¶m, &ad, 1, NULL, 0); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV } else { struct bt_mesh_ble_adv_data data = {0}; - struct ble_adv_tx *tx = cb_data; + struct bt_mesh_ble_adv_tx *tx = cb_data; if (tx == NULL) { BT_ERR("Invalid adv user data"); @@ -231,13 +166,20 @@ static inline int adv_send(struct net_buf *buf) bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); +#if CONFIG_BLE_MESH_USE_BLE_50 + err = bt_mesh_ble_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, &tx->param, &data); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_mesh_ble_adv_start(&tx->param, &data); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ net_buf_unref(buf); - adv_send_start(duration, err, cb, cb_data); + if (!start_cb_called && cb && cb->start) { + cb->start(duration, err, cb_data); + } + if (err) { BT_ERR("Start advertising failed: err %d", err); return err; @@ -245,10 +187,18 @@ static inline int adv_send(struct net_buf *buf) BT_DBG("Advertising started. Sleeping %u ms", duration); - k_sleep(K_MSEC(duration)); +#if CONFIG_BLE_MESH_USE_BLE_50 + if (!bt_mesh_adv_task_wait(UINT32_MAX, K_FOREVER, NULL)) { + BT_WARN("Advertising didn't finish on time"); + bt_le_ext_adv_stop(CONFIG_BLE_MESH_ADV_INST_ID); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_adv_task_wait(K_MSEC(duration)); err = bt_le_adv_stop(); - adv_send_end(err, cb, cb_data); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + + BLE_MESH_SEND_END_CB(err, cb, cb_data); if (err) { BT_ERR("Stop advertising failed: err %d", err); return 0; @@ -258,10 +208,23 @@ static inline int adv_send(struct net_buf *buf) return 0; } -static inline TickType_t K_WAIT(int32_t val) +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +static QueueHandle_t relay_adv_handle_get(void) { - return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); + struct bt_mesh_adv_type_manager *adv_type = NULL; + + BT_DBG("RelayAdvHandleGet"); + + adv_type = bt_mesh_adv_types_mgmt_get(BLE_MESH_ADV_RELAY_DATA); + + if (adv_type->adv_q == NULL) { + BT_DBG("HandleNotFound"); + return NULL; + } + + return adv_type->adv_q->q.handle; } +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ static void adv_thread(void *p) { @@ -287,7 +250,7 @@ static void adv_thread(void *p) #if !CONFIG_BLE_MESH_RELAY_ADV_BUF #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); while (!(*buf)) { int32_t timeout = 0; @@ -295,22 +258,24 @@ static void adv_thread(void *p) timeout = bt_mesh_proxy_server_adv_start(); BT_DBG("Mesh Proxy Advertising up to %d ms", timeout); - xQueueReceive(adv_queue.handle, &msg, K_WAIT(timeout)); + + xQueueReceive(adv_queue->q.handle, &msg, K_WAIT(timeout)); + BT_DBG("Mesh Proxy Advertising stop"); bt_mesh_proxy_server_adv_stop(); } -#else - xQueueReceive(adv_queue.handle, &msg, portMAX_DELAY); +#else /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ + xQueueReceive(adv_queue->q.handle, &msg, portMAX_DELAY); #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER handle = xQueueSelectFromSet(mesh_queue_set, K_NO_WAIT); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } else { while (!(*buf)) { @@ -327,10 +292,10 @@ static void adv_thread(void *p) bt_mesh_proxy_server_adv_stop(); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } } @@ -338,10 +303,10 @@ static void adv_thread(void *p) #else /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ handle = xQueueSelectFromSet(mesh_queue_set, portMAX_DELAY); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ @@ -358,7 +323,7 @@ static void adv_thread(void *p) BT_WARN("Failed to send adv packet"); } #else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ - if (msg.relay && ignore_relay_packet(msg.timestamp)) { + if (msg.relay && bt_mesh_ignore_relay_packet(msg.timestamp)) { /* If the interval between "current time - msg.timestamp" is bigger than * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. */ @@ -383,144 +348,6 @@ static void adv_thread(void *p) } } -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) -{ - struct bt_mesh_adv *adv = NULL; - struct net_buf *buf = NULL; - - if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) { - BT_WARN("Refusing to allocate buffer while suspended"); - return NULL; - } - - bt_mesh_r_mutex_lock(&adv_buf_alloc_lock); - buf = net_buf_alloc(pool, timeout); - if (!buf) { - bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock); - return NULL; - } - - BT_DBG("pool %p, buf_count %d, uinit_count %d", - buf->pool, pool->buf_count, pool->uninit_count); - - adv = get_id(net_buf_id(buf)); - BLE_MESH_ADV(buf) = adv; - - (void)memset(adv, 0, sizeof(*adv)); - - adv->type = type; - - bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock); - return buf; -} - -void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) -{ - int i; - - if (pool == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return; - } - - for (i = 0; i < pool->buf_count; i++) { - struct net_buf *buf = &pool->__bufs[i]; - if (buf->ref > 1U) { - buf->ref = 1U; - } - net_buf_unref(buf); - } -} - -struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, - type, timeout); -} - -void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, - uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag) -{ - if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) { - BT_ERR("%s, Invalid parameter", __func__); - return; - } - - switch (flag) { - case BLE_MESH_BUF_REF_EQUAL: - if (buf->ref != ref_cmp) { - BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp); - } - break; - case BLE_MESH_BUF_REF_SMALL: - if (buf->ref >= ref_cmp) { - BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp); - } - break; - default: - break; - } -} - -static void bt_mesh_unref_buf(bt_mesh_msg_t *msg) -{ - struct net_buf *buf = NULL; - - if (msg->arg) { - buf = (struct net_buf *)msg->arg; - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); - if (buf->ref > 1U) { - buf->ref = 1U; - } - net_buf_unref(buf); - } -} - -static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) -{ - if (adv_queue.handle == NULL) { - BT_ERR("Invalid adv queue"); - return; - } - - if (front) { - if (xQueueSendToFront(adv_queue.handle, msg, timeout) != pdTRUE) { - BT_ERR("Failed to send item to adv queue front"); - bt_mesh_unref_buf(msg); - } - } else { - if (xQueueSend(adv_queue.handle, msg, timeout) != pdTRUE) { - BT_ERR("Failed to send item to adv queue back"); - bt_mesh_unref_buf(msg); - } - } -} - -void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - bt_mesh_msg_t msg = { - .relay = false, - }; - - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); - - BLE_MESH_ADV(buf)->cb = cb; - BLE_MESH_ADV(buf)->cb_data = cb_data; - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); - BLE_MESH_ADV(buf)->xmit = xmit; - - bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); - - msg.arg = (void *)net_buf_ref(buf); - bt_mesh_task_post(&msg, portMAX_DELAY, false); -} - void bt_mesh_adv_update(void) { bt_mesh_msg_t msg = { @@ -533,479 +360,61 @@ void bt_mesh_adv_update(void) bt_mesh_task_post(&msg, K_NO_WAIT, false); } -#if CONFIG_BLE_MESH_RELAY_ADV_BUF -static bool ignore_relay_packet(uint32_t timestamp) -{ - uint32_t now = k_uptime_get_32(); - uint32_t interval = 0U; - - if (now >= timestamp) { - interval = now - timestamp; - } else { - interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1; - } - - return (interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false; -} - -static struct bt_mesh_adv *relay_adv_alloc(int id) -{ - return &relay_adv_pool[id]; -} - -struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&relay_adv_buf_pool, relay_adv_alloc, - type, timeout); -} - -static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout) -{ - QueueSetMemberHandle_t handle = NULL; - bt_mesh_msg_t old_msg = {0}; - - if (relay_queue.handle == NULL) { - BT_ERR("Invalid relay queue"); - return; - } - - if (xQueueSend(relay_queue.handle, msg, timeout) == pdTRUE) { - return; - } - - /* If failed to send packet to the relay queue(queue is full), we will - * remove the oldest packet in the queue and put the new one into it. - */ - handle = xQueueSelectFromSet(mesh_queue_set, K_NO_WAIT); - if (handle && uxQueueMessagesWaiting(relay_queue.handle)) { - BT_INFO("Full queue, remove the oldest relay packet"); - /* Remove the oldest relay packet from queue */ - if (xQueueReceive(relay_queue.handle, &old_msg, K_NO_WAIT) != pdTRUE) { - BT_ERR("Failed to remove item from relay queue"); - bt_mesh_unref_buf(msg); - return; - } - /* Unref buf used for the oldest relay packet */ - bt_mesh_unref_buf(&old_msg); - /* Send the latest relay packet to queue */ - if (xQueueSend(relay_queue.handle, msg, K_NO_WAIT) != pdTRUE) { - BT_ERR("Failed to send item to relay queue"); - bt_mesh_unref_buf(msg); - return; - } - } else { - BT_WARN("Empty queue, but failed to send the relay packet"); - bt_mesh_unref_buf(msg); - } -} - -void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, - uint16_t src, uint16_t dst, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - bt_mesh_msg_t msg = { - .relay = true, - }; - - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); - - BLE_MESH_ADV(buf)->cb = cb; - BLE_MESH_ADV(buf)->cb_data = cb_data; - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); - BLE_MESH_ADV(buf)->xmit = xmit; - - msg.arg = (void *)net_buf_ref(buf); - msg.src = src; - msg.dst = dst; - msg.timestamp = k_uptime_get_32(); - /* Use K_NO_WAIT here, if relay_queue is full return immediately */ - ble_mesh_relay_task_post(&msg, K_NO_WAIT); -} - -uint16_t bt_mesh_get_stored_relay_count(void) -{ - return (uint16_t)uxQueueMessagesWaiting(relay_queue.handle); -} -#endif /* #if CONFIG_BLE_MESH_RELAY_ADV_BUF */ - void bt_mesh_adv_init(void) { -#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - adv_queue.handle = xQueueCreate(BLE_MESH_ADV_QUEUE_SIZE, sizeof(bt_mesh_msg_t)); - __ASSERT(adv_queue.handle, "Failed to create queue"); -#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - adv_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 - adv_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(adv_queue.buffer, "Failed to create queue buffer"); -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - adv_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_ADV_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - adv_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_ADV_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#endif - __ASSERT(adv_queue.storage, "Failed to create queue storage"); - adv_queue.handle = xQueueCreateStatic(BLE_MESH_ADV_QUEUE_SIZE, sizeof(bt_mesh_msg_t), (uint8_t*)adv_queue.storage, adv_queue.buffer); - __ASSERT(adv_queue.handle, "Failed to create static queue"); -#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ + BT_DBG("LegacyAdvInit"); + bt_mesh_adv_common_init(); + adv_queue = bt_mesh_adv_queue_get(); + + assert(adv_queue && adv_queue->q.handle && adv_queue->send); #if CONFIG_BLE_MESH_RELAY_ADV_BUF -#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - relay_queue.handle = xQueueCreate(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t)); - __ASSERT(relay_queue.handle, "Failed to create relay queue"); -#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - relay_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 - relay_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(relay_queue.buffer, "Failed to create relay queue buffer"); -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - relay_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_RELAY_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - relay_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_RELAY_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#endif - __ASSERT(relay_queue.storage, "Failed to create relay queue storage"); - relay_queue.handle = xQueueCreateStatic(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t), (uint8_t*)relay_queue.storage, relay_queue.buffer); - __ASSERT(relay_queue.handle, "Failed to create static relay queue"); -#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ - - mesh_queue_set = xQueueCreateSet(BLE_MESH_QUEUE_SET_SIZE); - __ASSERT(mesh_queue_set, "Failed to create queue set"); - xQueueAddToSet(adv_queue.handle, mesh_queue_set); - xQueueAddToSet(relay_queue.handle, mesh_queue_set); + bt_mesh_relay_adv_init(); #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - __ASSERT(adv_task.task, "Failed to create adv thread task"); - adv_task.stack = heap_caps_calloc_prefer(1, BLE_MESH_ADV_TASK_STACK_SIZE * sizeof(StackType_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - __ASSERT(adv_task.stack, "Failed to create adv thread stack"); - adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, - BLE_MESH_ADV_TASK_PRIO, adv_task.stack, adv_task.task, BLE_MESH_ADV_TASK_CORE); - __ASSERT(adv_task.handle, "Failed to create static adv thread"); -#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ - int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, - BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE); - __ASSERT(ret == pdTRUE, "Failed to create adv thread"); - (void)ret; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ - bt_mesh_r_mutex_create(&adv_buf_alloc_lock); +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_init(); +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + QueueHandle_t relay_adv_handle = relay_adv_handle_get(); + assert(relay_adv_handle); + + mesh_queue_set = xQueueCreateSet(BLE_MESH_QUEUE_SET_SIZE); + assert(mesh_queue_set); + + xQueueAddToSet(adv_queue->q.handle, mesh_queue_set); + xQueueAddToSet(relay_adv_handle, mesh_queue_set); +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + + bt_mesh_adv_task_init(adv_thread); } #if CONFIG_BLE_MESH_DEINIT void bt_mesh_adv_deinit(void) { - if (adv_queue.handle == NULL) { - return; - } + BT_DBG("LegacyAdvDeinit"); - vTaskDelete(adv_task.handle); - adv_task.handle = NULL; -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - heap_caps_free(adv_task.stack); - adv_task.stack = NULL; - heap_caps_free(adv_task.task); - adv_task.task = NULL; -#endif + /* Adv task must be deinit first */ + bt_mesh_adv_task_deinit(); #if CONFIG_BLE_MESH_RELAY_ADV_BUF - xQueueRemoveFromSet(adv_queue.handle, mesh_queue_set); - xQueueRemoveFromSet(relay_queue.handle, mesh_queue_set); + QueueHandle_t relay_adv_handle = relay_adv_handle_get(); + assert(relay_adv_handle); - vQueueDelete(relay_queue.handle); - relay_queue.handle = NULL; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - heap_caps_free(relay_queue.buffer); - relay_queue.buffer = NULL; - heap_caps_free(relay_queue.storage); - relay_queue.storage = NULL; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ - - bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool); - memset(relay_adv_pool, 0, sizeof(relay_adv_pool)); + xQueueRemoveFromSet(adv_queue->q.handle, mesh_queue_set); + xQueueRemoveFromSet(relay_adv_handle, mesh_queue_set); vQueueDelete(mesh_queue_set); mesh_queue_set = NULL; + + bt_mesh_relay_adv_deinit(); #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ - vQueueDelete(adv_queue.handle); - adv_queue.handle = NULL; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - heap_caps_free(adv_queue.buffer); - adv_queue.buffer = NULL; - heap_caps_free(adv_queue.storage); - adv_queue.storage = NULL; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ - - bt_mesh_unref_buf_from_pool(&adv_buf_pool); - memset(adv_pool, 0, sizeof(adv_pool)); - #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV bt_mesh_ble_adv_deinit(); #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ - bt_mesh_r_mutex_free(&adv_buf_alloc_lock); + + bt_mesh_adv_common_deinit(); } #endif /* CONFIG_BLE_MESH_DEINIT */ - -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -static struct bt_mesh_adv *ble_adv_alloc(int id) -{ - return &ble_adv_pool[id]; -} - -static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&ble_adv_buf_pool, ble_adv_alloc, - type, timeout); -} - -static void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, - void *cb_data, bool front) -{ - bt_mesh_msg_t msg = { - .relay = false, - }; - - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); - - BLE_MESH_ADV(buf)->cb = cb; - BLE_MESH_ADV(buf)->cb_data = cb_data; - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); - - bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); - - msg.arg = (void *)net_buf_ref(buf); - bt_mesh_task_post(&msg, portMAX_DELAY, front); -} - -static void ble_adv_tx_reset(struct ble_adv_tx *tx, bool unref) -{ - if (tx->buf == NULL) { - return; - } - - if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) { - k_delayed_work_free(&tx->resend); - } - bt_mesh_atomic_set(tx->flags, 0); - memset(&tx->param, 0, sizeof(tx->param)); - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->buf), 0); - if (unref) { - net_buf_unref(tx->buf); - } - tx->buf = NULL; -} - -static void ble_adv_send_start(uint16_t duration, int err, void *cb_data) -{ - struct ble_adv_tx *tx = cb_data; - - BT_DBG("%s, duration %d, err %d", __func__, duration, err); - - /* If failed to send BLE adv packet, and param->count is not 0 - * which means the timer has been initialized, here we need to - * free the timer. - */ - if (err) { - ble_adv_tx_reset(tx, true); - } -} - -static void ble_adv_send_end(int err, void *cb_data) -{ - struct ble_adv_tx *tx = cb_data; - - BT_DBG("%s, err %d", __func__, err); - - if (err) { - ble_adv_tx_reset(tx, true); - return; - } - - if (tx->param.count) { - k_delayed_work_submit(&tx->resend, tx->param.period); - } else { - ble_adv_tx_reset(tx, true); - } -} - -static struct bt_mesh_send_cb ble_adv_send_cb = { - .start = ble_adv_send_start, - .end = ble_adv_send_end, -}; - -static void ble_adv_resend(struct k_work *work) -{ - struct ble_adv_tx *tx = CONTAINER_OF(work, - struct ble_adv_tx, - resend.work); - bool front = false; - - if (tx->buf == NULL) { - /* The advertising has been cancelled */ - return; - } - - front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; - bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front); - - if (tx->param.count == SEND_BLE_ADV_INFINITE) { - /* Send the BLE advertising packet infinitely */ - return; - } - - if (tx->param.count > 0U) { - tx->param.count--; - } -} - -int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, - const struct bt_mesh_ble_adv_data *data, uint8_t *index) -{ - struct ble_adv_tx *tx = NULL; - struct net_buf *buf = NULL; - bool front = false; - - if (param == NULL || index == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return -EINVAL; - } - - if (param->adv_type != BLE_MESH_ADV_DIRECT_IND && - (param->interval < 0x20 || param->interval > 0x4000)) { - BT_ERR("Invalid adv interval 0x%04x", param->interval); - return -EINVAL; - } - - if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { - BT_ERR("Invalid adv type 0x%02x", param->adv_type); - return -EINVAL; - } - - if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) { - BT_ERR("Invalid own addr type 0x%02x", param->own_addr_type); - return -EINVAL; - } - - if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || - param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || - param->adv_type == BLE_MESH_ADV_DIRECT_IND || - param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) && - param->peer_addr_type > BLE_MESH_ADDR_RANDOM) { - BT_ERR("Invalid peer addr type 0x%02x", param->peer_addr_type); - return -EINVAL; - } - - if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) { - BT_ERR("Invalid adv data length (adv %d, scan rsp %d)", - data->adv_data_len, data->scan_rsp_data_len); - return -EINVAL; - } - - if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) { - BT_ERR("Invalid adv priority %d", param->priority); - return -EINVAL; - } - - if (param->duration < ADV_SCAN_INT(param->interval)) { - BT_ERR("Too small duration %dms", param->duration); - return -EINVAL; - } - - buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, K_NO_WAIT); - if (!buf) { - BT_ERR("No empty ble adv buffer"); - return -ENOBUFS; - } - - /* Set advertising data and scan response data */ - memset(buf->data, 0, buf->size); - if (data) { - net_buf_add_u8(buf, data->adv_data_len); - if (data->adv_data_len) { - net_buf_add_mem(buf, data->adv_data, data->adv_data_len); - } - net_buf_add_u8(buf, data->scan_rsp_data_len); - if (data->scan_rsp_data_len) { - net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len); - } - } - - *index = net_buf_id(buf); - tx = &ble_adv_tx[*index]; - tx->buf = buf; - memcpy(&tx->param, param, sizeof(tx->param)); - - front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; - bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front); - if (param->count) { - if (k_delayed_work_init(&tx->resend, ble_adv_resend)) { - /* If failed to create a timer, the BLE adv packet will be - * sent only once. Just give a warning here, and since the - * BLE adv packet can be sent, return 0 here. - */ - BT_WARN("Send BLE adv packet only once"); - tx->param.count = 0; - net_buf_unref(buf); - return 0; - } - bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT); - } else { - /* Send the BLE advertising packet only once */ - net_buf_unref(buf); - } - - return 0; -} - -int bt_mesh_stop_ble_advertising(uint8_t index) -{ - struct ble_adv_tx *tx = NULL; - bool unref = true; - - if (index >= ARRAY_SIZE(ble_adv_tx)) { - BT_ERR("Invalid adv index %d", index); - return -EINVAL; - } - - tx = &ble_adv_tx[index]; - - if (tx->buf == NULL) { - BT_WARN("Already stopped, index %d", index); - return 0; - } - - /* busy 1, ref 1; busy 1, ref 2; - * busy 0, ref 0; busy 0, ref 1; - */ - - if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf)) && - tx->buf->ref == 1U) { - unref = false; - } - ble_adv_tx_reset(tx, unref); - - return 0; -} - -#if CONFIG_BLE_MESH_DEINIT -static void bt_mesh_ble_adv_deinit(void) -{ - for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) { - struct ble_adv_tx *tx = &ble_adv_tx[i]; - ble_adv_tx_reset(tx, false); - } - bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool); - memset(ble_adv_pool, 0, sizeof(ble_adv_pool)); -} -#endif /* CONFIG_BLE_MESH_DEINIT */ -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ diff --git a/components/bt/esp_ble_mesh/core/adv.h b/components/bt/esp_ble_mesh/core/adv.h index e249eed1b1..79f8ca2991 100644 --- a/components/bt/esp_ble_mesh/core/adv.h +++ b/components/bt/esp_ble_mesh/core/adv.h @@ -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_ */ diff --git a/components/bt/esp_ble_mesh/core/adv_common.c b/components/bt/esp_ble_mesh/core/adv_common.c index ff4e50ac1c..cd6157e3bc 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.c +++ b/components/bt/esp_ble_mesh/core/adv_common.c @@ -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) { diff --git a/components/bt/esp_ble_mesh/core/adv_common.h b/components/bt/esp_ble_mesh/core/adv_common.h index 54267ee522..c52fc18cc3 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.h +++ b/components/bt/esp_ble_mesh/core/adv_common.h @@ -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); diff --git a/components/bt/esp_ble_mesh/core/beacon.c b/components/bt/esp_ble_mesh/core/beacon.c index e58214c0c3..32e31f10a9 100644 --- a/components/bt/esp_ble_mesh/core/beacon.c +++ b/components/bt/esp_ble_mesh/core/beacon.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/ble_adv.h b/components/bt/esp_ble_mesh/core/ble_adv.h new file mode 100644 index 0000000000..733320d608 --- /dev/null +++ b/components/bt/esp_ble_mesh/core/ble_adv.h @@ -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_ */ diff --git a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index 1803b56a5a..c04206e657 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA * SPDX-FileCopyrightText: 2015-2016 Intel Corporation - * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,20 +17,14 @@ #include "p_256_ecc_pp.h" #include "osi/future.h" #include "device/controller.h" - -#if CONFIG_MBEDTLS_HARDWARE_AES -#include "mbedtls/aes.h" -#endif - -#include -#include - #include "mesh/hci.h" #include "mesh/adapter.h" #include "mesh/common.h" #include "prov_pvnr.h" +#include "scan.h" #include "net.h" #include "beacon.h" +#include "btc_ble_mesh_ble.h" #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" @@ -54,13 +48,12 @@ struct bt_mesh_dev bt_mesh_dev; */ #define BLE_MESH_DEV 0 -/* P-256 Variables */ -static uint8_t bt_mesh_public_key[64]; -static uint8_t bt_mesh_private_key[32]; - /* Scan related functions */ static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb; + +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); +#endif #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER || \ @@ -104,6 +97,16 @@ static struct bt_mesh_prov_conn_cb *bt_mesh_gattc_conn_cb; static tBTA_GATTC_IF bt_mesh_gattc_if; #endif +#if CONFIG_BLE_MESH_USE_BLE_50 && \ + CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ + (!CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) +static inline void bt_mesh_set_ble_adv_running(); + +static inline void bt_mesh_unset_ble_adv_running(); + +static inline bool bt_mesh_is_ble_adv_running(); +#endif + int bt_mesh_host_init(void) { return 0; @@ -138,11 +141,18 @@ void bt_mesh_hci_init(void) const uint8_t *p = controller_get_interface()->get_ble_supported_states(); uint64_t states_fh = 0, states_sh = 0; - STREAM_TO_UINT32(states_fh, p); - STREAM_TO_UINT32(states_sh, p); + + /* macro STREAM_TO_UINT32 expansion */ + states_fh = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); + (p) += 4; + + states_sh = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); + (p) += 4; + bt_mesh_dev.le.states = (states_sh << 32) | states_fh; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_results_change_2_bta(tBTM_INQ_RESULTS *p_inq, uint8_t *p_eir, tBTA_DM_SEARCH_CBACK *p_scan_cback) { @@ -185,6 +195,252 @@ static void bt_mesh_scan_results_cb(tBTM_INQ_RESULTS *p_inq, uint8_t *p_eir) { bt_mesh_scan_results_change_2_bta(p_inq, p_eir, bt_mesh_scan_result_callback); } +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 +extern void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, + tBTA_DM_BLE_5_GAP_CB_PARAMS *params); + +void bt_mesh_ble_ext_adv_report(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report) +{ +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + bt_mesh_ble_adv_report_t adv_rpt = {0}; + + if (bt_mesh_ble_scan_state_get()) { + memcpy(adv_rpt.addr, ext_adv_report->addr, BLE_MESH_ADDR_LEN); + memcpy(adv_rpt.dir_addr, ext_adv_report->dir_addr, BLE_MESH_ADDR_LEN); + + adv_rpt.addr_type = ext_adv_report->addr_type; + adv_rpt.data = ext_adv_report->adv_data_len ? ext_adv_report->adv_data : NULL; + adv_rpt.length = ext_adv_report->adv_data_len; + adv_rpt.rssi = ext_adv_report->rssi; + adv_rpt.event_type = ext_adv_report->event_type; + adv_rpt.primary_phy = ext_adv_report->primary_phy; + adv_rpt.secondary_phy = ext_adv_report->secondry_phy; + adv_rpt.sid = ext_adv_report->sid; + adv_rpt.tx_power = ext_adv_report->tx_power; + adv_rpt.dir_addr_type = ext_adv_report->dir_addr_type; + adv_rpt.data_status = ext_adv_report->data_status; + adv_rpt.per_adv_interval = ext_adv_report->per_adv_interval; + + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ +} + +#if CONFIG_BLE_MESH_LONG_PACKET +static struct { + struct bt_mesh_adv_report adv_rpt; + uint8_t adv_data_len; + uint8_t adv_data[2 + CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN]; +} adv_report_cache; +#endif /* CONFIG_BLE_MESH_LONG_PACKET */ + +static bool bt_mesh_scan_result_process(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report) +{ + struct bt_mesh_adv_report adv_rpt = {0}; + uint8_t *adv_data = NULL; + uint8_t adv_data_len = 0; + + assert(ext_adv_report); + + adv_rpt.addr.type = ext_adv_report->addr_type; + memcpy(adv_rpt.addr.val, ext_adv_report->addr, BLE_MESH_ADDR_LEN); + adv_rpt.primary_phy = ext_adv_report->primary_phy; + adv_rpt.secondary_phy = ext_adv_report->secondry_phy; + adv_rpt.rssi = ext_adv_report->rssi; + adv_rpt.tx_power = ext_adv_report->tx_power; + adv_data = ext_adv_report->adv_data; + adv_data_len = ext_adv_report->adv_data_len; + +#if !CONFIG_BLE_MESH_EXT_ADV + if (!(ext_adv_report->event_type & BTM_BLE_ADV_LEGACY_MASK)) { + return false; + } +#endif + + BT_DBG("Recv adv report type %04x", ext_adv_report->event_type); + + if (ext_adv_report->adv_data_len > BLE_MESH_GAP_ADV_MAX_LEN) { + return false; + } + + switch (ext_adv_report->event_type) { + case BLE_MESH_ADV_IND: + case BLE_MESH_ADV_DIRECT_IND: + case BLE_MESH_ADV_SCAN_IND: + case BLE_MESH_ADV_NONCONN_IND: + case BLE_MESH_ADV_SCAN_RSP: +#if CONFIG_BLE_MESH_EXT_ADV + case BLE_MESH_EXT_ADV_NONCONN_IND: +#endif + adv_rpt.adv_type = ext_adv_report->event_type; + break; + default: + return false; + break; + } + +#if CONFIG_BLE_MESH_LONG_PACKET + switch (ext_adv_report->data_status) { + case BTM_BLE_EXT_ADV_DATA_COMPLETE: + if (adv_report_cache.adv_data_len) { + memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len, + ext_adv_report->adv_data, ext_adv_report->adv_data_len); + adv_report_cache.adv_data_len += ext_adv_report->adv_data_len; + adv_data = adv_report_cache.adv_data; + adv_data_len = adv_report_cache.adv_data_len; + adv_report_cache.adv_data_len = 0; + } + break; + case BTM_BLE_EXT_ADV_DATA_INCOMPLETE: + if ((adv_report_cache.adv_data_len + ext_adv_report->adv_data_len) > BLE_MESH_GAP_ADV_MAX_LEN) { + adv_report_cache.adv_data_len = 0; + return false; + } + if (adv_report_cache.adv_data_len == 0) { + memcpy(&adv_report_cache.adv_rpt, &adv_rpt, sizeof(struct bt_mesh_adv_report)); + } + memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len, + ext_adv_report->adv_data, ext_adv_report->adv_data_len); + adv_report_cache.adv_data_len += ext_adv_report->adv_data_len; + /* To avoid discarding user's packets, + * it is assumed here that this packet + * is not mesh's packet */ + return false; + case BTM_BLE_EXT_ADV_DATA_TRUNCATED: + if (adv_report_cache.adv_data_len) { + memset(&adv_report_cache, 0, sizeof(adv_report_cache)); + } + return false; + default: + assert(0); + } +#else /* CONFIG_BLE_MESH_LONG_PACKET */ + if (ext_adv_report->data_status != BTM_BLE_EXT_ADV_DATA_COMPLETE) { + return false; + } +#endif /* CONFIG_BLE_MESH_LONG_PACKET */ + + if (bt_mesh_scan_dev_found_cb) { + net_buf_simple_init_with_data(&adv_rpt.adv_data, adv_data, adv_data_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + if (adv_rpt.adv_data.len != adv_data_len) { + /* The advertising data has been processed by Mesh Protocol */ + return true; + } + } + return false; +} + +void ble_mesh_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, + tBTA_DM_BLE_5_GAP_CB_PARAMS *params) +{ + BT_DBG("recv event %d", event); + + switch (event) { + case BTA_DM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->set_params.instance)) { + goto transfer_to_user; + } + if (params->set_params.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_data_set.instance)) { + goto transfer_to_user; + } + if (params->adv_data_set.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->scan_rsp_data_set.instance)) { + goto transfer_to_user; + } + if (params->scan_rsp_data_set.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_start.instance[0])) { + goto transfer_to_user; + } + if (params->adv_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_start.instance[0])) { + goto transfer_to_user; + } + if (params->adv_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_ADV_TERMINATED_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_term.adv_handle)) { + goto transfer_to_user; + } +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(params->adv_term.adv_handle)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + if (params->adv_term.status == 0x43 || /* Limit reached */ + params->adv_term.status == 0x3C) { /* Advertising timeout */ + bt_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + params->adv_term.status == 0x00) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + bt_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_REPORT_EVT: + if (!bt_mesh_scan_result_process(¶ms->ext_adv_report)) { + bt_mesh_ble_ext_adv_report(¶ms->ext_adv_report); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT: + if (params->scan_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_STOP_COMPLETE_EVT: + if (params->scan_stop.status != BTM_SUCCESS) { + BT_ERR("BTM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT Failed"); + } + break; + default: + goto transfer_to_user; + } + + return; + +transfer_to_user: + btc_ble_5_gap_callback(event, params); +} +#endif static bool valid_adv_param(const struct bt_mesh_adv_param *param) { @@ -205,7 +461,12 @@ static bool valid_adv_param(const struct bt_mesh_adv_param *param) return true; } +#if CONFIG_BLE_MESH_USE_BLE_50 +static int set_adv_data(uint16_t hci_op, const uint8_t inst_id, + const struct bt_mesh_adv_data *ad, size_t ad_len) +#else static int set_adv_data(uint16_t hci_op, const struct bt_mesh_adv_data *ad, size_t ad_len) +#endif { struct bt_mesh_hci_cp_set_adv_data param = {0}; int i; @@ -216,7 +477,7 @@ static int set_adv_data(uint16_t hci_op, const struct bt_mesh_adv_data *ad, size for (i = 0; i < ad_len; i++) { /* Check if ad fit in the remaining buffer */ - if (param.len + ad[i].data_len + 2 > 31) { + if (param.len + ad[i].data_len + 2 > sizeof(param.data)) { return -EINVAL; } @@ -227,16 +488,22 @@ static int set_adv_data(uint16_t hci_op, const struct bt_mesh_adv_data *ad, size param.len += ad[i].data_len; } +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapConfigExtAdvDataRaw(hci_op == BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, + inst_id, param.len, param.data); +#else /* Set adv data and scan rsp data. */ if (hci_op == BLE_MESH_HCI_OP_SET_ADV_DATA) { BLE_MESH_BTM_CHECK_STATUS(BTM_BleWriteAdvDataRaw(param.data, param.len)); } else if (hci_op == BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA) { BLE_MESH_BTM_CHECK_STATUS(BTM_BleWriteScanRspRaw(param.data, param.len)); } +#endif return 0; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void start_adv_completed_cb(uint8_t status) { #if BLE_MESH_DEV @@ -245,6 +512,7 @@ static void start_adv_completed_cb(uint8_t status) } #endif } +#endif static bool valid_scan_param(const struct bt_mesh_scan_param *param) { @@ -276,15 +544,54 @@ static bool valid_scan_param(const struct bt_mesh_scan_param *param) static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t filter_dup, uint8_t scan_fil_policy) { +#if !CONFIG_BLE_MESH_USE_BLE_50 uint8_t addr_type_own = BLE_MESH_ADDR_PUBLIC; /* Currently only support Public Address */ tGATT_IF client_if = 0xFF; /* Default GATT interface id */ +#endif +#if CONFIG_BLE_MESH_USE_BLE_50 + tBTA_DM_BLE_EXT_SCAN_PARAMS ext_scan_params = {0}; + + if (interval == 0 || + interval < window) { + BT_ERR("invalid scan param itvl %d win %d", interval, window); + return EINVAL; + } + + ext_scan_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; + ext_scan_params.filter_policy = scan_fil_policy; + ext_scan_params.scan_duplicate = filter_dup; + + if (window == 0) { + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_CODE_MASK; + } else if (interval > window) { + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_UNCODE_MASK | BTM_BLE_GAP_EXT_SCAN_CODE_MASK; + } else { + // interval == window + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_UNCODE_MASK; + } + + ext_scan_params.uncoded_cfg.scan_type = scan_type; + ext_scan_params.uncoded_cfg.scan_interval = interval; + ext_scan_params.uncoded_cfg.scan_window = window; + + ext_scan_params.coded_cfg.scan_type = scan_type; + ext_scan_params.coded_cfg.scan_interval = interval; + ext_scan_params.coded_cfg.scan_window = interval - window; + + BTA_DmBleGapSetExtScanParams(&ext_scan_params); + + BTM_BleGapRegisterCallback(ble_mesh_5_gap_callback); + + BTA_DmBleGapExtScan(true, 0, 0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ BLE_MESH_BTM_CHECK_STATUS( BTM_BleSetScanFilterParams(client_if, interval, window, scan_type, addr_type_own, filter_dup, scan_fil_policy, NULL)); /* BLE Mesh scan permanently, so no duration of scan here */ BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(true, 0, bt_mesh_scan_results_cb, NULL, NULL)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if BLE_MESH_DEV if (scan_type == BLE_MESH_SCAN_ACTIVE) { @@ -297,22 +604,32 @@ static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, return 0; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { - struct net_buf_simple buf = {0}; - bt_mesh_addr_t addr = {0}; + struct bt_mesh_adv_report adv_rpt = {0}; BT_DBG("%s, event %d", __func__, event); if (event == BTA_DM_INQ_RES_EVT) { /* TODO: How to process scan response here? PS: p_data->inq_res.scan_rsp_len */ - addr.type = p_data->inq_res.ble_addr_type; - memcpy(addr.val, p_data->inq_res.bd_addr, BLE_MESH_ADDR_LEN); - net_buf_simple_init_with_data(&buf, p_data->inq_res.p_eir, p_data->inq_res.adv_data_len); + adv_rpt.addr.type = p_data->inq_res.ble_addr_type; + adv_rpt.rssi = p_data->inq_res.rssi; + adv_rpt.adv_type = p_data->inq_res.ble_evt_type; + + memcpy(adv_rpt.addr.val, p_data->inq_res.bd_addr, BLE_MESH_ADDR_LEN); + + net_buf_simple_init_with_data(&adv_rpt.adv_data, p_data->inq_res.p_eir, p_data->inq_res.adv_data_len); if (bt_mesh_scan_dev_found_cb) { - bt_mesh_scan_dev_found_cb(&addr, p_data->inq_res.rssi, p_data->inq_res.ble_evt_type, &buf, p_data->inq_res.scan_rsp_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + + if (p_data->inq_res.scan_rsp_len) { + adv_rpt.adv_type = BLE_MESH_ADV_SCAN_RSP; + net_buf_simple_init_with_data(&adv_rpt.adv_data, p_data->inq_res.p_eir + p_data->inq_res.adv_data_len, p_data->inq_res.scan_rsp_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + } } } else if (event == BTA_DM_INQ_CMPL_EVT) { BT_INFO("Scan completed, number of scan response %d", p_data->inq_cmpl.num_resps); @@ -320,14 +637,157 @@ static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARC BT_WARN("Unexpected scan result event %d", event); } } +#endif +#if CONFIG_BLE_MESH_USE_BLE_50 +static struct { + bool set; + tBTA_DM_BLE_GAP_EXT_ADV_PARAMS param; +} last_param[BLE_MESH_ADV_INST_TYPES_NUM]; + +int bt_le_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_adv_param *param, + const struct bt_mesh_adv_data *ad, size_t ad_len, + const struct bt_mesh_adv_data *sd, size_t sd_len) +{ + tBTA_DM_BLE_GAP_EXT_ADV_PARAMS ext_adv_params = {0}; + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + uint16_t interval = 0U; + int err = 0; + + assert(param); + +#if BLE_MESH_DEV + if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return -EALREADY; + } +#endif + + if (!valid_adv_param(param)) { + BT_ERR("Invalid adv parameters"); + return -EINVAL; + } + + memset(&ext_adv_params, 0, sizeof(tBTA_DM_BLE_GAP_EXT_ADV_PARAMS)); + + if (param->options & BLE_MESH_ADV_OPT_CONNECTABLE) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND; + } else if (sd != NULL) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_SCAN; + } else { + if (param->primary_phy == BLE_MESH_ADV_PHY_1M && + param->secondary_phy == BLE_MESH_ADV_PHY_1M && + param->include_tx_power == false && + ad->data_len <= 29) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN; + } + } + +#if CONFIG_BLE_MESH_PRB_SRV + /* NOTE: When a Mesh Private beacon is advertised, the Mesh Private beacon shall + * use a resolvable private address or a non-resolvable private address in the + * AdvA field of the advertising PDU. + */ + if (ad->type == BLE_MESH_DATA_MESH_BEACON && ad->data[0] == BEACON_TYPE_PRIVATE) { + ext_adv_params.own_addr_type = BLE_MESH_ADDR_RANDOM; + } else { + ext_adv_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; + } +#else + ext_adv_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; +#endif + + ext_adv_params.sid = inst_id; + ext_adv_params.max_skip = 0; + ext_adv_params.tx_power = param->tx_power; + ext_adv_params.scan_req_notif = false; + ext_adv_params.primary_phy = param->primary_phy; + ext_adv_params.secondary_phy = param->secondary_phy; + ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + ext_adv_params.channel_map = param->channel_map; + + if (param->include_tx_power) { + ext_adv_params.type |= BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_INCLUDE_TX_PWR; + } + + interval = param->interval_min; + +#if CONFIG_BLE_MESH_RANDOM_ADV_INTERVAL + /* If non-connectable mesh packets are transmitted with an adv interval + * not smaller than 10ms, then we will use a random adv interval between + * [interval / 2, interval] for them. + */ + if (ext_adv_params.type == BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN + && interval >= 16) { + interval >>= 1; + interval += (bt_mesh_get_rand() % (interval + 1)); + + BT_DBG("%u->%u", param->interval_min, interval); + } +#endif + + ext_adv_params.interval_min = interval; + ext_adv_params.interval_max = interval; + + if (memcmp(&ext_adv_params, &last_param[inst_id].param, sizeof(tBTA_DM_BLE_GAP_EXT_ADV_PARAMS))) { + if (last_param[inst_id].set) { + BTA_DmBleGapExtAdvSetRemove(inst_id); + } + + last_param[inst_id].set = true; + + /* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */ + BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params); + + memcpy(&last_param[inst_id].param, &ext_adv_params, sizeof(tBTA_DM_BLE_GAP_EXT_ADV_PARAMS)); + } + + err = set_adv_data(BLE_MESH_HCI_OP_SET_ADV_DATA, inst_id, ad, ad_len); + if (err) { + BT_ERR("Failed to set adv data, err %d", err); + return err; + } + + /* + * We need to set SCAN_RSP when enabling advertising type that allows + * for Scan Requests. + * + * If sd was not provided but we enable connectable undirected + * advertising sd needs to be cleared from values set by previous calls. + * Clearing sd is done by calling set_adv_data() with NULL data and zero len. + * So following condition check is unusual but correct. + */ + if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { + err = set_adv_data(BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, inst_id, sd, sd_len); + if (err) { + BT_ERR("Failed to set scan rsp data err %d", err); + return err; + } + } + + ext_adv.instance = inst_id; + ext_adv.duration = param->adv_duration / 10; + ext_adv.max_events = param->adv_count; + + BTA_DmBleGapExtAdvEnable(true, 1, &ext_adv); + +#if BLE_MESH_DEV + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); + + if (!(param->options & BLE_MESH_ADV_OPT_ONE_TIME)) { + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + } +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* APIs functions */ 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) { tBTA_START_ADV_CMPL_CBACK *p_start_adv_cb = NULL; - tBTM_BLE_ADV_CHNL_MAP channel_map = 0U; tBLE_ADDR_TYPE addr_type_own = 0U; tBLE_BD_ADDR p_dir_bda = {0}; tBTM_BLE_AFP adv_fil_pol = 0U; @@ -348,7 +808,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, err = set_adv_data(BLE_MESH_HCI_OP_SET_ADV_DATA, ad, ad_len); if (err) { - BT_ERR("Failed to set adv data"); + BT_ERR("Failed to set adv data, err %d", err); return err; } @@ -364,7 +824,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { err = set_adv_data(BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, sd, sd_len); if (err) { - BT_ERR("Failed to set scan rsp data"); + BT_ERR("Failed to set scan rsp data, err %d", err); return err; } } @@ -391,7 +851,6 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, addr_type_own = BLE_MESH_ADDR_PUBLIC; #endif - channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; adv_fil_pol = BLE_MESH_AP_SCAN_CONN_ALL; p_start_adv_cb = start_adv_completed_cb; @@ -414,7 +873,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, BLE_MESH_BTM_CHECK_STATUS( BTM_BleSetAdvParamsAll(interval, interval, adv_type, addr_type_own, &p_dir_bda, - channel_map, adv_fil_pol, p_start_adv_cb)); + param->channel_map, adv_fil_pol, p_start_adv_cb)); BLE_MESH_BTM_CHECK_STATUS(BTM_BleStartAdv()); #if BLE_MESH_DEV @@ -427,8 +886,100 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +#if CONFIG_BLE_MESH_USE_BLE_50 +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +static bool _ble_adv_running_flag; + +static inline void bt_mesh_set_ble_adv_running() +{ + _ble_adv_running_flag = true; +} + +static inline void bt_mesh_unset_ble_adv_running() +{ + _ble_adv_running_flag = false; +} + +static inline bool bt_mesh_is_ble_adv_running() +{ + return _ble_adv_running_flag == true; +} +#endif /* !CONFIG_BLE_MESH_SUPPORT_MULTI_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 *data) +{ + tBTA_DM_BLE_GAP_EXT_ADV_PARAMS ext_adv_params = {0}; + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + struct bt_mesh_hci_cp_set_adv_data set = {0}; + + switch (param->adv_type) { + case BLE_MESH_ADV_IND: + case BLE_MESH_ADV_DIRECT_IND: + case BLE_MESH_ADV_SCAN_IND: + case BLE_MESH_ADV_NONCONN_IND: + case BLE_MESH_ADV_SCAN_RSP: + ext_adv_params.type = param->adv_type; + break; + default: + BT_ERR("Unsupported adv type %d", param->adv_type); + return -EINVAL; + } + + ext_adv_params.max_skip = 0; + ext_adv_params.tx_power = 0x7F; + ext_adv_params.sid = inst_id; + ext_adv_params.scan_req_notif = false; + ext_adv_params.own_addr_type = param->own_addr_type; + ext_adv_params.interval_min = param->interval; + ext_adv_params.interval_max = param->interval; + ext_adv_params.primary_phy = BLE_MESH_ADV_PHY_1M; + ext_adv_params.secondary_phy = BLE_MESH_ADV_PHY_1M; + ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + ext_adv_params.channel_map = BLE_MESH_ADV_CHAN_37 | BLE_MESH_ADV_CHAN_38 | BLE_MESH_ADV_CHAN_39; + + if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || + param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || + param->adv_type == BLE_MESH_ADV_DIRECT_IND || + param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + ext_adv_params.peer_addr_type = param->peer_addr_type; + memcpy(ext_adv_params.peer_addr, param->peer_addr, BLE_MESH_ADDR_LEN); + } + + ext_adv.instance = inst_id; + ext_adv.duration = param->duration; + ext_adv.max_events = param->count; + + /* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */ + BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params); + + if (data && param->adv_type != BLE_MESH_ADV_DIRECT_IND && + param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + if (data->adv_data_len) { + set.len = data->adv_data_len; + memcpy(set.data, data->adv_data, data->adv_data_len); + BTA_DmBleGapConfigExtAdvDataRaw(false, inst_id, set.len, set.data); + } + if (data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) { + set.len = data->scan_rsp_data_len; + memcpy(set.data, data->scan_rsp_data, data->scan_rsp_data_len); + BTA_DmBleGapConfigExtAdvDataRaw(true, inst_id, set.len, set.data); + } + } + + BTA_DmBleGapExtAdvEnable(true, 1, &ext_adv); + +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_set_ble_adv_running(); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data) { @@ -451,7 +1002,7 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, } } - channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + channel_map = BLE_MESH_ADV_CHAN_37 | BLE_MESH_ADV_CHAN_38 | BLE_MESH_ADV_CHAN_39; adv_fil_pol = BLE_MESH_AP_SCAN_CONN_ALL; if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || @@ -470,8 +1021,32 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_stop(uint8_t inst_id) +{ + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return 0; + } +#endif + + ext_adv.instance = inst_id; + + BTA_DmBleGapExtAdvEnable(false, 1, &ext_adv); + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_adv_stop(void) { #if BLE_MESH_DEV @@ -489,6 +1064,7 @@ int bt_le_adv_stop(void) return 0; } +#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) { @@ -530,7 +1106,11 @@ int bt_le_scan_stop(void) return -EALREADY; } +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(false, 0 ,0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(false, 0, NULL, NULL, NULL)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); bt_mesh_scan_dev_found_cb = NULL; @@ -657,6 +1237,19 @@ static void bt_mesh_bta_gatts_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) /* When connection is created, advertising will be stopped automatically. */ bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); #endif + +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) + /* Check if this connection is created by Proxy client */ + for (size_t i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, p_data->conn.remote_bda, BLE_MESH_ADDR_LEN)) { + BT_WARN("Already create connection with %s by proxy client", + bt_hex(p_data->conn.remote_bda, BLE_MESH_ADDR_LEN)); + return; + } + } +#endif if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->connected != NULL) { uint8_t index = BLE_MESH_GATT_GET_CONN_ID(p_data->conn.conn_id); if (index < BLE_MESH_MAX_CONN) { @@ -1241,12 +1834,37 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) } if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(false, 0 ,0); +#else BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(false, 0, NULL, NULL, NULL)); +#endif bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); } BT_DBG("Create conn with %s", bt_hex(addr->val, BLE_MESH_ADDR_LEN)); +#if CONFIG_BLE_MESH_USE_BLE_50 + /* Min_interval: 15ms + * Max_interval: 15ms + * Slave_latency: 0x0 + * Supervision_timeout: 1s + */ + conn_1m_param.scan_interval = 0x0020; + conn_1m_param.scan_window = 0x0020; + conn_1m_param.interval_min = 0x18; + conn_1m_param.interval_max = 0x18; + conn_1m_param.latency = 0; + conn_1m_param.supervision_timeout = 0x64; + conn_1m_param.min_ce_len = 0; + conn_1m_param.max_ce_len = 0; + + BTA_GATTC_Enh_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, + bt_mesh_gattc_info[i].addr.type, true, + BTA_GATT_TRANSPORT_LE, TRUE, BLE_ADDR_UNKNOWN_TYPE, + false, 0xFF, 0xFF, + BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* Min_interval: 15ms * Max_interval: 15ms * Slave_latency: 0x0 @@ -1258,9 +1876,11 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) conn_1m_param.supervision_timeout = 0x64; BTA_GATTC_Enh_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, - bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, - false, 0xFF, 0xFF, - BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); + bt_mesh_gattc_info[i].addr.type, true, + BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, + false, 0xFF, 0xFF, + BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; } @@ -1663,11 +2283,15 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) * use BTM_BleScan() to re-enable scan. */ if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(true, 0 ,0); +#else tBTM_STATUS status = BTM_BleScan(true, 0, bt_mesh_scan_results_cb, NULL, NULL); if (status != BTM_SUCCESS && status != BTM_CMD_STARTED) { BT_ERR("Invalid scan status %d", status); break; } +#endif bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); } break; @@ -1845,185 +2469,9 @@ void bt_mesh_gatt_deinit(void) void bt_mesh_adapt_init(void) { - /* initialization of P-256 parameters */ - p_256_init_curve(KEY_LENGTH_DWORDS_P256); - - /* Set "bt_mesh_dev.flags" to 0 (only the "BLE_MESH_DEV_HAS_PUB_KEY" - * flag is used) here, because we need to make sure each time after - * the private key is initialized, a corresponding public key must - * be generated. - */ + /* Use unified crypto module initialization */ + bt_mesh_crypto_init(); bt_mesh_atomic_set(bt_mesh_dev.flags, 0); - bt_mesh_rand(bt_mesh_private_key, sizeof(bt_mesh_private_key)); -} - -void bt_mesh_set_private_key(const uint8_t pri_key[32]) -{ - memcpy(bt_mesh_private_key, pri_key, 32); -} - -const uint8_t *bt_mesh_pub_key_get(void) -{ - uint8_t private_key[32] = {0}; - Point public_key = {0}; - - if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_HAS_PUB_KEY)) { - return bt_mesh_public_key; - } - - /* BLE Mesh BQB test case MESH/NODE/PROV/UPD/BV-12-C requires - * different public key for each provisioning procedure. - * Note: if enabled, when Provisioner provision multiple devices - * at the same time, this may cause invalid confirmation value. - * - * Use the following code for generating different private key - * for each provisioning procedure. - * - * if (bt_mesh_rand(bt_mesh_private_key, BT_OCTET32_LEN)) { - * BT_ERR("%s, Unable to generate bt_mesh_private_key", __func__); - * return NULL; - * } - */ - - memcpy(private_key, bt_mesh_private_key, BT_OCTET32_LEN); - ECC_PointMult(&public_key, &(curve_p256.G), (DWORD *)private_key, KEY_LENGTH_DWORDS_P256); - - memcpy(bt_mesh_public_key, public_key.x, BT_OCTET32_LEN); - memcpy(bt_mesh_public_key + BT_OCTET32_LEN, public_key.y, BT_OCTET32_LEN); - - bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_HAS_PUB_KEY); - - BT_DBG("Public Key %s", bt_hex(bt_mesh_public_key, sizeof(bt_mesh_public_key))); - - return bt_mesh_public_key; -} - -bool bt_mesh_check_public_key(const uint8_t key[64]) -{ - struct p256_pub_key { - uint8_t x[32]; - uint8_t y[32]; - } check = {0}; - - sys_memcpy_swap(check.x, key, 32); - sys_memcpy_swap(check.y, key + 32, 32); - - return ECC_CheckPointIsInElliCur_P256((Point *)&check); -} - -int bt_mesh_dh_key_gen(const uint8_t remote_pub_key[64], uint8_t dhkey[32]) -{ - uint8_t private_key[32] = {0}; - Point peer_pub_key = {0}; - Point new_pub_key = {0}; - - BT_DBG("private key = %s", bt_hex(bt_mesh_private_key, BT_OCTET32_LEN)); - - memcpy(private_key, bt_mesh_private_key, BT_OCTET32_LEN); - memcpy(peer_pub_key.x, remote_pub_key, BT_OCTET32_LEN); - memcpy(peer_pub_key.y, &remote_pub_key[BT_OCTET32_LEN], BT_OCTET32_LEN); - - BT_DBG("remote public key x = %s", bt_hex(peer_pub_key.x, BT_OCTET32_LEN)); - BT_DBG("remote public key y = %s", bt_hex(peer_pub_key.y, BT_OCTET32_LEN)); - - ECC_PointMult(&new_pub_key, &peer_pub_key, (DWORD *)private_key, KEY_LENGTH_DWORDS_P256); - - BT_DBG("new public key x = %s", bt_hex(new_pub_key.x, 32)); - BT_DBG("new public key y = %s", bt_hex(new_pub_key.y, 32)); - - memcpy(dhkey, new_pub_key.x, 32); - - return 0; -} - -int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16], - uint8_t enc_data[16]) -{ - uint8_t tmp[16] = {0}; - - BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16)); - -#if CONFIG_MBEDTLS_HARDWARE_AES - mbedtls_aes_context ctx = {0}; - - mbedtls_aes_init(&ctx); - - sys_memcpy_swap(tmp, key, 16); - - if (mbedtls_aes_setkey_enc(&ctx, tmp, 128) != 0) { - mbedtls_aes_free(&ctx); - return -EINVAL; - } - - sys_memcpy_swap(tmp, plaintext, 16); - - if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, - tmp, enc_data) != 0) { - mbedtls_aes_free(&ctx); - return -EINVAL; - } - - mbedtls_aes_free(&ctx); -#else /* CONFIG_MBEDTLS_HARDWARE_AES */ - struct tc_aes_key_sched_struct s = {0}; - - sys_memcpy_swap(tmp, key, 16); - - if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) { - return -EINVAL; - } - - sys_memcpy_swap(tmp, plaintext, 16); - - if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) { - return -EINVAL; - } -#endif /* CONFIG_MBEDTLS_HARDWARE_AES */ - - 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]) -{ - BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16)); - -#if CONFIG_MBEDTLS_HARDWARE_AES - mbedtls_aes_context ctx = {0}; - - mbedtls_aes_init(&ctx); - - if (mbedtls_aes_setkey_enc(&ctx, key, 128) != 0) { - mbedtls_aes_free(&ctx); - return -EINVAL; - } - - if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, - plaintext, enc_data) != 0) { - mbedtls_aes_free(&ctx); - return -EINVAL; - } - - mbedtls_aes_free(&ctx); -#else /* CONFIG_MBEDTLS_HARDWARE_AES */ - struct tc_aes_key_sched_struct s = {0}; - - if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) { - return -EINVAL; - } - - if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) { - return -EINVAL; - } -#endif /* CONFIG_MBEDTLS_HARDWARE_AES */ - - BT_DBG("enc_data %s", bt_hex(enc_data, 16)); - - return 0; } #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN diff --git a/components/bt/esp_ble_mesh/core/cfg_cli.c b/components/bt/esp_ble_mesh/core/cfg_cli.c index c0968428d2..211f80e9ed 100644 --- a/components/bt/esp_ble_mesh/core/cfg_cli.c +++ b/components/bt/esp_ble_mesh/core/cfg_cli.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/cfg_srv.c b/components/bt/esp_ble_mesh/core/cfg_srv.c index d8be5f0424..9be3e51983 100644 --- a/components/bt/esp_ble_mesh/core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/core/cfg_srv.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/crypto.c b/components/bt/esp_ble_mesh/core/crypto.c index a9991e324b..6066ef15c6 100644 --- a/components/bt/esp_ble_mesh/core/crypto.c +++ b/components/bt/esp_ble_mesh/core/crypto.c @@ -11,12 +11,6 @@ #include #include -#include -#include -#include -#include -#include - #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, diff --git a/components/bt/esp_ble_mesh/core/crypto.h b/components/bt/esp_ble_mesh/core/crypto.h index 69627c956b..ac6924c4f1 100644 --- a/components/bt/esp_ble_mesh/core/crypto.h +++ b/components/bt/esp_ble_mesh/core/crypto.h @@ -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 #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]) { diff --git a/components/bt/esp_ble_mesh/core/ext_adv.c b/components/bt/esp_ble_mesh/core/ext_adv.c index 8b85076aed..c4feaa7a4e 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.c +++ b/components/bt/esp_ble_mesh/core/ext_adv.c @@ -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); diff --git a/components/bt/esp_ble_mesh/core/ext_adv.h b/components/bt/esp_ble_mesh/core/ext_adv.h index eaa9c4f819..51118fb5d6 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.h +++ b/components/bt/esp_ble_mesh/core/ext_adv.h @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/fast_prov.c b/components/bt/esp_ble_mesh/core/fast_prov.c index 3fe9b74248..5d34db8a09 100644 --- a/components/bt/esp_ble_mesh/core/fast_prov.c +++ b/components/bt/esp_ble_mesh/core/fast_prov.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/friend.c b/components/bt/esp_ble_mesh/core/friend.c index e31810e263..46060d3b0f 100644 --- a/components/bt/esp_ble_mesh/core/friend.c +++ b/components/bt/esp_ble_mesh/core/friend.c @@ -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; diff --git a/components/bt/esp_ble_mesh/core/health_cli.c b/components/bt/esp_ble_mesh/core/health_cli.c index df9685e45f..c458710db1 100644 --- a/components/bt/esp_ble_mesh/core/health_cli.c +++ b/components/bt/esp_ble_mesh/core/health_cli.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/health_srv.c b/components/bt/esp_ble_mesh/core/health_srv.c index 98656586e7..f7db34babb 100644 --- a/components/bt/esp_ble_mesh/core/health_srv.c +++ b/components/bt/esp_ble_mesh/core/health_srv.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/heartbeat.c b/components/bt/esp_ble_mesh/core/heartbeat.c index 444ea285de..4324da3223 100644 --- a/components/bt/esp_ble_mesh/core/heartbeat.c +++ b/components/bt/esp_ble_mesh/core/heartbeat.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/include/mesh/access.h b/components/bt/esp_ble_mesh/core/include/mesh/access.h index 77f0cabde6..6aa64080bd 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/access.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/access.h @@ -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 * diff --git a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h index 5a1e4326a9..506b229f0f 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h @@ -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, diff --git a/components/bt/esp_ble_mesh/core/include/mesh/hci.h b/components/bt/esp_ble_mesh/core/include/mesh/hci.h index 9be507d95e..2d2ecc8a0d 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/hci.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/hci.h @@ -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) diff --git a/components/bt/esp_ble_mesh/core/local.c b/components/bt/esp_ble_mesh/core/local.c index c0fc5b3f45..fb933cc804 100644 --- a/components/bt/esp_ble_mesh/core/local.c +++ b/components/bt/esp_ble_mesh/core/local.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/main.c b/components/bt/esp_ble_mesh/core/main.c index cc5543697e..3b6dcb1402 100644 --- a/components/bt/esp_ble_mesh/core/main.c +++ b/components/bt/esp_ble_mesh/core/main.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index 1b0bfc2b55..b436ce5d6b 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -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) diff --git a/components/bt/esp_ble_mesh/core/net.h b/components/bt/esp_ble_mesh/core/net.h index 493954178f..b5f5ff0a78 100644 --- a/components/bt/esp_ble_mesh/core/net.h +++ b/components/bt/esp_ble_mesh/core/net.h @@ -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); diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c index 42cbec6a54..ac2b16b5d9 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA * SPDX-FileCopyrightText: 2015-2016 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,23 +10,17 @@ #include "btc/btc_task.h" #include "osi/alarm.h" - -#include "mbedtls/aes.h" -#include "mbedtls/ecp.h" - #include "host/ble_hs.h" #include "host/ble_uuid.h" #include "host/ble_att.h" #include "host/ble_gatt.h" #include "services/gap/ble_svc_gap.h" #include "services/gatt/ble_svc_gatt.h" - -#include -#include - #include "mesh/hci.h" #include "mesh/common.h" #include "prov_pvnr.h" +#include "scan.h" +#include "btc_ble_mesh_ble.h" /** @def BT_UUID_MESH_PROV * @brief Mesh Provisioning Service @@ -63,13 +57,8 @@ static uint16_t proxy_svc_start_handle, prov_svc_start_handle; struct bt_mesh_dev bt_mesh_dev; -/* P-256 Variables */ -static uint8_t bt_mesh_public_key[64]; -static uint8_t bt_mesh_private_key[32]; - /* Scan related functions */ static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb; - #if CONFIG_BLE_MESH_NODE /* the gatt database list to save the attribute table */ static sys_slist_t bt_mesh_gatts_db; @@ -79,10 +68,59 @@ static struct bt_mesh_conn bt_mesh_gatts_conn[BLE_MESH_MAX_CONN]; static struct bt_mesh_conn_cb *bt_mesh_gatts_conn_cb; static uint8_t bt_mesh_gatts_addr[6]; + +#if CONFIG_BLE_MESH_USE_BLE_50 +static bool g_gatts_svcs_add = false; +#endif #endif /* CONFIG_BLE_MESH_NODE */ +#if CONFIG_BLE_MESH_USE_BLE_50 && \ + CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ + (!CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) +static inline void bt_mesh_set_ble_adv_running(); + +static inline void bt_mesh_unset_ble_adv_running(); + +static inline bool bt_mesh_is_ble_adv_running(); +#endif + static bool g_host_init = false; +#if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_USE_BLE_50 + +#define BT_MESH_GATTS_CONN_UNUSED 0xFF + +static void bt_mesh_gatts_conn_init(void) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + bt_mesh_gatts_conn[i].handle = BT_MESH_GATTS_CONN_UNUSED; + } +} + +static int bt_mesh_find_free_conn_idx(void) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + if (bt_mesh_gatts_conn[i].handle == BT_MESH_GATTS_CONN_UNUSED) { + return i; + } + } + return -ENOMEM; +} + +static int bt_mesh_find_conn_idx(uint16_t conn_handle) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + if (bt_mesh_gatts_conn[i].handle == conn_handle) { + return i; + } + } + return -ENODEV; +} +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_USE_BLE_50 */ + int bt_mesh_host_init(void) { int rc; @@ -145,7 +183,13 @@ void bt_mesh_hci_init(void) #endif } +#if CONFIG_BLE_MESH_USE_BLE_50 +static struct ble_gap_ext_disc_params uncoded_disc_params; +static struct ble_gap_ext_disc_params coded_disc_params; +#else static struct ble_gap_disc_params scan_param; +#endif + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) @@ -351,13 +395,19 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, } uuid = &service->uuid; - uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); + uuid_length = (uint8_t)(uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); if (uuid_length != 2) { return 0; } for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { - if (bt_mesh_gattc_info[i].service_uuid == (uint16_t)BLE_UUID16(uuid)->value) { + /** + * In scenarios with multiple connections, to prevent + * subsequent connections from affecting the first one, + * a check for the connection handle is needed here. + */ + if (bt_mesh_gattc_info[i].conn.handle == conn_handle && + bt_mesh_gattc_info[i].service_uuid == (uint16_t)BLE_UUID16(uuid)->value) { bt_mesh_gattc_info[i].start_handle = service->start_handle; bt_mesh_gattc_info[i].end_handle = service->end_handle; break; @@ -401,9 +451,53 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, CONFIG_BLE_MESH_GATT_PROXY_CLIENT || (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) */ -static int disc_cb(struct ble_gap_event *event, void *arg) +#if CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_ble_ext_adv_report(struct ble_gap_ext_disc_desc *desc) { +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + bt_mesh_ble_adv_report_t adv_rpt = {0}; + if (bt_mesh_ble_scan_state_get()) { + memcpy(adv_rpt.addr, desc->addr.val, BLE_MESH_ADDR_LEN); + memcpy(adv_rpt.dir_addr, desc->direct_addr.val, BLE_MESH_ADDR_LEN); + + /* Here, only a shallow copy needs to be implemented; + * deep copying behavior occurs in btc_ble_mesh_ble_copy_req_data. */ + adv_rpt.data = desc->length_data ? (uint8_t *)desc->data : NULL; + + adv_rpt.event_type = desc->props; + adv_rpt.addr_type = desc->addr.type; + adv_rpt.length = desc->length_data; + adv_rpt.rssi = desc->rssi; + adv_rpt.primary_phy = desc->prim_phy; + adv_rpt.secondary_phy = desc->sec_phy; + adv_rpt.sid = desc->sid; + adv_rpt.tx_power = desc->tx_power; + adv_rpt.dir_addr_type = desc->direct_addr.type; + adv_rpt.data_status = desc->data_status; + adv_rpt.per_adv_interval = desc->periodic_adv_itvl; + + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ +} +#endif + +#if CONFIG_BLE_MESH_LONG_PACKET +static struct { + struct bt_mesh_adv_report adv_rpt; + uint8_t adv_data_len; + uint8_t adv_data[2 + CONFIG_BLE_MESH_LONG_PACKET_ADV_LEN]; +} adv_report_cache; +#endif + +int disc_cb(struct ble_gap_event *event, void *arg) +{ +#if CONFIG_BLE_MESH_USE_BLE_50 + struct ble_gap_ext_disc_desc *desc; +#else struct ble_gap_disc_desc *desc; +#endif + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) @@ -416,22 +510,114 @@ static int disc_cb(struct ble_gap_event *event, void *arg) #endif switch (event->type) { - case BLE_GAP_EVENT_DISC: { - struct net_buf_simple buf = {0}; +#if CONFIG_BLE_MESH_USE_BLE_50 + case BLE_GAP_EVENT_EXT_DISC: { + struct bt_mesh_adv_report adv_rpt = {0}; + uint8_t *adv_data = NULL; + uint8_t adv_data_len = 0; - desc = &event->disc; - net_buf_simple_init_with_data(&buf, (void *)desc->data, desc->length_data); + desc = &event->ext_disc; + if (desc->length_data > BLE_MESH_GAP_ADV_MAX_LEN) { + /* @todo: bt_mesh_ble_ext_adv_report and transfer + * to user have functional duplication */ + goto report_to_user; + } + memcpy(&adv_rpt.addr, &desc->addr, sizeof(bt_mesh_addr_t)); + adv_rpt.rssi = desc->rssi; + adv_rpt.adv_type = desc->props; + adv_rpt.primary_phy = desc->prim_phy; + adv_rpt.secondary_phy = desc->sec_phy; + adv_rpt.tx_power = desc->tx_power; + adv_data = (uint8_t *)desc->data; + adv_data_len = desc->length_data; + +#if CONFIG_BLE_MESH_LONG_PACKET + switch (desc->data_status) { + case BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE: + if (adv_report_cache.adv_data_len) { + memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len, + desc->data, desc->length_data); + adv_report_cache.adv_data_len += desc->length_data; + adv_data = adv_report_cache.adv_data; + adv_data_len = adv_report_cache.adv_data_len; + adv_report_cache.adv_data_len = 0; + } + break; + case BLE_GAP_EXT_ADV_DATA_STATUS_INCOMPLETE: + if ((adv_report_cache.adv_data_len + desc->length_data) > BLE_MESH_GAP_ADV_MAX_LEN) { + adv_report_cache.adv_data_len = 0; + return false; + } + if (adv_report_cache.adv_data_len == 0) { + memcpy(&adv_report_cache.adv_rpt, &adv_rpt, sizeof(struct bt_mesh_adv_report)); + } + memcpy(adv_report_cache.adv_data + adv_report_cache.adv_data_len, + desc->data, desc->length_data); + adv_report_cache.adv_data_len += desc->length_data; + /* To avoid discarding user's packets, + * it is assumed here that this packet + * is not mesh's packet */ + goto report_to_user; + case BLE_GAP_EXT_ADV_DATA_STATUS_TRUNCATED: + if (adv_report_cache.adv_data_len) { + memset(&adv_report_cache, 0, sizeof(adv_report_cache)); + } + goto report_to_user; + default: + assert(0); + } +#else /* CONFIG_BLE_MESH_LONG_PACKET */ + if (desc->data_status != BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE) { + goto report_to_user; + } +#endif /* CONFIG_BLE_MESH_LONG_PACKET */ + + net_buf_simple_init_with_data(&adv_rpt.adv_data, (void *)adv_data, adv_data_len); if (bt_mesh_scan_dev_found_cb) { /* TODO: Support Scan Response data length for NimBLE host */ - bt_mesh_scan_dev_found_cb((bt_mesh_addr_t *)&desc->addr, desc->rssi, desc->event_type, &buf, 0); + if (desc->props & BLE_HCI_ADV_LEGACY_MASK || + (IS_ENABLED(CONFIG_BLE_MESH_EXT_ADV) && + desc->props == BLE_MESH_EXT_ADV_NONCONN_IND)) { + bt_mesh_scan_dev_found_cb(&adv_rpt); + } + } + + /* Mesh didn't process that data */ + if (adv_rpt.adv_data.len == adv_data_len) { + goto report_to_user; + } + break; + +report_to_user: + bt_mesh_ble_ext_adv_report(desc); + break; + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + case BLE_GAP_EVENT_DISC: { + struct bt_mesh_adv_report adv_rpt = {0}; + + desc = &event->disc; + + adv_rpt.rssi = desc->rssi; + adv_rpt.adv_type = desc->event_type; + + memcpy(&adv_rpt.addr, &desc->addr, sizeof(bt_mesh_addr_t)); + + net_buf_simple_init_with_data(&adv_rpt.adv_data, (void *)desc->data, desc->length_data); + + if (bt_mesh_scan_dev_found_cb) { + /* TODO: Support Scan Response data length for NimBLE host */ + bt_mesh_scan_dev_found_cb(&adv_rpt); } break; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) case BLE_GAP_EVENT_CONNECT: + /* @todo: process connect failed event */ if (event->connect.status == 0) { /* Connection successfully established. */ MODLOG_DFLT(INFO, "Connection established "); @@ -447,10 +633,21 @@ static int disc_cb(struct ble_gap_event *event, void *arg) break; } } + if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + goto transfer_to_user; + } + } else { + goto transfer_to_user; } } if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + rc = ble_gap_ext_disc(BLE_OWN_ADDR_PUBLIC, 0, 0, 0, 0, 0, + uncoded_disc_params.itvl ? &uncoded_disc_params : NULL, + coded_disc_params.itvl ? &coded_disc_params : NULL, disc_cb, NULL); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ rc = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &scan_param, disc_cb, NULL); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ if (rc != 0) { BT_ERR("Invalid scan status %d", rc); break; @@ -499,7 +696,13 @@ static int disc_cb(struct ble_gap_event *event, void *arg) bt_mesh_gattc_info[i].wr_desc_done = false; break; } + + if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + goto transfer_to_user; + } } + } else { + goto transfer_to_user; } break; case BLE_GAP_EVENT_MTU: @@ -526,6 +729,8 @@ static int disc_cb(struct ble_gap_event *event, void *arg) } /* Search Mesh Provisioning Service or Mesh Proxy Service */ ble_gattc_disc_all_svcs(bt_mesh_gattc_info[i].conn.handle, svc_disced, NULL); + } else { + goto transfer_to_user; } break; case BLE_GAP_EVENT_NOTIFY_RX: @@ -536,8 +741,8 @@ static int disc_cb(struct ble_gap_event *event, void *arg) } if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { - BT_ERR("Conn handle 0x%04x not found", event->notify_rx.conn_handle); - return 0; + BT_DBG("Conn handle 0x%04x not blonges to Mesh", event->notify_rx.conn_handle); + goto transfer_to_user; } conn = &bt_mesh_gattc_info[i].conn; @@ -562,7 +767,7 @@ static int disc_cb(struct ble_gap_event *event, void *arg) if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->prov_notify != NULL) { len = bt_mesh_gattc_conn_cb->prov_notify(&bt_mesh_gattc_info[i].conn, - notif_data, notif_len); + notif_data, notif_len); if (len < 0) { BT_ERR("prov_notify failed"); bt_mesh_gattc_disconnect(conn); @@ -573,7 +778,7 @@ static int disc_cb(struct ble_gap_event *event, void *arg) if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->proxy_notify != NULL && bt_mesh_gattc_info[i].wr_desc_done) { len = bt_mesh_gattc_conn_cb->proxy_notify(&bt_mesh_gattc_info[i].conn, - notif_data, notif_len); + notif_data, notif_len); if (len < 0) { BT_ERR("proxy_notify failed"); bt_mesh_gattc_disconnect(conn); @@ -584,14 +789,53 @@ static int disc_cb(struct ble_gap_event *event, void *arg) break; #endif default: + goto transfer_to_user; break; } return 0; + +transfer_to_user: +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_ble_nimble_evt_to_btc(event, arg); +#endif + return 0; } +#if CONFIG_BLE_MESH_USE_BLE_50 +/** + * @brief Get the gap callback function used by BLE Mesh + * + * @note The user must get the mesh gap event handler function + * through the bt_mesh_nimble_gap_cb_get function and pass + * it in as a callback function when using the api: + * ble_gap_ext_connect, ble_gap_ext_disc, ble_gap_connect, + * and ble_gap_disc. + * + * @return void* + */ +void *bt_mesh_nimble_gap_cb_get(void) +{ + return (void*)disc_cb; +} +#endif + static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t filter_dup) { +#if CONFIG_BLE_MESH_USE_BLE_50 + uncoded_disc_params.itvl = (window ? interval : 0); + uncoded_disc_params.window = window; + + coded_disc_params.itvl = ((interval > window) ? interval : 0); + coded_disc_params.window = ((interval > window) ? interval - window : 0); + + coded_disc_params.passive = (scan_type == BLE_MESH_SCAN_PASSIVE); + uncoded_disc_params.passive = (scan_type == BLE_MESH_SCAN_PASSIVE); + + ble_gap_ext_disc(BLE_OWN_ADDR_PUBLIC, 0, 0, filter_dup, 0, 0, + uncoded_disc_params.itvl ? &uncoded_disc_params : NULL, + coded_disc_params.itvl ? &coded_disc_params : NULL, disc_cb, NULL); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ scan_param.filter_duplicates = filter_dup; scan_param.itvl = interval; scan_param.window = window; @@ -602,6 +846,7 @@ static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, scan_param.passive = 0; } ble_gap_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &scan_param, disc_cb, NULL); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if BLE_MESH_DEV if (scan_type == BLE_MESH_SCAN_ACTIVE) { @@ -653,12 +898,38 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) /* When connection is created, advertising will be stopped automatically. */ bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); #endif + +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) + /* Check if this connection is created by Proxy client */ + for (size_t i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, desc.peer_id_addr.val, BLE_MESH_ADDR_LEN)) { + BT_WARN("Already create connection with %s by proxy client", + bt_hex(desc.peer_id_addr.val, BLE_MESH_ADDR_LEN)); + return 0; + } + } +#endif + if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->connected != NULL) { - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); + int index = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_free_conn_idx(); + if (index != -ENOMEM) { + bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); + (bt_mesh_gatts_conn_cb->connected)(&bt_mesh_gatts_conn[index], 0); + } else { + BT_ERR("No space for new connection"); + ble_gap_terminate(event->connect.conn_handle, BLE_ERR_CONN_LIMIT); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); if (index < BLE_MESH_MAX_CONN) { bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); (bt_mesh_gatts_conn_cb->connected)(&bt_mesh_gatts_conn[index], 0); } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ memcpy(bt_mesh_gatts_addr, desc.peer_id_addr.val, BLE_MESH_ADDR_LEN); /* This is for EspBleMesh Android app. When it tries to connect with the * device at the first time and it fails due to some reason. And after @@ -678,11 +949,23 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); #endif if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->disconnected != NULL) { - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); + int index = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle)); + if (index != -ENODEV) { + bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); + (bt_mesh_gatts_conn_cb->disconnected)(&bt_mesh_gatts_conn[index], event->disconnect.reason); + } else { + BT_ERR("No device"); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); if (index < BLE_MESH_MAX_CONN) { bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); (bt_mesh_gatts_conn_cb->disconnected)(&bt_mesh_gatts_conn[index], event->disconnect.reason); } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_gatts_conn[index].handle = 0; memset(bt_mesh_gatts_addr, 0x0, BLE_MESH_ADDR_LEN); } @@ -699,6 +982,42 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) case BLE_GAP_EVENT_ADV_COMPLETE: BT_DBG("advertise complete; reason=%d", event->adv_complete.reason); + +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + assert(CONFIG_BLE_MESH_ADV_INST_ID == event->adv_complete.instance); + /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ + if (event->adv_complete.reason == BLE_HS_ETIMEOUT) { + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + event->adv_complete.reason == 0) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; case BLE_GAP_EVENT_ENC_CHANGE: @@ -721,10 +1040,20 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) event->subscribe.prev_indicate, event->subscribe.cur_indicate); struct bt_mesh_gatt_attr *attr = bt_mesh_gatts_find_attr_by_handle(event->subscribe.attr_handle + 1); - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle); + int index = 0; uint16_t len = 0; uint16_t ccc_val = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle)); + if (index == -ENODEV) { + BT_ERR("Couldn't find conn %d", event->subscribe.conn_handle); + return 0; + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + if (event->subscribe.prev_notify != event->subscribe.cur_notify) { ccc_val = event->subscribe.cur_notify; } else if (event->subscribe.prev_indicate != event->subscribe.cur_indicate) { @@ -777,10 +1106,254 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) #else static int gap_event_cb(struct ble_gap_event *event, void *arg) { +#if CONFIG_BLE_MESH_USE_BLE_50 + switch (event->type) { + case BLE_GAP_EVENT_ADV_COMPLETE: + BT_DBG("Provisioner advertise complete; reason=%d", + event->adv_complete.reason); +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + assert(CONFIG_BLE_MESH_ADV_INST_ID == event->adv_complete.instance); + /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ + if (event->adv_complete.reason == BLE_HS_ETIMEOUT) { + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + event->adv_complete.reason == 0) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + break; + } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; } #endif /* CONFIG_BLE_MESH_NODE */ +#if CONFIG_BLE_MESH_USE_BLE_50 +static struct { + bool set; + struct ble_gap_ext_adv_params param; +} last_param[BLE_MESH_ADV_INST_TYPES_NUM]; + +int bt_le_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_adv_param *param, + const struct bt_mesh_adv_data *ad, size_t ad_len, + const struct bt_mesh_adv_data *sd, size_t sd_len) +{ + struct ble_gap_ext_adv_params adv_params = {0}; + struct os_mbuf *data = NULL; + struct os_mbuf *scan_rsp = NULL; + uint8_t *buf = NULL; + uint16_t interval = 0; + uint8_t buf_len = 0; + int err = 0; + + err = ble_gap_ext_adv_active(inst_id); + if (err) { + BT_ERR("adv inst(%d) is running %d", inst_id, err); + return -EINVAL; + } + +#if BLE_MESH_DEV + if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return -EALREADY; + } +#endif + buf = bt_mesh_calloc(ad_len * BLE_MESH_GAP_ADV_MAX_LEN); + if (!buf) { + BT_ERR("ad buffer alloc failed"); + return -ENOMEM; + } + + err = set_ad(ad, ad_len, buf, &buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("set_ad failed: err %d", err); + return err; + } + + data = os_msys_get_pkthdr(buf_len, 0); + if (!data) { + bt_mesh_free(buf); + BT_ERR("os buf get failed"); + return -ENOBUFS; + } + + err = os_mbuf_append(data, buf, buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("Append ad data to os buf failed %d", err); + return -EINVAL; + } + + bt_mesh_free(buf); + + if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { + buf_len = 0; + + buf = bt_mesh_calloc(sd_len * BLE_HS_ADV_MAX_SZ); + if (!buf) { + BT_ERR("ad buffer alloc failed"); + return -ENOMEM; + } + + err = set_ad(sd, sd_len, buf, &buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("set_ad failed: err %d", err); + return err; + } + + scan_rsp = os_msys_get_pkthdr(buf_len, 0); + if (!data) { + bt_mesh_free(buf); + BT_ERR("os buf get failed"); + return -ENOBUFS; + } + + err = os_mbuf_append(scan_rsp, buf, buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("Append ad data to os buf failed %d", err); + return -EINVAL; + } + + bt_mesh_free(buf); + } + + memset(&adv_params, 0, sizeof adv_params); + + assert(param); + + if (param->options & BLE_MESH_ADV_OPT_CONNECTABLE) { + adv_params.connectable = true; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + } else if (sd != NULL) { + adv_params.connectable = false; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + } else { + if (param->primary_phy == BLE_MESH_ADV_PHY_1M && + param->secondary_phy == BLE_MESH_ADV_PHY_1M && + param->include_tx_power == false && + ad->data_len <= 29) { + adv_params.legacy_pdu = true; + } + } + + adv_params.sid = inst_id; + adv_params.primary_phy = param->primary_phy; + adv_params.secondary_phy = param->secondary_phy; + adv_params.tx_power = param->tx_power; + adv_params.own_addr_type = BLE_OWN_ADDR_PUBLIC; + adv_params.include_tx_power = param->include_tx_power; + + interval = param->interval_min; + +#if CONFIG_BLE_MESH_RANDOM_ADV_INTERVAL + /* If non-connectable mesh packets are transmitted with an adv interval + * not smaller than 10ms, then we will use a random adv interval between + * [interval / 2, interval] for them. + */ + if (adv_params.legacy_pdu && interval >= 16) { + interval >>= 1; + interval += (bt_mesh_get_rand() % (interval + 1)); + + BT_DBG("%u->%u", param->interval_min, interval); + } +#endif + + adv_params.itvl_min = interval; + adv_params.itvl_max = interval; + + if (memcmp(&adv_params, &last_param[inst_id].param, + sizeof(struct ble_gap_ext_adv_params))) { + if (last_param[inst_id].set) { + err = ble_gap_ext_adv_remove(inst_id); + if (err != 0 && err != BLE_HS_EALREADY) { + BT_ERR("Advertising rm failed: err %d", err); + return err; + } + } + last_param[inst_id].set = true; + err = ble_gap_ext_adv_configure(inst_id, &adv_params, NULL, gap_event_cb, NULL); + if (err != 0) { + BT_ERR("Advertising config failed: err %d", err); + return err; + } + + memcpy(&last_param[inst_id].param, &adv_params, sizeof(struct ble_gap_ext_adv_params)); + } + + err = ble_gap_ext_adv_set_data(inst_id, data); + if (err != 0) { + BT_ERR("Advertising set failed: err %d", err); + return err; + } + + if (scan_rsp) { + err = ble_gap_ext_adv_rsp_set_data(inst_id, scan_rsp); + if (err != 0) { + BT_ERR("scan rsp set failed: err %d", err); + return err; + } else { + BT_INFO("scan rsp set succeed\n"); + } + } + +again: + + if (param->adv_duration < 10 && + param->adv_duration != 0) { + BT_WARN("adv duration shall not be less than 10ms"); + } + + err = ble_gap_ext_adv_start(inst_id, param->adv_duration ? + 2 + param->adv_duration / 10 : 0, param->adv_count); + if (err) { + if (err == BLE_HS_EALREADY) { + ble_gap_ext_adv_stop(inst_id); + goto again; + } + + BT_ERR("Advertising start failed: err %d", err); + return err; + } + +#if BLE_MESH_DEV + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); + + if (!(param->options & BLE_MESH_ADV_OPT_ONE_TIME)) { + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + } +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* APIs functions */ int bt_le_adv_start(const struct bt_mesh_adv_param *param, const struct bt_mesh_adv_data *ad, size_t ad_len, @@ -857,6 +1430,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, adv_params.itvl_min = interval; adv_params.itvl_max = interval; + adv_params.channel_map = param->channel_map; again: err = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, @@ -881,8 +1455,156 @@ again: return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +#if CONFIG_BLE_MESH_USE_BLE_50 +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +/** + * The current flag is only used to distinguish between BLE ADV + * and proxy ADV in the same adv instance to handle the adv + * completed events. + * + * This flag is not needed in the case of multiple adv instances. + */ +static bool _ble_adv_running_flag; + +static inline void bt_mesh_set_ble_adv_running() +{ + _ble_adv_running_flag = true; +} + +static inline void bt_mesh_unset_ble_adv_running() +{ + _ble_adv_running_flag = false; +} + +static inline bool bt_mesh_is_ble_adv_running() +{ + return _ble_adv_running_flag == true; +} +#endif /* BLE_MESH_SUPPORT_MULTI_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) +{ + struct ble_gap_ext_adv_params adv_params = {0}; + struct os_mbuf *data = NULL; + int err = 0; + + assert(param); + + switch (param->adv_type) { + case BLE_MESH_ADV_IND: + adv_params.connectable = true; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_DIRECT_IND: + adv_params.connectable = true; + adv_params.scannable = false; + adv_params.directed = true; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_SCAN_IND: + adv_params.connectable = false; + adv_params.scannable = true; + adv_params.directed = false; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_NONCONN_IND: + adv_params.connectable = false; + adv_params.scannable = false; + adv_params.directed = false; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_DIRECT_IND_LOW_DUTY: + adv_params.connectable = true; + adv_params.scannable = false; + adv_params.directed = true; + adv_params.high_duty_directed = true; + adv_params.legacy_pdu = true; + break; + } + + adv_params.itvl_min = param->interval; + adv_params.itvl_max = param->interval; + adv_params.channel_map = BLE_MESH_ADV_CHAN_37 | BLE_MESH_ADV_CHAN_38 | BLE_MESH_ADV_CHAN_39; + adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + adv_params.primary_phy = BLE_MESH_ADV_PHY_1M; + adv_params.secondary_phy = BLE_MESH_ADV_PHY_1M; + + if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || + param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || + param->adv_type == BLE_MESH_ADV_DIRECT_IND || + param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + adv_params.peer.type = param->peer_addr_type; + memcpy(adv_params.peer.val, param->peer_addr, BLE_MESH_ADDR_LEN); + } + + + if (ble_gap_ext_adv_configure(inst_id, &adv_params, NULL, + gap_event_cb, NULL)) { + BT_ERR("ble adv configure failed\n"); + return -EINVAL; + } + + if (adv_data && param->adv_type != BLE_MESH_ADV_DIRECT_IND && + param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + if (adv_data->adv_data_len) { + data = os_msys_get_pkthdr(adv_data->adv_data_len, 0); + if (!data) { + BT_ERR("Failed to alloc buffer for ble"); + return -ENOMEM; + } + + if (os_mbuf_append(data, adv_data->adv_data, adv_data->adv_data_len)) { + BT_ERR("Append data failed"); + return -EINVAL; + } + + err = ble_gap_ext_adv_set_data(inst_id, data); + if (err) { + BT_ERR("Failed to set advertising data, err %d", err); + return err; + } + } + if (adv_data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) { + data = os_msys_get_pkthdr(adv_data->scan_rsp_data_len, 0); + if (!data) { + BT_ERR("Failed to alloc buffer for ble"); + return -ENOMEM; + } + + if (os_mbuf_append(data, adv_data->scan_rsp_data, adv_data->scan_rsp_data_len)) { + BT_ERR("Append data failed"); + return -EINVAL; + } + err = ble_gap_ext_adv_rsp_set_data(inst_id, data); + if (err) { + BT_ERR("Failed to set scan rsp data, err %d", err); + return err; + } + } + } + + err = ble_gap_ext_adv_start(inst_id, 2 + param->duration / 10, param->count); + if (err) { + BT_ERR("Failed to start advertising, err %d", err); + return err; + } + +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_set_ble_adv_running(); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data) { @@ -932,7 +1654,7 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, } adv_params.itvl_min = param->interval; adv_params.itvl_max = param->interval; - adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + adv_params.channel_map = BLE_MESH_ADV_CHAN_37 | BLE_MESH_ADV_CHAN_38 | BLE_MESH_ADV_CHAN_39; adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; adv_params.high_duty_cycle = (param->adv_type == BLE_MESH_ADV_DIRECT_IND) ? true : false; @@ -953,8 +1675,27 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_stop(uint8_t inst_id) +{ +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return 0; + } +#endif + ble_gap_ext_adv_stop(inst_id); + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_adv_stop(void) { #if BLE_MESH_DEV @@ -971,6 +1712,7 @@ int bt_le_adv_stop(void) return 0; } +#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) { @@ -991,6 +1733,7 @@ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t c err = start_le_scan(param->type, param->interval, param->window, param->filter_dup); if (err) { + BT_ERR("Failed to start advertising, err %d", err); return err; } @@ -1559,6 +2302,7 @@ int bt_mesh_gattc_write_no_rsp(struct bt_mesh_conn *conn, om = ble_hs_mbuf_from_flat(data, len); if (om == NULL) { + BT_ERR("om buffer alloc failed"); return -1; } @@ -1630,9 +2374,19 @@ static int proxy_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, { if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR || ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC) { struct bt_mesh_gatt_attr *attr = bt_mesh_gatts_find_attr_by_handle(attr_handle); - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(conn_handle); + int index = 0; uint16_t len = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(conn_handle)); + if (index == -ENODEV) { + BT_ERR("Unknown conn handle"); + return 0; + } +#else + index = BLE_MESH_GATT_GET_CONN_ID(conn_handle); +#endif + BT_DBG("write, handle %d, len %d, data %s", attr_handle, ctxt->om->om_len, bt_hex(ctxt->om->om_data, ctxt->om->om_len)); @@ -1721,6 +2475,57 @@ void gatt_register_cb(struct ble_gatt_register_ctxt *ctxt, } } +#if CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_gatts_svcs_add(void) +{ + ble_hs_cfg.gatts_register_cb = gatt_register_cb; + +#if CONFIG_BLE_MESH_NODE + int rc = 0; + + ble_svc_gap_init(); + ble_svc_gatt_init(); + + rc = ble_gatts_count_cfg(svc_defs); + assert(rc == 0); + + rc = ble_gatts_add_svcs(svc_defs); + assert(rc == 0); + + g_gatts_svcs_add = true; +#endif +} + +void bt_mesh_gatt_init(void) +{ + ble_att_set_preferred_mtu(BLE_MESH_GATT_DEF_MTU_SIZE); + +#if CONFIG_BLE_MESH_NODE + static bool init = false; + + if (init == false) { + assert(g_gatts_svcs_add); + + ble_gatts_svc_set_visibility(prov_svc_start_handle, 1); + ble_gatts_svc_set_visibility(proxy_svc_start_handle, 0); + +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_gatts_conn_init(); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + init = true; + } +#endif /* CONFIG_BLE_MESH_NODE */ + +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT + for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + bt_mesh_gattc_info[i].conn.handle = 0xFFFF; + bt_mesh_gattc_info[i].mtu = BLE_ATT_MTU_DFLT; + bt_mesh_gattc_info[i].wr_desc_done = false; + } +#endif +} +#else void bt_mesh_gatt_init(void) { ble_att_set_preferred_mtu(BLE_ATT_MTU_DFLT); @@ -1760,6 +2565,7 @@ void bt_mesh_gatt_init(void) } #endif } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_DEINIT void bt_mesh_gatt_deinit(void) @@ -1788,199 +2594,11 @@ void bt_mesh_gatt_deinit(void) } #endif /* CONFIG_BLE_MESH_DEINIT */ -void ble_sm_alg_ecc_init(void); - void bt_mesh_adapt_init(void) { - /* initialization of P-256 parameters */ - ble_sm_alg_ecc_init(); - - /* Set "bt_mesh_dev.flags" to 0 (only the "BLE_MESH_DEV_HAS_PUB_KEY" - * flag is used) here, because we need to make sure each time after - * the private key is initialized, a corresponding public key must - * be generated. - */ + /* Use unified crypto module initialization */ + bt_mesh_crypto_init(); bt_mesh_atomic_set(bt_mesh_dev.flags, 0); - bt_mesh_rand(bt_mesh_private_key, sizeof(bt_mesh_private_key)); -} - -void bt_mesh_set_private_key(const uint8_t pri_key[32]) -{ - memcpy(bt_mesh_private_key, pri_key, 32); -} - -int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv); - -const uint8_t *bt_mesh_pub_key_get(void) -{ - uint8_t pri_key[32] = {0}; - -#if 1 - if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_HAS_PUB_KEY)) { - return bt_mesh_public_key; - } -#else - /* BLE Mesh BQB test case MESH/NODE/PROV/UPD/BV-12-C requires - * different public key for each provisioning procedure. - * Note: if enabled, when Provisioner provision multiple devices - * at the same time, this may cause invalid confirmation value. - */ - if (bt_mesh_rand(bt_mesh_private_key, 32)) { - BT_ERR("%s, Unable to generate bt_mesh_private_key", __func__); - return NULL; - } -#endif - - int rc = ble_sm_alg_gen_key_pair(bt_mesh_public_key, pri_key); - if (rc != 0) { - BT_ERR("Failed to generate the key pair"); - return NULL; - } - memcpy(bt_mesh_private_key, pri_key, 32); - - bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_HAS_PUB_KEY); - - BT_DBG("Public Key %s", bt_hex(bt_mesh_public_key, sizeof(bt_mesh_public_key))); - - return bt_mesh_public_key; -} - -bool bt_mesh_check_public_key(const uint8_t key[64]) -{ - struct mbedtls_ecp_point pt = {0}; - mbedtls_ecp_group grp = {0}; - bool rc = false; - - uint8_t pub[65] = {0}; - /* Hardcoded first byte of pub key for MBEDTLS_ECP_PF_UNCOMPRESSED */ - pub[0] = 0x04; - memcpy(&pub[1], key, 64); - - /* Initialize the required structures here */ - mbedtls_ecp_point_init(&pt); - mbedtls_ecp_group_init(&grp); - - /* Below 3 steps are to validate public key on curve secp256r1 */ - if (mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1) != 0) { - goto exit; - } - - if (mbedtls_ecp_point_read_binary(&grp, &pt, pub, 65) != 0) { - goto exit; - } - - if (mbedtls_ecp_check_pubkey(&grp, &pt) != 0) { - goto exit; - } - - rc = true; - -exit: - mbedtls_ecp_point_free(&pt); - mbedtls_ecp_group_free(&grp); - return rc; - -} - -int ble_sm_alg_gen_dhkey(uint8_t *peer_pub_key_x, uint8_t *peer_pub_key_y, - uint8_t *our_priv_key, uint8_t *out_dhkey); - -int bt_mesh_dh_key_gen(const uint8_t remote_pub_key[64], uint8_t dhkey[32]) -{ - BT_DBG("private key = %s", bt_hex(bt_mesh_private_key, 32)); - - return ble_sm_alg_gen_dhkey((uint8_t *)&remote_pub_key[0], (uint8_t *)&remote_pub_key[32], - bt_mesh_private_key, dhkey); -} - -int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16], - uint8_t enc_data[16]) -{ - uint8_t tmp[16] = {0}; - - BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16)); - -#if CONFIG_MBEDTLS_HARDWARE_AES - mbedtls_aes_context ctx = {0}; - - mbedtls_aes_init(&ctx); - - sys_memcpy_swap(tmp, key, 16); - - if (mbedtls_aes_setkey_enc(&ctx, tmp, 128) != 0) { - mbedtls_aes_free(&ctx); - return -EINVAL; - } - - sys_memcpy_swap(tmp, plaintext, 16); - - if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, - tmp, enc_data) != 0) { - mbedtls_aes_free(&ctx); - return -EINVAL; - } - - mbedtls_aes_free(&ctx); -#else /* CONFIG_MBEDTLS_HARDWARE_AES */ - struct tc_aes_key_sched_struct s = {0}; - - sys_memcpy_swap(tmp, key, 16); - - if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) { - return -EINVAL; - } - - sys_memcpy_swap(tmp, plaintext, 16); - - if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) { - return -EINVAL; - } -#endif /* CONFIG_MBEDTLS_HARDWARE_AES */ - - 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]) -{ - BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16)); - -#if CONFIG_MBEDTLS_HARDWARE_AES - mbedtls_aes_context ctx = {0}; - - mbedtls_aes_init(&ctx); - - if (mbedtls_aes_setkey_enc(&ctx, key, 128) != 0) { - mbedtls_aes_free(&ctx); - return -EINVAL; - } - - if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, - plaintext, enc_data) != 0) { - mbedtls_aes_free(&ctx); - return -EINVAL; - } - - mbedtls_aes_free(&ctx); -#else /* CONFIG_MBEDTLS_HARDWARE_AES */ - struct tc_aes_key_sched_struct s = {0}; - - if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) { - return -EINVAL; - } - - if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) { - return -EINVAL; - } -#endif /* CONFIG_MBEDTLS_HARDWARE_AES */ - - BT_DBG("enc_data %s", bt_hex(enc_data, 16)); - - return 0; } #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN @@ -1991,12 +2609,12 @@ int bt_mesh_update_exceptional_list(uint8_t sub_code, uint32_t type, void *info) if ((sub_code > BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN) || (sub_code < BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN && - type > BLE_MESH_EXCEP_LIST_TYPE_MESH_PROXY_ADV) || + type > BLE_MESH_EXCEP_LIST_TYPE_MAX) || (sub_code == BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN && !(type & BLE_MESH_EXCEP_LIST_CLEAN_ALL_LIST))) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; - } + } if (type == BLE_MESH_EXCEP_LIST_TYPE_MESH_LINK_ID) { if (!info) { diff --git a/components/bt/esp_ble_mesh/core/prov_node.c b/components/bt/esp_ble_mesh/core/prov_node.c index 0805c1ddb9..24bb71bfb6 100644 --- a/components/bt/esp_ble_mesh/core/prov_node.c +++ b/components/bt/esp_ble_mesh/core/prov_node.c @@ -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; } diff --git a/components/bt/esp_ble_mesh/core/prov_pvnr.c b/components/bt/esp_ble_mesh/core/prov_pvnr.c index d1df4a69e1..3182f49e80 100644 --- a/components/bt/esp_ble_mesh/core/prov_pvnr.c +++ b/components/bt/esp_ble_mesh/core/prov_pvnr.c @@ -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; } diff --git a/components/bt/esp_ble_mesh/core/proxy_client.c b/components/bt/esp_ble_mesh/core/proxy_client.c index d8d68c9347..710159fd25 100644 --- a/components/bt/esp_ble_mesh/core/proxy_client.c +++ b/components/bt/esp_ble_mesh/core/proxy_client.c @@ -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; diff --git a/components/bt/esp_ble_mesh/core/proxy_client.h b/components/bt/esp_ble_mesh/core/proxy_client.h index ef8db32f6d..6bc0732d3f 100644 --- a/components/bt/esp_ble_mesh/core/proxy_client.h +++ b/components/bt/esp_ble_mesh/core/proxy_client.h @@ -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, diff --git a/components/bt/esp_ble_mesh/core/proxy_server.c b/components/bt/esp_ble_mesh/core/proxy_server.c index ed73f1144a..6021ca7f8f 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.c +++ b/components/bt/esp_ble_mesh/core/proxy_server.c @@ -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 diff --git a/components/bt/esp_ble_mesh/core/proxy_server.h b/components/bt/esp_ble_mesh/core/proxy_server.h index c1994a56d4..d16d0d390f 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.h +++ b/components/bt/esp_ble_mesh/core/proxy_server.h @@ -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); diff --git a/components/bt/esp_ble_mesh/core/rpl.c b/components/bt/esp_ble_mesh/core/rpl.c index c6ab282472..43f4a4afda 100644 --- a/components/bt/esp_ble_mesh/core/rpl.c +++ b/components/bt/esp_ble_mesh/core/rpl.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/scan.c b/components/bt/esp_ble_mesh/core/scan.c index c709d9eaec..a7a685d099 100644 --- a/components/bt/esp_ble_mesh/core/scan.c +++ b/components/bt/esp_ble_mesh/core/scan.c @@ -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) { diff --git a/components/bt/esp_ble_mesh/core/scan.h b/components/bt/esp_ble_mesh/core/scan.h index b7d0555c83..612751d3f2 100644 --- a/components/bt/esp_ble_mesh/core/scan.h +++ b/components/bt/esp_ble_mesh/core/scan.h @@ -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 diff --git a/components/bt/esp_ble_mesh/core/storage/settings_nvs.c b/components/bt/esp_ble_mesh/core/storage/settings_nvs.c index e2f730d41a..f539c0a35a 100644 --- a/components/bt/esp_ble_mesh/core/storage/settings_nvs.c +++ b/components/bt/esp_ble_mesh/core/storage/settings_nvs.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/test.c b/components/bt/esp_ble_mesh/core/test.c index 5b47258d5f..6433f9c0d4 100644 --- a/components/bt/esp_ble_mesh/core/test.c +++ b/components/bt/esp_ble_mesh/core/test.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/core/transport.c b/components/bt/esp_ble_mesh/core/transport.c index b4855c4d87..8c5319b717 100644 --- a/components/bt/esp_ble_mesh/core/transport.c +++ b/components/bt/esp_ble_mesh/core/transport.c @@ -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); } diff --git a/components/bt/esp_ble_mesh/core/transport.enh.c b/components/bt/esp_ble_mesh/core/transport.enh.c index be9316fc3a..7d81ebcbc5 100644 --- a/components/bt/esp_ble_mesh/core/transport.enh.c +++ b/components/bt/esp_ble_mesh/core/transport.enh.c @@ -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); } diff --git a/components/bt/esp_ble_mesh/core/transport.h b/components/bt/esp_ble_mesh/core/transport.h index 500c87eddf..e4487fa9fd 100644 --- a/components/bt/esp_ble_mesh/core/transport.h +++ b/components/bt/esp_ble_mesh/core/transport.h @@ -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)) diff --git a/components/bt/esp_ble_mesh/lib/ext.c b/components/bt/esp_ble_mesh/lib/ext.c index bf334422d4..75434312d5 100644 --- a/components/bt/esp_ble_mesh/lib/ext.c +++ b/components/bt/esp_ble_mesh/lib/ext.c @@ -35,8 +35,6 @@ #include "lpn.h" #include "rpl.h" #include "foundation.h" -#include -#include #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, diff --git a/components/bt/esp_ble_mesh/lib/lib b/components/bt/esp_ble_mesh/lib/lib index 70cbef2ed7..e44762384e 160000 --- a/components/bt/esp_ble_mesh/lib/lib +++ b/components/bt/esp_ble_mesh/lib/lib @@ -1 +1 @@ -Subproject commit 70cbef2ed7693b893eb766ad66fb919f0d34ac40 +Subproject commit e44762384ed104a0ebc78f134eeba5f3ab648ddc diff --git a/components/bt/esp_ble_mesh/models/client/client_common.c b/components/bt/esp_ble_mesh/models/client/client_common.c index 211e4d8435..e87c68f62c 100644 --- a/components/bt/esp_ble_mesh/models/client/client_common.c +++ b/components/bt/esp_ble_mesh/models/client/client_common.c @@ -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); diff --git a/components/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c b/components/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c index a153ccbba9..de5550ce61 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c +++ b/components/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h b/components/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h index eb3fa5677d..a19e5539bb 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h +++ b/components/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h @@ -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 */ diff --git a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_blob_model_api.h b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_blob_model_api.h index 165450ed56..0f9097262a 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_blob_model_api.h +++ b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_blob_model_api.h @@ -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. */ diff --git a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h index 6ef42d3dd8..f2b2d121c1 100644 --- a/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h +++ b/components/bt/esp_ble_mesh/v1.1/api/models/include/esp_ble_mesh_dfu_model_api.h @@ -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 */ diff --git a/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c b/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c index d60df283f1..b6fe3ecdbd 100644 --- a/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c +++ b/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_dfu_model.c @@ -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; } diff --git a/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c b/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c index e9d0c13d4f..e5200d7c3f 100644 --- a/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c +++ b/components/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c @@ -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 */ diff --git a/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h b/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h index db443dadb2..5b78299a3e 100644 --- a/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h +++ b/components/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h @@ -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 */ diff --git a/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c b/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c index e5ff20c328..21eea26d43 100644 --- a/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c +++ b/components/bt/esp_ble_mesh/v1.1/dfu/dfu_cli.c @@ -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: */ diff --git a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfu_cli.h b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfu_cli.h index 531e359994..306af5fbad 100644 --- a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfu_cli.h +++ b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/dfu/dfu_cli.h @@ -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: */ diff --git a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/mbt/blob.h b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/mbt/blob.h index 29199360a4..bd797e41ff 100644 --- a/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/mbt/blob.h +++ b/components/bt/esp_ble_mesh/v1.1/include/mesh_v1.1/mbt/blob.h @@ -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. */ diff --git a/components/bt/esp_ble_mesh/v1.1/mbt/blob.h b/components/bt/esp_ble_mesh/v1.1/mbt/blob.h index c539219d9e..79d09d89f4 100644 --- a/components/bt/esp_ble_mesh/v1.1/mbt/blob.h +++ b/components/bt/esp_ble_mesh/v1.1/mbt/blob.h @@ -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 diff --git a/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c b/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c index 9132829a23..435ef3b5bc 100644 --- a/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c +++ b/components/bt/esp_ble_mesh/v1.1/mbt/blob_cli.c @@ -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); } diff --git a/components/bt/esp_ble_mesh/v1.1/mbt/blob_srv.c b/components/bt/esp_ble_mesh/v1.1/mbt/blob_srv.c index 3540a6abea..88fe61ad0b 100644 --- a/components/bt/esp_ble_mesh/v1.1/mbt/blob_srv.c +++ b/components/bt/esp_ble_mesh/v1.1/mbt/blob_srv.c @@ -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)) diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index ab323fa1a0..b10c80f961 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -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 \ diff --git a/docs/en/api-reference/bluetooth/esp-ble-mesh.rst b/docs/en/api-reference/bluetooth/esp-ble-mesh.rst index 3d0e01bf27..bae0be6c64 100644 --- a/docs/en/api-reference/bluetooth/esp-ble-mesh.rst +++ b/docs/en/api-reference/bluetooth/esp-ble-mesh.rst @@ -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) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst b/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst index a383f17c3d..72f1697b9a 100644 --- a/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst +++ b/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst @@ -29,6 +29,7 @@ Mesh 核心 * 私有信标 * 子网桥 * 次要增强 + * 设备固件更新(预览) * 多个客户端模型同时运行 * 支持多个客户端模型同时向不同节点发送数据包 diff --git a/examples/bluetooth/esp_ble_mesh/common_components/example_init/ble_mesh_example_init.c b/examples/bluetooth/esp_ble_mesh/common_components/example_init/ble_mesh_example_init.c index 81600912b4..d473255f23 100644 --- a/examples/bluetooth/esp_ble_mesh/common_components/example_init/ble_mesh_example_init.c +++ b/examples/bluetooth/esp_ble_mesh/common_components/example_init/ble_mesh_example_init.c @@ -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);