[tcat][ble] Fix BLE advertisement contents after Commissioner disconnect (#12913)

This fixes the issue observed in tests, that the BLE advertisement contents (flags) were not updated
after a TCAT Commissioner disconnects. A unit test is added for BLE advertisement contents to
validate the advertisement data changes.

It also adds an explicit 'disconnect' CLI command to the TCAT expect tests, which wasn't tested
before.
This commit is contained in:
Esko Dijk
2026-06-08 14:47:21 -07:00
committed by Jonathan Hui
parent fee7292f15
commit 9403edeaaf
5 changed files with 82 additions and 8 deletions
+11 -2
View File
@@ -196,10 +196,19 @@ Error BleSecure::NotifyAdvertisementChanged(void)
uint16_t advertisementLen = 0;
uint8_t *advertisementData = nullptr;
VerifyOrExit(mBleState == kAdvertising);
VerifyOrExit(mBleState != kStopped);
SuccessOrExit(error = otPlatBleGetAdvertisementBuffer(&GetInstance(), &advertisementData));
SuccessOrExit(error = Get<MeshCoP::TcatAgent>().GetAdvertisementData(advertisementLen, advertisementData));
SuccessOrExit(error = otPlatBleGapAdvUpdateData(&GetInstance(), advertisementData, advertisementLen));
if (mBleState == kAdvertising)
{
SuccessOrExit(error = otPlatBleGapAdvUpdateData(&GetInstance(), advertisementData, advertisementLen));
}
else
{
// Any other state: update buffered data for when advertising resumes.
SuccessOrExit(error = otPlatBleGapAdvSetData(&GetInstance(), advertisementData, advertisementLen));
}
exit:
return error;
@@ -53,6 +53,9 @@ send "thread start\n"
expect_line "\tTYPE:\tRESPONSE_W_STATUS"
expect_line "\tVALUE:\t0x00"
send "disconnect\n"
expect_line "Done"
dispose_tcat_client 1
switch_node 1
+12 -6
View File
@@ -801,6 +801,10 @@ OT_TOOL_WEAK otPlatMcuPowerState otPlatGetMcuPowerState(otInstance *aInstance) {
OT_TOOL_WEAK otError otPlatSetMcuPowerState(otInstance *aInstance, otPlatMcuPowerState aState) { return OT_ERROR_NONE; }
#endif // OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
#ifdef OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
uint8_t sPlatBleLastAdvSetData[OT_TCAT_ADVERTISEMENT_MAX_LEN];
uint16_t sPlatBleLastAdvSetDataLen = 0;
otError otPlatBleEnable(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -875,17 +879,19 @@ bool otPlatBleSupportsMultiRadio(otInstance *aInstance)
otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aAdvertisementData);
OT_UNUSED_VARIABLE(aAdvertisementLen);
if (aAdvertisementData == nullptr || aAdvertisementLen > OT_TCAT_ADVERTISEMENT_MAX_LEN)
{
return OT_ERROR_INVALID_ARGS;
}
memcpy(sPlatBleLastAdvSetData, aAdvertisementData, aAdvertisementLen);
sPlatBleLastAdvSetDataLen = aAdvertisementLen;
return OT_ERROR_NONE;
}
otError otPlatBleGapAdvUpdateData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aAdvertisementData);
OT_UNUSED_VARIABLE(aAdvertisementLen);
return OT_ERROR_NONE;
return otPlatBleGapAdvSetData(aInstance, aAdvertisementData, aAdvertisementLen);
}
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
+12
View File
@@ -57,4 +57,16 @@ ot::Instance *testInitAdditionalInstance(uint8_t id);
#endif
void testFreeInstance(otInstance *aInstance);
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#include <openthread/tcat.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint8_t sPlatBleLastAdvSetData[OT_TCAT_ADVERTISEMENT_MAX_LEN];
extern uint16_t sPlatBleLastAdvSetDataLen;
#ifdef __cplusplus
}
#endif
#endif
#endif // OT_UNIT_TEST_PLATFORM_H_
+44
View File
@@ -36,6 +36,7 @@
#include <openthread/ble_secure.h>
#include "cli/cli_dataset.hpp"
#include "radio/ble_secure.hpp"
#define OT_TCAT_X509_CERT \
"-----BEGIN CERTIFICATE-----\n" \
@@ -267,6 +268,8 @@ static Instance *TestInitInstanceTcat(void)
memcpy(&sCommExtPanId, &kExtPanId, sizeof(sCommExtPanId));
memcpy(&sCommAuth, &kCommCert1AuthField, sizeof(sCommAuth));
memcpy(&sDeviceAuth, &kDeviceCert1AuthField, sizeof(sDeviceAuth));
sPlatBleLastAdvSetDataLen = 0;
memset(sPlatBleLastAdvSetData, 0, OT_TCAT_ADVERTISEMENT_MAX_LEN);
return instance;
}
@@ -336,6 +339,46 @@ void TestTcatConnectionAndCertAttributes(void)
testFreeInstance(instance);
}
void TestTcatAdvertisementUpdates(void)
{
TestBleSecure ble;
Instance *instance = TestInitInstanceTcat();
uint8_t advDataSnapshot[OT_TCAT_ADVERTISEMENT_MAX_LEN];
uint16_t advDataSnapshotLen;
VerifyOrQuit(sPlatBleLastAdvSetDataLen == 0, "Adv data should be unset before BleSecure start");
SuccessOrQuit(otBleSecureStart(instance, HandleBleSecureConnect, nullptr, true, &ble));
SuccessOrQuit(otBleSecureTcatStart(instance, nullptr));
VerifyOrQuit(sPlatBleLastAdvSetDataLen > 0, "Adv data should be set after BleSecure start");
advDataSnapshotLen = sPlatBleLastAdvSetDataLen;
memcpy(advDataSnapshot, sPlatBleLastAdvSetData, advDataSnapshotLen);
otPlatBleGapOnConnected(instance, kConnectionId);
SuccessOrQuit(otBleSecureConnect(instance));
// BLE connect and initiating TLS does not change the adv data.
VerifyOrQuit(sPlatBleLastAdvSetDataLen == advDataSnapshotLen &&
memcmp(sPlatBleLastAdvSetData, advDataSnapshot, advDataSnapshotLen) == 0,
"Adv data changed unexpectedly after BLE connect");
advDataSnapshotLen = sPlatBleLastAdvSetDataLen;
memcpy(advDataSnapshot, sPlatBleLastAdvSetData, advDataSnapshotLen);
// Commissioner sets dataset, then disconnects
instance->Get<ActiveDatasetManager>().SaveLocal(sPartialDataset);
otBleSecureDisconnect(instance);
// Adv is changed due to the partial dataset now being advertised in the S flag.
VerifyOrQuit(sPlatBleLastAdvSetDataLen == advDataSnapshotLen, "Adv data length changed unexpectedly");
VerifyOrQuit(memcmp(sPlatBleLastAdvSetData, advDataSnapshot, advDataSnapshotLen) != 0,
"Adv data did not change after disconnect, which it should due to S flag");
otBleSecureStop(instance);
testFreeInstance(instance);
}
class UnitTester
{
private:
@@ -834,6 +877,7 @@ int main(void)
ot::MeshCoP::UnitTester::TestTcatCommissioner1AuthWithDeviceRequirements();
ot::MeshCoP::UnitTester::TestTcatCommissioner2AuthWithDeviceRequirements();
ot::MeshCoP::UnitTester::TestTcatCommissioner4AuthWithExistingPartialDataset();
ot::MeshCoP::TestTcatAdvertisementUpdates();
printf("All tests passed\n");
#else
printf("TCAT feature is not enabled\n");