Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions config/nrfconnect/chip-module/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -568,4 +568,13 @@ config CHIP_QSPI_NOR_POWER_MANAGEMENT_SUPPORT
Enables management of nRF QSPI NOR external flash power state
transitions during Matter operations.

config CHIP_BLE_MULTI_IDENTITY_SUPPORT
bool "Support for multiple BLE identities"
depends on BT
help
Enables support for multiple BLE identities, allowing the device to maintain separate BLE
advertisements and connections for different purposes. When this option is enabled, Matter
connection handlers will ignore events for connections established with a different local
identity.

endif # CHIP
48 changes: 39 additions & 9 deletions src/platform/Zephyr/BLEAdvertisingArbiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,32 @@ namespace {
// List of advertising requests ordered by priority
sys_slist_t sRequests;

bool sIsInitialized = false;
bool sWasDisconnection = false;
uint8_t sBtId = 0;
bool sIsInitialized = false;
atomic_t sRestart = ATOMIC_INIT(0);
uint8_t sBtId = 0;

// Cast an intrusive list node to the containing request object
const BLEAdvertisingArbiter::Request & ToRequest(const sys_snode_t * node)
{
return *static_cast<const BLEAdvertisingArbiter::Request *>(node);
}

#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT

// Check if connection identity matches the identity used for advertising
bool IsOurIdentity(const bt_conn * conn)
{
VerifyOrReturnValue(conn, false);

bt_conn_info info{};
const int err = bt_conn_get_info(conn, &info);
VerifyOrReturnValue(err == 0, false);

return info.id == sBtId;
}

#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT

// Notify application about stopped advertising if the callback has been provided
void NotifyAdvertisingStopped(const sys_snode_t * node)
{
Expand Down Expand Up @@ -81,24 +97,38 @@ CHIP_ERROR RestartAdvertising()
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
.disconnected = [](struct bt_conn * conn, uint8_t reason) { sWasDisconnection = true; },
.disconnected =
[](struct bt_conn * conn, uint8_t reason) {
#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
// Ignore disconnections from other identities
VerifyOrReturn(IsOurIdentity(conn));
#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
atomic_set(&sRestart, 1);
},
.recycled =
[]() {
// In this callback the connection object was returned to the pool and we can try to re-start connectable
// advertising, but only if the disconnection was detected.
if (sWasDisconnection)
// advertising, but only if the disconnection was detected or a previous restart attempt failed.
constexpr atomic_val_t oldValue = 1;
constexpr atomic_val_t newValue = 0;
const bool shouldRestart = atomic_cas(&sRestart, oldValue, newValue);

if (shouldRestart)
{

SystemLayer().ScheduleLambda([] {
if (!sys_slist_is_empty(&sRequests))
{
// Starting from Zephyr 4.0 Automatic advertiser resumption is deprecated,
// so the BLE Advertising Arbiter has to take over the responsibility of restarting the advertiser.
// Restart advertising in this callback if there are pending requests after the connection is released.
RestartAdvertising();
const CHIP_ERROR result = RestartAdvertising();
if (result != CHIP_NO_ERROR)
{
atomic_set(&sRestart, 1);
}
}
});
// Reset the disconnection flag to avoid restarting advertising multiple times
sWasDisconnection = false;
}
},
};
Expand Down
39 changes: 39 additions & 0 deletions src/platform/Zephyr/BLEManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,21 @@ constexpr uint8_t kMatterBleIdentity = 1;
constexpr uint8_t kMatterBleIdentity = 0;
#endif // CONFIG_BT_BONDABLE

#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT

bool IsMatterIdentity(const bt_conn * conn)
{
VerifyOrReturnValue(conn, false);

bt_conn_info info{};
const int err = bt_conn_get_info(conn, &info);
VerifyOrReturnValue(err == 0, false);

return info.id == kMatterBleIdentity;
}

#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT

int InitRandomStaticAddress(bool idPresent, int & id)
{
// Generate a random static address for the default identity.
Expand Down Expand Up @@ -877,6 +892,10 @@ bool BLEManagerImpl::UnsetSubscribed(bt_conn * conn)
ssize_t BLEManagerImpl::HandleRXWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, const void * buf, uint16_t len,
uint16_t offset, uint8_t flags)
{
#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
VerifyOrReturnValue(IsMatterIdentity(conId), BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED));
#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT

ChipDeviceEvent event;
PacketBufferHandle packetBuf = PacketBufferHandle::NewWithData(buf, len);

Expand All @@ -901,6 +920,10 @@ ssize_t BLEManagerImpl::HandleRXWrite(struct bt_conn * conId, const struct bt_ga

ssize_t BLEManagerImpl::HandleTXCCCWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, uint16_t value)
{
#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
VerifyOrReturnValue(IsMatterIdentity(conId), BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED));
#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT

ChipDeviceEvent event;

if (value != BT_GATT_CCC_INDICATE && value != 0)
Expand All @@ -919,6 +942,10 @@ ssize_t BLEManagerImpl::HandleTXCCCWrite(struct bt_conn * conId, const struct bt

void BLEManagerImpl::HandleTXIndicated(struct bt_conn * conId, bt_gatt_indicate_params *, uint8_t err)
{
#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
VerifyOrReturn(IsMatterIdentity(conId));
#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT

ChipDeviceEvent event;

event.Type = DeviceEventType::kPlatformZephyrBleC2IndDoneEvent;
Expand All @@ -939,6 +966,10 @@ void BLEManagerImpl::HandleConnect(struct bt_conn * conId, uint8_t err)
ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", sInstance.mTotalConnNum, CONFIG_BT_MAX_CONN);

VerifyOrExit(bt_conn_get_info(conId, &bt_info) == 0, );
#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
// Drop all callbacks incoming for the identity other than the one used for advertising
VerifyOrExit(bt_info.id == kMatterBleIdentity, );
#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
// 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
Expand Down Expand Up @@ -969,6 +1000,10 @@ void BLEManagerImpl::HandleDisconnect(struct bt_conn * conId, uint8_t reason)
ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", sInstance.mTotalConnNum, CONFIG_BT_MAX_CONN);

VerifyOrExit(bt_conn_get_info(conId, &bt_info) == 0, );
#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
// Drop all callbacks incoming for the identity other than the one used for advertising
VerifyOrExit(bt_info.id == kMatterBleIdentity, );
#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
// 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
Expand All @@ -988,6 +1023,10 @@ void BLEManagerImpl::HandleDisconnect(struct bt_conn * conId, uint8_t reason)
ssize_t BLEManagerImpl::HandleC3Read(struct bt_conn * conId, const struct bt_gatt_attr * attr, void * buf, uint16_t len,
uint16_t offset)
{
#ifdef CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT
VerifyOrReturnValue(IsMatterIdentity(conId), 0);
#endif // CONFIG_CHIP_BLE_MULTI_IDENTITY_SUPPORT

ChipLogDetail(DeviceLayer, "Read request received for CHIPoBLE C3 (ConnId 0x%02x)", bt_conn_index(conId));

if (sInstance.c3CharDataBufferHandle.IsNull())
Expand Down
Loading