[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; uint16_t advertisementLen = 0;
uint8_t *advertisementData = nullptr; uint8_t *advertisementData = nullptr;
VerifyOrExit(mBleState == kAdvertising); VerifyOrExit(mBleState != kStopped);
SuccessOrExit(error = otPlatBleGetAdvertisementBuffer(&GetInstance(), &advertisementData)); SuccessOrExit(error = otPlatBleGetAdvertisementBuffer(&GetInstance(), &advertisementData));
SuccessOrExit(error = Get<MeshCoP::TcatAgent>().GetAdvertisementData(advertisementLen, 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: exit:
return error; return error;
@@ -53,6 +53,9 @@ send "thread start\n"
expect_line "\tTYPE:\tRESPONSE_W_STATUS" expect_line "\tTYPE:\tRESPONSE_W_STATUS"
expect_line "\tVALUE:\t0x00" expect_line "\tVALUE:\t0x00"
send "disconnect\n"
expect_line "Done"
dispose_tcat_client 1 dispose_tcat_client 1
switch_node 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; } OT_TOOL_WEAK otError otPlatSetMcuPowerState(otInstance *aInstance, otPlatMcuPowerState aState) { return OT_ERROR_NONE; }
#endif // OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL #endif // OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
#ifdef OPENTHREAD_CONFIG_BLE_TCAT_ENABLE #ifdef OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
uint8_t sPlatBleLastAdvSetData[OT_TCAT_ADVERTISEMENT_MAX_LEN];
uint16_t sPlatBleLastAdvSetDataLen = 0;
otError otPlatBleEnable(otInstance *aInstance) otError otPlatBleEnable(otInstance *aInstance)
{ {
OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aInstance);
@@ -875,17 +879,19 @@ bool otPlatBleSupportsMultiRadio(otInstance *aInstance)
otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen) otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen)
{ {
OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aAdvertisementData); if (aAdvertisementData == nullptr || aAdvertisementLen > OT_TCAT_ADVERTISEMENT_MAX_LEN)
OT_UNUSED_VARIABLE(aAdvertisementLen); {
return OT_ERROR_INVALID_ARGS;
}
memcpy(sPlatBleLastAdvSetData, aAdvertisementData, aAdvertisementLen);
sPlatBleLastAdvSetDataLen = aAdvertisementLen;
return OT_ERROR_NONE; return OT_ERROR_NONE;
} }
otError otPlatBleGapAdvUpdateData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen) otError otPlatBleGapAdvUpdateData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen)
{ {
OT_UNUSED_VARIABLE(aInstance); return otPlatBleGapAdvSetData(aInstance, aAdvertisementData, aAdvertisementLen);
OT_UNUSED_VARIABLE(aAdvertisementData);
OT_UNUSED_VARIABLE(aAdvertisementLen);
return OT_ERROR_NONE;
} }
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE #endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
+12
View File
@@ -57,4 +57,16 @@ ot::Instance *testInitAdditionalInstance(uint8_t id);
#endif #endif
void testFreeInstance(otInstance *aInstance); 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_ #endif // OT_UNIT_TEST_PLATFORM_H_
+44
View File
@@ -36,6 +36,7 @@
#include <openthread/ble_secure.h> #include <openthread/ble_secure.h>
#include "cli/cli_dataset.hpp" #include "cli/cli_dataset.hpp"
#include "radio/ble_secure.hpp"
#define OT_TCAT_X509_CERT \ #define OT_TCAT_X509_CERT \
"-----BEGIN CERTIFICATE-----\n" \ "-----BEGIN CERTIFICATE-----\n" \
@@ -267,6 +268,8 @@ static Instance *TestInitInstanceTcat(void)
memcpy(&sCommExtPanId, &kExtPanId, sizeof(sCommExtPanId)); memcpy(&sCommExtPanId, &kExtPanId, sizeof(sCommExtPanId));
memcpy(&sCommAuth, &kCommCert1AuthField, sizeof(sCommAuth)); memcpy(&sCommAuth, &kCommCert1AuthField, sizeof(sCommAuth));
memcpy(&sDeviceAuth, &kDeviceCert1AuthField, sizeof(sDeviceAuth)); memcpy(&sDeviceAuth, &kDeviceCert1AuthField, sizeof(sDeviceAuth));
sPlatBleLastAdvSetDataLen = 0;
memset(sPlatBleLastAdvSetData, 0, OT_TCAT_ADVERTISEMENT_MAX_LEN);
return instance; return instance;
} }
@@ -336,6 +339,46 @@ void TestTcatConnectionAndCertAttributes(void)
testFreeInstance(instance); 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 class UnitTester
{ {
private: private:
@@ -834,6 +877,7 @@ int main(void)
ot::MeshCoP::UnitTester::TestTcatCommissioner1AuthWithDeviceRequirements(); ot::MeshCoP::UnitTester::TestTcatCommissioner1AuthWithDeviceRequirements();
ot::MeshCoP::UnitTester::TestTcatCommissioner2AuthWithDeviceRequirements(); ot::MeshCoP::UnitTester::TestTcatCommissioner2AuthWithDeviceRequirements();
ot::MeshCoP::UnitTester::TestTcatCommissioner4AuthWithExistingPartialDataset(); ot::MeshCoP::UnitTester::TestTcatCommissioner4AuthWithExistingPartialDataset();
ot::MeshCoP::TestTcatAdvertisementUpdates();
printf("All tests passed\n"); printf("All tests passed\n");
#else #else
printf("TCAT feature is not enabled\n"); printf("TCAT feature is not enabled\n");