[tcat] implement tcat advertisement (#9858)

Commit introduces implementation of TCAT advertisement over BLE
compliant with Thread 1.3.1 specification.
This commit is contained in:
Przemysław Bida
2024-06-06 20:26:59 +02:00
committed by GitHub
parent cdeb02b035
commit 398df8c408
16 changed files with 587 additions and 50 deletions
+33
View File
@@ -35,6 +35,7 @@
#include <openthread/platform/ble.h>
#include "openthread/error.h"
#include "openthread/tcat.h"
#include "utils/code_utils.h"
#define PLAT_BLE_MSG_DATA_MAX 2048
@@ -87,6 +88,16 @@ static void deinitFds(void)
}
}
otError otPlatBleGetAdvertisementBuffer(otInstance *aInstance, uint8_t **aAdvertisementBuffer)
{
OT_UNUSED_VARIABLE(aInstance);
static uint8_t sAdvertisementBuffer[OT_TCAT_ADVERTISEMENT_MAX_LEN];
*aAdvertisementBuffer = sAdvertisementBuffer;
return OT_ERROR_NONE;
}
otError otPlatBleEnable(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -214,3 +225,25 @@ OT_TOOL_WEAK void otPlatBleGattServerOnWriteRequest(otInstance *aIns
* which is available in FTD/MTD library.
*/
}
void otPlatBleGetLinkCapabilities(otInstance *aInstance, otBleLinkCapabilities *aBleLinkCapabilities)
{
OT_UNUSED_VARIABLE(aInstance);
aBleLinkCapabilities->mGattNotifications = 1;
aBleLinkCapabilities->mL2CapDirect = 0;
aBleLinkCapabilities->mRsv = 0;
}
otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aAdvertisementData);
OT_UNUSED_VARIABLE(aAdvertisementLen);
return OT_ERROR_NONE;
}
bool otPlatBleSupportsMultiRadio(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return false;
}
+12 -1
View File
@@ -109,6 +109,17 @@ otError otBleSecureStart(otInstance *aInstance,
bool aTlvMode,
void *aContext);
/**
* Sets TCAT vendor info
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method call.
*
* @retval OT_ERROR_NONE Successfully set value.
* @retval OT_ERROR_INVALID_ARGS Value not set.
*/
otError otBleSecureSetTcatVendorInfo(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo);
/**
* Enables the TCAT protocol over BLE Secure.
*
@@ -122,7 +133,7 @@ otError otBleSecureStart(otInstance *aInstance,
* @retval OT_ERROR_INVALID_STATE The BLE function has not been started or line mode is not selected.
*
*/
otError otBleSecureTcatStart(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo, otHandleTcatJoin aHandler);
otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aHandler);
/**
* Stops the BLE Secure server.
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (418)
#define OPENTHREAD_API_VERSION (419)
/**
* @addtogroup api-instance
+65
View File
@@ -104,6 +104,23 @@ extern "C" {
#define OT_BLE_DEFAULT_POWER 0
/**
* TOBLE service UUID
*/
#define OT_TOBLE_SERVICE_UUID 0xfffb
/**
* Represent BLE link capabilities
*
*/
typedef struct otBleLinkCapabilities
{
uint8_t mRsv : 6;
bool mL2CapDirect : 1;
bool mGattNotifications : 1;
} otBleLinkCapabilities;
/**
* Represents a BLE packet.
*
@@ -151,6 +168,38 @@ otError otPlatBleDisable(otInstance *aInstance);
/****************************************************************************
* @section Bluetooth Low Energy GAP.
***************************************************************************/
/**
* Gets BLE Advertising buffer.
*
* @note This function shall be used only for BLE Peripheral role.
* Returned buffer should have enough space to fit max advertisement
* defined by specification.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aAdvertisementData The formatted TCAT advertisement frame.
* @param[in] aAdvertisementLen The TCAT advertisement frame length.
*
* @retval OT_ERROR_NONE Advertising procedure has been started.
* @retval OT_ERROR_NO_BUFS No bufferspace available.
*
*/
otError otPlatBleGetAdvertisementBuffer(otInstance *aInstance, uint8_t **aAdvertisementBuffer);
/**
* Sets BLE Advertising data.
*
* @note This function shall be used only for BLE Peripheral role.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aAdvertisementData The formatted TCAT advertisement frame.
* @param[in] aAdvertisementLen The TCAT advertisement frame length.
*
* @retval OT_ERROR_NONE Advertising procedure has been started.
* @retval OT_ERROR_INVALID_STATE BLE Device is in invalid state.
* @retval OT_ERROR_INVALID_ARGS Invalid value has been supplied.
*
*/
otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen);
/**
* Starts BLE Advertising procedure.
@@ -281,6 +330,22 @@ otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle, con
*/
extern void otPlatBleGattServerOnWriteRequest(otInstance *aInstance, uint16_t aHandle, const otBleRadioPacket *aPacket);
/**
* Function to retrieve from platform BLE link capabilities.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[out] aBleLinkCapabilities The pointer to retrieve the BLE ling capabilities.
*
*/
void otPlatBleGetLinkCapabilities(otInstance *aInstance, otBleLinkCapabilities *aBleLinkCapabilities);
/**
* Function to retrieve from platform multiradio support of BLE and IEEE.
*
* @param[in] aInstance The OpenThread instance structure.
*
*/
bool otPlatBleSupportsMultiRadio(otInstance *aInstance);
/**
* @}
*
+35 -9
View File
@@ -67,6 +67,10 @@ extern "C" {
#define OT_TCAT_MAX_SERVICE_NAME_LENGTH \
15 ///< Maximum string length of a UDP or TCP service name (does not include null char).
#define OT_TCAT_ADVERTISEMENT_MAX_LEN 29 ///< Maximum length of TCAT advertisement.
#define OT_TCAT_OPCODE 0x2 ///< TCAT Advertisement Operation Code.
#define OT_TCAT_MAX_VENDORID_SIZE 5 ///< TCAT max size of vendor ID including null as termination.
/**
* Represents TCAT status code.
*
@@ -111,6 +115,27 @@ typedef enum otTcatCommandClass
} otTcatCommandClass;
/**
* Represents Device ID type.
*
*/
typedef enum otTcatDeviceIdType
{
OT_TCAT_DEVICE_ID_EMPTY = 0, ///< Vendor device ID type not set
OT_TCAT_DEVICE_ID_OUI24 = 1, ///< Vendor device ID type IEEE OUI-24
OT_TCAT_DEVICE_ID_OUI36 = 2, ///< Vendor device ID type IEEE OUI-36
OT_TCAT_DEVICE_ID_DISCRIMINATOR = 3, ///< Vendor device ID type Device Discriminator
OT_TCAT_DEVICE_ID_IANAPEN = 4, ///< Vendor device ID type IANA PEN
OT_TCAT_DEVICE_ID_MAX = 5, ///< Vendor device ID type size
} otTcatDeviceIdType;
typedef struct otTcatDeviceId
{
otTcatDeviceIdType mDeviceIdType;
uint16_t mDeviceIdLen;
uint8_t mDeviceId[OT_TCAT_MAX_VENDORID_SIZE];
} otTcatDeviceId;
/**
* This structure represents a TCAT vendor information.
*
@@ -119,15 +144,16 @@ typedef enum otTcatCommandClass
*/
typedef struct otTcatVendorInfo
{
const char *mProvisioningUrl; ///< Provisioning URL path string
const char *mVendorName; ///< Vendor name string
const char *mVendorModel; ///< Vendor model string
const char *mVendorSwVersion; ///< Vendor software version string
const char *mVendorData; ///< Vendor specific data string
const char *mPskdString; ///< Vendor managed pre-shared key for device
const char *mInstallCode; ///< Vendor managed install code string
const char *mDeviceId; ///< Vendor managed device ID string (if NULL: device ID is set to EUI-64 in binary format)
const char *mProvisioningUrl; ///< Provisioning URL path string
const char *mVendorName; ///< Vendor name string
const char *mVendorModel; ///< Vendor model string
const char *mVendorSwVersion; ///< Vendor software version string
const char *mVendorData; ///< Vendor specific data string
const char *mPskdString; ///< Vendor managed pre-shared key for device
const char *mInstallCode; ///< Vendor managed install code string
const otTcatDeviceId *mDeviceIds; /** Vendor managed device ID array.
(if NULL: device ID is set to EUI-64 in binary format)
Array is terminated like C string with OT_TCAT_DEVICE_ID_EMPTY */
} otTcatVendorInfo;
/**
+89 -4
View File
@@ -31,10 +31,12 @@
#include "cli/cli_utils.hpp"
#include "cli/cli_tcat.hpp"
#include "common/code_utils.hpp"
#include <openthread/ble_secure.h>
#include <mbedtls/oid.h>
#include <openthread/error.h>
#include <openthread/tcat.h>
#include <openthread/platform/ble.h>
@@ -79,7 +81,9 @@ namespace ot {
namespace Cli {
const char kPskdVendor[] = "J01NM3";
otTcatDeviceId sVendorDeviceIds[OT_TCAT_DEVICE_ID_MAX];
const char kPskdVendor[] = "JJJJJJ";
const char kUrl[] = "dummy_url";
static void HandleBleSecureReceive(otInstance *aInstance,
@@ -99,7 +103,8 @@ static void HandleBleSecureReceive(otInstance *aInstance,
uint16_t nLen;
uint8_t buf[kTextMaxLen];
nLen = otMessageRead(aMessage, (uint16_t)aOffset, buf + kBufPrefixLen, sizeof(buf) - kBufPrefixLen - 1);
nLen =
otMessageRead(aMessage, static_cast<uint16_t>(aOffset), buf + kBufPrefixLen, sizeof(buf) - kBufPrefixLen - 1);
memcpy(buf, "RECV:", kBufPrefixLen);
@@ -109,6 +114,85 @@ static void HandleBleSecureReceive(otInstance *aInstance,
IgnoreReturnValue(otBleSecureFlush(aInstance));
}
template <> otError Tcat::Process<Cmd("vendorid")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otTcatDeviceId devId;
static const char *const kVendorIdTypes[] = {"empty", "oui24", "oui36", "discriminator", "ianapen"};
mVendorInfo.mDeviceIds = sVendorDeviceIds;
if (aArgs[0].IsEmpty())
{
if (mVendorInfo.mDeviceIds[0].mDeviceIdType != OT_TCAT_DEVICE_ID_EMPTY)
{
OutputLine("Set vendorIds:");
for (size_t i = 0; mVendorInfo.mDeviceIds[i].mDeviceIdType != OT_TCAT_DEVICE_ID_EMPTY; i++)
{
OutputFormat("type %s, value: ", kVendorIdTypes[mVendorInfo.mDeviceIds[i].mDeviceIdType]);
OutputBytesLine(const_cast<uint8_t *>(mVendorInfo.mDeviceIds[i].mDeviceId),
mVendorInfo.mDeviceIds[i].mDeviceIdLen);
}
}
else
{
OutputLine("%s", kVendorIdTypes[OT_TCAT_DEVICE_ID_EMPTY]);
}
ExitNow();
}
if (aArgs[0] == kVendorIdTypes[OT_TCAT_DEVICE_ID_OUI24])
{
devId.mDeviceIdType = OT_TCAT_DEVICE_ID_OUI24;
}
else if (aArgs[0] == kVendorIdTypes[OT_TCAT_DEVICE_ID_OUI36])
{
devId.mDeviceIdType = OT_TCAT_DEVICE_ID_OUI36;
}
else if (aArgs[0] == kVendorIdTypes[OT_TCAT_DEVICE_ID_DISCRIMINATOR])
{
devId.mDeviceIdType = OT_TCAT_DEVICE_ID_DISCRIMINATOR;
}
else if (aArgs[0] == kVendorIdTypes[OT_TCAT_DEVICE_ID_IANAPEN])
{
devId.mDeviceIdType = OT_TCAT_DEVICE_ID_IANAPEN;
}
else if (aArgs[0] == kVendorIdTypes[OT_TCAT_DEVICE_ID_EMPTY])
{
for (otTcatDeviceId &vendorDeviceId : sVendorDeviceIds)
{
vendorDeviceId.mDeviceIdType = OT_TCAT_DEVICE_ID_EMPTY;
vendorDeviceId.mDeviceIdLen = 0;
}
ExitNow();
}
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
if (!aArgs[1].IsEmpty() && aArgs[1].GetLength() < (OT_TCAT_MAX_VENDORID_SIZE * 2 + 1))
{
devId.mDeviceIdLen = OT_TCAT_MAX_VENDORID_SIZE;
SuccessOrExit(error = aArgs[1].ParseAsHexString(devId.mDeviceIdLen, devId.mDeviceId));
for (otTcatDeviceId &vendorDeviceId : sVendorDeviceIds)
{
if (vendorDeviceId.mDeviceIdType == devId.mDeviceIdType ||
vendorDeviceId.mDeviceIdType == OT_TCAT_DEVICE_ID_EMPTY)
{
vendorDeviceId = devId;
break;
}
}
}
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
exit:
return error;
}
template <> otError Tcat::Process<Cmd("start")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
@@ -129,8 +213,9 @@ template <> otError Tcat::Process<Cmd("start")>(Arg aArgs[])
otBleSecureSetSslAuthMode(GetInstancePtr(), true);
SuccessOrExit(error = otBleSecureSetTcatVendorInfo(GetInstancePtr(), &mVendorInfo));
SuccessOrExit(error = otBleSecureStart(GetInstancePtr(), nullptr, HandleBleSecureReceive, true, nullptr));
SuccessOrExit(error = otBleSecureTcatStart(GetInstancePtr(), &mVendorInfo, nullptr));
SuccessOrExit(error = otBleSecureTcatStart(GetInstancePtr(), nullptr));
exit:
return error;
@@ -152,7 +237,7 @@ otError Tcat::Process(Arg aArgs[])
aCommandString, &Tcat::Process<Cmd(aCommandString)> \
}
static constexpr Command kCommands[] = {CmdEntry("start"), CmdEntry("stop")};
static constexpr Command kCommands[] = {CmdEntry("start"), CmdEntry("stop"), CmdEntry("vendorid")};
static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+7 -2
View File
@@ -55,9 +55,14 @@ otError otBleSecureStart(otInstance *aInstance,
return AsCoreType(aInstance).Get<Ble::BleSecure>().Start(aConnectHandler, aReceiveHandler, aTlvMode, aContext);
}
otError otBleSecureTcatStart(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo, otHandleTcatJoin aHandler)
otError otBleSecureSetTcatVendorInfo(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo)
{
return AsCoreType(aInstance).Get<Ble::BleSecure>().TcatStart(AsCoreType(aVendorInfo), aHandler);
return AsCoreType(aInstance).Get<Ble::BleSecure>().TcatSetVendorInfo(AsCoreType(aVendorInfo));
}
otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aHandler)
{
return AsCoreType(aInstance).Get<Ble::BleSecure>().TcatStart(aHandler);
}
void otBleSecureStop(otInstance *aInstance) { AsCoreType(aInstance).Get<Ble::BleSecure>().Stop(); }
+1
View File
@@ -33,6 +33,7 @@
*/
#include "meshcop.hpp"
#include <openthread/platform/toolchain.h>
#include "common/clearable.hpp"
#include "common/crc16.hpp"
+103 -16
View File
@@ -32,11 +32,10 @@
*/
#include "tcat_agent.hpp"
#include <openthread/tcat.h>
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#include <stdio.h>
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
@@ -64,7 +63,6 @@ TcatAgent::TcatAgent(Instance &aInstance)
, mVendorInfo(nullptr)
, mCurrentApplicationProtocol(kApplicationProtocolNone)
, mState(kStateDisabled)
, mAlreadyCommissioned(false)
, mCommissionerHasNetworkName(false)
, mCommissionerHasDomainName(false)
, mCommissionerHasExtendedPanId(false)
@@ -73,25 +71,17 @@ TcatAgent::TcatAgent(Instance &aInstance)
mCurrentServiceName[0] = 0;
}
Error TcatAgent::Start(const TcatAgent::VendorInfo &aVendorInfo,
AppDataReceiveCallback aAppDataReceiveCallback,
JoinCallback aHandler,
void *aContext)
Error TcatAgent::Start(AppDataReceiveCallback aAppDataReceiveCallback, JoinCallback aHandler, void *aContext)
{
Error error = kErrorNone;
LogInfo("Starting");
VerifyOrExit(aVendorInfo.IsValid(), error = kErrorInvalidArgs);
SuccessOrExit(error = mJoinerPskd.SetFrom(aVendorInfo.mPskdString));
VerifyOrExit(mVendorInfo != nullptr, error = kErrorFailed);
mAppDataReceiveCallback.Set(aAppDataReceiveCallback, aContext);
mJoinCallback.Set(aHandler, aContext);
mVendorInfo = &aVendorInfo;
mCurrentApplicationProtocol = kApplicationProtocolNone;
mState = kStateEnabled;
mAlreadyCommissioned = false;
exit:
LogWarnOnError(error, "start TCAT agent");
@@ -102,12 +92,23 @@ void TcatAgent::Stop(void)
{
mCurrentApplicationProtocol = kApplicationProtocolNone;
mState = kStateDisabled;
mAlreadyCommissioned = false;
mAppDataReceiveCallback.Clear();
mJoinCallback.Clear();
LogInfo("TCAT agent stopped");
}
Error TcatAgent::SetTcatVendorInfo(const VendorInfo &aVendorInfo)
{
Error error = kErrorNone;
VerifyOrExit(aVendorInfo.IsValid(), error = kErrorInvalidArgs);
SuccessOrExit(error = mJoinerPskd.SetFrom(aVendorInfo.mPskdString));
mVendorInfo = &aVendorInfo;
exit:
return error;
}
Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext)
{
size_t len;
@@ -160,7 +161,6 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext)
mCurrentApplicationProtocol = kApplicationProtocolNone;
mCurrentServiceName[0] = 0;
mState = kStateConnected;
mAlreadyCommissioned = Get<ActiveDatasetManager>().IsCommissioned();
LogInfo("TCAT agent connected");
exit:
@@ -170,7 +170,6 @@ exit:
void TcatAgent::Disconnected(void)
{
mCurrentApplicationProtocol = kApplicationProtocolNone;
mAlreadyCommissioned = false;
if (mState != kStateDisabled)
{
@@ -501,6 +500,94 @@ exit:
return error;
}
void SeralizeTcatAdvertisementTlv(uint8_t *aBuffer,
uint16_t &aOffset,
TcatAdvertisementTlvType aType,
uint16_t aLength,
const uint8_t *aValue)
{
aBuffer[aOffset++] = static_cast<uint8_t>(aType << 4 | (aLength & 0xf));
memcpy(aBuffer + aOffset, aValue, aLength);
aOffset += aLength;
}
Error TcatAgent::GetAdvertisementData(uint16_t &aLen, uint8_t *aAdvertisementData)
{
Error error = kErrorNone;
DeviceTypeAndStatus tas;
otBleLinkCapabilities caps;
VerifyOrExit(mVendorInfo != nullptr && aAdvertisementData != nullptr, error = kErrorInvalidArgs);
aLen = 0;
LittleEndian::WriteUint16(OT_TOBLE_SERVICE_UUID, aAdvertisementData);
aLen += sizeof(uint16_t);
aAdvertisementData[2] = OPENTHREAD_CONFIG_THREAD_VERSION << 4 | OT_TCAT_OPCODE;
aLen++;
if (mVendorInfo->mDeviceIds != nullptr)
{
for (uint8_t i = 0; mVendorInfo->mDeviceIds[i].mDeviceIdType != OT_TCAT_DEVICE_ID_EMPTY; i++)
{
switch (MapEnum(mVendorInfo->mDeviceIds[i].mDeviceIdType))
{
case kTcatDeviceIdOui24:
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorOui24,
mVendorInfo->mDeviceIds[i].mDeviceIdLen,
mVendorInfo->mDeviceIds[i].mDeviceId);
break;
case kTcatDeviceIdOui36:
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorOui36,
mVendorInfo->mDeviceIds[i].mDeviceIdLen,
mVendorInfo->mDeviceIds[i].mDeviceId);
break;
case kTcatDeviceIdDiscriminator:
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvDeviceDiscriminator,
mVendorInfo->mDeviceIds[i].mDeviceIdLen,
mVendorInfo->mDeviceIds[i].mDeviceId);
break;
case kTcatDeviceIdIanaPen:
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorIanaPen,
mVendorInfo->mDeviceIds[i].mDeviceIdLen,
mVendorInfo->mDeviceIds[i].mDeviceId);
break;
default:
break;
}
}
}
otPlatBleGetLinkCapabilities(&GetInstance(), &caps);
if (caps.mGattNotifications || caps.mL2CapDirect)
{
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvBleLinkCapabilities, kTlvBleLinkCapabilitiesLength,
reinterpret_cast<uint8_t *>(&caps));
}
tas.mRsv = 0;
tas.mMultiradioSupport = otPlatBleSupportsMultiRadio(&GetInstance());
tas.mIsCommisionned = Get<ActiveDatasetManager>().IsCommissioned();
tas.mThreadNetworkActive = Get<Mle::Mle>().IsAttached();
tas.mDeviceType = Get<Mle::Mle>().GetDeviceMode().IsFullThreadDevice();
tas.mRxOnWhenIdle = Get<Mle::Mle>().GetDeviceMode().IsRxOnWhenIdle();
#if OPENTHREAD_FTD && (OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE || OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE || \
OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE)
tas.mIsBorderRouter = true;
#else
tas.mIsBorderRouter = false;
#endif
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvDeviceTypeAndStatus, kTlvDeviceTypeAndStatusLength,
reinterpret_cast<uint8_t *>(&tas));
OT_ASSERT(aLen <= OT_TCAT_ADVERTISEMENT_MAX_LEN);
exit:
return error;
}
} // namespace MeshCoP
} // namespace ot
+71 -9
View File
@@ -154,10 +154,10 @@ public:
};
/**
* TCAT TLV Types.
* TCAT Command TLV Types.
*
*/
enum TlvType : uint8_t
enum CommandTlvType : uint8_t
{
// Command Class General
kTlvResponseWithStatus = 1, ///< TCAT response with status value TLV
@@ -256,6 +256,19 @@ public:
kStateConnected,
};
/**
* Represents Device ID type.
*
*/
enum TcatDeviceIdType : uint8_t
{
kTcatDeviceIdEmpty = OT_TCAT_DEVICE_ID_EMPTY,
kTcatDeviceIdOui24 = OT_TCAT_DEVICE_ID_OUI24,
kTcatDeviceIdOui36 = OT_TCAT_DEVICE_ID_OUI36,
kTcatDeviceIdDiscriminator = OT_TCAT_DEVICE_ID_DISCRIMINATOR,
kTcatDeviceIdIanaPen = OT_TCAT_DEVICE_ID_IANAPEN,
};
/**
* Initializes the Joiner object.
*
@@ -267,8 +280,6 @@ public:
/**
* Enables the TCAT protocol.
*
* @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method
* call, may be NULL).
* @param[in] aAppDataReceiveCallback A pointer to a function that is called when the user data is received.
* @param[in] aHandler A pointer to a function that is called when the join operation completes.
* @param[in] aContext A context pointer.
@@ -277,10 +288,7 @@ public:
* @retval kErrorInvalidArgs The aVendorInfo is invalid.
*
*/
Error Start(const VendorInfo &aVendorInfo,
AppDataReceiveCallback aAppDataReceiveCallback,
JoinCallback aHandler,
void *aContext);
Error Start(AppDataReceiveCallback aAppDataReceiveCallback, JoinCallback aHandler, void *aContext);
/**
* Stops the TCAT protocol.
@@ -288,6 +296,14 @@ public:
*/
void Stop(void);
/**
* Set the TCAT Vendor Info object
*
* @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method call).
*
*/
Error SetTcatVendorInfo(const VendorInfo &aVendorInfo);
/**
* Indicates whether or not the TCAT agent is enabled.
*
@@ -317,6 +333,18 @@ public:
*/
bool IsCommandClassAuthorized(CommandClass aCommandClass) const;
/**
* Gets TCAT advertisement data.
*
* @param[out] aLen Advertisement length.
* @param[out] aAdvertisementData Advertisement data.
*
* @retval kErrorNone Successfully started the TCAT agent.
* @retval kErrorInvalidArgs The aVendorInfo is invalid or provided incorrect parameters.
*
*/
Error GetAdvertisementData(uint16_t &aLen, uint8_t *aAdvertisementData);
private:
Error Connected(MeshCoP::SecureTransport &aTlsContext);
void Disconnected(void);
@@ -345,7 +373,6 @@ private:
ExtendedPanId mCommissionerExtendedPanId;
char mCurrentServiceName[OT_TCAT_MAX_SERVICE_NAME_LENGTH + 1];
State mState;
bool mAlreadyCommissioned : 1;
bool mCommissionerHasNetworkName : 1;
bool mCommissionerHasDomainName : 1;
bool mCommissionerHasExtendedPanId : 1;
@@ -358,9 +385,44 @@ private:
DefineCoreType(otTcatVendorInfo, MeshCoP::TcatAgent::VendorInfo);
DefineMapEnum(otTcatApplicationProtocol, MeshCoP::TcatAgent::TcatApplicationProtocol);
DefineMapEnum(otTcatDeviceIdType, MeshCoP::TcatAgent::TcatDeviceIdType);
// Command class TLVs
typedef UintTlvInfo<MeshCoP::TcatAgent::kTlvResponseWithStatus, uint8_t> ResponseWithStatusTlv;
/**
* Represent Device Type and Status
*
*/
struct DeviceTypeAndStatus
{
uint8_t mRsv : 1;
bool mMultiradioSupport : 1;
bool mStoresActiveOpertonalDataset : 1;
bool mIsCommisionned : 1;
bool mThreadNetworkActive : 1;
bool mIsBorderRouter : 1;
bool mRxOnWhenIdle : 1;
bool mDeviceType : 1;
};
static constexpr uint8_t kTlvVendorOui24Length = 3;
static constexpr uint8_t kTlvVendorOui36Length = 5;
static constexpr uint8_t kTlvDeviceDiscriminatorLength = 5;
static constexpr uint8_t kTlvBleLinkCapabilitiesLength = 1;
static constexpr uint8_t kTlvDeviceTypeAndStatusLength = 1;
static constexpr uint8_t kTlvVendorIanaPenLength = 4;
enum TcatAdvertisementTlvType : uint8_t
{
kTlvVendorOui24 = 1, ///< TCAT vendor OUI 24
kTlvVendorOui36 = 2, ///< TCAT vendor OUI 36
kTlvDeviceDiscriminator = 3, ///< TCAT random vendor discriminator
kTlvDeviceTypeAndStatus = 4, ///< TCAT Thread device type and status
kTlvBleLinkCapabilities = 5, ///< TCAT BLE link capabilities of device
kTlvVendorIanaPen = 6, ///< TCAT Vendor IANA PEN
};
} // namespace ot
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
+11 -4
View File
@@ -64,7 +64,9 @@ BleSecure::BleSecure(Instance &aInstance)
Error BleSecure::Start(ConnectCallback aConnectHandler, ReceiveCallback aReceiveHandler, bool aTlvMode, void *aContext)
{
Error error = kErrorNone;
Error error = kErrorNone;
uint16_t advertisementLen = 0;
uint8_t *advertisementData = nullptr;
VerifyOrExit(mBleState == kStopped, error = kErrorAlready);
@@ -74,7 +76,13 @@ Error BleSecure::Start(ConnectCallback aConnectHandler, ReceiveCallback aReceive
mMtuSize = kInitialMtuSize;
SuccessOrExit(error = otPlatBleEnable(&GetInstance()));
SuccessOrExit(error = otPlatBleGetAdvertisementBuffer(&GetInstance(), &advertisementData));
SuccessOrExit(error = mTcatAgent.GetAdvertisementData(advertisementLen, advertisementData));
VerifyOrExit(advertisementData != nullptr, error = kErrorFailed);
SuccessOrExit(error = otPlatBleGapAdvSetData(&GetInstance(), advertisementData, advertisementLen));
SuccessOrExit(error = otPlatBleGapAdvStart(&GetInstance(), OT_BLE_ADV_INTERVAL_DEFAULT));
SuccessOrExit(error = mTls.Open(&BleSecure::HandleTlsReceive, &BleSecure::HandleTlsConnected, this));
SuccessOrExit(error = mTls.Bind(HandleTransport, this));
@@ -86,14 +94,13 @@ exit:
return error;
}
Error BleSecure::TcatStart(const MeshCoP::TcatAgent::VendorInfo &aVendorInfo,
MeshCoP::TcatAgent::JoinCallback aJoinHandler)
Error BleSecure::TcatStart(MeshCoP::TcatAgent::JoinCallback aJoinHandler)
{
Error error;
VerifyOrExit(mBleState != kStopped, error = kErrorInvalidState);
error = mTcatAgent.Start(aVendorInfo, mReceiveCallback.GetHandler(), aJoinHandler, mReceiveCallback.GetContext());
error = mTcatAgent.Start(mReceiveCallback.GetHandler(), aJoinHandler, mReceiveCallback.GetContext());
exit:
return error;
+12 -2
View File
@@ -101,7 +101,6 @@ public:
/**
* Enables the TCAT protocol over BLE Secure.
*
* @param[in] aVendorInfo A reference to the Vendor Information (must remain valid after the method call)
* @param[in] aHandler Callback to a function that is called when the join operation completes.
*
* @retval kErrorNone Successfully started the BLE Secure Joiner role.
@@ -109,7 +108,18 @@ public:
* @retval kErrorInvaidState The BLE function has not been started or line mode is not selected.
*
*/
Error TcatStart(const MeshCoP::TcatAgent::VendorInfo &aVendorInfo, MeshCoP::TcatAgent::JoinCallback aHandler);
Error TcatStart(MeshCoP::TcatAgent::JoinCallback aHandler);
/**
* Set the TCAT Vendor Info object
*
* @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method call).
*
*/
Error TcatSetVendorInfo(const MeshCoP::TcatAgent::VendorInfo &aVendorInfo)
{
return mTcatAgent.SetTcatVendorInfo(aVendorInfo);
}
/**
* Stops the secure BLE agent.
+34
View File
@@ -26,6 +26,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <openthread/tcat.h>
#include <openthread/platform/ble.h>
otError otPlatBleEnable(otInstance *aInstance)
@@ -40,6 +41,16 @@ otError otPlatBleDisable(otInstance *aInstance)
return OT_ERROR_NOT_IMPLEMENTED;
}
otError otPlatBleGetAdvertisementBuffer(otInstance *aInstance, uint8_t **aAdvertisementBuffer)
{
OT_UNUSED_VARIABLE(aInstance);
static uint8_t sAdvertisementBuffer[OT_TCAT_ADVERTISEMENT_MAX_LEN];
*aAdvertisementBuffer = sAdvertisementBuffer;
return OT_ERROR_NONE;
}
otError otPlatBleGapAdvStart(otInstance *aInstance, uint16_t aInterval)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -73,3 +84,26 @@ otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle, con
OT_UNUSED_VARIABLE(aPacket);
return OT_ERROR_NOT_IMPLEMENTED;
}
void otPlatBleGetLinkCapabilities(otInstance *aInstance, otBleLinkCapabilities *aBleLinkCapabilities)
{
OT_UNUSED_VARIABLE(aInstance);
aBleLinkCapabilities->mGattNotifications = 1;
aBleLinkCapabilities->mL2CapDirect = 0;
aBleLinkCapabilities->mRsv = 0;
}
otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aAdvertisementData);
OT_UNUSED_VARIABLE(aAdvertisementLen);
return OT_ERROR_NONE;
}
bool otPlatBleSupportsMultiRadio(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return false;
}
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/expect -f
#
# Copyright (c) 2022, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
source "tests/scripts/expect/_common.exp"
spawn_node 1 "cli"
switch_node 1
send "tcat vendorid ianapen f378\n"
expect_line "Done"
send "tcat vendorid\n"
expect_line "type ianapen, value: f378"
expect_line "Done"
send "tcat vendorid ianapen f378aabb\n"
expect_line "Done"
send "tcat vendorid\n"
expect_line "type ianapen, value: f378aabb"
expect_line "Done"
send "tcat vendorid oui24 f378aa\n"
expect_line "Done"
send "tcat vendorid\n"
expect_line "type oui24, value: f378aa"
expect_line "Done"
send "tcat vendorid oui36 f378aabbcc\n"
expect_line "Done"
send "tcat vendorid\n"
expect_line "type oui36, value: f378aabbcc"
expect_line "Done"
send "tcat vendorid discriminator f378aabbdd\n"
expect_line "Done"
send "tcat vendorid\n"
expect_line "type discriminator, value: f378aabbdd"
expect_line "Done"
send "tcat vendorid empty\n"
expect_line "Done"
send "tcat vendorid\n"
expect_line "empty"
expect_line "Done"
+35
View File
@@ -36,6 +36,7 @@
#include <stdio.h>
#include <sys/time.h>
#ifdef OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#include <openthread/tcat.h>
#include <openthread/platform/ble.h>
#endif
@@ -732,6 +733,16 @@ otError otPlatBleDisable(otInstance *aInstance)
return OT_ERROR_NONE;
}
otError otPlatBleGetAdvertisementBuffer(otInstance *aInstance, uint8_t **aAdvertisementBuffer)
{
OT_UNUSED_VARIABLE(aInstance);
static uint8_t sAdvertisementBuffer[OT_TCAT_ADVERTISEMENT_MAX_LEN];
*aAdvertisementBuffer = sAdvertisementBuffer;
return OT_ERROR_NONE;
}
otError otPlatBleGapAdvStart(otInstance *aInstance, uint16_t aInterval)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -765,6 +776,30 @@ otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle, con
OT_UNUSED_VARIABLE(aPacket);
return OT_ERROR_NONE;
}
void otPlatBleGetLinkCapabilities(otInstance *aInstance, otBleLinkCapabilities *aBleLinkCapabilities)
{
OT_UNUSED_VARIABLE(aInstance);
aBleLinkCapabilities->mGattNotifications = true;
aBleLinkCapabilities->mL2CapDirect = false;
aBleLinkCapabilities->mRsv = 0;
}
bool otPlatBleSupportsMultiRadio(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return false;
}
otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aAdvertisementData);
OT_UNUSED_VARIABLE(aAdvertisementLen);
return OT_ERROR_NONE;
}
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
+3 -2
View File
@@ -122,10 +122,11 @@ void TestTcat(void)
otBleSecureSetSslAuthMode(instance, true);
// Validate BLE secure and Tcat start APIs
VerifyOrQuit(otBleSecureTcatStart(instance, &vendorInfo, nullptr) == kErrorInvalidState);
SuccessOrQuit(otBleSecureSetTcatVendorInfo(instance, &vendorInfo));
VerifyOrQuit(otBleSecureTcatStart(instance, nullptr) == kErrorInvalidState);
SuccessOrQuit(otBleSecureStart(instance, HandleBleSecureConnect, nullptr, true, &ble));
VerifyOrQuit(otBleSecureStart(instance, HandleBleSecureConnect, nullptr, true, nullptr) == kErrorAlready);
SuccessOrQuit(otBleSecureTcatStart(instance, &vendorInfo, nullptr));
SuccessOrQuit(otBleSecureTcatStart(instance, nullptr));
// Validate connection callbacks when platform informs that peer has connected/disconnected
otPlatBleGapOnConnected(instance, kConnectionId);