mirror of
https://github.com/espressif/openthread.git
synced 2026-07-30 07:37:46 +00:00
[ncp] adding SpinelEncoder class and updating NCP implementation (#2221)
This commit adds a new class `SpinelEncoder` which provides a set of methods/APIs to help in encoding/writing content using Spinel formating (it is practically a C++ wrapper over Spinel C APIs). A unit test `test_spinel_encoder` is also added in this commit. This commit also updates the `NcpBase` implementation to adopt the new `SpinelEncoder` class mainly in implementation of get, insert, and remove handlers for different Spinel properties. The new class provides the following advantages: (a) it simplifies the implementation of handers, particularly get-handlers for properties with a single type output; (b) it adds type-checking and type-safety when frames are being created, e.g., if the Spinel format expects a `SPINEL_DATATYPE_UINT8` but a `uint16_t` value is provided, the new model will cause a compile-time error (few instances in code where the types did not match are fixed in this commit).
This commit is contained in:
committed by
Jonathan Hui
parent
7dbc20d2dd
commit
192df6cf00
@@ -66,6 +66,7 @@
|
||||
<ClCompile Include="..\..\src\ncp\ncp_buffer.cpp" />
|
||||
<ClCompile Include="..\..\src\ncp\ncp_spi.cpp" />
|
||||
<ClCompile Include="..\..\src\ncp\spinel.c" />
|
||||
<ClCompile Include="..\..\src\ncp\spinel_encoder.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\ncp\changed_props_set.hpp" />
|
||||
@@ -73,6 +74,7 @@
|
||||
<ClInclude Include="..\..\src\ncp\ncp_buffer.hpp" />
|
||||
<ClInclude Include="..\..\src\ncp\ncp_spi.hpp" />
|
||||
<ClInclude Include="..\..\src\ncp\spinel.h" />
|
||||
<ClInclude Include="..\..\src\ncp\spinel_encoder.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
<ClCompile Include="..\..\src\ncp\spinel.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ncp\spinel_encoder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ncp\ncp_spi.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -56,5 +59,8 @@
|
||||
<ClInclude Include="..\..\src\ncp\spinel.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ncp\spinel_encoder.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
<ClCompile Include="..\..\src\ncp\ncp_buffer.cpp" />
|
||||
<ClCompile Include="..\..\src\ncp\ncp_uart.cpp" />
|
||||
<ClCompile Include="..\..\src\ncp\spinel.c" />
|
||||
<ClCompile Include="..\..\src\ncp\spinel_encoder.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\ncp\changed_props_set.hpp" />
|
||||
@@ -75,6 +76,7 @@
|
||||
<ClInclude Include="..\..\src\ncp\ncp_buffer.hpp" />
|
||||
<ClInclude Include="..\..\src\ncp\ncp_uart.hpp" />
|
||||
<ClInclude Include="..\..\src\ncp\spinel.h" />
|
||||
<ClInclude Include="..\..\src\ncp\spinel_encoder.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
<ClCompile Include="..\..\src\ncp\spinel.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ncp\spinel_encoder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\ncp\changed_props_set.hpp">
|
||||
@@ -62,5 +65,8 @@
|
||||
<ClInclude Include="..\..\src\ncp\spinel.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ncp\spinel_encoder.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -71,6 +71,8 @@ COMMON_SOURCES = \
|
||||
ncp_buffer.hpp \
|
||||
spinel.c \
|
||||
spinel.h \
|
||||
spinel_encoder.hpp \
|
||||
spinel_encoder.cpp \
|
||||
spinel_platform.h \
|
||||
ncp_spi.cpp \
|
||||
ncp_spi.hpp \
|
||||
|
||||
+199
-512
File diff suppressed because it is too large
Load Diff
+55
-83
@@ -47,6 +47,7 @@
|
||||
#include "changed_props_set.hpp"
|
||||
#include "common/tasklet.hpp"
|
||||
#include "ncp/ncp_buffer.hpp"
|
||||
#include "ncp/spinel_encoder.hpp"
|
||||
|
||||
#include "spinel.h"
|
||||
|
||||
@@ -63,10 +64,7 @@ namespace Ncp {
|
||||
|
||||
|
||||
#define NCP_GET_PROP_HANDLER(name) \
|
||||
otError GetPropertyHandler_##name( \
|
||||
uint8_t aHeader, \
|
||||
spinel_prop_key_t aKey \
|
||||
)
|
||||
otError GetPropertyHandler_##name(void)
|
||||
|
||||
#define NCP_SET_PROP_HANDLER(name) \
|
||||
otError SetPropertyHandler_##name( \
|
||||
@@ -78,16 +76,12 @@ namespace Ncp {
|
||||
|
||||
#define NCP_INSERT_PROP_HANDLER(name) \
|
||||
otError InsertPropertyHandler_##name( \
|
||||
uint8_t aHeader, \
|
||||
spinel_prop_key_t aKey, \
|
||||
const uint8_t *aValuePtr, \
|
||||
uint16_t aValueLen \
|
||||
)
|
||||
|
||||
#define NCP_REMOVE_PROP_HANDLER(name) \
|
||||
otError RemovePropertyHandler_##name( \
|
||||
uint8_t aHeader, \
|
||||
spinel_prop_key_t aKey, \
|
||||
const uint8_t *aValuePtr, \
|
||||
uint16_t aValueLen \
|
||||
)
|
||||
@@ -175,59 +169,6 @@ public:
|
||||
#endif
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This method is called to start a new outbound frame.
|
||||
*
|
||||
* param[in] aHeader The spinel header byte
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started a new frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to start a new frame.
|
||||
*
|
||||
*/
|
||||
otError OutboundFrameBegin(uint8_t aHeader);
|
||||
|
||||
/**
|
||||
* This method adds data to the current outbound frame being written.
|
||||
*
|
||||
* If no buffer space is available, this method should discard and clear the frame before returning an error status.
|
||||
*
|
||||
* @param[in] aDataBuffer A pointer to data buffer.
|
||||
* @param[in] aDataBufferLength The length of the data buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added new data to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add data.
|
||||
*
|
||||
*/
|
||||
otError OutboundFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength);
|
||||
|
||||
/**
|
||||
* This method adds a message to the current outbound frame being written.
|
||||
*
|
||||
* If no buffer space is available, this method should discard and clear the frame before returning an error status.
|
||||
* In case of success, the passed-in message @aMessage should be owned by outbound buffer and should be freed
|
||||
* when either the frame is successfully sent and removed or if the frame is discarded.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message to be added to current frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added the message to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add message.
|
||||
*
|
||||
*/
|
||||
otError OutboundFrameFeedMessage(otMessage *aMessage);
|
||||
|
||||
/**
|
||||
* This method finalizes and sends the current outbound frame
|
||||
*
|
||||
* If no buffer space is available, this method should discard and clear the frame
|
||||
* before returning an error status.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added the message to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add message.
|
||||
*
|
||||
*/
|
||||
otError OutboundFrameEnd(void);
|
||||
|
||||
/**
|
||||
* This method is called by the framer whenever a framing error is detected.
|
||||
*/
|
||||
@@ -252,7 +193,9 @@ private:
|
||||
typedef otError(NcpBase::*CommandHandlerType)(uint8_t aHeader, unsigned int aCommand, const uint8_t *aArgPtr,
|
||||
uint16_t aArgLen);
|
||||
|
||||
typedef otError(NcpBase::*GetPropertyHandlerType)(uint8_t aHeader, spinel_prop_key_t aKey);
|
||||
typedef otError(NcpBase::*GetPropertyHandlerType)(void);
|
||||
|
||||
typedef otError(NcpBase::*InsertRemovePropertyHandlerType)(const uint8_t *aValuePtr, uint16_t aValueLen);
|
||||
|
||||
typedef otError(NcpBase::*SetPropertyHandlerType)(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
const uint8_t *aValuePtr, uint16_t aValueLen);
|
||||
@@ -278,24 +221,17 @@ private:
|
||||
struct InsertPropertyHandlerEntry
|
||||
{
|
||||
spinel_prop_key_t mPropKey;
|
||||
SetPropertyHandlerType mHandler;
|
||||
InsertRemovePropertyHandlerType mHandler;
|
||||
};
|
||||
|
||||
struct RemovePropertyHandlerEntry
|
||||
{
|
||||
spinel_prop_key_t mPropKey;
|
||||
SetPropertyHandlerType mHandler;
|
||||
InsertRemovePropertyHandlerType mHandler;
|
||||
};
|
||||
|
||||
otError OutboundFrameSend(void);
|
||||
|
||||
NcpFrameBuffer::FrameTag GetLastOutboundFrameTag(void);
|
||||
|
||||
otError OutboundFrameFeedPacked(const char *aPackFormat, ...);
|
||||
|
||||
otError OutboundFrameFeedVPacked(const char *aPackFormat, va_list aArgs);
|
||||
|
||||
|
||||
otError HandleCommand(uint8_t aHeader, unsigned int aCommand, const uint8_t *aArgPtr, uint16_t aArgLen);
|
||||
|
||||
otError HandleCommandPropertyGet(uint8_t aHeader, spinel_prop_key_t aKey);
|
||||
@@ -311,14 +247,6 @@ private:
|
||||
|
||||
|
||||
otError SendLastStatus(uint8_t aHeader, spinel_status_t aLastStatus);
|
||||
|
||||
otError SendPropertyUpdate(uint8_t aHeader, uint8_t aCommand, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
|
||||
uint16_t aValueLen);
|
||||
|
||||
otError SendPropertyUpdate(uint8_t aHeader, uint8_t aCommand, spinel_prop_key_t aKey, otMessage *message);
|
||||
|
||||
otError SendPropertyUpdate(uint8_t aHeader, uint8_t aCommand, spinel_prop_key_t aKey, const char *format, ...);
|
||||
|
||||
otError SendSetPropertyResponse(uint8_t aHeader, spinel_prop_key_t aKey, otError aError);
|
||||
|
||||
static void UpdateChangedProps(Tasklet &aTasklet);
|
||||
@@ -363,7 +291,7 @@ private:
|
||||
static void SendDoneTask(void *aContext);
|
||||
void SendDoneTask(void);
|
||||
|
||||
otError GetPropertyHandler_ChannelMaskHelper(uint8_t aHeader, spinel_prop_key_t aKey, uint32_t channel_mask);
|
||||
otError GetPropertyHandler_ChannelMaskHelper(uint32_t channel_mask);
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
|
||||
@@ -536,9 +464,52 @@ private:
|
||||
#endif
|
||||
NCP_GET_PROP_HANDLER(STREAM_NET);
|
||||
NCP_SET_PROP_HANDLER(STREAM_NET);
|
||||
NCP_GET_PROP_HANDLER(MAC_CNTR);
|
||||
NCP_GET_PROP_HANDLER(NCP_CNTR);
|
||||
NCP_GET_PROP_HANDLER(IP_CNTR);
|
||||
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_TOTAL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_ACK_REQ);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_ACKED);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_NO_ACK_REQ);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_DATA);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_DATA_POLL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_BEACON);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_BEACON_REQ);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_OTHER);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_RETRY);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_UNICAST);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_PKT_BROADCAST);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_ERR_CCA);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_ERR_ABORT);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_TOTAL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_DATA);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_DATA_POLL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_BEACON);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_BEACON_REQ);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_OTHER);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_FILT_WL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_FILT_DA);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_UNICAST);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_BROADCAST);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_ERR_EMPTY);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_ERR_UKWN_NBR);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_ERR_NVLD_SADDR);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_ERR_SECURITY);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_ERR_BAD_FCS);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_ERR_OTHER);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_PKT_DUP);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_IP_SEC_TOTAL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_IP_INSEC_TOTAL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_IP_DROPPED);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_IP_SEC_TOTAL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_IP_INSEC_TOTAL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_IP_DROPPED);
|
||||
NCP_GET_PROP_HANDLER(CNTR_TX_SPINEL_TOTAL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_SPINEL_TOTAL);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_SPINEL_OUT_OF_ORDER_TID);
|
||||
NCP_GET_PROP_HANDLER(CNTR_RX_SPINEL_ERR);
|
||||
NCP_GET_PROP_HANDLER(CNTR_IP_TX_SUCCESS);
|
||||
NCP_GET_PROP_HANDLER(CNTR_IP_RX_SUCCESS);
|
||||
NCP_GET_PROP_HANDLER(CNTR_IP_TX_FAILURE);
|
||||
NCP_GET_PROP_HANDLER(CNTR_IP_RX_FAILURE);
|
||||
NCP_GET_PROP_HANDLER(MSG_BUFFER_COUNTERS);
|
||||
#if OPENTHREAD_ENABLE_MAC_FILTER
|
||||
NCP_GET_PROP_HANDLER(MAC_WHITELIST_ENABLED);
|
||||
@@ -639,6 +610,7 @@ protected:
|
||||
static uint8_t LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aSecureDataRequests, bool aDeviceType, bool aNetworkData);
|
||||
otInstance *mInstance;
|
||||
NcpFrameBuffer mTxFrameBuffer;
|
||||
SpinelEncoder mEncoder;
|
||||
bool mHostPowerStateInProgress;
|
||||
|
||||
private:
|
||||
|
||||
+100
-253
@@ -56,53 +56,28 @@
|
||||
namespace ot {
|
||||
namespace Ncp {
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
otThreadGetLocalLeaderWeight(mInstance)
|
||||
);
|
||||
return mEncoder.WriteUint8(otThreadGetLocalLeaderWeight(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_LEADER_WEIGHT(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_LEADER_WEIGHT(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
otThreadGetLeaderWeight(mInstance)
|
||||
);
|
||||
return mEncoder.WriteUint8(otThreadGetLeaderWeight(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_CHILD_TABLE(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_CHILD_TABLE(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otChildInfo childInfo;
|
||||
uint8_t maxChildren;
|
||||
uint8_t modeFlags;
|
||||
|
||||
mDisableStreamWrite = true;
|
||||
|
||||
SuccessOrExit(error = OutboundFrameBegin(aHeader));
|
||||
SuccessOrExit(
|
||||
error = OutboundFrameFeedPacked(
|
||||
SPINEL_DATATYPE_COMMAND_PROP_S,
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey
|
||||
));
|
||||
|
||||
maxChildren = otThreadGetMaxAllowedChildren(mInstance);
|
||||
|
||||
for (uint8_t index = 0; index < maxChildren; index++)
|
||||
{
|
||||
error = otThreadGetChildInfoByIndex(mInstance, index, &childInfo);
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
if (otThreadGetChildInfoByIndex(mInstance, index, &childInfo) != OT_ERROR_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -114,47 +89,28 @@ otError NcpBase::GetPropertyHandler_THREAD_CHILD_TABLE(uint8_t aHeader, spinel_p
|
||||
childInfo.mFullNetworkData
|
||||
);
|
||||
|
||||
SuccessOrExit(
|
||||
error = OutboundFrameFeedPacked(
|
||||
SPINEL_DATATYPE_STRUCT_S(
|
||||
SPINEL_DATATYPE_EUI64_S // EUI64 Address
|
||||
SPINEL_DATATYPE_UINT16_S // Rloc16
|
||||
SPINEL_DATATYPE_UINT32_S // Timeout
|
||||
SPINEL_DATATYPE_UINT32_S // Age
|
||||
SPINEL_DATATYPE_UINT8_S // Network Data Version
|
||||
SPINEL_DATATYPE_UINT8_S // Link Quality In
|
||||
SPINEL_DATATYPE_INT8_S // Average RSS
|
||||
SPINEL_DATATYPE_UINT8_S // Mode (flags)
|
||||
SPINEL_DATATYPE_INT8_S // Most recent RSS
|
||||
),
|
||||
childInfo.mExtAddress.m8,
|
||||
childInfo.mRloc16,
|
||||
childInfo.mTimeout,
|
||||
childInfo.mAge,
|
||||
childInfo.mNetworkDataVersion,
|
||||
childInfo.mLinkQualityIn,
|
||||
childInfo.mAverageRssi,
|
||||
modeFlags,
|
||||
childInfo.mLastRssi
|
||||
));
|
||||
SuccessOrExit(error = mEncoder.OpenStruct());
|
||||
|
||||
SuccessOrExit(error = mEncoder.WriteEui64(childInfo.mExtAddress));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(childInfo.mRloc16));
|
||||
SuccessOrExit(error = mEncoder.WriteUint32(childInfo.mTimeout));
|
||||
SuccessOrExit(error = mEncoder.WriteUint32(childInfo.mAge));
|
||||
SuccessOrExit(error = mEncoder.WriteUint8(childInfo.mNetworkDataVersion));
|
||||
SuccessOrExit(error = mEncoder.WriteUint8(childInfo.mLinkQualityIn));
|
||||
SuccessOrExit(error = mEncoder.WriteInt8(childInfo.mAverageRssi));
|
||||
SuccessOrExit(error = mEncoder.WriteUint8(modeFlags));
|
||||
SuccessOrExit(error = mEncoder.WriteInt8(childInfo.mLastRssi));
|
||||
|
||||
SuccessOrExit(error = mEncoder.CloseStruct());
|
||||
}
|
||||
|
||||
SuccessOrExit(error = OutboundFrameSend());
|
||||
|
||||
exit:
|
||||
mDisableStreamWrite = false;
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_ROLE_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_ROLE_ENABLED(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_BOOL_S,
|
||||
otThreadIsRouterRoleEnabled(mInstance)
|
||||
);
|
||||
return mEncoder.WriteBool(otThreadIsRouterRoleEnabled(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_ROUTER_ROLE_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -179,16 +135,9 @@ exit:
|
||||
return SendSetPropertyResponse(aHeader, aKey, error);
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_NET_PSKC(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_NET_PSKC(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_DATA_S,
|
||||
otThreadGetPSKc(mInstance),
|
||||
sizeof(spinel_net_pskc_t)
|
||||
);
|
||||
return mEncoder.WriteData(otThreadGetPSKc(mInstance), sizeof(spinel_net_pskc_t));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_NET_PSKC(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
|
||||
@@ -215,15 +164,9 @@ exit:
|
||||
return SendSetPropertyResponse(aHeader, aKey, error);
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_CHILD_COUNT_MAX(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_CHILD_COUNT_MAX(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
otThreadGetMaxAllowedChildren(mInstance)
|
||||
);
|
||||
return mEncoder.WriteUint8(otThreadGetMaxAllowedChildren(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_CHILD_COUNT_MAX(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -248,15 +191,9 @@ exit:
|
||||
return SendSetPropertyResponse(aHeader, aKey, error);
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_UPGRADE_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_UPGRADE_THRESHOLD(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
otThreadGetRouterUpgradeThreshold(mInstance)
|
||||
);
|
||||
return mEncoder.WriteUint8(otThreadGetRouterUpgradeThreshold(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_ROUTER_UPGRADE_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -281,15 +218,9 @@ exit:
|
||||
return SendSetPropertyResponse(aHeader, aKey, error);
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_DOWNGRADE_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_DOWNGRADE_THRESHOLD(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
otThreadGetRouterDowngradeThreshold(mInstance)
|
||||
);
|
||||
return mEncoder.WriteUint8(otThreadGetRouterDowngradeThreshold(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_ROUTER_DOWNGRADE_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -314,15 +245,9 @@ exit:
|
||||
return SendSetPropertyResponse(aHeader, aKey, error);
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_SELECTION_JITTER(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_SELECTION_JITTER(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
otThreadGetRouterSelectionJitter(mInstance)
|
||||
);
|
||||
return mEncoder.WriteUint8(otThreadGetRouterSelectionJitter(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_ROUTER_SELECTION_JITTER(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -347,15 +272,9 @@ exit:
|
||||
return SendSetPropertyResponse(aHeader, aKey, error);
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_CONTEXT_REUSE_DELAY(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_CONTEXT_REUSE_DELAY(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT32_S,
|
||||
otThreadGetContextIdReuseDelay(mInstance)
|
||||
);
|
||||
return mEncoder.WriteUint32(otThreadGetContextIdReuseDelay(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_CONTEXT_REUSE_DELAY(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -380,15 +299,9 @@ otError NcpBase::SetPropertyHandler_THREAD_CONTEXT_REUSE_DELAY(uint8_t aHeader,
|
||||
return SendSetPropertyResponse(aHeader, aKey, error);
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_NETWORK_ID_TIMEOUT(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_NETWORK_ID_TIMEOUT(void)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
otThreadGetNetworkIdTimeout(mInstance)
|
||||
);
|
||||
return mEncoder.WriteUint8(otThreadGetNetworkIdTimeout(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_NETWORK_ID_TIMEOUT(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -414,22 +327,9 @@ otError NcpBase::SetPropertyHandler_THREAD_NETWORK_ID_TIMEOUT(uint8_t aHeader, s
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
otError NcpBase::GetPropertyHandler_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::GetPropertyHandler_THREAD_COMMISSIONER_ENABLED(void)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
||||
if (otCommissionerGetState(mInstance) == OT_COMMISSIONER_STATE_ACTIVE)
|
||||
{
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_BOOL_S,
|
||||
enabled
|
||||
);
|
||||
return mEncoder.WriteBool(otCommissionerGetState(mInstance) == OT_COMMISSIONER_STATE_ACTIVE);
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -464,17 +364,15 @@ exit:
|
||||
return SendLastStatus(aHeader, ThreadErrorToSpinelStatus(error));
|
||||
}
|
||||
|
||||
otError NcpBase::InsertPropertyHandler_THREAD_JOINERS(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
otError NcpBase::InsertPropertyHandler_THREAD_JOINERS(const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
{
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_status_t spinelError = SPINEL_STATUS_OK;
|
||||
otExtAddress *extAddress = NULL;
|
||||
const char *aPSKd = NULL;
|
||||
uint32_t joinerTimeout = 0;
|
||||
|
||||
VerifyOrExit(mAllowLocalNetworkDataChange == true, spinelError = SPINEL_STATUS_INVALID_STATE);
|
||||
VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
aValuePtr,
|
||||
@@ -504,26 +402,11 @@ otError NcpBase::InsertPropertyHandler_THREAD_JOINERS(uint8_t aHeader, spinel_pr
|
||||
extAddress = NULL;
|
||||
}
|
||||
|
||||
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
|
||||
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
error = otCommissionerAddJoiner(mInstance, extAddress, aPSKd, joinerTimeout);
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
|
||||
error = SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_INSERTED,
|
||||
aKey,
|
||||
aValuePtr,
|
||||
aValueLen
|
||||
);
|
||||
|
||||
exit:
|
||||
|
||||
if (spinelError != SPINEL_STATUS_OK)
|
||||
{
|
||||
error = SendLastStatus(aHeader, spinelError);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -558,6 +441,7 @@ otError NcpBase::SetPropertyHandler_THREAD_STEERING_DATA(uint8_t aHeader, spinel
|
||||
otExtAddress *extAddress;
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_status_t spinelError = SPINEL_STATUS_OK;
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
aValuePtr,
|
||||
@@ -566,26 +450,21 @@ otError NcpBase::SetPropertyHandler_THREAD_STEERING_DATA(uint8_t aHeader, spinel
|
||||
&extAddress
|
||||
);
|
||||
|
||||
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
|
||||
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
|
||||
|
||||
error = otThreadSetSteeringData(mInstance, extAddress);
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
|
||||
// Note that there is no get handler for this property
|
||||
|
||||
SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, aKey));
|
||||
SuccessOrExit(error = mEncoder.WriteEui64(*extAddress));
|
||||
SuccessOrExit(error = mEncoder.EndFrame());
|
||||
|
||||
exit:
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
if (spinelError != SPINEL_STATUS_OK)
|
||||
{
|
||||
// Note that there is no get handler for this property.
|
||||
error = SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_EUI64_S,
|
||||
extAddress->m8
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = SendLastStatus(aHeader, ThreadErrorToSpinelStatus(error));
|
||||
error = SendLastStatus(aHeader, spinelError);
|
||||
}
|
||||
|
||||
return error;
|
||||
@@ -620,44 +499,7 @@ otError NcpBase::SetPropertyHandler_THREAD_PREFERRED_ROUTER_ID(uint8_t aHeader,
|
||||
uint8_t routerId = 0;
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
aValuePtr,
|
||||
aValueLen,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
&routerId
|
||||
);
|
||||
|
||||
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
error = otThreadSetPreferredRouterId(mInstance, routerId);
|
||||
|
||||
exit:
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
error = SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
routerId
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = SendLastStatus(aHeader, ThreadErrorToSpinelStatus(error));
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpBase::RemovePropertyHandler_THREAD_ACTIVE_ROUTER_IDS(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
{
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_status_t spinelError = SPINEL_STATUS_OK;
|
||||
uint8_t routerId;
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
aValuePtr,
|
||||
@@ -668,24 +510,16 @@ otError NcpBase::RemovePropertyHandler_THREAD_ACTIVE_ROUTER_IDS(uint8_t aHeader,
|
||||
|
||||
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
|
||||
|
||||
error = otThreadReleaseRouterId(mInstance, routerId);
|
||||
|
||||
// `INVALID_STATE` is returned when router ID was not allocated (i.e. not in the list)
|
||||
// in such a case, the "remove" operation can be considered successful.
|
||||
VerifyOrExit(error != OT_ERROR_INVALID_STATE, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
|
||||
|
||||
error = otThreadSetPreferredRouterId(mInstance, routerId);
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
|
||||
error = SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_REMOVED,
|
||||
aKey,
|
||||
aValuePtr,
|
||||
aValueLen
|
||||
);
|
||||
// Note that there is no get handler for this property.
|
||||
|
||||
SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, aKey));
|
||||
SuccessOrExit(error = mEncoder.WriteUint8(routerId));
|
||||
SuccessOrExit(error = mEncoder.EndFrame());
|
||||
|
||||
exit:
|
||||
|
||||
if (spinelError != SPINEL_STATUS_OK)
|
||||
{
|
||||
error = SendLastStatus(aHeader, spinelError);
|
||||
@@ -694,16 +528,39 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY
|
||||
otError NcpBase::GetPropertyHandler_THREAD_TMF_PROXY_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
|
||||
otError NcpBase::RemovePropertyHandler_THREAD_ACTIVE_ROUTER_IDS(const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
{
|
||||
return SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
SPINEL_DATATYPE_BOOL_S,
|
||||
otTmfProxyIsEnabled(mInstance)
|
||||
);
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint8_t routerId;
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
aValuePtr,
|
||||
aValueLen,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
&routerId
|
||||
);
|
||||
|
||||
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
error = otThreadReleaseRouterId(mInstance, routerId);
|
||||
|
||||
// `INVALID_STATE` is returned when router ID was not allocated (i.e. not in the list)
|
||||
// in such a case, the "remove" operation can be considered successful.
|
||||
|
||||
if (error == OT_ERROR_INVALID_STATE)
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY
|
||||
otError NcpBase::GetPropertyHandler_THREAD_TMF_PROXY_ENABLED(void)
|
||||
{
|
||||
return mEncoder.WriteBool(otTmfProxyIsEnabled(mInstance));
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_THREAD_TMF_PROXY_STREAM(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
@@ -812,34 +669,24 @@ void NcpBase::HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint1
|
||||
uint16_t length = otMessageGetLength(aMessage);
|
||||
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
|
||||
|
||||
SuccessOrExit(error = OutboundFrameBegin(header));
|
||||
|
||||
SuccessOrExit(
|
||||
error = OutboundFrameFeedPacked(
|
||||
SPINEL_DATATYPE_COMMAND_PROP_S SPINEL_DATATYPE_UINT16_S,
|
||||
header,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
SPINEL_PROP_THREAD_TMF_PROXY_STREAM,
|
||||
length
|
||||
));
|
||||
|
||||
SuccessOrExit(error = OutboundFrameFeedMessage(aMessage));
|
||||
|
||||
SuccessOrExit(
|
||||
error = OutboundFrameFeedPacked(
|
||||
SPINEL_DATATYPE_UINT16_S SPINEL_DATATYPE_UINT16_S,
|
||||
aLocator,
|
||||
aPort
|
||||
));
|
||||
SuccessOrExit(error = mEncoder.BeginFrame(
|
||||
header,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
SPINEL_PROP_THREAD_TMF_PROXY_STREAM
|
||||
));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(length));
|
||||
SuccessOrExit(error = mEncoder.WriteMessage(aMessage));
|
||||
|
||||
// Set the `aMessage` pointer to NULL to indicate that it does
|
||||
// not need to be freed at the exit. The `aMessage` is now owned
|
||||
// by the OutboundFrame and will be freed when the frame is either
|
||||
// by the outbound frame and will be freed when the frame is either
|
||||
// successfully sent and then removed, or if the frame gets
|
||||
// discarded.
|
||||
aMessage = NULL;
|
||||
|
||||
SuccessOrExit(error = OutboundFrameSend());
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(aLocator));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(aPort));
|
||||
SuccessOrExit(error = mEncoder.EndFrame());
|
||||
|
||||
exit:
|
||||
|
||||
|
||||
+635
-1569
File diff suppressed because it is too large
Load Diff
+73
-175
@@ -68,55 +68,38 @@ void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError)
|
||||
uint16_t flags = 0;
|
||||
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
|
||||
|
||||
SuccessOrExit(OutboundFrameBegin(header));
|
||||
|
||||
if (aFrame->mDidTX)
|
||||
{
|
||||
flags |= SPINEL_MD_FLAG_TX;
|
||||
}
|
||||
|
||||
// Append frame header and frame length
|
||||
SuccessOrExit(
|
||||
OutboundFrameFeedPacked(
|
||||
SPINEL_DATATYPE_COMMAND_PROP_S SPINEL_DATATYPE_UINT16_S,
|
||||
header,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
SPINEL_PROP_STREAM_RAW,
|
||||
(aError == OT_ERROR_NONE) ? aFrame->mLength : 0
|
||||
));
|
||||
SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW));
|
||||
SuccessOrExit(mEncoder.WriteUint16((aError == OT_ERROR_NONE) ? aFrame->mLength : 0));
|
||||
|
||||
if (aError == OT_ERROR_NONE)
|
||||
{
|
||||
// Append the frame contents
|
||||
SuccessOrExit(OutboundFrameFeedData(aFrame->mPsdu, aFrame->mLength));
|
||||
SuccessOrExit(mEncoder.WriteData(aFrame->mPsdu, aFrame->mLength));
|
||||
}
|
||||
|
||||
// Append metadata (rssi, etc)
|
||||
SuccessOrExit(
|
||||
OutboundFrameFeedPacked(
|
||||
SPINEL_DATATYPE_INT8_S
|
||||
SPINEL_DATATYPE_INT8_S
|
||||
SPINEL_DATATYPE_UINT16_S
|
||||
SPINEL_DATATYPE_STRUCT_S( // PHY-data
|
||||
SPINEL_DATATYPE_UINT8_S // 802.15.4 channel
|
||||
SPINEL_DATATYPE_UINT8_S // 802.15.4 LQI
|
||||
SPINEL_DATATYPE_UINT32_S // The timestamp milliseconds
|
||||
SPINEL_DATATYPE_UINT16_S // The timestamp microseconds
|
||||
)
|
||||
SPINEL_DATATYPE_STRUCT_S( // Vendor-data
|
||||
SPINEL_DATATYPE_UINT_PACKED_S
|
||||
),
|
||||
aFrame->mPower, // TX Power
|
||||
-128, // Noise Floor (Currently unused)
|
||||
flags, // Flags
|
||||
aFrame->mChannel, // Receive channel
|
||||
aFrame->mLqi, // Link quality indicator
|
||||
aFrame->mMsec, // The timestamp milliseconds
|
||||
aFrame->mUsec, // The timestamp microseconds, offset to mMsec
|
||||
aError // Receive error
|
||||
));
|
||||
SuccessOrExit(mEncoder.WriteInt8(aFrame->mPower)); // TX Power
|
||||
SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise Floor (Currently unused)
|
||||
SuccessOrExit(mEncoder.WriteUint16(flags)); // Flags
|
||||
|
||||
SuccessOrExit(OutboundFrameSend());
|
||||
SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
|
||||
SuccessOrExit(mEncoder.WriteUint8(aFrame->mChannel)); // 802.15.4 channel (Receive channel)
|
||||
SuccessOrExit(mEncoder.WriteUint8(aFrame->mLqi)); // 802.15.4 LQI
|
||||
SuccessOrExit(mEncoder.WriteUint32(aFrame->mMsec)); // The timestamp milliseconds
|
||||
SuccessOrExit(mEncoder.WriteUint16(aFrame->mUsec)); // The timestamp microseconds, offset to mMsec
|
||||
SuccessOrExit(mEncoder.CloseStruct());
|
||||
|
||||
SuccessOrExit(mEncoder.OpenStruct()); // Vendor-data
|
||||
SuccessOrExit(mEncoder.WriteUintPacked(aError)); // Receive error
|
||||
SuccessOrExit(mEncoder.CloseStruct());
|
||||
|
||||
SuccessOrExit(mEncoder.EndFrame());
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -138,40 +121,28 @@ void NcpBase::LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame,
|
||||
// Clear cached transmit TID
|
||||
mCurTransmitTID = 0;
|
||||
|
||||
SuccessOrExit(OutboundFrameBegin(header));
|
||||
|
||||
SuccessOrExit(OutboundFrameFeedPacked(
|
||||
SPINEL_DATATYPE_COMMAND_PROP_S SPINEL_DATATYPE_UINT_PACKED_S SPINEL_DATATYPE_BOOL_S,
|
||||
header,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
SPINEL_PROP_LAST_STATUS,
|
||||
ThreadErrorToSpinelStatus(aError),
|
||||
framePending
|
||||
));
|
||||
SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_LAST_STATUS));
|
||||
SuccessOrExit(mEncoder.WriteUintPacked(ThreadErrorToSpinelStatus(aError)));
|
||||
SuccessOrExit(mEncoder.WriteBool(framePending));
|
||||
|
||||
if (aAckFrame && aError == OT_ERROR_NONE)
|
||||
{
|
||||
SuccessOrExit(OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT16_S, aAckFrame->mLength));
|
||||
SuccessOrExit(OutboundFrameFeedData(aAckFrame->mPsdu, aAckFrame->mLength));
|
||||
SuccessOrExit(OutboundFrameFeedPacked(
|
||||
SPINEL_DATATYPE_INT8_S
|
||||
SPINEL_DATATYPE_INT8_S
|
||||
SPINEL_DATATYPE_UINT16_S
|
||||
SPINEL_DATATYPE_STRUCT_S( // PHY-data
|
||||
SPINEL_DATATYPE_UINT8_S // 802.15.4 channel
|
||||
SPINEL_DATATYPE_UINT8_S // 802.15.4 LQI
|
||||
),
|
||||
aAckFrame->mPower, // RSSI
|
||||
-128, // Noise Floor (Currently unused)
|
||||
0, // Flags
|
||||
aAckFrame->mChannel, // Receive channel
|
||||
aAckFrame->mLqi, // Link quality indicator
|
||||
aFrame->mMsec, // The timestamp milliseconds
|
||||
aFrame->mUsec // The timestamp microseconds, offset to mMsec
|
||||
));
|
||||
SuccessOrExit(mEncoder.WriteUint16(aAckFrame->mLength));
|
||||
SuccessOrExit(mEncoder.WriteData(aAckFrame->mPsdu, aAckFrame->mLength));
|
||||
|
||||
SuccessOrExit(mEncoder.WriteInt8(aAckFrame->mPower)); // RSSI
|
||||
SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise Floor (Currently unused)
|
||||
SuccessOrExit(mEncoder.WriteUint16(0)); // Flags
|
||||
|
||||
SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
|
||||
|
||||
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mChannel)); // Receive channel
|
||||
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mLqi)); // Link Quality Indicator
|
||||
|
||||
SuccessOrExit(mEncoder.CloseStruct());
|
||||
}
|
||||
|
||||
SuccessOrExit(OutboundFrameSend());
|
||||
SuccessOrExit(mEncoder.EndFrame());
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -186,15 +157,7 @@ void NcpBase::LinkRawEnergyScanDone(otInstance *, int8_t aEnergyScanMaxRssi)
|
||||
|
||||
void NcpBase::LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi)
|
||||
{
|
||||
SendPropertyUpdate(
|
||||
SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
SPINEL_PROP_MAC_ENERGY_SCAN_RESULT,
|
||||
SPINEL_DATATYPE_UINT8_S
|
||||
SPINEL_DATATYPE_INT8_S,
|
||||
mCurScanChannel,
|
||||
aEnergyScanMaxRssi
|
||||
);
|
||||
int8_t scanChannel = mCurScanChannel;
|
||||
|
||||
// Clear current scan channel
|
||||
mCurScanChannel = kInvalidScanChannel;
|
||||
@@ -203,17 +166,32 @@ void NcpBase::LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi)
|
||||
// since the energy scan could have been on a different channel.
|
||||
otLinkRawReceive(mInstance, mCurReceiveChannel, &NcpBase::LinkRawReceiveDone);
|
||||
|
||||
SuccessOrExit(
|
||||
mEncoder.BeginFrame(
|
||||
SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
SPINEL_PROP_MAC_ENERGY_SCAN_RESULT
|
||||
));
|
||||
|
||||
SuccessOrExit(mEncoder.WriteUint8(static_cast<uint8_t>(scanChannel)));
|
||||
SuccessOrExit(mEncoder.WriteInt8(aEnergyScanMaxRssi));
|
||||
SuccessOrExit(mEncoder.EndFrame());
|
||||
|
||||
// We are finished with the scan, so send out
|
||||
// a property update indicating such.
|
||||
SendPropertyUpdate(
|
||||
SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
SPINEL_PROP_MAC_SCAN_STATE,
|
||||
SPINEL_DATATYPE_UINT8_S,
|
||||
SPINEL_SCAN_STATE_IDLE
|
||||
);
|
||||
}
|
||||
SuccessOrExit(
|
||||
mEncoder.BeginFrame(
|
||||
SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
SPINEL_PROP_MAC_SCAN_STATE
|
||||
));
|
||||
|
||||
SuccessOrExit(mEncoder.WriteUint8(SPINEL_SCAN_STATE_IDLE));
|
||||
SuccessOrExit(mEncoder.EndFrame());
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_MAC_SRC_MATCH_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
@@ -273,14 +251,9 @@ otError NcpBase::SetPropertyHandler_MAC_SRC_MATCH_SHORT_ADDRESSES(uint8_t aHeade
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
}
|
||||
|
||||
error =
|
||||
SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
aValuePtr,
|
||||
aValueLen
|
||||
);
|
||||
SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, aKey));
|
||||
SuccessOrExit(error = mEncoder.WriteData(aValuePtr, aValueLen));
|
||||
SuccessOrExit(error = mEncoder.EndFrame());
|
||||
|
||||
exit:
|
||||
|
||||
@@ -328,14 +301,9 @@ otError NcpBase::SetPropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(uint8_t aHe
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
}
|
||||
|
||||
error =
|
||||
SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_IS,
|
||||
aKey,
|
||||
aValuePtr,
|
||||
aValueLen
|
||||
);
|
||||
SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, aKey));
|
||||
SuccessOrExit(error = mEncoder.WriteData(aValuePtr, aValueLen));
|
||||
SuccessOrExit(error = mEncoder.EndFrame());
|
||||
|
||||
exit:
|
||||
|
||||
@@ -347,12 +315,10 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpBase::RemovePropertyHandler_MAC_SRC_MATCH_SHORT_ADDRESSES(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
otError NcpBase::RemovePropertyHandler_MAC_SRC_MATCH_SHORT_ADDRESSES(const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
{
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_status_t spinelError = SPINEL_STATUS_OK;
|
||||
uint16_t shortAddress;
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
@@ -362,35 +328,18 @@ otError NcpBase::RemovePropertyHandler_MAC_SRC_MATCH_SHORT_ADDRESSES(uint8_t aHe
|
||||
&shortAddress
|
||||
);
|
||||
|
||||
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
|
||||
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
error = otLinkRawSrcMatchClearShortEntry(mInstance, shortAddress);
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
|
||||
error = SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_REMOVED,
|
||||
aKey,
|
||||
aValuePtr,
|
||||
aValueLen
|
||||
);
|
||||
|
||||
exit:
|
||||
|
||||
if (spinelError != SPINEL_STATUS_OK)
|
||||
{
|
||||
error = SendLastStatus(aHeader, spinelError);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpBase::RemovePropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
otError NcpBase::RemovePropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
{
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_status_t spinelError = SPINEL_STATUS_OK;
|
||||
otExtAddress *extAddress;
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
@@ -400,35 +349,18 @@ otError NcpBase::RemovePropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(uint8_t
|
||||
&extAddress
|
||||
);
|
||||
|
||||
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
|
||||
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
error = otLinkRawSrcMatchClearExtEntry(mInstance, extAddress);
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
|
||||
error = SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_REMOVED,
|
||||
aKey,
|
||||
aValuePtr,
|
||||
aValueLen
|
||||
);
|
||||
|
||||
exit:
|
||||
|
||||
if (spinelError != SPINEL_STATUS_OK)
|
||||
{
|
||||
error = SendLastStatus(aHeader, spinelError);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpBase::InsertPropertyHandler_MAC_SRC_MATCH_SHORT_ADDRESSES(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
otError NcpBase::InsertPropertyHandler_MAC_SRC_MATCH_SHORT_ADDRESSES(const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
{
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_status_t spinelError = SPINEL_STATUS_OK;
|
||||
uint16_t short_address;
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
@@ -438,36 +370,18 @@ otError NcpBase::InsertPropertyHandler_MAC_SRC_MATCH_SHORT_ADDRESSES(uint8_t aHe
|
||||
&short_address
|
||||
);
|
||||
|
||||
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
|
||||
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
error = otLinkRawSrcMatchAddShortEntry(mInstance, short_address);
|
||||
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
|
||||
error = SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_INSERTED,
|
||||
aKey,
|
||||
aValuePtr,
|
||||
aValueLen
|
||||
);
|
||||
|
||||
exit:
|
||||
|
||||
if (spinelError != SPINEL_STATUS_OK)
|
||||
{
|
||||
error = SendLastStatus(aHeader, spinelError);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpBase::InsertPropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(uint8_t aHeader, spinel_prop_key_t aKey,
|
||||
const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
otError NcpBase::InsertPropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(const uint8_t *aValuePtr, uint16_t aValueLen)
|
||||
{
|
||||
spinel_ssize_t parsedLength;
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_status_t spinelError = SPINEL_STATUS_OK;
|
||||
otExtAddress *extAddress = NULL;
|
||||
|
||||
parsedLength = spinel_datatype_unpack(
|
||||
@@ -477,27 +391,11 @@ otError NcpBase::InsertPropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(uint8_t
|
||||
&extAddress
|
||||
);
|
||||
|
||||
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
|
||||
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
error = otLinkRawSrcMatchAddExtEntry(mInstance, extAddress);
|
||||
|
||||
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
|
||||
|
||||
error = SendPropertyUpdate(
|
||||
aHeader,
|
||||
SPINEL_CMD_PROP_VALUE_INSERTED,
|
||||
aKey,
|
||||
aValuePtr,
|
||||
aValueLen
|
||||
);
|
||||
|
||||
exit:
|
||||
|
||||
if (spinelError != SPINEL_STATUS_OK)
|
||||
{
|
||||
error = SendLastStatus(aHeader, spinelError);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
+23
-5
@@ -211,8 +211,8 @@ uint16_t NcpFrameBuffer::ReadUint16At(uint8_t *aBufPtr, Direction aDirection)
|
||||
return value;
|
||||
}
|
||||
|
||||
// Writes a byte at the write tail, discards the frame if buffer gets full.
|
||||
otError NcpFrameBuffer::InFrameFeedByte(uint8_t aByte)
|
||||
// Appends a byte at the write tail and updates the tail, discards the frame if buffer gets full.
|
||||
otError NcpFrameBuffer::InFrameAppend(uint8_t aByte)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint8_t *newTail;
|
||||
@@ -254,7 +254,7 @@ otError NcpFrameBuffer::InFrameBeginSegment(void)
|
||||
// Reserve space for the segment header.
|
||||
for (uint16_t i = kSegmentHeaderSize; i; i--)
|
||||
{
|
||||
SuccessOrExit(error = InFrameFeedByte(0));
|
||||
SuccessOrExit(error = InFrameAppend(0));
|
||||
}
|
||||
|
||||
// Write the flags at the segment head.
|
||||
@@ -344,6 +344,21 @@ otError NcpFrameBuffer::InFrameBegin(Priority aPriority)
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError NcpFrameBuffer::InFrameFeedByte(uint8_t aByte)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
// Begin a new segment (if we are not in middle of segment already).
|
||||
SuccessOrExit(error = InFrameBeginSegment());
|
||||
|
||||
error = InFrameAppend(aByte);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpFrameBuffer::InFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -356,7 +371,7 @@ otError NcpFrameBuffer::InFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDa
|
||||
// Write the data buffer
|
||||
while (aDataBufferLength--)
|
||||
{
|
||||
SuccessOrExit(error = InFrameFeedByte(*aDataBuffer++));
|
||||
SuccessOrExit(error = InFrameAppend(*aDataBuffer++));
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -383,12 +398,15 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpFrameBuffer::InFrameGetPosition(WritePosition &aPosition) const
|
||||
otError NcpFrameBuffer::InFrameGetPosition(WritePosition &aPosition)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
// Begin a new segment (if we are not in middle of segment already).
|
||||
SuccessOrExit(error = InFrameBeginSegment());
|
||||
|
||||
aPosition.mPosition = mWriteSegmentTail;
|
||||
aPosition.mSegmentHead = mWriteSegmentHead;
|
||||
|
||||
|
||||
+25
-7
@@ -40,7 +40,6 @@
|
||||
namespace ot {
|
||||
namespace Ncp {
|
||||
|
||||
|
||||
/**
|
||||
* This class implements a buffer/queue for storing NCP frames.
|
||||
*
|
||||
@@ -52,6 +51,7 @@ namespace Ncp {
|
||||
*/
|
||||
class NcpFrameBuffer
|
||||
{
|
||||
friend class SpinelEncoder;
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -163,6 +163,24 @@ public:
|
||||
*/
|
||||
otError InFrameBegin(Priority aPriority);
|
||||
|
||||
/**
|
||||
* This method adds a single byte to current input frame.
|
||||
*
|
||||
* Before using this method `InFrameBegin()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aByte The byte value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given byte to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the byte.
|
||||
* @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError InFrameFeedByte(uint8_t aByte);
|
||||
|
||||
/**
|
||||
* This method adds data to the current input frame.
|
||||
*
|
||||
@@ -177,7 +195,7 @@ public:
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added new data to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add data.
|
||||
* @retval OT_ERROR_INVALID_STATE InFrameBegin() has not been called earlier to start the frame.
|
||||
* @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError InFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength);
|
||||
@@ -198,7 +216,7 @@ public:
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added the message to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the message.
|
||||
* @retval OT_ERROR_INVALID_STATE InFrameBegin() has not been called earlier to start the frame.
|
||||
* @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame.
|
||||
* @retval OT_ERROR_INVALID_ARGS If @p aMessage is NULL.
|
||||
*
|
||||
*/
|
||||
@@ -214,10 +232,10 @@ public:
|
||||
* @param[out] aPosition A reference to a `WritePosition` to save the current write position.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully saved current write position in @p aPosition.
|
||||
* @retval OT_ERROR_INVALID_STATE InFrameBegin() has not been called earlier to start the frame.
|
||||
* @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError InFrameGetPosition(WritePosition &aPosition) const;
|
||||
otError InFrameGetPosition(WritePosition &aPosition);
|
||||
|
||||
/**
|
||||
* This method overwrites the previously written content in the current input frame at a given write position.
|
||||
@@ -286,7 +304,7 @@ public:
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully ended the input frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add message.
|
||||
* @retval OT_ERROR_INVALID_STATE InFrameBegin() has not been called earlier to start the frame.
|
||||
* @retval OT_ERROR_INVALID_STATE `InFrameBegin()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError InFrameEnd(void);
|
||||
@@ -581,7 +599,7 @@ private:
|
||||
bool HasFrame(Priority aPriority) const;
|
||||
void UpdateReadWriteStartPointers(void);
|
||||
|
||||
otError InFrameFeedByte(uint8_t aByte);
|
||||
otError InFrameAppend(uint8_t aByte);
|
||||
otError InFrameBeginSegment(void);
|
||||
void InFrameEndSegment(uint16_t aSegmentHeaderFlags);
|
||||
void InFrameDiscard(void);
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements a spinel encoder.
|
||||
*/
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include "spinel_encoder.hpp"
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Ncp {
|
||||
|
||||
otError SpinelEncoder::BeginFrame(NcpFrameBuffer::Priority aPriority)
|
||||
{
|
||||
mNumOpenStructs = 0;
|
||||
return mNcpBuffer.InFrameBegin(aPriority);
|
||||
}
|
||||
|
||||
otError SpinelEncoder::BeginFrame(uint8_t aHeader, unsigned int aCommand)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
// Non-zero TID indicates this is a response to a spinel command.
|
||||
|
||||
if (SPINEL_HEADER_GET_TID(aHeader) != 0)
|
||||
{
|
||||
SuccessOrExit(error = BeginFrame(NcpFrameBuffer::kPriorityHigh));
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = BeginFrame(NcpFrameBuffer::kPriorityLow));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = WriteUint8(aHeader));
|
||||
SuccessOrExit(error = WriteUintPacked(aCommand));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::BeginFrame(uint8_t aHeader, unsigned int aCommand, spinel_prop_key_t aKey)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = BeginFrame(aHeader, aCommand));
|
||||
|
||||
// The write position is saved before writing the property key,
|
||||
// so that if fetching the property fails and we need to
|
||||
// reply with a `LAST_STATUS` error we can get back to
|
||||
// this saved write position and update the property key.
|
||||
// (Also see `OverwriteWithLastStatusError()`).
|
||||
|
||||
SuccessOrExit(error = SavePosition());
|
||||
SuccessOrExit(error = WriteUintPacked(aKey));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::OverwriteWithLastStatusError(spinel_status_t aStatus)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = ResetToSaved());
|
||||
SuccessOrExit(error = WriteUintPacked(SPINEL_PROP_LAST_STATUS));
|
||||
SuccessOrExit(error = WriteUintPacked(aStatus));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::EndFrame(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
while (mNumOpenStructs > 0)
|
||||
{
|
||||
SuccessOrExit(error = CloseStruct());
|
||||
}
|
||||
|
||||
error = mNcpBuffer.InFrameEnd();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::WriteUint16(uint16_t aUint16)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint16 >> 0) & 0xff));
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint16 >> 8) & 0xff));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::WriteUint32(uint32_t aUint32)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 0) & 0xff));
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 8) & 0xff));
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 16) & 0xff));
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 24) & 0xff));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::WriteUintPacked(unsigned int aUint)
|
||||
{
|
||||
uint8_t buffer[6];
|
||||
spinel_ssize_t len;
|
||||
|
||||
len = spinel_packed_uint_encode(buffer, sizeof(buffer), aUint);
|
||||
|
||||
return WriteData(buffer, static_cast<uint16_t>(len));
|
||||
}
|
||||
|
||||
otError SpinelEncoder::WriteDataWithLen(const uint8_t *aData, uint16_t aDataLen)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = WriteUint16(aDataLen));
|
||||
SuccessOrExit(error = WriteData(aData, aDataLen));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::WriteUtf8(const char *aUtf8)
|
||||
{
|
||||
otError error;
|
||||
size_t len = strlen(aUtf8);
|
||||
|
||||
if (len >= 0xffff)
|
||||
{
|
||||
len = 0xffff;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = WriteData(reinterpret_cast<const uint8_t *>(aUtf8), static_cast<uint16_t>(len)));
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::OpenStruct(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameGetPosition(mStructPosition[mNumOpenStructs]));
|
||||
|
||||
// Reserve bytes for the length to be filled when the struct gets closed.
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));
|
||||
|
||||
mNumOpenStructs++;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::CloseStruct(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t len;
|
||||
uint8_t buffer[sizeof(uint16_t)];
|
||||
|
||||
VerifyOrExit(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
mNumOpenStructs--;
|
||||
|
||||
len = mNcpBuffer.InFrameGetDistance(mStructPosition[mNumOpenStructs]);
|
||||
VerifyOrExit(len >= sizeof(uint16_t), error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
len -= sizeof(uint16_t);
|
||||
|
||||
buffer[0] = (len >> 0 & 0xff);
|
||||
buffer[1] = (len >> 8 & 0xff);
|
||||
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameOverwrite(mStructPosition[mNumOpenStructs], buffer, sizeof(buffer)));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::SavePosition(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameGetPosition(mSavedPosition));
|
||||
mSavedNumOpenStructs = mNumOpenStructs;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::ResetToSaved(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = mNcpBuffer.InFrameReset(mSavedPosition));
|
||||
mNumOpenStructs = mSavedNumOpenStructs;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::WritePacked(const char *aPackFormat, ...)
|
||||
{
|
||||
uint8_t buf[kPackFormatBufferSize];
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_ssize_t packedLen;
|
||||
va_list args;
|
||||
|
||||
va_start(args, aPackFormat);
|
||||
|
||||
packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, args);
|
||||
VerifyOrExit((packedLen > 0) && (packedLen <= static_cast<spinel_ssize_t>(sizeof(buf))), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
error = mNcpBuffer.InFrameFeedData(buf, static_cast<uint16_t>(packedLen));
|
||||
|
||||
va_end(args);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SpinelEncoder::WriteVPacked(const char *aPackFormat, va_list aArgs)
|
||||
{
|
||||
uint8_t buf[kPackFormatBufferSize];
|
||||
otError error = OT_ERROR_NONE;
|
||||
spinel_ssize_t packedLen;
|
||||
|
||||
packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, aArgs);
|
||||
VerifyOrExit((packedLen > 0) && (packedLen <= static_cast<spinel_ssize_t>(sizeof(buf))), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
error = mNcpBuffer.InFrameFeedData(buf, static_cast<uint16_t>(packedLen));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Ncp
|
||||
} // namespace ot
|
||||
@@ -0,0 +1,652 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains the definitions of a spinel encoder.
|
||||
*/
|
||||
|
||||
#ifndef SPINEL_ENCODER_HPP_
|
||||
#define SPINEL_ENCODER_HPP_
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <openthread/message.h>
|
||||
#include <openthread/ncp.h>
|
||||
#include <openthread/types.h>
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
#include "ncp/spinel.h"
|
||||
#include "ncp/ncp_buffer.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Ncp {
|
||||
|
||||
/**
|
||||
* This class defines a spinel encoder.
|
||||
*
|
||||
*/
|
||||
class SpinelEncoder
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes a `SpinelEncoder` object.
|
||||
*
|
||||
* @param[in] aNcpBuffer A reference to a `NcpFrameBuffer` where the frames are written.
|
||||
*
|
||||
*/
|
||||
SpinelEncoder(NcpFrameBuffer &aNcpBuffer): mNcpBuffer(aNcpBuffer), mNumOpenStructs(0) { }
|
||||
|
||||
/**
|
||||
* This method begins a new frame to be added/written to the frame buffer.
|
||||
*
|
||||
* If there is a previous frame being written (for which `EndFrame()` has not yet been called), calling
|
||||
* `BeginFrame()` will discard and clear the previous unfinished frame.
|
||||
*
|
||||
* @param[in] aPriority Priority level of the new input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started a new frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to start a new frame.
|
||||
*
|
||||
*/
|
||||
otError BeginFrame(NcpFrameBuffer::Priority aPriority);
|
||||
|
||||
/**
|
||||
* This method begins a new spinel command frame to be added/written to the frame buffer.
|
||||
*
|
||||
* If there is a previous frame being written (for which `EndFrame()` has not yet been called), calling
|
||||
* `BeginFrame()` will discard and clear the previous unfinished frame.
|
||||
*
|
||||
* The spinel transaction ID (TID) in the given spinel header is used to determine the priority level of the new
|
||||
* frame. Non-zero TID value indicates that the frame is a response and therefore it uses higher priority level.
|
||||
*
|
||||
* @param[in] aHeader Spinel header for new the command frame.
|
||||
* @param[in] aCommand Spinel command.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started a new frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to start a new frame.
|
||||
*
|
||||
*/
|
||||
otError BeginFrame(uint8_t aHeader, unsigned int aCommand);
|
||||
|
||||
/**
|
||||
* This method begins a new spinel property update command frame to be added/written to the frame buffer.
|
||||
*
|
||||
* If there is a previous frame being written (for which `EndFrame()` has not yet been called), calling
|
||||
* `BeginFrame()` will discard and clear the previous unfinished frame.
|
||||
*
|
||||
* The spinel transaction ID (TID) in the given spinel header is used to determine the priority level of the new
|
||||
* frame. Non-zero TID value indicates that the frame is a response and therefore it uses higher priority level.
|
||||
*
|
||||
* This method saves the write position before the property key (see also `SavePosition()`) so that if fetching the
|
||||
* property fails and the property key should be switched to `LAST_STATUS` with an error status, the saved
|
||||
* position can be used to update the property key in the frame (see also `OverwriteWithLastStatusError()`)
|
||||
*
|
||||
* @param[in] aHeader Spinel header for new the command frame.
|
||||
* @param[in] aCommand Spinel command.
|
||||
* @param[in] aKey Spinel property key
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started a new frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to start a new frame.
|
||||
*
|
||||
*/
|
||||
otError BeginFrame(uint8_t aHeader, unsigned int aCommand, spinel_prop_key_t aKey);
|
||||
|
||||
/**
|
||||
* This method overwrites the property key with `LAST_STATUS` in a property update command frame.
|
||||
*
|
||||
* This method should be only used after a successful `BeginFrame(aHeader, aCommand, aPropertKey)`, otherwise, its
|
||||
* behavior is undefined.
|
||||
*
|
||||
* This method moves the write position back to saved position by `BeginFrame()` and replaces the property key
|
||||
* `SPINEL_PORP_LAST_STATUS` and writes the given spinel status error.
|
||||
*
|
||||
* @param[in] aStatus Spinel error status
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully updated the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to update the frame.
|
||||
*
|
||||
*/
|
||||
otError OverwriteWithLastStatusError(spinel_status_t aStatus);
|
||||
|
||||
/**
|
||||
* This method finalizes/ends the current frame being written to the buffer.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new frame. Otherwise, this method
|
||||
* does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the frame and return error status
|
||||
* `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* This method ensures to close any open structure (previously opened using `OpenStruct()` but not closed using
|
||||
* `CloseStruct()`).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully ended the input frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add message.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError EndFrame(void);
|
||||
|
||||
/**
|
||||
* This method encodes and writes a boolean value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aBool The boolean value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given byte to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteBool(bool aBool) { return mNcpBuffer.InFrameFeedByte( aBool ? 0x01: 0x00); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes a `uint8_t` value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aUint8 The value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteUint8(uint8_t aUint8) { return mNcpBuffer.InFrameFeedByte(aUint8); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes an `int8_t` value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aInt8 The value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteInt8(int8_t aInt8) { return WriteUint8(static_cast<uint8_t>(aInt8)); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes a `uint16_t` value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aUint16 The value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteUint16(uint16_t aUint16);
|
||||
|
||||
/**
|
||||
* This method encodes and writes an `int16_t` value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aInt16 The value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteInt16(int16_t aInt16) { return WriteUint16(static_cast<uint16_t>(aInt16)); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes a `uint32_t` value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aUint32 The value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteUint32(uint32_t aUint32);
|
||||
|
||||
/**
|
||||
* This method encodes and writes an `int32_t` value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aInt32 The value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteInt32(int32_t aInt32) { return WriteUint32(static_cast<uint32_t>(aInt32)); }
|
||||
|
||||
/**
|
||||
* This method encodes (using spinel packed integer format) and writes a value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aUint The value to add to input frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteUintPacked(unsigned int aUint);
|
||||
|
||||
/**
|
||||
* This method encodes and writes an IPv6 address to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aIp6Addr A reference to the IPv6 address to be added (as `spinel_ipv6addr_t`)
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given address to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the IP address.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteIp6Address(const spinel_ipv6addr_t &aIp6Addr) { return WriteIp6Address(aIp6Addr.bytes); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes an IPv6 address to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aIp6Addr A reference to the IPv6 address to be added (as `otIp6Address`)
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given address to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the IP address.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteIp6Address(const otIp6Address &aIp6Addr) { return WriteIp6Address(aIp6Addr.mFields.m8); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes an IPv6 address to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aIp6AddrBuf A pointer to a buffer containing the IPv6 address.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given address to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the IP address.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteIp6Address(const uint8_t *aIp6AddrBuf) { return WriteData(aIp6AddrBuf, sizeof(spinel_ipv6addr_t)); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes an EUI64 value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aEui64 A reference to the EUI64 value as a `spinel_eui64_t` type.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the EUI64 value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteEui64(const spinel_eui64_t &aEui64) { return WriteEui64(aEui64.bytes); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes an EUI64 value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aExtAddress A reference to an `otExtAddress`
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the EUI64 value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteEui64(const otExtAddress &aExtAddress) { return WriteEui64(aExtAddress.m8); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes an EUI64 value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aExtAddress A pointer to a buffer containing the EUI64 value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the EUI64 value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteEui64(const uint8_t *aEui64) { return WriteData(aEui64, sizeof(spinel_eui64_t)); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes an EUI48 value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aEui48 A reference to the EUI48 value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the EUI48 value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteEui48(const spinel_eui48_t &aEui48) { return WriteEui48(aEui48.bytes); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes an EUI48 value to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aEui48 A pointer to a buffer containing the EUI64 value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given value to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the EUI48 value.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteEui48(const uint8_t *aEui48) { return WriteData(aEui48, sizeof(spinel_eui48_t)); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes a UTF8 string to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aUtf8 A const character pointer (C string).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given string to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the string.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteUtf8(const char *aUtf8);
|
||||
|
||||
/**
|
||||
* This method encodes and writes a sequence of bytes to current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aData A pointer to data buffer.
|
||||
* @param[in] aDataLen The length (number of bytes) in the data buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given data to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the byte.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteData(const uint8_t *aData, uint16_t aDataLen) { return mNcpBuffer.InFrameFeedData(aData, aDataLen); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes a data blob (sequence of bytes) with its length prepended before the data.
|
||||
*
|
||||
* The length of the data (in bytes) is prepended (with the length encoded as a `uint16`). The size of the length
|
||||
* field is not included in the length. This is similar to `SPINEL_DATATYPE_DATA_WLEN` type.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @param[in] aData A pointer to data buffer.
|
||||
* @param[in] aDataLen The length (number of bytes) in the data buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given data to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the byte.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteDataWithLen(const uint8_t *aData, uint16_t aDataLen);
|
||||
|
||||
/**
|
||||
* This method adds a message to the current input frame.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the frame and return error status
|
||||
* `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* In case of success, the passed-in message @p aMessage will be owned by the frame buffer instance and will be
|
||||
* freed when either the the frame is removed or discarded. In case of failure @p aMessage remains unchanged.
|
||||
*
|
||||
* @param[in] aMessage A message to be added to current frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added the message to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the message.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
* @retval OT_ERROR_INVALID_ARGS If @p aMessage is NULL.
|
||||
*
|
||||
*/
|
||||
otError WriteMessage(otMessage *aMessage) { return mNcpBuffer.InFrameFeedMessage(aMessage); }
|
||||
|
||||
/**
|
||||
* This method encodes and writes a set of variables to the current input frame using a given spinel packing format
|
||||
* string.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* Note that the encoded buffer should fit in `kPackFormatBufferSize` bytes.
|
||||
*
|
||||
* @param[in] aPackFormat A string giving the spinel packing format.
|
||||
* @param[in] ... Variable arguments corresponding to the types given in @p aPackFormat (see
|
||||
* `spinel_datatype_pack()`).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given data to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the byte.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WritePacked(const char *aPackFormat, ...);
|
||||
|
||||
/**
|
||||
* This method encodes and writes a set of variables to the current input frame using a given spinel packing format
|
||||
* string.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the current input frame and return the
|
||||
* error status `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* Note that the encoded buffer should fit in `kPackFormatBufferSize` bytes.
|
||||
*
|
||||
* @param[in] aPackFormat A string giving the spinel packing format.
|
||||
* @param[in] aArgs Variable arguments corresponding to the types given in @p aPackFormat (see
|
||||
* `spinel_datatype_pack()`).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added given data to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the byte.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError WriteVPacked(const char *aPackFormat, va_list aArgs);
|
||||
|
||||
/**
|
||||
* This method opens a struct in the current input frame.
|
||||
*
|
||||
* After a successful call to this method, all the subsequent `Write<SomeType>()` methods add the field/value to
|
||||
* the current open struct until the struct is closed using `CloseStruct()` method. Structs can be nested. Up to
|
||||
* `kMaxNestedStructs` nested structs can be opened at the same time.
|
||||
*
|
||||
* Before using this method `BeginFrame()` must be called to start and prepare a new input frame. Otherwise, this
|
||||
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the frame and return error status
|
||||
* `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added the message to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to open the struct.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame or if we reached
|
||||
* the maximum number of nested open structures.
|
||||
*
|
||||
*/
|
||||
otError OpenStruct(void);
|
||||
|
||||
/**
|
||||
* This method closes the most recently opened struct (using `OpenStruct()`) in the current input frame.
|
||||
*
|
||||
* Each call to `CloseStruct()` must correspond to an earlier successfully opened struct. If a frame is ended using
|
||||
* `EndFrame()` with remaining open structs, the `EndFrame()` method will close all the remaining structs.
|
||||
*
|
||||
* If no buffer space is available, this method will discard and clear the frame and return error status
|
||||
* `OT_ERROR_NO_BUFS`.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added the message to the frame.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to open the struct.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame or if there is no
|
||||
* open struct to close
|
||||
*/
|
||||
otError CloseStruct(void);
|
||||
|
||||
/**
|
||||
* This method saves the current write position in the input frame.
|
||||
*
|
||||
* The saved position can later be used to discard a portion of written/encoded frame and move the write pointer
|
||||
* back to the saved position (using `ResetToSaved()`).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully saved current write position in @p aPosition.
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
*
|
||||
*/
|
||||
otError SavePosition(void);
|
||||
|
||||
/**
|
||||
* This method resets the write position of input frame back to a previously saved position. Any added content
|
||||
* after the write position is discarded.
|
||||
*
|
||||
* The saved position must belong to the same input frame saved earlier with `SavePosition()`. This method cannot
|
||||
* be used if the input frame has an added `otMessage`.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully reset the write position of current input frame..
|
||||
* @retval OT_ERROR_INVALID_STATE `BeginFrame()` has not been called earlier to start the frame.
|
||||
* @retval OT_ERROR_INVALID_ARGS The saved position is not valid (does not belong to same input frame), or
|
||||
* the input frame has an added `otMessage`.
|
||||
*
|
||||
*/
|
||||
otError ResetToSaved(void);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kPackFormatBufferSize = 96, ///< Size of buffer used when encoding using `WritePacked()` or `WriteVPacked()`.
|
||||
kMaxNestedStructs = 4, ///< Maximum number of nested structs.
|
||||
};
|
||||
|
||||
NcpFrameBuffer &mNcpBuffer;
|
||||
NcpFrameBuffer::WritePosition mStructPosition[kMaxNestedStructs];
|
||||
uint8_t mNumOpenStructs;
|
||||
|
||||
uint8_t mSavedNumOpenStructs;
|
||||
NcpFrameBuffer::WritePosition mSavedPosition;
|
||||
};
|
||||
|
||||
} // namespace Ncp
|
||||
} // namespace ot
|
||||
|
||||
#endif // SPINEL_ENCODER_HPP_
|
||||
@@ -97,6 +97,7 @@ check_PROGRAMS = \
|
||||
test-strlcat \
|
||||
test-strlcpy \
|
||||
test-strnlen \
|
||||
test-spinel-encoder \
|
||||
test-timer \
|
||||
test-toolchain \
|
||||
$(NULL)
|
||||
@@ -186,6 +187,9 @@ test_strlcpy_SOURCES = test_strlcpy.c
|
||||
test_strnlen_LDADD = $(COMMON_LDADD)
|
||||
test_strnlen_SOURCES = test_strnlen.c
|
||||
|
||||
test_spinel_encoder_LDADD = $(COMMON_LDADD)
|
||||
test_spinel_encoder_SOURCES = test_platform.cpp test_spinel_encoder.cpp
|
||||
|
||||
test_timer_LDADD = $(COMMON_LDADD)
|
||||
test_timer_SOURCES = test_platform.cpp test_timer.cpp
|
||||
|
||||
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <openthread/openthread.h>
|
||||
|
||||
#include "openthread-instance.h"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "ncp/spinel_encoder.hpp"
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
namespace ot {
|
||||
namespace Ncp {
|
||||
|
||||
enum
|
||||
{
|
||||
kTestBufferSize = 800,
|
||||
};
|
||||
|
||||
// Dump the buffer content to screen.
|
||||
void DumpBuffer(const char *aTextMessage, uint8_t *aBuffer, uint16_t aBufferLength)
|
||||
{
|
||||
enum
|
||||
{
|
||||
kBytesPerLine = 32, // Number of bytes per line.
|
||||
};
|
||||
|
||||
char charBuff[kBytesPerLine + 1];
|
||||
uint16_t counter;
|
||||
uint8_t byte;
|
||||
|
||||
printf("\n%s - len = %u\n ", aTextMessage, aBufferLength);
|
||||
|
||||
counter = 0;
|
||||
|
||||
while (aBufferLength--)
|
||||
{
|
||||
byte = *aBuffer++;
|
||||
printf("%02X ", byte);
|
||||
charBuff[counter] = isprint(byte) ? static_cast<char>(byte) : '.';
|
||||
counter++;
|
||||
|
||||
if (counter == kBytesPerLine)
|
||||
{
|
||||
charBuff[counter] = 0;
|
||||
printf(" %s\n ", charBuff);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
charBuff[counter] = 0;
|
||||
|
||||
while (counter++ < kBytesPerLine)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf(" %s\n", charBuff);
|
||||
}
|
||||
|
||||
|
||||
otError ReadFrame(NcpFrameBuffer &aNcpBuffer, uint8_t *aFrame, uint16_t &aFrameLen)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = aNcpBuffer.OutFrameBegin());
|
||||
aFrameLen = aNcpBuffer.OutFrameGetLength();
|
||||
VerifyOrExit(aNcpBuffer.OutFrameRead(aFrameLen, aFrame) == aFrameLen, error = OT_ERROR_FAILED);
|
||||
SuccessOrExit(error = aNcpBuffer.OutFrameRemove());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void TestSpinelEncoder(void)
|
||||
{
|
||||
uint8_t buffer[kTestBufferSize];
|
||||
NcpFrameBuffer ncpBuffer(buffer, kTestBufferSize);
|
||||
SpinelEncoder encoder(ncpBuffer);
|
||||
|
||||
uint8_t frame[kTestBufferSize];
|
||||
uint16_t frameLen;
|
||||
spinel_ssize_t parsedLen;
|
||||
|
||||
const bool kBool_1 = true;
|
||||
const bool kBool_2 = false;
|
||||
const uint8_t kUint8 = 0x42;
|
||||
const int8_t kInt8 = -73;
|
||||
const uint16_t kUint16 = 0xabcd;
|
||||
const int16_t kInt16 = -567;
|
||||
const uint32_t kUint32 = 0xdeadbeef;
|
||||
const int32_t kInt32 = -123455678L;
|
||||
const unsigned int kUint_1 = 9;
|
||||
const unsigned int kUint_2 = 0xa3;
|
||||
const unsigned int kUint_3 = 0x8765;
|
||||
const unsigned int kUint_4 = SPINEL_MAX_UINT_PACKED - 1;
|
||||
|
||||
const spinel_ipv6addr_t kIp6Addr =
|
||||
{
|
||||
{ 0x6B, 0x41, 0x65, 0x73, 0x42, 0x68, 0x61, 0x76, 0x54, 0x61, 0x72, 0x7A, 0x49, 0x69, 0x61, 0x4E }
|
||||
};
|
||||
|
||||
const spinel_eui48_t kEui48 =
|
||||
{
|
||||
{ 4, 8, 15, 16, 23, 42 } // "Lost" EUI48!
|
||||
};
|
||||
|
||||
const spinel_eui64_t kEui64 =
|
||||
{
|
||||
{ 2, 3, 5, 7, 11, 13, 17, 19 }, // "Prime" EUI64!
|
||||
};
|
||||
|
||||
const char kString_1[] = "OpenThread";
|
||||
const char kString_2[] = "";
|
||||
|
||||
const uint16_t kData[] = { 10, 20, 3, 15, 1000, 60, 16 }; // ... then comes 17,18,19,20 :)
|
||||
|
||||
bool b_1, b_2;
|
||||
uint8_t u8;
|
||||
int8_t i8;
|
||||
uint16_t u16;
|
||||
int16_t i16;
|
||||
uint32_t u32;
|
||||
int32_t i32;
|
||||
unsigned int u_1, u_2, u_3, u_4;
|
||||
spinel_ipv6addr_t *ip6Addr;
|
||||
spinel_eui48_t *eui48;
|
||||
spinel_eui64_t *eui64;
|
||||
const char *utf_1;
|
||||
const char *utf_2;
|
||||
const uint8_t *dataPtr;
|
||||
spinel_size_t dataLen;
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
printf("\nTest 1: Encoding of simple types");
|
||||
|
||||
SuccessOrQuit(encoder.BeginFrame(NcpFrameBuffer::kPriorityLow), "BeginFrame() failed.");
|
||||
SuccessOrQuit(encoder.WriteBool(kBool_1), "WriteBool() failed.");
|
||||
SuccessOrQuit(encoder.WriteBool(kBool_2), "WriteBool() failed.");
|
||||
SuccessOrQuit(encoder.WriteUint8(kUint8), "WriteUint8() failed.");
|
||||
SuccessOrQuit(encoder.WriteInt8(kInt8), "WriteUint8() failed.");
|
||||
SuccessOrQuit(encoder.WriteUint16(kUint16), "WriteUint16() failed.");
|
||||
SuccessOrQuit(encoder.WriteInt16(kInt16), "WriteInt16() failed.");
|
||||
SuccessOrQuit(encoder.WriteUint32(kUint32), "WriteUint32() failed.");
|
||||
SuccessOrQuit(encoder.WriteInt32(kInt32), "WriteUint32() failed.");
|
||||
SuccessOrQuit(encoder.WriteUintPacked(kUint_1), "WriteUintPacked() failed.");
|
||||
SuccessOrQuit(encoder.WriteUintPacked(kUint_2), "WriteUintPacked() failed.");
|
||||
SuccessOrQuit(encoder.WriteUintPacked(kUint_3), "WriteUintPacked() failed.");
|
||||
SuccessOrQuit(encoder.WriteUintPacked(kUint_4), "WriteUintPacked() failed.");
|
||||
SuccessOrQuit(encoder.WriteIp6Address(kIp6Addr), "WriteIp6Addr() failed.");
|
||||
SuccessOrQuit(encoder.WriteEui48(kEui48), "WriteEui48() failed.");
|
||||
SuccessOrQuit(encoder.WriteEui64(kEui64), "WriteEui64() failed.");
|
||||
SuccessOrQuit(encoder.WriteUtf8(kString_1), "WriteUtf8() failed.");
|
||||
SuccessOrQuit(encoder.WriteUtf8(kString_2), "WriteUtf8() failed.");
|
||||
SuccessOrQuit(encoder.WriteData((const uint8_t *)kData, sizeof(kData)), "WriteData() failed.");
|
||||
SuccessOrQuit(encoder.EndFrame(), "EndFrame() failed.");
|
||||
|
||||
DumpBuffer("Buffer", buffer, 256);
|
||||
SuccessOrQuit(ReadFrame(ncpBuffer, frame, frameLen), "ReadFrame() failed.");
|
||||
DumpBuffer("Frame", frame, frameLen);
|
||||
|
||||
parsedLen = spinel_datatype_unpack(
|
||||
frame,
|
||||
(spinel_size_t)frameLen,
|
||||
(
|
||||
SPINEL_DATATYPE_BOOL_S
|
||||
SPINEL_DATATYPE_BOOL_S
|
||||
SPINEL_DATATYPE_UINT8_S
|
||||
SPINEL_DATATYPE_INT8_S
|
||||
SPINEL_DATATYPE_UINT16_S
|
||||
SPINEL_DATATYPE_INT16_S
|
||||
SPINEL_DATATYPE_UINT32_S
|
||||
SPINEL_DATATYPE_INT32_S
|
||||
SPINEL_DATATYPE_UINT_PACKED_S
|
||||
SPINEL_DATATYPE_UINT_PACKED_S
|
||||
SPINEL_DATATYPE_UINT_PACKED_S
|
||||
SPINEL_DATATYPE_UINT_PACKED_S
|
||||
SPINEL_DATATYPE_IPv6ADDR_S
|
||||
SPINEL_DATATYPE_EUI48_S
|
||||
SPINEL_DATATYPE_EUI64_S
|
||||
SPINEL_DATATYPE_UTF8_S
|
||||
SPINEL_DATATYPE_UTF8_S
|
||||
SPINEL_DATATYPE_DATA_S
|
||||
),
|
||||
&b_1,
|
||||
&b_2,
|
||||
&u8,
|
||||
&i8,
|
||||
&u16,
|
||||
&i16,
|
||||
&u32,
|
||||
&i32,
|
||||
&u_1,
|
||||
&u_2,
|
||||
&u_3,
|
||||
&u_4,
|
||||
&ip6Addr,
|
||||
&eui48,
|
||||
&eui64,
|
||||
&utf_1,
|
||||
&utf_2,
|
||||
&dataPtr,
|
||||
&dataLen
|
||||
);
|
||||
|
||||
VerifyOrQuit(parsedLen == frameLen, "spinel parse failed");
|
||||
VerifyOrQuit(b_1 == kBool_1, "WriteBool() parse failed.");
|
||||
VerifyOrQuit(b_2 == kBool_2, "WriteBool() parse failed.");
|
||||
VerifyOrQuit(u8 == kUint8, "WriteUint8() parse failed.");
|
||||
VerifyOrQuit(i8 == kInt8, "WriteUint8() parse failed.");
|
||||
VerifyOrQuit(u16 == kUint16, "WriteUint16() parse failed.");
|
||||
VerifyOrQuit(i16 == kInt16, "WriteInt16() parse failed.");
|
||||
VerifyOrQuit(u32 == kUint32, "WriteUint32() parse failed.");
|
||||
VerifyOrQuit(i32 == kInt32, "WriteUint32() parse failed.");
|
||||
VerifyOrQuit(u_1 == kUint_1, "WriteUintPacked() parse failed.");
|
||||
VerifyOrQuit(u_2 == kUint_2, "WriteUintPacked() parse failed.");
|
||||
VerifyOrQuit(u_3 == kUint_3, "WriteUintPacked() parse failed.");
|
||||
VerifyOrQuit(u_4 == kUint_4, "WriteUintPacked() parse failed.");
|
||||
VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0, "WriteIp6Address() parse failed.");
|
||||
VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0, "WriteEui48() parse failed.");
|
||||
VerifyOrQuit(memcmp(eui64, &kEui64, sizeof(spinel_eui64_t)) == 0, "WriteEui64() parse failed.");
|
||||
VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0, "WriteUtf8() parse failed.");
|
||||
VerifyOrQuit(memcmp(utf_2, kString_2, sizeof(kString_2)) == 0, "WriteUtf8() parse failed.");
|
||||
VerifyOrQuit(dataLen == sizeof(kData), "WriteData() parse failed.");
|
||||
VerifyOrQuit(memcmp(dataPtr, &kData, sizeof(kData)) == 0, "WriteData() parse failed.");
|
||||
|
||||
printf(" -- PASS\n");
|
||||
|
||||
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
printf("\nTest 2: Test a single simple struct.");
|
||||
|
||||
SuccessOrQuit(encoder.BeginFrame(NcpFrameBuffer::kPriorityLow), "BeginFrame() failed.");
|
||||
SuccessOrQuit(encoder.WriteUint8(kUint8), "WriteUint8() failed.");
|
||||
SuccessOrQuit(encoder.OpenStruct(), "OpenStruct() failed.");
|
||||
{
|
||||
SuccessOrQuit(encoder.WriteUint32(kUint32), "WriteUint32() failed.");
|
||||
SuccessOrQuit(encoder.WriteEui48(kEui48), "WriteEui48() failed.");
|
||||
SuccessOrQuit(encoder.WriteUintPacked(kUint_3), "WriteUintPacked() failed.");
|
||||
}
|
||||
SuccessOrQuit(encoder.CloseStruct(), "CloseStruct() failed.");
|
||||
SuccessOrQuit(encoder.WriteInt16(kInt16), "WriteInt16() failed.");
|
||||
SuccessOrQuit(encoder.EndFrame(), "EndFrame() failed.");
|
||||
|
||||
DumpBuffer("Buffer", buffer, 256);
|
||||
SuccessOrQuit(ReadFrame(ncpBuffer, frame, frameLen), "ReadFrame() failed.");
|
||||
DumpBuffer("Frame", frame, frameLen);
|
||||
|
||||
parsedLen = spinel_datatype_unpack(
|
||||
frame,
|
||||
(spinel_size_t)frameLen,
|
||||
(
|
||||
SPINEL_DATATYPE_UINT8_S
|
||||
SPINEL_DATATYPE_STRUCT_S(
|
||||
SPINEL_DATATYPE_UINT32_S
|
||||
SPINEL_DATATYPE_EUI48_S
|
||||
SPINEL_DATATYPE_UINT_PACKED_S
|
||||
)
|
||||
SPINEL_DATATYPE_INT16_S
|
||||
|
||||
),
|
||||
&u8,
|
||||
&u32,
|
||||
&eui48,
|
||||
&u_3,
|
||||
&i16
|
||||
);
|
||||
|
||||
VerifyOrQuit(parsedLen == frameLen, "spinel parse failed");
|
||||
VerifyOrQuit(u8 == kUint8, "WriteUint8() parse failed.");
|
||||
VerifyOrQuit(i16 == kInt16, "WriteInt16() parse failed.");
|
||||
VerifyOrQuit(u32 == kUint32, "WriteUint32() parse failed.");
|
||||
VerifyOrQuit(u_3 == kUint_3, "WriteUintPacked() parse failed.");
|
||||
VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0, "WriteEui48() parse failed.");
|
||||
|
||||
// Parse the struct as a "data with len".
|
||||
parsedLen = spinel_datatype_unpack(
|
||||
frame,
|
||||
(spinel_size_t)frameLen,
|
||||
(
|
||||
SPINEL_DATATYPE_UINT8_S
|
||||
SPINEL_DATATYPE_DATA_WLEN_S
|
||||
SPINEL_DATATYPE_INT16_S
|
||||
|
||||
),
|
||||
&u8,
|
||||
&dataPtr,
|
||||
&dataLen,
|
||||
&i16
|
||||
);
|
||||
|
||||
VerifyOrQuit(parsedLen == frameLen, "spinel parse failed");
|
||||
VerifyOrQuit(u8 == kUint8, "WriteUint8() parse failed.");
|
||||
VerifyOrQuit(i16 == kInt16, "WriteInt16() parse failed.");
|
||||
|
||||
printf(" -- PASS\n");
|
||||
|
||||
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
printf("\nTest 3: Test multiple structs and struct within struct.");
|
||||
|
||||
SuccessOrQuit(encoder.BeginFrame(NcpFrameBuffer::kPriorityLow), "BeginFrame() failed.");
|
||||
SuccessOrQuit(encoder.OpenStruct(), "OpenStruct() failed.");
|
||||
{
|
||||
SuccessOrQuit(encoder.WriteUint8(kUint8), "WriteUint8() failed.");
|
||||
SuccessOrQuit(encoder.WriteUtf8(kString_1), "WriteUtf8() failed.");
|
||||
SuccessOrQuit(encoder.OpenStruct(), "OpenStruct() failed.");
|
||||
{
|
||||
SuccessOrQuit(encoder.WriteBool(kBool_1), "WriteBool() failed.");
|
||||
SuccessOrQuit(encoder.WriteIp6Address(kIp6Addr), "WriteIp6Addr() failed.");
|
||||
|
||||
}
|
||||
SuccessOrQuit(encoder.CloseStruct(), "CloseStruct() failed.");
|
||||
SuccessOrQuit(encoder.WriteUint16(kUint16), "WriteUint16() failed.");
|
||||
}
|
||||
SuccessOrQuit(encoder.CloseStruct(), "CloseStruct() failed.");
|
||||
SuccessOrQuit(encoder.WriteEui48(kEui48), "WriteEui48() failed.");
|
||||
SuccessOrQuit(encoder.OpenStruct(), "OpenStruct() failed.");
|
||||
{
|
||||
SuccessOrQuit(encoder.WriteUint32(kUint32), "WriteUint32() failed.");
|
||||
}
|
||||
SuccessOrQuit(encoder.CloseStruct(), "CloseStruct() failed.");
|
||||
SuccessOrQuit(encoder.WriteInt32(kInt32), "WriteUint32() failed.");
|
||||
SuccessOrQuit(encoder.EndFrame(), "EndFrame() failed.");
|
||||
|
||||
DumpBuffer("Buffer", buffer, 256 + 100);
|
||||
|
||||
SuccessOrQuit(ReadFrame(ncpBuffer, frame, frameLen), "ReadFrame() failed.");
|
||||
|
||||
parsedLen = spinel_datatype_unpack(
|
||||
frame,
|
||||
(spinel_size_t)frameLen,
|
||||
(
|
||||
SPINEL_DATATYPE_STRUCT_S(
|
||||
SPINEL_DATATYPE_UINT8_S
|
||||
SPINEL_DATATYPE_UTF8_S
|
||||
SPINEL_DATATYPE_STRUCT_S(
|
||||
SPINEL_DATATYPE_BOOL_S
|
||||
SPINEL_DATATYPE_IPv6ADDR_S
|
||||
)
|
||||
SPINEL_DATATYPE_UINT16_S
|
||||
)
|
||||
SPINEL_DATATYPE_EUI48_S
|
||||
SPINEL_DATATYPE_STRUCT_S(
|
||||
SPINEL_DATATYPE_UINT32_S
|
||||
)
|
||||
SPINEL_DATATYPE_INT32_S
|
||||
),
|
||||
&u8,
|
||||
&utf_1,
|
||||
&b_1,
|
||||
&ip6Addr,
|
||||
&u16,
|
||||
&eui48,
|
||||
&u32,
|
||||
&i32
|
||||
);
|
||||
|
||||
VerifyOrQuit(parsedLen == frameLen, "spinel parse failed");
|
||||
VerifyOrQuit(b_1 == kBool_1, "WriteBool() parse failed.");
|
||||
VerifyOrQuit(u8 == kUint8, "WriteUint8() parse failed.");
|
||||
VerifyOrQuit(u16 == kUint16, "WriteUint16() parse failed.");
|
||||
VerifyOrQuit(u32 == kUint32, "WriteUint32() parse failed.");
|
||||
VerifyOrQuit(i32 == kInt32, "WriteUint32() parse failed.");
|
||||
VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0, "WriteIp6Address() parse failed.");
|
||||
VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0, "WriteEui48() parse failed.");
|
||||
VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0, "WriteUtf8() parse failed.");
|
||||
|
||||
printf(" -- PASS\n");
|
||||
|
||||
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
printf("\nTest 4: Test unclosed struct.");
|
||||
|
||||
SuccessOrQuit(encoder.BeginFrame(NcpFrameBuffer::kPriorityLow), "BeginFrame() failed.");
|
||||
SuccessOrQuit(encoder.WriteUint8(kUint8), "WriteUint8() failed.");
|
||||
SuccessOrQuit(encoder.OpenStruct(), "OpenStruct() failed.");
|
||||
{
|
||||
SuccessOrQuit(encoder.WriteUint32(kUint32), "WriteUint32() failed.");
|
||||
SuccessOrQuit(encoder.OpenStruct(), "OpenStruct() failed.");
|
||||
{
|
||||
SuccessOrQuit(encoder.WriteEui48(kEui48), "WriteEui48() failed.");
|
||||
SuccessOrQuit(encoder.WriteUintPacked(kUint_3), "WriteUintPacked() failed.");
|
||||
// Do not close the structs expecting `EndFrame()` to close them.
|
||||
}
|
||||
}
|
||||
SuccessOrQuit(encoder.EndFrame(), "EndFrame() failed.");
|
||||
|
||||
SuccessOrQuit(ReadFrame(ncpBuffer, frame, frameLen), "ReadFrame() failed.");
|
||||
|
||||
parsedLen = spinel_datatype_unpack(
|
||||
frame,
|
||||
(spinel_size_t)frameLen,
|
||||
(
|
||||
SPINEL_DATATYPE_UINT8_S
|
||||
SPINEL_DATATYPE_STRUCT_S(
|
||||
SPINEL_DATATYPE_UINT32_S
|
||||
SPINEL_DATATYPE_STRUCT_S(
|
||||
SPINEL_DATATYPE_EUI48_S
|
||||
SPINEL_DATATYPE_UINT_PACKED_S
|
||||
)
|
||||
)
|
||||
),
|
||||
&u8,
|
||||
&u32,
|
||||
&eui48,
|
||||
&u_3
|
||||
);
|
||||
|
||||
VerifyOrQuit(parsedLen == frameLen, "spinel parse failed");
|
||||
VerifyOrQuit(u8 == kUint8, "WriteUint8() parse failed.");
|
||||
VerifyOrQuit(u32 == kUint32, "WriteUint32() parse failed.");
|
||||
VerifyOrQuit(u_3 == kUint_3, "WriteUintPacked() parse failed.");
|
||||
VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0, "WriteEui48() parse failed.");
|
||||
|
||||
printf(" -- PASS\n");
|
||||
|
||||
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
printf("\nTest 5: Test saving position and reseting back to a saved position");
|
||||
|
||||
SuccessOrQuit(encoder.BeginFrame(NcpFrameBuffer::kPriorityLow), "BeginFrame() failed.");
|
||||
SuccessOrQuit(encoder.WriteUint8(kUint8), "WriteUint8() failed.");
|
||||
SuccessOrQuit(encoder.OpenStruct(), "OpenStruct() failed.");
|
||||
{
|
||||
SuccessOrQuit(encoder.WriteUint32(kUint32), "WriteUint32() failed.");
|
||||
|
||||
// Save position in middle a first open struct.
|
||||
SuccessOrQuit(encoder.SavePosition(), "SavePosition failed.");
|
||||
SuccessOrQuit(encoder.OpenStruct(), "OpenStruct() failed.");
|
||||
{
|
||||
SuccessOrQuit(encoder.WriteEui48(kEui48), "WriteEui48() failed.");
|
||||
SuccessOrQuit(encoder.WriteUintPacked(kUint_3), "WriteUintPacked() failed.");
|
||||
}
|
||||
|
||||
// Reset to saved position in middle of the second open struct which should be discarded.
|
||||
|
||||
SuccessOrQuit(encoder.ResetToSaved(), "ResetToSaved() failed.");
|
||||
|
||||
SuccessOrQuit(encoder.WriteIp6Address(kIp6Addr), "WriteIp6Addr() failed.");
|
||||
SuccessOrQuit(encoder.WriteEui64(kEui64), "WriteEui64() failed.");
|
||||
}
|
||||
SuccessOrQuit(encoder.CloseStruct(), "CloseStruct() failed.");
|
||||
SuccessOrQuit(encoder.WriteUtf8(kString_1), "WriteUtf8() failed.");
|
||||
SuccessOrQuit(encoder.EndFrame(), "EndFrame() failed.");
|
||||
|
||||
SuccessOrQuit(ReadFrame(ncpBuffer, frame, frameLen), "ReadFrame() failed.");
|
||||
|
||||
parsedLen = spinel_datatype_unpack(
|
||||
frame,
|
||||
(spinel_size_t)frameLen,
|
||||
(
|
||||
SPINEL_DATATYPE_UINT8_S
|
||||
SPINEL_DATATYPE_STRUCT_S(
|
||||
SPINEL_DATATYPE_UINT32_S
|
||||
SPINEL_DATATYPE_IPv6ADDR_S
|
||||
SPINEL_DATATYPE_EUI64_S
|
||||
)
|
||||
SPINEL_DATATYPE_UTF8_S
|
||||
),
|
||||
&u8,
|
||||
&u32,
|
||||
&ip6Addr,
|
||||
&eui64,
|
||||
&utf_1
|
||||
);
|
||||
|
||||
VerifyOrQuit(parsedLen == frameLen, "spinel parse failed");
|
||||
|
||||
VerifyOrQuit(u8 == kUint8, "WriteUint8() parse failed.");
|
||||
VerifyOrQuit(u32 == kUint32, "WriteUint32() parse failed.");
|
||||
VerifyOrQuit(i32 == kInt32, "WriteUint32() parse failed.");
|
||||
VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0, "WriteIp6Address() parse failed.");
|
||||
VerifyOrQuit(memcmp(eui64, &kEui64, sizeof(spinel_eui64_t)) == 0, "WriteEui64() parse failed.");
|
||||
VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0, "WriteUtf8() parse failed.");
|
||||
|
||||
printf(" -- PASS\n");
|
||||
}
|
||||
|
||||
} // namespace Ncp
|
||||
} // namespace ot
|
||||
|
||||
#ifdef ENABLE_TEST_MAIN
|
||||
int main(void)
|
||||
{
|
||||
ot::Ncp::TestSpinelEncoder();
|
||||
printf("\nAll tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user