From e394994d39e541379f4b20fa40d8b628f8c271b1 Mon Sep 17 00:00:00 2001 From: Martin Girardot <165289184+Martin-NXP@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:12:01 +0100 Subject: [PATCH] Custom BLE data at application layer (#36857) * [Zephyr] Add support to custom BLE advertising data at application layer Signed-off-by: Martin Girardot * [NXP][RTs] Add support to custom advertising data at application layer Signed-off-by: Martin Girardot * [NXP][examples[common] Add support to custom advertising data at application layer Signed-off-by: Martin Girardot * [NXP] Update nxp matter support submodule Signed-off-by: Martin Girardot * Restyled by whitespace * Restyled by clang-format * Restyled by gn * [NXP] update BLE include path Signed-off-by: Martin Girardot * Restyled by clang-format --------- Signed-off-by: Martin Girardot Co-authored-by: Restyled.io --- config/zephyr/Kconfig | 7 + .../nxp/common/main/AppTask.cpp | 3 + .../all-clusters-app/nxp/rt/rt1060/BUILD.gn | 4 + .../all-clusters-app/nxp/rt/rt1170/BUILD.gn | 4 + .../all-clusters-app/nxp/rt/rw61x/BUILD.gn | 4 + .../thermostat/nxp/common/main/AppTask.cpp | 11 + .../nxp/common/main/BleZephyrManagerApp.cpp | 100 ++++++ examples/thermostat/nxp/rt/rt1060/BUILD.gn | 16 + examples/thermostat/nxp/rt/rt1060/args.gni | 4 + examples/thermostat/nxp/rt/rt1170/BUILD.gn | 16 + examples/thermostat/nxp/rt/rt1170/args.gni | 4 + examples/thermostat/nxp/rt/rw61x/BUILD.gn | 16 + examples/thermostat/nxp/rt/rw61x/args.gni | 4 + examples/thermostat/nxp/zephyr/CMakeLists.txt | 11 + examples/thermostat/nxp/zephyr/prj.conf | 4 + src/platform/Zephyr/BLEManagerImpl.cpp | 31 +- src/platform/Zephyr/BLEManagerImpl.h | 8 + .../CHIPDeviceNXPPlatformDefaultConfig.h | 3 +- .../ble_zephyr/BLEAdvertisingArbiter.cpp | 31 +- .../common/ble_zephyr/BLEAdvertisingArbiter.h | 18 + .../nxp/common/ble_zephyr/BLEManagerImpl.cpp | 308 ++++++++++++++---- .../nxp/common/ble_zephyr/BLEManagerImpl.h | 18 +- third_party/nxp/nxp_matter_support | 2 +- 23 files changed, 545 insertions(+), 82 deletions(-) create mode 100644 examples/thermostat/nxp/common/main/BleZephyrManagerApp.cpp diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig index d8717a625d3dd3..7b0ee1d15062d5 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -582,3 +582,10 @@ config CHIP_BLE_ADVERTISING_DURATION else the maximum duration time can be extended to 2880 minutes (48h). endif + +if BT +config CHIP_CUSTOM_BLE_ADV_DATA + bool "Use custom BLE advertising data" + help + Customization of BLE advertising data at the application layer +endif diff --git a/examples/all-clusters-app/nxp/common/main/AppTask.cpp b/examples/all-clusters-app/nxp/common/main/AppTask.cpp index 0b945d49561e43..702a63e89b5c8d 100644 --- a/examples/all-clusters-app/nxp/common/main/AppTask.cpp +++ b/examples/all-clusters-app/nxp/common/main/AppTask.cpp @@ -40,6 +40,9 @@ void AllClustersApp::AppTask::PostInitMatterStack() void AllClustersApp::AppTask::PostInitMatterServerInstance() { +#ifdef APP_BT_DEVICE_NAME + chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(APP_BT_DEVICE_NAME); +#endif // Disable last fixed endpoint, which is used as a placeholder for all of the // supported clusters so that ZAP will generated the requisite code. emberAfEndpointEnableDisable(emberAfEndpointFromIndex(static_cast(emberAfFixedEndpointCount() - 1)), false); diff --git a/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn b/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn index beca71ac1002d8..d5a4936a48f5a0 100644 --- a/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn +++ b/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn @@ -223,6 +223,10 @@ rt_executable("all_cluster_app") { ] } + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] + } + # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { diff --git a/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn b/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn index 70a0a4d640738c..edbd208506b824 100644 --- a/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn +++ b/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn @@ -188,6 +188,10 @@ rt_executable("all_cluster_app") { sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] } + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] + } + # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { diff --git a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn index 5b73da4bc92080..cb4e017b9b45bf 100644 --- a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn +++ b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn @@ -210,6 +210,10 @@ rt_executable("all_cluster_app") { sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] } + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] + } + # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { diff --git a/examples/thermostat/nxp/common/main/AppTask.cpp b/examples/thermostat/nxp/common/main/AppTask.cpp index 8e3f8f1036a2e4..583e3c3dc1bbd4 100644 --- a/examples/thermostat/nxp/common/main/AppTask.cpp +++ b/examples/thermostat/nxp/common/main/AppTask.cpp @@ -24,6 +24,10 @@ #include #include +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include "BLEApplicationManager.h" +#endif + using namespace chip; void ThermostatApp::AppTask::PreInitMatterStack() @@ -33,6 +37,13 @@ void ThermostatApp::AppTask::PreInitMatterStack() void ThermostatApp::AppTask::PostInitMatterStack() { +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#ifdef APP_BT_DEVICE_NAME + chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(APP_BT_DEVICE_NAME); +#endif + /* BLEApplicationManager implemented per platform or left blank */ + chip::NXP::App::BleAppMgr().Init(); +#endif chip::app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&chip::NXP::App::GetICDUtil()); } diff --git a/examples/thermostat/nxp/common/main/BleZephyrManagerApp.cpp b/examples/thermostat/nxp/common/main/BleZephyrManagerApp.cpp new file mode 100644 index 00000000000000..170ef3c4cc45ab --- /dev/null +++ b/examples/thermostat/nxp/common/main/BleZephyrManagerApp.cpp @@ -0,0 +1,100 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * Copyright 2024 NXP + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BLEApplicationManager.h" + +#include + +#include "BLEManagerImpl.h" +#include +#include +#include + +#define ADV_LEN 2 + +using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceLayer::Internal; +using namespace ::chip::NXP::App; + +BLEApplicationManager BLEApplicationManager::sInstance; + +struct ServiceData +{ + uint8_t uuid[2]; + chip::Ble::ChipBLEDeviceIdentificationInfo deviceIdInfo; +} __attribute__((packed)); + +ServiceData serviceData; +std::array advertisingData; +std::array scanResponseData; + +constexpr uint8_t kAdvertisingFlags = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR; + +uint8_t manuf_data[ADV_LEN] = { + 0x25, + 0x00, +}; + +bt_uuid_16 UUID16_CHIPoBLEService = BT_UUID_INIT_16(0xFFF6); + +/** + * @brief Init BLE application manager + * + * In this example, the application manager is used to customize BLE advertising + * parameters. This example is provided for platforms with Zephyr BLE manager support. + * + * @note This example set custom Zephyr BLE manager Matter advertising parameters ( + * CONFIG_CHIP_CUSTOM_BLE_ADV_DATA for kconfig or ble_adv_data_custom for GN is set). + * To keep the advertising support for commissining, it is needed to register the whole + * adv data (adv flags + Matter adv data + custom adv data) and register scan + * response data as default adv and response data will be skipped. + * kAdvertisingFlags and manuf_data are given for examples, size of advertisingData and + * scanResponseData have to be set according to custom requirements. + * + * For custom Gatt services, APIs bt_gatt_service_register and bt_gatt_service_unregister + * could be called at application layer. It will not override Matter Gatt services but + * add new one. + * + * @note At the end of the commissioning advertising will be stopped. + * + * To start new advertising process, APIs : + * chip::DeviceLayer::BLEAdvertisingArbiter::InsertRequest + * chip::DeviceLayer::BLEAdvertisingArbiter::CancelRequest + * could be called. If InsertRequest API is called several time, only the request with the + * higher priority will be advertise. + * + */ +void BLEApplicationManager::Init(void) +{ + /* Register Matter adv data + custom adv data */ + static_assert(sizeof(serviceData) == 10, "Unexpected size of BLE advertising data!"); + const char * name = bt_get_name(); + const uint8_t nameSize = static_cast(strlen(name)); + Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val); + chip::DeviceLayer::ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo); + + advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); + /* Matter adv data for commissining */ + advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); + /* Example of custom BLE adv data */ + advertisingData[2] = BT_DATA(BT_DATA_MANUFACTURER_DATA, manuf_data, ADV_LEN); + scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); + chip::DeviceLayer::Internal::BLEMgrImpl().SetCustomAdvertising(Span(advertisingData)); + chip::DeviceLayer::Internal::BLEMgrImpl().SetCustomScanResponse(Span(scanResponseData)); +} diff --git a/examples/thermostat/nxp/rt/rt1060/BUILD.gn b/examples/thermostat/nxp/rt/rt1060/BUILD.gn index e57cc01b92b47b..c365ee9d47b4ca 100644 --- a/examples/thermostat/nxp/rt/rt1060/BUILD.gn +++ b/examples/thermostat/nxp/rt/rt1060/BUILD.gn @@ -147,6 +147,22 @@ rt_executable("thermostat") { "../../common/main/main.cpp", ] + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-ThermostatApp\"" ] + include_dirs += [ "${common_example_dir}/app_ble/include" ] + if (ble_adv_data_custom) { + # to customize BLE advertising data + defines += [ "CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=1" ] + include_dirs += [ "${chip_root}/src/platform/nxp/common/ble_zephyr" ] + sources += [ "../../common/main/BleZephyrManagerApp.cpp" ] + } else { + # Empty implementation, default matter advertising data + sources += [ + "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", + ] + } + } + if (chip_with_diag_logs_demo) { include_dirs += [ "${common_example_dir}/diagnostic_logs/include", diff --git a/examples/thermostat/nxp/rt/rt1060/args.gni b/examples/thermostat/nxp/rt/rt1060/args.gni index c2d91a5db7bae7..d3fc29a80c4920 100644 --- a/examples/thermostat/nxp/rt/rt1060/args.gni +++ b/examples/thermostat/nxp/rt/rt1060/args.gni @@ -14,6 +14,10 @@ import("//build_overrides/chip.gni") +# Set to true to customized BLE advertising data at application layer, +# instead of default Zephyr BLE manager implementation advertising data +ble_adv_data_custom = true + # SDK target definitions nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/thermostat/nxp/rt/rt1170/BUILD.gn b/examples/thermostat/nxp/rt/rt1170/BUILD.gn index abb7090f962559..3e03df43488247 100644 --- a/examples/thermostat/nxp/rt/rt1170/BUILD.gn +++ b/examples/thermostat/nxp/rt/rt1170/BUILD.gn @@ -135,6 +135,22 @@ rt_executable("thermostat") { "../../common/main/main.cpp", ] + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-ThermostatApp\"" ] + include_dirs += [ "${common_example_dir}/app_ble/include" ] + if (ble_adv_data_custom) { + # to customize BLE advertising data + defines += [ "CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=1" ] + include_dirs += [ "${chip_root}/src/platform/nxp/common/ble_zephyr" ] + sources += [ "../../common/main/BleZephyrManagerApp.cpp" ] + } else { + # Empty implementation, default matter advertising data + sources += [ + "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", + ] + } + } + if (chip_with_diag_logs_demo) { include_dirs += [ "${common_example_dir}/diagnostic_logs/include", diff --git a/examples/thermostat/nxp/rt/rt1170/args.gni b/examples/thermostat/nxp/rt/rt1170/args.gni index c2d91a5db7bae7..d3fc29a80c4920 100644 --- a/examples/thermostat/nxp/rt/rt1170/args.gni +++ b/examples/thermostat/nxp/rt/rt1170/args.gni @@ -14,6 +14,10 @@ import("//build_overrides/chip.gni") +# Set to true to customized BLE advertising data at application layer, +# instead of default Zephyr BLE manager implementation advertising data +ble_adv_data_custom = true + # SDK target definitions nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/thermostat/nxp/rt/rw61x/BUILD.gn b/examples/thermostat/nxp/rt/rw61x/BUILD.gn index 07a58e947756c6..6dd71061c010c5 100644 --- a/examples/thermostat/nxp/rt/rw61x/BUILD.gn +++ b/examples/thermostat/nxp/rt/rw61x/BUILD.gn @@ -145,6 +145,22 @@ rt_executable("thermostat") { "../../common/main/main.cpp", ] + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-ThermostatApp\"" ] + include_dirs += [ "${common_example_dir}/app_ble/include" ] + if (ble_adv_data_custom) { + # to customize BLE advertising data + defines += [ "CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=1" ] + include_dirs += [ "${chip_root}/src/platform/nxp/common/ble_zephyr" ] + sources += [ "../../common/main/BleZephyrManagerApp.cpp" ] + } else { + # Empty implementation, default matter advertising data + sources += [ + "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", + ] + } + } + if (chip_with_diag_logs_demo) { include_dirs += [ "${common_example_dir}/diagnostic_logs/include", diff --git a/examples/thermostat/nxp/rt/rw61x/args.gni b/examples/thermostat/nxp/rt/rw61x/args.gni index c2d91a5db7bae7..d3fc29a80c4920 100644 --- a/examples/thermostat/nxp/rt/rw61x/args.gni +++ b/examples/thermostat/nxp/rt/rw61x/args.gni @@ -14,6 +14,10 @@ import("//build_overrides/chip.gni") +# Set to true to customized BLE advertising data at application layer, +# instead of default Zephyr BLE manager implementation advertising data +ble_adv_data_custom = true + # SDK target definitions nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/thermostat/nxp/zephyr/CMakeLists.txt b/examples/thermostat/nxp/zephyr/CMakeLists.txt index b478cfff9f2566..221e66e2451162 100644 --- a/examples/thermostat/nxp/zephyr/CMakeLists.txt +++ b/examples/thermostat/nxp/zephyr/CMakeLists.txt @@ -52,6 +52,7 @@ target_include_directories(app ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/device_callbacks/include ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/factory_data/include ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/app_task/include + ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/app_ble/include ) target_sources(app @@ -73,6 +74,16 @@ target_compile_definitions(app PUBLIC "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/zephyr/FactoryDataProviderImpl.h\"" ) +if(CONFIG_CHIP_CUSTOM_BLE_ADV_DATA) + target_sources(app PRIVATE + ${THERMOSTAT_NXP_COMMON_DIR}/main/BleZephyrManagerApp.cpp + ) +else() + target_sources(app PRIVATE + ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/app_ble/source/BLEApplicationManagerEmpty.cpp + ) +endif() + if(CONFIG_CHIP_OTA_REQUESTOR) target_sources(app PRIVATE ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/ota_requestor/source/OTARequestorInitiatorCommon.cpp diff --git a/examples/thermostat/nxp/zephyr/prj.conf b/examples/thermostat/nxp/zephyr/prj.conf index a2fa69056d517e..6e1ad43097242d 100644 --- a/examples/thermostat/nxp/zephyr/prj.conf +++ b/examples/thermostat/nxp/zephyr/prj.conf @@ -56,3 +56,7 @@ CONFIG_CHIP_LIB_SHELL=y # enable NET commands if desired # CONFIG_NET_SHELL=y CONFIG_CHIP_STATISTICS=y + +# To customized BLE advertising data at application layer, +# instead of default Zephyr BLE manager implementation advertising data +CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=y diff --git a/src/platform/Zephyr/BLEManagerImpl.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp index 49751da62479e3..6b8ba4b6989ce6 100644 --- a/src/platform/Zephyr/BLEManagerImpl.cpp +++ b/src/platform/Zephyr/BLEManagerImpl.cpp @@ -284,6 +284,13 @@ struct BLEManagerImpl::ServiceData inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() { +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + if (mCustomAdvertising.empty()) + { + ChipLogError(DeviceLayer, "mCustomAdvertising should be set when CONFIG_CHIP_CUSTOM_BLE_ADV_DATA is define"); + return CHIP_ERROR_INTERNAL; + } +#else static ServiceData serviceData; static std::array advertisingData; static std::array scanResponseData; @@ -304,9 +311,10 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() } #endif - advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); - advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); - scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); + advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); + advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); + scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); +#endif // CONFIG_CHIP_CUSTOM_BLE_ADV_DATA mAdvertisingRequest.priority = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY; mAdvertisingRequest.options = kAdvertisingOptions; @@ -328,9 +336,13 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; } +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + mAdvertisingRequest.advertisingData = mCustomAdvertising; + mAdvertisingRequest.scanResponseData = mCustomScanResponse; +#else mAdvertisingRequest.advertisingData = Span(advertisingData); mAdvertisingRequest.scanResponseData = nameSize ? Span(scanResponseData) : Span{}; - +#endif mAdvertisingRequest.onStarted = [](int rc) { if (rc == 0) { @@ -967,6 +979,17 @@ ssize_t BLEManagerImpl::HandleC3Read(struct bt_conn * conId, const struct bt_gat } #endif +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA +void BLEManagerImpl::SetCustomAdvertising(Span CustomAdvertising) +{ + mCustomAdvertising = CustomAdvertising; +} +void BLEManagerImpl::SetCustomScanResponse(Span CustomScanResponse) +{ + mCustomScanResponse = CustomScanResponse; +} +#endif + } // namespace Internal } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Zephyr/BLEManagerImpl.h b/src/platform/Zephyr/BLEManagerImpl.h index 8c09ed457f94b2..9e83dc47ed6ae6 100644 --- a/src/platform/Zephyr/BLEManagerImpl.h +++ b/src/platform/Zephyr/BLEManagerImpl.h @@ -105,6 +105,10 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla #endif // The summarized number of Bluetooth LE connections related to the device (including these not related to Matter service). uint16_t mTotalConnNum; +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + Span mCustomAdvertising = {}; + Span mCustomScanResponse = {}; +#endif void DriveBLEState(void); CHIP_ERROR PrepareAdvertisingRequest(); @@ -150,6 +154,10 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING static ssize_t HandleC3Read(struct bt_conn * conn, const struct bt_gatt_attr * attr, void * buf, uint16_t len, uint16_t offset); #endif +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + void SetCustomAdvertising(Span CustomAdvertising); + void SetCustomScanResponse(Span CustomScanResponse); +#endif }; /** diff --git a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h index 5e5fd2b14d5fea..79ceb200dbe1c5 100644 --- a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h +++ b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h @@ -85,7 +85,8 @@ #ifndef CHIP_DEVICE_BLE_ADVERTISING_PRIORITY /// Priority of the Matter BLE advertising when there are multiple application /// components that compete for the BLE advertising. -#define CHIP_DEVICE_BLE_ADVERTISING_PRIORITY 0 +/// Increase priority to 1 to allow user to insert custom advertising data with higher priority (0) +#define CHIP_DEVICE_BLE_ADVERTISING_PRIORITY 1 #endif // CHIP_DEVICE_BLE_ADVERTISING_PRIORITY // ========== Platform-specific Configuration ========= diff --git a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp index ee6b91da3f9c7e..f66b98317e27e3 100644 --- a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp +++ b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp @@ -29,6 +29,9 @@ namespace { // List of advertising requests ordered by priority sys_slist_t sRequests; +bool sIsInitialized = false; +uint8_t sBtId = 0; + // Cast an intrusive list node to the containing request object const BLEAdvertisingArbiter::Request & ToRequest(const sys_snode_t * node) { @@ -55,8 +58,9 @@ CHIP_ERROR RestartAdvertising() ReturnErrorOnFailure(MapErrorZephyr(bt_le_adv_stop())); VerifyOrReturnError(!sys_slist_is_empty(&sRequests), CHIP_NO_ERROR); - const Request & top = ToRequest(sys_slist_peek_head(&sRequests)); - const bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr); + const Request & top = ToRequest(sys_slist_peek_head(&sRequests)); + bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr); + params.id = sBtId; const int result = bt_le_adv_start(¶ms, top.advertisingData.data(), top.advertisingData.size(), top.scanResponseData.data(), top.scanResponseData.size()); @@ -70,8 +74,26 @@ CHIP_ERROR RestartAdvertising() } // namespace +CHIP_ERROR Init(uint8_t btId) +{ + if (sIsInitialized) + { + return CHIP_ERROR_INCORRECT_STATE; + } + + sBtId = btId; + sIsInitialized = true; + + return CHIP_NO_ERROR; +} + CHIP_ERROR InsertRequest(Request & request) { + if (!sIsInitialized) + { + return CHIP_ERROR_INCORRECT_STATE; + } + CancelRequest(request); sys_snode_t * prev = nullptr; @@ -109,6 +131,11 @@ CHIP_ERROR InsertRequest(Request & request) void CancelRequest(Request & request) { + if (!sIsInitialized) + { + return; + } + const bool isTopPriority = (sys_slist_peek_head(&sRequests) == &request); VerifyOrReturn(sys_slist_find_and_remove(&sRequests, &request)); diff --git a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h index 11a90c7070cd0a..0204a406244eab 100644 --- a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h +++ b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h @@ -62,6 +62,18 @@ struct Request : public sys_snode_t OnAdvertisingStopped onStopped; ///< (Optional) Callback invoked when the request stops being top-priority. }; +/** + * @brief Initialize BLE advertising arbiter + * + * @note This method must be called before trying to insert or cancel any requests. + * + * @param btId Local Bluetooth LE identifier to be used for the advertising parameters. Currently Bluetooth LE identifier used in + * this method will be used for all advertising requests and changing it dynamically is not supported. + * @return error If the module is already initialized. + * @return success Otherwise. + */ +CHIP_ERROR Init(uint8_t btId); + /** * @brief Request BLE advertising * @@ -75,6 +87,9 @@ struct Request : public sys_snode_t * @note This method does not take ownership of the request object so the object * must not get destroyed before it is cancelled. * + * @note The arbiter module has to be initialized using Init() method before + * invoking this method. + * * @param request Reference to advertising request that contains priority and * other advertising parameters. * @return error If the request is top-priority and failed to restart the @@ -95,6 +110,9 @@ CHIP_ERROR InsertRequest(Request & request); * An attempt to cancel a request that has not been registered at the * advertising arbiter is a no-op. That is, it returns immediately. * + * @note The arbiter module has to be initialized using Init() method before + * invoking this method. + * * @param request Reference to advertising request that contains priority and * other advertising parameters. */ diff --git a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp index 0d1c4c0dcb8932..aca08a9339b243 100644 --- a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp +++ b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp @@ -27,9 +27,10 @@ #include "BLEManagerImpl.h" -#include +#include #include #include +#include #include #include #include @@ -44,6 +45,10 @@ #include #include +#ifdef CONFIG_BT_BONDABLE +#include +#endif // CONFIG_BT_BONDABLE + #include using namespace ::chip; @@ -70,12 +75,6 @@ const bt_uuid_128 UUID128_CHIPoBLEChar_C3 = bt_uuid_16 UUID16_CHIPoBLEService = BT_UUID_INIT_16(0xFFF6); -const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, - 0x9D, 0x11 } }; - -const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, - 0x9D, 0x12 } }; - _bt_gatt_ccc CHIPoBLEChar_TX_CCC = BT_GATT_CCC_INITIALIZER(nullptr, BLEManagerImpl::HandleTXCCCWrite, nullptr); // clang-format off @@ -107,7 +106,13 @@ bt_gatt_service sChipoBleService = BT_GATT_SERVICE(sChipoBleAttributes); // This value should be adjusted accordingly if the service declaration changes. constexpr int kCHIPoBLE_CCC_AttributeIndex = 3; -CHIP_ERROR InitRandomStaticAddress() +#ifdef CONFIG_BT_BONDABLE +constexpr uint8_t kMatterBleIdentity = 1; +#else +constexpr uint8_t kMatterBleIdentity = 0; +#endif // CONFIG_BT_BONDABLE + +int InitRandomStaticAddress(bool idPresent, int & id) { // Generate a random static address for the default identity. // This must be done before bt_enable() as after that updating the default identity is not possible. @@ -122,20 +127,29 @@ CHIP_ERROR InitRandomStaticAddress() if (error) { ChipLogError(DeviceLayer, "Failed to create BLE address: %d", error); - return MapErrorZephyr(error); + return error; } - error = bt_id_create(&addr, nullptr); + if (!idPresent) + { + id = bt_id_create(&addr, nullptr); + } +#if CONFIG_BT_ID_MAX == 2 + else + { + id = bt_id_reset(1, &addr, nullptr); + } +#endif // CONFIG_BT_BONDABLE - if (error < 0) + if (id < 0) { ChipLogError(DeviceLayer, "Failed to create BLE identity: %d", error); - return MapErrorZephyr(error); + return id; } ChipLogProgress(DeviceLayer, "BLE address: %02X:%02X:%02X:%02X:%02X:%02X", addr.a.val[5], addr.a.val[4], addr.a.val[3], addr.a.val[2], addr.a.val[1], addr.a.val[0]); - return CHIP_NO_ERROR; + return 0; } } // unnamed namespace @@ -144,16 +158,41 @@ BLEManagerImpl BLEManagerImpl::sInstance; CHIP_ERROR BLEManagerImpl::_Init() { + int err = 0; + int id = 0; + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART); mFlags.Set(Flags::kFastAdvertisingEnabled, true); - mGAPConns = 0; + mMatterConnNum = 0; + mTotalConnNum = 0; memset(mSubscribedConns, 0, sizeof(mSubscribedConns)); - ReturnErrorOnFailure(InitRandomStaticAddress()); - int err = bt_enable(NULL); +#ifdef CONFIG_BT_BONDABLE + bt_addr_le_t idsAddr[CONFIG_BT_ID_MAX]; + size_t idsCount = CONFIG_BT_ID_MAX; + + err = bt_enable(nullptr); + + VerifyOrReturnError(err == 0, MapErrorZephyr(err)); + + settings_load(); + + bt_id_get(idsAddr, &idsCount); + + err = InitRandomStaticAddress(idsCount > 1, id); + + VerifyOrReturnError(err == 0 && id == kMatterBleIdentity, MapErrorZephyr(err)); + +#else + err = InitRandomStaticAddress(false, id); + VerifyOrReturnError(err == 0 && id == kMatterBleIdentity, MapErrorZephyr(err)); + err = bt_enable(nullptr); VerifyOrReturnError(err == 0, MapErrorZephyr(err)); +#endif // CONFIG_BT_BONDABLE + + BLEAdvertisingArbiter::Init(static_cast(id)); memset(&mConnCallbacks, 0, sizeof(mConnCallbacks)); mConnCallbacks.connected = HandleConnect; @@ -199,7 +238,13 @@ void BLEManagerImpl::DriveBLEState() { mFlags.Clear(Flags::kAdvertisingRefreshNeeded); err = StartAdvertising(); - SuccessOrExit(err); + if (err != CHIP_NO_ERROR) + { + // Return prematurely but keep the CHIPoBLE service mode enabled to allow advertising retries + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; + ChipLogError(DeviceLayer, "Could not start CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format()); + return; + } } } else @@ -207,7 +252,12 @@ void BLEManagerImpl::DriveBLEState() if (mFlags.Has(Flags::kAdvertising)) { err = StopAdvertising(); - SuccessOrExit(err); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format()); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; + return; + } } // If no connections are active unregister also CHIPoBLE GATT service @@ -224,13 +274,6 @@ void BLEManagerImpl::DriveBLEState() } } } - -exit: - if (err != CHIP_NO_ERROR) - { - ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format()); - mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; - } } struct BLEManagerImpl::ServiceData @@ -241,6 +284,13 @@ struct BLEManagerImpl::ServiceData inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() { +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + if (mCustomAdvertising.empty()) + { + ChipLogError(DeviceLayer, "mCustomAdvertising should be set when CONFIG_CHIP_CUSTOM_BLE_ADV_DATA is define"); + return CHIP_ERROR_INTERNAL; + } +#else static ServiceData serviceData; static std::array advertisingData; static std::array scanResponseData; @@ -252,21 +302,47 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val); ReturnErrorOnFailure(ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo)); - advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); - advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); - scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); - - mAdvertisingRequest.priority = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY; - mAdvertisingRequest.options = kAdvertisingOptions; - mAdvertisingRequest.minInterval = mFlags.Has(Flags::kFastAdvertisingEnabled) - ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN - : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; - mAdvertisingRequest.maxInterval = mFlags.Has(Flags::kFastAdvertisingEnabled) - ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX - : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + if (mFlags.Has(Flags::kExtendedAdvertisingEnabled)) + { + serviceData.deviceIdInfo.SetVendorId(DEVICE_HANDLE_NULL); + serviceData.deviceIdInfo.SetProductId(DEVICE_HANDLE_NULL); + serviceData.deviceIdInfo.SetExtendedAnnouncementFlag(true); + } +#endif + + advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); + advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); + scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); +#endif + + mAdvertisingRequest.priority = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY; + mAdvertisingRequest.options = kAdvertisingOptions; + + if (mFlags.Has(Flags::kFastAdvertisingEnabled)) + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX; + } +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + else if (mFlags.Has(Flags::kExtendedAdvertisingEnabled)) + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX; + } +#endif + else + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; + } +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + mAdvertisingRequest.advertisingData = mCustomAdvertising; + mAdvertisingRequest.scanResponseData = mCustomScanResponse; +#else mAdvertisingRequest.advertisingData = Span(advertisingData); mAdvertisingRequest.scanResponseData = nameSize ? Span(scanResponseData) : Span{}; - +#endif mAdvertisingRequest.onStarted = [](int rc) { if (rc == 0) { @@ -275,29 +351,53 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() else { ChipLogError(DeviceLayer, "Failed to start CHIPoBLE advertising: %d", rc); + BLEManagerImpl().StopAdvertising(); } }; return CHIP_NO_ERROR; } -CHIP_ERROR BLEManagerImpl::StartAdvertising() +CHIP_ERROR BLEManagerImpl::RegisterGattService() { - // Prepare advertising request - ReturnErrorOnFailure(PrepareAdvertisingRequest()); - - // Register dynamically CHIPoBLE GATT service + // Register CHIPoBLE GATT service if (!mFlags.Has(Flags::kChipoBleGattServiceRegister)) { int err = bt_gatt_service_register(&sChipoBleService); - if (err != 0) - ChipLogError(DeviceLayer, "Failed to register CHIPoBLE GATT service"); + { + ChipLogError(DeviceLayer, "Failed to register CHIPoBLE GATT service: %d", err); + } VerifyOrReturnError(err == 0, MapErrorZephyr(err)); - mFlags.Set(Flags::kChipoBleGattServiceRegister); } + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::UnregisterGattService() +{ + // Unregister CHIPoBLE GATT service + if (mFlags.Has(Flags::kChipoBleGattServiceRegister)) + { + int err = bt_gatt_service_unregister(&sChipoBleService); + if (err != 0) + { + ChipLogError(DeviceLayer, "Failed to unregister CHIPoBLE GATT service: %d", err); + } + + VerifyOrReturnError(err == 0, MapErrorZephyr(err)); + mFlags.Clear(Flags::kChipoBleGattServiceRegister); + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::StartAdvertising() +{ + // Prepare advertising request + ReturnErrorOnFailure(PrepareAdvertisingRequest()); + // We need to register GATT service before issuing the advertising to start + ReturnErrorOnFailure(RegisterGattService()); // Initialize C3 characteristic data #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING @@ -305,7 +405,13 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising() #endif // Request advertising - ReturnErrorOnFailure(BLEAdvertisingArbiter::InsertRequest(mAdvertisingRequest)); + CHIP_ERROR err = BLEAdvertisingArbiter::InsertRequest(mAdvertisingRequest); + if (CHIP_NO_ERROR != err) + { + // It makes not sense to keep GATT services registered after the advertising request failed + (void) UnregisterGattService(); + return err; + } // Transition to the Advertising state... if (!mFlags.Has(Flags::kAdvertising)) @@ -322,10 +428,17 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising() if (mFlags.Has(Flags::kFastAdvertisingEnabled)) { - // Start timer to change advertising interval. + // Start timer to change advertising interval from fast to slow. DeviceLayer::SystemLayer().StartTimer( System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME), - HandleBLEAdvertisementIntervalChange, this); + HandleSlowBLEAdvertisementInterval, this); + +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + // Start timer to schedule start of the extended advertising + DeviceLayer::SystemLayer().StartTimer( + System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS), + HandleExtendedBLEAdvertisementInterval, this); +#endif } } @@ -342,6 +455,10 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() mFlags.Clear(Flags::kAdvertising); mFlags.Set(Flags::kFastAdvertisingEnabled, true); +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + mFlags.Clear(Flags::kExtendedAdvertisingEnabled); +#endif + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped"); // Post a CHIPoBLEAdvertisingChange(Stopped) event. @@ -353,7 +470,12 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() } // Cancel timer event changing CHIPoBLE advertisement interval - DeviceLayer::SystemLayer().CancelTimer(HandleBLEAdvertisementIntervalChange, this); + DeviceLayer::SystemLayer().CancelTimer(HandleSlowBLEAdvertisementInterval, this); + DeviceLayer::SystemLayer().CancelTimer(HandleExtendedBLEAdvertisementInterval, this); + } + else + { + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising already stopped"); } return CHIP_NO_ERROR; @@ -361,13 +483,13 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) { - if (mFlags.Has(Flags::kAdvertisingEnabled) != val) - { - ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off"); + ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off"); - mFlags.Set(Flags::kAdvertisingEnabled, val); - PlatformMgr().ScheduleWork(DriveBLEState, 0); - } + mFlags.Set(Flags::kAdvertisingEnabled, val); + // Ensure that each enabling/disabling of the general advertising clears + // the extended mode, to make sure we always start fresh in the regular mode + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); + PlatformMgr().ScheduleWork(DriveBLEState, 0); return CHIP_NO_ERROR; } @@ -378,8 +500,14 @@ CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) { case BLEAdvertisingMode::kFastAdvertising: mFlags.Set(Flags::kFastAdvertisingEnabled, true); + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); break; case BLEAdvertisingMode::kSlowAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, false); + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); + break; + case BLEAdvertisingMode::kExtendedAdvertising: + mFlags.Set(Flags::kExtendedAdvertisingEnabled, true); mFlags.Set(Flags::kFastAdvertisingEnabled, false); break; default: @@ -410,15 +538,13 @@ CHIP_ERROR BLEManagerImpl::HandleGAPConnect(const ChipDeviceEvent * event) if (connEvent->HciResult == BT_HCI_ERR_SUCCESS) { ChipLogProgress(DeviceLayer, "BLE connection established (ConnId: 0x%02x)", bt_conn_index(connEvent->BtConn)); - mGAPConns++; + mMatterConnNum++; } else { ChipLogError(DeviceLayer, "BLE connection failed (reason: 0x%02x)", connEvent->HciResult); } - ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), CONFIG_BT_MAX_CONN); - mFlags.Set(Flags::kAdvertisingRefreshNeeded); PlatformMgr().ScheduleWork(DriveBLEState, 0); @@ -433,7 +559,10 @@ CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event) ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (reason 0x%02x)", connEvent->HciResult); - mGAPConns--; + if (mMatterConnNum > 0) + { + mMatterConnNum--; + } // If indications were enabled for this connection, record that they are now disabled and // notify the BLE Layer of a disconnect. @@ -461,8 +590,6 @@ CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event) // Unref bt_conn before scheduling DriveBLEState. bt_conn_unref(connEvent->BtConn); - ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), CONFIG_BT_MAX_CONN); - ChipDeviceEvent disconnectEvent; disconnectEvent.Type = DeviceEventType::kCHIPoBLEConnectionClosed; ReturnErrorOnFailure(PlatformMgr().PostEvent(&disconnectEvent)); @@ -485,7 +612,7 @@ CHIP_ERROR BLEManagerImpl::HandleTXCharCCCDWrite(const ChipDeviceEvent * event) if (writeEvent->Value == BT_GATT_CCC_INDICATE && SetSubscribed(writeEvent->BtConn)) { // Alert the BLE layer that CHIPoBLE "subscribe" has been received and increment the bt_conn reference counter. - HandleSubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); + HandleSubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); ChipLogProgress(DeviceLayer, "CHIPoBLE connection established (ConnId: 0x%02x, GATT MTU: %u)", bt_conn_index(writeEvent->BtConn), GetMTU(writeEvent->BtConn)); @@ -501,7 +628,7 @@ CHIP_ERROR BLEManagerImpl::HandleTXCharCCCDWrite(const ChipDeviceEvent * event) { if (UnsetSubscribed(writeEvent->BtConn)) { - HandleUnsubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); + HandleUnsubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); } } @@ -517,7 +644,7 @@ CHIP_ERROR BLEManagerImpl::HandleRXCharWrite(const ChipDeviceEvent * event) ChipLogDetail(DeviceLayer, "Write request received for CHIPoBLE RX characteristic (ConnId 0x%02x)", bt_conn_index(c1WriteEvent->BtConn)); - HandleWriteReceived(c1WriteEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX, + HandleWriteReceived(c1WriteEvent->BtConn, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_1_UUID, PacketBufferHandle::Adopt(c1WriteEvent->Data)); bt_conn_unref(c1WriteEvent->BtConn); @@ -532,7 +659,7 @@ CHIP_ERROR BLEManagerImpl::HandleTXCharComplete(const ChipDeviceEvent * event) bt_conn_index(c2IndDoneEvent->BtConn), c2IndDoneEvent->Result); // Signal the BLE Layer that the outstanding indication is complete. - HandleIndicationConfirmation(c2IndDoneEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); + HandleIndicationConfirmation(c2IndDoneEvent->BtConn, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); bt_conn_unref(c2IndDoneEvent->BtConn); return CHIP_NO_ERROR; @@ -570,12 +697,18 @@ CHIP_ERROR BLEManagerImpl::PrepareC3CharData() } #endif -void BLEManagerImpl::HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param) +void BLEManagerImpl::HandleSlowBLEAdvertisementInterval(System::Layer * layer, void * param) { BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to slow"); } +void BLEManagerImpl::HandleExtendedBLEAdvertisementInterval(System::Layer * layer, void * param) +{ + BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kExtendedAdvertising); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to extended"); +} + void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -616,14 +749,13 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) uint16_t BLEManagerImpl::_NumConnections(void) { - return mGAPConns; + return mMatterConnNum; } CHIP_ERROR BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) { ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (ConnId %02x)", bt_conn_index(conId)); - int status = bt_conn_disconnect(conId, BT_HCI_ERR_REMOTE_USER_TERM_CONN); - return (status == 0) ? CHIP_NO_ERROR : MapErrorZephyr(status); + return MapErrorZephyr(bt_conn_disconnect(conId, BT_HCI_ERR_REMOTE_USER_TERM_CONN)); } uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const @@ -662,7 +794,8 @@ CHIP_ERROR BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const Chi params->attr = &sChipoBleAttributes[kCHIPoBLE_CCC_AttributeIndex]; params->func = HandleTXIndicated; params->data = pBuf->Start(); - params->len = pBuf->DataLength(); + VerifyOrExit(CanCastTo(pBuf->DataLength()), err = CHIP_ERROR_MESSAGE_TOO_LONG); + params->len = static_cast(pBuf->DataLength()); status = bt_gatt_indicate(conId, params); VerifyOrExit(status == 0, err = MapErrorZephyr(status)); @@ -775,9 +908,16 @@ void BLEManagerImpl::HandleTXIndicated(struct bt_conn * conId, bt_gatt_indicate_ void BLEManagerImpl::HandleConnect(struct bt_conn * conId, uint8_t err) { ChipDeviceEvent event; + bt_conn_info bt_info; PlatformMgr().LockChipStack(); + sInstance.mTotalConnNum++; + ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", sInstance.mTotalConnNum, CONFIG_BT_MAX_CONN); + + VerifyOrExit(bt_conn_get_info(conId, &bt_info) == 0, ); + // Drop all callbacks incoming for the role other than peripheral, required by the Matter accessory + VerifyOrExit(bt_info.role == BT_CONN_ROLE_PERIPHERAL, ); // Don't handle BLE connecting events when it is not related to CHIPoBLE VerifyOrExit(sInstance.mFlags.Has(Flags::kChipoBleGattServiceRegister), ); @@ -794,9 +934,20 @@ void BLEManagerImpl::HandleConnect(struct bt_conn * conId, uint8_t err) void BLEManagerImpl::HandleDisconnect(struct bt_conn * conId, uint8_t reason) { ChipDeviceEvent event; + bt_conn_info bt_info; PlatformMgr().LockChipStack(); + if (sInstance.mTotalConnNum > 0) + { + sInstance.mTotalConnNum--; + } + + ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", sInstance.mTotalConnNum, CONFIG_BT_MAX_CONN); + + VerifyOrExit(bt_conn_get_info(conId, &bt_info) == 0, ); + // Drop all callbacks incoming for the role other than peripheral, required by the Matter accessory + VerifyOrExit(bt_info.role == BT_CONN_ROLE_PERIPHERAL, ); // Don't handle BLE disconnecting events when it is not related to CHIPoBLE VerifyOrExit(sInstance.mFlags.Has(Flags::kChipoBleGattServiceRegister), ); @@ -821,8 +972,21 @@ ssize_t BLEManagerImpl::HandleC3Read(struct bt_conn * conId, const struct bt_gat return 0; } + // For BLE, the max payload size is limited to UINT16_MAX since the length + // field is 2 bytes long. So, the cast to uint16_t should be fine. return bt_gatt_attr_read(conId, attr, buf, len, offset, sInstance.c3CharDataBufferHandle->Start(), - sInstance.c3CharDataBufferHandle->DataLength()); + static_cast(sInstance.c3CharDataBufferHandle->DataLength())); +} +#endif + +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA +void BLEManagerImpl::SetCustomAdvertising(Span CustomAdvertising) +{ + mCustomAdvertising = CustomAdvertising; +} +void BLEManagerImpl::SetCustomScanResponse(Span CustomScanResponse) +{ + mCustomScanResponse = CustomScanResponse; } #endif diff --git a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h index 4ae142b65cb6c0..db00009a938cea 100644 --- a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h +++ b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h @@ -92,12 +92,13 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla kAdvertisingRefreshNeeded = 0x0010, /**< The advertising state/configuration has changed, but the SoftDevice has yet to be updated. */ kChipoBleGattServiceRegister = 0x0020, /**< The system has currently CHIPoBLE GATT service registered. */ + kExtendedAdvertisingEnabled = 0x0040, /**< The application has enabled extended advertising. */ }; struct ServiceData; BitFlags mFlags; - uint16_t mGAPConns; + uint16_t mMatterConnNum; CHIPoBLEServiceMode mServiceMode; bool mSubscribedConns[CONFIG_BT_MAX_CONN]; bt_gatt_indicate_params mIndicateParams[CONFIG_BT_MAX_CONN]; @@ -106,6 +107,12 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING PacketBufferHandle c3CharDataBufferHandle; #endif + // The summarized number of Bluetooth LE connections related to the device (including these not related to Matter service). + uint16_t mTotalConnNum; +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + Span mCustomAdvertising = {}; + Span mCustomScanResponse = {}; +#endif void DriveBLEState(void); CHIP_ERROR PrepareAdvertisingRequest(); @@ -123,6 +130,8 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla bool SetSubscribed(bt_conn * conn); bool UnsetSubscribed(bt_conn * conn); uint32_t GetAdvertisingInterval(); + CHIP_ERROR RegisterGattService(); + CHIP_ERROR UnregisterGattService(); static void DriveBLEState(intptr_t arg); @@ -130,7 +139,8 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla static void HandleTXIndicated(bt_conn * conn, bt_gatt_indicate_params * attr, uint8_t err); static void HandleConnect(bt_conn * conn, uint8_t err); static void HandleDisconnect(bt_conn * conn, uint8_t reason); - static void HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param); + static void HandleSlowBLEAdvertisementInterval(System::Layer * layer, void * param); + static void HandleExtendedBLEAdvertisementInterval(System::Layer * layer, void * param); // ===== Members for internal use by the following friends. @@ -148,6 +158,10 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING static ssize_t HandleC3Read(struct bt_conn * conn, const struct bt_gatt_attr * attr, void * buf, uint16_t len, uint16_t offset); #endif +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + void SetCustomAdvertising(Span CustomAdvertising); + void SetCustomScanResponse(Span CustomScanResponse); +#endif }; /** diff --git a/third_party/nxp/nxp_matter_support b/third_party/nxp/nxp_matter_support index 7323d61dfc746a..2fff7067131f13 160000 --- a/third_party/nxp/nxp_matter_support +++ b/third_party/nxp/nxp_matter_support @@ -1 +1 @@ -Subproject commit 7323d61dfc746aff677cb40c17cfed9d43dd9c1d +Subproject commit 2fff7067131f130c560de9fa49f247022270ca55