Skip to content

Commit

Permalink
[nrf noup][zephyr] Enabled support for bonding in the BLEManager
Browse files Browse the repository at this point in the history
Currently the Zephyr BLE Manager rotates Bluetooth addresses
on every boot and it does this by creating new Bluetooth identity.
Because of that the Zephyr stack does not create default Bluetooth
ID, which is required e.g. for the bonding purposes.

Added creating two separate Bluetooth identities - for the Matter
service advertising and for the bonding purposes.

Signed-off-by: Kamil Kasperczyk <kamil.kasperczyk@nordicsemi.no>
  • Loading branch information
kkasperczyk-no committed Jan 4, 2024
1 parent 50a62b4 commit 5ae6384
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 10 deletions.
31 changes: 29 additions & 2 deletions src/platform/Zephyr/BLEAdvertisingArbiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ namespace {
// List of advertising requests ordered by priority
sys_slist_t sRequests;

bool sIsInitialized;
uint8_t sBtId;

// Cast an intrusive list node to the containing request object
const BLEAdvertisingArbiter::Request & ToRequest(const sys_snode_t * node)
{
Expand All @@ -55,8 +58,9 @@ CHIP_ERROR RestartAdvertising()
ReturnErrorOnFailure(System::MapErrorZephyr(bt_le_adv_stop()));
ReturnErrorCodeIf(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(&params, top.advertisingData.data(), top.advertisingData.size(), top.scanResponseData.data(),
top.scanResponseData.size());

Expand All @@ -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;
Expand Down Expand Up @@ -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));

Expand Down
17 changes: 17 additions & 0 deletions src/platform/Zephyr/BLEAdvertisingArbiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ 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.
* @return error If the module is already initialized.
* @return success Otherwise.
*/
CHIP_ERROR Init(uint8_t btId);

/**
* @brief Request BLE advertising
*
Expand All @@ -74,6 +85,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
Expand All @@ -94,6 +108,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.
*/
Expand Down
57 changes: 49 additions & 8 deletions src/platform/Zephyr/BLEManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/util.h>

#include <zephyr/settings/settings.h>

#include <array>

using namespace ::chip;
Expand Down Expand Up @@ -106,7 +108,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.
Expand All @@ -121,20 +129,29 @@ CHIP_ERROR InitRandomStaticAddress()
if (error)
{
ChipLogError(DeviceLayer, "Failed to create BLE address: %d", error);
return System::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 System::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
Expand All @@ -143,6 +160,9 @@ 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);
Expand All @@ -151,10 +171,31 @@ CHIP_ERROR BLEManagerImpl::_Init()

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<uint8_t>(id));

memset(&mConnCallbacks, 0, sizeof(mConnCallbacks));
mConnCallbacks.connected = HandleConnect;
mConnCallbacks.disconnected = HandleDisconnect;
Expand Down

0 comments on commit 5ae6384

Please sign in to comment.