Skip to content

Commit

Permalink
Custom BLE data at application layer (project-chip#36857)
Browse files Browse the repository at this point in the history
* [Zephyr] Add support to custom BLE advertising data at application layer

Signed-off-by: Martin Girardot <[email protected]>

* [NXP][RTs] Add support to custom advertising data at application layer

Signed-off-by: Martin Girardot <[email protected]>

* [NXP][examples[common] Add support to custom advertising data at application layer

Signed-off-by: Martin Girardot <[email protected]>

* [NXP] Update nxp matter support submodule

Signed-off-by: Martin Girardot <[email protected]>

* Restyled by whitespace

* Restyled by clang-format

* Restyled by gn

* [NXP] update BLE include path

Signed-off-by: Martin Girardot <[email protected]>

* Restyled by clang-format

---------

Signed-off-by: Martin Girardot <[email protected]>
Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
Martin-NXP and restyled-commits authored Dec 17, 2024
1 parent 4e44586 commit e394994
Show file tree
Hide file tree
Showing 23 changed files with 545 additions and 82 deletions.
7 changes: 7 additions & 0 deletions config/zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions examples/all-clusters-app/nxp/common/main/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint16_t>(emberAfFixedEndpointCount() - 1)), false);
Expand Down
4 changes: 4 additions & 0 deletions examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
11 changes: 11 additions & 0 deletions examples/thermostat/nxp/common/main/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#include <app/InteractionModelEngine.h>
#include <app/util/attribute-storage.h>

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include "BLEApplicationManager.h"
#endif

using namespace chip;

void ThermostatApp::AppTask::PreInitMatterStack()
Expand All @@ -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());
}

Expand Down
100 changes: 100 additions & 0 deletions examples/thermostat/nxp/common/main/BleZephyrManagerApp.cpp
Original file line number Diff line number Diff line change
@@ -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 <platform/internal/CHIPDeviceLayerInternal.h>

#include "BLEManagerImpl.h"
#include <ble/Ble.h>
#include <platform/ConfigurationManager.h>
#include <zephyr/bluetooth/gatt.h>

#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<bt_data, 3> advertisingData;
std::array<bt_data, 1> 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<uint8_t>(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<bt_data>(advertisingData));
chip::DeviceLayer::Internal::BLEMgrImpl().SetCustomScanResponse(Span<bt_data>(scanResponseData));
}
16 changes: 16 additions & 0 deletions examples/thermostat/nxp/rt/rt1060/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions examples/thermostat/nxp/rt/rt1060/args.gni
Original file line number Diff line number Diff line change
Expand Up @@ -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")
16 changes: 16 additions & 0 deletions examples/thermostat/nxp/rt/rt1170/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions examples/thermostat/nxp/rt/rt1170/args.gni
Original file line number Diff line number Diff line change
Expand Up @@ -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")
16 changes: 16 additions & 0 deletions examples/thermostat/nxp/rt/rw61x/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions examples/thermostat/nxp/rt/rw61x/args.gni
Original file line number Diff line number Diff line change
Expand Up @@ -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")
11 changes: 11 additions & 0 deletions examples/thermostat/nxp/zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions examples/thermostat/nxp/zephyr/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
31 changes: 27 additions & 4 deletions src/platform/Zephyr/BLEManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bt_data, 2> advertisingData;
static std::array<bt_data, 1> scanResponseData;
Expand All @@ -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;
Expand All @@ -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<bt_data>(advertisingData);
mAdvertisingRequest.scanResponseData = nameSize ? Span<bt_data>(scanResponseData) : Span<bt_data>{};

#endif
mAdvertisingRequest.onStarted = [](int rc) {
if (rc == 0)
{
Expand Down Expand Up @@ -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<bt_data> CustomAdvertising)
{
mCustomAdvertising = CustomAdvertising;
}
void BLEManagerImpl::SetCustomScanResponse(Span<bt_data> CustomScanResponse)
{
mCustomScanResponse = CustomScanResponse;
}
#endif

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
Expand Down
8 changes: 8 additions & 0 deletions src/platform/Zephyr/BLEManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<bt_data> mCustomAdvertising = {};
Span<bt_data> mCustomScanResponse = {};
#endif

void DriveBLEState(void);
CHIP_ERROR PrepareAdvertisingRequest();
Expand Down Expand Up @@ -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<bt_data> CustomAdvertising);
void SetCustomScanResponse(Span<bt_data> CustomScanResponse);
#endif
};

/**
Expand Down
Loading

0 comments on commit e394994

Please sign in to comment.