diff --git a/etc/visual-studio/libopenthread-ncp-spi.vcxproj b/etc/visual-studio/libopenthread-ncp-spi.vcxproj
index 9fd14d36d..d7adc3a5e 100644
--- a/etc/visual-studio/libopenthread-ncp-spi.vcxproj
+++ b/etc/visual-studio/libopenthread-ncp-spi.vcxproj
@@ -66,6 +66,7 @@
+
@@ -73,6 +74,7 @@
+
diff --git a/etc/visual-studio/libopenthread-ncp-spi.vcxproj.filters b/etc/visual-studio/libopenthread-ncp-spi.vcxproj.filters
index c58c45d1c..ad6f0f90b 100644
--- a/etc/visual-studio/libopenthread-ncp-spi.vcxproj.filters
+++ b/etc/visual-studio/libopenthread-ncp-spi.vcxproj.filters
@@ -36,6 +36,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -56,5 +59,8 @@
Header Files
+
+ Header Files
+
diff --git a/etc/visual-studio/libopenthread-ncp-uart.vcxproj b/etc/visual-studio/libopenthread-ncp-uart.vcxproj
index 3ce3ab613..3e996c4cb 100644
--- a/etc/visual-studio/libopenthread-ncp-uart.vcxproj
+++ b/etc/visual-studio/libopenthread-ncp-uart.vcxproj
@@ -67,6 +67,7 @@
+
@@ -75,6 +76,7 @@
+
diff --git a/etc/visual-studio/libopenthread-ncp-uart.vcxproj.filters b/etc/visual-studio/libopenthread-ncp-uart.vcxproj.filters
index 7f5765def..16df2e80e 100644
--- a/etc/visual-studio/libopenthread-ncp-uart.vcxproj.filters
+++ b/etc/visual-studio/libopenthread-ncp-uart.vcxproj.filters
@@ -42,6 +42,9 @@
Source Files
+
+ Source Files
+
@@ -62,5 +65,8 @@
Header Files
+
+ Header Files
+
diff --git a/src/ncp/Makefile.am b/src/ncp/Makefile.am
index c31ff4eb7..c9e2e6c78 100644
--- a/src/ncp/Makefile.am
+++ b/src/ncp/Makefile.am
@@ -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 \
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index 3be20af31..531e29340 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -182,52 +182,52 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] =
#endif
NCP_GET_PROP_HANDLER_ENTRY(STREAM_NET),
// MAC counters
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_TOTAL, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_ACK_REQ, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_ACKED, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_NO_ACK_REQ, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_DATA, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_DATA_POLL, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_BEACON, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_BEACON_REQ, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_OTHER, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_RETRY, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_UNICAST, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_PKT_BROADCAST, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_ERR_CCA, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_ERR_ABORT, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_TOTAL, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_DATA, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_DATA_POLL, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_BEACON, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_BEACON_REQ, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_OTHER, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_FILT_WL, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_FILT_DA, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_UNICAST, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_BROADCAST, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_ERR_EMPTY, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_ERR_UKWN_NBR, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_ERR_NVLD_SADDR, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_ERR_SECURITY, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_ERR_BAD_FCS, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_ERR_OTHER, MAC_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_PKT_DUP, MAC_CNTR),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_TOTAL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_ACK_REQ),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_ACKED),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_NO_ACK_REQ),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_DATA),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_DATA_POLL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_BEACON),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_BEACON_REQ),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_OTHER),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_RETRY),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_UNICAST),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_PKT_BROADCAST),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_ERR_CCA),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_ERR_ABORT),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_TOTAL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_DATA),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_DATA_POLL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_BEACON),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_BEACON_REQ),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_OTHER),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_FILT_WL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_FILT_DA),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_UNICAST),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_BROADCAST),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_ERR_EMPTY),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_ERR_UKWN_NBR),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_ERR_NVLD_SADDR),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_ERR_SECURITY),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_ERR_BAD_FCS),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_ERR_OTHER),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_PKT_DUP),
// NCP counters
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_IP_SEC_TOTAL, NCP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_IP_INSEC_TOTAL, NCP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_IP_DROPPED, NCP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_IP_SEC_TOTAL, NCP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_IP_INSEC_TOTAL, NCP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_IP_DROPPED, NCP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_TX_SPINEL_TOTAL, NCP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_SPINEL_TOTAL, NCP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_RX_SPINEL_ERR, NCP_CNTR),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_IP_SEC_TOTAL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_IP_INSEC_TOTAL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_IP_DROPPED),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_IP_SEC_TOTAL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_IP_INSEC_TOTAL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_IP_DROPPED),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_TX_SPINEL_TOTAL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_SPINEL_TOTAL),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_RX_SPINEL_ERR),
// IP counters
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_IP_TX_SUCCESS, IP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_IP_RX_SUCCESS, IP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_IP_TX_FAILURE, IP_CNTR),
- NCP_GET_PROP_HANDLER_ENTRY_METHOD(CNTR_IP_RX_FAILURE, IP_CNTR),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_IP_TX_SUCCESS),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_IP_RX_SUCCESS),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_IP_TX_FAILURE),
+ NCP_GET_PROP_HANDLER_ENTRY(CNTR_IP_RX_FAILURE),
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_FTD
@@ -534,6 +534,7 @@ NcpBase *NcpBase::sNcpInstance = NULL;
NcpBase::NcpBase(otInstance *aInstance):
mInstance(aInstance),
mTxFrameBuffer(mTxBuffer, sizeof(mTxBuffer)),
+ mEncoder(mTxFrameBuffer),
mHostPowerStateInProgress(false),
mLastStatus(SPINEL_STATUS_OK),
mSupportedChannelMask(OT_RADIO_SUPPORTED_CHANNELS),
@@ -606,62 +607,14 @@ NcpBase *NcpBase::GetNcpInstance(void)
}
// ----------------------------------------------------------------------------
-// MARK: Outbound Frame methods
+// MARK: Serial Traffic Glue
// ----------------------------------------------------------------------------
-otError NcpBase::OutboundFrameBegin(uint8_t aHeader)
-{
- NcpFrameBuffer::Priority priority;
-
- // Non-zero tid indicates this is a response to a spinel command.
- if (SPINEL_HEADER_GET_TID(aHeader) != 0)
- {
- priority = NcpFrameBuffer::kPriorityHigh;
- }
- else
- {
- priority = NcpFrameBuffer::kPriorityLow;
- }
-
- return mTxFrameBuffer.InFrameBegin(priority);
-}
-
-otError NcpBase::OutboundFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength)
-{
- return mTxFrameBuffer.InFrameFeedData(aDataBuffer, aDataBufferLength);
-}
-
-otError NcpBase::OutboundFrameFeedMessage(otMessage *aMessage)
-{
- return mTxFrameBuffer.InFrameFeedMessage(aMessage);
-}
-
-otError NcpBase::OutboundFrameEnd(void)
-{
- return mTxFrameBuffer.InFrameEnd();
-}
-
NcpFrameBuffer::FrameTag NcpBase::GetLastOutboundFrameTag(void)
{
return mTxFrameBuffer.InFrameGetLastTag();
}
-// ----------------------------------------------------------------------------
-// MARK: Serial Traffic Glue
-// ----------------------------------------------------------------------------
-
-otError NcpBase::OutboundFrameSend(void)
-{
- otError error;
-
- SuccessOrExit(error = OutboundFrameEnd());
-
- mTxSpinelFrameCounter++;
-
-exit:
- return error;
-}
-
void NcpBase::HandleReceive(const uint8_t *aBuf, uint16_t aBufLength)
{
uint8_t header = 0;
@@ -781,7 +734,7 @@ void NcpBase::HandleFrameRemovedFromNcpBuffer(NcpFrameBuffer::FrameTag aFrameTag
if (mHostPowerStateHeader)
{
SuccessOrExit(
- GetPropertyHandler_HOST_POWER_STATE(
+ HandleCommandPropertyGet(
mHostPowerStateHeader,
SPINEL_PROP_HOST_POWER_STATE
));
@@ -819,6 +772,7 @@ void NcpBase::IncrementFrameErrorCounter(void)
otError NcpBase::StreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLen)
{
otError error = OT_ERROR_NONE;
+ uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
spinel_prop_key_t streamPropKey;
if (aStreamId == 0)
@@ -833,21 +787,18 @@ otError NcpBase::StreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLe
VerifyOrExit(!mDisableStreamWrite, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(streamPropKey), error = OT_ERROR_INVALID_STATE);
- error = SendPropertyUpdate(
- SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
- SPINEL_CMD_PROP_VALUE_IS,
- streamPropKey,
- aDataPtr,
- static_cast(aDataLen)
- );
+ SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, streamPropKey));
+ SuccessOrExit(error = mEncoder.WriteData(aDataPtr, static_cast(aDataLen)));
+ SuccessOrExit(error = mEncoder.EndFrame());
- if (error != OT_ERROR_NONE)
+exit:
+
+ if (error == OT_ERROR_NO_BUFS)
{
mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
mUpdateChangedPropsTask.Post();
}
-exit:
return error;
}
@@ -881,46 +832,32 @@ void NcpBase::HandleRawFrame(const otRadioFrame *aFrame)
goto exit;
}
- 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,
- aFrame->mLength
- ));
+ SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW));
+ SuccessOrExit(mEncoder.WriteUint16(aFrame->mLength));
// 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_NULL_S // Empty for now
- )
- SPINEL_DATATYPE_STRUCT_S( // Vendor-data
- SPINEL_DATATYPE_NULL_S // Empty for now
- ),
- aFrame->mPower, // TX Power
- -128, // Noise Floor (Currently unused)
- flags // Flags
+ SuccessOrExit(mEncoder.WriteInt8(aFrame->mPower)); // TX Power
+ SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise floor (Currently unused)
+ SuccessOrExit(mEncoder.WriteUint16(flags)); // Flags
- // Skip PHY and Vendor data for now
- ));
+ SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
+ // Empty for now
+ SuccessOrExit(mEncoder.CloseStruct());
- SuccessOrExit(OutboundFrameSend());
+ SuccessOrExit(mEncoder.OpenStruct()); // Vendor-data
+ // Empty for now
+ SuccessOrExit(mEncoder.CloseStruct());
+
+ SuccessOrExit(mEncoder.EndFrame());
exit:
return;
@@ -1033,25 +970,34 @@ exit:
otError NcpBase::HandleCommandPropertyGet(uint8_t aHeader, spinel_prop_key_t aKey)
{
unsigned i;
+ bool found = false;
otError error = OT_ERROR_NONE;
for (i = 0; i < sizeof(mGetPropertyHandlerTable) / sizeof(mGetPropertyHandlerTable[0]); i++)
{
if (mGetPropertyHandlerTable[i].mPropKey == aKey)
{
+ found = true;
break;
}
}
- if (i < sizeof(mGetPropertyHandlerTable) / sizeof(mGetPropertyHandlerTable[0]))
+ mDisableStreamWrite = true;
+ SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, aKey));
+
+ if (found)
{
- error = (this->*mGetPropertyHandlerTable[i].mHandler)(aHeader, aKey);
+ SuccessOrExit(error = (this->*mGetPropertyHandlerTable[i].mHandler)());
}
else
{
- error = SendLastStatus(aHeader, SPINEL_STATUS_PROP_NOT_FOUND);
+ SuccessOrExit(error = mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_PROP_NOT_FOUND));
}
+ SuccessOrExit(error = mEncoder.EndFrame());
+
+exit:
+ mDisableStreamWrite = false;
return error;
}
@@ -1086,6 +1032,7 @@ otError NcpBase::HandleCommandPropertyInsert(uint8_t aHeader, spinel_prop_key_t
{
unsigned i;
otError error = OT_ERROR_NONE;
+ spinel_status_t spinelError = SPINEL_STATUS_PROP_NOT_FOUND;
for (i = 0; i < sizeof(mInsertPropertyHandlerTable) / sizeof(mInsertPropertyHandlerTable[0]); i++)
{
@@ -1097,13 +1044,22 @@ otError NcpBase::HandleCommandPropertyInsert(uint8_t aHeader, spinel_prop_key_t
if (i < sizeof(mInsertPropertyHandlerTable) / sizeof(mInsertPropertyHandlerTable[0]))
{
- error = (this->*mInsertPropertyHandlerTable[i].mHandler)(aHeader, aKey, aValuePtr, aValueLen);
+ spinelError = ThreadErrorToSpinelStatus(
+ (this->*mInsertPropertyHandlerTable[i].mHandler)(aValuePtr, aValueLen));
+ }
+
+ if (spinelError == SPINEL_STATUS_OK)
+ {
+ SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_INSERTED, aKey));
+ SuccessOrExit(error = mEncoder.WriteData(aValuePtr, aValueLen));
+ SuccessOrExit(error = mEncoder.EndFrame());
}
else
{
- error = SendLastStatus(aHeader, SPINEL_STATUS_PROP_NOT_FOUND);
+ SuccessOrExit(error = SendLastStatus(aHeader, spinelError));
}
+exit:
return error;
}
@@ -1112,6 +1068,7 @@ otError NcpBase::HandleCommandPropertyRemove(uint8_t aHeader, spinel_prop_key_t
{
unsigned i;
otError error = OT_ERROR_NONE;
+ spinel_status_t spinelError = SPINEL_STATUS_PROP_NOT_FOUND;
for (i = 0; i < sizeof(mRemovePropertyHandlerTable) / sizeof(mRemovePropertyHandlerTable[0]); i++)
{
@@ -1123,92 +1080,43 @@ otError NcpBase::HandleCommandPropertyRemove(uint8_t aHeader, spinel_prop_key_t
if (i < sizeof(mRemovePropertyHandlerTable) / sizeof(mRemovePropertyHandlerTable[0]))
{
- error = (this->*mRemovePropertyHandlerTable[i].mHandler)(aHeader, aKey, aValuePtr, aValueLen);
+ spinelError = ThreadErrorToSpinelStatus(
+ (this->*mRemovePropertyHandlerTable[i].mHandler)(aValuePtr, aValueLen));
+ }
+
+ if (spinelError == SPINEL_STATUS_OK)
+ {
+ SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_REMOVED, aKey));
+ SuccessOrExit(error = mEncoder.WriteData(aValuePtr, aValueLen));
+ SuccessOrExit(error = mEncoder.EndFrame());
}
else
{
- error = SendLastStatus(aHeader, SPINEL_STATUS_PROP_NOT_FOUND);
+ SuccessOrExit(error = SendLastStatus(aHeader, spinelError));
}
+exit:
return error;
}
-
// ----------------------------------------------------------------------------
-// MARK: Outbound Command Handlers
+// MARK: Outbound Frame Methods
// ----------------------------------------------------------------------------
otError NcpBase::SendLastStatus(uint8_t aHeader, spinel_status_t aLastStatus)
{
+ otError error = OT_ERROR_NONE;
+
if (SPINEL_HEADER_GET_IID(aHeader) == 0)
{
mLastStatus = aLastStatus;
}
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- SPINEL_PROP_LAST_STATUS,
- SPINEL_DATATYPE_UINT_PACKED_S,
- aLastStatus
- );
-}
-
-otError NcpBase::SendPropertyUpdate(uint8_t aHeader, uint8_t aCommand, spinel_prop_key_t aKey,
- const char *aPackFormat, ...)
-{
- otError error = OT_ERROR_NONE;
- va_list args;
-
- va_start(args, aPackFormat);
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_COMMAND_PROP_S, aHeader, aCommand, aKey));
- SuccessOrExit(error = OutboundFrameFeedVPacked(aPackFormat, args));
- SuccessOrExit(error = OutboundFrameSend());
+ SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_LAST_STATUS));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(aLastStatus));
+ SuccessOrExit(error = mEncoder.EndFrame());
exit:
- va_end(args);
- return error;
-}
-
-otError NcpBase::SendPropertyUpdate(uint8_t aHeader, uint8_t aCommand, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
-{
- otError error = OT_ERROR_NONE;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_COMMAND_PROP_S, aHeader, aCommand, aKey));
- SuccessOrExit(error = OutboundFrameFeedData(aValuePtr, aValueLen));
- SuccessOrExit(error = OutboundFrameSend());
-
-exit:
- return error;
-}
-
-otError NcpBase::SendPropertyUpdate(uint8_t aHeader, uint8_t aCommand, spinel_prop_key_t aKey, otMessage *aMessage)
-{
- otError error = OT_ERROR_NONE;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_COMMAND_PROP_S, aHeader, aCommand, aKey));
- SuccessOrExit(error = OutboundFrameFeedMessage(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
- // successfully sent and then removed, or if the frame gets
- // discarded.
- aMessage = NULL;
-
- SuccessOrExit(error = OutboundFrameSend());
-
-exit:
-
- if (aMessage != NULL)
- {
- otMessageFree(aMessage);
- }
-
return error;
}
@@ -1226,34 +1134,6 @@ otError NcpBase::SendSetPropertyResponse(uint8_t aHeader, spinel_prop_key_t aKey
return aError;
}
-otError NcpBase::OutboundFrameFeedVPacked(const char *aPackFormat, va_list aArgs)
-{
- uint8_t buf[96];
- otError error = OT_ERROR_NO_BUFS;
- spinel_ssize_t packedLen;
-
- packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, aArgs);
-
- if ((packedLen > 0) && (packedLen <= static_cast(sizeof(buf))))
- {
- error = OutboundFrameFeedData(buf, static_cast(packedLen));
- }
-
- return error;
-}
-
-otError NcpBase::OutboundFrameFeedPacked(const char *aPackFormat, ...)
-{
- otError error;
- va_list args;
-
- va_start(args, aPackFormat);
- error = OutboundFrameFeedVPacked(aPackFormat, args);
- va_end(args);
-
- return error;
-}
-
// ----------------------------------------------------------------------------
// MARK: Individual Command Handlers
// ----------------------------------------------------------------------------
@@ -1466,21 +1346,11 @@ otError NcpBase::CommandHandler_PEEK(uint8_t aHeader, unsigned int aCommand, con
VerifyOrExit(mAllowPeekDelegate(address, count), spinelError = SPINEL_STATUS_INVALID_ARGUMENT);
}
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- (
- SPINEL_DATATYPE_COMMAND_S // Header and Command
- SPINEL_DATATYPE_UINT32_S // Address
- SPINEL_DATATYPE_UINT16_S // Count
- ),
- aHeader,
- SPINEL_CMD_PEEK_RET,
- address,
- count
- ));
- SuccessOrExit(error = OutboundFrameFeedData(reinterpret_cast(address), count));
- SuccessOrExit(error = OutboundFrameSend());
+ SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PEEK_RET));
+ SuccessOrExit(error = mEncoder.WriteUint32(address));
+ SuccessOrExit(error = mEncoder.WriteUint16(count));
+ SuccessOrExit(error = mEncoder.WriteData(reinterpret_cast(address), count));
+ SuccessOrExit(error = mEncoder.EndFrame());
exit:
if (spinelError != SPINEL_STATUS_OK)
@@ -1544,30 +1414,18 @@ exit:
// MARK: Individual Property Getters and Setters
// ----------------------------------------------------------------------------
-otError NcpBase::GetPropertyHandler_PHY_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_PHY_ENABLED(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
#if OPENTHREAD_ENABLE_RAW_LINK_API
- otLinkRawIsEnabled(mInstance)
+ return mEncoder.WriteBool(otLinkRawIsEnabled(mInstance));
#else
- false
-#endif // OPENTHREAD_ENABLE_RAW_LINK_API
- );
+ return mEncoder.WriteBool(false);
+#endif
}
-otError NcpBase::GetPropertyHandler_PHY_CHAN(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_PHY_CHAN(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- otLinkGetChannel(mInstance)
- );
+ return mEncoder.WriteUint8(otLinkGetChannel(mInstance));
}
otError NcpBase::SetPropertyHandler_PHY_CHAN(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -1612,17 +1470,12 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_MAC_PROMISCUOUS_MODE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_PROMISCUOUS_MODE(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_INT8_S,
- otPlatRadioGetPromiscuous(mInstance)
- ? SPINEL_MAC_PROMISCUOUS_MODE_FULL
- : SPINEL_MAC_PROMISCUOUS_MODE_OFF
- );
+ return mEncoder.WriteUint8(otPlatRadioGetPromiscuous(mInstance)
+ ? SPINEL_MAC_PROMISCUOUS_MODE_FULL
+ : SPINEL_MAC_PROMISCUOUS_MODE_OFF
+ );
}
otError NcpBase::SetPropertyHandler_MAC_PROMISCUOUS_MODE(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -1661,15 +1514,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_MAC_15_4_PANID(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_15_4_PANID(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT16_S,
- otLinkGetPanId(mInstance)
- );
+ return mEncoder.WriteUint16(otLinkGetPanId(mInstance));
}
otError NcpBase::SetPropertyHandler_MAC_15_4_PANID(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -1694,15 +1541,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_MAC_15_4_LADDR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_15_4_LADDR(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_EUI64_S,
- otLinkGetExtendedAddress(mInstance)
- );
+ return mEncoder.WriteEui64(*otLinkGetExtendedAddress(mInstance));
}
otError NcpBase::SetPropertyHandler_MAC_15_4_LADDR(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -1727,26 +1568,14 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_MAC_15_4_SADDR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_15_4_SADDR(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT16_S,
- otLinkGetShortAddress(mInstance)
- );
+ return mEncoder.WriteUint16(otLinkGetShortAddress(mInstance));
}
-otError NcpBase::GetPropertyHandler_MAC_RAW_STREAM_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_RAW_STREAM_ENABLED(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- mIsRawStreamEnabled
- );
+ return mEncoder.WriteBool(mIsRawStreamEnabled);
}
otError NcpBase::SetPropertyHandler_MAC_RAW_STREAM_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -1787,33 +1616,22 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_UNSOL_UPDATE_FILTER(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_UNSOL_UPDATE_FILTER(void)
{
otError error = OT_ERROR_NONE;
uint8_t numEntries;
const ChangedPropsSet::Entry *entry;
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
entry = mChangedPropsSet.GetSupportedEntries(numEntries);
for (uint8_t index = 0; index < numEntries; index++, entry++)
{
if (mChangedPropsSet.IsEntryFiltered(index))
{
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, entry->mPropKey));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(entry->mPropKey));
}
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
return error;
}
@@ -1863,12 +1681,10 @@ exit:
return error;
}
-otError NcpBase::InsertPropertyHandler_UNSOL_UPDATE_FILTER(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::InsertPropertyHandler_UNSOL_UPDATE_FILTER(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
unsigned int propKey;
parsedLength = spinel_datatype_unpack(
@@ -1878,35 +1694,18 @@ otError NcpBase::InsertPropertyHandler_UNSOL_UPDATE_FILTER(uint8_t aHeader, spin
&propKey
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = mChangedPropsSet.EnablePropertyFilter(static_cast(propKey), true);
- 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::RemovePropertyHandler_UNSOL_UPDATE_FILTER(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_UNSOL_UPDATE_FILTER(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
unsigned int propKey;
parsedLength = spinel_datatype_unpack(
@@ -1916,169 +1715,106 @@ otError NcpBase::RemovePropertyHandler_UNSOL_UPDATE_FILTER(uint8_t aHeader, spin
&propKey
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = mChangedPropsSet.EnablePropertyFilter(static_cast(propKey), false);
- 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::GetPropertyHandler_LAST_STATUS(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_LAST_STATUS(void)
{
- return SendPropertyUpdate(aHeader, SPINEL_CMD_PROP_VALUE_IS, aKey, SPINEL_DATATYPE_UINT_PACKED_S, mLastStatus);
+ return mEncoder.WriteUintPacked(mLastStatus);
}
-otError NcpBase::GetPropertyHandler_PROTOCOL_VERSION(uint8_t aHeader, spinel_prop_key_t aKey)
-{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- (
- SPINEL_DATATYPE_UINT_PACKED_S // Major
- SPINEL_DATATYPE_UINT_PACKED_S // Minor
- ),
- SPINEL_PROTOCOL_VERSION_THREAD_MAJOR,
- SPINEL_PROTOCOL_VERSION_THREAD_MINOR
- );
-}
-
-otError NcpBase::GetPropertyHandler_INTERFACE_TYPE(uint8_t aHeader, spinel_prop_key_t aKey)
-{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT_PACKED_S,
- SPINEL_PROTOCOL_TYPE_THREAD
- );
-}
-
-otError NcpBase::GetPropertyHandler_VENDOR_ID(uint8_t aHeader, spinel_prop_key_t aKey)
-{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT_PACKED_S,
- 0 // Vendor ID. Zero for unknown.
- );
-}
-
-otError NcpBase::GetPropertyHandler_CAPS(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_PROTOCOL_VERSION(void)
{
otError error = OT_ERROR_NONE;
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROTOCOL_VERSION_THREAD_MAJOR));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROTOCOL_VERSION_THREAD_MINOR));
- // Begin adding capabilities //////////////////////////////////////////////
+exit:
+ return error;
+}
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_COUNTERS));
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_UNSOL_UPDATE_FILTER));
+otError NcpBase::GetPropertyHandler_INTERFACE_TYPE(void)
+{
+ return mEncoder.WriteUintPacked(SPINEL_PROTOCOL_TYPE_THREAD);
+}
+
+otError NcpBase::GetPropertyHandler_VENDOR_ID(void)
+{
+ return mEncoder.WriteUintPacked(0); // Vendor ID. Zero for unknown.
+}
+
+otError NcpBase::GetPropertyHandler_CAPS(void)
+{
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_COUNTERS));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_UNSOL_UPDATE_FILTER));
#if OPENTHREAD_ENABLE_RAW_LINK_API
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_MAC_RAW));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MAC_RAW));
#endif
#if OPENTHREAD_MTD || OPENTHREAD_FTD
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_NET_THREAD_1_0));
+
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_NET_THREAD_1_0));
#if OPENTHREAD_ENABLE_MAC_FILTER
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_MAC_WHITELIST));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MAC_WHITELIST));
#endif
#if OPENTHREAD_ENABLE_JAM_DETECTION
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_JAM_DETECT));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_JAM_DETECT));
#endif
#if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_OOB_STEERING_DATA));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_OOB_STEERING_DATA));
#endif
#if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_PEEK_POKE));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_PEEK_POKE));
#endif
// TODO: Somehow get the following capability from the radio.
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_802_15_4_2450MHZ_OQPSK));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_802_15_4_2450MHZ_OQPSK));
#if OPENTHREAD_CONFIG_MAX_CHILDREN > 0
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_ROLE_ROUTER));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_ROLE_ROUTER));
#endif
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_ROLE_SLEEPY));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_ROLE_SLEEPY));
#if OPENTHREAD_ENABLE_LEGACY
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_NEST_LEGACY_INTERFACE));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_NEST_LEGACY_INTERFACE));
#endif
#if OPENTHREAD_ENABLE_TMF_PROXY
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_THREAD_TMF_PROXY));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_TMF_PROXY));
#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
- // End adding capabilities /////////////////////////////////////////////////
-
- SuccessOrExit(error = OutboundFrameSend());
exit:
return error;
}
-otError NcpBase::GetPropertyHandler_NCP_VERSION(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NCP_VERSION(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UTF8_S,
- otGetVersionString()
- );
+ return mEncoder.WriteUtf8(otGetVersionString());
}
-otError NcpBase::GetPropertyHandler_INTERFACE_COUNT(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_INTERFACE_COUNT(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- 1 // Only one interface for now
- );
+ return mEncoder.WriteUint8(1); // Only one interface for now
}
-otError NcpBase::GetPropertyHandler_POWER_STATE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_POWER_STATE(void)
{
- // Always online at the moment
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- SPINEL_POWER_STATE_ONLINE
- );
+ return mEncoder.WriteUint8(SPINEL_POWER_STATE_ONLINE); // Always online at the moment
}
otError NcpBase::SetPropertyHandler_POWER_STATE(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -2092,37 +1828,23 @@ otError NcpBase::SetPropertyHandler_POWER_STATE(uint8_t aHeader, spinel_prop_key
return SendLastStatus(aHeader, SPINEL_STATUS_UNIMPLEMENTED);
}
-otError NcpBase::GetPropertyHandler_HWADDR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_HWADDR(void)
{
otExtAddress hwAddr;
- otPlatRadioGetIeeeEui64(mInstance, hwAddr.m8);
+ otLinkGetFactoryAssignedIeeeEui64(mInstance, &hwAddr);
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_EUI64_S,
- hwAddr.m8
- );
+ return mEncoder.WriteEui64(hwAddr);
}
-otError NcpBase::GetPropertyHandler_LOCK(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_LOCK(void)
{
// TODO: Implement property lock (Needs API!)
- OT_UNUSED_VARIABLE(aKey);
-
- return SendLastStatus(aHeader, SPINEL_STATUS_UNIMPLEMENTED);
+ return mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_UNIMPLEMENTED);
}
-otError NcpBase::GetPropertyHandler_HOST_POWER_STATE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_HOST_POWER_STATE(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- mHostPowerState
- );
+ return mEncoder.WriteUint8(mHostPowerState);
}
otError NcpBase::SetPropertyHandler_HOST_POWER_STATE(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -2206,57 +1928,34 @@ otError NcpBase::SetPropertyHandler_HOST_POWER_STATE(uint8_t aHeader, spinel_pro
return error;
}
-otError NcpBase::GetPropertyHandler_UNSOL_UPDATE_LIST(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_UNSOL_UPDATE_LIST(void)
{
otError error = OT_ERROR_NONE;
uint8_t numEntries;
const ChangedPropsSet::Entry *entry;
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
entry = mChangedPropsSet.GetSupportedEntries(numEntries);
for (uint8_t index = 0; index < numEntries; index++, entry++)
{
if (entry->mFilterable)
{
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, entry->mPropKey));
+ SuccessOrExit(error = mEncoder.WriteUintPacked(entry->mPropKey));
}
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
return error;
}
-otError NcpBase::GetPropertyHandler_PHY_RX_SENSITIVITY(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_PHY_RX_SENSITIVITY(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_INT8_S,
- otPlatRadioGetReceiveSensitivity(mInstance)
- );
+ return mEncoder.WriteInt8(otPlatRadioGetReceiveSensitivity(mInstance));
}
-otError NcpBase::GetPropertyHandler_PHY_TX_POWER(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_PHY_TX_POWER(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_INT8_S,
- otLinkGetMaxTransmitPower(mInstance)
- );
+ return mEncoder.WriteInt8(otLinkGetMaxTransmitPower(mInstance));
}
otError NcpBase::SetPropertyHandler_PHY_TX_POWER(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -2281,7 +1980,7 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_DEBUG_TEST_ASSERT(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_DEBUG_TEST_ASSERT(void)
{
assert(false);
@@ -2291,17 +1990,11 @@ otError NcpBase::GetPropertyHandler_DEBUG_TEST_ASSERT(uint8_t aHeader, spinel_pr
// property value to indicate this.
OT_UNREACHABLE_CODE(
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- false
- );
+ return mEncoder.WriteBool(false);
)
}
-otError NcpBase::GetPropertyHandler_DEBUG_NCP_LOG_LEVEL(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_DEBUG_NCP_LOG_LEVEL(void)
{
uint8_t logLevel = 0;
@@ -2328,13 +2021,7 @@ otError NcpBase::GetPropertyHandler_DEBUG_NCP_LOG_LEVEL(uint8_t aHeader, spinel_
break;
}
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- logLevel
- );
+ return mEncoder.WriteUint8(logLevel);
}
otError NcpBase::SetPropertyHandler_DEBUG_NCP_LOG_LEVEL(uint8_t aHeader, spinel_prop_key_t aKey,
diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp
index ea9342101..6a641d096 100644
--- a/src/ncp/ncp_base.hpp
+++ b/src/ncp/ncp_base.hpp
@@ -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:
diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp
index 50835955b..193a6f0e5 100644
--- a/src/ncp/ncp_base_ftd.cpp
+++ b/src/ncp/ncp_base_ftd.cpp
@@ -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:
diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp
index ffe98dac5..c240a27df 100644
--- a/src/ncp/ncp_base_mtd.cpp
+++ b/src/ncp/ncp_base_mtd.cpp
@@ -172,15 +172,9 @@ uint8_t NcpBase::LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aSecureDataRequest
return flags;
}
-otError NcpBase::GetPropertyHandler_MAC_DATA_POLL_PERIOD(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_DATA_POLL_PERIOD(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- otLinkGetPollPeriod(mInstance)
- );
+ return mEncoder.WriteUint32(otLinkGetPollPeriod(mInstance));
}
otError NcpBase::SetPropertyHandler_MAC_DATA_POLL_PERIOD(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -205,19 +199,12 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-
-otError NcpBase::GetPropertyHandler_MAC_EXTENDED_ADDR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_EXTENDED_ADDR(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_EUI64_S,
- otLinkGetExtendedAddress(mInstance)
- );
+ return mEncoder.WriteEui64(*otLinkGetExtendedAddress(mInstance));
}
-otError NcpBase::GetPropertyHandler_PHY_FREQ(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_PHY_FREQ(void)
{
uint32_t freq_khz(0);
const uint8_t chan(otLinkGetChannel(mInstance));
@@ -235,29 +222,17 @@ otError NcpBase::GetPropertyHandler_PHY_FREQ(uint8_t aHeader, spinel_prop_key_t
freq_khz = 2405000 - (5000 * 11) + 5000 * (chan);
}
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- freq_khz
- );
+ return mEncoder.WriteUint32(freq_khz);
}
-otError NcpBase::GetPropertyHandler_PHY_CHAN_SUPPORTED(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_PHY_CHAN_SUPPORTED(void)
{
- return GetPropertyHandler_ChannelMaskHelper(aHeader, aKey, mSupportedChannelMask);
+ return GetPropertyHandler_ChannelMaskHelper(mSupportedChannelMask);
}
-otError NcpBase::GetPropertyHandler_PHY_RSSI(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_PHY_RSSI(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_INT8_S,
- otPlatRadioGetRssi(mInstance)
- );
+ return mEncoder.WriteInt8(otPlatRadioGetRssi(mInstance));
}
otError NcpBase::CommandHandler_NET_SAVE(uint8_t aHeader, unsigned int aCommand, const uint8_t *aArgPtr,
@@ -290,26 +265,14 @@ otError NcpBase::CommandHandler_NET_RECALL(uint8_t aHeader, unsigned int aComman
return SendLastStatus(aHeader, SPINEL_STATUS_UNIMPLEMENTED);
}
-otError NcpBase::GetPropertyHandler_NET_SAVED(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_SAVED(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- otDatasetIsCommissioned(mInstance)
- );
+ return mEncoder.WriteBool(otDatasetIsCommissioned(mInstance));
}
-otError NcpBase::GetPropertyHandler_NET_IF_UP(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_IF_UP(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- otIp6IsEnabled(mInstance)
- );
+ return mEncoder.WriteBool(otIp6IsEnabled(mInstance));
}
otError NcpBase::SetPropertyHandler_NET_IF_UP(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -334,15 +297,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_NET_STACK_UP(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_STACK_UP(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED
- );
+ return mEncoder.WriteBool(otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED);
}
otError NcpBase::SetPropertyHandler_NET_STACK_UP(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -396,7 +353,7 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_NET_ROLE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_ROLE(void)
{
spinel_net_role_t role(SPINEL_NET_ROLE_DETACHED);
@@ -420,13 +377,7 @@ otError NcpBase::GetPropertyHandler_NET_ROLE(uint8_t aHeader, spinel_prop_key_t
break;
}
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- role
- );
+ return mEncoder.WriteUint8(role);
}
otError NcpBase::SetPropertyHandler_NET_ROLE(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -471,15 +422,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_NET_NETWORK_NAME(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_NETWORK_NAME(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UTF8_S,
- otThreadGetNetworkName(mInstance)
- );
+ return mEncoder.WriteUtf8(otThreadGetNetworkName(mInstance));
}
otError NcpBase::SetPropertyHandler_NET_NETWORK_NAME(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -504,16 +449,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_NET_XPANID(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_XPANID(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_DATA_S,
- otThreadGetExtendedPanId(mInstance),
- sizeof(spinel_net_xpanid_t)
- );
+ return mEncoder.WriteData(otThreadGetExtendedPanId(mInstance), sizeof(spinel_net_xpanid_t));
}
otError NcpBase::SetPropertyHandler_NET_XPANID(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -540,16 +478,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_NET_MASTER_KEY(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_MASTER_KEY(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_DATA_S,
- otThreadGetMasterKey(mInstance)->m8,
- OT_MASTER_KEY_SIZE
- );
+ return mEncoder.WriteData(otThreadGetMasterKey(mInstance)->m8, OT_MASTER_KEY_SIZE);
}
otError NcpBase::SetPropertyHandler_NET_MASTER_KEY(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -576,15 +507,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_NET_KEY_SEQUENCE_COUNTER(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_KEY_SEQUENCE_COUNTER(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- otThreadGetKeySequenceCounter(mInstance)
- );
+ return mEncoder.WriteUint32(otThreadGetKeySequenceCounter(mInstance));
}
otError NcpBase::SetPropertyHandler_NET_KEY_SEQUENCE_COUNTER(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -609,26 +534,14 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_NET_PARTITION_ID(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_PARTITION_ID(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- otThreadGetPartitionId(mInstance)
- );
+ return mEncoder.WriteUint32(otThreadGetPartitionId(mInstance));
}
-otError NcpBase::GetPropertyHandler_NET_KEY_SWITCH_GUARDTIME(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_KEY_SWITCH_GUARDTIME(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- otThreadGetKeySwitchGuardTime(mInstance)
- );
+ return mEncoder.WriteUint32(otThreadGetKeySwitchGuardTime(mInstance));
}
otError NcpBase::SetPropertyHandler_NET_KEY_SWITCH_GUARDTIME(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -653,32 +566,19 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA_VERSION(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA_VERSION(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- otNetDataGetVersion(mInstance)
- );
+ return mEncoder.WriteUint8(otNetDataGetVersion(mInstance));
}
-otError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA_VERSION(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- otNetDataGetStableVersion(mInstance)
- );
+ return mEncoder.WriteUint8(otNetDataGetStableVersion(mInstance));
}
#if OPENTHREAD_ENABLE_BORDER_ROUTER
-otError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA(void)
{
- otError error = OT_ERROR_NONE;
uint8_t networkData[255];
uint8_t networkDataLen = 255;
@@ -689,24 +589,11 @@ otError NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA(uint8_t aHeader, spinel_
&networkDataLen
);
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
- SuccessOrExit(error = OutboundFrameFeedData(networkData, networkDataLen));
- SuccessOrExit(error = OutboundFrameSend());
-
-exit:
- return error;
+ return mEncoder.WriteData(networkData, networkDataLen);
}
-otError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(void)
{
- otError error = OT_ERROR_NONE;
uint8_t networkData[255];
uint8_t networkDataLen = 255;
@@ -717,25 +604,12 @@ otError NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(uint8_t aHeader,
&networkDataLen
);
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
- SuccessOrExit(error = OutboundFrameFeedData(networkData, networkDataLen));
- SuccessOrExit(error = OutboundFrameSend());
-
-exit:
- return error;
+ return mEncoder.WriteData(networkData, networkDataLen);
}
#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
-otError NcpBase::GetPropertyHandler_THREAD_LEADER_NETWORK_DATA(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_LEADER_NETWORK_DATA(void)
{
- otError error = OT_ERROR_NONE;
uint8_t networkData[255];
uint8_t networkDataLen = 255;
@@ -746,24 +620,11 @@ otError NcpBase::GetPropertyHandler_THREAD_LEADER_NETWORK_DATA(uint8_t aHeader,
&networkDataLen
);
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
- SuccessOrExit(error = OutboundFrameFeedData(networkData, networkDataLen));
- SuccessOrExit(error = OutboundFrameSend());
-
-exit:
- return error;
+ return mEncoder.WriteData(networkData, networkDataLen);
}
-otError NcpBase::GetPropertyHandler_THREAD_STABLE_LEADER_NETWORK_DATA(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_STABLE_LEADER_NETWORK_DATA(void)
{
- otError error = OT_ERROR_NONE;
uint8_t networkData[255];
uint8_t networkDataLen = 255;
@@ -774,35 +635,15 @@ otError NcpBase::GetPropertyHandler_THREAD_STABLE_LEADER_NETWORK_DATA(uint8_t aH
&networkDataLen
);
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
- SuccessOrExit(error = OutboundFrameFeedData(networkData, networkDataLen));
- SuccessOrExit(error = OutboundFrameSend());
-
-exit:
- return error;
+ return mEncoder.WriteData(networkData, networkDataLen);
}
-otError NcpBase::GetPropertyHandler_THREAD_LEADER_RID(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_LEADER_RID(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- otThreadGetLeaderRouterId(mInstance)
- );
+ return mEncoder.WriteUint8(otThreadGetLeaderRouterId(mInstance));
}
-
-
-otError NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(void)
{
otError error = OT_ERROR_NONE;
otIp6Address address;
@@ -811,69 +652,45 @@ otError NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t aHeader, spinel_p
if (error == OT_ERROR_NONE)
{
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_IPv6ADDR_S,
- &address
- );
+ error = mEncoder.WriteIp6Address(address);
}
else
{
- error = SendLastStatus(aHeader, ThreadErrorToSpinelStatus(error));
+ error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
}
return error;
}
-otError NcpBase::GetPropertyHandler_THREAD_PARENT(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_PARENT(void)
{
otError error = OT_ERROR_NONE;
+
otRouterInfo parentInfo;
error = otThreadGetParentInfo(mInstance, &parentInfo);
if (error == OT_ERROR_NONE)
{
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- (
- SPINEL_DATATYPE_EUI64_S // Parent's extended address
- SPINEL_DATATYPE_UINT16_S // Parent's rloc16
- ),
- parentInfo.mExtAddress.m8,
- parentInfo.mRloc16
- );
+ SuccessOrExit(error = mEncoder.WriteEui64(parentInfo.mExtAddress)); // Parent's extended address
+ SuccessOrExit(error = mEncoder.WriteUint16(parentInfo.mRloc16));
}
else
{
- error = SendLastStatus(aHeader, ThreadErrorToSpinelStatus(error));
+ error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
}
+exit:
return error;
}
-otError NcpBase::GetPropertyHandler_THREAD_NEIGHBOR_TABLE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_NEIGHBOR_TABLE(void)
{
otError error = OT_ERROR_NONE;
otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
otNeighborInfo neighInfo;
uint8_t modeFlags;
- mDisableStreamWrite = true;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighInfo) == OT_ERROR_NONE)
{
modeFlags = LinkFlagsToFlagByte(
@@ -883,62 +700,37 @@ otError NcpBase::GetPropertyHandler_THREAD_NEIGHBOR_TABLE(uint8_t aHeader, spine
neighInfo.mFullNetworkData
);
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_EUI64_S // EUI64 Address
- SPINEL_DATATYPE_UINT16_S // Rloc16
- SPINEL_DATATYPE_UINT32_S // Age
- SPINEL_DATATYPE_UINT8_S // Link Quality In
- SPINEL_DATATYPE_INT8_S // Average RSS
- SPINEL_DATATYPE_UINT8_S // Mode (flags)
- SPINEL_DATATYPE_BOOL_S // Is Child
- SPINEL_DATATYPE_UINT32_S // Link Frame Counter
- SPINEL_DATATYPE_UINT32_S // MLE Frame Counter
- SPINEL_DATATYPE_INT8_S // Most recent RSS
- ),
- neighInfo.mExtAddress.m8,
- neighInfo.mRloc16,
- neighInfo.mAge,
- neighInfo.mLinkQualityIn,
- neighInfo.mAverageRssi,
- modeFlags,
- neighInfo.mIsChild,
- neighInfo.mLinkFrameCounter,
- neighInfo.mMleFrameCounter,
- neighInfo.mLastRssi
- ));
+ SuccessOrExit(error = mEncoder.OpenStruct());
+
+ SuccessOrExit(error = mEncoder.WriteEui64(neighInfo.mExtAddress));
+ SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mRloc16));
+ SuccessOrExit(error = mEncoder.WriteUint32(neighInfo.mAge));
+ SuccessOrExit(error = mEncoder.WriteUint8(neighInfo.mLinkQualityIn));
+ SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mAverageRssi));
+ SuccessOrExit(error = mEncoder.WriteUint8(modeFlags));
+ SuccessOrExit(error = mEncoder.WriteBool(neighInfo.mIsChild));
+ SuccessOrExit(error = mEncoder.WriteUint32(neighInfo.mLinkFrameCounter));
+ SuccessOrExit(error = mEncoder.WriteUint32(neighInfo.mMleFrameCounter));
+ SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mLastRssi));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
- mDisableStreamWrite = false;
return error;
}
-otError NcpBase::GetPropertyHandler_THREAD_ASSISTING_PORTS(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_ASSISTING_PORTS(void)
{
otError error = OT_ERROR_NONE;
uint8_t numEntries = 0;
const uint16_t *ports = otIp6GetUnsecurePorts(mInstance, &numEntries);
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
for (; numEntries != 0; ports++, numEntries--)
{
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT16_S, *ports));
+ SuccessOrExit(error = mEncoder.WriteUint16(*ports));
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
return error;
}
@@ -999,15 +791,9 @@ exit:
return error;
}
-otError NcpBase::GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- mAllowLocalNetworkDataChange
- );
+ return mEncoder.WriteBool(mAllowLocalNetworkDataChange);
}
#if OPENTHREAD_ENABLE_BORDER_ROUTER
@@ -1045,46 +831,25 @@ exit:
}
#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
-otError NcpBase::GetPropertyHandler_THREAD_ON_MESH_NETS(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_ON_MESH_NETS(void)
{
otError error = OT_ERROR_NONE;
otBorderRouterConfig borderRouterConfig;
otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT;
- uint8_t flags;
-
- mDisableStreamWrite = true;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
// Fill from non-local network data first
while (otNetDataGetNextOnMeshPrefix(mInstance, &iter, &borderRouterConfig) == OT_ERROR_NONE)
{
- flags = BorderRouterConfigToFlagByte(borderRouterConfig);
+ SuccessOrExit(error = mEncoder.OpenStruct());
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_IPv6ADDR_S // IPv6 Prefix
- SPINEL_DATATYPE_UINT8_S // Prefix Length (in bits)
- SPINEL_DATATYPE_BOOL_S // isStable
- SPINEL_DATATYPE_UINT8_S // Flags
- SPINEL_DATATYPE_BOOL_S // isLocal
- SPINEL_DATATYPE_UINT16_S // RLOC16
- ),
- &borderRouterConfig.mPrefix,
- 64,
- borderRouterConfig.mStable,
- flags,
- false,
- borderRouterConfig.mRloc16
- ));
+ SuccessOrExit(error = mEncoder.WriteIp6Address(borderRouterConfig.mPrefix.mPrefix));
+ SuccessOrExit(error = mEncoder.WriteUint8(borderRouterConfig.mPrefix.mLength));
+ SuccessOrExit(error = mEncoder.WriteBool(borderRouterConfig.mStable));
+ SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
+ SuccessOrExit(error = mEncoder.WriteBool(false)); // isLocal
+ SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
#if OPENTHREAD_ENABLE_BORDER_ROUTER
@@ -1094,42 +859,28 @@ otError NcpBase::GetPropertyHandler_THREAD_ON_MESH_NETS(uint8_t aHeader, spinel_
// Fill from local network data last
while (otBorderRouterGetNextOnMeshPrefix(mInstance, &iter, &borderRouterConfig) == OT_ERROR_NONE)
{
- flags = BorderRouterConfigToFlagByte(borderRouterConfig);
+ SuccessOrExit(error = mEncoder.OpenStruct());
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_IPv6ADDR_S // IPv6 Prefix
- SPINEL_DATATYPE_UINT8_S // Prefix Length (in bits)
- SPINEL_DATATYPE_BOOL_S // isStable
- SPINEL_DATATYPE_UINT8_S // Flags
- SPINEL_DATATYPE_BOOL_S // isLocal
- SPINEL_DATATYPE_UINT16_S // RLOC16
- ),
- &borderRouterConfig.mPrefix,
- 64,
- borderRouterConfig.mStable,
- flags,
- true,
- borderRouterConfig.mRloc16
- ));
+ SuccessOrExit(error = mEncoder.WriteIp6Address(borderRouterConfig.mPrefix.mPrefix));
+ SuccessOrExit(error = mEncoder.WriteUint8(borderRouterConfig.mPrefix.mLength));
+ SuccessOrExit(error = mEncoder.WriteBool(borderRouterConfig.mStable));
+ SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
+ SuccessOrExit(error = mEncoder.WriteBool(true)); // isLocal
+ SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
- mDisableStreamWrite = false;
return error;
}
#if OPENTHREAD_ENABLE_BORDER_ROUTER
-otError NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
otBorderRouterConfig borderRouterConfig;
otIp6Address *addrPtr;
bool stable = false;
@@ -1137,7 +888,7 @@ otError NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t aHeader, spin
memset(&borderRouterConfig, 0, sizeof(otBorderRouterConfig));
- VerifyOrExit(mAllowLocalNetworkDataChange == true, spinelError = SPINEL_STATUS_INVALID_STATE);
+ VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
parsedLength = spinel_datatype_unpack(
aValuePtr,
@@ -1154,7 +905,7 @@ otError NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t aHeader, spin
&flags
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
borderRouterConfig.mPrefix.mPrefix = *addrPtr;
borderRouterConfig.mStable = stable;
@@ -1168,38 +919,21 @@ otError NcpBase::InsertPropertyHandler_THREAD_ON_MESH_NETS(uint8_t aHeader, spin
borderRouterConfig.mOnMesh = ((flags & SPINEL_NET_FLAG_ON_MESH) != 0);
error = otBorderRouterAddOnMeshPrefix(mInstance, &borderRouterConfig);
- 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::RemovePropertyHandler_THREAD_ON_MESH_NETS(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_THREAD_ON_MESH_NETS(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
otIp6Prefix ip6Prefix;
otIp6Address *addrPtr;
memset(&ip6Prefix, 0, sizeof(otIp6Prefix));
- VerifyOrExit(mAllowLocalNetworkDataChange == true, spinelError = SPINEL_STATUS_INVALID_STATE);
+ VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
parsedLength = spinel_datatype_unpack(
aValuePtr,
@@ -1212,46 +946,28 @@ otError NcpBase::RemovePropertyHandler_THREAD_ON_MESH_NETS(uint8_t aHeader, spin
&ip6Prefix.mLength
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
ip6Prefix.mPrefix = *addrPtr;
error = otBorderRouterRemoveOnMeshPrefix(mInstance, &ip6Prefix);
- // If prefix was not on the list, "remove" command is successful,
- // and we respond with a `SPINEL_STATUS_OK` status.
- VerifyOrExit(error != OT_ERROR_NOT_FOUND, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
+ // If prefix was not on the list, "remove" command can be considred
+ // successful.
- 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)
+ if (error == OT_ERROR_NOT_FOUND)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
-otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_JOINER_FLAG(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_JOINER_FLAG(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- mDiscoveryScanJoinerFlag
- );
+ return mEncoder.WriteBool(mDiscoveryScanJoinerFlag);
}
otError NcpBase::SetPropertyHandler_THREAD_DISCOVERY_SCAN_JOINER_FLAG(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -1276,15 +992,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- mDiscoveryScanEnableFiltering
- );
+ return mEncoder.WriteBool(mDiscoveryScanEnableFiltering);
}
otError NcpBase::SetPropertyHandler_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -1310,15 +1020,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_PANID(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_DISCOVERY_SCAN_PANID(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT16_S,
- mDiscoveryScanPanId
- );
+ return mEncoder.WriteUint16(mDiscoveryScanPanId);
}
otError NcpBase::SetPropertyHandler_THREAD_DISCOVERY_SCAN_PANID(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -1343,42 +1047,23 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(void)
{
otError error = OT_ERROR_NONE;
const uint8_t *mlPrefix = otThreadGetMeshLocalPrefix(mInstance);
+ otIp6Address addr;
- if (mlPrefix)
- {
- otIp6Address addr;
+ VerifyOrExit(mlPrefix != NULL); // If `mlPrefix` is NULL send empty response.
- memcpy(addr.mFields.m8, mlPrefix, 8);
+ memcpy(addr.mFields.m8, mlPrefix, 8);
- // Zero out the last 8 bytes.
- memset(addr.mFields.m8 + 8, 0, 8);
+ // Zero out the last 8 bytes.
+ memset(addr.mFields.m8 + 8, 0, 8);
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- (
- SPINEL_DATATYPE_IPv6ADDR_S // Mesh-local IPv6 address
- SPINEL_DATATYPE_UINT8_S // Prefix length (in bits)
- ),
- &addr,
- 64
- );
- }
- else
- {
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_VOID_S
- );
- }
+ SuccessOrExit(error = mEncoder.WriteIp6Address(addr)); // Mesh local prefix
+ SuccessOrExit(error = mEncoder.WriteUint8(64)); // Prefix length (in bits)
+exit:
return error;
}
@@ -1395,108 +1080,54 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_IPV6_ML_ADDR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_IPV6_ML_ADDR(void)
{
otError error = OT_ERROR_NONE;
const otIp6Address *ml64 = otThreadGetMeshLocalEid(mInstance);
- if (ml64)
- {
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_IPv6ADDR_S,
- ml64
- );
- }
- else
- {
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_VOID_S
- );
- }
+ VerifyOrExit(ml64 != NULL);
+ SuccessOrExit(error = mEncoder.WriteIp6Address(*ml64));
+exit:
return error;
}
-otError NcpBase::GetPropertyHandler_IPV6_LL_ADDR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_IPV6_LL_ADDR(void)
{
otError error = OT_ERROR_NONE;
const otIp6Address *address = otThreadGetLinkLocalIp6Address(mInstance);
- if (address)
- {
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_IPv6ADDR_S,
- address
- );
- }
- else
- {
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_VOID_S
- );
- }
+ VerifyOrExit(address != NULL);
+ SuccessOrExit(error = mEncoder.WriteIp6Address(*address));
+exit:
return error;
}
-otError NcpBase::GetPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_IPV6_ADDRESS_TABLE(void)
{
otError error = OT_ERROR_NONE;
- mDisableStreamWrite = true;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
for (const otNetifAddress *address = otIp6GetUnicastAddresses(mInstance); address; address = address->mNext)
{
+ SuccessOrExit(error = mEncoder.OpenStruct());
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_IPv6ADDR_S // IPv6 address
- SPINEL_DATATYPE_UINT8_S // Prefix length (in bits)
- SPINEL_DATATYPE_UINT32_S // Preferred lifetime
- SPINEL_DATATYPE_UINT32_S // Valid lifetime
- ),
- &address->mAddress,
- address->mPrefixLength,
- address->mPreferred ? 0xffffffff : 0,
- address->mValid ? 0xffffffff : 0
- ));
+ SuccessOrExit(error = mEncoder.WriteIp6Address(address->mAddress));
+ SuccessOrExit(error = mEncoder.WriteUint8(address->mPrefixLength));
+ SuccessOrExit(error = mEncoder.WriteUint32(address->mPreferred ? 0xffffffff : 0));
+ SuccessOrExit(error = mEncoder.WriteUint32(address->mValid ? 0xffffffff : 0));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
- mDisableStreamWrite = false;
return error;
}
-otError NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
otNetifAddress netifAddr;
otIp6Address *addrPtr;
uint32_t preferredLifetime;
@@ -1518,7 +1149,7 @@ otError NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t aHeader, spine
&validLifetime
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
netifAddr.mAddress = *addrPtr;
netifAddr.mPrefixLength = prefixLen;
@@ -1527,34 +1158,14 @@ otError NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t aHeader, spine
error = otIp6AddUnicastAddress(mInstance, &netifAddr);
- VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
-
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_INSERTED,
- aKey,
- aValuePtr,
- aValueLen
- );
-
- spinelError = SPINEL_STATUS_OK;
-
exit:
-
- if (spinelError != SPINEL_STATUS_OK)
- {
- error = SendLastStatus(aHeader, spinelError);
- }
-
return error;
}
-otError NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
otIp6Address *addrPtr;
parsedLength = spinel_datatype_unpack(
@@ -1564,51 +1175,29 @@ otError NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t aHeader, spine
&addrPtr
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otIp6RemoveUnicastAddress(mInstance, addrPtr);
- // If address was not on the list, "remove" command is successful,
- // and we respond with a `SPINEL_STATUS_OK` status.
- VerifyOrExit(error != OT_ERROR_NOT_FOUND, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
-
- 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)
+ // If address was not on the list, "remove" command is successful.
+ if (error == OT_ERROR_NOT_FOUND)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
-otError NcpBase::GetPropertyHandler_IPV6_ROUTE_TABLE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_IPV6_ROUTE_TABLE(void)
{
// TODO: Implement get route table
- OT_UNUSED_VARIABLE(aKey);
-
- return SendLastStatus(aHeader, SPINEL_STATUS_UNIMPLEMENTED);
+ return mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_UNIMPLEMENTED);
}
-otError NcpBase::GetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- otIcmp6IsEchoEnabled(mInstance)
- );
+ return mEncoder.WriteBool(otIcmp6IsEchoEnabled(mInstance));
}
otError NcpBase::SetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -1633,46 +1222,26 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(void)
{
otError error = OT_ERROR_NONE;
const otNetifMulticastAddress *address;
- mDisableStreamWrite = true;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
for (address = otIp6GetMulticastAddresses(mInstance); address; address = address->mNext)
{
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_IPv6ADDR_S // IPv6 address
- ),
- &address->mAddress
- ));
+ SuccessOrExit(error = mEncoder.OpenStruct());
+ SuccessOrExit(error = mEncoder.WriteIp6Address(address->mAddress));
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
- mDisableStreamWrite = false;
return error;
}
-otError NcpBase::InsertPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::InsertPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
otIp6Address *addrPtr;
parsedLength = spinel_datatype_unpack(
@@ -1682,40 +1251,23 @@ otError NcpBase::InsertPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(uint8_t aHea
&addrPtr
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otIp6SubscribeMulticastAddress(mInstance, addrPtr);
- VerifyOrExit(error != OT_ERROR_ALREADY, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
-
- VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
-
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_INSERTED,
- aKey,
- aValuePtr,
- aValueLen
- );
-
- spinelError = SPINEL_STATUS_OK;
-
-exit:
-
- if (spinelError != SPINEL_STATUS_OK)
+ if (error == OT_ERROR_ALREADY)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
-otError NcpBase::RemovePropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
otIp6Address *addrPtr;
parsedLength = spinel_datatype_unpack(
@@ -1725,44 +1277,25 @@ otError NcpBase::RemovePropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(uint8_t aHea
&addrPtr
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otIp6UnsubscribeMulticastAddress(mInstance, addrPtr);
// If the address was not on the list, "remove" command is successful,
// and we respond with a `SPINEL_STATUS_OK` status.
- VerifyOrExit(error != OT_ERROR_NOT_FOUND, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
-
- 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)
+ if (error == OT_ERROR_NOT_FOUND)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
-otError NcpBase::GetPropertyHandler_THREAD_RLOC16_DEBUG_PASSTHRU(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_RLOC16_DEBUG_PASSTHRU(void)
{
// Note reverse logic: passthru enabled = filter disabled
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- !otIp6IsReceiveFilterEnabled(mInstance)
- );
+ return mEncoder.WriteBool(!otIp6IsReceiveFilterEnabled(mInstance));
}
otError NcpBase::SetPropertyHandler_THREAD_RLOC16_DEBUG_PASSTHRU(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -1788,78 +1321,48 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_OFF_MESH_ROUTES(void)
{
otError error = OT_ERROR_NONE;
- otExternalRouteConfig external_route_config;
+ otExternalRouteConfig routeConfig;
otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT;
- mDisableStreamWrite = true;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
- while (otNetDataGetNextRoute(mInstance, &iter, &external_route_config) == OT_ERROR_NONE)
+ while (otNetDataGetNextRoute(mInstance, &iter, &routeConfig) == OT_ERROR_NONE)
{
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_IPv6ADDR_S // IPv6 Prefix
- SPINEL_DATATYPE_UINT8_S // Prefix Length (in bits)
- SPINEL_DATATYPE_BOOL_S // IsStable
- SPINEL_DATATYPE_UINT8_S // Route Preference Flags
- SPINEL_DATATYPE_BOOL_S // IsLocal
- SPINEL_DATATYPE_BOOL_S // NextHopIsThisDevice
- SPINEL_DATATYPE_UINT16_S // RLOC16
- ),
- &external_route_config.mPrefix.mPrefix,
- external_route_config.mPrefix.mLength,
- external_route_config.mStable,
- ExternalRoutePreferenceToFlagByte(external_route_config.mPreference),
- false,
- external_route_config.mNextHopIsThisDevice,
- external_route_config.mRloc16
- ));
+ SuccessOrExit(error = mEncoder.OpenStruct());
+
+ SuccessOrExit(error = mEncoder.WriteIp6Address(routeConfig.mPrefix.mPrefix));
+ SuccessOrExit(error = mEncoder.WriteUint8(routeConfig.mPrefix.mLength));
+ SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mStable));
+ SuccessOrExit(error = mEncoder.WriteUint8(ExternalRoutePreferenceToFlagByte(routeConfig.mPreference)));
+ SuccessOrExit(error = mEncoder.WriteBool(false)); // IsLocal
+ SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mNextHopIsThisDevice));
+ SuccessOrExit(error = mEncoder.WriteUint16(routeConfig.mRloc16));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
#if OPENTHREAD_ENABLE_BORDER_ROUTER
iter = OT_NETWORK_DATA_ITERATOR_INIT;
- while (otBorderRouterGetNextRoute(mInstance, &iter, &external_route_config) == OT_ERROR_NONE)
+ while (otBorderRouterGetNextRoute(mInstance, &iter, &routeConfig) == OT_ERROR_NONE)
{
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_IPv6ADDR_S // IPv6 Prefix
- SPINEL_DATATYPE_UINT8_S // Prefix Length (in bits)
- SPINEL_DATATYPE_BOOL_S // IsStable
- SPINEL_DATATYPE_UINT8_S // Route Preference Flags
- SPINEL_DATATYPE_BOOL_S // IsLocal
- SPINEL_DATATYPE_BOOL_S // NextHopIsThisDevice
- SPINEL_DATATYPE_UINT16_S // RLOC16
- ),
- &external_route_config.mPrefix.mPrefix,
- external_route_config.mPrefix.mLength,
- external_route_config.mStable,
- ExternalRoutePreferenceToFlagByte(external_route_config.mPreference),
- true,
- external_route_config.mNextHopIsThisDevice,
- external_route_config.mRloc16
- ));
+ SuccessOrExit(error = mEncoder.OpenStruct());
+
+ SuccessOrExit(error = mEncoder.WriteIp6Address(routeConfig.mPrefix.mPrefix));
+ SuccessOrExit(error = mEncoder.WriteUint8(routeConfig.mPrefix.mLength));
+ SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mStable));
+ SuccessOrExit(error = mEncoder.WriteUint8(ExternalRoutePreferenceToFlagByte(routeConfig.mPreference)));
+ SuccessOrExit(error = mEncoder.WriteBool(true)); // IsLocal
+ SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mNextHopIsThisDevice));
+ SuccessOrExit(error = mEncoder.WriteUint16(routeConfig.mRloc16));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
- mDisableStreamWrite = false;
return error;
}
@@ -1886,12 +1389,10 @@ static int FlagByteToExternalRoutePreference(uint8_t aFlags)
return route_preference;
}
-otError NcpBase::InsertPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::InsertPropertyHandler_THREAD_OFF_MESH_ROUTES(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
otExternalRouteConfig routeConfig;
otIp6Address *addrPtr;
bool stable = false;
@@ -1899,7 +1400,7 @@ otError NcpBase::InsertPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t aHeader, s
memset(&routeConfig, 0, sizeof(otExternalRouteConfig));
- VerifyOrExit(mAllowLocalNetworkDataChange == true, spinelError = SPINEL_STATUS_INVALID_STATE);
+ VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
parsedLength = spinel_datatype_unpack(
aValuePtr,
@@ -1916,45 +1417,28 @@ otError NcpBase::InsertPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t aHeader, s
&flags
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
routeConfig.mPrefix.mPrefix = *addrPtr;
routeConfig.mStable = stable;
routeConfig.mPreference = FlagByteToExternalRoutePreference(flags);
error = otBorderRouterAddRoute(mInstance, &routeConfig);
- 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::RemovePropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_THREAD_OFF_MESH_ROUTES(const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
- spinel_status_t spinelError = SPINEL_STATUS_OK;
otIp6Prefix ip6Prefix;
otIp6Address *addrPtr;
memset(&ip6Prefix, 0, sizeof(otIp6Prefix));
- VerifyOrExit(mAllowLocalNetworkDataChange == true, spinelError = SPINEL_STATUS_INVALID_STATE);
+ VerifyOrExit(mAllowLocalNetworkDataChange == true, error = OT_ERROR_INVALID_STATE);
parsedLength = spinel_datatype_unpack(
aValuePtr,
@@ -1967,43 +1451,27 @@ otError NcpBase::RemovePropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t aHeader, s
&ip6Prefix.mLength
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
ip6Prefix.mPrefix = *addrPtr;
error = otBorderRouterRemoveRoute(mInstance, &ip6Prefix);
- // If the route prefix was not on the list, "remove" command is successful,
- // and we respond with a `SPINEL_STATUS_OK` status.
- VerifyOrExit(error != OT_ERROR_NOT_FOUND, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
-
- 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)
+ // If the route prefix was not on the list, "remove" command is successful.
+ if (error == OT_ERROR_NOT_FOUND)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
#endif // OPENTHREAD_ENABLE_BORDER_ROUTER
-otError NcpBase::GetPropertyHandler_STREAM_NET(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_STREAM_NET(void)
{
// TODO: Implement explicit data poll.
- OT_UNUSED_VARIABLE(aKey);
-
- return SendLastStatus(aHeader, SPINEL_STATUS_UNIMPLEMENTED);
+ return mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_UNIMPLEMENTED);
}
otError NcpBase::SetPropertyHandler_STREAM_NET(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -2081,76 +1549,44 @@ exit:
#if OPENTHREAD_ENABLE_JAM_DETECTION
-otError NcpBase::GetPropertyHandler_JAM_DETECT_ENABLE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_JAM_DETECT_ENABLE(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- otJamDetectionIsEnabled(mInstance)
- );
+ return mEncoder.WriteBool(otJamDetectionIsEnabled(mInstance));
}
-otError NcpBase::GetPropertyHandler_JAM_DETECTED(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_JAM_DETECTED(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- otJamDetectionGetState(mInstance)
- );
+ return mEncoder.WriteBool(otJamDetectionGetState(mInstance));
}
-otError NcpBase::GetPropertyHandler_JAM_DETECT_RSSI_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_JAM_DETECT_RSSI_THRESHOLD(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_INT8_S,
- otJamDetectionGetRssiThreshold(mInstance)
- );
+ return mEncoder.WriteInt8(otJamDetectionGetRssiThreshold(mInstance));
}
-otError NcpBase::GetPropertyHandler_JAM_DETECT_WINDOW(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_JAM_DETECT_WINDOW(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- otJamDetectionGetWindow(mInstance)
- );
+ return mEncoder.WriteUint8(otJamDetectionGetWindow(mInstance));
}
-otError NcpBase::GetPropertyHandler_JAM_DETECT_BUSY(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_JAM_DETECT_BUSY(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- otJamDetectionGetBusyPeriod(mInstance)
- );
+ return mEncoder.WriteUint8(otJamDetectionGetBusyPeriod(mInstance));
}
-otError NcpBase::GetPropertyHandler_JAM_DETECT_HISTORY_BITMAP(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_JAM_DETECT_HISTORY_BITMAP(void)
{
+ otError error = OT_ERROR_NONE;
uint64_t historyBitmap = otJamDetectionGetHistoryBitmap(mInstance);
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- (
- SPINEL_DATATYPE_UINT32_S // History bitmap - bits 0-31
- SPINEL_DATATYPE_UINT32_S // History bitmap - bits 32-63
- ),
- static_cast(historyBitmap & 0xffffffff),
- static_cast(historyBitmap >> 32)
- );
+ // History bitmap - bits 0-31
+ SuccessOrExit(error = mEncoder.WriteUint32(static_cast(historyBitmap & 0xffffffff)));
+
+ // // History bitmap - bits 32-63
+ SuccessOrExit(error = mEncoder.WriteUint32(static_cast(historyBitmap >> 32)));
+
+exit:
+ return error;
}
otError NcpBase::SetPropertyHandler_JAM_DETECT_ENABLE(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -2263,321 +1699,254 @@ void NcpBase::HandleJamStateChange(bool aJamState)
#endif // OPENTHREAD_ENABLE_JAM_DETECTION
-otError NcpBase::GetPropertyHandler_MAC_CNTR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_TOTAL(void)
{
- uint32_t value;
- const otMacCounters *macCounters;
- otError error = OT_ERROR_NONE;
-
- macCounters = otLinkGetCounters(mInstance);
-
- assert(macCounters != NULL);
-
- switch (aKey)
- {
- case SPINEL_PROP_CNTR_TX_PKT_TOTAL:
- value = macCounters->mTxTotal;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_ACK_REQ:
- value = macCounters->mTxAckRequested;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_ACKED:
- value = macCounters->mTxAcked;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_NO_ACK_REQ:
- value = macCounters->mTxNoAckRequested;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_DATA:
- value = macCounters->mTxData;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_DATA_POLL:
- value = macCounters->mTxDataPoll;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_BEACON:
- value = macCounters->mTxBeacon;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_BEACON_REQ:
- value = macCounters->mTxBeaconRequest;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_OTHER:
- value = macCounters->mTxOther;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_RETRY:
- value = macCounters->mTxRetry;
- break;
-
- case SPINEL_PROP_CNTR_TX_ERR_CCA:
- value = macCounters->mTxErrCca;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_UNICAST:
- value = macCounters->mTxUnicast;
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_BROADCAST:
- value = macCounters->mTxBroadcast;
- break;
-
- case SPINEL_PROP_CNTR_TX_ERR_ABORT:
- value = macCounters->mTxErrAbort;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_TOTAL:
- value = macCounters->mRxTotal;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_DATA:
- value = macCounters->mRxData;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_DATA_POLL:
- value = macCounters->mRxDataPoll;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_BEACON:
- value = macCounters->mRxBeacon;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_BEACON_REQ:
- value = macCounters->mRxBeaconRequest;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_OTHER:
- value = macCounters->mRxOther;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_FILT_WL:
- value = macCounters->mRxWhitelistFiltered;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_FILT_DA:
- value = macCounters->mRxDestAddrFiltered;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_DUP:
- value = macCounters->mRxDuplicated;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_UNICAST:
- value = macCounters->mRxUnicast;
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_BROADCAST:
- value = macCounters->mRxBroadcast;
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_EMPTY:
- value = macCounters->mRxErrNoFrame;
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_UKWN_NBR:
- value = macCounters->mRxErrUnknownNeighbor;
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_NVLD_SADDR:
- value = macCounters->mRxErrInvalidSrcAddr;
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_SECURITY:
- value = macCounters->mRxErrSec;
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_BAD_FCS:
- value = macCounters->mRxErrFcs;
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_OTHER:
- value = macCounters->mRxErrOther;
- break;
-
- default:
- error = SendLastStatus(aHeader, SPINEL_STATUS_INTERNAL_ERROR);
- ExitNow();
- }
-
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- value
- );
-
-exit:
- return error;
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxTotal);
}
-otError NcpBase::GetPropertyHandler_NCP_CNTR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_ACK_REQ(void)
{
- uint32_t value;
- otError error = OT_ERROR_NONE;
-
- switch (aKey)
- {
- case SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL:
- value = mInboundSecureIpFrameCounter;
- break;
-
- case SPINEL_PROP_CNTR_TX_IP_INSEC_TOTAL:
- value = mInboundInsecureIpFrameCounter;
- break;
-
- case SPINEL_PROP_CNTR_TX_IP_DROPPED:
- value = mDroppedInboundIpFrameCounter;
- break;
-
- case SPINEL_PROP_CNTR_RX_IP_SEC_TOTAL:
- value = mOutboundSecureIpFrameCounter;
- break;
-
- case SPINEL_PROP_CNTR_RX_IP_INSEC_TOTAL:
- value = mOutboundInsecureIpFrameCounter;
- break;
-
- case SPINEL_PROP_CNTR_RX_IP_DROPPED:
- value = mDroppedOutboundIpFrameCounter;
- break;
-
- case SPINEL_PROP_CNTR_TX_SPINEL_TOTAL:
- value = mTxSpinelFrameCounter;
- break;
-
- case SPINEL_PROP_CNTR_RX_SPINEL_TOTAL:
- value = mRxSpinelFrameCounter;
- break;
-
- case SPINEL_PROP_CNTR_RX_SPINEL_OUT_OF_ORDER_TID:
- value = mRxSpinelOutOfOrderTidCounter;
- break;
-
- case SPINEL_PROP_CNTR_RX_SPINEL_ERR:
- value = mFramingErrorCounter;
- break;
-
- default:
- error = SendLastStatus(aHeader, SPINEL_STATUS_INTERNAL_ERROR);
- ExitNow();
- }
-
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- value
- );
-
-exit:
- return error;
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxAckRequested);
}
-otError NcpBase::GetPropertyHandler_IP_CNTR(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_ACKED(void)
{
- uint32_t value;
- otError error = OT_ERROR_NONE;
-
- const otIpCounters *counters = otThreadGetIp6Counters(mInstance);
-
- switch (aKey)
- {
- case SPINEL_PROP_CNTR_IP_TX_SUCCESS:
- value = counters->mTxSuccess;
- break;
-
- case SPINEL_PROP_CNTR_IP_RX_SUCCESS:
- value = counters->mRxSuccess;
- break;
-
- case SPINEL_PROP_CNTR_IP_TX_FAILURE:
- value = counters->mTxFailure;
- break;
-
- case SPINEL_PROP_CNTR_IP_RX_FAILURE:
- value = counters->mRxFailure;
- break;
-
- default:
- error = SendLastStatus(aHeader, SPINEL_STATUS_INTERNAL_ERROR);
- ExitNow();
- break;
- }
-
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- value
- );
-
-exit:
- return error;
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxAcked);
}
-otError NcpBase::GetPropertyHandler_MSG_BUFFER_COUNTERS(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_NO_ACK_REQ(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxNoAckRequested);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_DATA(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxData);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_DATA_POLL(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxDataPoll);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_BEACON(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBeacon);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_BEACON_REQ(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBeaconRequest);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_OTHER(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxOther);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_RETRY(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxRetry);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_ERR_CCA(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxErrCca);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_UNICAST(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxUnicast);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_PKT_BROADCAST(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBroadcast);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_ERR_ABORT(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxErrAbort);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_TOTAL(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxTotal);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_DATA(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxData);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_DATA_POLL(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDataPoll);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_BEACON(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBeacon);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_BEACON_REQ(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBeaconRequest);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_OTHER(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxOther);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_FILT_WL(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxWhitelistFiltered);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_FILT_DA(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDestAddrFiltered);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_DUP(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDuplicated);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_UNICAST(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxUnicast);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_PKT_BROADCAST(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBroadcast);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_EMPTY(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrNoFrame);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_UKWN_NBR(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrUnknownNeighbor);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_NVLD_SADDR(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrInvalidSrcAddr);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_SECURITY(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrSec);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_BAD_FCS(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrFcs);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_ERR_OTHER(void)
+{
+ return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrOther);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_IP_SEC_TOTAL(void)
+{
+ return mEncoder.WriteUint32(mInboundSecureIpFrameCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_IP_INSEC_TOTAL(void)
+{
+ return mEncoder.WriteUint32(mInboundInsecureIpFrameCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_IP_DROPPED(void)
+{
+ return mEncoder.WriteUint32(mDroppedInboundIpFrameCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_IP_SEC_TOTAL(void)
+{
+ return mEncoder.WriteUint32(mOutboundSecureIpFrameCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_IP_INSEC_TOTAL(void)
+{
+ return mEncoder.WriteUint32(mOutboundInsecureIpFrameCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_IP_DROPPED(void)
+{
+ return mEncoder.WriteUint32(mDroppedOutboundIpFrameCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_TX_SPINEL_TOTAL(void)
+{
+ return mEncoder.WriteUint32(mTxSpinelFrameCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_SPINEL_TOTAL(void)
+{
+ return mEncoder.WriteUint32(mRxSpinelFrameCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_SPINEL_OUT_OF_ORDER_TID(void)
+{
+ return mEncoder.WriteUint32(mRxSpinelOutOfOrderTidCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_RX_SPINEL_ERR(void)
+{
+ return mEncoder.WriteUint32(mFramingErrorCounter);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_IP_TX_SUCCESS(void)
+{
+ return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mTxSuccess);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_IP_RX_SUCCESS(void)
+{
+ return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mRxSuccess);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_IP_TX_FAILURE(void)
+{
+ return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mTxFailure);
+}
+
+otError NcpBase::GetPropertyHandler_CNTR_IP_RX_FAILURE(void)
+{
+ return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mRxFailure);
+}
+
+otError NcpBase::GetPropertyHandler_MSG_BUFFER_COUNTERS(void)
{
otError error = OT_ERROR_NONE;
otBufferInfo bufferInfo;
otMessageGetBufferInfo(mInstance, &bufferInfo);
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- (
- SPINEL_DATATYPE_UINT16_S // Total buffers
- SPINEL_DATATYPE_UINT16_S // Free buffers
- SPINEL_DATATYPE_UINT16_S // Lowpan send messages
- SPINEL_DATATYPE_UINT16_S // Lowpan send buffers
- SPINEL_DATATYPE_UINT16_S // Lowpan reassembly messages
- SPINEL_DATATYPE_UINT16_S // Lowpan reassembly buffers
- SPINEL_DATATYPE_UINT16_S // Ip6 messages
- SPINEL_DATATYPE_UINT16_S // Ip6 buffers
- SPINEL_DATATYPE_UINT16_S // Mpl messages
- SPINEL_DATATYPE_UINT16_S // Mpl buffers
- SPINEL_DATATYPE_UINT16_S // Mle messages
- SPINEL_DATATYPE_UINT16_S // Mle buffers
- SPINEL_DATATYPE_UINT16_S // Arp messages
- SPINEL_DATATYPE_UINT16_S // Arp buffers
- SPINEL_DATATYPE_UINT16_S // Coap messages
- SPINEL_DATATYPE_UINT16_S // Coap buffers
- ),
- bufferInfo.mTotalBuffers,
- bufferInfo.mFreeBuffers,
- bufferInfo.m6loSendMessages,
- bufferInfo.m6loSendBuffers,
- bufferInfo.m6loReassemblyMessages,
- bufferInfo.m6loReassemblyBuffers,
- bufferInfo.mIp6Messages,
- bufferInfo.mIp6Buffers,
- bufferInfo.mMplMessages,
- bufferInfo.mMplBuffers,
- bufferInfo.mMleMessages,
- bufferInfo.mMleBuffers,
- bufferInfo.mArpMessages,
- bufferInfo.mArpBuffers,
- bufferInfo.mCoapMessages,
- bufferInfo.mCoapBuffers
- ));
-
- SuccessOrExit(error = OutboundFrameSend());
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mTotalBuffers));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mFreeBuffers));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loSendMessages));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loSendBuffers));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loReassemblyMessages));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loReassemblyBuffers));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mIp6Messages));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mIp6Buffers));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMplMessages));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMplBuffers));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMleMessages));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMleBuffers));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mArpMessages));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mArpBuffers));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mCoapMessages));
+ SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mCoapBuffers));
exit:
return error;
@@ -2585,140 +1954,70 @@ exit:
#if OPENTHREAD_ENABLE_MAC_FILTER
-otError NcpBase::GetPropertyHandler_MAC_WHITELIST(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_WHITELIST(void)
{
otMacFilterEntry entry;
otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
otError error = OT_ERROR_NONE;
- mDisableStreamWrite = true;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
while (otLinkFilterGetNextAddress(mInstance, &iterator, &entry) == OT_ERROR_NONE)
{
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_EUI64_S // Extended address
- SPINEL_DATATYPE_INT8_S // Rss
- ),
- entry.mExtAddress.m8,
- entry.mRssIn
- ));
+ SuccessOrExit(error = mEncoder.OpenStruct());
+
+ SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
+ SuccessOrExit(error = mEncoder.WriteInt8(entry.mRssIn));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
- mDisableStreamWrite = false;
return error;
}
-otError NcpBase::GetPropertyHandler_MAC_WHITELIST_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_WHITELIST_ENABLED(void)
{
- otMacFilterAddressMode mode = otLinkFilterGetAddressMode(mInstance);
- bool isEnabled = (mode == OT_MAC_FILTER_ADDRESS_MODE_WHITELIST) ? true : false;
-
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- isEnabled
- );
+ return mEncoder.WriteBool(otLinkFilterGetAddressMode(mInstance) == OT_MAC_FILTER_ADDRESS_MODE_WHITELIST);
}
-otError NcpBase::GetPropertyHandler_MAC_BLACKLIST(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_BLACKLIST(void)
{
otMacFilterEntry entry;
otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
otError error = OT_ERROR_NONE;
- mDisableStreamWrite = true;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
while (otLinkFilterGetNextAddress(mInstance, &iterator, &entry) == OT_ERROR_NONE)
{
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_EUI64_S // Extended address
- ),
- entry.mExtAddress.m8
- ));
+ SuccessOrExit(error = mEncoder.OpenStruct());
+ SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
- mDisableStreamWrite = false;
return error;
}
-otError NcpBase::GetPropertyHandler_MAC_BLACKLIST_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_BLACKLIST_ENABLED(void)
{
- otMacFilterAddressMode mode = otLinkFilterGetAddressMode(mInstance);
- bool isEnabled = (mode == OT_MAC_FILTER_ADDRESS_MODE_BLACKLIST) ? true : false;
-
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- isEnabled
- );
+ return mEncoder.WriteBool(otLinkFilterGetAddressMode(mInstance) == OT_MAC_FILTER_ADDRESS_MODE_BLACKLIST);
}
-otError NcpBase::GetPropertyHandler_MAC_FIXED_RSS(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_FIXED_RSS(void)
{
otMacFilterEntry entry;
otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
otError error = OT_ERROR_NONE;
- mDisableStreamWrite = true;
-
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
while (otLinkFilterGetNextRssIn(mInstance, &iterator, &entry) == OT_ERROR_NONE)
{
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_STRUCT_S(
- SPINEL_DATATYPE_EUI64_S // Extended address
- SPINEL_DATATYPE_INT8_S // Rss
- ),
- entry.mExtAddress.m8,
- entry.mRssIn
- ));
+ SuccessOrExit(error = mEncoder.OpenStruct());
+
+ SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
+ SuccessOrExit(error = mEncoder.WriteInt8(entry.mRssIn));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
- mDisableStreamWrite = false;
return error;
}
@@ -2964,7 +2263,7 @@ exit:
}
#endif // OPENTHREAD_ENABLE_MAC_FILTER
-otError NcpBase::GetPropertyHandler_THREAD_MODE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_MODE(void)
{
uint8_t numericMode;
otLinkModeConfig modeConfig = otThreadGetLinkMode(mInstance);
@@ -2976,13 +2275,7 @@ otError NcpBase::GetPropertyHandler_THREAD_MODE(uint8_t aHeader, spinel_prop_key
modeConfig.mNetworkData
);
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- numericMode
- );
+ return mEncoder.WriteUint8(numericMode);
}
otError NcpBase::SetPropertyHandler_THREAD_MODE(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -3014,38 +2307,19 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-
-otError NcpBase::GetPropertyHandler_THREAD_CHILD_TIMEOUT(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_CHILD_TIMEOUT(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT32_S,
- otThreadGetChildTimeout(mInstance)
- );
+ return mEncoder.WriteUint32(otThreadGetChildTimeout(mInstance));
}
-otError NcpBase::GetPropertyHandler_THREAD_RLOC16(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_THREAD_RLOC16(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT16_S,
- otThreadGetRloc16(mInstance)
- );
+ return mEncoder.WriteUint16(otThreadGetRloc16(mInstance));
}
-otError NcpBase::GetPropertyHandler_NET_REQUIRE_JOIN_EXISTING(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NET_REQUIRE_JOIN_EXISTING(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_BOOL_S,
- mRequireJoinExistingNetwork
- );
+ return mEncoder.WriteBool(mRequireJoinExistingNetwork);
}
otError NcpBase::SetPropertyHandler_NET_REQUIRE_JOIN_EXISTING(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -3186,6 +2460,7 @@ otError NcpBase::SetPropertyHandler_NEST_STREAM_MFG(uint8_t aHeader, spinel_prop
char *output = NULL;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
+ spinel_status_t spinelError = SPINEL_STATUS_OK;
parsedLength = spinel_datatype_unpack(
aValuePtr,
@@ -3194,56 +2469,16 @@ otError NcpBase::SetPropertyHandler_NEST_STREAM_MFG(uint8_t aHeader, spinel_prop
&string
);
- if ((parsedLength > 0) && (string != NULL))
- {
- // all diagnostics related features are processed within diagnostics module
- output = otDiagProcessCmdLine(string);
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- reinterpret_cast(output),
- static_cast(strlen(output) + 1)
- );
- }
- else
- {
- error = SendLastStatus(aHeader, SPINEL_STATUS_PARSE_ERROR);
- }
- return error;
-}
+ VerifyOrExit((parsedLength > 0) && (string != NULL), spinelError = SPINEL_STATUS_PARSE_ERROR);
-#endif // OPENTHREAD_ENABLE_DIAG
+ // All diagnostics related features are processed within diagnostics module
+ output = otDiagProcessCmdLine(string);
-otError NcpBase::InsertPropertyHandler_THREAD_ASSISTING_PORTS(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;
- uint16_t port;
-
- parsedLength = spinel_datatype_unpack(
- aValuePtr,
- aValueLen,
- SPINEL_DATATYPE_UINT16_S,
- &port
- );
-
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
-
- error = otIp6AddUnsecurePort(mInstance, port);
- VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
-
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_INSERTED,
- aKey,
- aValuePtr,
- aValueLen
- );
+ SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, aKey));
+ SuccessOrExit(error = mEncoder.WriteUtf8(output));
+ SuccessOrExit(error = mEncoder.EndFrame());
exit:
@@ -3255,14 +2490,34 @@ exit:
return error;
}
-#if OPENTHREAD_ENABLE_MAC_FILTER
+#endif // OPENTHREAD_ENABLE_DIAG
-otError NcpBase::InsertPropertyHandler_MAC_WHITELIST(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::InsertPropertyHandler_THREAD_ASSISTING_PORTS(const uint8_t *aValuePtr, uint16_t aValueLen)
+{
+ spinel_ssize_t parsedLength;
+ otError error = OT_ERROR_NONE;
+ uint16_t port;
+
+ parsedLength = spinel_datatype_unpack(
+ aValuePtr,
+ aValueLen,
+ SPINEL_DATATYPE_UINT16_S,
+ &port
+ );
+
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
+
+ error = otIp6AddUnsecurePort(mInstance, port);
+exit:
+ return error;
+}
+
+#if OPENTHREAD_ENABLE_MAC_FILTER
+
+otError NcpBase::InsertPropertyHandler_MAC_WHITELIST(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;
int8_t rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
@@ -3286,42 +2541,30 @@ otError NcpBase::InsertPropertyHandler_MAC_WHITELIST(uint8_t aHeader, spinel_pro
);
}
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otLinkFilterAddAddress(mInstance, extAddress);
- VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_ALREADY, spinelError = ThreadErrorToSpinelStatus(error));
+ if (error == OT_ERROR_ALREADY)
+ {
+ error = OT_ERROR_NONE;
+ }
+
+ SuccessOrExit(error);
if (rss != OT_MAC_FILTER_FIXED_RSS_DISABLED)
{
error = otLinkFilterAddRssIn(mInstance, extAddress, rss);
- 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_BLACKLIST(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::InsertPropertyHandler_MAC_BLACKLIST(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(
@@ -3331,36 +2574,23 @@ otError NcpBase::InsertPropertyHandler_MAC_BLACKLIST(uint8_t aHeader, spinel_pro
&extAddress
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otLinkFilterAddAddress(mInstance, extAddress);
- VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_ALREADY, spinelError = ThreadErrorToSpinelStatus(error));
-
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_INSERTED,
- aKey,
- aValuePtr,
- aValueLen
- );
-
-exit:
-
- if (spinelError != SPINEL_STATUS_OK)
+ if (error == OT_ERROR_ALREADY)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
-otError NcpBase::InsertPropertyHandler_MAC_FIXED_RSS(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::InsertPropertyHandler_MAC_FIXED_RSS(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;
int8_t rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
@@ -3384,38 +2614,20 @@ otError NcpBase::InsertPropertyHandler_MAC_FIXED_RSS(uint8_t aHeader, spinel_pro
);
}
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otLinkFilterAddRssIn(mInstance, extAddress, rss);
- 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;
}
#endif // OPENTHREAD_ENABLE_MAC_FILTER
-otError NcpBase::RemovePropertyHandler_THREAD_ASSISTING_PORTS(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_THREAD_ASSISTING_PORTS(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 port;
parsedLength = spinel_datatype_unpack(
@@ -3425,42 +2637,26 @@ otError NcpBase::RemovePropertyHandler_THREAD_ASSISTING_PORTS(uint8_t aHeader, s
&port
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otIp6RemoveUnsecurePort(mInstance, port);
- // If unsecure port was not on the list, "remove" command is successful,
- // and we respond with a `SPINEL_STATUS_OK` status.
- VerifyOrExit(error != OT_ERROR_NOT_FOUND, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
-
- 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)
+ // If unsecure port was not on the list, "remove" command is successful.
+ if (error == OT_ERROR_NOT_FOUND)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
#if OPENTHREAD_ENABLE_MAC_FILTER
-otError NcpBase::RemovePropertyHandler_MAC_WHITELIST(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_MAC_WHITELIST(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(
@@ -3470,38 +2666,23 @@ otError NcpBase::RemovePropertyHandler_MAC_WHITELIST(uint8_t aHeader, spinel_pro
&extAddress
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otLinkFilterRemoveAddress(mInstance, extAddress);
- VerifyOrExit(error != OT_ERROR_NOT_FOUND, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
-
- 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)
+ if (error == OT_ERROR_NOT_FOUND)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
-otError NcpBase::RemovePropertyHandler_MAC_BLACKLIST(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_MAC_BLACKLIST(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(
@@ -3511,38 +2692,23 @@ otError NcpBase::RemovePropertyHandler_MAC_BLACKLIST(uint8_t aHeader, spinel_pro
&extAddress
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otLinkFilterRemoveAddress(mInstance, extAddress);
- VerifyOrExit(error != OT_ERROR_NOT_FOUND, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
-
- 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)
+ if (error == OT_ERROR_NOT_FOUND)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
-otError NcpBase::RemovePropertyHandler_MAC_FIXED_RSS(uint8_t aHeader, spinel_prop_key_t aKey,
- const uint8_t *aValuePtr, uint16_t aValueLen)
+otError NcpBase::RemovePropertyHandler_MAC_FIXED_RSS(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;
if (aValueLen > 0)
@@ -3554,30 +2720,17 @@ otError NcpBase::RemovePropertyHandler_MAC_FIXED_RSS(uint8_t aHeader, spinel_pro
&extAddress
);
- VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
+ VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
}
error = otLinkFilterRemoveRssIn(mInstance, extAddress);
- VerifyOrExit(error != OT_ERROR_NOT_FOUND, error = SendLastStatus(aHeader, SPINEL_STATUS_OK));
-
- 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)
+ if (error == OT_ERROR_NOT_FOUND)
{
- error = SendLastStatus(aHeader, spinelError);
+ error = OT_ERROR_NONE;
}
+exit:
return error;
}
@@ -3636,16 +2789,9 @@ void NcpBase::HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
#endif // OPENTHREAD_ENABLE_LEGACY
#if OPENTHREAD_ENABLE_LEGACY
-otError NcpBase::GetPropertyHandler_NEST_LEGACY_ULA_PREFIX(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NEST_LEGACY_ULA_PREFIX(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_DATA_S,
- mLegacyUlaPrefix,
- sizeof(mLegacyUlaPrefix)
- );
+ return mEncoder.WriteData(mLegacyUlaPrefix, sizeof(mLegacyUlaPrefix));
}
otError NcpBase::SetPropertyHandler_NEST_LEGACY_ULA_PREFIX(uint8_t aHeader, spinel_prop_key_t aKey,
@@ -3678,55 +2824,38 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_NEST_LEGACY_LAST_NODE_JOINED(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_NEST_LEGACY_LAST_NODE_JOINED(void)
{
+
if (!mLegacyNodeDidJoin)
{
memset(&mLegacyLastJoinedNode, 0, sizeof(mLegacyLastJoinedNode));
}
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_EUI64_S,
- &mLegacyLastJoinedNode,
- sizeof(mLegacyLastJoinedNode)
- );
+ return mEncoder.WriteEui64(mLegacyLastJoinedNode);
}
#endif // OPENTHREAD_ENABLE_LEGACY
-otError NcpBase::GetPropertyHandler_ChannelMaskHelper(uint8_t aHeader, spinel_prop_key_t aKey, uint32_t aChannelMask)
+otError NcpBase::GetPropertyHandler_ChannelMaskHelper(uint32_t aChannelMask)
{
otError error = OT_ERROR_NONE;
- SuccessOrExit(error = OutboundFrameBegin(aHeader));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S,
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey
- ));
-
- for (int i = 0; i < 32; i++)
+ for (uint8_t i = 0; i < 32; i++)
{
if (0 != (aChannelMask & (1 << i)))
{
- SuccessOrExit(error = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT8_S, i));
+ SuccessOrExit(error = mEncoder.WriteUint8(i));
}
}
- SuccessOrExit(error = OutboundFrameSend());
-
exit:
return error;
}
-otError NcpBase::GetPropertyHandler_MAC_SCAN_MASK(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_SCAN_MASK(void)
{
- return GetPropertyHandler_ChannelMaskHelper(aHeader, aKey, mChannelMask);
+ return GetPropertyHandler_ChannelMaskHelper(mChannelMask);
}
otError NcpBase::SetPropertyHandler_MAC_SCAN_MASK(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -3749,15 +2878,9 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_MAC_SCAN_PERIOD(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_SCAN_PERIOD(void)
{
- return SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT16_S,
- mScanPeriod
- );
+ return mEncoder.WriteUint16(mScanPeriod);
}
otError NcpBase::SetPropertyHandler_MAC_SCAN_PERIOD(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -3782,71 +2905,41 @@ exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
-otError NcpBase::GetPropertyHandler_MAC_SCAN_STATE(uint8_t aHeader, spinel_prop_key_t aKey)
+otError NcpBase::GetPropertyHandler_MAC_SCAN_STATE(void)
{
- otError error = OT_ERROR_NONE;
+ uint8_t scanState = SPINEL_SCAN_STATE_IDLE;
#if OPENTHREAD_ENABLE_RAW_LINK_API
if (otLinkRawIsEnabled(mInstance))
{
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- mCurScanChannel == kInvalidScanChannel
- ? SPINEL_SCAN_STATE_IDLE
- : SPINEL_SCAN_STATE_ENERGY
- );
+ scanState = (mCurScanChannel == kInvalidScanChannel) ? SPINEL_SCAN_STATE_IDLE : SPINEL_SCAN_STATE_ENERGY;
}
else
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
+
{
if (otLinkIsActiveScanInProgress(mInstance))
{
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- SPINEL_SCAN_STATE_BEACON
- );
+ scanState = SPINEL_SCAN_STATE_BEACON;
+
}
else if (otLinkIsEnergyScanInProgress(mInstance))
{
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- SPINEL_SCAN_STATE_ENERGY
- );
+ scanState = SPINEL_SCAN_STATE_ENERGY;
}
else if (otThreadIsDiscoverInProgress(mInstance))
{
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- SPINEL_SCAN_STATE_DISCOVER
- );
+ scanState = SPINEL_SCAN_STATE_DISCOVER;
}
else
{
- error = SendPropertyUpdate(
- aHeader,
- SPINEL_CMD_PROP_VALUE_IS,
- aKey,
- SPINEL_DATATYPE_UINT8_S,
- SPINEL_SCAN_STATE_IDLE
- );
+ scanState = SPINEL_SCAN_STATE_IDLE;
}
}
- return error;
+ return mEncoder.WriteUint8(scanState);
}
otError NcpBase::SetPropertyHandler_MAC_SCAN_STATE(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
@@ -3962,7 +3055,7 @@ void NcpBase::HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aCo
void NcpBase::HandleActiveScanResult(otActiveScanResult *aResult)
{
- otError error;
+ otError error = OT_ERROR_NONE;
if (aResult)
{
@@ -3978,55 +3071,48 @@ void NcpBase::HandleActiveScanResult(otActiveScanResult *aResult)
flags |= SPINEL_BEACON_THREAD_FLAG_NATIVE;
}
- error = SendPropertyUpdate(
- SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
- SPINEL_CMD_PROP_VALUE_INSERTED,
- SPINEL_PROP_MAC_SCAN_BEACON,
- SPINEL_DATATYPE_MAC_SCAN_RESULT_S(
- SPINEL_802_15_4_DATATYPE_MAC_SCAN_RESULT_V1_S,
- SPINEL_NET_DATATYPE_MAC_SCAN_RESULT_V2_S
- ),
- aResult->mChannel, // Channel
- aResult->mRssi, // RSSI
- // "mac-layer data"
- aResult->mExtAddress.m8, // laddr
- 0xFFFF, // saddr, not given
- aResult->mPanId, // panid
- aResult->mLqi, // lqi
- // "net-layer data"
- SPINEL_PROTOCOL_TYPE_THREAD, // type
- flags, // flags
- aResult->mNetworkName.m8, // network name
- aResult->mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE, // xpanid
- aResult->mSteeringData.m8, aResult->mSteeringData.mLength // steering data
- );
+ SuccessOrExit(error = mEncoder.BeginFrame(
+ SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
+ SPINEL_CMD_PROP_VALUE_INSERTED,
+ SPINEL_PROP_MAC_SCAN_BEACON
+ ));
+ SuccessOrExit(error = mEncoder.WriteUint8(aResult->mChannel));
+ SuccessOrExit(error = mEncoder.WriteInt8(aResult->mRssi));
- if (error != OT_ERROR_NONE)
- {
- mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
- mUpdateChangedPropsTask.Post();
- }
+ SuccessOrExit(error = mEncoder.OpenStruct()); // "mac-layer data"
+ SuccessOrExit(error = mEncoder.WriteEui64(aResult->mExtAddress));
+ SuccessOrExit(error = mEncoder.WriteUint16(0xffff)); // short address, not given
+ SuccessOrExit(error = mEncoder.WriteUint16(aResult->mPanId));
+ SuccessOrExit(error = mEncoder.WriteUint8(aResult->mLqi));
+ SuccessOrExit(error = mEncoder.CloseStruct());
+
+ SuccessOrExit(error = mEncoder.OpenStruct()); // "net-layer data"
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROTOCOL_TYPE_THREAD)); // type
+ SuccessOrExit(error = mEncoder.WriteUint8(flags));
+ SuccessOrExit(error = mEncoder.WriteUtf8(aResult->mNetworkName.m8));
+ SuccessOrExit(error = mEncoder.WriteDataWithLen(aResult->mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE));
+ SuccessOrExit(error = mEncoder.WriteDataWithLen(aResult->mSteeringData.m8, aResult->mSteeringData.mLength));
+ SuccessOrExit(error = mEncoder.CloseStruct());
+
+ SuccessOrExit(error = mEncoder.EndFrame());
}
else
{
- // We are finished with the scan, so send out
- // a property update indicating such.
- error = 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
- );
+ // We are finished with the scan, send an unsolicated
+ // scan state update.
+ mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
+ mUpdateChangedPropsTask.Post();
+ }
- // If we could not send the end of scan indicator message now (no
- // buffer space), we add the MAC_SCAN_STATE property to changed
- // property set so that the update is sent when buffer becomes
+exit:
+
+ if (error != OT_ERROR_NONE)
+ {
+ // We ran out of buffer adding a scan result so remember to send
+ // an async `LAST_STATUS(NOMEM)` when buffer space becomes
// available.
- if (error != OT_ERROR_NONE)
- {
- mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
- }
+ mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
+ mUpdateChangedPropsTask.Post();
}
}
@@ -4037,52 +3123,36 @@ void NcpBase::HandleEnergyScanResult_Jump(otEnergyScanResult *aResult, void *aCo
void NcpBase::HandleEnergyScanResult(otEnergyScanResult *aResult)
{
- otError error;
+ otError error = OT_ERROR_NONE;
if (aResult)
{
- error = SendPropertyUpdate(
- SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
- SPINEL_CMD_PROP_VALUE_INSERTED,
- SPINEL_PROP_MAC_ENERGY_SCAN_RESULT,
- (
- SPINEL_DATATYPE_UINT8_S // Channel
- SPINEL_DATATYPE_INT8_S // Rssi
- ),
- aResult->mChannel,
- aResult->mMaxRssi
- );
-
- if (error != OT_ERROR_NONE)
- {
- mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
- mUpdateChangedPropsTask.Post();
- }
+ SuccessOrExit(error = mEncoder.BeginFrame(
+ SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
+ SPINEL_CMD_PROP_VALUE_INSERTED,
+ SPINEL_PROP_MAC_SCAN_BEACON
+ ));
+ SuccessOrExit(error = mEncoder.WriteUint8(aResult->mChannel));
+ SuccessOrExit(error = mEncoder.WriteInt8(aResult->mMaxRssi));
+ SuccessOrExit(error = mEncoder.EndFrame());
}
else
{
- // We are finished with the scan, so send out
- // a property update indicating such.
- error = 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
- );
+ // We are finished with the scan, send an unsolicated
+ // scan state update.
+ mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
+ mUpdateChangedPropsTask.Post();
+ }
- // If we could not send the end of scan indicator message now (no
- // buffer space), we add the MAC_SCAN_STATE property to changed
- // property set so that the update is sent when buffer becomes
- // available.
- if (error != OT_ERROR_NONE)
- {
- mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
- }
+exit:
+
+ if (error != OT_ERROR_NONE)
+ {
+ mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
+ mUpdateChangedPropsTask.Post();
}
}
-
// ----------------------------------------------------------------------------
// MARK: Outbound Datagram Handling
// ----------------------------------------------------------------------------
@@ -4099,18 +3169,14 @@ void NcpBase::HandleDatagramFromStack(otMessage *aMessage)
bool isSecure = otMessageIsLinkSecurityEnabled(aMessage);
uint16_t length = otMessageGetLength(aMessage);
- SuccessOrExit(error = OutboundFrameBegin(header));
+ SuccessOrExit(error = mEncoder.BeginFrame(
+ header,
+ SPINEL_CMD_PROP_VALUE_IS,
+ isSecure ? SPINEL_PROP_STREAM_NET : SPINEL_PROP_STREAM_NET_INSECURE
+ ));
- SuccessOrExit(
- error = OutboundFrameFeedPacked(
- SPINEL_DATATYPE_COMMAND_PROP_S SPINEL_DATATYPE_UINT16_S,
- header,
- SPINEL_CMD_PROP_VALUE_IS,
- isSecure ? SPINEL_PROP_STREAM_NET : SPINEL_PROP_STREAM_NET_INSECURE,
- length
- ));
-
- SuccessOrExit(error = OutboundFrameFeedMessage(aMessage));
+ 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
@@ -4121,7 +3187,7 @@ void NcpBase::HandleDatagramFromStack(otMessage *aMessage)
// Append any metadata (rssi, lqi, channel, etc) here!
- SuccessOrExit(error = OutboundFrameSend());
+ SuccessOrExit(error = mEncoder.EndFrame());
exit:
diff --git a/src/ncp/ncp_base_radio.cpp b/src/ncp/ncp_base_radio.cpp
index 665b6efa7..ace98cade 100644
--- a/src/ncp/ncp_base_radio.cpp
+++ b/src/ncp/ncp_base_radio.cpp
@@ -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(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;
}
diff --git a/src/ncp/ncp_buffer.cpp b/src/ncp/ncp_buffer.cpp
index a33c8f178..8293797c2 100644
--- a/src/ncp/ncp_buffer.cpp
+++ b/src/ncp/ncp_buffer.cpp
@@ -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;
diff --git a/src/ncp/ncp_buffer.hpp b/src/ncp/ncp_buffer.hpp
index bc07c1939..2fdacf4bb 100644
--- a/src/ncp/ncp_buffer.hpp
+++ b/src/ncp/ncp_buffer.hpp
@@ -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);
diff --git a/src/ncp/spinel_encoder.cpp b/src/ncp/spinel_encoder.cpp
new file mode 100644
index 000000000..6ab6ce593
--- /dev/null
+++ b/src/ncp/spinel_encoder.cpp
@@ -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
+
+#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(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(aUtf8), static_cast(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(sizeof(buf))), error = OT_ERROR_NO_BUFS);
+
+ error = mNcpBuffer.InFrameFeedData(buf, static_cast(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(sizeof(buf))), error = OT_ERROR_NO_BUFS);
+
+ error = mNcpBuffer.InFrameFeedData(buf, static_cast(packedLen));
+
+exit:
+ return error;
+}
+
+} // namespace Ncp
+} // namespace ot
diff --git a/src/ncp/spinel_encoder.hpp b/src/ncp/spinel_encoder.hpp
new file mode 100644
index 000000000..c197e0532
--- /dev/null
+++ b/src/ncp/spinel_encoder.hpp
@@ -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
+
+#include
+#include
+#include
+
+#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(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(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(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()` 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_
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index ba17b2556..bc17680c5 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -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
diff --git a/tests/unit/test_spinel_encoder.cpp b/tests/unit/test_spinel_encoder.cpp
new file mode 100644
index 000000000..4ca952b6b
--- /dev/null
+++ b/tests/unit/test_spinel_encoder.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
+
+#include
+
+#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(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