Skip to content

Commit bf94bcc

Browse files
[zephyr] Enabled support for bonding in the BLEManager
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>
1 parent cfb9404 commit bf94bcc

File tree

3 files changed

+95
-10
lines changed

3 files changed

+95
-10
lines changed

src/platform/Zephyr/BLEAdvertisingArbiter.cpp

+29-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ namespace {
2929
// List of advertising requests ordered by priority
3030
sys_slist_t sRequests;
3131

32+
bool sIsInitialized;
33+
uint8_t sBtId;
34+
3235
// Cast an intrusive list node to the containing request object
3336
const BLEAdvertisingArbiter::Request & ToRequest(const sys_snode_t * node)
3437
{
@@ -55,8 +58,9 @@ CHIP_ERROR RestartAdvertising()
5558
ReturnErrorOnFailure(System::MapErrorZephyr(bt_le_adv_stop()));
5659
ReturnErrorCodeIf(sys_slist_is_empty(&sRequests), CHIP_NO_ERROR);
5760

58-
const Request & top = ToRequest(sys_slist_peek_head(&sRequests));
59-
const bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr);
61+
const Request & top = ToRequest(sys_slist_peek_head(&sRequests));
62+
bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr);
63+
params.id = sBtId;
6064
const int result = bt_le_adv_start(&params, top.advertisingData.data(), top.advertisingData.size(), top.scanResponseData.data(),
6165
top.scanResponseData.size());
6266

@@ -70,8 +74,26 @@ CHIP_ERROR RestartAdvertising()
7074

7175
} // namespace
7276

77+
CHIP_ERROR Init(uint8_t btId)
78+
{
79+
if (sIsInitialized)
80+
{
81+
return CHIP_ERROR_INCORRECT_STATE;
82+
}
83+
84+
sBtId = btId;
85+
sIsInitialized = true;
86+
87+
return CHIP_NO_ERROR;
88+
}
89+
7390
CHIP_ERROR InsertRequest(Request & request)
7491
{
92+
if (!sIsInitialized)
93+
{
94+
return CHIP_ERROR_INCORRECT_STATE;
95+
}
96+
7597
CancelRequest(request);
7698

7799
sys_snode_t * prev = nullptr;
@@ -109,6 +131,11 @@ CHIP_ERROR InsertRequest(Request & request)
109131

110132
void CancelRequest(Request & request)
111133
{
134+
if (!sIsInitialized)
135+
{
136+
return;
137+
}
138+
112139
const bool isTopPriority = (sys_slist_peek_head(&sRequests) == &request);
113140
VerifyOrReturn(sys_slist_find_and_remove(&sRequests, &request));
114141

src/platform/Zephyr/BLEAdvertisingArbiter.h

+17
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@ struct Request : public sys_snode_t
6161
OnAdvertisingStopped onStopped; ///< (Optional) Callback invoked when the request stops being top-priority.
6262
};
6363

64+
/**
65+
* @brief Initialize BLE advertising arbiter
66+
*
67+
* @note This method must be called before trying to insert or cancel any requests.
68+
*
69+
* @param btId Local Bluetooth LE identifier to be used for the advertising parameters.
70+
* @return error If the module is already initialized.
71+
* @return success Otherwise.
72+
*/
73+
CHIP_ERROR Init(uint8_t btId);
74+
6475
/**
6576
* @brief Request BLE advertising
6677
*
@@ -74,6 +85,9 @@ struct Request : public sys_snode_t
7485
* @note This method does not take ownership of the request object so the object
7586
* must not get destroyed before it is cancelled.
7687
*
88+
* @note The arbiter module has to be initialized using Init() method before
89+
* invoking this method.
90+
*
7791
* @param request Reference to advertising request that contains priority and
7892
* other advertising parameters.
7993
* @return error If the request is top-priority and failed to restart the
@@ -94,6 +108,9 @@ CHIP_ERROR InsertRequest(Request & request);
94108
* An attempt to cancel a request that has not been registered at the
95109
* advertising arbiter is a no-op. That is, it returns immediately.
96110
*
111+
* @note The arbiter module has to be initialized using Init() method before
112+
* invoking this method.
113+
*
97114
* @param request Reference to advertising request that contains priority and
98115
* other advertising parameters.
99116
*/

src/platform/Zephyr/BLEManagerImpl.cpp

+49-8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
#include <zephyr/sys/byteorder.h>
4545
#include <zephyr/sys/util.h>
4646

47+
#include <zephyr/settings/settings.h>
48+
4749
#include <array>
4850

4951
using namespace ::chip;
@@ -107,7 +109,13 @@ bt_gatt_service sChipoBleService = BT_GATT_SERVICE(sChipoBleAttributes);
107109
// This value should be adjusted accordingly if the service declaration changes.
108110
constexpr int kCHIPoBLE_CCC_AttributeIndex = 3;
109111

110-
CHIP_ERROR InitRandomStaticAddress()
112+
#ifdef CONFIG_BT_BONDABLE
113+
constexpr uint8_t kMatterBleIdentity = 1;
114+
#else
115+
constexpr uint8_t kMatterBleIdentity = 0;
116+
#endif // CONFIG_BT_BONDABLE
117+
118+
int InitRandomStaticAddress(bool idPresent, int & id)
111119
{
112120
// Generate a random static address for the default identity.
113121
// This must be done before bt_enable() as after that updating the default identity is not possible.
@@ -122,20 +130,29 @@ CHIP_ERROR InitRandomStaticAddress()
122130
if (error)
123131
{
124132
ChipLogError(DeviceLayer, "Failed to create BLE address: %d", error);
125-
return System::MapErrorZephyr(error);
133+
return error;
126134
}
127135

128-
error = bt_id_create(&addr, nullptr);
136+
if (!idPresent)
137+
{
138+
id = bt_id_create(&addr, nullptr);
139+
}
140+
#if CONFIG_BT_ID_MAX == 2
141+
else
142+
{
143+
id = bt_id_reset(1, &addr, nullptr);
144+
}
145+
#endif // CONFIG_BT_BONDABLE
129146

130-
if (error < 0)
147+
if (id < 0)
131148
{
132149
ChipLogError(DeviceLayer, "Failed to create BLE identity: %d", error);
133-
return System::MapErrorZephyr(error);
150+
return id;
134151
}
135152

136153
ChipLogProgress(DeviceLayer, "BLE address: %02X:%02X:%02X:%02X:%02X:%02X", addr.a.val[5], addr.a.val[4], addr.a.val[3],
137154
addr.a.val[2], addr.a.val[1], addr.a.val[0]);
138-
return CHIP_NO_ERROR;
155+
return 0;
139156
}
140157

141158
} // unnamed namespace
@@ -144,17 +161,41 @@ BLEManagerImpl BLEManagerImpl::sInstance;
144161

