From c8e79a926620e48830778714cfe4b2ea2453fcaf Mon Sep 17 00:00:00 2001 From: jacqueline Date: Fri, 25 Jul 2025 13:33:07 +1000 Subject: Update forked idf components --- lib/bt/esp_ble_mesh/Kconfig.in | 520 +++++++------ .../esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c | 26 +- .../api/core/esp_ble_mesh_common_api.c | 2 +- .../api/core/include/esp_ble_mesh_ble_api.h | 88 ++- lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h | 25 +- lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c | 49 +- lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c | 10 +- lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h | 39 +- .../esp_ble_mesh/btc/include/btc_ble_mesh_prov.h | 2 +- lib/bt/esp_ble_mesh/common/atomic.c | 16 +- lib/bt/esp_ble_mesh/common/include/mesh/atomic.h | 27 + lib/bt/esp_ble_mesh/common/include/mesh/mutex.h | 7 +- lib/bt/esp_ble_mesh/common/include/mesh/queue.h | 33 + lib/bt/esp_ble_mesh/common/include/mesh/utils.h | 2 +- lib/bt/esp_ble_mesh/common/mutex.c | 53 +- lib/bt/esp_ble_mesh/common/queue.c | 48 ++ lib/bt/esp_ble_mesh/core/access.c | 148 +++- lib/bt/esp_ble_mesh/core/adv.c | 775 +++----------------- lib/bt/esp_ble_mesh/core/adv.h | 82 +-- lib/bt/esp_ble_mesh/core/adv_common.c | 683 +++++++++++++++++ lib/bt/esp_ble_mesh/core/adv_common.h | 293 ++++++++ lib/bt/esp_ble_mesh/core/beacon.c | 13 +- lib/bt/esp_ble_mesh/core/ble_adv.c | 323 ++++++++ lib/bt/esp_ble_mesh/core/ble_adv.h | 54 ++ lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c | 597 ++++++++++++++- lib/bt/esp_ble_mesh/core/cfg_srv.c | 165 ++++- lib/bt/esp_ble_mesh/core/crypto.c | 2 + lib/bt/esp_ble_mesh/core/ext_adv.c | 427 +++++++++++ lib/bt/esp_ble_mesh/core/ext_adv.h | 39 + lib/bt/esp_ble_mesh/core/friend.c | 34 +- lib/bt/esp_ble_mesh/core/include/mesh/access.h | 4 +- lib/bt/esp_ble_mesh/core/include/mesh/adapter.h | 161 +++- lib/bt/esp_ble_mesh/core/lpn.c | 3 + lib/bt/esp_ble_mesh/core/main.c | 20 +- lib/bt/esp_ble_mesh/core/mesh.h | 1 + lib/bt/esp_ble_mesh/core/net.c | 289 ++++++-- lib/bt/esp_ble_mesh/core/net.h | 14 +- lib/bt/esp_ble_mesh/core/nimble_host/adapter.c | 812 ++++++++++++++++++++- lib/bt/esp_ble_mesh/core/prov_common.c | 33 +- lib/bt/esp_ble_mesh/core/prov_common.h | 2 + lib/bt/esp_ble_mesh/core/prov_node.c | 37 +- lib/bt/esp_ble_mesh/core/prov_pvnr.c | 55 +- lib/bt/esp_ble_mesh/core/prov_pvnr.h | 2 + lib/bt/esp_ble_mesh/core/proxy_client.c | 91 ++- lib/bt/esp_ble_mesh/core/proxy_client.h | 4 + lib/bt/esp_ble_mesh/core/proxy_server.c | 121 ++- lib/bt/esp_ble_mesh/core/proxy_server.h | 4 +- lib/bt/esp_ble_mesh/core/pvnr_mgmt.c | 2 + lib/bt/esp_ble_mesh/core/scan.c | 218 ++++-- lib/bt/esp_ble_mesh/core/scan.h | 8 +- lib/bt/esp_ble_mesh/core/storage/settings.c | 5 +- lib/bt/esp_ble_mesh/core/tag.h | 53 ++ lib/bt/esp_ble_mesh/core/transport.c | 67 +- lib/bt/esp_ble_mesh/core/transport.enh.c | 6 +- lib/bt/esp_ble_mesh/lib/ext.c | 88 ++- lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h | 2 +- lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a | Bin 943462 -> 1487706 bytes lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a | Bin 2057546 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a | Bin 0 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a | Bin 2057546 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a | Bin 0 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a | Bin 2057546 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a | Bin 943462 -> 1487414 bytes lib/bt/esp_ble_mesh/models/client/client_common.c | 2 + .../esp_ble_mesh/models/server/time_scene_server.c | 6 +- .../v1.1/api/core/esp_ble_mesh_rpr_model_api.c | 33 +- .../api/core/include/esp_ble_mesh_rpr_model_api.h | 22 +- .../esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c | 84 ++- .../v1.1/btc/include/btc_ble_mesh_rpr_model.h | 20 +- 69 files changed, 5474 insertions(+), 1377 deletions(-) create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/queue.h create mode 100644 lib/bt/esp_ble_mesh/common/queue.c create mode 100644 lib/bt/esp_ble_mesh/core/adv_common.c create mode 100644 lib/bt/esp_ble_mesh/core/adv_common.h create mode 100644 lib/bt/esp_ble_mesh/core/ble_adv.c create mode 100644 lib/bt/esp_ble_mesh/core/ble_adv.h create mode 100644 lib/bt/esp_ble_mesh/core/ext_adv.c create mode 100644 lib/bt/esp_ble_mesh/core/ext_adv.h create mode 100644 lib/bt/esp_ble_mesh/core/tag.h create mode 100644 lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a create mode 100644 lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a (limited to 'lib/bt/esp_ble_mesh') diff --git a/lib/bt/esp_ble_mesh/Kconfig.in b/lib/bt/esp_ble_mesh/Kconfig.in index 216ab39a..eb761a5e 100644 --- a/lib/bt/esp_ble_mesh/Kconfig.in +++ b/lib/bt/esp_ble_mesh/Kconfig.in @@ -6,22 +6,97 @@ if BLE_MESH help It is a temporary solution and needs further modifications. + config BLE_MESH_V11_SUPPORT + bool "Support ESP BLE Mesh v1.1 features (Preview)" + default y + help + Support BLE Mesh v1.1 features + config BLE_MESH_RANDOM_ADV_INTERVAL bool "Support using random adv interval for mesh packets" select BT_BLE_HIGH_DUTY_ADV_INTERVAL if BT_BLUEDROID_ENABLED + select BT_NIMBLE_HIGH_DUTY_ADV_ITVL if BT_NIMBLE_ENABLED default n help Enable this option to allow using random advertising interval for mesh packets. And this could help avoid collision of advertising packets. + 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. + + 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 || 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 + 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 @@ -32,6 +107,7 @@ if BLE_MESH config BLE_MESH_ACTIVE_SCAN bool "Support Active Scan in BLE Mesh" + depends on BLE_MESH_V11_SUPPORT help Enable this option to allow using BLE Active Scan for BLE Mesh. @@ -281,6 +357,7 @@ if BLE_MESH config BLE_MESH_PROV_EPA bool "BLE Mesh enhanced provisioning authentication" depends on BLE_MESH_PROV + depends on BLE_MESH_V11_SUPPORT default y help Enable this option to support BLE Mesh enhanced provisioning authentication @@ -290,6 +367,7 @@ if BLE_MESH config BLE_MESH_CERT_BASED_PROV bool "Support Certificate-based provisioning" depends on BLE_MESH_PROV + depends on BLE_MESH_V11_SUPPORT default n help Enable this option to support BLE Mesh Certificate-Based Provisioning. @@ -390,6 +468,7 @@ if BLE_MESH config BLE_MESH_PROXY_SOLIC_PDU_RX bool "Support receiving Proxy Solicitation PDU" depends on BLE_MESH_GATT_PROXY_SERVER + depends on BLE_MESH_V11_SUPPORT help Enable this option to support receiving Proxy Solicitation PDU. @@ -397,7 +476,7 @@ if BLE_MESH int "Maximum capacity of solicitation replay protection list" depends on BLE_MESH_PROXY_SOLIC_PDU_RX default 2 - range 1 255 + range 1 65536 help This option specifies the maximum capacity of the solicitation replay protection list. The solicitation replay protection list is used to @@ -405,6 +484,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 @@ -417,6 +503,7 @@ if BLE_MESH config BLE_MESH_PROXY_SOLIC_PDU_TX bool "Support sending Proxy Solicitation PDU" depends on BLE_MESH_GATT_PROXY_CLIENT + depends on BLE_MESH_V11_SUPPORT help Enable this option to support sending Proxy Solicitation PDU. @@ -703,6 +790,7 @@ if BLE_MESH to perform the IV index recovery procedure. config BLE_MESH_SAR_ENHANCEMENT + depends on BLE_MESH_V11_SUPPORT bool "Segmentation and reassembly enhancement" default n help @@ -1102,253 +1190,257 @@ if BLE_MESH help Enable support for Health Server model. - config BLE_MESH_BRC_CLI - bool "Bridge Configuration Client model" - help - Enable support for Bridge Configuration Client model. - - config BLE_MESH_BRC_SRV - bool "Bridge Configuration Server model" - default n - help - Enable support for Bridge Configuration Server model. - - if BLE_MESH_BRC_SRV + if BLE_MESH_V11_SUPPORT - config BLE_MESH_MAX_BRIDGING_TABLE_ENTRY_COUNT - int "Maximum number of Bridging Table entries" - range 16 65535 - default 16 + config BLE_MESH_BRC_CLI + bool "Bridge Configuration Client model" help - Maximum number of Bridging Table entries that the Bridge Configuration Server can support. + Enable support for Bridge Configuration Client model. - config BLE_MESH_BRIDGE_CRPL - int "Maximum capacity of bridge replay protection list" - default 5 - range 1 255 + config BLE_MESH_BRC_SRV + bool "Bridge Configuration Server model" + default n help - This option specifies the maximum capacity of the bridge replay - protection list. The bridge replay protection list is used to - prevent a bridged subnet from replay attack, which will store the - source address and sequence number of the received bridge messages. + Enable support for Bridge Configuration Server model. - endif #BLE_MESH_BRC_SRV + if BLE_MESH_BRC_SRV - config BLE_MESH_PRB_CLI - bool "Mesh Private Beacon Client model" - help - Enable support for Mesh Private Beacon Client model. + config BLE_MESH_MAX_BRIDGING_TABLE_ENTRY_COUNT + int "Maximum number of Bridging Table entries" + range 16 65535 + default 16 + help + Maximum number of Bridging Table entries that the Bridge Configuration Server can support. - config BLE_MESH_PRB_SRV - bool "Mesh Private Beacon Server model" - help - Enable support for Mesh Private Beacon Server model. + config BLE_MESH_BRIDGE_CRPL + int "Maximum capacity of bridge replay protection list" + default 5 + range 1 255 + help + This option specifies the maximum capacity of the bridge replay + protection list. The bridge replay protection list is used to + prevent a bridged subnet from replay attack, which will store the + source address and sequence number of the received bridge messages. - config BLE_MESH_ODP_CLI - bool "On-Demand Private Proxy Client model" - help - Enable support for On-Demand Private Proxy Client model. + endif #BLE_MESH_BRC_SRV - config BLE_MESH_ODP_SRV - bool "On-Demand Private Proxy Server model" - depends on BLE_MESH_PROXY_SOLIC_PDU_RX - select BLE_MESH_SRPL_SRV - help - Enable support for On-Demand Private Proxy Server model. + config BLE_MESH_PRB_CLI + bool "Mesh Private Beacon Client model" + help + Enable support for Mesh Private Beacon Client model. - config BLE_MESH_SRPL_CLI - bool "Solicitation PDU RPL Configuration Client model" - help - Enable support for Solicitation PDU RPL Configuration Client model. + config BLE_MESH_PRB_SRV + bool "Mesh Private Beacon Server model" + help + Enable support for Mesh Private Beacon Server model. - config BLE_MESH_SRPL_SRV - bool "Solicitation PDU RPL Configuration Server model" - depends on BLE_MESH_PROXY_SOLIC_PDU_RX - help - Enable support for Solicitation PDU RPL Configuration Server model. - Note: - This option depends on the functionality of receiving Solicitation - PDU. If the device doesn't support receiving Solicitation PDU, then - there is no need to enable this server model. + config BLE_MESH_ODP_CLI + bool "On-Demand Private Proxy Client model" + help + Enable support for On-Demand Private Proxy Client model. - config BLE_MESH_AGG_CLI - bool "Opcodes Aggregator Client model" - help - Enable support for Opcodes Aggregator Client model. + config BLE_MESH_ODP_SRV + bool "On-Demand Private Proxy Server model" + depends on BLE_MESH_PROXY_SOLIC_PDU_RX + select BLE_MESH_SRPL_SRV + help + Enable support for On-Demand Private Proxy Server model. - config BLE_MESH_AGG_SRV - bool "Opcodes Aggregator Server model" - help - Enable support for Opcodes Aggregator Server model. + config BLE_MESH_SRPL_CLI + bool "Solicitation PDU RPL Configuration Client model" + help + Enable support for Solicitation PDU RPL Configuration Client model. - config BLE_MESH_SAR_CLI - bool "SAR Configuration Client model" - help - Enable support for SAR Configuration Client model. + config BLE_MESH_SRPL_SRV + bool "Solicitation PDU RPL Configuration Server model" + depends on BLE_MESH_PROXY_SOLIC_PDU_RX + help + Enable support for Solicitation PDU RPL Configuration Server model. + Note: + This option depends on the functionality of receiving Solicitation + PDU. If the device doesn't support receiving Solicitation PDU, then + there is no need to enable this server model. + + config BLE_MESH_AGG_CLI + bool "Opcodes Aggregator Client model" + help + Enable support for Opcodes Aggregator Client model. - config BLE_MESH_SAR_SRV - bool "SAR Configuration Server model" - help - Enable support for SAR Configuration Server model. + config BLE_MESH_AGG_SRV + bool "Opcodes Aggregator Server model" + help + Enable support for Opcodes Aggregator Server model. - config BLE_MESH_COMP_DATA_1 - bool "Support Composition Data Page 1" - help - Composition Data Page 1 contains information about the relationships - among models. - Each model either can be a root model or can extend other models. + config BLE_MESH_SAR_CLI + bool "SAR Configuration Client model" + help + Enable support for SAR Configuration Client model. - config BLE_MESH_COMP_DATA_128 - bool "Support Composition Data Page 128" - help - Composition Data Page 128 is used to indicate the structure of - elements, features, and models of a node after the successful - execution of the Node Address Refresh procedure or the Node - Composition Refresh procedure, or after the execution of the - Node Removal procedure followed by the provisioning process. - Composition Data Page 128 shall be present if the node supports - the Remote Provisioning Server model; otherwise it is optional. + config BLE_MESH_SAR_SRV + bool "SAR Configuration Server model" + help + Enable support for SAR Configuration Server model. - config BLE_MESH_MODELS_METADATA_0 - bool "Support Models Metadata Page 0" - help - The Models Metadata state contains metadata of a node’s models. - The Models Metadata state is composed of a number of pages of - information. - Models Metadata Page 0 shall be present if the node supports - the Large Composition Data Server model. + config BLE_MESH_COMP_DATA_1 + bool "Support Composition Data Page 1" + help + Composition Data Page 1 contains information about the relationships + among models. + Each model either can be a root model or can extend other models. - config BLE_MESH_MODELS_METADATA_128 - bool "Support Models Metadata Page 128" - depends on BLE_MESH_MODELS_METADATA_0 - help - The Models Metadata state contains metadata of a node’s models. - The Models Metadata state is composed of a number of pages of - information. - Models Metadata Page 128 contains metadata for the node’s models - after the successful execution of the Node Address Refresh - procedure or the Node Composition Refresh procedure, or after - the execution of the Node Removal procedure followed by the - provisioning process. - Models Metadata Page 128 shall be present if the node supports - the Remote Provisioning Server model and the node supports the - Large Composition Data Server model. + config BLE_MESH_COMP_DATA_128 + bool "Support Composition Data Page 128" + help + Composition Data Page 128 is used to indicate the structure of + elements, features, and models of a node after the successful + execution of the Node Address Refresh procedure or the Node + Composition Refresh procedure, or after the execution of the + Node Removal procedure followed by the provisioning process. + Composition Data Page 128 shall be present if the node supports + the Remote Provisioning Server model; otherwise it is optional. + + config BLE_MESH_MODELS_METADATA_0 + bool "Support Models Metadata Page 0" + help + The Models Metadata state contains metadata of a node’s models. + The Models Metadata state is composed of a number of pages of + information. + Models Metadata Page 0 shall be present if the node supports + the Large Composition Data Server model. + + config BLE_MESH_MODELS_METADATA_128 + bool "Support Models Metadata Page 128" + depends on BLE_MESH_MODELS_METADATA_0 + help + The Models Metadata state contains metadata of a node’s models. + The Models Metadata state is composed of a number of pages of + information. + Models Metadata Page 128 contains metadata for the node’s models + after the successful execution of the Node Address Refresh + procedure or the Node Composition Refresh procedure, or after + the execution of the Node Removal procedure followed by the + provisioning process. + Models Metadata Page 128 shall be present if the node supports + the Remote Provisioning Server model and the node supports the + Large Composition Data Server model. + + config BLE_MESH_LCD_CLI + bool "Large Composition Data Client model" + help + Enable support for Large Composition Data Client model. - config BLE_MESH_LCD_CLI - bool "Large Composition Data Client model" - help - Enable support for Large Composition Data Client model. + config BLE_MESH_LCD_SRV + bool "Large Composition Data Server model" + select BLE_MESH_MODELS_METADATA_0 + help + Enable support for Large Composition Data Server model. - config BLE_MESH_LCD_SRV - bool "Large Composition Data Server model" - select BLE_MESH_MODELS_METADATA_0 - help - Enable support for Large Composition Data Server model. + config BLE_MESH_RPR_CLI + bool "Remote Provisioning Client model" + depends on BLE_MESH_PROVISIONER + select BLE_MESH_PROV + help + Enable support for Remote Provisioning Client model - config BLE_MESH_RPR_CLI - bool "Remote Provisioning Client model" - depends on BLE_MESH_PROVISIONER - select BLE_MESH_PROV - help - Enable support for Remote Provisioning Client model + if BLE_MESH_RPR_CLI - if BLE_MESH_RPR_CLI + config BLE_MESH_RPR_CLI_PROV_SAME_TIME + int "Maximum number of PB-Remote running at the same time by Provisioner" + range 1 5 + default 2 + help + This option specifies how many devices can be provisioned at the same time + using PB-REMOTE. For example, if the value is 2, it means a Provisioner can + provision two unprovisioned devices with PB-REMOTE at the same time. - config BLE_MESH_RPR_CLI_PROV_SAME_TIME - int "Maximum number of PB-Remote running at the same time by Provisioner" - range 1 5 - default 2 + endif # BLE_MESH_RPR_CLI + + config BLE_MESH_RPR_SRV + bool "Remote Provisioning Server model" + depends on BLE_MESH_NODE + select BLE_MESH_PB_ADV help - This option specifies how many devices can be provisioned at the same time - using PB-REMOTE. For example, if the value is 2, it means a Provisioner can - provision two unprovisioned devices with PB-REMOTE at the same time. + Enable support for Remote Provisioning Server model - endif # BLE_MESH_RPR_CLI + if BLE_MESH_RPR_SRV - config BLE_MESH_RPR_SRV - bool "Remote Provisioning Server model" - depends on BLE_MESH_NODE - select BLE_MESH_PB_ADV - help - Enable support for Remote Provisioning Server model + config BLE_MESH_RPR_SRV_MAX_SCANNED_ITEMS + int "Maximum number of device information can be scanned" + range 4 255 + default 10 + help + This option specifies how many device information can a Remote + Provisioning Server store each time while scanning. - if BLE_MESH_RPR_SRV + config BLE_MESH_RPR_SRV_ACTIVE_SCAN + bool "Support Active Scan for remote provisioning" + select BLE_MESH_ACTIVE_SCAN + help + Enable this option to support Active Scan for remote provisioning. - config BLE_MESH_RPR_SRV_MAX_SCANNED_ITEMS - int "Maximum number of device information can be scanned" - range 4 255 - default 10 - help - This option specifies how many device information can a Remote - Provisioning Server store each time while scanning. + config BLE_MESH_RPR_SRV_MAX_EXT_SCAN + int "Maximum number of extended scan procedures" + range 1 10 + default 1 + help + This option specifies how many extended scan procedures can be + started by the Remote Provisioning Server. - config BLE_MESH_RPR_SRV_ACTIVE_SCAN - bool "Support Active Scan for remote provisioning" - select BLE_MESH_ACTIVE_SCAN - help - Enable this option to support Active Scan for remote provisioning. + endif # BLE_MESH_RPR_SRV - config BLE_MESH_RPR_SRV_MAX_EXT_SCAN - int "Maximum number of extended scan procedures" - range 1 10 - default 1 + config BLE_MESH_DF_CLI + bool "Directed Forwarding Configuration Client model" help - This option specifies how many extended scan procedures can be - started by the Remote Provisioning Server. + Enable support for Directed Forwarding Configuration Client model. - endif # BLE_MESH_RPR_SRV + config BLE_MESH_DF_SRV + bool "Directed Forwarding Configuration Server model" + help + Enable support for Directed Forwarding Configuration Server model. - config BLE_MESH_DF_CLI - bool "Directed Forwarding Configuration Client model" - help - Enable support for Directed Forwarding Configuration Client model. + if BLE_MESH_DF_SRV - config BLE_MESH_DF_SRV - bool "Directed Forwarding Configuration Server model" - help - Enable support for Directed Forwarding Configuration Server model. + config BLE_MESH_MAX_DISC_TABLE_ENTRY_COUNT + int "Maximum number of discovery table entries in a given subnet" + range 2 255 + default 2 + help + Maximum number of Discovery Table entries supported by the node in a given subnet. - if BLE_MESH_DF_SRV + config BLE_MESH_MAX_FORWARD_TABLE_ENTRY_COUNT + int "Maximum number of forward table entries in a given subnet" + range 2 64 + default 2 + help + Maximum number of Forward Table entries supported by the node in a given subnet. - config BLE_MESH_MAX_DISC_TABLE_ENTRY_COUNT - int "Maximum number of discovery table entries in a given subnet" - range 2 255 - default 2 - help - Maximum number of Discovery Table entries supported by the node in a given subnet. + config BLE_MESH_MAX_DEPS_NODES_PER_PATH + int "Maximum number of dependent nodes per path" + range 2 64 + default 2 + help + Maximum size of dependent nodes list supported by each forward table entry. - config BLE_MESH_MAX_FORWARD_TABLE_ENTRY_COUNT - int "Maximum number of forward table entries in a given subnet" - range 2 64 - default 2 - help - Maximum number of Forward Table entries supported by the node in a given subnet. + config BLE_MESH_PATH_MONITOR_TEST + bool "Enable Path Monitoring test mode" + default n + help + The option only removes the Path Use timer; all other behavior of the + device is not changed. + If Path Monitoring test mode is going to be used, this option should + be enabled. - config BLE_MESH_MAX_DEPS_NODES_PER_PATH - int "Maximum number of dependent nodes per path" - range 2 64 - default 2 - help - Maximum size of dependent nodes list supported by each forward table entry. + if BLE_MESH_GATT_PROXY_SERVER + config BLE_MESH_SUPPORT_DIRECTED_PROXY + bool "Enable Directed Proxy functionality" + default y + help + Support Directed Proxy functionality. + endif - config BLE_MESH_PATH_MONITOR_TEST - bool "Enable Path Monitoring test mode" - default n - help - The option only removes the Path Use timer; all other behavior of the - device is not changed. - If Path Monitoring test mode is going to be used, this option should - be enabled. - - if BLE_MESH_GATT_PROXY_SERVER - config BLE_MESH_SUPPORT_DIRECTED_PROXY - bool "Enable Directed Proxy functionality" - default y - help - Support Directed Proxy functionality. - endif + endif # BLE_MESH_DF_SRV - endif # BLE_MESH_DF_SRV + endif # BLE_MESH_V11_SUPPORT endmenu #Support for BLE Mesh Foundation models @@ -1441,30 +1533,31 @@ if BLE_MESH config BLE_MESH_GENERIC_SERVER bool "Generic server models" - default y + default n help Enable support for Generic server models. config BLE_MESH_SENSOR_SERVER bool "Sensor server models" - default y + default n help Enable support for Sensor server models. config BLE_MESH_TIME_SCENE_SERVER bool "Time and Scenes server models" - default y + default n help Enable support for Time and Scenes server models. config BLE_MESH_LIGHTING_SERVER bool "Lighting server models" - default y + default n help Enable support for Lighting server models. config BLE_MESH_MBT_CLI bool "BLOB Transfer Client model" + depends on BLE_MESH_V11_SUPPORT default n help Enable support for BLOB Transfer Client model. @@ -1483,6 +1576,7 @@ if BLE_MESH config BLE_MESH_MBT_SRV bool "BLOB Transfer Server model" + depends on BLE_MESH_V11_SUPPORT default n help Enable support for BLOB Transfer Server model. @@ -1628,5 +1722,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/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c b/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c index 559528e8..fcba1f4b 100644 --- a/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c +++ b/lib/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/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c b/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c index 82128786..eaa18681 100644 --- a/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c +++ b/lib/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/lib/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h b/lib/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h index 6818ba18..83d7e627 100644 --- a/lib/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h +++ b/lib/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,24 @@ 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 + */ + 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 +216,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/lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index efbf2df5..188d6db2 100644 --- a/lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -415,6 +415,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 */ diff --git a/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c b/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c index ead6c2cc..27699600 100644 --- a/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c +++ b/lib/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,7 @@ #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 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 +28,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 +86,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_callback(¶m, ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT); +} +#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 +165,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 +207,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/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index 67d5353b..e8782500 100644 --- a/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -10,11 +10,13 @@ #include "btc_ble_mesh_prov.h" #include "btc_ble_mesh_config_model.h" #include "btc_ble_mesh_health_model.h" -#include "btc_ble_mesh_prb_model.h" #include "btc_ble_mesh_generic_model.h" #include "btc_ble_mesh_time_scene_model.h" #include "btc_ble_mesh_sensor_model.h" #include "btc_ble_mesh_lighting_model.h" + +#if CONFIG_BLE_MESH_V11_SUPPORT +#include "btc_ble_mesh_prb_model.h" #include "btc_ble_mesh_brc_model.h" #include "btc_ble_mesh_odp_model.h" #include "btc_ble_mesh_srpl_model.h" @@ -24,8 +26,11 @@ #include "btc_ble_mesh_rpr_model.h" #include "btc_ble_mesh_df_model.h" #include "btc_ble_mesh_mbt_model.h" +#include "mesh_v1.1/utils.h" +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #include "adv.h" +#include "scan.h" #include "mesh/kernel.h" #include "mesh/proxy.h" #include "mesh.h" @@ -65,8 +70,6 @@ #include "mesh/state_binding.h" #include "local.h" -#include "mesh_v1.1/utils.h" - #include "esp_ble_mesh_common_api.h" #include "esp_ble_mesh_provisioning_api.h" #include "esp_ble_mesh_networking_api.h" @@ -2946,6 +2949,7 @@ 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, }; + 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/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h b/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h index 8c63002a..e5d21df0 100644 --- a/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h +++ b/lib/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/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h b/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h index f2777927..741a6b31 100644 --- a/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h +++ b/lib/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/lib/bt/esp_ble_mesh/common/atomic.c b/lib/bt/esp_ble_mesh/common/atomic.c index 723ce7e3..9c856cc3 100644 --- a/lib/bt/esp_ble_mesh/common/atomic.c +++ b/lib/bt/esp_ble_mesh/common/atomic.c @@ -13,7 +13,7 @@ /* * SPDX-FileCopyrightText: 2016 Intel Corporation * SPDX-FileCopyrightText: 2011-2014 Wind River Systems, Inc. - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -170,4 +170,18 @@ bt_mesh_atomic_val_t bt_mesh_atomic_inc(bt_mesh_atomic_t *target) return ret; } +bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val) +{ + bt_mesh_atomic_lock(); + + if (*target == excepted) { + *target = new_val; + bt_mesh_atomic_unlock(); + return true; + } + + bt_mesh_atomic_unlock(); + return false; +} + #endif /* #ifndef CONFIG_ATOMIC_OPERATIONS_BUILTIN */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h b/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h index f7283436..b2849743 100644 --- a/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h +++ b/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h @@ -147,6 +147,33 @@ static inline bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, extern bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value); #endif +/** + * @brief Atomic CAS operation. + * + * This compares the contents of @a *target + * with the contents of @a excepted. If equal, + * the operation is a read-modify-write operation + * that writes @a new_val into @a *target and return true. + * If they are not equal, the operation is a read + * and return false. + * + * @param target Address of atomic variable. + * @param excepted Value of excepted. + * @param new_val Write if target value is equal to expected one. + * + * @return + * - true: Target value updated. + * - false: Target value not updated. + */ +#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN +static inline bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val) +{ + return __atomic_compare_exchange_n(target, &excepted, &new_val, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +} +#else +extern bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val); +#endif + /** * @cond INTERNAL_HIDDEN */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h b/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h index ee897500..0cc47eb0 100644 --- a/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h +++ b/lib/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/lib/bt/esp_ble_mesh/common/include/mesh/queue.h b/lib/bt/esp_ble_mesh/common/include/mesh/queue.h new file mode 100644 index 00000000..021c99ba --- /dev/null +++ b/lib/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/lib/bt/esp_ble_mesh/common/include/mesh/utils.h b/lib/bt/esp_ble_mesh/common/include/mesh/utils.h index 98243483..967fed2e 100644 --- a/lib/bt/esp_ble_mesh/common/include/mesh/utils.h +++ b/lib/bt/esp_ble_mesh/common/include/mesh/utils.h @@ -200,7 +200,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/lib/bt/esp_ble_mesh/common/mutex.c b/lib/bt/esp_ble_mesh/common/mutex.c index 6c3b2bf6..3a3dedb8 100644 --- a/lib/bt/esp_ble_mesh/common/mutex.c +++ b/lib/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/lib/bt/esp_ble_mesh/common/queue.c b/lib/bt/esp_ble_mesh/common/queue.c new file mode 100644 index 00000000..1fc3d66a --- /dev/null +++ b/lib/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/lib/bt/esp_ble_mesh/core/access.c b/lib/bt/esp_ble_mesh/core/access.c index 9606581e..3791add9 100644 --- a/lib/bt/esp_ble_mesh/core/access.c +++ b/lib/bt/esp_ble_mesh/core/access.c @@ -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 */ @@ -11,6 +11,7 @@ #include #include "mesh.h" +#include "tag.h" #include "adv.h" #include "lpn.h" #include "friend.h" @@ -22,7 +23,9 @@ #include "fast_prov.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define BLE_MESH_SDU_MAX_LEN 384 @@ -814,6 +817,135 @@ static bool ready_to_send(uint16_t dst) return false; } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static bool use_friend_cred(uint16_t net_idx, uint16_t dst) +{ + /* Currently LPN only supports using NetKey in bt_mesh.sub[0] */ + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && + net_idx == 0 && + bt_mesh_lpn_match(dst)) { + return true; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + bt_mesh_friend_match(net_idx, dst)) { + return true; + } + + return false; +} + +bool bt_mesh_valid_security_cred(struct bt_mesh_net_tx *tx) +{ + /* If the message is tagged with immutable-credentials, + * then the security credentials shall not be changed + * in lower layers. + * If not, later a better security credentials could be + * chosen for the message. + */ + if (!bt_mesh_tag_immutable_cred(tx->ctx->send_tag)) { + return true; + } + + if (tx->ctx->send_cred > BLE_MESH_FRIENDSHIP_CRED) { + return false; + } + + if (tx->ctx->send_cred == BLE_MESH_FRIENDSHIP_CRED && + !use_friend_cred(tx->ctx->net_idx, tx->ctx->addr)) { + return false; + } + + return true; +} + +void bt_mesh_choose_better_security_cred(struct bt_mesh_net_tx *tx) +{ + uint8_t send_cred = 0U; + uint8_t send_tag = 0U; + uint16_t net_idx = 0U; + uint16_t addr = 0U; + + send_cred = tx->ctx->send_cred; + send_tag = tx->ctx->send_tag; + net_idx = tx->ctx->net_idx; + addr = tx->ctx->addr; + + /* If the message is tagged with immutable-credentials, + * then the security credentials shall not be changed. + */ + if (bt_mesh_tag_immutable_cred(send_tag)) { + return; + } + + if (send_cred > BLE_MESH_FRIENDSHIP_CRED) { + BT_INFO("Use managed flooding security credentials"); + tx->ctx->send_cred = BLE_MESH_FLOODING_CRED; + return; + } + + if (send_cred == BLE_MESH_FRIENDSHIP_CRED) { + if (!use_friend_cred(net_idx, addr)) { + BT_INFO("Use managed flooding security credentials"); + tx->ctx->send_cred = BLE_MESH_FLOODING_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + } else { + /* TODO: + * For LPN, do we need to change the friendship security + * credentials to managed flooding credentials? + * If changed, this could increase the possibility that + * the corresponding Friend node receives this message. + */ + } + return; + } + + /* If the message is destinated to a LPN, the following could be + * introduced to send the message with the friendship credentials. + * + * For LPN, this optimization should not be introduced, since it + * may cause the message failed to received by the Friend node, + * using friendship credentials will make the message can not be + * relayed by other mesh nodes. + */ + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + BLE_MESH_ADDR_IS_UNICAST(addr) && + bt_mesh_friend_match(net_idx, addr)) { + BT_INFO("Use friendship security credentials"); + tx->ctx->send_cred = BLE_MESH_FRIENDSHIP_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + return; + } + + /** + * Spec 3.7.3.1 + * The Low power node in friendship should use friendship security + * material. + * + * But in Spec 3.6.6.2 + * Depending on the value of the Publish Friendship Credentials Flag + * (see Section 4.2.3.4), the Low Power node model publishes messages + * using either the friendship security credentials or the managed + * flooding security credentials (see Section 3.9.6.3.1). + * + * So use the BLE_MESH_TAG_IMMUTABLE_CRED to indicate that the + * credentials of the message should not be changed when the + * message is sent by model publishing, even though the spec + * didn't require this flag to be set when model publishing. + */ + +#if CONFIG_BLE_MESH_LOW_POWER + if (BLE_MESH_ADDR_IS_UNICAST(addr) && + bt_mesh.lpn.frnd == addr && + !bt_mesh_tag_immutable_cred(send_tag)) { + tx->ctx->send_cred = BLE_MESH_FRIENDSHIP_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + return; + } +#endif +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static int model_send(struct bt_mesh_model *model, struct bt_mesh_net_tx *tx, bool implicit_bind, struct net_buf_simple *msg, @@ -1108,11 +1240,13 @@ size_t bt_mesh_rx_devkey_size(void) #if CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioned()) { size = 1; +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_dev_key_ca_valid()) { size += 1; } +#endif /* CONFIG_BLE_MESH_RPR_SRV */ } -#endif +#endif /* CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER */ #if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { @@ -1122,9 +1256,11 @@ size_t bt_mesh_rx_devkey_size(void) #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER size = 1; +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_dev_key_ca_valid()) { size += 1; } +#endif /* CONFIG_BLE_MESH_RPR_SRV */ if (bt_mesh_is_provisioner_en()) { size += 1; } @@ -1156,7 +1292,9 @@ const uint8_t *bt_mesh_rx_devkey_get(size_t index, uint16_t src) #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (index == 0) { key = bt_mesh.dev_key; - } else if (index == 1 && bt_mesh_dev_key_ca_valid()) { + } else +#if CONFIG_BLE_MESH_RPR_SRV + if (index == 1 && bt_mesh_dev_key_ca_valid()) { /* If index == 1, there are two cases. * 1. bt_mesh_dev_key_ca_valid() is true, it should be return bt_mesh.dev_key_ca. * 2. bt_mesh_is_provisioner_en() is true, it should be return bt_mesh_provisioner_dev_key_get(src). @@ -1166,7 +1304,9 @@ const uint8_t *bt_mesh_rx_devkey_get(size_t index, uint16_t src) * Then this round of function bt_mesh_rx_devkey_get(2, src) will return bt_mesh_provisioner_dev_key_get(src). */ key = bt_mesh.dev_key_ca; - } else { + } else +#endif + { key = bt_mesh_provisioner_dev_key_get(src); } #endif diff --git a/lib/bt/esp_ble_mesh/core/adv.c b/lib/bt/esp_ble_mesh/core/adv.c index dbbda0ab..54efa0d4 100644 --- a/lib/bt/esp_ble_mesh/core/adv.c +++ b/lib/bt/esp_ble_mesh/core/adv.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,110 +23,20 @@ #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; -/* 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); #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) @@ -144,17 +54,6 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, } } -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) { const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; @@ -187,25 +86,41 @@ static inline int adv_send(struct net_buf *buf) param.interval_min = ADV_SCAN_UNIT(adv_int); param.interval_max = param.interval_min; +#if CONFIG_BLE_MESH_USE_BLE_50 + param.adv_duration = duration; + param.adv_count = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1; +#endif + #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) { bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); - struct bt_mesh_adv_data solic_ad[3] = { - BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_FLAGS, (BLE_MESH_AD_GENERAL | BLE_MESH_AD_NO_BREDR)), + struct bt_mesh_adv_data solic_ad[2] = { BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18), BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len), }; - err = bt_le_adv_start(¶m, solic_ad, 3, NULL, 0); +#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 { 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"); @@ -229,7 +144,11 @@ 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 */ @@ -242,9 +161,19 @@ 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 (!ble_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 */ + ble_mesh_adv_task_wait(K_MSEC(duration)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +#if !CONFIG_BLE_MESH_USE_BLE_50 err = bt_le_adv_stop(); +#endif + adv_send_end(err, cb, cb_data); if (err) { BT_ERR("Stop advertising failed: err %d", err); @@ -255,15 +184,12 @@ static inline int adv_send(struct net_buf *buf) return 0; } -static inline TickType_t K_WAIT(int32_t val) -{ - return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); -} - static void adv_thread(void *p) { #if CONFIG_BLE_MESH_RELAY_ADV_BUF QueueSetMemberHandle_t handle = NULL; + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; #endif bt_mesh_msg_t msg = {0}; struct net_buf **buf = NULL; @@ -277,28 +203,28 @@ 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; BT_DBG("Mesh Proxy Advertising start"); 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); + 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)) { @@ -310,10 +236,10 @@ static void adv_thread(void *p) BT_DBG("Mesh Proxy Advertising stop"); 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); } } } @@ -321,10 +247,10 @@ static void adv_thread(void *p) #else 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 */ @@ -335,14 +261,13 @@ static void adv_thread(void *p) } /* busy == 0 means this was canceled */ - if (BLE_MESH_ADV(*buf)->busy) { - BLE_MESH_ADV(*buf)->busy = 0U; + if (bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(*buf), 1, 0)) { #if !CONFIG_BLE_MESH_RELAY_ADV_BUF if (adv_send(*buf)) { 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. */ @@ -364,119 +289,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; - } - - buf = net_buf_alloc(pool, timeout); - if (!buf) { - 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; - - 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; - BLE_MESH_ADV(buf)->busy = 0U; - 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) @@ -490,7 +302,7 @@ void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, BLE_MESH_ADV(buf)->cb = cb; BLE_MESH_ADV(buf)->cb_data = cb_data; - BLE_MESH_ADV(buf)->busy = 1U; + 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); @@ -509,476 +321,55 @@ 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; - BLE_MESH_ADV(buf)->busy = 1U; - 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 */ #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); + bt_mesh_relay_adv_init(); #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); + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_init(); #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 */ + 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 && !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; 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); -#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + xQueueAddToSet(adv_queue->q.handle, mesh_queue_set); + xQueueAddToSet(relay_adv_handle, mesh_queue_set); +#endif -#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_adv_task_init(adv_thread); } #if CONFIG_BLE_MESH_DEINIT void bt_mesh_adv_deinit(void) { - if (adv_queue.handle == NULL) { - return; - } - - 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); - - 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)); + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; + xQueueRemoveFromSet(adv_queue->q.handle, mesh_queue_set); + xQueueRemoveFromSet(relay_adv_handle, mesh_queue_set); vQueueDelete(mesh_queue_set); mesh_queue_set = NULL; -#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)); + bt_mesh_relay_adv_deinit(); +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV bt_mesh_ble_adv_deinit(); #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ -} -#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; - BLE_MESH_ADV(buf)->busy = 1U; - - 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)); - BLE_MESH_ADV(tx->buf)->busy = 0U; - 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 (BLE_MESH_ADV(tx->buf)->busy == 1U && - 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)); + bt_mesh_adv_common_deinit(); } #endif /* CONFIG_BLE_MESH_DEINIT */ -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ diff --git a/lib/bt/esp_ble_mesh/core/adv.h b/lib/bt/esp_ble_mesh/core/adv.h index ab37ec3c..5770364a 100644 --- a/lib/bt/esp_ble_mesh/core/adv.h +++ b/lib/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,96 +10,30 @@ #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)) - -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, -}; - -struct bt_mesh_adv { - const struct bt_mesh_send_cb *cb; - void *cb_data; - - uint8_t type:3, - busy:1; - 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/lib/bt/esp_ble_mesh/core/adv_common.c b/lib/bt/esp_ble_mesh/core/adv_common.c new file mode 100644 index 00000000..4a7078d7 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/adv_common.c @@ -0,0 +1,683 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "adv_common.h" +#include "net.h" +#include "ble_adv.h" + +NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT]; + +static struct bt_mesh_adv_queue adv_queue; + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT]; +struct bt_mesh_adv_queue relay_adv_queue; + +#define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6) +#define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF + +#endif + +#if CONFIG_BLE_MESH_FRIEND +/* We reserve one extra buffer for each friendship, since we need to be able + * to resend the last sent PDU, which sits separately outside of the queue. + */ +#define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \ + CONFIG_BLE_MESH_FRIEND_LPN_COUNT) + +NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, NULL); + +bt_mesh_friend_adv_t frnd_adv_pool[FRIEND_BUF_COUNT]; + +struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx) +{ + frnd_adv_pool[idx].app_idx = BLE_MESH_KEY_UNUSED; + return &frnd_adv_pool[idx].adv; +} +#endif + +struct bt_mesh_adv_task { + TaskHandle_t handle; +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + StaticTask_t *task; + StackType_t *stack; +#endif +}; + +static struct bt_mesh_adv_task adv_task; +static struct bt_mesh_adv_type_manager adv_types[BLE_MESH_ADV_TYPES_NUM]; + +#if CONFIG_BLE_MESH_USE_BLE_50 +static struct bt_mesh_adv_inst adv_insts[] = { + [BLE_MESH_ADV_INS] = { + .id = CONFIG_BLE_MESH_ADV_INST_ID, +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + .busy = false, +#endif + }, +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + [BLE_MESH_ADV_PROXY_INS] = { + .id = CONFIG_BLE_MESH_PROXY_ADV_INST_ID, + .busy = false, + }, +#endif +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + [BLE_MESH_RELAY_ADV_INS] = { + .id = CONFIG_BLE_MESH_RELAY_ADV_INST_ID, + .busy = false, + }, +#endif +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + [BLE_MESH_BLE_ADV_INS] = { + .id = CONFIG_BLE_MESH_BLE_ADV_INST_ID, + .busy = false, + }, +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +}; + +static struct bt_mesh_adv_inst *find_adv_inst_with_inst_id(uint8_t id) +{ + for (int i = 0; i < ARRAY_SIZE(adv_insts); i++) { + if (adv_insts[i].id == id) { + return &adv_insts[i]; + } + } + + return NULL; +} + +struct bt_mesh_adv_inst *bt_mesh_get_adv_insts_set(void) +{ + return adv_insts; +} + +bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id) +{ + return (find_adv_inst_with_inst_id(adv_inst_id) != NULL); +} + +int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return -EINVAL; + } + + if (inst_id == BLE_MESH_ADV_INS_UNUSED) { + BT_ERR("Invalid instance id %d", inst_id); + return -EINVAL; + } + + adv_insts[inst_type].id = inst_id; + return 0; +} + +int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return -EINVAL; + } + + bt_le_ext_adv_stop(adv_insts[inst_type].id); + + adv_insts[inst_type].id = BLE_MESH_ADV_INS_UNUSED; +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + adv_insts[inst_type].spt_mask = 0; +#endif + return 0; +} + +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +struct bt_mesh_adv *adv_alloc(int id) +{ + return &adv_pool[id]; +} + +struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type) +{ + return &adv_types[adv_type]; +} + +void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, + uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag) +{ + if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + switch (flag) { + case BLE_MESH_BUF_REF_EQUAL: + if (buf->ref != ref_cmp) { + BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp); + } + break; + case BLE_MESH_BUF_REF_SMALL: + if (buf->ref >= ref_cmp) { + BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp); + } + break; + default: + break; + } +} + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask |= BIT(adv_type); +} + +void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask &= ~BIT(adv_type); +} + +void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask = 0; +} +#endif + +int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, uint16_t queue_size, + bt_mesh_adv_queue_send_cb_t cb) +{ + if (!adv_queue || !queue_size || !cb) { + BT_ERR("Invalid param %s", __func__); + return -EINVAL; + } + + bt_mesh_queue_init(&adv_queue->q, queue_size, sizeof(bt_mesh_msg_t)); + + adv_queue->send = cb; + + return 0; +} + +int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue) +{ + if (!adv_queue) { + BT_ERR("Invalid param %s", __func__); + return -EINVAL; + } + + bt_mesh_queue_deinit(&adv_queue->q); + + adv_queue->send = NULL; + + return 0; +} + +void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, + struct bt_mesh_adv_queue *adv_queue, + struct net_buf_pool *buf_pool, + bt_mesh_pool_allocator_t adv_alloc) +{ + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("%s Invalid adv type %d",__func__, adv_type); + return; + } + + if (!adv_queue || !buf_pool || !adv_alloc) { + BT_ERR("Invalid parameters %s", __func__); + return; + } + + adv_types[adv_type].adv_q = adv_queue; + adv_types[adv_type].pool = buf_pool; + adv_types[adv_type].pool_allocator = adv_alloc; +} + +void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type) +{ + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("%s Invalid adv type %d",__func__, adv_type); + return; + } + + adv_types[adv_type].adv_q = NULL; + adv_types[adv_type].pool = NULL; + adv_types[adv_type].pool_allocator = NULL; +} + +#if CONFIG_BLE_MESH_USE_BLE_50 +int ble_mesh_adv_task_wakeup(uint32_t evt) +{ + xTaskNotify(adv_task.handle, evt, eSetBits); + return 0; +} + +bool ble_mesh_adv_task_wait(uint32_t wait_bits, uint32_t timeout, uint32_t *notify) +{ + return (xTaskNotifyWait(wait_bits, UINT32_MAX, notify, K_WAIT(timeout)) == pdTRUE); +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ +bool ble_mesh_adv_task_wait(uint32_t timeout) +{ + vTaskDelay(K_WAIT(timeout)); + return true; +} +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +uint16_t bt_mesh_pdu_duration(uint8_t xmit) +{ + uint16_t duration = 0U; + uint16_t adv_int = 0U; + + adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit)); + duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); + + return duration; +} + +struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, + int32_t timeout) +{ + struct bt_mesh_adv *adv = NULL; + struct net_buf *buf = NULL; + struct net_buf_pool *pool = adv_types[type].pool; + + if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) { + BT_WARN("Refusing to allocate buffer while suspended"); + return NULL; + } + + if (!pool || !adv_types[type].pool_allocator) { + BT_ERR("Uninitialized adv type %d", type); + return NULL; + } + + buf = net_buf_alloc(pool, timeout); + if (!buf) { + BT_WARN("Buf alloc failed"); + return NULL; + } + + BT_DBG("pool %p, buf_count %d, uinit_count %d, ref %d", + buf->pool, pool->buf_count, pool->uninit_count, buf->ref); + + adv = adv_types[type].pool_allocator(net_buf_id(buf)); + BLE_MESH_ADV(buf) = adv; + + (void)memset(adv, 0, sizeof(*adv)); + + adv->type = type; + + return buf; +} + +void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) +{ + if (pool == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + for (int i = 0; i < pool->buf_count; i++) { + struct net_buf *buf = &pool->__bufs[i]; + if (buf->ref > 1U) { + buf->ref = 1U; + } + net_buf_unref(buf); + } +} + +void bt_mesh_unref_buf(bt_mesh_msg_t *msg) +{ + struct net_buf *buf = 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); + } +} + +void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data, uint16_t src, + uint16_t dst, bool front) +{ + bt_mesh_msg_t msg = { + .relay = false, /* useless flag in multi-instance mode */ + }; + + BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, + bt_hex(buf->data, buf->len)); + + BLE_MESH_ADV(buf)->cb = cb; + BLE_MESH_ADV(buf)->cb_data = cb_data; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); + BLE_MESH_ADV(buf)->xmit = xmit; + + bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + + msg.arg = (void *)net_buf_ref(buf); + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_RELAY_DATA) { + msg.relay = true; + msg.src = src; + msg.dst = dst; + msg.timestamp = k_uptime_get_32(); + } +#endif + + assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q && adv_types[BLE_MESH_ADV(buf)->type].adv_q->send); + + adv_types[BLE_MESH_ADV(buf)->type].adv_q->send(&msg, portMAX_DELAY, front); + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_PKT_SEND_EVT); +#endif +} + +struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void) +{ + return &adv_queue; +} + +void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + if (adv_queue.q.handle == NULL) { + BT_ERR("Invalid adv queue"); + return; + } + + if (front) { + if (xQueueSendToFront(adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue front"); + bt_mesh_unref_buf(msg); + } + } else { + if (xQueueSend(adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue back"); + bt_mesh_unref_buf(msg); + } + } +} + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +bool bt_mesh_ignore_relay_packet(uint32_t timestamp) +{ + uint32_t now = k_uptime_get_32(); + uint32_t interval = 0U; + + if (now >= timestamp) { + interval = now - timestamp; + } else { + interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1; + } + + return ((interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false); +} + +static struct bt_mesh_adv *relay_adv_alloc(int id) +{ + 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(type, timeout); +} + +static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + bt_mesh_msg_t old_msg = {0}; + + ARG_UNUSED(front); + + if (relay_adv_queue.q.handle == NULL) { + BT_ERR("Invalid relay queue"); + return; + } + + if (xQueueSend(relay_adv_queue.q.handle, msg, timeout) == pdTRUE) { + return; + } + + /* If failed to send packet to the relay queue(queue is full), we will + * remove the oldest packet in the queue and put the new one into it. + */ + if (uxQueueMessagesWaiting(relay_adv_queue.q.handle)) { + BT_INFO("Full queue, remove the oldest relay packet"); + /* Remove the oldest relay packet from queue */ + if (xQueueReceive(relay_adv_queue.q.handle, &old_msg, K_NO_WAIT) != pdTRUE) { + BT_ERR("Failed to remove item from relay queue"); + bt_mesh_unref_buf(msg); + return; + } + /* Unref buf used for the oldest relay packet */ + bt_mesh_unref_buf(&old_msg); + /* Send the latest relay packet to queue */ + if (xQueueSend(relay_adv_queue.q.handle, msg, K_NO_WAIT) != pdTRUE) { + BT_ERR("Failed to send item to relay queue"); + bt_mesh_unref_buf(msg); + return; + } + } else { + BT_WARN("Empty queue, but failed to send the relay packet"); + bt_mesh_unref_buf(msg); + } +} + +uint16_t bt_mesh_get_stored_relay_count(void) +{ + return (uint16_t)uxQueueMessagesWaiting(relay_adv_queue.q.handle); +} + +void bt_mesh_relay_adv_init(void) +{ + bt_mesh_adv_queue_init(&relay_adv_queue, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, + ble_mesh_relay_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_RELAY_DATA, &relay_adv_queue, + &relay_adv_buf_pool, &relay_adv_alloc); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + bt_mesh_adv_inst_init(BLE_MESH_RELAY_ADV_INS, + CONFIG_BLE_MESH_RELAY_ADV_INST_ID); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_relay_adv_deinit(void) +{ + bt_mesh_adv_queue_deinit(&relay_adv_queue); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_RELAY_DATA); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_deinit(BLE_MESH_RELAY_ADV_INS); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool); + memset(relay_adv_pool, 0, sizeof(relay_adv_pool)); +} +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + +#if CONFIG_BLE_MESH_FRIEND +struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void) +{ + return &friend_buf_pool; +} + +void bt_mesh_frnd_adv_init(void) +{ + bt_mesh_adv_type_init(BLE_MESH_ADV_FRIEND, &adv_queue, &friend_buf_pool, bt_mesh_frnd_adv_buf_get); +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_FRIEND); +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +} + +void bt_mesh_frnd_adv_deinit(void) +{ + bt_mesh_adv_type_deinit(BLE_MESH_ADV_FRIEND); + +#if CONFIG_BLE_MESH_FRIEND && CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_FRIEND); +#endif /* CONFIG_BLE_MESH_FRIEND */ + + bt_mesh_unref_buf_from_pool(&friend_buf_pool); + memset(frnd_adv_pool, 0, sizeof(frnd_adv_pool)); +} +#endif /* CONFIG_BLE_MESH_FRIEND */ + +void bt_mesh_adv_task_init(void adv_thread(void *p)) +{ + if (!adv_thread) { + BT_ERR("Invalid param %s", __func__); + return; + } + +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + __ASSERT(adv_task.task, "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 */ +} + +void bt_mesh_adv_common_init(void) +{ + bt_mesh_adv_queue_init(&adv_queue, BLE_MESH_ADV_QUEUE_SIZE, bt_mesh_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_PROV, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_DATA, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_BEACON, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_URI, &adv_queue, &adv_buf_pool, adv_alloc); +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX + bt_mesh_adv_type_init(BLE_MESH_ADV_PROXY_SOLIC, &adv_queue, &adv_buf_pool, adv_alloc); +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_adv_inst_init(BLE_MESH_ADV_INS, CONFIG_BLE_MESH_ADV_INST_ID); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + /** + * Due to the limitation of the sequence number in the network layer, + * it is not possible to use multiple advertising instances to process + * data from the same message queue when sending mesh packets. + * + * Therefore, shall to check whether there are + * duplicates in the queue buffer corresponding to each advertising instance. + */ + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_PROV); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_DATA); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BEACON); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_URI); +#endif +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_task_deinit(void) +{ + vTaskDelete(adv_task.handle); + adv_task.handle = NULL; + +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + heap_caps_free(adv_task.stack); + adv_task.stack = NULL; + heap_caps_free(adv_task.task); + adv_task.task = NULL; +#endif +} + +void bt_mesh_adv_common_deinit(void) +{ + bt_mesh_adv_type_deinit(BLE_MESH_ADV_PROV); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_DATA); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_BEACON); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_URI); + + bt_mesh_adv_queue_deinit(&adv_queue); +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_adv_inst_deinit(BLE_MESH_ADV_INS); +#endif + + bt_mesh_unref_buf_from_pool(&adv_buf_pool); + memset(adv_pool, 0, sizeof(adv_pool)); +} +#endif /* CONFIG_BLE_MESH_DEINIT */ diff --git a/lib/bt/esp_ble_mesh/core/adv_common.h b/lib/bt/esp_ble_mesh/core/adv_common.h new file mode 100644 index 00000000..0477e889 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/adv_common.h @@ -0,0 +1,293 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _ADV_COMMON_H_ +#define _ADV_COMMON_H_ + +#include "mesh/common.h" +#include "mesh/atomic.h" +#include "mesh/access.h" +#include "mesh/adapter.h" +#include "mesh/queue.h" +#include "mesh/timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Pre-5.0 controllers enforce a minimum interval of 100ms + * whereas 5.0+ controllers can go down to 20ms. + */ +#if CONFIG_BLE_MESH_HCI_5_0 +#define ADV_ITVL_MIN 20 +#else +#define ADV_ITVL_MIN 100 +#endif + +/* Convert from ms to 0.625ms units */ +#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) +/* Convert from 0.625ms units to interval(ms) */ +#define ADV_SCAN_INT(val) ((val) * 5 / 8) + +/* Maximum advertising data payload for a single data type */ +#define BLE_MESH_ADV_DATA_SIZE 29 + +/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */ +#define BLE_MESH_ADV_USER_DATA_SIZE 4 + +#define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf)) +#define BLE_MESH_ADV_BUSY(buf) (BLE_MESH_ADV(buf)->busy) + +#define BLE_MESH_MSG_NET_BUF(msg) ((struct net_buf *)(msg->arg)) + +#define BLE_MESH_ADV_INS_UNUSED 0xFF + +/* We reserve one queue item for bt_mesh_adv_update() */ +#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1) + +struct bt_mesh_adv { + const struct bt_mesh_send_cb *cb; + void *cb_data; + + uint8_t type; + + bt_mesh_atomic_t busy; + + uint8_t xmit; +}; + +#if CONFIG_BLE_MESH_FRIEND + +#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), bt_mesh_friend_adv_t, adv) + +typedef struct { + struct bt_mesh_adv adv; + uint16_t app_idx; +} bt_mesh_friend_adv_t; + +#endif + +enum { +#if CONFIG_BLE_MESH_USE_BLE_50 + ADV_TASK_MESH_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_ADV_INST_ID), + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + ADV_TASK_PROX_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_PROXY_ADV_INST_ID), +#endif + +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + ADV_TASK_RELAY_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_RELAY_ADV_INST_ID), +#endif + +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + ADV_TASK_BLE_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_BLE_ADV_INST_ID), +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + ADV_TASK_PROXY_ADV_UPD_EVT = BIT(30), +#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + ADV_TASK_PKT_SEND_EVT = BIT(31), + ADV_TASK_EVT_MAX, +}; + +uint16_t bt_mesh_pdu_duration(uint8_t xmit); + +typedef struct bt_mesh_msg { + bool relay; /* Flag indicates if the packet is a relayed one */ + void *arg; /* Pointer to the struct net_buf */ + uint16_t src; /* Source address for relay packets */ + uint16_t dst; /* Destination address for relay packets */ + uint32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */ +} bt_mesh_msg_t; + +typedef struct bt_mesh_adv *(*bt_mesh_pool_allocator_t)(int id); +typedef void (*bt_mesh_adv_queue_send_cb_t)(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +struct bt_mesh_adv_queue { + bt_mesh_queue_t q; + bt_mesh_adv_queue_send_cb_t send; +}; + +struct bt_mesh_adv_inst { + uint8_t id; +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bool busy; + struct net_buf *sending_buf; + + /* indicates that which adv_type is supported by this instance */ + uint32_t spt_mask; +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +}; + +enum bt_mesh_adv_type { + BLE_MESH_ADV_PROV, + BLE_MESH_ADV_DATA, +#if CONFIG_BLE_MESH_FRIEND + BLE_MESH_ADV_FRIEND, +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + BLE_MESH_ADV_RELAY_DATA, +#endif + BLE_MESH_ADV_BEACON, + BLE_MESH_ADV_URI, +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX + BLE_MESH_ADV_PROXY_SOLIC, +#endif +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + BLE_MESH_ADV_BLE, +#endif + BLE_MESH_ADV_TYPES_NUM, +}; + +typedef enum { + BLE_MESH_BUF_REF_EQUAL, + BLE_MESH_BUF_REF_SMALL, + BLE_MESH_BUF_REF_MAX, +} bt_mesh_buf_ref_flag_t; + +struct bt_mesh_adv_type_manager { + struct bt_mesh_adv_queue *adv_q; + struct net_buf_pool *pool; + bt_mesh_pool_allocator_t pool_allocator; +}; + +static const uint8_t adv_type[] = { + [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, + [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#if CONFIG_BLE_MESH_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 TickType_t K_WAIT(int32_t val) +{ + return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); +} + +struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void); + +struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, + int32_t timeout); + +static inline struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout) +{ + return bt_mesh_adv_create_from_pool(type, timeout); +} + +void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, + uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag); + +struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type); + +void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data, uint16_t src, + uint16_t dst, bool front); + +void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool); +void bt_mesh_unref_buf(bt_mesh_msg_t *msg); + +int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, + uint16_t queue_size, + bt_mesh_adv_queue_send_cb_t cb); + +int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue); + +void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, + struct bt_mesh_adv_queue *adv_queue, + struct net_buf_pool *buf_pool, + bt_mesh_pool_allocator_t adv_alloc); + +void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type); + +void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +#if CONFIG_BLE_MESH_USE_BLE_50 +struct bt_mesh_adv_inst * bt_mesh_get_adv_insts_set(void); +int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id); +int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); + +void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); + +void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); +#endif + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +void bt_mesh_relay_adv_init(void); +bool bt_mesh_ignore_relay_packet(uint32_t timestamp); +struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout); + +static inline void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, + uint16_t src, uint16_t dst, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, src, dst, false); +}; + +uint16_t bt_mesh_get_stored_relay_count(void); + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_relay_adv_deinit(void); +#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + +#if CONFIG_BLE_MESH_FRIEND +struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int id); +struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void); +void bt_mesh_frnd_adv_init(void); +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_frnd_adv_deinit(void); +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_FRIEND */ + +void bt_mesh_adv_task_init(void adv_thread(void *p)); +void bt_mesh_adv_common_init(void); + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_task_deinit(void); +void bt_mesh_adv_common_deinit(void); +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 +bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id); +bool ble_mesh_adv_task_wait(uint32_t wait_bits, TickType_t timeout, uint32_t *notify); +int ble_mesh_adv_task_wakeup(uint32_t evt); +#else +bool ble_mesh_adv_task_wait(uint32_t timeout); +#endif + +#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 /* _ADV_COMMON_H_ */ diff --git a/lib/bt/esp_ble_mesh/core/beacon.c b/lib/bt/esp_ble_mesh/core/beacon.c index 488a3c5f..97ec6ebd 100644 --- a/lib/bt/esp_ble_mesh/core/beacon.c +++ b/lib/bt/esp_ble_mesh/core/beacon.c @@ -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 */ @@ -25,7 +25,9 @@ #include "pvnr_mgmt.h" #include "mesh/common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if defined(CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL) #define UNPROV_BEACON_INTERVAL K_SECONDS(CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL) @@ -33,7 +35,11 @@ #define UNPROV_BEACON_INTERVAL K_SECONDS(5) #endif +#if CONFIG_BLE_MESH_BQB_TEST +#define SECURE_BEACON_INTERVAL K_SECONDS(3) +#else #define SECURE_BEACON_INTERVAL K_SECONDS(10) +#endif /* 3 transmissions, 20ms interval */ #define UNPROV_XMIT BLE_MESH_TRANSMIT(2, 20) @@ -472,12 +478,13 @@ void bt_mesh_beacon_recv(struct net_buf_simple *buf, int8_t rssi) bt_mesh_provisioner_unprov_beacon_recv(buf, rssi); } - if (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && - bt_mesh_is_provisioned()) { +#if CONFIG_BLE_MESH_RPR_SRV + if (bt_mesh_is_provisioned()) { const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr(); bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type()); bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi); } +#endif break; case BEACON_TYPE_SECURE: secure_beacon_recv(buf); diff --git a/lib/bt/esp_ble_mesh/core/ble_adv.c b/lib/bt/esp_ble_mesh/core/ble_adv.c new file mode 100644 index 00000000..ec99efa0 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/ble_adv.c @@ -0,0 +1,323 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "ble_adv.h" +#include "mesh/common.h" +#include "mesh/buf.h" + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + +static struct bt_mesh_adv_queue ble_adv_queue; +#define BLE_MESH_BLE_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1) +/* length + advertising data + length + scan response data */ +NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, + ((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; + +static struct bt_mesh_ble_adv_tx ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; + +#define SEND_BLE_ADV_INFINITE 0xFFFF + +static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +static struct bt_mesh_adv *ble_adv_alloc(int id) +{ + return &ble_adv_pool[id]; +} + +static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + BT_DBG("%s", __func__); + + if (ble_adv_queue.q.handle == NULL) { + BT_ERR("Invalid adv queue"); + return; + } + + if (front) { + if (xQueueSendToFront(ble_adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue front"); + bt_mesh_unref_buf(msg); + } + } else { + if (xQueueSend(ble_adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue back"); + bt_mesh_unref_buf(msg); + } + } +} + +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(type, timeout); +} + +inline void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, + void *cb_data, bool front) +{ + bt_mesh_generic_adv_send(buf, 0, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, front); +} + +static void ble_adv_tx_reset(struct bt_mesh_ble_adv_tx *tx, bool unref) +{ + if (tx->buf == NULL) { + return; + } + + if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) { + k_delayed_work_free(&tx->resend); + } + bt_mesh_atomic_set(tx->flags, 0); + memset(&tx->param, 0, sizeof(tx->param)); + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->buf), 0); + if (unref) { + net_buf_unref(tx->buf); + } + tx->buf = NULL; +} + +static void ble_adv_send_start(uint16_t duration, int err, void *cb_data) +{ + struct bt_mesh_ble_adv_tx *tx = cb_data; + + BT_DBG("%s, duration %d, err %d", __func__, duration, err); + + /* If failed to send BLE adv packet, and param->count is not 0 + * which means the timer has been initialized, here we need to + * free the timer. + */ + if (err) { + ble_adv_tx_reset(tx, true); + } +} + +static void ble_adv_send_end(int err, void *cb_data) +{ + struct bt_mesh_ble_adv_tx *tx = cb_data; + + BT_DBG("%s, err %d", __func__, err); + + if (err) { + ble_adv_tx_reset(tx, true); + return; + } + + if (tx->param.count) { + if (tx->param.period) { + k_delayed_work_submit(&tx->resend, tx->param.period); + } else { + k_work_submit(&tx->resend.work); + } + } else { + ble_adv_tx_reset(tx, true); + } +} + +static struct bt_mesh_send_cb ble_adv_send_cb = { + .start = ble_adv_send_start, + .end = ble_adv_send_end, +}; + +static void ble_adv_resend(struct k_work *work) +{ + struct bt_mesh_ble_adv_tx *tx = CONTAINER_OF(work, struct bt_mesh_ble_adv_tx, resend.work); + bool front = false; + + if (tx->buf == NULL) { + /* The advertising has been cancelled */ + return; + } + + front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; + bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front); + + if (tx->param.count == SEND_BLE_ADV_INFINITE) { + /* Send the BLE advertising packet infinitely */ + return; + } + + if (tx->param.count > 0U) { + tx->param.count--; + } +} + +int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data, uint8_t *index) +{ + struct bt_mesh_ble_adv_tx *tx = NULL; + struct net_buf *buf = NULL; + bool front = false; + + if (param == NULL || index == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + if (param->adv_type != BLE_MESH_ADV_DIRECT_IND && + (param->interval < 0x20 || param->interval > 0x4000)) { + BT_ERR("Invalid adv interval 0x%04x", param->interval); + return -EINVAL; + } + + if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + BT_ERR("Invalid adv type 0x%02x", param->adv_type); + return -EINVAL; + } + + if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) { + BT_ERR("Invalid own addr type 0x%02x", param->own_addr_type); + return -EINVAL; + } + + if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || + param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || + param->adv_type == BLE_MESH_ADV_DIRECT_IND || + param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) && + param->peer_addr_type > BLE_MESH_ADDR_RANDOM) { + BT_ERR("Invalid peer addr type 0x%02x", param->peer_addr_type); + return -EINVAL; + } + + if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) { + BT_ERR("Invalid adv data length (adv %d, scan rsp %d)", + data->adv_data_len, data->scan_rsp_data_len); + return -EINVAL; + } + + if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) { + BT_ERR("Invalid adv priority %d", param->priority); + return -EINVAL; + } + + if (param->duration < ADV_SCAN_INT(param->interval)) { + BT_ERR("Too small duration %dms", param->duration); + return -EINVAL; + } + + buf = bt_mesh_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 bt_mesh_ble_adv_tx *tx = NULL; + bool unref = true; + + if (index >= ARRAY_SIZE(ble_adv_tx)) { + BT_ERR("Invalid adv index %d", index); + return -EINVAL; + } + + tx = &ble_adv_tx[index]; + + if (tx->buf == NULL) { + BT_WARN("Already stopped, index %d", index); + return 0; + } + + /* busy 1, ref 1; busy 1, ref 2; + * busy 0, ref 0; busy 0, ref 1; + */ + + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf)) && + tx->buf->ref == 1U) { + unref = false; + } + ble_adv_tx_reset(tx, unref); + + return 0; +} + +void bt_mesh_ble_adv_init(void) +{ + bt_mesh_adv_queue_init(&ble_adv_queue, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, bt_mesh_ble_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_BLE, &ble_adv_queue, &ble_adv_buf_pool, ble_adv_alloc); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + bt_mesh_adv_inst_init(BLE_MESH_BLE_ADV_INS, CONFIG_BLE_MESH_BLE_ADV_INST_ID); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_BLE_ADV_INS, BLE_MESH_ADV_BLE); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BLE); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_ble_adv_deinit(void) +{ + for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) { + struct bt_mesh_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)); + + bt_mesh_adv_queue_deinit(&ble_adv_queue); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_BLE); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + bt_mesh_adv_inst_deinit(BLE_MESH_BLE_ADV_INS); + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_BLE_ADV_INS, BLE_MESH_ADV_BLE); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_BLE); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ diff --git a/lib/bt/esp_ble_mesh/core/ble_adv.h b/lib/bt/esp_ble_mesh/core/ble_adv.h new file mode 100644 index 00000000..733320d6 --- /dev/null +++ b/lib/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/lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index e0fc33b4..db962097 100644 --- a/lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -29,10 +29,14 @@ #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" +#endif struct bt_mesh_dev bt_mesh_dev; @@ -58,7 +62,10 @@ 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 || \ @@ -102,6 +109,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; @@ -136,11 +153,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) { @@ -183,6 +207,193 @@ 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; + 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 */ +} + +static bool bt_mesh_scan_result_process(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report) +{ + struct bt_mesh_adv_report adv_rpt = {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; + + if (!(ext_adv_report->event_type & BTM_BLE_ADV_LEGACY_MASK)) { + return false; + } + + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { + return false; + } + + BT_DBG("Recv adv report type %04x", ext_adv_report->event_type); + + 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: + adv_rpt.adv_type = ext_adv_report->event_type; + break; + default: + return false; + break; + } + + if (bt_mesh_scan_dev_found_cb) { + net_buf_simple_init_with_data(&adv_rpt.adv_data, ext_adv_report->adv_data, ext_adv_report->adv_data_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + if (adv_rpt.adv_data.len != ext_adv_report->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 + ble_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 */ + ble_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(); + ble_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) { @@ -203,7 +414,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; @@ -225,16 +441,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 @@ -243,6 +465,7 @@ static void start_adv_completed_cb(uint8_t status) } #endif } +#endif static bool valid_scan_param(const struct bt_mesh_scan_param *param) { @@ -274,15 +497,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) { @@ -295,22 +557,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); @@ -318,7 +590,133 @@ 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 +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) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN; + } else { + BT_ERR("Unsupported PHY: pri %d sec %d",param->primary_phy, param->secondary_phy); + return -EINVAL; + } + } + +#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 = 0x7F; + ext_adv_params.scan_req_notif = false; + ext_adv_params.primary_phy = param->primary_phy; + ext_adv_params.secondary_phy = param->secondary_phy; + ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + ext_adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + + 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; + + /* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */ + BTA_DmBleGapExtAdvSetParams(inst_id, &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, @@ -346,7 +744,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; } @@ -362,7 +760,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; } } @@ -425,8 +823,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}; + + 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); + } + } + + 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_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_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); + + 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) { @@ -468,8 +958,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 @@ -487,6 +1001,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) { @@ -528,7 +1043,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; @@ -655,6 +1174,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) { @@ -1196,6 +1728,7 @@ uint16_t bt_mesh_gattc_get_service_uuid(struct bt_mesh_conn *conn) int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) { + tBTA_BLE_CONN_PARAMS conn_1m_param = {0}; uint8_t zero[6] = {0}; int i; @@ -1238,21 +1771,49 @@ 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 */ - BTA_DmSetBlePrefConnParams(bt_mesh_gattc_info[i].addr.val, 0x18, 0x18, 0x00, 0x64); - - BTA_GATTC_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); + 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, + BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); +#else + /* Min_interval: 15ms + * Max_interval: 15ms + * Slave_latency: 0x0 + * Supervision_timeout: 1s + */ + conn_1m_param.interval_min = 0x18; + conn_1m_param.interval_max = 0x18; + conn_1m_param.latency = 0; + 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, + BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); +#endif return 0; } @@ -1592,8 +2153,10 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (bt_mesh_gattc_info[i].conn.handle == handle) { if (bt_mesh_gattc_info[i].wr_desc_done == false) { - BT_DBG("Receive notification before finishing to write ccc"); + BT_WARN("Receive notification before finishing to write ccc"); +#if !CONFIG_BLE_MESH_BQB_TEST return; +#endif } conn = &bt_mesh_gattc_info[i].conn; @@ -1653,11 +2216,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; diff --git a/lib/bt/esp_ble_mesh/core/cfg_srv.c b/lib/bt/esp_ble_mesh/core/cfg_srv.c index 9d91cb21..fe605939 100644 --- a/lib/bt/esp_ble_mesh/core/cfg_srv.c +++ b/lib/bt/esp_ble_mesh/core/cfg_srv.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,7 +30,9 @@ #include "mesh/common.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define DEFAULT_TTL 7 @@ -38,6 +40,158 @@ static struct bt_mesh_cfg_srv *conf; static struct label labels[CONFIG_BLE_MESH_LABEL_COUNT]; +#if !CONFIG_BLE_MESH_V11_SUPPORT +const void *comp_0; + +static uint8_t bt_mesh_comp_page_check(uint8_t page, bool largest) +{ + /* If the page doesn't exist, TWO situations currently: + * 1. For Composition Data Get: + * With the Page field set to the largest page number of + * the Composition Data that the node supports and that is + * less than the Page field value of the received Config + * Composition Data Get message; + * 2. For Large Composition Data Get: + * The Page field shall be set to the largest page number + * of the Composition Data that the node supports. + */ + ARG_UNUSED(largest); + + if (page != 0) { + BT_WARN("Composition Data Page %d not exists", page); + } + + return 0; +} + +static inline uint16_t get_comp_elem_size(struct bt_mesh_elem *elem) +{ + return (4 + elem->model_count * 2 + elem->vnd_model_count * 4); +} + +static uint16_t get_comp_data_size(const struct bt_mesh_comp *comp) +{ + uint16_t size = 10; /* CID + PID + VID + CRPL + Features */ + + for (int i = 0; i < comp->elem_count; i++) { + size += get_comp_elem_size(&(comp->elem[i])); + } + + return size; +} + +static void get_comp_data(struct net_buf_simple *buf, + const struct bt_mesh_comp *comp, + bool full_element) +{ + struct bt_mesh_model *model = NULL; + struct bt_mesh_elem *elem = NULL; + uint16_t feat = 0; + + if (IS_ENABLED(CONFIG_BLE_MESH_RELAY)) { + feat |= BLE_MESH_FEAT_RELAY; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { + feat |= BLE_MESH_FEAT_PROXY; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + feat |= BLE_MESH_FEAT_FRIEND; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { + feat |= BLE_MESH_FEAT_LOW_POWER; + } + + net_buf_simple_add_le16(buf, comp->cid); + net_buf_simple_add_le16(buf, comp->pid); + net_buf_simple_add_le16(buf, comp->vid); + net_buf_simple_add_le16(buf, CONFIG_BLE_MESH_CRPL); + net_buf_simple_add_le16(buf, feat); + + for (size_t i = 0; i < comp->elem_count; i++) { + elem = &(comp->elem[i]); + + /* If "full_element" is true, which means the complete list + * of models within the element needs to fit in the data, + * otherwise the element shall not be reported. + */ + if (full_element && + net_buf_simple_tailroom(buf) < get_comp_elem_size(elem)) { + return; + } + + net_buf_simple_add_le16(buf, elem->loc); + net_buf_simple_add_u8(buf, elem->model_count); + net_buf_simple_add_u8(buf, elem->vnd_model_count); + + for (size_t j = 0; j < elem->model_count; j++) { + model = &(elem->models[j]); + net_buf_simple_add_le16(buf, model->id); + } + + for (size_t j = 0; j < elem->vnd_model_count; j++) { + model = &(elem->vnd_models[j]); + net_buf_simple_add_le16(buf, model->vnd.company); + net_buf_simple_add_le16(buf, model->vnd.id); + } + } +} + +static int fetch_comp_data(struct net_buf_simple *buf, + const struct bt_mesh_comp *comp, + uint8_t page, uint16_t offset, + bool full_element) +{ + uint16_t size = get_comp_data_size(comp); + + if (offset >= size) { + BT_WARN("Too large offset %d for comp data %d, size %d", + page, offset, size); + return 0; + } + + if (net_buf_simple_tailroom(buf) < 10 || + size - offset > net_buf_simple_tailroom(buf)) { + BT_ERR("Too small buffer for comp data %d, %d, expected %d", + page, buf->size, size - offset); + return -EINVAL; + } + + if (offset) { + struct net_buf_simple *pdu = bt_mesh_alloc_buf(size); + if (pdu == NULL) { + BT_ERR("%s, Out of memory", __func__); + return -ENOMEM; + } + + get_comp_data(pdu, comp, false); + + /* Get part of Composition Data Page 0/128 */ + net_buf_simple_add_mem(buf, pdu->data + offset, pdu->len - offset); + + bt_mesh_free_buf(pdu); + } else { + get_comp_data(buf, comp, full_element); + } + + return 0; +} + +static int bt_mesh_get_comp_data(struct net_buf_simple *buf, + uint8_t page, uint16_t offset, + bool full_element) +{ + if (page == 0) { + return fetch_comp_data(buf, comp_0, page, offset, full_element); + } + + BT_ERR("Invalid Composition Data Page %d", page); + return -EINVAL; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static void comp_data_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) @@ -1133,7 +1287,7 @@ static struct label *va_find(const uint8_t *label_uuid, return match; } -static uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) +uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) { struct label *update = NULL, *free_slot = NULL; @@ -1141,6 +1295,9 @@ static uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) if (update) { update->ref++; va_store(update); + if (addr) { + *addr = update->addr; + } return STATUS_SUCCESS; } @@ -1160,7 +1317,7 @@ static uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) return STATUS_SUCCESS; } -static uint8_t va_del(uint8_t *label_uuid, uint16_t *addr) +uint8_t va_del(uint8_t *label_uuid, uint16_t *addr) { struct label *update = NULL; @@ -2758,7 +2915,7 @@ static void node_reset(struct bt_mesh_model *model, bt_mesh_model_msg_init(&msg, OP_NODE_RESET_STATUS); - /* Send the response first since we wont have any keys left to + /* Send the response first since we won't have any keys left to * send it later. */ if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { diff --git a/lib/bt/esp_ble_mesh/core/crypto.c b/lib/bt/esp_ble_mesh/core/crypto.c index 9b762fb5..2577c65e 100644 --- a/lib/bt/esp_ble_mesh/core/crypto.c +++ b/lib/bt/esp_ble_mesh/core/crypto.c @@ -22,7 +22,9 @@ #include "mesh/common.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4) #define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4) diff --git a/lib/bt/esp_ble_mesh/core/ext_adv.c b/lib/bt/esp_ble_mesh/core/ext_adv.c new file mode 100644 index 00000000..b8b4d231 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/ext_adv.c @@ -0,0 +1,427 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "mesh/kernel.h" +#include "mesh.h" +#include "mesh/hci.h" +#include "mesh/common.h" +#include "mesh/ffs.h" +#include "ext_adv.h" +#include "beacon.h" +#include "prov_common.h" +#include "foundation.h" +#include "proxy_server.h" +#include "proxy_client.h" +#include "prov_pvnr.h" +#include "mesh/adapter.h" + +#include "adv_common.h" +#include "ble_adv.h" + +static struct bt_mesh_adv_queue *adv_queue; + +static struct bt_mesh_adv_inst *adv_insts; + +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); + } +} + +static inline int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) +{ + struct net_buf *buf = inst->sending_buf; + const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; + void *cb_data = BLE_MESH_ADV(buf)->cb_data; + struct bt_mesh_adv_param param = {0}; + uint16_t duration = 0U, adv_int = 0U; + struct bt_mesh_adv_data ad = {0}; + int err = 0; + + BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type, + buf->len, bt_hex(buf->data, buf->len)); + + switch (BLE_MESH_ADV(buf)->type) { + case BLE_MESH_ADV_PROV: + case BLE_MESH_ADV_DATA: +#if CONFIG_BLE_MESH_FRIEND + case BLE_MESH_ADV_FRIEND: +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + case BLE_MESH_ADV_RELAY_DATA: +#endif +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX + case BLE_MESH_ADV_PROXY_SOLIC: +#endif + case BLE_MESH_ADV_BEACON: + case BLE_MESH_ADV_URI: { + 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); + + BT_DBG("count %u interval %ums duration %ums", + BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int, + duration); + + ad.type = adv_type[BLE_MESH_ADV(buf)->type]; + ad.data_len = buf->len; + ad.data = buf->data; + + param.options = 0U; + param.interval_min = ADV_SCAN_UNIT(adv_int); + param.interval_max = param.interval_min; + + param.adv_duration = duration; + param.adv_count = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1; + + param.primary_phy = BLE_MESH_ADV_PHY_1M; + param.secondary_phy = BLE_MESH_ADV_PHY_1M; + +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX + if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) { + bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + struct bt_mesh_adv_data solic_ad[2] = { + BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18), + BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len), + }; + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); + } else +#endif + { + bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL); + err = bt_le_ext_adv_start(inst->id, ¶m, &ad, 1, NULL, 0); + } + } + break; +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + case BLE_MESH_ADV_BLE: + struct bt_mesh_ble_adv_data data = {0}; + struct bt_mesh_ble_adv_tx *tx = cb_data; + + if (tx == NULL) { + BT_ERR("Invalid adv user data"); + net_buf_unref(buf); + return -EINVAL; + } + + BT_DBG("interval %dms, duration %dms, period %dms, count %d", + ADV_SCAN_INT(tx->param.interval), tx->param.duration, + tx->param.period, tx->param.count); + + data.adv_data_len = tx->buf->data[0]; + if (data.adv_data_len) { + memcpy(data.adv_data, tx->buf->data + 1, data.adv_data_len); + } + data.scan_rsp_data_len = tx->buf->data[data.adv_data_len + 1]; + if (data.scan_rsp_data_len) { + memcpy(data.scan_rsp_data, tx->buf->data + data.adv_data_len + 2, data.scan_rsp_data_len); + } + duration = tx->param.duration; + + bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + + err = bt_mesh_ble_ext_adv_start(inst->id, &tx->param, &data); + break; +#endif + default: + BT_ERR("Error Type"); + break; + } + + adv_send_start(duration, err, cb, cb_data); + if (err) { + BT_ERR("Start advertising failed: err %d", err); + return err; + } + + *adv_duration = duration; + BT_DBG("Advertising started. %u ms", duration); + return 0; +} + +static inline int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t *msg) +{ + while(uxQueueMessagesWaiting(msg_queue->handle)) { + xQueueReceive(msg_queue->handle, msg, K_WAIT(K_FOREVER)); + + /* In the previous adv task design, only + * the *buf of messages pushed to the queue + * by adv_update would be empty, but in the + * new design, there is a new processing method + * for adv_update's messages, + * so *buf here cannot be empty. */ + assert(msg->arg); + + /* If the message is canceled for advertising, + * then continue to retrieve the next message + * from that queue. */ + if (!bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(BLE_MESH_MSG_NET_BUF(msg)), 1, 0)) { + bt_mesh_adv_buf_ref_debug(__func__, BLE_MESH_MSG_NET_BUF(msg), 1U, BLE_MESH_BUF_REF_EQUAL); + /* Cancel the adv task's reference to this data packet. + * tips: The reference of buffer by adv_task occurs + * when the buffer is pushed into the queue. + */ + net_buf_unref(BLE_MESH_MSG_NET_BUF(msg)); + /* Avoid reading the last message in the queue, which could lead + * to pointing to an invalid buffer due to the absence of other + * messages in the queue. */ + msg->arg = NULL; + continue; + } + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + /* If the relay message should be ignored, + * then continue to retrieve the next message + * from that queue. */ + if (msg->relay && bt_mesh_ignore_relay_packet(msg->timestamp)) { + /* If the interval between "current time - msg.timestamp" is bigger than + * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. + */ + BT_DBG("Ignore relay packet"); + net_buf_unref(BLE_MESH_MSG_NET_BUF(msg)); + msg->arg = NULL; + continue; + } +#endif + break; + } + + if (msg->arg == NULL) { + return -EINVAL; + } + + return 0; +} + +static inline int active_idle_adv_instance(uint32_t *update_evts, uint16_t *min_duration) +{ + uint32_t evts = 0; + uint16_t duration = K_FOREVER; + uint16_t cur_min_duration = K_FOREVER; + enum bt_mesh_adv_type adv_type = 0; + struct bt_mesh_adv_inst *instance = NULL; + bt_mesh_queue_t *msg_queue = NULL; + bt_mesh_msg_t msg = {0}; + uint32_t spt_mask = 0; + +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (!adv_insts[BLE_MESH_ADV_PROXY_INS].busy) { + BT_DBG("Mesh Proxy Advertising start"); + duration = bt_mesh_proxy_server_adv_start(); + if (duration < cur_min_duration) { + cur_min_duration = duration; + } + adv_insts[BLE_MESH_ADV_PROXY_INS].busy = true; + evts |= ADV_TASK_ADV_INST_EVT(adv_insts[BLE_MESH_ADV_PROXY_INS].id); + } +#endif + + for (int i = BLE_MESH_ADV_INS; i < BLE_MESH_ADV_INS_TYPES_NUM; i++) { + instance = &adv_insts[i]; + if (instance->busy +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + || unlikely(instance->id == CONFIG_BLE_MESH_PROXY_ADV_INST_ID) +#endif + ) { + continue; + } + + spt_mask = instance->spt_mask; + adv_type = 0; + + while(spt_mask) { + adv_type = find_lsb_set(spt_mask) - 1; + spt_mask &= ~BIT(adv_type); + msg_queue = &(bt_mesh_adv_types_mgnt_get(adv_type)->adv_q->q); + + /* When there is no new message in the queue, *buf (aka: msg.arg) + * will be empty. */ + if (find_valid_msg_from_queue(msg_queue, &msg)) { + BT_DBG("no valid message for instance %d", instance->id); + continue; + } + + instance->sending_buf = (struct net_buf *)msg.arg; + if (adv_send(instance, &duration)) { + BT_ERR("adv start failed"); + net_buf_unref(instance->sending_buf); + instance->sending_buf = NULL; + /* When this adv instance fails to broadcast, it could be + * due to some persistent issues, such as incorrect adv + * parameter settings, or it could be due to some temporary + * issues, such as memory allocation failure. Therefore, it + * is advisable to skip subsequent queue reads for this instance + * and attempt to broadcast subsequent data again next time, + * rather than disabling the adv instance. */ + break; + } + + if (duration < cur_min_duration) { + cur_min_duration = duration; + } + + instance->busy = true; + evts |= ADV_TASK_ADV_INST_EVT(adv_insts[i].id); + + /* Must be nullified to avoid affecting the next adv + * instance's judgment on whether the message queue + * is empty. */ + msg.arg = NULL; + break; + } + } + + *min_duration = cur_min_duration; + *update_evts |= evts; + + return 0; +} + +static uint32_t received_adv_evts_handle(uint32_t recv_evts) +{ + uint32_t evt = 0; + + if (!recv_evts) { + return 0; + } + + for (int i = 0; recv_evts && i < BLE_MESH_ADV_INS_TYPES_NUM; i++) { + evt = ADV_TASK_ADV_INST_EVT(adv_insts[i].id); + if (recv_evts & evt) { + recv_evts &= ~evt; +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ +CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (unlikely(i == BLE_MESH_ADV_PROXY_INS)) { + BT_DBG("Mesh Proxy Advertising auto stop"); + bt_mesh_proxy_server_adv_flag_set(false); + } else +#endif + { + /* adv_send_end maybe*/ + adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); + bt_mesh_adv_buf_ref_debug(__func__, adv_insts[i].sending_buf, 4U, BLE_MESH_BUF_REF_SMALL); + net_buf_unref(adv_insts[i].sending_buf); + adv_insts[i].sending_buf = NULL; + } + adv_insts[i].busy = false; + } + } + + return recv_evts; +} + +static void adv_thread(void *p) +{ + uint16_t adv_duration = K_FOREVER; + uint32_t recv_evts = 0; + uint32_t wait_evts = 0; + + BT_DBG("%s, starts", __func__); + + while (1) { + adv_duration = K_FOREVER; + wait_evts |= ADV_TASK_PKT_SEND_EVT; + + active_idle_adv_instance(&wait_evts, &adv_duration); + + ble_mesh_adv_task_wait(wait_evts, adv_duration, &recv_evts); + + wait_evts &= ~recv_evts; + +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (recv_evts & ADV_TASK_PROXY_ADV_UPD_EVT) { + adv_insts[BLE_MESH_ADV_PROXY_INS].busy = false; + recv_evts &= ~ADV_TASK_PROXY_ADV_UPD_EVT; + } +#endif + + /** + * `recv_evts == ADV_TASK_PKT_SEND_EVT` indicates that new packets + * have been placed into the queue, and the advertising instances started + * previous have not yet stopped. + */ + if (recv_evts == ADV_TASK_PKT_SEND_EVT) { + continue; + } + + recv_evts = received_adv_evts_handle(recv_evts); + + if (recv_evts) { + BT_ERR("Remain evts %08x to handle", recv_evts); + } + } +} + +void bt_mesh_adv_update(void) +{ +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + BT_DBG("Mesh Proxy Advertising stopped manually"); + bt_mesh_proxy_server_adv_stop(); + if (adv_insts[BLE_MESH_ADV_PROXY_INS].busy) { + ble_mesh_adv_task_wakeup(ADV_TASK_PROXY_ADV_UPD_EVT); + } +#endif +} + +void bt_mesh_adv_init(void) +{ + bt_mesh_adv_common_init(); + + adv_insts = bt_mesh_get_adv_insts_set(); + adv_queue = bt_mesh_adv_queue_get(); + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + bt_mesh_relay_adv_init(); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_init(); +#endif + + bt_mesh_adv_task_init(adv_thread); +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_deinit(void) +{ + bt_mesh_adv_task_deinit(); + + bt_mesh_adv_common_deinit(); + + adv_insts = NULL; + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + bt_mesh_relay_adv_deinit(); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_deinit(); +#endif +} +#endif /* CONFIG_BLE_MESH_DEINIT */ diff --git a/lib/bt/esp_ble_mesh/core/ext_adv.h b/lib/bt/esp_ble_mesh/core/ext_adv.h new file mode 100644 index 00000000..3004db27 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/ext_adv.h @@ -0,0 +1,39 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _EXT_ADV_H_ +#define _EXT_ADV_H_ + +#include "mesh/atomic.h" +#include "mesh/access.h" +#include "mesh/adapter.h" +#include "mesh/queue.h" +#include "adv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, false); +} + +void bt_mesh_adv_update(void); + +void bt_mesh_adv_init(void); +void bt_mesh_adv_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _EXT_ADV_H_ */ diff --git a/lib/bt/esp_ble_mesh/core/friend.c b/lib/bt/esp_ble_mesh/core/friend.c index fca3cf13..99e41cd0 100644 --- a/lib/bt/esp_ble_mesh/core/friend.c +++ b/lib/bt/esp_ble_mesh/core/friend.c @@ -21,18 +21,12 @@ #include "mesh/common.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #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). * @@ -55,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, @@ -81,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) { if (frnd->lpn == BLE_MESH_ADDR_UNASSIGNED) { @@ -183,7 +163,7 @@ static void friend_clear(struct bt_mesh_friend *frnd, uint8_t reason) /* Cancel the sending if necessary */ if (frnd->pending_buf) { bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 2U, BLE_MESH_BUF_REF_EQUAL); - BLE_MESH_ADV(frnd->last)->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(frnd->last), 0); } else { bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 1U, BLE_MESH_BUF_REF_EQUAL); } @@ -366,8 +346,7 @@ 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); + buf = bt_mesh_adv_create_from_pool(BLE_MESH_ADV_FRIEND, K_NO_WAIT); if (!buf) { return NULL; } @@ -1321,6 +1300,8 @@ int bt_mesh_friend_init(void) } } + bt_mesh_frnd_adv_init(); + friend_init = true; return 0; @@ -1347,8 +1328,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/lib/bt/esp_ble_mesh/core/include/mesh/access.h b/lib/bt/esp_ble_mesh/core/include/mesh/access.h index 86731036..fac49976 100644 --- a/lib/bt/esp_ble_mesh/core/include/mesh/access.h +++ b/lib/bt/esp_ble_mesh/core/include/mesh/access.h @@ -4,7 +4,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -348,7 +348,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/lib/bt/esp_ble_mesh/core/include/mesh/adapter.h b/lib/bt/esp_ble_mesh/core/include/mesh/adapter.h index 1cb239a3..f02c9f5b 100644 --- a/lib/bt/esp_ble_mesh/core/include/mesh/adapter.h +++ b/lib/bt/esp_ble_mesh/core/include/mesh/adapter.h @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA * SPDX-FileCopyrightText: 2015-2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,18 +21,78 @@ 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 +#if CONFIG_IDF_TARGET_ESP32 +#define BLE_MESH_MAX_CONN 1 +#elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) +/* @todo: must ensure CONFIG_BT_CTRL_BLE_MAX_ACT is greater than 2 */ +#if CONFIG_BT_ACL_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) +/* decrease the adv,scan */ +#define BLE_MESH_MAX_CONN (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) +#else #define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS +#endif /* CONFIG_BT_ACL_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) */ +#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 +#if CONFIG_BT_ACL_CONNECTIONS > CONFIG_BT_LE_MAX_CONNECTIONS +#define BLE_MESH_MAX_CONN CONFIG_BT_LE_MAX_CONNECTIONS +#else +#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS +#endif /* 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 1 +#elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) +/* @todo: must ensure CONFIG_BT_CTRL_BLE_MAX_ACT is greater than 2 */ +#if CONFIG_BT_NIMBLE_MAX_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) +/* decrease the adv,scan */ +#define BLE_MESH_MAX_CONN (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) +#else +#define BLE_MESH_MAX_CONN CONFIG_BT_NIMBLE_MAX_CONNECTIONS +#endif /* 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 #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 */ #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_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 +#endif + /* BD ADDR types */ #define BLE_MESH_ADDR_PUBLIC 0x00 #define BLE_MESH_ADDR_RANDOM 0x01 @@ -43,11 +103,22 @@ 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 */ +#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 /* advertising channel map */ #define BLE_MESH_ADV_CHNL_37 BIT(0) @@ -400,6 +471,39 @@ struct bt_mesh_adv_param { /** Maximum Advertising Interval (N * 0.625) */ uint16_t interval_max; + +#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; +#endif +}; + +#define ADV_TASK_ADV_INST_EVT(inst_id) BIT(inst_id) + +enum bt_mesh_adv_inst_type { + BLE_MESH_ADV_INS, +#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_INS, +#endif +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + BLE_MESH_RELAY_ADV_INS, +#endif +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + BLE_MESH_BLE_ADV_INS, +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + BLE_MESH_ADV_INS_TYPES_NUM, }; #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV @@ -441,7 +545,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 +557,38 @@ 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; +#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. @@ -553,7 +674,7 @@ struct bt_mesh_gatt_attr { * @param len Length of data to read * @param offset Offset to start reading from * - * @return Number fo bytes read, or in case of an error + * @return Number of bytes read, or in case of an error * BLE_MESH_GATT_ERR() with a specific ATT error code. */ ssize_t (*read)(struct bt_mesh_conn *conn, @@ -684,6 +805,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 +827,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); diff --git a/lib/bt/esp_ble_mesh/core/lpn.c b/lib/bt/esp_ble_mesh/core/lpn.c index f445be56..80f5b432 100644 --- a/lib/bt/esp_ble_mesh/core/lpn.c +++ b/lib/bt/esp_ble_mesh/core/lpn.c @@ -10,6 +10,7 @@ #include #include "crypto.h" +#include "tag.h" #include "adv.h" #include "scan.h" #include "mesh.h" @@ -23,7 +24,9 @@ #include "mesh/cfg_srv.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef CONFIG_BLE_MESH_LOW_POWER diff --git a/lib/bt/esp_ble_mesh/core/main.c b/lib/bt/esp_ble_mesh/core/main.c index ad94e2c8..957234e3 100644 --- a/lib/bt/esp_ble_mesh/core/main.c +++ b/lib/bt/esp_ble_mesh/core/main.c @@ -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 */ @@ -30,7 +30,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif static bool mesh_init = false; @@ -161,9 +163,9 @@ void bt_mesh_node_reset(void) bt_mesh_clear_seq(); bt_mesh_clear_dkca(); bt_mesh_clear_role(); - if (IS_ENABLED(CONFIG_BLE_MESH_DF_SRV)) { - bt_mesh_clear_all_directed_forwarding_table_data(); - } +#if CONFIG_BLE_MESH_DF_SRV + bt_mesh_clear_all_directed_forwarding_table_data(); +#endif } memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags)); @@ -405,12 +407,14 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, return -EALREADY; } +#if CONFIG_BLE_MESH_V11_SUPPORT extern int bt_mesh_v11_ext_init(void); err = bt_mesh_v11_ext_init(); if (err) { BT_ERR("Bluetooth Mesh v1.1 init failed"); return err; } +#endif bt_mesh_mutex_init(); @@ -437,7 +441,9 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, if ((IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) || - IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)) { + IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) || + (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && + IS_ENABLED(CONFIG_BLE_MESH_PB_GATT))) { bt_mesh_proxy_client_init(); } @@ -587,7 +593,9 @@ int bt_mesh_deinit(struct bt_mesh_deinit_param *param) if ((IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) || - IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)) { + IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) || + (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && + IS_ENABLED(CONFIG_BLE_MESH_PB_GATT))) { bt_mesh_proxy_client_deinit(); } diff --git a/lib/bt/esp_ble_mesh/core/mesh.h b/lib/bt/esp_ble_mesh/core/mesh.h index c9392240..12784479 100644 --- a/lib/bt/esp_ble_mesh/core/mesh.h +++ b/lib/bt/esp_ble_mesh/core/mesh.h @@ -11,6 +11,7 @@ #define _MESH_H_ #include "net.h" +#include "tag.h" #ifdef __cplusplus extern "C" { diff --git a/lib/bt/esp_ble_mesh/core/net.c b/lib/bt/esp_ble_mesh/core/net.c index 2f988966..4f54c854 100644 --- a/lib/bt/esp_ble_mesh/core/net.c +++ b/lib/bt/esp_ble_mesh/core/net.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ #include "crypto.h" #include "adv.h" +#include "net.h" #include "scan.h" #include "mesh.h" #include "lpn.h" @@ -31,7 +32,9 @@ #include "proxy_server.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* Minimum valid Mesh Network PDU length. The Network headers * themselves take up 9 bytes. After that there is a minimum of 1 byte @@ -834,6 +837,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("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key, buf->len); @@ -911,18 +917,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 - 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 bt_mesh_adv_send(buf, BLE_MESH_ADV(buf)->xmit, cb, cb_data); return 0; @@ -1019,9 +1029,37 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf, return bt_mesh_net_obfuscate(buf->data, BLE_MESH_NET_IVI_TX, priv); } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static void bt_mesh_net_adv_xmit_update(struct bt_mesh_net_tx *tx) +{ + /* When transmitting a Network PDU that is tagged as friendship, + * the Advertising Bearer Network Interface shall transmit the + * Network PDU over the advertising bearer only once. + * + * Note: Currently when transmitting a packet with the friendship + * credentials used, the message flow will not reach here. It + * will be enqueued into the friend queue in transport.c, and + * waited to be sent. + */ + if (bt_mesh_tag_friendship(tx->ctx->send_tag)) { + tx->xmit = BLE_MESH_TRANSMIT(0, BLE_MESH_TRANSMIT_INT(bt_mesh_net_transmit_get())); + return; + } + + if (bt_mesh_tag_relay(tx->ctx->send_tag)) { + tx->xmit = bt_mesh_relay_retransmit_get(); + } else { + tx->xmit = bt_mesh_net_transmit_get(); + } + + return; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + 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; @@ -1086,31 +1124,48 @@ 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)) { + send_cb_finalize(send_cb, cb_data); + send_cb = NULL; - err = 0; 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()) { + 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)) { /* If Proxy Client succeeds to send messages with GATT bearer, @@ -1118,34 +1173,43 @@ 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; - err = 0; - goto done; + goto done; + } } } +#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 (cb && cb->start) { - cb->start(0, 0, cb_data); - } + /* 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 (send_cb && send_cb->start) { + send_cb->start(0, 0, cb_data); + } - net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf)); + 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(); + bt_mesh_net_local(); - err = 0; - /* If it is a group address, it still needs to be relayed */ - if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { goto done; } + + net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf)); + bt_mesh_net_local(); } if ((bearer & BLE_MESH_ADV_BEARER) && @@ -1167,7 +1231,6 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, BLE_MESH_TRANSMIT_COUNT(tx->xmit), BLE_MESH_TRANSMIT_INT(tx->xmit)); bt_mesh_adv_send(buf, tx->xmit, cb, cb_data); - err = 0; goto done; } @@ -1407,13 +1470,94 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if) case BLE_MESH_NET_IF_ADV: return (bt_mesh_relay_get() == BLE_MESH_RELAY_ENABLED); case BLE_MESH_NET_IF_PROXY: - return (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED || - bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED); + return (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED +#if CONFIG_BLE_MESH_PRB_SRV + || bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED +#endif + ); default: return false; } } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static uint8_t net_retransmission_adv(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->ctx.recv_cred == BLE_MESH_FLOODING_CRED) { + uint8_t bearer = BLE_MESH_NONE_BEARER; + + /* Inbound bearer: ADV; + * Inbound Security Material: managed flooding; + */ + + /* Condition: Relay is enabled. */ + if (IS_ENABLED(CONFIG_BLE_MESH_RELAY) && + bt_mesh_relay_get() == BLE_MESH_RELAY_ENABLED) { + bearer |= BLE_MESH_ADV_BEARER; + *cred = BLE_MESH_FLOODING_CRED; + /* Additional action: Tag as relay */ + *tag |= BLE_MESH_TAG_RELAY; + } + + /* Condition: Proxy is enabled. */ + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { + bearer |= BLE_MESH_GATT_BEARER; + *cred = BLE_MESH_FLOODING_CRED; + } + + return bearer; + } + + if (rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED && + IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + bt_mesh_friend_get() == BLE_MESH_FRIEND_ENABLED) { + + /* Condition: Directed friend is disabled. */ + *cred = BLE_MESH_FLOODING_CRED; + return BLE_MESH_ALL_BEARERS; + } + + return BLE_MESH_NONE_BEARER; +} + +static uint8_t net_retransmission_gatt(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->ctx.recv_cred == BLE_MESH_FLOODING_CRED) { + /* Inbound bearer: GATT; + * Inbound Security Material: managed flooding; + * Condition: Proxy is enabled; + */ + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { + /* Condition: Directed proxy is disabled. */ + *cred = BLE_MESH_FLOODING_CRED; + return BLE_MESH_ALL_BEARERS; + } + + return BLE_MESH_NONE_BEARER; + } + + return BLE_MESH_NONE_BEARER; +} + +static uint8_t bt_mesh_net_retrans_match(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->net_if == BLE_MESH_NET_IF_ADV) { + return net_retransmission_adv(rx, cred, tag); + } + + if (rx->net_if == BLE_MESH_NET_IF_PROXY) { + return net_retransmission_gatt(rx, cred, tag); + } + + return BLE_MESH_NONE_BEARER; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static void bt_mesh_net_relay(struct net_buf_simple *sbuf, struct bt_mesh_net_rx *rx) { @@ -1538,7 +1682,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, if (bt_mesh_get_stored_relay_count() >= BLE_MESH_MAX_STORED_RELAY_COUNT) { xmit = BLE_MESH_TRANSMIT(0, 20); } - buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_DATA, K_NO_WAIT); + buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_RELAY_DATA, K_NO_WAIT); #endif if (!buf) { @@ -1606,20 +1750,25 @@ 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 bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED || +#endif rx->net_if == BLE_MESH_NET_IF_LOCAL || 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) { + + if (((bearer & (~BLE_MESH_GATT_BEARER)) == 0) || + bt_mesh_proxy_server_find_client_by_addr(rx->ctx.recv_dst)) { goto done; } } } +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ if (((bearer & BLE_MESH_ADV_BEARER) && relay_to_adv(rx->net_if)) || netkey_changed || @@ -1769,24 +1918,26 @@ 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}; - BT_DBG("rssi %d net_if %u", rssi, net_if); + assert(rx); + + BT_DBG("rssi %d net_if %u", rx->ctx.recv_rssi, net_if); if (!ready_to_recv()) { return; } - if (bt_mesh_net_decode(data, net_if, &rx, &buf)) { + if (bt_mesh_net_decode(data, net_if, rx, &buf)) { return; } - if (ignore_net_msg(rx.ctx.addr, rx.ctx.recv_dst)) { + if (ignore_net_msg(rx->ctx.addr, rx->ctx.recv_dst)) { return; } @@ -1796,24 +1947,26 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, 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, + 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 (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 net_if == BLE_MESH_NET_IF_PROXY) { - bt_mesh_proxy_server_addr_add(data, rx.ctx.addr); + 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; } @@ -1826,11 +1979,11 @@ 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)) { + rx->ctx.recv_tag |= BLE_MESH_TAG_IMMUTABLE_CRED; } #endif /* CONFIG_BLE_MESH_DF_SRV */ } @@ -1842,24 +1995,24 @@ 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); + bt_mesh_net_relay(&buf, rx); } } diff --git a/lib/bt/esp_ble_mesh/core/net.h b/lib/bt/esp_ble_mesh/core/net.h index 7da8c4a0..94e07819 100644 --- a/lib/bt/esp_ble_mesh/core/net.h +++ b/lib/bt/esp_ble_mesh/core/net.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 */ @@ -465,8 +465,16 @@ 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 = { .ctx.recv_rssi = rssi }; + bt_mesh_generic_net_recv(data, &rx, net_if); +} bool bt_mesh_primary_subnet_exist(void); diff --git a/lib/bt/esp_ble_mesh/core/nimble_host/adapter.c b/lib/bt/esp_ble_mesh/core/nimble_host/adapter.c index 0418b76c..b2477345 100644 --- a/lib/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/lib/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-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,8 @@ #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 @@ -69,7 +71,6 @@ 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 +80,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,9 +195,16 @@ 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_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) static struct gattc_prov_info { /* Service to be found depends on the type of adv pkt received */ struct bt_mesh_conn conn; @@ -350,13 +407,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; @@ -396,13 +459,52 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, return rc; } -#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ +#endif /* (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) */ -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->data; + + 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 + +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_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) int rc, i; uint8_t notif_data[100]; uint16_t notif_len; @@ -412,21 +514,59 @@ static int disc_cb(struct ble_gap_event *event, void *arg) #endif switch (event->type) { +#if CONFIG_BLE_MESH_USE_BLE_50 + case BLE_GAP_EVENT_EXT_DISC: { + struct bt_mesh_adv_report adv_rpt = {0}; + + desc = &event->ext_disc; + + 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; + + 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 */ + if (desc->props & BLE_HCI_ADV_LEGACY_MASK) { + bt_mesh_scan_dev_found_cb(&adv_rpt); + } + } + + /* Mesh didn't process that data */ + if (adv_rpt.adv_data.len == desc->length_data) { + bt_mesh_ble_ext_adv_report(desc); + } + + break; + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ case BLE_GAP_EVENT_DISC: { - struct net_buf_simple buf = {0}; + struct bt_mesh_adv_report adv_rpt = {0}; desc = &event->disc; - net_buf_simple_init_with_data(&buf, (void *)desc->data, desc->length_data); + + 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((bt_mesh_addr_t *)&desc->addr, desc->rssi, desc->event_type, &buf, 0); + 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_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 "); @@ -442,10 +582,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; @@ -494,7 +645,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: @@ -521,6 +678,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: @@ -531,8 +690,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; @@ -557,7 +716,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); @@ -568,7 +727,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); @@ -579,14 +738,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; @@ -597,6 +795,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) { @@ -648,12 +847,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 @@ -673,11 +898,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); } @@ -693,8 +930,43 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) return 0; case BLE_GAP_EVENT_ADV_COMPLETE: - MODLOG_DFLT(INFO, "advertise complete; reason=%d", - event->adv_complete.reason); + BT_DBG("advertise complete; reason=%d", + event->adv_complete.reason); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_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) { + ble_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(); + ble_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: @@ -717,10 +989,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) { @@ -773,10 +1055,233 @@ 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 + ble_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) { + ble_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(); + ble_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 +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_HS_ADV_MAX_SZ); + 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) { + adv_params.legacy_pdu = true; + } + } + + adv_params.sid = inst_id; + adv_params.primary_phy = param->primary_phy; + adv_params.secondary_phy = param->secondary_phy; + adv_params.tx_power = 0x7F; // tx power will be selected by controller + adv_params.own_addr_type = BLE_OWN_ADDR_PUBLIC; + + 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; + + 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; + } + + 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, @@ -877,8 +1382,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_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_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) { @@ -949,8 +1602,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 @@ -967,6 +1639,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) { @@ -987,6 +1660,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; } @@ -1309,7 +1983,6 @@ int bt_mesh_gatts_service_stop(struct bt_mesh_gatt_service *svc) { int rc; uint16_t handle; - const ble_uuid_t *uuid; if (!svc) { BT_ERR("%s, Invalid parameter", __func__); @@ -1317,12 +1990,11 @@ int bt_mesh_gatts_service_stop(struct bt_mesh_gatt_service *svc) } if (BLE_MESH_UUID_16(svc->attrs[0].user_data)->val == BT_UUID_MESH_PROXY_VAL) { - uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL); + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); } else { - uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL); + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); } - rc = ble_gatts_find_svc(uuid, &handle); assert(rc == 0); ble_gatts_svc_set_visibility(handle, 0); @@ -1336,15 +2008,13 @@ int bt_mesh_gatts_service_start(struct bt_mesh_gatt_service *svc) { int rc; uint16_t handle; - const ble_uuid_t *uuid; if (BLE_MESH_UUID_16(svc->attrs[0].user_data)->val == BT_UUID_MESH_PROXY_VAL) { - uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL); + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); } else { - uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL); + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); } - rc = ble_gatts_find_svc(uuid, &handle); assert(rc == 0); ble_gatts_svc_set_visibility(handle, 1); @@ -1361,7 +2031,8 @@ int bt_mesh_gatts_set_local_device_name(const char *name) #endif /* CONFIG_BLE_MESH_NODE */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) void bt_mesh_gattc_conn_cb_register(struct bt_mesh_prov_conn_cb *cb) { bt_mesh_gattc_conn_cb = cb; @@ -1558,6 +2229,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; } @@ -1602,7 +2274,10 @@ void bt_mesh_gattc_disconnect(struct bt_mesh_conn *conn) * Mesh Proxy Data In: 0x2ADD * Mesh PROXY Data Out: 0x2ADE */ -#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + +#endif /* (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)*/ struct bt_mesh_conn *bt_mesh_conn_ref(struct bt_mesh_conn *conn) { @@ -1626,9 +2301,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)); @@ -1717,6 +2402,58 @@ 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, "func bt_mesh_gatts_svcs_add should be called before mesh init"); + + 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); @@ -1747,7 +2484,8 @@ void bt_mesh_gatt_init(void) #endif /* CONFIG_BLE_MESH_NODE */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) 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; @@ -1755,6 +2493,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) @@ -1765,7 +2504,8 @@ void bt_mesh_gatt_deinit(void) #endif #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { bt_mesh_gattc_info[i].conn.handle = 0xFFFF; memset(&bt_mesh_gattc_info[i].addr, 0, sizeof(bt_mesh_addr_t)); @@ -1985,12 +2725,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/lib/bt/esp_ble_mesh/core/prov_common.c b/lib/bt/esp_ble_mesh/core/prov_common.c index 655c4712..6f9e1dfa 100644 --- a/lib/bt/esp_ble_mesh/core/prov_common.c +++ b/lib/bt/esp_ble_mesh/core/prov_common.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 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 */ @@ -135,6 +135,9 @@ bool bt_mesh_prov_pdu_check(uint8_t type, uint16_t length, uint8_t *reason) #define CLOSE_XMIT BLE_MESH_TRANSMIT(2, 20) #define CLOSE_TIMEOUT K_MSEC(100) +#define CLOSE_RETRANS_CNT 3 +#define CLOSE_RETRANS_WITH_REASON(cnt, rsn) (((cnt) << 4) | ((rsn) & 0x0f)) +#define CLOSE_RETRANS_GET(rsn) ((rsn) >> 4) #define BUF_TIMEOUT K_MSEC(400) @@ -143,7 +146,7 @@ bool bt_mesh_prov_pdu_check(uint8_t type, uint16_t length, uint8_t *reason) static uint8_t bt_mesh_prov_buf_type_get(struct net_buf_simple *buf) { - return buf->data[PROV_BUF_HEADROOM]; + return buf->__buf[PROV_BUF_HEADROOM]; } uint8_t node_next_xact_id(struct bt_mesh_prov_link *link) @@ -359,7 +362,7 @@ static void free_segments(struct bt_mesh_prov_link *link) link->tx.buf[i] = NULL; bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); /* Mark as canceled */ - BLE_MESH_ADV(buf)->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); net_buf_unref(buf); } } @@ -457,12 +460,19 @@ static void prov_retransmit(struct k_work *work) if (link->pb_remote_close) { link->pb_remote_close(link, link->reason); } + return; } else { - if (link->reset_adv_link) { - link->reset_adv_link(link, link->reason); + uint8_t retrans_cnt = CLOSE_RETRANS_GET(link->reason); + if (!retrans_cnt) { + if (link->reset_adv_link) { + link->reset_adv_link(link, link->reason); + } + return; + } else { + retrans_cnt--; + link->reason = CLOSE_RETRANS_WITH_REASON(retrans_cnt, link->reason); } } - return; } bt_mesh_mutex_lock(&link->buf_lock); @@ -474,7 +484,7 @@ static void prov_retransmit(struct k_work *work) break; } - if (BLE_MESH_ADV(buf)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(buf))) { continue; } @@ -547,7 +557,14 @@ int bt_mesh_prov_bearer_ctl_send(struct bt_mesh_prov_link *link, uint8_t op, if (op == LINK_CLOSE) { bt_mesh_atomic_clear_bit(link->flags, LINK_ACTIVE); bt_mesh_atomic_set_bit(link->flags, LINK_CLOSING); - link->reason = *((uint8_t *)data); + /** We can also use buf->ref and a flag to decide that + * link close has been sent 3 times. + * Here we use another way: use retransmit timer and need + * to make sure the timer is not cancelled during sending + * link close pdu, Therefore, use the higher four bits + * of reason as a retransmit count. + */ + link->reason = CLOSE_RETRANS_WITH_REASON(CLOSE_RETRANS_CNT, (*((uint8_t *)data))); } return 0; diff --git a/lib/bt/esp_ble_mesh/core/prov_common.h b/lib/bt/esp_ble_mesh/core/prov_common.h index 561712ef..d2a8771b 100644 --- a/lib/bt/esp_ble_mesh/core/prov_common.h +++ b/lib/bt/esp_ble_mesh/core/prov_common.h @@ -17,7 +17,9 @@ #include "mesh/timer.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/lib/bt/esp_ble_mesh/core/prov_node.c b/lib/bt/esp_ble_mesh/core/prov_node.c index 4871a1cb..cf789470 100644 --- a/lib/bt/esp_ble_mesh/core/prov_node.c +++ b/lib/bt/esp_ble_mesh/core/prov_node.c @@ -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 */ @@ -22,7 +22,9 @@ #include "prov_common.h" #include "prov_node.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_NODE @@ -80,12 +82,12 @@ static void reset_state(void) } #endif /* CONFIG_BLE_MESH_PB_GATT */ -#if CONFIG_BLE_MESH_PB_ADV /* Clear everything except the retransmit and protocol timer * delayed work objects. */ (void)memset(&prov_link, 0, offsetof(struct bt_mesh_prov_link, tx.retransmit)); +#if CONFIG_BLE_MESH_PB_ADV prov_link.pending_ack = PROV_XACT_NVAL; prov_link.rx.prev_id = PROV_XACT_NVAL; @@ -152,7 +154,7 @@ static int prov_send_gatt(struct bt_mesh_prov_link *link, struct net_buf_simple /* Changed by Espressif, add provisioning timeout timer operations. * When sending a provisioning PDU successfully, restart the 60s timer. */ -#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT && CONFIG_BLE_MESH_RPR_SRV +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE)) { err = bt_mesh_proxy_client_send(link->conn, BLE_MESH_PROXY_PROV, msg); @@ -1073,10 +1075,19 @@ static void link_ack(struct prov_rx *rx, struct net_buf_simple *buf) bt_mesh_prov_clear_tx(&prov_link, true); bt_mesh_rpr_srv_recv_link_ack(prov_link.pb_remote_uuid, true); } else { - BT_INFO("Link ACK for PB-Remote already received"); + BT_DBG("Link ACK for PB-Remote already received"); + return; } } #endif /* CONFIG_BLE_MESH_RPR_SRV */ + + if (!k_delayed_work_remaining_get(&prov_link.prot_timer)) { + /** + * When the link is opened, the provisioner and the unprovisioned device + * shall start the link timer with the timeout value set to 60 seconds. + */ + k_delayed_work_submit(&prov_link.prot_timer, PROTOCOL_TIMEOUT); + } } static void link_close(struct prov_rx *rx, struct net_buf_simple *buf) @@ -1432,6 +1443,11 @@ int bt_mesh_pb_gatt_open(struct bt_mesh_conn *conn) { BT_DBG("conn %p", conn); + /** + * It's necessary to determine if it is PB_REMOTE because when the + * node acts as an RPR server, LINK_ACTIVE has already been set upon + * receiving the link open from the RPR client. + */ if (!bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE) && bt_mesh_atomic_test_and_set_bit(prov_link.flags, LINK_ACTIVE)) { BT_ERR("Link is busy"); @@ -1449,6 +1465,14 @@ int bt_mesh_pb_gatt_open(struct bt_mesh_conn *conn) prov_link.expect = PROV_INVITE; } + /** + * Just like ADV Link, start provision timeout timer after + * establishing the link to prevent the RPR server from + * being unable to recover to a configurable network state + * during remote provisioning. + */ + k_delayed_work_submit(&prov_link.prot_timer, PROTOCOL_TIMEOUT); + if (bt_mesh_prov_get()->link_open) { bt_mesh_prov_get()->link_open(BLE_MESH_PROV_GATT); } @@ -1469,6 +1493,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 @@ -1494,7 +1521,7 @@ static void protocol_timeout(struct k_work *work) #if CONFIG_BLE_MESH_PB_GATT if (prov_link.conn) { -#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT && CONFIG_BLE_MESH_RPR_SRV +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) { prov_link.pb_remote_reset = true; bt_mesh_gattc_disconnect(prov_link.conn); diff --git a/lib/bt/esp_ble_mesh/core/prov_pvnr.c b/lib/bt/esp_ble_mesh/core/prov_pvnr.c index e2e0fe58..091e3e86 100644 --- a/lib/bt/esp_ble_mesh/core/prov_pvnr.c +++ b/lib/bt/esp_ble_mesh/core/prov_pvnr.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 */ @@ -22,7 +22,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_PROVISIONER @@ -45,6 +47,10 @@ _Static_assert(BLE_MESH_MAX_CONN >= CONFIG_BLE_MESH_PBG_SAME_TIME, */ static struct bt_mesh_prov_link prov_links[BLE_MESH_PROV_SAME_TIME]; +#if CONFIG_BLE_MESH_RPR_CLI +extern struct bt_mesh_prov_link rpr_links[CONFIG_BLE_MESH_RPR_CLI_PROV_SAME_TIME]; +#endif + struct bt_mesh_prov_ctx { /* Primary element address of Provisioner */ uint16_t primary_addr; @@ -242,7 +248,7 @@ void bt_mesh_provisioner_restore_prov_info(uint16_t primary_addr, uint16_t alloc } #endif /* CONFIG_BLE_MESH_SETTINGS */ -static bool is_unprov_dev_being_provision(const uint8_t uuid[16]) +bool bt_mesh_is_unprov_dev_being_prov(const uint8_t uuid[16]) { int i; @@ -259,6 +265,15 @@ static bool is_unprov_dev_being_provision(const uint8_t uuid[16]) } #endif /* CONFIG_BLE_MESH_FAST_PROV */ +#if CONFIG_BLE_MESH_RPR_CLI + for (i = 0; i < CONFIG_BLE_MESH_RPR_CLI_PROV_SAME_TIME;i++) { + if (!memcmp(rpr_links[i].pb_remote_uuid, uuid, 16)) { + BT_WARN("Device is being provisioning by Remote Provisioning"); + return true; + } + } +#endif + for (i = 0; i < BLE_MESH_PROV_SAME_TIME; i++) { if (bt_mesh_atomic_test_bit(prov_links[i].flags, LINK_ACTIVE) #if CONFIG_BLE_MESH_PB_GATT @@ -309,7 +324,7 @@ static int provisioner_check_unprov_dev_info(const uint8_t uuid[16], bt_mesh_pro * receive the connectable prov adv pkt from this device. * Here we check both PB-GATT and PB-ADV link status. */ - if (is_unprov_dev_being_provision(uuid)) { + if (bt_mesh_is_unprov_dev_being_prov(uuid)) { return -EALREADY; } @@ -364,7 +379,7 @@ static int provisioner_start_prov_pb_adv(const uint8_t uuid[16], const bt_mesh_a return -EIO; } - if (is_unprov_dev_being_provision(uuid)) { + if (bt_mesh_is_unprov_dev_being_prov(uuid)) { bt_mesh_pb_adv_unlock(); return 0; } @@ -426,7 +441,7 @@ static int provisioner_start_prov_pb_gatt(const uint8_t uuid[16], const bt_mesh_ return -EIO; } - if (is_unprov_dev_being_provision(uuid)) { + if (bt_mesh_is_unprov_dev_being_prov(uuid)) { bt_mesh_pb_gatt_unlock(); return 0; } @@ -1413,7 +1428,7 @@ static int prov_auth(struct bt_mesh_prov_link *link, return -EINVAL; } - /* Provisioner ouput number/string and wait for device's Provisioning Input Complete PDU */ + /* Provisioner output number/string and wait for device's Provisioning Input Complete PDU */ link->expect = PROV_INPUT_COMPLETE; /* NOTE: The Bluetooth SIG recommends that mesh implementations enforce a randomly @@ -1957,6 +1972,7 @@ static void send_prov_data(struct bt_mesh_prov_link *link) uint8_t session_key[16] = {0}; uint8_t nonce[13] = {0}; uint8_t pdu[25] = {0}; + uint8_t *dev_uuid = NULL; PROV_BUF(buf, 34); int err = 0; @@ -2012,7 +2028,13 @@ static void send_prov_data(struct bt_mesh_prov_link *link) */ /* Check if this device is a re-provisioned device */ - node = bt_mesh_provisioner_get_node_with_uuid(link->uuid); + if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE)) { + dev_uuid = link->pb_remote_uuid; + } else { + dev_uuid = link->uuid; + } + + node = bt_mesh_provisioner_get_node_with_uuid(dev_uuid); if (node) { if (link->element_num <= node->element_num && link->pb_remote_nppi != NPPI_NODE_ADDR_REFRESH) { @@ -2027,7 +2049,7 @@ static void send_prov_data(struct bt_mesh_prov_link *link) */ if (!bt_mesh_atomic_test_bit(link->flags, PB_REMOTE) || link->pb_remote_nppi == NPPI_UNKNOWN) { - bt_mesh_provisioner_remove_node(link->uuid); + bt_mesh_provisioner_remove_node(dev_uuid); } } @@ -2211,6 +2233,7 @@ static void prov_complete(struct bt_mesh_prov_link *link, uint16_t net_idx = 0U; uint16_t index = 0U; bool nppi = false; + uint8_t *dev_uuid = NULL; int err = 0; int i; @@ -2227,12 +2250,16 @@ static void prov_complete(struct bt_mesh_prov_link *link, net_idx = prov_ctx.net_idx; } - if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE) && - link->pb_remote_nppi != NPPI_UNKNOWN) { - nppi = true; + if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE)) { + if (link->pb_remote_nppi != NPPI_UNKNOWN) { + nppi = true; + } + dev_uuid = link->pb_remote_uuid; + } else { + dev_uuid = link->uuid; } - err = bt_mesh_provisioner_provision(&link->addr, link->uuid, link->oob_info, + err = bt_mesh_provisioner_provision(&link->addr, dev_uuid, link->oob_info, link->unicast_addr, link->element_num, net_idx, link->kri_flags, bt_mesh.iv_index, device_key, &index, nppi); @@ -2264,13 +2291,13 @@ static void prov_complete(struct bt_mesh_prov_link *link, #endif /* CONFIG_BLE_MESH_RPR_CLI */ if (bt_mesh_prov_get()->prov_complete) { - bt_mesh_prov_get()->prov_complete(index, link->uuid, link->unicast_addr, + bt_mesh_prov_get()->prov_complete(index, dev_uuid, link->unicast_addr, link->element_num, net_idx); } /* Find if the device is in the device queue */ for (i = 0; i < ARRAY_SIZE(unprov_dev); i++) { - if (!memcmp(unprov_dev[i].uuid, link->uuid, 16) && + if (!memcmp(unprov_dev[i].uuid, dev_uuid, 16) && (unprov_dev[i].flags & RM_AFTER_PROV)) { memset(&unprov_dev[i], 0, sizeof(struct unprov_dev_queue)); break; diff --git a/lib/bt/esp_ble_mesh/core/prov_pvnr.h b/lib/bt/esp_ble_mesh/core/prov_pvnr.h index 0553a72d..b3eb5048 100644 --- a/lib/bt/esp_ble_mesh/core/prov_pvnr.h +++ b/lib/bt/esp_ble_mesh/core/prov_pvnr.h @@ -379,6 +379,8 @@ uint16_t bt_mesh_provisioner_get_fast_prov_net_idx(void); */ uint8_t bt_mesh_set_fast_prov_unicast_addr_range(uint16_t min, uint16_t max); +bool bt_mesh_is_unprov_dev_being_prov(const uint8_t uuid[16]); + int bt_mesh_rpr_cli_pdu_recv(struct bt_mesh_prov_link *link, uint8_t type, struct net_buf_simple *buf); diff --git a/lib/bt/esp_ble_mesh/core/proxy_client.c b/lib/bt/esp_ble_mesh/core/proxy_client.c index 9382cf61..ac05f92f 100644 --- a/lib/bt/esp_ble_mesh/core/proxy_client.c +++ b/lib/bt/esp_ble_mesh/core/proxy_client.c @@ -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 */ @@ -21,14 +21,17 @@ #include "pvnr_mgmt.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) static struct bt_mesh_proxy_server { struct bt_mesh_conn *conn; - + bt_mesh_addr_t addr; enum __attribute__((packed)) { CLI_NONE, CLI_PROV, @@ -83,6 +86,22 @@ static void proxy_sar_timeout(struct k_work *work) bt_mesh_gattc_disconnect(server->conn); } +#if (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) +int bt_mesh_rpr_srv_set_waiting_prov_link(struct bt_mesh_prov_link *link, + bt_mesh_addr_t *addr) +{ + for (size_t i = 0; i < ARRAY_SIZE(waiting_conn_link);i++) { + if (waiting_conn_link[i].link == NULL) { + waiting_conn_link[i].link = link; + memcpy(&waiting_conn_link[i].addr, addr, sizeof(bt_mesh_addr_t)); + return 0; + } + } + + return -ENOBUFS; +} +#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT */ + #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT /** * The following callbacks are used to notify proper information @@ -113,22 +132,6 @@ void bt_mesh_proxy_client_set_filter_status_cb(proxy_client_recv_filter_status_c proxy_client_filter_status_recv_cb = cb; } -#if (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) -int bt_mesh_rpr_srv_set_waiting_prov_link(struct bt_mesh_prov_link *link, - bt_mesh_addr_t *addr) -{ - for (size_t i = 0; i < ARRAY_SIZE(waiting_conn_link);i++) { - if (waiting_conn_link[i].link == NULL) { - waiting_conn_link[i].link = link; - memcpy(&waiting_conn_link[i].addr, addr, sizeof(bt_mesh_addr_t)); - return 0; - } - } - - return -ENOBUFS; -} -#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT */ - static void filter_status(struct bt_mesh_proxy_server *server, struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) @@ -264,7 +267,9 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_server *server) } else #endif { +#if CONFIG_BLE_MESH_PROVISIONER bt_mesh_provisioner_pb_gatt_recv(server->conn, &server->buf); +#endif } break; #endif @@ -460,6 +465,7 @@ static void proxy_connected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, int server->conn = bt_mesh_conn_ref(conn); server->conn_type = CLI_NONE; + memcpy(&server->addr, addr, sizeof(bt_mesh_addr_t)); net_buf_simple_reset(&server->buf); #if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT @@ -492,6 +498,7 @@ static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, if (bt_mesh_prov_node_get_link()->conn == conn) { for (size_t i = 0; i < ARRAY_SIZE(waiting_conn_link); i++) { if (waiting_conn_link[i].link->conn == conn) { + waiting_conn_link[i].link = NULL; memset(&waiting_conn_link[i].addr, 0, sizeof(bt_mesh_addr_t)); break; } @@ -501,7 +508,9 @@ static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, } else #endif /* CONFIG_BLE_MESH_RPR_SRV */ { +#if CONFIG_BLE_MESH_PROVISIONER bt_mesh_provisioner_pb_gatt_close(conn, reason); +#endif /* CONFIG_BLE_MESH_PROVISIONER */ } } #endif /* CONFIG_BLE_MESH_PB_GATT && (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) */ @@ -548,7 +557,9 @@ static ssize_t prov_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) } #endif +#if CONFIG_BLE_MESH_PROVISIONER return bt_mesh_provisioner_pb_gatt_open(conn, addr->val); +#endif } return -ENOMEM; @@ -619,6 +630,12 @@ static ssize_t proxy_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) return 0; } +#if CONFIG_BLE_MESH_BQB_TEST + /* notify maybe received first */ + if (server->conn_type == CLI_PROXY) { + return 0; + } +#endif return -EINVAL; } @@ -631,6 +648,16 @@ static ssize_t proxy_recv_ntf(struct bt_mesh_conn *conn, uint8_t *data, uint16_t return -ENOTCONN; } +#if CONFIG_BLE_MESH_BQB_TEST + /* update conn type if notify received before write ccc */ + if (server->conn_type == CLI_NONE) { + server->conn_type = CLI_PROXY; + if (proxy_client_connect_cb) { + proxy_client_connect_cb(&server->addr, server - servers, server->net_idx); + } + } +#endif + if (server->conn_type == CLI_PROXY) { return proxy_recv(conn, NULL, data, len, 0, 0); } @@ -692,10 +719,12 @@ int bt_mesh_proxy_client_gatt_disable(void) static struct bt_mesh_prov_conn_cb conn_callbacks = { .connected = proxy_connected, .disconnected = proxy_disconnected, -#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT +#if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) && \ + CONFIG_BLE_MESH_PB_GATT .prov_write_descr = prov_write_ccc, .prov_notify = prov_recv_ntf, -#endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */ +#endif /* (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) && \ + CONFIG_BLE_MESH_PB_GATT */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT .proxy_write_descr = proxy_write_ccc, .proxy_notify = proxy_recv_ntf, @@ -818,6 +847,23 @@ 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++; + } + + return count; +} + bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst) { bool send = false; @@ -1123,4 +1169,5 @@ int bt_mesh_proxy_client_deinit(void) #endif /* CONFIG_BLE_MESH_DEINIT */ #endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) */ diff --git a/lib/bt/esp_ble_mesh/core/proxy_client.h b/lib/bt/esp_ble_mesh/core/proxy_client.h index d2d85017..6bc0732d 100644 --- a/lib/bt/esp_ble_mesh/core/proxy_client.h +++ b/lib/bt/esp_ble_mesh/core/proxy_client.h @@ -11,7 +11,9 @@ #include "mesh/adapter.h" #include "prov_common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef __cplusplus extern "C" { @@ -102,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/lib/bt/esp_ble_mesh/core/proxy_server.c b/lib/bt/esp_ble_mesh/core/proxy_server.c index 020793dc..e8069155 100644 --- a/lib/bt/esp_ble_mesh/core/proxy_server.c +++ b/lib/bt/esp_ble_mesh/core/proxy_server.c @@ -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 */ @@ -22,17 +22,23 @@ #include "prov_common.h" #include "prov_node.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #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_INS_UNUSED; +#endif + #define ADV_OPT (BLE_MESH_ADV_OPT_CONNECTABLE | BLE_MESH_ADV_OPT_ONE_TIME) #if CONFIG_BLE_MESH_GATT_PROXY_SERVER && \ @@ -50,12 +56,24 @@ 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, +#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, +#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, +#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, +#endif }; static bool proxy_adv_enabled; @@ -152,6 +170,11 @@ 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) +{ + proxy_adv_enabled = enable; +} + #if CONFIG_BLE_MESH_GATT_PROXY_SERVER /** * The following callbacks are used to notify proper information @@ -826,10 +849,18 @@ static void proxy_connected(struct bt_mesh_conn *conn, uint8_t err) BT_DBG("conn %p err 0x%02x", conn, err); + if (gatt_svc == MESH_GATT_PROV && conn_count == 1) { + BT_WARN("Only one prov connection could exists"); + bt_mesh_gatts_disconnect(conn, 0x13); + return; + } + 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 #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX /* Before re-enabling advertising, stop advertising @@ -1019,7 +1050,6 @@ int bt_mesh_proxy_server_prov_enable(void) } } - return 0; } @@ -1333,7 +1363,7 @@ int bt_mesh_proxy_server_segment_send(struct bt_mesh_conn *conn, uint8_t type, net_buf_simple_pull(msg, mtu); while (msg->len) { - if (msg->len + 1 < mtu) { + if (msg->len + 1 <= mtu) { net_buf_simple_push_u8(msg, BLE_MESH_PROXY_PDU_HDR(BLE_MESH_PROXY_SAR_LAST, type)); proxy_send(conn, msg->data, msg->len); break; @@ -1463,14 +1493,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 + err = bt_le_adv_start(&fast_adv_param, node_id_ad, + ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); +#endif 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; } @@ -1489,14 +1524,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 + err = bt_le_adv_start(&slow_adv_param, net_id_ad, + ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); +#endif 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; } @@ -1559,7 +1599,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; } @@ -1603,7 +1643,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; } @@ -1715,6 +1755,7 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) && sub->private_node_id == BLE_MESH_PRIVATE_NODE_IDENTITY_STOPPED #endif ) { + /* advertising node identity forever */ if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { net_id_adv(sub); } @@ -1830,17 +1871,25 @@ static int32_t solic_adv_private_net_id(void) int32_t bt_mesh_proxy_server_adv_start(void) { + BT_DBG("proxy server start"); + if (gatt_svc == MESH_GATT_NONE) { return K_FOREVER; } +#if CONFIG_BLE_MESH_USE_BLE_50 + if (proxy_adv_inst == BLE_MESH_ADV_INS_UNUSED) { + return K_FOREVER; + } +#endif + #if CONFIG_BLE_MESH_PB_GATT if (prov_fast_adv) { prov_start_time = k_uptime_get_32(); } 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; @@ -1852,9 +1901,15 @@ 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) { @@ -1884,25 +1939,35 @@ 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("adv_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_INS_UNUSED) { + BT_ERR("Proxy adv inst is not initialized!"); + return -EINVAL; + } + + err = bt_le_ext_adv_stop(proxy_adv_inst); +#else err = bt_le_adv_stop(); +#endif 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 = { @@ -1914,6 +1979,14 @@ int bt_mesh_proxy_server_init(void) { int i; +#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 +#endif + #if CONFIG_BLE_MESH_GATT_PROXY_SERVER bt_mesh_gatts_service_register(&proxy_svc); #endif @@ -1952,7 +2025,11 @@ int bt_mesh_proxy_server_deinit(void) { int i; - proxy_adv_enabled = false; +#if CONFIG_BLE_MESH_USE_BLE_50 + proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; +#endif + + bt_mesh_proxy_server_adv_flag_set(false); gatt_svc = MESH_GATT_NONE; #if CONFIG_BLE_MESH_GATT_PROXY_SERVER diff --git a/lib/bt/esp_ble_mesh/core/proxy_server.h b/lib/bt/esp_ble_mesh/core/proxy_server.h index b9872891..fc4041f8 100644 --- a/lib/bt/esp_ble_mesh/core/proxy_server.h +++ b/lib/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/lib/bt/esp_ble_mesh/core/pvnr_mgmt.c b/lib/bt/esp_ble_mesh/core/pvnr_mgmt.c index 2531a2d2..96ad2feb 100644 --- a/lib/bt/esp_ble_mesh/core/pvnr_mgmt.c +++ b/lib/bt/esp_ble_mesh/core/pvnr_mgmt.c @@ -22,7 +22,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_PROVISIONER diff --git a/lib/bt/esp_ble_mesh/core/scan.c b/lib/bt/esp_ble_mesh/core/scan.c index e1b43dd2..192f63f8 100644 --- a/lib/bt/esp_ble_mesh/core/scan.c +++ b/lib/bt/esp_ble_mesh/core/scan.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,7 +27,9 @@ #include "prov_pvnr.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* Scan Window and Interval are equal for continuous scanning */ #define SCAN_INTERVAL 0x20 @@ -39,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 + .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, +}; + #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; @@ -84,13 +102,14 @@ int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6], { uint8_t idx = 0; uint8_t cnt = 0; + uint8_t pair_num = unprov_dev_info_fifo.pair_num; - if (uuid == NULL || addr == NULL) { + if (uuid == NULL && addr == NULL) { BT_WARN("No available information to query"); return -1; } - while (cnt < unprov_dev_info_fifo.pair_num) { + while (cnt < pair_num) { idx = (cnt + unprov_dev_info_fifo.start_idx) % BLE_MESH_STORE_UNPROV_INFO_MAX_NUM; if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_UUID) { if (!memcmp(unprov_dev_info_fifo.info[idx].addr, addr, 6)) { @@ -116,8 +135,7 @@ int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6], cnt++; } - if (cnt == unprov_dev_info_fifo.pair_num) { - BT_WARN("Didn't find info for %d", query_type); + if (cnt == pair_num) { return -1; } @@ -134,6 +152,11 @@ int bt_mesh_unprov_dev_fifo_enqueue(uint8_t uuid[16], const uint8_t addr[6], uin return -EINVAL; } + if (!bt_mesh_unprov_dev_info_query(uuid, NULL, NULL, BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_ADDR | + BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS)) { + return 0; + } + if (unprov_dev_info_fifo.pair_num == BLE_MESH_STORE_UNPROV_INFO_MAX_NUM) { bt_mesh_unprov_dev_fifo_dequeue(NULL, NULL); } @@ -164,7 +187,8 @@ uint8_t bt_mesh_get_adv_type(void) #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) static bool adv_flags_valid(struct net_buf_simple *buf) { uint8_t flags = 0U; @@ -251,8 +275,10 @@ static void handle_adv_service_data(struct net_buf_simple *buf, } switch (type) { -#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT +#if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) && \ + CONFIG_BLE_MESH_PB_GATT case BLE_MESH_UUID_MESH_PROV_VAL: +#if CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { if (buf->len != PROV_SVC_DATA_LEN) { BT_WARN("Invalid Mesh Prov Service Data length %d", buf->len); @@ -262,15 +288,19 @@ static void handle_adv_service_data(struct net_buf_simple *buf, BT_DBG("Start to handle Mesh Prov Service Data"); bt_mesh_provisioner_prov_adv_recv(buf, addr, rssi); } +#endif /* CONFIG_BLE_MESH_PROVISIONER */ - if (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && - bt_mesh_is_provisioned()) { +#if CONFIG_BLE_MESH_RPR_SRV + if (bt_mesh_is_provisioned()) { const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr(); bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type()); bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi); } +#endif /* CONFIG_BLE_MESH_RPR_SRV */ +#endif /* (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) && + CONFIG_BLE_MESH_PB_GATT */ break; -#endif + #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT case BLE_MESH_UUID_MESH_PROXY_VAL: if (buf->len != PROXY_SVC_DATA_LEN_NET_ID && @@ -303,8 +333,9 @@ static void handle_adv_service_data(struct net_buf_simple *buf, } } #endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX */ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) */ #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN static bool ble_scan_en; @@ -333,13 +364,27 @@ int bt_mesh_stop_ble_scan(void) return 0; } +bool bt_mesh_ble_scan_state_get(void) +{ + 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) { - bt_mesh_ble_scan_cb_evt_to_btc(addr, adv_type, data, length, rssi); + 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 = data; + adv_rpt.rssi = rssi; + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); } +#endif } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ @@ -361,14 +406,15 @@ 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_state buf_state = {0}; + struct net_buf_simple *buf = &adv_rpt->adv_data; + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) uint16_t uuid = 0U; #endif #if (CONFIG_BLE_MESH_RPR_SRV || CONFIG_BLE_MESH_SUPPORT_BLE_SCAN) @@ -376,19 +422,43 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, uint16_t adv_len = buf->len; #endif - if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) { + net_buf_simple_save(buf, &buf_state); + + if (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND && + adv_rpt->adv_type != BLE_MESH_ADV_IND +#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN + && adv_rpt->adv_type != BLE_MESH_ADV_SCAN_RSP +#endif + ) { #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } BT_DBG("scan, 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; + unprov_dev_addr = &adv_rpt->addr; + current_adv_type = adv_rpt->adv_type; +#endif + +#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; + } else { +#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 + 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; @@ -398,16 +468,18 @@ 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); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } if (len > buf->len) { BT_DBG("AD malformed"); #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } @@ -418,14 +490,17 @@ 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); + type == BLE_MESH_DATA_MESH_BEACON) && (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND)) { + BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 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, + }; + bt_mesh_generic_net_recv(buf, &rx, BLE_MESH_NET_IF_ADV); break; #if CONFIG_BLE_MESH_PB_ADV case BLE_MESH_DATA_MESH_PROV: @@ -438,17 +513,19 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, break; #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) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) case BLE_MESH_DATA_FLAGS: if (!adv_flags_valid(buf)) { 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); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } break; @@ -456,7 +533,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, if (!adv_service_uuid_valid(buf, &uuid)) { 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. */ @@ -464,18 +541,19 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, } #endif #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + 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 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. */ @@ -483,44 +561,21 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, } #endif #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + 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, - }; - err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb); if (err && err != -EALREADY) { BT_ERR("starting scan failed (err %d)", err); @@ -543,6 +598,49 @@ 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) { + return -EINVAL; + } + + 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("Failed to stop scan (err %d)", err); + return err; + } + + /** + * Since the user only needs to set the scan interval + * and scan window parameters, 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("Failed to start scan (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/lib/bt/esp_ble_mesh/core/scan.h b/lib/bt/esp_ble_mesh/core/scan.h index b7d0555c..612751d3 100644 --- a/lib/bt/esp_ble_mesh/core/scan.h +++ b/lib/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/lib/bt/esp_ble_mesh/core/storage/settings.c b/lib/bt/esp_ble_mesh/core/storage/settings.c index 34a40d2d..40cf117f 100644 --- a/lib/bt/esp_ble_mesh/core/storage/settings.c +++ b/lib/bt/esp_ble_mesh/core/storage/settings.c @@ -22,7 +22,9 @@ #include "pvnr_mgmt.h" #include "prov_pvnr.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* BLE Mesh NVS Key and corresponding data struct. * Note: The length of nvs key must be <= 15. @@ -1481,6 +1483,8 @@ int settings_core_commit(void) struct bt_mesh_hb_pub *hb_pub = NULL; struct bt_mesh_cfg_srv *cfg = NULL; + bt_mesh_atomic_set_bit(bt_mesh.flags, BLE_MESH_VALID); + hb_pub = bt_mesh_hb_pub_get(); if (hb_pub && hb_pub->dst != BLE_MESH_ADDR_UNASSIGNED && hb_pub->count && hb_pub->period) { @@ -1499,7 +1503,6 @@ int settings_core_commit(void) cfg->default_ttl = stored_cfg.cfg.default_ttl; } - bt_mesh_atomic_set_bit(bt_mesh.flags, BLE_MESH_VALID); bt_mesh_net_start(); } #endif /* CONFIG_BLE_MESH_NODE */ diff --git a/lib/bt/esp_ble_mesh/core/tag.h b/lib/bt/esp_ble_mesh/core/tag.h new file mode 100644 index 00000000..d1b98310 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/tag.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_v11_TAG_H_ +#define _BLE_MESH_v11_TAG_H_ + +#include +#include + +#include "mesh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !CONFIG_BLE_MESH_V11_SUPPORT + +/* TAG - additional metadata */ +#define BLE_MESH_TAG_SEND_SEGMENTED BIT(0) +#define BLE_MESH_TAG_IMMUTABLE_CRED BIT(1) +#define BLE_MESH_TAG_RELAY BIT(3) +#define BLE_MESH_TAG_FRIENDSHIP BIT(4) + +static inline bool bt_mesh_tag_send_segmented(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_SEND_SEGMENTED); +} + +static inline bool bt_mesh_tag_immutable_cred(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_IMMUTABLE_CRED); +} + +static inline bool bt_mesh_tag_relay(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_RELAY); +} + +static inline bool bt_mesh_tag_friendship(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_FRIENDSHIP); +} + +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_v11_TAG_H_ */ diff --git a/lib/bt/esp_ble_mesh/core/transport.c b/lib/bt/esp_ble_mesh/core/transport.c index 64ac566a..fd3fd60a 100644 --- a/lib/bt/esp_ble_mesh/core/transport.c +++ b/lib/bt/esp_ble_mesh/core/transport.c @@ -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 */ @@ -11,6 +11,7 @@ #include #include "crypto.h" +#include "tag.h" #include "adv.h" #include "mesh.h" #include "lpn.h" @@ -26,7 +27,9 @@ #include "mesh/cfg_srv.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* The transport layer needs at least three buffers for itself to avoid * deadlocks. Ensure that there are a sufficient number of advertising @@ -310,7 +313,15 @@ static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) { bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 3U, BLE_MESH_BUF_REF_SMALL); - BLE_MESH_ADV(tx->seg[seg_idx])->busy = 0U; + /** + * When cancelling a segment that is still in the adv sending queue, `tx->seg_pending` + * must else be decremented by one. More detailed information + * can be found in BLEMESH24-26. + */ + if (bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(tx->seg[seg_idx]), 1, 0)) { + tx->seg_pending--; + } + net_buf_unref(tx->seg[seg_idx]); tx->seg[seg_idx] = NULL; tx->nack_count--; @@ -369,6 +380,20 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err) static void schedule_retransmit(struct seg_tx *tx) { + /* It's possible that a segment broadcast hasn't finished, + * but the tx are already released. Only the seg_pending + * of this segment remains unprocessed. So, here, we + * determine if the tx are released by checking if the + * destination (dst) is unassigned, and then process + * the seg_pending of this segment. + * See BLEMESH25-92 for details */ + if (tx->dst == BLE_MESH_ADDR_UNASSIGNED) { + if (tx->seg_pending) { + tx->seg_pending--; + } + return; + } + if (--tx->seg_pending) { return; } @@ -443,7 +468,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx) continue; } - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { BT_DBG("Skipping segment that's still advertising"); continue; } @@ -493,7 +518,15 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, net_tx->aszmic, sdu->len); for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) { - if (!seg_tx[i].nack_count) { + if (!seg_tx[i].nack_count && + /* In some critical conditions, the tx might be + * reset before a segment broadcast is finished. + * If this happens, the seg_pending of the segment + * hasn't been processed. To avoid assigning this + * uncleared tx to a new message, extra checks for + * seg_pending being 0 are added. See BLEMESH25-92 + * for details.*/ + !seg_tx[i].seg_pending) { tx = &seg_tx[i]; break; } @@ -1031,18 +1064,18 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, return 0; } - if (IS_ENABLED(CONFIG_BLE_MESH_DF_SRV)) { - switch (ctl_op) { - case TRANS_CTL_OP_PATH_REQ: - case TRANS_CTL_OP_PATH_REPLY: - case TRANS_CTL_OP_PATH_CFM: - case TRANS_CTL_OP_PATH_ECHO_REQ: - case TRANS_CTL_OP_PATH_ECHO_REPLY: - case TRANS_CTL_OP_DEP_NODE_UPDATE: - case TRANS_CTL_OP_PATH_REQ_SOLIC: - return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); - } +#if CONFIG_BLE_MESH_DF_SRV + switch (ctl_op) { + case TRANS_CTL_OP_PATH_REQ: + case TRANS_CTL_OP_PATH_REPLY: + case TRANS_CTL_OP_PATH_CFM: + case TRANS_CTL_OP_PATH_ECHO_REQ: + case TRANS_CTL_OP_PATH_ECHO_REPLY: + case TRANS_CTL_OP_DEP_NODE_UPDATE: + case TRANS_CTL_OP_PATH_REQ_SOLIC: + return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); } +#endif if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { switch (ctl_op) { @@ -1528,7 +1561,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, * eventually be freed up and we'll be able to process * this one. */ - BT_WARN("No free slots for new incoming segmented messages"); + BT_WARN("No free slots for new incoming segmented messages, src: %04x", net_rx->ctx.addr); return -ENOMEM; } @@ -1751,8 +1784,6 @@ void bt_mesh_trans_init(void) { int i; - bt_mesh_sar_init(); - for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { k_delayed_work_init(&seg_tx[i].rtx_timer, seg_retransmit); } diff --git a/lib/bt/esp_ble_mesh/core/transport.enh.c b/lib/bt/esp_ble_mesh/core/transport.enh.c index 6ef6c0a5..a4a5130e 100644 --- a/lib/bt/esp_ble_mesh/core/transport.enh.c +++ b/lib/bt/esp_ble_mesh/core/transport.enh.c @@ -350,7 +350,7 @@ static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) */ bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 4U, BLE_MESH_BUF_REF_SMALL); - BLE_MESH_ADV(tx->seg[seg_idx])->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->seg[seg_idx]), 0); net_buf_unref(tx->seg[seg_idx]); tx->seg[seg_idx] = NULL; @@ -498,7 +498,7 @@ static bool send_next_segment(struct seg_tx *tx, int *result) /* The segment may have already been transmitted, for example, the * Segment Retransmission timer is expired earlier. */ - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { return false; } @@ -768,7 +768,7 @@ static bool resend_unacked_seg(struct seg_tx *tx, int *result) * A is still going to be retransmitted, but at this moment we could * find that the "busy" flag of Segment A is 1. */ - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { return false; } diff --git a/lib/bt/esp_ble_mesh/lib/ext.c b/lib/bt/esp_ble_mesh/lib/ext.c index ca779960..d9803b83 100644 --- a/lib/bt/esp_ble_mesh/lib/ext.c +++ b/lib/bt/esp_ble_mesh/lib/ext.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,8 @@ #include #include +#include "esp_log.h" + #if CONFIG_BT_BLUEDROID_ENABLED #include "bta/bta_api.h" #endif @@ -79,6 +81,25 @@ #define RPL(a) ((struct bt_mesh_rpl *)(a)) #define VOID(a) ((void *)(a)) +/* Declare Lib Variables */ +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_FRIEND; +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +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_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 */ void bt_mesh_ext_put_be16(uint16_t val, uint8_t dst[2]) { @@ -190,6 +211,11 @@ void bt_mesh_ext_mem_swap(void *buf, size_t length) sys_mem_swap(buf, length); } +uint32_t bt_mesh_ext_log_timestamp(void) +{ + return esp_log_timestamp(); +} + /* Net buf */ void bt_mesh_ext_buf_simple_init(struct net_buf_simple *buf, size_t reserve_head) { @@ -498,6 +524,11 @@ float bt_mesh_ext_log2(float num) return bt_mesh_log2(num); } +const char *bt_mesh_ext_hex(const void *buf, size_t len) +{ + return bt_hex(buf, len); +} + /* Crypto */ bool bt_mesh_ext_s1(const char *m, uint8_t salt[16]) { @@ -1147,17 +1178,17 @@ uint8_t *bt_mesh_ext_net_get_dev_key_ca(void) return bt_mesh.dev_key_ca; } -uint8_t bt_mesh_ext_net_get_rpl_count(void) +uint16_t bt_mesh_ext_net_get_rpl_count(void) { return ARRAY_SIZE(bt_mesh.rpl); } -uint16_t bt_mesh_ext_net_get_rpl_src(uint8_t index) +uint16_t bt_mesh_ext_net_get_rpl_src(uint16_t index) { return bt_mesh.rpl[index].src; } -void bt_mesh_ext_net_reset_rpl(uint8_t index) +void bt_mesh_ext_net_reset_rpl(uint16_t index) { memset(&bt_mesh.rpl[index], 0, sizeof(bt_mesh.rpl[index])); } @@ -1494,6 +1525,11 @@ void bt_mesh_ext_prov_link_set_expect(void *link, uint8_t val) LINK(link)->expect = val; } +uint8_t bt_mesh_ext_prov_link_get_expect(void *link) +{ + return LINK(link)->expect; +} + uint8_t bt_mesh_ext_prov_link_get_pub_key_type(void *link) { return LINK(link)->public_key; @@ -1621,6 +1657,16 @@ uint8_t *bt_mesh_ext_prov_link_get_pb_remote_uuid(void *link) return LINK(link)->pb_remote_uuid; } +void *bt_mesh_ext_prov_link_get_prot_timer(void *link) +{ + return &(LINK(link)->prot_timer); +} + +void *bt_mesh_ext_prov_link_get_with_work(void *work) +{ + return CONTAINER_OF(work, struct bt_mesh_prov_link, prot_timer.work); +} + uint8_t bt_mesh_ext_prov_link_get_pb_remote_timeout(void *link) { return LINK(link)->pb_remote_timeout; @@ -2037,9 +2083,19 @@ int bt_mesh_ext_rpr_cli_pdu_recv(void *link, uint8_t type, struct net_buf_simple } #if CONFIG_BLE_MESH_RPR_CLI -static struct bt_mesh_prov_link rpr_links[CONFIG_BLE_MESH_RPR_CLI_PROV_SAME_TIME]; +struct bt_mesh_prov_link rpr_links[CONFIG_BLE_MESH_RPR_CLI_PROV_SAME_TIME]; #endif /* CONFIG_BLE_MESH_RPR_CLI */ +bool bt_mesh_ext_bt_mesh_is_unprov_dev_being_prov(void *uuid) +{ +#if CONFIG_BLE_MESH_RPR_CLI + return bt_mesh_is_unprov_dev_being_prov(uuid); +#else + assert(0); + return 0; +#endif +} + void *bt_mesh_ext_rpr_cli_get_rpr_link(uint8_t index) { #if CONFIG_BLE_MESH_RPR_CLI @@ -2071,16 +2127,12 @@ int bt_mesh_ext_rpr_srv_nppi_pdu_recv(uint8_t type, const uint8_t *data) int bt_mesh_ext_rpr_srv_set_waiting_prov_link(void* link, bt_mesh_addr_t *addr) { -#if (CONFIG_BLE_MESH_GATT_PROXY_CLIENT && \ - CONFIG_BLE_MESH_PB_GATT && \ - CONFIG_BLE_MESH_RPR_SRV) +#if (CONFIG_BLE_MESH_PB_GATT && CONFIG_BLE_MESH_RPR_SRV) return bt_mesh_rpr_srv_set_waiting_prov_link(link, addr); #else assert(0); return 0; -#endif /* (CONFIG_BLE_MESH_GATT_PROXY_CLIENT && \ - CONFIG_BLE_MESH_PB_GATT && \ - CONFIG_BLE_MESH_RPR_SRV) */ +#endif /* CONFIG_BLE_MESH_PB_GATT && CONFIG_BLE_MESH_RPR_SRV) */ } /* Friend */ @@ -3764,7 +3816,7 @@ void *bt_mesh_ext_brc_srv_get_bridge_table_entry(void *srv, uint8_t index) #endif /* CONFIG_BLE_MESH_BRC_SRV */ } -void *bt_mesh_ext_brc_srv_get_bridge_rpl(uint8_t index) +void *bt_mesh_ext_brc_srv_get_bridge_rpl(uint16_t index) { #if CONFIG_BLE_MESH_BRC_SRV return &bridge_rpl[index]; @@ -3954,6 +4006,9 @@ void bt_mesh_ext_mbt_server_cb_evt_to_btc(uint8_t event, void *model, void *ctx) } typedef struct { + uint64_t config_ble_mesh_stack_trace_level : 3; + + uint64_t config_ble_mesh_use_ble_50: 1; uint64_t config_ble_mesh_use_duplicate_scan : 1; uint64_t config_ble_mesh_pb_adv : 1; uint64_t config_ble_mesh_pb_gatt : 1; @@ -3997,6 +4052,7 @@ typedef struct { uint64_t config_ble_mesh_srpl_cli : 1; uint64_t config_ble_mesh_srpl_srv : 1; + uint32_t config_ble_mesh_prov_protocol_timeout; uint16_t config_ble_mesh_record_frag_max_size; uint16_t config_ble_mesh_crpl; uint16_t config_ble_mesh_proxy_solic_rx_crpl; @@ -4116,6 +4172,9 @@ typedef struct { } bt_mesh_ext_config_t; static const bt_mesh_ext_config_t bt_mesh_ext_cfg = { + .config_ble_mesh_stack_trace_level = BLE_MESH_LOG_LEVEL, + + .config_ble_mesh_use_ble_50 = IS_ENABLED(CONFIG_BLE_MESH_USE_BLE_50), .config_ble_mesh_use_duplicate_scan = IS_ENABLED(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN), .config_ble_mesh_pb_adv = IS_ENABLED(CONFIG_BLE_MESH_PB_ADV), .config_ble_mesh_pb_gatt = IS_ENABLED(CONFIG_BLE_MESH_PB_GATT), @@ -4160,6 +4219,7 @@ static const bt_mesh_ext_config_t bt_mesh_ext_cfg = { .config_ble_mesh_sar_srv = IS_ENABLED(CONFIG_BLE_MESH_SAR_SRV), .config_ble_mesh_srpl_cli = IS_ENABLED(CONFIG_BLE_MESH_SRPL_CLI), .config_ble_mesh_srpl_srv = IS_ENABLED(CONFIG_BLE_MESH_SRPL_SRV), + .config_ble_mesh_prov_protocol_timeout = PROTOCOL_TIMEOUT, #if CONFIG_BLE_MESH_CERT_BASED_PROV .config_ble_mesh_record_frag_max_size = CONFIG_BLE_MESH_RECORD_FRAG_MAX_SIZE, @@ -4495,6 +4555,7 @@ typedef struct { int (*_bt_mesh_ext_rpr_cli_pdu_send)(void *link, uint8_t type); int (*_bt_mesh_ext_rpr_cli_recv_pub_key_outbound_report)(void *link); int (*_bt_mesh_ext_rpr_cli_pdu_recv)(void *link, uint8_t type, struct net_buf_simple *buf); + bool (*_bt_mesh_ext_bt_mesh_is_unprov_dev_being_prov)(void *uuid); void *(*_bt_mesh_ext_rpr_cli_get_rpr_link)(uint8_t index); /* CONFIG_BLE_MESH_RPR_CLI */ @@ -4526,7 +4587,7 @@ typedef struct { uint16_t (*_bt_mesh_ext_sub_get_sbr_net_idx)(void *sub); void (*_bt_mesh_ext_sub_set_sbr_net_idx)(void *sub, uint16_t sbr_net_idx); void *(*_bt_mesh_ext_brc_srv_get_bridge_table_entry)(void *srv, uint8_t index); - void *(*_bt_mesh_ext_brc_srv_get_bridge_rpl)(uint8_t index); + void *(*_bt_mesh_ext_brc_srv_get_bridge_rpl)(uint16_t index); /* CONFIG_BLE_MESH_BRC_SRV */ /* CONFIG_BLE_MESH_AGG_CLI */ @@ -4816,6 +4877,7 @@ static const bt_mesh_ext_funcs_t bt_mesh_ext_func = { ._bt_mesh_ext_rpr_cli_pdu_send = bt_mesh_ext_rpr_cli_pdu_send, ._bt_mesh_ext_rpr_cli_recv_pub_key_outbound_report = bt_mesh_ext_rpr_cli_recv_pub_key_outbound_report, ._bt_mesh_ext_rpr_cli_pdu_recv = bt_mesh_ext_rpr_cli_pdu_recv, + ._bt_mesh_ext_bt_mesh_is_unprov_dev_being_prov = bt_mesh_ext_bt_mesh_is_unprov_dev_being_prov, ._bt_mesh_ext_rpr_cli_get_rpr_link = bt_mesh_ext_rpr_cli_get_rpr_link, /* CONFIG_BLE_MESH_RPR_CLI */ diff --git a/lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h b/lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h index 71a02314..d8e80b19 100644 --- a/lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h +++ b/lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a index 5f8b75a3..73d2771c 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a index ffc32db1..27e93069 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a new file mode 100644 index 00000000..27e93069 Binary files /dev/null and b/lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a index ffc32db1..27e93069 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a new file mode 100644 index 00000000..27e93069 Binary files /dev/null and b/lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a index ffc32db1..27e93069 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a index 5f8b75a3..a72cd64c 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/models/client/client_common.c b/lib/bt/esp_ble_mesh/models/client/client_common.c index db878516..7e544870 100644 --- a/lib/bt/esp_ble_mesh/models/client/client_common.c +++ b/lib/bt/esp_ble_mesh/models/client/client_common.c @@ -14,7 +14,9 @@ #include "mesh/client_common.h" #include "mesh/common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define HCI_TIME_FOR_START_ADV K_MSEC(5) /* Three adv related hci commands may take 4 ~ 5ms */ diff --git a/lib/bt/esp_ble_mesh/models/server/time_scene_server.c b/lib/bt/esp_ble_mesh/models/server/time_scene_server.c index 3494653a..a63550bc 100644 --- a/lib/bt/esp_ble_mesh/models/server/time_scene_server.c +++ b/lib/bt/esp_ble_mesh/models/server/time_scene_server.c @@ -244,7 +244,8 @@ static void time_get(struct bt_mesh_model *model, change.time_status.subsecond = srv->state->time.subsecond; change.time_status.uncertainty = srv->state->time.uncertainty; change.time_status.time_authority = srv->state->time.time_authority; - change.time_status.tai_utc_delta_curr = srv->state->time.subsecond; + change.time_status.tai_utc_delta_curr = srv->state->time.tai_utc_delta_curr; + change.time_status.time_zone_offset_curr = srv->state->time.time_zone_offset_curr; bt_mesh_time_scene_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change)); @@ -386,7 +387,8 @@ static void time_set(struct bt_mesh_model *model, change.time_set.subsecond = srv->state->time.subsecond; change.time_set.uncertainty = srv->state->time.uncertainty; change.time_set.time_authority = srv->state->time.time_authority; - change.time_set.tai_utc_delta_curr = srv->state->time.subsecond; + change.time_set.tai_utc_delta_curr = srv->state->time.tai_utc_delta_curr; + change.time_set.time_zone_offset_curr = srv->state->time.time_zone_offset_curr; break; case BLE_MESH_MODEL_OP_TIME_ZONE_SET: change.time_zone_set.time_zone_offset_new = srv->state->time.time_zone_offset_new; diff --git a/lib/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c b/lib/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c index 5ab2cd17..de5550ce 100644 --- a/lib/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c +++ b/lib/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "btc/btc_manage.h" @@ -91,4 +92,34 @@ esp_err_t esp_ble_mesh_register_rpr_server_callback(esp_ble_mesh_rpr_server_cb_t return (btc_profile_cb_set(BTC_PID_RPR_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL); } + +esp_err_t esp_ble_mesh_rpr_server_set_uuid_match(const uint8_t *match_val, uint8_t match_len, uint8_t offset) +{ + btc_ble_mesh_rpr_server_args_t arg = {0}; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_RPR_SERVER; + msg.act = BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH; + + if (!match_len || match_len > 16 || + !match_val || offset >= 16 || + offset + match_len > 16) { + return ESP_ERR_INVALID_ARG; + } + + arg.set_uuid_match.match_val = bt_mesh_calloc(match_len); + if (!arg.set_uuid_match.match_val) { + BT_ERR("%s:Out of memory", __func__); + return ESP_ERR_NO_MEM; + } + + memcpy(arg.set_uuid_match.match_val, match_val, match_len); + arg.set_uuid_match.match_len = match_len; + arg.set_uuid_match.offset = offset; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_rpr_server_args_t), + btc_ble_mesh_rpr_server_arg_deep_copy, + btc_ble_mesh_rpr_server_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} #endif /* CONFIG_BLE_MESH_RPR_SRV */ diff --git a/lib/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h b/lib/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h index 31d0923e..a19e5539 100644 --- a/lib/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h +++ b/lib/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -396,6 +396,13 @@ typedef union { uint16_t net_idx; /*!< NetKey Index used by Remote Provisioning Client */ uint16_t rpr_cli_addr; /*!< Unicast address of Remote Provisioning Client */ } prov_comp; + + /** + * @brief ESP_BLE_MESH_RPR_SERVER_SET_UUID_MATCH_COMP_EVT + */ + struct { + int err_code; /*!< Indicate the result of setting Device UUID match value by the Remote Provisioning Server */ + } set_uuid_match_comp; } esp_ble_mesh_rpr_server_cb_param_t; /** This enum value is the event of Remote Provisioning Server model */ @@ -407,6 +414,7 @@ typedef enum { ESP_BLE_MESH_RPR_SERVER_LINK_OPEN_EVT, ESP_BLE_MESH_RPR_SERVER_LINK_CLOSE_EVT, ESP_BLE_MESH_RPR_SERVER_PROV_COMP_EVT, + ESP_BLE_MESH_RPR_SERVER_SET_UUID_MATCH_COMP_EVT, ESP_BLE_MESH_RPR_SERVER_EVT_MAX, } esp_ble_mesh_rpr_server_cb_event_t; @@ -474,6 +482,18 @@ typedef void (* esp_ble_mesh_rpr_server_cb_t)(esp_ble_mesh_rpr_server_cb_event_t */ esp_err_t esp_ble_mesh_register_rpr_server_callback(esp_ble_mesh_rpr_server_cb_t callback); +/** + * @brief This function is called by Remote Provisioning Server to set the part of + * the device UUID to be compared before starting to remote provision. + * + * @param[in] match_val: Value to be compared with the part of the device UUID. + * @param[in] match_len: Length of the compared match value. + * @param[in] offset: Offset of the device UUID to be compared (based on zero). + * + * @return ESP_OK on success or error code otherwise. +*/ +esp_err_t esp_ble_mesh_rpr_server_set_uuid_match(const uint8_t *match_val, uint8_t match_len, uint8_t offset); + #ifdef __cplusplus } #endif diff --git a/lib/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c b/lib/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c index 5e4437f4..e5200d7c 100644 --- a/lib/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c +++ b/lib/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -451,6 +451,61 @@ void btc_ble_mesh_rpr_client_cb_handler(btc_msg_t *msg) #if CONFIG_BLE_MESH_RPR_SRV /* Remote Provisioning Server model related functions */ +extern int bt_mesh_rpr_srv_scan_set_dev_uuid_match(uint8_t offset, uint8_t length,const uint8_t *match); + +void btc_ble_mesh_rpr_server_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_ble_mesh_rpr_server_args_t *dst = p_dest; + btc_ble_mesh_rpr_server_args_t *src = p_src; + + if (!msg || !dst || !src) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + switch(msg->act) { + case BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH: + dst->set_uuid_match.match_val = bt_mesh_calloc(src->set_uuid_match.match_len); + if (dst->set_uuid_match.match_val) { + memcpy(dst->set_uuid_match.match_val, src->set_uuid_match.match_val, src->set_uuid_match.match_len); + dst->set_uuid_match.match_len = src->set_uuid_match.match_len; + dst->set_uuid_match.offset = src->set_uuid_match.offset; + } else { + BT_ERR("%s, Out of memory, act %d", __func__, msg->act); + } + bt_mesh_free(src->set_uuid_match.match_val); + break; + default: + BT_DBG("%s, Unknown act %d", __func__, msg->act); + break; + } + + return; +} + +void btc_ble_mesh_rpr_server_arg_deep_free(btc_msg_t *msg) +{ + btc_ble_mesh_rpr_server_args_t *arg = NULL; + + if (!msg) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + arg = (btc_ble_mesh_rpr_server_args_t *)msg->arg; + + switch(msg->act) { + case BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH: + if (arg->set_uuid_match.match_val) { + bt_mesh_free(arg->set_uuid_match.match_val); + } + break; + default: + break; + } + + return; +} static inline void btc_ble_mesh_rpr_server_cb_to_app(esp_ble_mesh_rpr_server_cb_event_t event, esp_ble_mesh_rpr_server_cb_param_t *param) @@ -522,6 +577,33 @@ void bt_mesh_rpr_server_cb_evt_to_btc(uint8_t event, const void *val, size_t len btc_ble_mesh_rpr_server_cb(&cb_params, act); } +void btc_ble_mesh_rpr_server_call_handler(btc_msg_t *msg) +{ + esp_ble_mesh_rpr_server_cb_param_t cb = {0}; + btc_ble_mesh_rpr_server_args_t *arg = NULL; + + if (!msg) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + arg = (btc_ble_mesh_rpr_server_args_t *)msg->arg; + + switch (msg->act) { + case BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH: + cb.set_uuid_match_comp.err_code = bt_mesh_rpr_srv_scan_set_dev_uuid_match(arg->set_uuid_match.offset, + arg->set_uuid_match.match_len, + arg->set_uuid_match.match_val); + + btc_ble_mesh_rpr_server_cb(&cb, ESP_BLE_MESH_RPR_SERVER_SET_UUID_MATCH_COMP_EVT); + break; + default: + break; + } + + btc_ble_mesh_rpr_server_arg_deep_free(msg); +} + void btc_ble_mesh_rpr_server_cb_handler(btc_msg_t *msg) { esp_ble_mesh_rpr_server_cb_param_t *arg = NULL; diff --git a/lib/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h b/lib/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h index e5217782..5b78299a 100644 --- a/lib/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h +++ b/lib/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,6 +64,11 @@ void bt_mesh_rpr_client_cb_evt_to_btc(uint32_t opcode, uint8_t event, struct bt_mesh_msg_ctx *ctx, const void *val, size_t len); +typedef enum { + BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH, + BTC_BLE_MESH_ACT_RPR_SRV_MAX, +} btc_ble_mesh_rpr_server_act_t; + typedef enum { BTC_BLE_MESH_EVT_RPR_SERVER_SCAN_START, BTC_BLE_MESH_EVT_RPR_SERVER_SCAN_STOP, @@ -72,9 +77,22 @@ typedef enum { BTC_BLE_MESH_EVT_RPR_SERVER_LINK_OPEN, BTC_BLE_MESH_EVT_RPR_SERVER_LINK_CLOSE, BTC_BLE_MESH_EVT_RPR_SERVER_PROV_COMP, + BTC_BLE_MESH_EVT_RPR_SERVER_SET_UUID_MATCH_COMP, BTC_BLE_MESH_EVT_RPR_SERVER_MAX, } btc_ble_mesh_rpr_server_evt_t; +typedef union { + struct { + uint8_t *match_val; + uint8_t match_len; + uint8_t offset; + } set_uuid_match; +} btc_ble_mesh_rpr_server_args_t; + +void btc_ble_mesh_rpr_server_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_ble_mesh_rpr_server_arg_deep_free(btc_msg_t *msg); + +void btc_ble_mesh_rpr_server_call_handler(btc_msg_t *msg); void btc_ble_mesh_rpr_server_cb_handler(btc_msg_t *msg); void bt_mesh_rpr_server_cb_evt_to_btc(uint8_t event, const void *val, size_t len); -- cgit v1.2.3