mirror of
https://github.com/espressif/openthread.git
synced 2026-07-30 15:47:46 +00:00
[ble][tcat] add BLE 'non-advertising' state, TCAT active/standby states, and timed activation (#11802)
This adds a BLE 'non-advertising' state in which BLE is enabled for connections, but not advertising. - If the TCAT agent is not started and BLE is started, BLE advertising will be enabled by default. - If the TCAT agent is started, then BLE advertising is under control of the TCAT agent - depending on its state. The TCAT agent, while started, can be now in standby mode or in active mode. In standby, it doesn't advertise and doesn't allow incoming TCAT connections. In active mode, it allows both advertising and incoming connections. Timed activation of the active mode is also possible. CLI commands are added to test the new modes and timed activation. Existing architecture is not changed (BLE-Secure is in control and has all APIs to access TCAT agent). It also fixes some (API) documentation and clarifies this where needed. Also, an error-value bugfix is done. The TcatAgent is now added to instance.hpp/cpp, because that is required to use a timer from within TcatAgent. Log messages of TcatAgent are shortened and more often try to use an identical constant string value. This saves memory in the binary, due to string re-use. The "join callback" is clarified and extended to support callback to the application when the TCAT Commissioner instructs the TCAT Device to try join a Thread network, or leave a Thread network.
This commit is contained in:
@@ -88,25 +88,32 @@ typedef void (*otHandleBleSecureConnect)(otInstance *aInstance,
|
||||
*
|
||||
* When TCAT has been started, the TCAT agent automatically responds with status OT_TCAT_STATUS_UNSUPPORTED
|
||||
* if no response has been generated or no handler is defined. The application may generate a response to
|
||||
* incoming TCAT application data or vendor-specific data by calling `otBleSecureSendApplicationTlv`.
|
||||
* incoming TCAT application data or vendor-specific data by calling #otBleSecureSendApplicationTlv.
|
||||
*/
|
||||
typedef otHandleTcatApplicationDataReceive otHandleBleSecureReceive;
|
||||
|
||||
/**
|
||||
* Starts the BLE Secure service.
|
||||
* When TLV mode is active, the function @p aReceiveHandler will be called once a complete TLV was received and the
|
||||
* message offset points to the TLV value.
|
||||
*
|
||||
* When TLV mode is active, the function @p aReceiveHandler will be called once a complete TLV or line
|
||||
* was received and the message offset points to the TLV value.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aConnectHandler A pointer to a function that will be called when the connection
|
||||
* state changes.
|
||||
* @param[in] aReceiveHandler A pointer to a function that will be called once data has been received
|
||||
* over the TLS connection.
|
||||
* @param[in] aTlvMode A boolean value indicating if line mode shall be activated.
|
||||
* @param[in] aTlvMode A boolean value indicating if TLV mode (TRUE) shall be activated, or
|
||||
* line mode (FALSE).
|
||||
* @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the BLE Secure server.
|
||||
* @retval OT_ERROR_ALREADY The service was stated already.
|
||||
* @retval OT_ERROR_NONE Successfully started the BLE Secure server.
|
||||
* @retval OT_ERROR_FAILED The BLE radio could not be enabled, or BLE advertisement data unavailable, or
|
||||
* a socket could not be opened.
|
||||
* @retval OT_ERROR_NO_BUFS No bufferspace available.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid arguments or vendor BLE advertisement data unavailable.
|
||||
* @retval OT_ERROR_INVALID_STATE BLE Device or socket is in invalid state.
|
||||
* @retval OT_ERROR_ALREADY The service was started already.
|
||||
*/
|
||||
otError otBleSecureStart(otInstance *aInstance,
|
||||
otHandleBleSecureConnect aConnectHandler,
|
||||
@@ -115,13 +122,16 @@ otError otBleSecureStart(otInstance *aInstance,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Sets TCAT vendor info
|
||||
* Sets TCAT vendor info.
|
||||
*
|
||||
* The vendor info is used for advertising in TCAT Advertisements, as well as for responding
|
||||
* to particular TCAT commands that supply vendor info to the TCAT Commissioner.
|
||||
*
|
||||
* @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.
|
||||
* @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.
|
||||
* @retval OT_ERROR_NONE Successfully set vendor info.
|
||||
* @retval OT_ERROR_INVALID_ARGS Vendor info could not be set.
|
||||
*/
|
||||
otError otBleSecureSetTcatVendorInfo(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo);
|
||||
|
||||
@@ -129,21 +139,43 @@ otError otBleSecureSetTcatVendorInfo(otInstance *aInstance, const otTcatVendorIn
|
||||
* Enables the TCAT protocol over BLE Secure.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aHandler A pointer to a function that is called when the join operation completes.
|
||||
* @param[in] aJoinHandler A pointer to a function that is called when a network join or leave
|
||||
* operation is requested under guidance of the TCAT Commissioner.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the BLE Secure Joiner role.
|
||||
* @retval OT_ERROR_INVALID_ARGS @p aElevationPsk or @p aVendorInfo is invalid.
|
||||
* @retval OT_ERROR_INVALID_STATE The BLE function has not been started or line mode is not selected.
|
||||
* @retval OT_ERROR_NONE Successfully started TCAT over BLE Secure.
|
||||
* @retval OT_ERROR_ALREADY TCAT is already started.
|
||||
* @retval OT_ERROR_FAILED TCAT vendor info could not be initialized.
|
||||
* @retval OT_ERROR_INVALID_STATE The BLE Secure function is not started yet or TLV mode is not selected.
|
||||
*/
|
||||
otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aHandler);
|
||||
otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aJoinHandler);
|
||||
|
||||
/**
|
||||
* Stops the BLE Secure server.
|
||||
*
|
||||
* If the TCAT agent is active, it is also stopped and any ongoing connection is forcibly ended.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*/
|
||||
void otBleSecureStop(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Sets the TCAT agent over BLE Secure into active or standby state.
|
||||
*
|
||||
* In standby state, no BLE advertisements are sent and TCAT Commissioners can't connect.
|
||||
* TCAT can be automatically enabled via a TMF message while in standby.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aActive If TRUE, attempts to set TCAT agent to active state.
|
||||
* If FALSE, attempts to set TCAT agent to standby (inactive) state.
|
||||
* @param[in] aDelayMs Delay in ms before activating TCAT agent. If 0, activate immediately.
|
||||
* @param[in] aDurationMs Duration in ms of the activation of the TCAT agent. If 0, activate indefinitely.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set the TCAT state as requested.
|
||||
* @retval OT_ERROR_INVALID_STATE TCAT is not yet started, or not in a state from which it can
|
||||
* transition to the desired state.
|
||||
*/
|
||||
otError otBleSecureSetTcatAgentState(otInstance *aInstance, bool aActive, uint32_t aDelayMs, uint32_t aDurationMs);
|
||||
|
||||
/**
|
||||
* Sets the Pre-Shared Key (PSK) and cipher suite
|
||||
* TLS_PSK_WITH_AES_128_CCM_8.
|
||||
@@ -295,8 +327,9 @@ otError otBleSecureGetThreadAttributeFromOwnCertificate(otInstance *aInstance,
|
||||
void otBleSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate);
|
||||
|
||||
/**
|
||||
* Sets the local device's X509 certificate with corresponding private key for
|
||||
* TLS session with TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8.
|
||||
* Sets the local device's X509 certificate and corresponding private key.
|
||||
*
|
||||
* Used for TLS sessions with cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
|
||||
*
|
||||
* @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
|
||||
*
|
||||
@@ -314,9 +347,9 @@ void otBleSecureSetCertificate(otInstance *aInstance,
|
||||
|
||||
/**
|
||||
* Sets the trusted top level CAs. It is needed for validating the
|
||||
* certificate of the peer.
|
||||
* certificate of the peer via TLS.
|
||||
*
|
||||
* TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
|
||||
* Used for TLS sessions with cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
|
||||
*
|
||||
* @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
|
||||
*
|
||||
@@ -331,14 +364,14 @@ void otBleSecureSetCaCertificateChain(otInstance *aInstance,
|
||||
/**
|
||||
* Initializes TLS session with a peer using an already open BLE connection.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started TLS connection.
|
||||
*/
|
||||
otError otBleSecureConnect(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Stops the BLE and TLS connection.
|
||||
* Stops the BLE and TLS connections.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*/
|
||||
@@ -365,20 +398,20 @@ bool otBleSecureIsConnectionActive(otInstance *aInstance);
|
||||
bool otBleSecureIsConnected(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TCAT agent is enabled.
|
||||
* Indicates whether or not the TCAT agent is started over BLE secure.
|
||||
*
|
||||
* @retval TRUE The TCAT agent is enabled.
|
||||
* @retval FALSE The TCAT agent is not enabled.
|
||||
* @retval TRUE The TCAT agent is started, communicating over BLE secure.
|
||||
* @retval FALSE The TCAT agent is disabled on BLE secure.
|
||||
*/
|
||||
bool otBleSecureIsTcatEnabled(otInstance *aInstance);
|
||||
bool otBleSecureIsTcatAgentStarted(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether or not a TCAT command class is authorized.
|
||||
* Indicates whether or not a TCAT command class is authorized for the current TCAT Commissioner.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCommandClass A command class to check.
|
||||
*
|
||||
* @retval TRUE The command class is authorized.
|
||||
* @retval TRUE The command class is authorized for the current (if any) TCAT Commissioner.
|
||||
* @retval FALSE The command class is not authorized.
|
||||
*/
|
||||
bool otBleSecureIsCommandClassAuthorized(otInstance *aInstance, otTcatCommandClass aCommandClass);
|
||||
@@ -413,7 +446,7 @@ otError otBleSecureSendMessage(otInstance *aInstance, otMessage *aMessage);
|
||||
otError otBleSecureSend(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Sends a secure BLE data packet containing application data directed to the application layer @p aApplicationProtocol
|
||||
* Sends a secure BLE data packet containing application data directed to the application layer @p aApplicationProtocol
|
||||
* or a response to the latest received application data packet.
|
||||
*
|
||||
* Only a single response can be sent while executing the `otHandleBleSecureReceive` handler. If no (further) response
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (538)
|
||||
#define OPENTHREAD_API_VERSION (539)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
+18
-14
@@ -35,9 +35,7 @@
|
||||
* The functions in this module require the build-time feature `OPENTHREAD_CONFIG_BLE_TCAT_ENABLE=1`.
|
||||
*
|
||||
* @note
|
||||
* To enable cipher suite DTLS_PSK_WITH_AES_128_CCM_8, MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
* must be enabled in mbedtls-config.h
|
||||
* To enable cipher suite DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
|
||||
* To enable the required cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED must be enabled in mbedtls-config.h.
|
||||
*/
|
||||
|
||||
@@ -95,7 +93,7 @@ typedef enum otTcatStatusCode
|
||||
} otTcatStatusCode;
|
||||
|
||||
/**
|
||||
* Represents TCAT application protocol.
|
||||
* Represents TCAT application protocol options.
|
||||
*/
|
||||
typedef enum otTcatApplicationProtocol
|
||||
{
|
||||
@@ -126,16 +124,16 @@ typedef enum otTcatCommandClass
|
||||
} otTcatCommandClass;
|
||||
|
||||
/**
|
||||
* Represents Advertised Device ID type. (used during TCAT advertisement)
|
||||
* Represents Advertised Device ID type. Used during TCAT advertisement.
|
||||
*/
|
||||
typedef enum otTcatAdvertisedDeviceIdType
|
||||
{
|
||||
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
|
||||
OT_TCAT_DEVICE_ID_EMPTY = 0, ///< Advertised device ID type not set
|
||||
OT_TCAT_DEVICE_ID_OUI24 = 1, ///< Advertised device ID type IEEE OUI-24
|
||||
OT_TCAT_DEVICE_ID_OUI36 = 2, ///< Advertised device ID type IEEE OUI-36
|
||||
OT_TCAT_DEVICE_ID_DISCRIMINATOR = 3, ///< Advertised device ID type Device Discriminator
|
||||
OT_TCAT_DEVICE_ID_IANAPEN = 4, ///< Advertised device ID type IANA PEN
|
||||
OT_TCAT_DEVICE_ID_MAX = 5, ///< Advertised device ID max number of types
|
||||
} otTcatAdvertisedDeviceIdType;
|
||||
|
||||
typedef struct otTcatAdvertisedDeviceId
|
||||
@@ -202,10 +200,16 @@ typedef void (*otHandleTcatApplicationDataReceive)(otInstance *aIn
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Pointer to call to notify the completion of a join operation.
|
||||
* Pointer to call to notify the completion of a network join/leave operation performed under
|
||||
* guidance of a TCAT Commissioner.
|
||||
*
|
||||
* @param[in] aError OT_ERROR_NONE if the join process succeeded.
|
||||
* OT_ERROR_SECURITY if the join process failed due to security credentials.
|
||||
* @param[in] aError OT_ERROR_NONE if the network join/leave operation was successfully started.
|
||||
* OT_ERROR_INVALID_STATE if network join was requested but network credentials
|
||||
* were missing or incomplete.
|
||||
* OT_ERROR_REJECTED if a network join/leave operation was requested, but the
|
||||
* TCAT Commissioner is not authorized to make such a request.
|
||||
* OT_ERROR_SECURITY is reserved for future use for a failed join due to
|
||||
* credential mismatch.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*/
|
||||
typedef void (*otHandleTcatJoin)(otError aError, void *aContext);
|
||||
|
||||
+34
-8
@@ -1,12 +1,32 @@
|
||||
# OpenThread CLI - TCAT Example
|
||||
|
||||
The OpenThread BLE-Secure/TCAT APIs may be invoked via the OpenThread CLI for testing purposes.
|
||||
|
||||
> Note: in the present example, only TCAT over BLE is implemented.
|
||||
|
||||
## Command List
|
||||
|
||||
- advid [#advid]
|
||||
- devid [#devid]
|
||||
- help [#help]
|
||||
- start [#start]
|
||||
- stop [#stop]
|
||||
- [active](#active)
|
||||
- [advid](#advid)
|
||||
- [certid](#certid)
|
||||
- [devid](#devid)
|
||||
- [help](#help)
|
||||
- [standby](#standby)
|
||||
- [start](#start)
|
||||
- [stop](#stop)
|
||||
|
||||
### active
|
||||
|
||||
Activates TCAT functions, leaving standby mode in case the TCAT agent was in standby. The first optional parameter specifies delay in milliseconds before activating TCAT functions. The second optional parameter specifies the duration of activation in milliseconds. If `0` or not provided, the duration is indefinite.
|
||||
|
||||
```bash
|
||||
tcat active 5000
|
||||
Done
|
||||
tcat active 0 120000
|
||||
Done
|
||||
tcat active
|
||||
Done
|
||||
```
|
||||
|
||||
### advid
|
||||
|
||||
@@ -116,17 +136,23 @@ Print help.
|
||||
|
||||
```bash
|
||||
tcat help
|
||||
active
|
||||
advid
|
||||
certid
|
||||
devid
|
||||
help
|
||||
standby
|
||||
start
|
||||
stop
|
||||
Done
|
||||
```
|
||||
|
||||
### standby
|
||||
|
||||
Sets TCAT functions to standby, ready to be activated again via the CLI (using [active](#active)), by an application, or by a TMF message. The TCAT agent is not stopped.
|
||||
|
||||
### start
|
||||
|
||||
Start tcat server and ble advertisement.
|
||||
Start TCAT agent, activate TCAT functions and start sending TCAT advertisements. After starting, optionally standby mode can be set using [standby](#standby).
|
||||
|
||||
```bash
|
||||
tcat start
|
||||
@@ -135,7 +161,7 @@ Done
|
||||
|
||||
### stop
|
||||
|
||||
Stop tcat server and ble advertisement.
|
||||
Stop TCAT agent, which stops any ongoing connection and stops sending TCAT advertisements. When stopped, it can only be enabled again via [start](#start), so TCAT cannot be activated via a TMF message.
|
||||
|
||||
```bash
|
||||
tcat stop
|
||||
|
||||
+80
-12
@@ -33,7 +33,6 @@
|
||||
#include "cli/cli_tcat.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "common/string.hpp"
|
||||
|
||||
#include <openthread/ble_secure.h>
|
||||
@@ -271,7 +270,7 @@ exit:
|
||||
*/
|
||||
template <> otError Tcat::Process<Cmd("certid")>(Arg aArgs[])
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint8_t certCandidate = 0;
|
||||
|
||||
if (aArgs[0].IsEmpty())
|
||||
@@ -282,7 +281,7 @@ template <> otError Tcat::Process<Cmd("certid")>(Arg aArgs[])
|
||||
|
||||
SuccessOrExit(error = aArgs[0].ParseAsUint8(certCandidate));
|
||||
|
||||
VerifyOrExit(certCandidate < CERT_SET_COUNT, error = kErrorInvalidArgs);
|
||||
VerifyOrExit(certCandidate < CERT_SET_COUNT, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
mSelectedCert = certCandidate;
|
||||
|
||||
@@ -341,7 +340,7 @@ exit:
|
||||
* Done
|
||||
* @endcode
|
||||
* @par
|
||||
* Starts TCAT operation.
|
||||
* Starts TCAT agent and enables TCAT operation.
|
||||
* @sa otBleSecureSetCertificate
|
||||
* @sa otBleSecureSetCaCertificateChain
|
||||
* @sa otBleSecureSetSslAuthMode
|
||||
@@ -351,10 +350,10 @@ exit:
|
||||
*/
|
||||
template <> otError Tcat::Process<Cmd("start")>(Arg aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aArgs);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
ClearAllBytes(mVendorInfo);
|
||||
mVendorInfo.mPskdString = kPskdVendor;
|
||||
mVendorInfo.mProvisioningUrl = kUrl;
|
||||
@@ -399,35 +398,104 @@ exit:
|
||||
* Done
|
||||
* @endcode
|
||||
* @par
|
||||
* Stops TCAT operation.
|
||||
* Stops TCAT agent and stops TCAT operation.
|
||||
* @sa otBleSecureStop
|
||||
*/
|
||||
template <> otError Tcat::Process<Cmd("stop")>(Arg aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aArgs);
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
otBleSecureStop(GetInstancePtr());
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @cli tcat standby
|
||||
* @code
|
||||
* tcat standby
|
||||
* Done
|
||||
* @endcode
|
||||
* @par
|
||||
* Sets TCAT operation to standby, keeping the agent enabled.
|
||||
* @sa otBleSecureSetTcatAgentState
|
||||
*/
|
||||
template <> otError Tcat::Process<Cmd("standby")>(Arg aArgs[])
|
||||
{
|
||||
otError error;
|
||||
|
||||
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
error = otBleSecureSetTcatAgentState(GetInstancePtr(), false, 0, 0);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @cli tcat active
|
||||
* @code
|
||||
* tcat active
|
||||
* Done
|
||||
* @endcode
|
||||
* @code
|
||||
* tcat active 5000
|
||||
* Done
|
||||
* @endcode
|
||||
* @code
|
||||
* tcat active 5000 10000
|
||||
* Done
|
||||
* @endcode
|
||||
* @cparam tcat active [@ca{delay}] [@ca{duration}]
|
||||
* * The optional `delay` argument specifies the delay in milliseconds before activation.
|
||||
* * The optional `duration` argument specifies the duration in milliseconds to remain active.
|
||||
* A duration of 0 (default) means the TCAT agent remains active indefinitely.
|
||||
* @par
|
||||
* Sets TCAT operation to active.
|
||||
* @sa otBleSecureSetTcatAgentState
|
||||
*/
|
||||
template <> otError Tcat::Process<Cmd("active")>(Arg aArgs[])
|
||||
{
|
||||
otError error;
|
||||
uint32_t delay = 0;
|
||||
uint32_t duration = 0;
|
||||
|
||||
if (!aArgs[0].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[0].ParseAsUint32(delay));
|
||||
if (!aArgs[1].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[1].ParseAsUint32(duration));
|
||||
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
|
||||
error = otBleSecureSetTcatAgentState(GetInstancePtr(), true, delay, duration);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Tcat::Process(Arg aArgs[])
|
||||
{
|
||||
#define CmdEntry(aCommandString) {aCommandString, &Tcat::Process<Cmd(aCommandString)>}
|
||||
|
||||
static constexpr Command kCommands[] = {CmdEntry("advid"), CmdEntry("devid"), CmdEntry("start"), CmdEntry("stop")};
|
||||
static constexpr Command kCommands[] = {CmdEntry("active"), CmdEntry("advid"), CmdEntry("certid"),
|
||||
CmdEntry("devid"), CmdEntry("standby"), CmdEntry("start"),
|
||||
CmdEntry("stop")};
|
||||
|
||||
static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
|
||||
|
||||
#undef CmdEntry
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
otError error = OT_ERROR_INVALID_COMMAND;
|
||||
const Command *command;
|
||||
|
||||
if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
|
||||
{
|
||||
OutputCommandTable(kCommands);
|
||||
ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
|
||||
|
||||
@@ -57,7 +57,7 @@ otError otBleSecureStart(otInstance *aInstance,
|
||||
|
||||
otError otBleSecureSetTcatVendorInfo(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().TcatSetVendorInfo(AsCoreType(aVendorInfo));
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().SetTcatVendorInfo(AsCoreType(aVendorInfo));
|
||||
}
|
||||
|
||||
otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aHandler)
|
||||
@@ -67,6 +67,11 @@ otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aHandler)
|
||||
|
||||
void otBleSecureStop(otInstance *aInstance) { AsCoreType(aInstance).Get<Ble::BleSecure>().Stop(); }
|
||||
|
||||
otError otBleSecureSetTcatAgentState(otInstance *aInstance, bool aActive, uint32_t aDelayMs, uint32_t aDurationMs)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().TcatActive(aActive, aDelayMs, aDurationMs);
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
void otBleSecureSetPsk(otInstance *aInstance,
|
||||
const uint8_t *aPsk,
|
||||
@@ -174,9 +179,9 @@ bool otBleSecureIsConnectionActive(otInstance *aInstance)
|
||||
|
||||
bool otBleSecureIsConnected(otInstance *aInstance) { return AsCoreType(aInstance).Get<Ble::BleSecure>().IsConnected(); }
|
||||
|
||||
bool otBleSecureIsTcatEnabled(otInstance *aInstance)
|
||||
bool otBleSecureIsTcatAgentStarted(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().IsTcatEnabled();
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().IsTcatAgentStarted();
|
||||
}
|
||||
|
||||
bool otBleSecureIsCommandClassAuthorized(otInstance *aInstance, otTcatCommandClass aCommandClass)
|
||||
|
||||
@@ -235,7 +235,8 @@ Instance::Instance(void)
|
||||
, mApplicationCoapSecure(*this, kWithLinkSecurity)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
, mApplicationBleSecure(*this)
|
||||
, mBleSecure(*this)
|
||||
, mTcatAgent(*this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
, mPingSender(*this)
|
||||
|
||||
@@ -667,7 +667,8 @@ private:
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
Ble::BleSecure mApplicationBleSecure;
|
||||
Ble::BleSecure mBleSecure;
|
||||
MeshCoP::TcatAgent mTcatAgent;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
@@ -1113,7 +1114,8 @@ template <> inline Coap::ApplicationCoapSecure &Instance::Get(void) { return mAp
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
template <> inline Ble::BleSecure &Instance::Get(void) { return mApplicationBleSecure; }
|
||||
template <> inline Ble::BleSecure &Instance::Get(void) { return mBleSecure; }
|
||||
template <> inline MeshCoP::TcatAgent &Instance::Get(void) { return mTcatAgent; }
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
|
||||
+175
-79
@@ -32,12 +32,12 @@
|
||||
*/
|
||||
|
||||
#include "tcat_agent.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "crypto/storage.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "crypto/storage.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
#include "thread/network_diagnostic.hpp"
|
||||
|
||||
@@ -59,59 +59,111 @@ TcatAgent::TcatAgent(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mVendorInfo(nullptr)
|
||||
, mState(kStateDisabled)
|
||||
, mCommissionerHasNetworkName(false)
|
||||
, mCommissionerHasDomainName(false)
|
||||
, mCommissionerHasExtendedPanId(false)
|
||||
, mRandomChallenge(0)
|
||||
, mPskdVerified(false)
|
||||
, mPskcVerified(false)
|
||||
, mInstallCodeVerified(false)
|
||||
, mIsCommissioned(false)
|
||||
, mApplicationResponsePending(false)
|
||||
, mNextState(kStateDisabled)
|
||||
, mActiveOrStandbyTimer(aInstance)
|
||||
, mTcatActiveDurationMs(0)
|
||||
{
|
||||
mJoinerPskd.Clear();
|
||||
ClearCommissionerState();
|
||||
}
|
||||
|
||||
Error TcatAgent::Start(AppDataReceiveCallback aAppDataReceiveCallback, JoinCallback aHandler, void *aContext)
|
||||
void TcatAgent::ClearCommissionerState(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
LogInfo("Starting");
|
||||
VerifyOrExit(mVendorInfo != nullptr, error = kErrorFailed);
|
||||
mAppDataReceiveCallback.Set(aAppDataReceiveCallback, aContext);
|
||||
mJoinCallback.Set(aHandler, aContext);
|
||||
mRandomChallenge = 0;
|
||||
mState = kStateEnabled;
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "start TCAT agent");
|
||||
return error;
|
||||
}
|
||||
|
||||
void TcatAgent::Stop(void)
|
||||
{
|
||||
mState = kStateDisabled;
|
||||
mAppDataReceiveCallback.Clear();
|
||||
mJoinCallback.Clear();
|
||||
mCommissionerAuthorizationField = {};
|
||||
mCommissionerExtendedPanId.Clear();
|
||||
mCommissionerHasNetworkName = false;
|
||||
mCommissionerHasDomainName = false;
|
||||
mCommissionerHasExtendedPanId = false;
|
||||
mCommissionerNetworkName.m8[0] = '\0';
|
||||
mCommissionerDomainName.m8[0] = '\0';
|
||||
mCommissionerNetworkName.m8[0] = kNullChar;
|
||||
mCommissionerDomainName.m8[0] = kNullChar;
|
||||
mRandomChallenge = 0;
|
||||
mPskdVerified = false;
|
||||
mPskcVerified = false;
|
||||
mInstallCodeVerified = false;
|
||||
mIsCommissioned = false;
|
||||
LogInfo("TCAT agent stopped");
|
||||
mApplicationResponsePending = false;
|
||||
}
|
||||
|
||||
Error TcatAgent::Start(AppDataReceiveCallback aAppDataReceiveCallback, JoinCallback aJoinHandler, void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(!IsStarted(), error = kErrorAlready);
|
||||
VerifyOrExit(mVendorInfo != nullptr, error = kErrorFailed);
|
||||
|
||||
mAppDataReceiveCallback.Set(aAppDataReceiveCallback, aContext);
|
||||
mJoinCallback.Set(aJoinHandler, aContext);
|
||||
mState = kStateActive;
|
||||
mNextState = kStateActive;
|
||||
mTcatActiveDurationMs = 0;
|
||||
mActiveOrStandbyTimer.Stop();
|
||||
LogInfo("Start");
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "Start");
|
||||
return error;
|
||||
}
|
||||
|
||||
// Note: closing the TLS is handled by the transport class like #BleSecure
|
||||
void TcatAgent::Stop(void)
|
||||
{
|
||||
mAppDataReceiveCallback.Clear();
|
||||
mJoinCallback.Clear();
|
||||
mState = kStateDisabled;
|
||||
ClearCommissionerState();
|
||||
LogInfo("Stop");
|
||||
}
|
||||
|
||||
Error TcatAgent::Standby(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsStarted(), error = kErrorInvalidState);
|
||||
|
||||
mTcatActiveDurationMs = 0;
|
||||
mActiveOrStandbyTimer.Stop();
|
||||
mNextState = kStateStandby;
|
||||
if (!IsConnected())
|
||||
{
|
||||
// if already TLS-connected, only move to 'standby' once the connection is done.
|
||||
// if not yet fully connected, go to 'standby' immediately (ignoring a TLS handshake that may be ongoing)
|
||||
mState = kStateStandby;
|
||||
NotifyStateChange();
|
||||
LogInfo("Standby");
|
||||
}
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "Standby");
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TcatAgent::Activate(const uint32_t aDelayMs, const uint32_t aDurationMs)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsStarted(), error = kErrorInvalidState);
|
||||
|
||||
mTcatActiveDurationMs = aDurationMs;
|
||||
if (aDelayMs > 0)
|
||||
{
|
||||
mActiveOrStandbyTimer.Start(aDelayMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleTimer();
|
||||
}
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "Activate");
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TcatAgent::SetTcatVendorInfo(const VendorInfo &aVendorInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
JoinerPskd pskd;
|
||||
|
||||
VerifyOrExit(aVendorInfo.IsValid(), error = kErrorInvalidArgs);
|
||||
SuccessOrExit(error = mJoinerPskd.SetFrom(aVendorInfo.mPskdString));
|
||||
SuccessOrExit(error = pskd.SetFrom(aVendorInfo.mPskdString));
|
||||
mVendorInfo = &aVendorInfo;
|
||||
|
||||
exit:
|
||||
@@ -123,7 +175,10 @@ Error TcatAgent::Connected(MeshCoP::Tls::Extension &aTls)
|
||||
size_t len;
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
|
||||
VerifyOrExit(IsStarted() && !IsConnected() && mState != kStateStandby && mState != kStateStandbyTemporary,
|
||||
error = kErrorInvalidState);
|
||||
ClearCommissionerState();
|
||||
|
||||
len = sizeof(mCommissionerAuthorizationField);
|
||||
SuccessOrExit(
|
||||
error = aTls.GetThreadAttributeFromPeerCertificate(
|
||||
@@ -137,10 +192,6 @@ Error TcatAgent::Connected(MeshCoP::Tls::Extension &aTls)
|
||||
VerifyOrExit(len == sizeof(mDeviceAuthorizationField), error = kErrorParse);
|
||||
VerifyOrExit((mDeviceAuthorizationField.mHeader & kCommissionerFlag) == 0, error = kErrorParse);
|
||||
|
||||
mCommissionerHasDomainName = false;
|
||||
mCommissionerHasNetworkName = false;
|
||||
mCommissionerHasExtendedPanId = false;
|
||||
|
||||
len = sizeof(mCommissionerDomainName) - 1;
|
||||
if (aTls.GetThreadAttributeFromPeerCertificate(
|
||||
kCertificateDomainName, reinterpret_cast<uint8_t *>(&mCommissionerDomainName), &len) == kErrorNone)
|
||||
@@ -167,9 +218,15 @@ Error TcatAgent::Connected(MeshCoP::Tls::Extension &aTls)
|
||||
}
|
||||
}
|
||||
|
||||
mState = kStateConnected;
|
||||
// A temporary enablement stops after disconnect: to standby.
|
||||
// For others, return to prior state, upon disconnect.
|
||||
mNextState = (mState == kStateActiveTemporary) ? kStateStandby : mState;
|
||||
mState = kStateConnected;
|
||||
NotifyStateChange();
|
||||
LogInfo("Connected");
|
||||
|
||||
// This specifically stores the state IsCommissioned at _start_ of session:
|
||||
mIsCommissioned = Get<ActiveDatasetManager>().IsCommissioned();
|
||||
LogInfo("TCAT agent connected");
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -179,15 +236,11 @@ void TcatAgent::Disconnected(void)
|
||||
{
|
||||
if (mState != kStateDisabled)
|
||||
{
|
||||
mState = kStateEnabled;
|
||||
mState = mNextState;
|
||||
NotifyStateChange();
|
||||
LogInfo("Disconnected");
|
||||
ClearCommissionerState();
|
||||
}
|
||||
|
||||
mRandomChallenge = 0;
|
||||
mPskdVerified = false;
|
||||
mPskcVerified = false;
|
||||
mInstallCodeVerified = false;
|
||||
|
||||
LogInfo("TCAT agent disconnected");
|
||||
}
|
||||
|
||||
uint8_t TcatAgent::CheckAuthorizationRequirements(CommandClassFlags aFlagsRequired, Dataset::Info *aDatasetInfo) const
|
||||
@@ -248,7 +301,7 @@ uint8_t TcatAgent::CheckAuthorizationRequirements(CommandClassFlags aFlagsRequir
|
||||
break;
|
||||
|
||||
default:
|
||||
LogCrit("Error while processing access flags. Unexpected flag %d", flag);
|
||||
LogCrit("Error in access flags. Unexpected flag %d", flag);
|
||||
OT_ASSERT(false); // Should not get here
|
||||
}
|
||||
}
|
||||
@@ -405,7 +458,7 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncomingMessage, Message &aOutg
|
||||
break;
|
||||
|
||||
case kTlvDecommission:
|
||||
error = HandleDecomission();
|
||||
error = HandleDecommission();
|
||||
break;
|
||||
|
||||
case kTlvPing:
|
||||
@@ -546,7 +599,6 @@ exit:
|
||||
Error TcatAgent::HandleGetActiveOperationalDataset(Message &aOutgoingMessage, bool &aResponse)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Dataset dataset;
|
||||
Dataset::Tlvs datasetTlvs;
|
||||
|
||||
VerifyOrExit(IsCommandClassAuthorized(kExtraction), error = kErrorRejected);
|
||||
@@ -596,7 +648,7 @@ Error TcatAgent::HandleGetDiagnosticTlvs(const Message &aIncomingMessage,
|
||||
offsetRange.Init(aOffset, aLength);
|
||||
initialLength = aOutgoingMessage.GetLength();
|
||||
|
||||
// Start with extTlv to avoid the need for a temporary message buffer to calucalate reply length
|
||||
// Start with extTlv to avoid the need for a temporary message buffer to calculate reply length
|
||||
extTlv.SetType(kTlvResponseWithPayload);
|
||||
extTlv.SetLength(0);
|
||||
SuccessOrExit(error = aOutgoingMessage.Append(extTlv));
|
||||
@@ -633,7 +685,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TcatAgent::HandleDecomission(void)
|
||||
Error TcatAgent::HandleDecommission(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
unsigned char buf[kCommissionerCertMaxLength];
|
||||
@@ -992,6 +1044,8 @@ Error TcatAgent::HandleStartThreadInterface(void)
|
||||
error = Get<Mle::Mle>().Start();
|
||||
|
||||
exit:
|
||||
// error values for callback MUST be limited to the allowed set, see #JoinCallback
|
||||
mJoinCallback.InvokeIfSet(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1004,14 +1058,56 @@ Error TcatAgent::HandleStopThreadInterface(void)
|
||||
error = otThreadSetEnabled(&GetInstance(), false);
|
||||
|
||||
exit:
|
||||
mJoinCallback.InvokeIfSet(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
void SeralizeTcatAdvertisementTlv(uint8_t *aBuffer,
|
||||
uint16_t &aOffset,
|
||||
TcatAdvertisementTlvType aType,
|
||||
uint16_t aLength,
|
||||
const uint8_t *aValue)
|
||||
// called when TCAT active-or-standby timer expires
|
||||
void TcatAgent::HandleTimer(void)
|
||||
{
|
||||
switch (mState)
|
||||
{
|
||||
case kStateStandby:
|
||||
case kStateStandbyTemporary:
|
||||
if (mTcatActiveDurationMs > 0)
|
||||
{
|
||||
mActiveOrStandbyTimer.Start(mTcatActiveDurationMs);
|
||||
mState = kStateActiveTemporary;
|
||||
}
|
||||
else
|
||||
{
|
||||
mState = kStateActive;
|
||||
}
|
||||
NotifyStateChange();
|
||||
LogInfo("Active");
|
||||
break;
|
||||
|
||||
case kStateActiveTemporary:
|
||||
IgnoreError(Standby());
|
||||
break;
|
||||
|
||||
case kStateConnected:
|
||||
mNextState = (mTcatActiveDurationMs > 0) ? kStateStandby : kStateActive;
|
||||
break;
|
||||
|
||||
// kStateActive: will not go to standby, based on timer. Application has forced it to 'active'.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// internally called when TcatAgent state changes: perform any required actions.
|
||||
void TcatAgent::NotifyStateChange(void)
|
||||
{
|
||||
Get<Ble::BleSecure>().NotifySendAdvertisements(mState == kStateActive || mState == kStateActiveTemporary ||
|
||||
mState == kStateConnected);
|
||||
}
|
||||
|
||||
void SerializeTcatAdvertisementTlv(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);
|
||||
@@ -1040,24 +1136,24 @@ Error TcatAgent::GetAdvertisementData(uint16_t &aLen, uint8_t *aAdvertisementDat
|
||||
switch (MapEnum(mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdType))
|
||||
{
|
||||
case kTcatDeviceIdOui24:
|
||||
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorOui24,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdLen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceId);
|
||||
SerializeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorOui24,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdLen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceId);
|
||||
break;
|
||||
case kTcatDeviceIdOui36:
|
||||
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorOui36,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdLen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceId);
|
||||
SerializeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorOui36,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdLen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceId);
|
||||
break;
|
||||
case kTcatDeviceIdDiscriminator:
|
||||
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvDeviceDiscriminator,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdLen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceId);
|
||||
SerializeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvDeviceDiscriminator,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdLen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceId);
|
||||
break;
|
||||
case kTcatDeviceIdIanaPen:
|
||||
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorIanaPen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdLen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceId);
|
||||
SerializeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvVendorIanaPen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceIdLen,
|
||||
mVendorInfo->mAdvertisedDeviceIds[i].mDeviceId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1069,8 +1165,8 @@ Error TcatAgent::GetAdvertisementData(uint16_t &aLen, uint8_t *aAdvertisementDat
|
||||
|
||||
if (caps.mGattNotifications || caps.mL2CapDirect)
|
||||
{
|
||||
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvBleLinkCapabilities, kTlvBleLinkCapabilitiesLength,
|
||||
reinterpret_cast<uint8_t *>(&caps));
|
||||
SerializeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvBleLinkCapabilities, kTlvBleLinkCapabilitiesLength,
|
||||
reinterpret_cast<uint8_t *>(&caps));
|
||||
}
|
||||
|
||||
tas.mRsv = 0;
|
||||
@@ -1089,8 +1185,8 @@ Error TcatAgent::GetAdvertisementData(uint16_t &aLen, uint8_t *aAdvertisementDat
|
||||
tas.mIsBorderRouter = false;
|
||||
#endif
|
||||
|
||||
SeralizeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvDeviceTypeAndStatus, kTlvDeviceTypeAndStatusLength,
|
||||
reinterpret_cast<uint8_t *>(&tas));
|
||||
SerializeTcatAdvertisementTlv(aAdvertisementData, aLen, kTlvDeviceTypeAndStatus, kTlvDeviceTypeAndStatusLength,
|
||||
reinterpret_cast<uint8_t *>(&tas));
|
||||
OT_ASSERT(aLen <= OT_TCAT_ADVERTISEMENT_MAX_LEN);
|
||||
|
||||
exit:
|
||||
|
||||
+113
-45
@@ -63,18 +63,21 @@ namespace MeshCoP {
|
||||
|
||||
class TcatAgent : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
friend class Ble::BleSecure;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Pointer to call when application data was received over the TLS connection.
|
||||
*
|
||||
* Please see otHandleTcatApplicationDataReceive for details.
|
||||
* Please see #otHandleTcatApplicationDataReceive for details.
|
||||
*/
|
||||
typedef otHandleTcatApplicationDataReceive AppDataReceiveCallback;
|
||||
|
||||
/**
|
||||
* Pointer to call to notify the completion of a join operation.
|
||||
* Pointer to call to notify the completion of a Thread Network join/leave operation under
|
||||
* guidance of a TCAT Commissioner.
|
||||
*
|
||||
* Please see otHandleTcatJoin for details.
|
||||
* Please see #otHandleTcatJoin for details.
|
||||
*/
|
||||
typedef otHandleTcatJoin JoinCallback;
|
||||
|
||||
@@ -97,7 +100,7 @@ public:
|
||||
enum CertificateAuthorizationFieldHeader : uint8_t
|
||||
{
|
||||
kCommissionerFlag = 1 << 0, ///< TCAT commissioner ('1') or device ('0')
|
||||
kHeaderVersion = 0xD0, ///< Header version (3 bits)
|
||||
kHeaderVersion = 0xD0, ///< Header version (3 bits MSB)
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -115,14 +118,13 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a data structure for storing TCAT Commissioner authorization information in the
|
||||
* certificate ASN.1 field 1.3.6.1.4.1.44970.3.
|
||||
* certificate ASN.1 OID field 1.3.6.1.4.1.44970.3.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct CertificateAuthorizationField
|
||||
{
|
||||
CertificateAuthorizationFieldHeader mHeader; ///< Typ and version
|
||||
CertificateAuthorizationFieldHeader mHeader; ///< Type and version
|
||||
CommandClassFlags mCommissioningFlags; ///< Command class flags
|
||||
CommandClassFlags mExtractionFlags; ///< Command class flags
|
||||
CommandClassFlags mDecommissioningFlags; ///< Command class flags
|
||||
@@ -133,7 +135,7 @@ public:
|
||||
typedef CertificateAuthorizationField CertificateAuthorizationField;
|
||||
|
||||
/**
|
||||
* Represents the TCAT vendor information.
|
||||
* Represents the TCAT Device vendor information.
|
||||
*/
|
||||
class VendorInfo : public otTcatVendorInfo
|
||||
{
|
||||
@@ -168,16 +170,16 @@ public:
|
||||
kTlvRequestPskdHash = 0x14, ///< TCAT PSKd hash request TLV
|
||||
|
||||
// Command Class Commissioning
|
||||
kTlvSetActiveOperationalDataset = 0x20, ///< TCAT active operational dataset TLV
|
||||
kTlvSetActiveOperationalDatasetAlternative = 0x21, ///< TCAT active operational dataset alternative #1 TLV
|
||||
kTlvGetCommissionerCertificate = 0x25, ///< TCAT commissioner certificate query TLV
|
||||
kTlvGetDiagnosticTlvs = 0x26, ///< TCAT diagnostics TLVs query TLV
|
||||
kTlvStartThreadInterface = 0x27, ///< TCAT start thread interface request TLV
|
||||
kTlvStopThreadInterface = 0x28, ///< TCAT stop thread interface request TLV
|
||||
kTlvSetActiveOperationalDataset = 0x20, ///< TCAT active operational dataset TLV
|
||||
kTlvSetActiveOperationalDatasetAlt = 0x21, ///< TCAT active operational dataset alternative #1 TLV (reserved)
|
||||
kTlvGetCommissionerCertificate = 0x25, ///< TCAT commissioner certificate query TLV
|
||||
kTlvGetDiagnosticTlvs = 0x26, ///< TCAT diagnostics TLVs query TLV
|
||||
kTlvStartThreadInterface = 0x27, ///< TCAT start thread interface request TLV
|
||||
kTlvStopThreadInterface = 0x28, ///< TCAT stop thread interface request TLV
|
||||
|
||||
// Command Class Extraction
|
||||
kTlvGetActiveOperationalDataset = 0x40, ///< TCAT active oerational dataset query TLV
|
||||
kTlvGetActiveOperationalDatasetAlternative = 0x41, ///< TCAT active oerational dataset alternative #1 query TLV
|
||||
kTlvGetActiveOperationalDataset = 0x40, ///< TCAT active operational dataset query TLV
|
||||
kTlvGetActiveOperationalDatasetAlt = 0x41, ///< TCAT active operational dataset alternative #1 query TLV (rsv)
|
||||
|
||||
// Command Class Decommissioning
|
||||
kTlvDecommission = 0x60, ///< TCAT decommission request TLV
|
||||
@@ -193,9 +195,9 @@ public:
|
||||
kTlvSendVendorSpecificData = 0x9F, ///< TCAT send vendor specific command or data TLV
|
||||
|
||||
// Command Class CCM
|
||||
kTlvSetLDevIdOperationalCert = 0xA0, ///< TCAT LDevID operational certificate TLV
|
||||
kTlvSetLDevIdPrivateKey = 0xA1, ///< TCAT LDevID operational certificate pricate key TLV
|
||||
kTlvSetDomainCaCert = 0xA2, ///< TCAT domain CA certificate TLV
|
||||
kTlvSetLDevIdOperationalCert = 0xA0, ///< TCAT set LDevID operational certificate TLV (reserved)
|
||||
kTlvSetLDevIdPrivateKey = 0xA1, ///< TCAT set LDevID operational certificate private key TLV (reserved)
|
||||
kTlvSetDomainCaCert = 0xA2, ///< TCAT set domain CA certificate TLV (reserved)
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -238,7 +240,7 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a TCAT certificate V3 extension attribute (OID 1.3.6.1.4.1.44970.x).
|
||||
* Represents a TCAT certificate V3 extension attribute (ASN.1 OID 1.3.6.1.4.1.44970.x).
|
||||
*/
|
||||
enum TcatCertificateAttribute
|
||||
{
|
||||
@@ -250,13 +252,16 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents TCAT status.
|
||||
* Represents TCAT agent state.
|
||||
*/
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateDisabled,
|
||||
kStateEnabled,
|
||||
kStateConnected,
|
||||
kStateDisabled, // TCAT not initialized - can only be enabled by the local application
|
||||
kStateStandby, // TCAT initialized, waiting for activation by local app or via TMF, no advertisements
|
||||
kStateStandbyTemporary, // Like Standby, but after a time period, will go to Active
|
||||
kStateActive, // TCAT active to receive a connection, TCAT advertisements sent
|
||||
kStateActiveTemporary, // Like Active, but after a time period, will go to Standby
|
||||
kStateConnected, // TCAT Commissioner is currently connected
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -279,36 +284,87 @@ public:
|
||||
explicit TcatAgent(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* Enables the TCAT agent.
|
||||
* Starts/initializes the TCAT agent and activates TCAT functions.
|
||||
*
|
||||
* State transitions to kStateEnabled, TCAT Advertisements are sent, and connections
|
||||
* from TCAT Commissioners are allowed.
|
||||
* After Start(), optionally #Standby() can be used to immediately set the agent to standby mode.
|
||||
*
|
||||
* @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] aJoinHandler A pointer to a function that is called when a network join/leave operation
|
||||
* completes, under guidance of the TCAT Commissioner.
|
||||
* @param[in] aContext A context pointer.
|
||||
*
|
||||
* @retval kErrorNone Successfully started the TCAT agent.
|
||||
* @retval kErrorFailed Failed to start due to missing vendor info.
|
||||
* @retval kErrorFailed Failed to start due to missing vendor info. This info must be set with
|
||||
* #SetTcatVendorInfo().
|
||||
*/
|
||||
Error Start(AppDataReceiveCallback aAppDataReceiveCallback, JoinCallback aHandler, void *aContext);
|
||||
Error Start(AppDataReceiveCallback aAppDataReceiveCallback, JoinCallback aJoinHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* Stops the TCAT agent.
|
||||
*
|
||||
* State transitions to kStateDisabled. TCAT can only be enabled again via Start().
|
||||
* Any ongoing TCAT Commissioner connections are forcibly interrupted and any scheduled
|
||||
* activations are cleared.
|
||||
*/
|
||||
void Stop(void);
|
||||
|
||||
/**
|
||||
* Set the TCAT Vendor Info object
|
||||
* Sets the TCAT agent to standby state, deactivating TCAT functions.
|
||||
*
|
||||
* State transitions to kStateStandby. The callback information from Start() is retained.
|
||||
* In this state, TCAT Advertisements are not sent and new TCAT Commissioners cannot connect.
|
||||
* However, any existing connected TCAT Commissioner remains connected, postponing the
|
||||
* standby until this connection finalizes.
|
||||
*
|
||||
* TCAT can be activated again via Activate() or by receiving a TCAT_ENABLE.req TMF message.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the TCAT agent to kStateStandby, OR scheduled
|
||||
* to go to standby after the current connection closes.
|
||||
* @retval kErrorInvalidState If not in a suitable state to transition to kStateStandby.
|
||||
*/
|
||||
Error Standby(void);
|
||||
|
||||
/**
|
||||
* Activate TCAT functions of the TCAT agent.
|
||||
*
|
||||
* This requires the TCAT agent to be already started.
|
||||
* The state transitions to kStateActive of kStateActiveTemporary. In these states, TCAT Advertisements
|
||||
* are actively sent and TCAT Commissioners are able to connect. From here, TCAT can be set to standby
|
||||
* again using Standby().
|
||||
* If a connection is ongoing and aDurationMs==0, this call will ensure that kStateActive will
|
||||
* be kept after this connection is finished.
|
||||
* This function will override any ongoing temporary activation of TCAT, or any
|
||||
* previously scheduled activation for a future time.
|
||||
*
|
||||
* @param[in] aDelayMs Delay in ms before activating. If 0, activate immediately.
|
||||
* @param[in] aDurationMs Duration in ms of the activation. If 0, activate indefinitely.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the TCAT agent to kStateActive now, OR scheduled
|
||||
* for going to kStateActive after the current connection will finish.
|
||||
* @retval kErrorInvalidState If not in a suitable state to transition to kStateActive.
|
||||
*/
|
||||
Error Activate(uint32_t aDelayMs, uint32_t aDurationMs);
|
||||
|
||||
/**
|
||||
* Set the TCAT Device 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.
|
||||
* Indicates whether or not the TCAT agent has been started.
|
||||
*
|
||||
* @retval TRUE The TCAT agent is enabled.
|
||||
* @retval FALSE The TCAT agent is not enabled.
|
||||
* Any state other than kStateDisabled indicates it is started. Depending on the details
|
||||
* of TcatAgent::State, the TCAT features offered by the agent may either be active or inactive.
|
||||
* See #Start().
|
||||
*
|
||||
* @retval TRUE The TCAT agent is started.
|
||||
* @retval FALSE The TCAT agent is not started.
|
||||
*/
|
||||
bool IsEnabled(void) const { return mState != kStateDisabled; }
|
||||
bool IsStarted(void) const { return mState != kStateDisabled; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TCAT agent is connected.
|
||||
@@ -323,33 +379,44 @@ public:
|
||||
*
|
||||
* @param[in] aCommandClass Command class to subject to authorization check.
|
||||
*
|
||||
* @retval TRUE The command class is authorized for use by the present TCAT commissioner.
|
||||
* @retval TRUE The command class is authorized for use by the present (if any) TCAT commissioner.
|
||||
* @retval FALSE The command class is not authorized for use.
|
||||
*/
|
||||
bool IsCommandClassAuthorized(CommandClass aCommandClass) const;
|
||||
|
||||
/**
|
||||
* Gets TCAT advertisement data.
|
||||
* Gets TCAT advertisement data from the TCAT agent.
|
||||
*
|
||||
* @param[out] aLen Advertisement data length (up to OT_TCAT_ADVERTISEMENT_MAX_LEN).
|
||||
* @param[out] aAdvertisementData Advertisement data.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the TCAT advertisement data.
|
||||
* @retval kErrorInvalidArgs The data could not be retrieved, or aAdvertisementData is null.
|
||||
* @retval kErrorInvalidArgs The vendor data could not be retrieved, or aAdvertisementData is null.
|
||||
*/
|
||||
Error GetAdvertisementData(uint16_t &aLen, uint8_t *aAdvertisementData);
|
||||
|
||||
/**
|
||||
* @brief Gets the Install Code Verify Status during the current session.
|
||||
* @brief Gets the Install Code Verify Status of the current TCAT Commissioner session.
|
||||
*
|
||||
* @retval TRUE The install code was correctly verified.
|
||||
* @retval FALSE The install code was not verified.
|
||||
*/
|
||||
bool GetInstallCodeVerifyStatus(void) const { return mInstallCodeVerified; }
|
||||
bool GetApplicationResponsePending(void) { return mApplicationResponsePending; }
|
||||
void NotifyApplicationResponseSent(void) { mApplicationResponsePending = false; }
|
||||
|
||||
/**
|
||||
* Gets the current pending state for an application protocol response from the
|
||||
* TCAT agent.
|
||||
*
|
||||
* @retval TRUE There is an application protocol response pending to be sent
|
||||
* by the TCAT transport/link layer.
|
||||
* @retval FALSE There is no application protocol response pending to be sent.
|
||||
*/
|
||||
bool GetApplicationResponsePending(void) const { return mApplicationResponsePending; }
|
||||
|
||||
private:
|
||||
void NotifyApplicationResponseSent(void) { mApplicationResponsePending = false; }
|
||||
void NotifyStateChange(void);
|
||||
void ClearCommissionerState();
|
||||
Error Connected(MeshCoP::Tls::Extension &aTls);
|
||||
void Disconnected(void);
|
||||
|
||||
@@ -361,7 +428,7 @@ private:
|
||||
uint16_t aOffset,
|
||||
uint16_t aLength,
|
||||
bool &response);
|
||||
Error HandleDecomission(void);
|
||||
Error HandleDecommission(void);
|
||||
Error HandlePing(const Message &aIncomingMessage,
|
||||
Message &aOutgoingMessage,
|
||||
uint16_t aOffset,
|
||||
@@ -388,6 +455,7 @@ private:
|
||||
uint16_t aOffset,
|
||||
TcatApplicationProtocol aApplicationProtocol,
|
||||
bool &aResponse);
|
||||
void HandleTimer(void);
|
||||
|
||||
Error VerifyHash(const Message &aIncomingMessage,
|
||||
uint16_t aOffset,
|
||||
@@ -401,7 +469,6 @@ private:
|
||||
Dataset *aDataset) const;
|
||||
uint8_t CheckAuthorizationRequirements(CommandClassFlags aFlagsChecked, Dataset::Info *aDatasetInfo) const;
|
||||
|
||||
static constexpr uint16_t kJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
|
||||
static constexpr uint16_t kPingPayloadMaxLength = 512;
|
||||
static constexpr uint16_t kProvisioningUrlMaxLength = 64;
|
||||
static constexpr uint16_t kMaxPskdLength = OT_JOINER_MAX_PSKD_LENGTH;
|
||||
@@ -412,7 +479,6 @@ private:
|
||||
static constexpr uint8_t kServiceNameMaxLength = OT_TCAT_SERVICE_NAME_MAX_LENGTH;
|
||||
static constexpr uint8_t kApplicationLayerMaxCount = OT_TCAT_APPLICATION_LAYER_MAX_COUNT;
|
||||
|
||||
JoinerPskd mJoinerPskd;
|
||||
const VendorInfo *mVendorInfo;
|
||||
Callback<JoinCallback> mJoinCallback;
|
||||
Callback<AppDataReceiveCallback> mAppDataReceiveCallback;
|
||||
@@ -422,6 +488,7 @@ private:
|
||||
NetworkName mCommissionerDomainName;
|
||||
ExtendedPanId mCommissionerExtendedPanId;
|
||||
State mState;
|
||||
State mNextState;
|
||||
bool mCommissionerHasNetworkName : 1;
|
||||
bool mCommissionerHasDomainName : 1;
|
||||
bool mCommissionerHasExtendedPanId : 1;
|
||||
@@ -431,8 +498,9 @@ private:
|
||||
bool mInstallCodeVerified : 1;
|
||||
bool mIsCommissioned : 1;
|
||||
bool mApplicationResponsePending : 1;
|
||||
|
||||
friend class Ble::BleSecure;
|
||||
using ExpireTimer = TimerMilliIn<TcatAgent, &TcatAgent::HandleTimer>;
|
||||
ExpireTimer mActiveOrStandbyTimer;
|
||||
uint32_t mTcatActiveDurationMs;
|
||||
};
|
||||
|
||||
} // namespace MeshCoP
|
||||
@@ -446,7 +514,7 @@ DefineMapEnum(otTcatAdvertisedDeviceIdType, MeshCoP::TcatAgent::TcatDeviceIdType
|
||||
typedef UintTlvInfo<MeshCoP::TcatAgent::kTlvResponseWithStatus, uint8_t> ResponseWithStatusTlv;
|
||||
|
||||
/**
|
||||
* Represent Device Type and Status
|
||||
* Represent TCAT Device Type and Status
|
||||
*/
|
||||
struct DeviceTypeAndStatus
|
||||
{
|
||||
|
||||
@@ -51,12 +51,12 @@ BleSecure::BleSecure(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, MeshCoP::Tls::Extension(mTls)
|
||||
, mTls(aInstance, kNoLinkSecurity, *this)
|
||||
, mTcatAgent(aInstance)
|
||||
, mTlvMode(false)
|
||||
, mReceivedMessage(nullptr)
|
||||
, mSendMessage(nullptr)
|
||||
, mTransmitTask(aInstance)
|
||||
, mBleState(kStopped)
|
||||
, mBleAdvRequestedState(kAdvertising)
|
||||
, mMtuSize(kInitialMtuSize)
|
||||
{
|
||||
}
|
||||
@@ -77,31 +77,36 @@ Error BleSecure::Start(ConnectCallback aConnectHandler, ReceiveCallback aReceive
|
||||
SuccessOrExit(error = otPlatBleEnable(&GetInstance()));
|
||||
|
||||
SuccessOrExit(error = otPlatBleGetAdvertisementBuffer(&GetInstance(), &advertisementData));
|
||||
SuccessOrExit(error = mTcatAgent.GetAdvertisementData(advertisementLen, advertisementData));
|
||||
SuccessOrExit(error = Get<MeshCoP::TcatAgent>().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());
|
||||
mTls.SetReceiveCallback(HandleTlsReceive, this);
|
||||
mTls.SetConnectCallback(HandleTlsConnectEvent, this);
|
||||
SuccessOrExit(error = mTls.Bind(HandleTransport, this));
|
||||
|
||||
// attempt to start BLE advertising only if everything else succeeded.
|
||||
mBleState = kNotAdvertising;
|
||||
mBleAdvRequestedState = kAdvertising;
|
||||
error = SetRequestedBleAdvertisementsState();
|
||||
|
||||
exit:
|
||||
if (error == kErrorNone)
|
||||
if (error != kErrorNone && error != kErrorAlready)
|
||||
{
|
||||
mBleState = kAdvertising;
|
||||
mTls.Close();
|
||||
mBleState = kStopped;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
Error BleSecure::TcatStart(MeshCoP::TcatAgent::JoinCallback aJoinHandler)
|
||||
Error BleSecure::TcatStart(const MeshCoP::TcatAgent::JoinCallback aHandler)
|
||||
{
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(mBleState != kStopped, error = kErrorInvalidState);
|
||||
VerifyOrExit(mBleState != kStopped && mTlvMode, error = kErrorInvalidState);
|
||||
|
||||
error = mTcatAgent.Start(mReceiveCallback.GetHandler(), aJoinHandler, mReceiveCallback.GetContext());
|
||||
error = Get<MeshCoP::TcatAgent>().Start(mReceiveCallback.GetHandler(), aHandler, mReceiveCallback.GetContext());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -110,17 +115,16 @@ exit:
|
||||
void BleSecure::Stop(void)
|
||||
{
|
||||
VerifyOrExit(mBleState != kStopped);
|
||||
SuccessOrExit(otPlatBleGapAdvStop(&GetInstance()));
|
||||
SuccessOrExit(otPlatBleDisable(&GetInstance()));
|
||||
mBleState = kStopped;
|
||||
mMtuSize = kInitialMtuSize;
|
||||
|
||||
if (mTcatAgent.IsEnabled())
|
||||
{
|
||||
mTcatAgent.Stop();
|
||||
}
|
||||
// Even if stop-advertisements or disable BLE would fail, we continue closing TLS and stopping TCAT agent.
|
||||
IgnoreError(otPlatBleGapAdvStop(&GetInstance()));
|
||||
IgnoreError(otPlatBleDisable(&GetInstance()));
|
||||
mBleState = kStopped;
|
||||
mBleAdvRequestedState = kStopped;
|
||||
mMtuSize = kInitialMtuSize;
|
||||
|
||||
mTls.Close();
|
||||
Get<MeshCoP::TcatAgent>().Stop();
|
||||
|
||||
mTransmitQueue.DequeueAndFreeAll();
|
||||
|
||||
@@ -136,6 +140,25 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error BleSecure::TcatActive(bool aActive, uint32_t aDelayMs, uint32_t aDurationMs)
|
||||
{
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(mBleState != kStopped, error = kErrorInvalidState);
|
||||
|
||||
if (aActive)
|
||||
{
|
||||
error = Get<MeshCoP::TcatAgent>().Activate(aDelayMs, aDurationMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = Get<MeshCoP::TcatAgent>().Standby();
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error BleSecure::Connect(void)
|
||||
{
|
||||
Ip6::SockAddr sockaddr;
|
||||
@@ -158,14 +181,14 @@ void BleSecure::Disconnect(void)
|
||||
|
||||
if (mBleState == kConnected)
|
||||
{
|
||||
mBleState = kAdvertising;
|
||||
// request platform to close BLE. Once this closing is done, #HandleBleDisconnected will
|
||||
// be called by the platform, which will call BleSecure::Disconnect again.
|
||||
IgnoreError(otPlatBleGapDisconnect(&GetInstance()));
|
||||
}
|
||||
|
||||
// Update advertisement
|
||||
IgnoreError(NotifyAdvertisementChanged());
|
||||
|
||||
mConnectCallback.InvokeIfSet(&GetInstance(), false, false);
|
||||
// Update advertisement data
|
||||
IgnoreError(NotifyAdvertisementChanged());
|
||||
}
|
||||
|
||||
Error BleSecure::NotifyAdvertisementChanged(void)
|
||||
@@ -176,13 +199,42 @@ Error BleSecure::NotifyAdvertisementChanged(void)
|
||||
|
||||
VerifyOrExit(mBleState == kAdvertising);
|
||||
SuccessOrExit(error = otPlatBleGetAdvertisementBuffer(&GetInstance(), &advertisementData));
|
||||
SuccessOrExit(error = mTcatAgent.GetAdvertisementData(advertisementLen, advertisementData));
|
||||
SuccessOrExit(error = Get<MeshCoP::TcatAgent>().GetAdvertisementData(advertisementLen, advertisementData));
|
||||
SuccessOrExit(error = otPlatBleGapAdvUpdateData(&GetInstance(), advertisementData, advertisementLen));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void BleSecure::NotifySendAdvertisements(bool aSendAdvertisements)
|
||||
{
|
||||
mBleAdvRequestedState = aSendAdvertisements ? kAdvertising : kNotAdvertising;
|
||||
IgnoreError(SetRequestedBleAdvertisementsState());
|
||||
}
|
||||
|
||||
// performs platform calls to start or stop BLE advertisements as requested, and if successful
|
||||
// update mBleState to reflect actual state of kAdvertising / kNotAdvertising.
|
||||
Error BleSecure::SetRequestedBleAdvertisementsState(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
// Must not make GapAdv platform calls when kStopped, or kConnected.
|
||||
if (mBleAdvRequestedState == kAdvertising && mBleState == kNotAdvertising)
|
||||
{
|
||||
SuccessOrExit(error = otPlatBleGapAdvStart(&GetInstance(), OT_BLE_ADV_INTERVAL_DEFAULT));
|
||||
mBleState = kAdvertising;
|
||||
}
|
||||
else if (mBleAdvRequestedState == kNotAdvertising && mBleState == kAdvertising)
|
||||
{
|
||||
SuccessOrExit(error = otPlatBleGapAdvStop(&GetInstance()));
|
||||
mBleState = kNotAdvertising;
|
||||
}
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "start/stop advertisements");
|
||||
return error;
|
||||
}
|
||||
|
||||
void BleSecure::SetPsk(const MeshCoP::JoinerPskd &aPskd)
|
||||
{
|
||||
static_assert(static_cast<uint16_t>(MeshCoP::JoinerPskd::kMaxLength) <=
|
||||
@@ -234,7 +286,7 @@ Error BleSecure::SendApplicationTlv(MeshCoP::TcatAgent::TcatApplicationProtocol
|
||||
|
||||
VerifyOrExit((aTcatApplicationProtocol != MeshCoP::TcatAgent::kApplicationProtocolStatus &&
|
||||
aTcatApplicationProtocol != MeshCoP::TcatAgent::kApplicationProtocolResponse) ||
|
||||
mTcatAgent.GetApplicationResponsePending(),
|
||||
Get<MeshCoP::TcatAgent>().GetApplicationResponsePending(),
|
||||
error = kErrorRejected);
|
||||
|
||||
if (aLength > Tlv::kBaseTlvMaxLength)
|
||||
@@ -250,7 +302,7 @@ Error BleSecure::SendApplicationTlv(MeshCoP::TcatAgent::TcatApplicationProtocol
|
||||
ot::Tlv tlv;
|
||||
|
||||
tlv.SetType(static_cast<uint8_t>(aTcatApplicationProtocol));
|
||||
tlv.SetLength((uint8_t)aLength);
|
||||
tlv.SetLength(static_cast<uint8_t>(aLength));
|
||||
SuccessOrExit(error = Send(reinterpret_cast<uint8_t *>(&tlv), sizeof(tlv)));
|
||||
}
|
||||
|
||||
@@ -259,7 +311,7 @@ Error BleSecure::SendApplicationTlv(MeshCoP::TcatAgent::TcatApplicationProtocol
|
||||
if (aTcatApplicationProtocol == MeshCoP::TcatAgent::kApplicationProtocolStatus ||
|
||||
aTcatApplicationProtocol == MeshCoP::TcatAgent::kApplicationProtocolResponse)
|
||||
{
|
||||
mTcatAgent.NotifyApplicationResponseSent();
|
||||
Get<MeshCoP::TcatAgent>().NotifyApplicationResponseSent();
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -346,10 +398,15 @@ void BleSecure::HandleBleDisconnected(uint16_t aConnectionId)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aConnectionId);
|
||||
|
||||
// kAdvertising is the state that the BLE stack will automatically assume, after a BLE client disconnects.
|
||||
mBleState = kAdvertising;
|
||||
mMtuSize = kInitialMtuSize;
|
||||
|
||||
Disconnect(); // Stop TLS connection
|
||||
|
||||
// if a different BLE advertising state was requested earlier while a BLE client was connected,
|
||||
// then now's the time to fulfill the request.
|
||||
IgnoreError(SetRequestedBleAdvertisementsState());
|
||||
}
|
||||
|
||||
Error BleSecure::HandleBleMtuUpdate(uint16_t aMtu)
|
||||
@@ -384,7 +441,14 @@ void BleSecure::HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent)
|
||||
{
|
||||
mReceivedMessage = Get<MessagePool>().Allocate(Message::kTypeBle);
|
||||
}
|
||||
err = mTcatAgent.Connected(*this);
|
||||
if (mReceivedMessage == nullptr)
|
||||
{
|
||||
err = kErrorNoBufs;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = Get<MeshCoP::TcatAgent>().Connected(*this);
|
||||
}
|
||||
|
||||
if (err != kErrorNone)
|
||||
{
|
||||
@@ -399,14 +463,10 @@ void BleSecure::HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent)
|
||||
mReceivedMessage = nullptr;
|
||||
FreeMessage(mSendMessage);
|
||||
mSendMessage = nullptr;
|
||||
|
||||
if (mTcatAgent.IsEnabled())
|
||||
{
|
||||
mTcatAgent.Disconnected();
|
||||
}
|
||||
Get<MeshCoP::TcatAgent>().Disconnected();
|
||||
}
|
||||
|
||||
mConnectCallback.InvokeIfSet(&GetInstance(), aEvent == MeshCoP::Tls::kConnected, true);
|
||||
mConnectCallback.InvokeIfSet(&GetInstance(), aEvent == MeshCoP::Tls::kConnected, mBleState == kConnected);
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -447,7 +507,7 @@ void BleSecure::HandleTlsReceive(uint8_t *aBuf, uint16_t aLength)
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(mReceivedMessage->AppendBytes(aBuf, (uint16_t)missingBytes));
|
||||
SuccessOrExit(mReceivedMessage->AppendBytes(aBuf, static_cast<uint16_t>(missingBytes)));
|
||||
aLength -= missingBytes;
|
||||
aBuf += missingBytes;
|
||||
}
|
||||
@@ -480,9 +540,8 @@ void BleSecure::HandleTlsReceive(uint8_t *aBuf, uint16_t aLength)
|
||||
continue;
|
||||
}
|
||||
|
||||
// TLV fully loaded
|
||||
|
||||
if (mTcatAgent.IsEnabled())
|
||||
// TLV fully loaded - let TCAT agent handle it, if connected
|
||||
if (Get<MeshCoP::TcatAgent>().IsConnected())
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
@@ -494,7 +553,7 @@ void BleSecure::HandleTlsReceive(uint8_t *aBuf, uint16_t aLength)
|
||||
VerifyOrExit(mSendMessage != nullptr, error = kErrorNoBufs);
|
||||
}
|
||||
|
||||
error = mTcatAgent.HandleSingleTlv(*mReceivedMessage, *mSendMessage);
|
||||
error = Get<MeshCoP::TcatAgent>().HandleSingleTlv(*mReceivedMessage, *mSendMessage);
|
||||
IgnoreError(Flush());
|
||||
|
||||
if (error == kErrorAbort)
|
||||
@@ -509,8 +568,8 @@ void BleSecure::HandleTlsReceive(uint8_t *aBuf, uint16_t aLength)
|
||||
}
|
||||
else
|
||||
{
|
||||
mReceivedMessage->SetOffset((uint16_t)offset);
|
||||
mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, (int32_t)offset,
|
||||
mReceivedMessage->SetOffset(static_cast<uint16_t>(offset));
|
||||
mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, static_cast<int32_t>(offset),
|
||||
OT_TCAT_APPLICATION_PROTOCOL_NONE);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,15 +58,16 @@ public:
|
||||
/**
|
||||
* Pointer to call when the secure BLE connection state changes.
|
||||
*
|
||||
* Please see otHandleBleSecureConnect for details.
|
||||
* Please see #otHandleBleSecureConnect for details.
|
||||
*/
|
||||
typedef otHandleBleSecureConnect ConnectCallback;
|
||||
|
||||
/**
|
||||
* Pointer to call when data was received over the TLS connection.
|
||||
* If line mode is activated the function is called only after EOL has been received.
|
||||
* If line mode is active the function is called only after EOL has been received.
|
||||
* If TLV mode is active the function is called after a complete TLV has been received.
|
||||
*
|
||||
* Please see otHandleBleSecureReceive for details.
|
||||
* Please see #otHandleBleSecureReceive for details.
|
||||
*/
|
||||
typedef otHandleBleSecureReceive ReceiveCallback;
|
||||
|
||||
@@ -85,11 +86,14 @@ public:
|
||||
/**
|
||||
* Starts the secure BLE agent.
|
||||
*
|
||||
* See #otBleSecureStart for more details.
|
||||
*
|
||||
* @param[in] aConnectHandler A pointer to a function that will be called when the connection
|
||||
* state changes.
|
||||
* @param[in] aReceiveHandler A pointer to a function that will be called once data has been received
|
||||
* over the TLS connection.
|
||||
* @param[in] aTlvMode A boolean value indicating if line mode shall be activated.
|
||||
* @param[in] aTlvMode A boolean value indicating if TLV mode (TRUE) shall be activated or
|
||||
* line mode (FALSE).
|
||||
* @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
|
||||
*
|
||||
* @retval kErrorNone Successfully started the BLE agent.
|
||||
@@ -98,31 +102,55 @@ public:
|
||||
Error Start(ConnectCallback aConnectHandler, ReceiveCallback aReceiveHandler, bool aTlvMode, void *aContext);
|
||||
|
||||
/**
|
||||
* Enables the TCAT protocol over BLE Secure.
|
||||
* Sets the TCAT Vendor Info object.
|
||||
*
|
||||
* @param[in] aHandler Callback to a function that is called when the join operation completes.
|
||||
* See #otBleSecureSetTcatVendorInfo for more details.
|
||||
*
|
||||
* @retval kErrorNone Successfully started the BLE Secure Joiner role.
|
||||
* @retval kErrorInvalidArgs The aVendorInfo is invalid.
|
||||
* @retval kErrorInvaidState The BLE function has not been started or line mode is not selected.
|
||||
* @param[in] aVendorInfo A pointer to the Vendor Information (MUST remain valid after the method call).
|
||||
*
|
||||
* @retval kErrorNone Successfully set vendor info.
|
||||
* @retval kErrorInvalidArgs Vendor info could not be set.
|
||||
*/
|
||||
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)
|
||||
Error SetTcatVendorInfo(const MeshCoP::TcatAgent::VendorInfo &aVendorInfo)
|
||||
{
|
||||
return mTcatAgent.SetTcatVendorInfo(aVendorInfo);
|
||||
return Get<MeshCoP::TcatAgent>().SetTcatVendorInfo(aVendorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the TCAT protocol over BLE Secure.
|
||||
*
|
||||
* @param[in] aJoinHandler Callback to a function that is called when a network join operation
|
||||
* completes, under guidance of a TCAT Commissioner. This handler uses
|
||||
* the context (aContext) parameter already set with #Start().
|
||||
*
|
||||
* @retval kErrorNone Successfully started TCAT over BLE Secure.
|
||||
* @retval kErrorInvalidArgs Vendor info is invalid, see #TcatSetVendorInfo.
|
||||
* @retval kErrorInvalidState The BLE function is not started yet or TLV mode is not selected.
|
||||
*/
|
||||
Error TcatStart(MeshCoP::TcatAgent::JoinCallback aJoinHandler);
|
||||
|
||||
/**
|
||||
* Stops the secure BLE agent.
|
||||
*
|
||||
* See #otBleSecureStop for more details.
|
||||
*/
|
||||
void Stop(void);
|
||||
|
||||
/**
|
||||
* Sets the TCAT agent over BLE Secure into active or standby state.
|
||||
*
|
||||
* See #otBleSecureTcatActive for more details.
|
||||
*
|
||||
* @param[in] aActive TRUE to activate TCAT agent, FALSE to set it to standby.
|
||||
* @param[in] aDelayMs Delay in ms before activating TCAT, or 0 for immediate.
|
||||
* @param[in] aDurationMs Duration in ms of TCAT activation, or 0 for indefinite.
|
||||
* If a duration is given, then kStateActiveTemporary is used.
|
||||
*
|
||||
* @retval kErrorNone Successfully set TCAT over BLE Secure to requested state.
|
||||
* @retval kErrorInvalidState TCAT is not in a state that can transition to the requested state.
|
||||
*/
|
||||
Error TcatActive(bool aActive, uint32_t aDelayMs, uint32_t aDurationMs);
|
||||
|
||||
/**
|
||||
* Initializes TLS session with a peer using an already open BLE connection.
|
||||
*
|
||||
@@ -131,7 +159,7 @@ public:
|
||||
Error Connect(void);
|
||||
|
||||
/**
|
||||
* Stops the BLE and TLS connection.
|
||||
* Stops the BLE and TLS connections.
|
||||
*/
|
||||
void Disconnect(void);
|
||||
|
||||
@@ -152,29 +180,29 @@ public:
|
||||
bool IsConnected(void) const { return mTls.IsConnected(); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TCAT agent is enabled.
|
||||
* Indicates whether or not the TCAT agent is started over BLE secure.
|
||||
*
|
||||
* @retval TRUE The TCAT agent is enabled.
|
||||
* @retval FALSE The TCAT agent is not enabled.
|
||||
* @retval TRUE The TCAT agent is started, communicating over BLE secure.
|
||||
* @retval FALSE The TCAT agent is disabled on BLE secure.
|
||||
*/
|
||||
bool IsTcatEnabled(void) const { return mTcatAgent.IsEnabled(); }
|
||||
bool IsTcatAgentStarted(void) const { return Get<MeshCoP::TcatAgent>().IsStarted(); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not a TCAT command class is authorized for use.
|
||||
* Indicates whether or not a TCAT command class is authorized for use by the current TCAT Commissioner.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCommandClass A command class to subject to authorization check.
|
||||
*
|
||||
* @retval TRUE The command class is authorized for use by the present TCAT commissioner.
|
||||
* @retval TRUE The command class is authorized for use by the current TCAT commissioner.
|
||||
* @retval FALSE The command class is not authorized for use.
|
||||
*/
|
||||
bool IsCommandClassAuthorized(CommandClass aCommandClass) const
|
||||
{
|
||||
return mTcatAgent.IsCommandClassAuthorized(aCommandClass);
|
||||
return Get<MeshCoP::TcatAgent>().IsCommandClassAuthorized(aCommandClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the PSK.
|
||||
* Sets the PSK for the TLS connection over BLE secure.
|
||||
*
|
||||
* @param[in] aPsk A pointer to the PSK.
|
||||
* @param[in] aPskLength The PSK length.
|
||||
@@ -185,7 +213,7 @@ public:
|
||||
Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength) { return mTls.SetPsk(aPsk, aPskLength); }
|
||||
|
||||
/**
|
||||
* Sets the PSK.
|
||||
* Sets the PSK for the TLS connection over BLE secure.
|
||||
*
|
||||
* @param[in] aPskd A Joiner PSKd.
|
||||
*/
|
||||
@@ -219,7 +247,7 @@ public:
|
||||
Error Send(uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Sends a secure BLE data packet containing a TCAT Send Application Data TLV.
|
||||
* Sends a secure BLE data packet containing a TCAT application protocol TLV.
|
||||
*
|
||||
* @param[in] aApplicationProtocol An application protocol the data is directed to.
|
||||
* @param[in] aBuf A pointer to the data to send as the Value of the TCAT application TLV.
|
||||
@@ -236,7 +264,7 @@ public:
|
||||
uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Sends all remaining bytes in the send buffer.
|
||||
* Flushes i.e. sends all remaining bytes in the send buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully enqueued data into the output interface.
|
||||
* @retval kErrorNoBufs Failed to allocate buffer memory.
|
||||
@@ -279,22 +307,35 @@ public:
|
||||
* @return TRUE The install code was correctly verified.
|
||||
* @return FALSE The install code was not verified.
|
||||
*/
|
||||
bool GetInstallCodeVerifyStatus(void) const { return mTcatAgent.GetInstallCodeVerifyStatus(); }
|
||||
bool GetInstallCodeVerifyStatus(void) const { return Get<MeshCoP::TcatAgent>().GetInstallCodeVerifyStatus(); }
|
||||
|
||||
/**
|
||||
* @brief Notifies the BLE layer that the BLE advertisement data should be updated.
|
||||
* @brief Notifies the BLE layer that the TCAT advertisement data was changed, so
|
||||
* BLE advertisement message content should be updated.
|
||||
*
|
||||
* @retval kErrorNone Successfully updated.
|
||||
* @return kErrorFailed Update failed.
|
||||
* @retval kErrorNone Successfully updated using the new data.
|
||||
* @return kErrorFailed Update failed.
|
||||
*/
|
||||
Error NotifyAdvertisementChanged(void);
|
||||
Error NotifyAdvertisementChanged();
|
||||
|
||||
/**
|
||||
* @brief Notifies the BLE layer whether it should be sending BLE advertisements.
|
||||
* Based on its current state, the BLE layer will make platform calls to start or stop
|
||||
* BLE advertising. In case of errors, the error is written to log and state is not
|
||||
* updated.
|
||||
*
|
||||
* @param[in] aSendAdvertisements If TRUE, BLE is requested to send advertisements.
|
||||
* If FALSE, BLE is requested to not send advertisements.
|
||||
*/
|
||||
void NotifySendAdvertisements(bool aSendAdvertisements);
|
||||
|
||||
private:
|
||||
enum BleState : uint8_t
|
||||
{
|
||||
kStopped = 0, // Ble secure not started.
|
||||
kAdvertising = 1, // Ble secure not advertising.
|
||||
kConnected = 2, // Ble secure not connected.
|
||||
kStopped = 0, // Ble secure not started (so not advertising).
|
||||
kAdvertising = 1, // Ble secure is advertising.
|
||||
kConnected = 2, // Ble secure is connected (so not advertising).
|
||||
kNotAdvertising = 3, // Ble secure is started but not advertising.
|
||||
};
|
||||
|
||||
static constexpr uint8_t kInitialMtuSize = 23; // ATT_MTU
|
||||
@@ -314,10 +355,11 @@ private:
|
||||
static Error HandleTransport(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
Error HandleTransport(ot::Message &aMessage);
|
||||
|
||||
Error SetRequestedBleAdvertisementsState(void);
|
||||
|
||||
using TxTask = TaskletIn<BleSecure, &BleSecure::HandleTransmit>;
|
||||
|
||||
MeshCoP::Tls mTls;
|
||||
MeshCoP::TcatAgent mTcatAgent;
|
||||
Callback<ConnectCallback> mConnectCallback;
|
||||
Callback<ReceiveCallback> mReceiveCallback;
|
||||
bool mTlvMode;
|
||||
@@ -327,6 +369,7 @@ private:
|
||||
TxTask mTransmitTask;
|
||||
uint8_t mPacketBuffer[kPacketBufferSize];
|
||||
BleState mBleState;
|
||||
BleState mBleAdvRequestedState;
|
||||
uint16_t mMtuSize;
|
||||
};
|
||||
|
||||
|
||||
@@ -89,4 +89,31 @@ expect_line "Done"
|
||||
send "tcat devid\n"
|
||||
expect_line "Done"
|
||||
|
||||
# do TCAT agent state transitions. Initially, TCAT agent is stopped by default.
|
||||
#
|
||||
|
||||
send "tcat start\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "tcat standby\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "tcat active\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "tcat standby\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "tcat active 1000 3000\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "tcat standby\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "tcat active 1200000\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "tcat stop\n"
|
||||
expect_line "Done"
|
||||
|
||||
dispose_all
|
||||
|
||||
@@ -181,9 +181,9 @@ void TestTcat(void)
|
||||
VerifyOrQuit(otBleSecureConnect(instance) == kErrorInvalidState);
|
||||
|
||||
// Validate Tcat state changes after stopping BLE secure
|
||||
VerifyOrQuit(otBleSecureIsTcatEnabled(instance));
|
||||
VerifyOrQuit(otBleSecureIsTcatAgentStarted(instance));
|
||||
otBleSecureStop(instance);
|
||||
VerifyOrQuit(!otBleSecureIsTcatEnabled(instance));
|
||||
VerifyOrQuit(!otBleSecureIsTcatAgentStarted(instance));
|
||||
|
||||
testFreeInstance(instance);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user