145162
CHIP_ERROR BLEManagerImpl::_Init()
146163
{
164+
int err = 0;
165+
int id = 0;
166+
147167
mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
148168
mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
149169
mFlags.Set(Flags::kFastAdvertisingEnabled, true);
150170
mGAPConns = 0;
151171

152172
memset(mSubscribedConns, 0, sizeof(mSubscribedConns));
153173

154-
ReturnErrorOnFailure(InitRandomStaticAddress());
155-
int err = bt_enable(NULL);
174+
#ifdef CONFIG_BT_BONDABLE
175+
bt_addr_le_t idsAddr[CONFIG_BT_ID_MAX];
176+
size_t idsCount = CONFIG_BT_ID_MAX;
177+
178+
err = bt_enable(nullptr);
179+
156180
VerifyOrReturnError(err == 0, MapErrorZephyr(err));
157181

182+
settings_load();
183+
184+
bt_id_get(idsAddr, &idsCount);
185+
186+
err = InitRandomStaticAddress(idsCount > 1, id);
187+
188+
VerifyOrReturnError(err == 0 && id == kMatterBleIdentity, MapErrorZephyr(err));
189+
190+
#else
191+
err = InitRandomStaticAddress(false, id);
192+
VerifyOrReturnError(err == 0 && id == kMatterBleIdentity, MapErrorZephyr(err));
193+
err = bt_enable(nullptr);
194+
VerifyOrReturnError(err == 0, MapErrorZephyr(err));
195+
#endif // CONFIG_BT_BONDABLE
196+
197+
BLEAdvertisingArbiter::Init(static_cast<uint8_t>(id));
198+
158199
memset(&mConnCallbacks, 0, sizeof(mConnCallbacks));
159200
mConnCallbacks.connected = HandleConnect;
160201
mConnCallbacks.disconnected = HandleDisconnect;

0 commit comments

Comments
 (0)