[ncp] split ncp_base and rearrange declarations (#2045)

* split handlers into general, mtd, ftd and radio-only.
* move ChangedPropsSet into separate file.
* add Ncp namespace.
This commit is contained in:
Buke Po
2017-08-03 10:19:07 -07:00
committed by Jonathan Hui
parent 134e23695c
commit 818998e609
21 changed files with 7354 additions and 7068 deletions
@@ -58,12 +58,17 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ncp\changed_props_set.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_base.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_base_ftd.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_base_mtd.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_base_radio.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_buffer.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_spi.cpp" />
<ClCompile Include="..\..\src\ncp\spinel.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ncp\changed_props_set.hpp" />
<ClInclude Include="..\..\src\ncp\ncp_base.hpp" />
<ClInclude Include="..\..\src\ncp\ncp_buffer.hpp" />
<ClInclude Include="..\..\src\ncp\ncp_spi.hpp" />
@@ -72,4 +77,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
@@ -15,9 +15,21 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ncp\changed_props_set.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_base.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_base_ftd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_base_mtd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_base_radio.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_buffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -29,6 +41,9 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ncp\changed_props_set.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ncp\ncp_base.hpp">
<Filter>Header Files</Filter>
</ClInclude>
@@ -42,4 +57,4 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>
@@ -58,13 +58,18 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ncp\changed_props_set.cpp" />
<ClCompile Include="..\..\src\ncp\hdlc.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_base.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_base_ftd.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_base_mtd.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_base_radio.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_buffer.cpp" />
<ClCompile Include="..\..\src\ncp\ncp_uart.cpp" />
<ClCompile Include="..\..\src\ncp\spinel.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ncp\changed_props_set.hpp" />
<ClInclude Include="..\..\src\ncp\hdlc.hpp" />
<ClInclude Include="..\..\src\ncp\ncp_base.hpp" />
<ClInclude Include="..\..\src\ncp\ncp_buffer.hpp" />
@@ -15,12 +15,24 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ncp\changed_props_set.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\hdlc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_base.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_base_ftd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_base_mtd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_base_radio.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ncp\ncp_buffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -32,6 +44,9 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ncp\changed_props_set.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ncp\hdlc.hpp">
<Filter>Header Files</Filter>
</ClInclude>
+6
View File
@@ -173,12 +173,18 @@ typedef struct otNcpLegacyHandlers
/**
* This callback is invoked by the legacy stack to notify that a new
* legacy node did join the network.
*
* @param[in] aExtAddr A pointer to the extended address of the joined node.
*
*/
void otNcpHandleLegacyNodeDidJoin(const otExtAddress *aExtAddr);
/**
* This callback is invoked by the legacy stack to notify that the
* legacy ULA prefix has changed.
*
* param[in] aUlaPrefix A pointer to the received ULA prefix.
*
*/
void otNcpHandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix);
+6 -1
View File
@@ -61,8 +61,13 @@ libopenthread_ncp_ftd_a_CPPFLAGS = \
$(NULL)
COMMON_SOURCES = \
ncp_base.cpp \
changed_props_set.cpp \
changed_props_set.hpp \
ncp_base.hpp \
ncp_base.cpp \
ncp_base_mtd.cpp \
ncp_base_ftd.cpp \
ncp_base_radio.cpp \
ncp_buffer.cpp \
ncp_buffer.hpp \
spinel.c \
+167
View File
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2016-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 "changed_props_set.hpp"
namespace ot {
namespace Ncp {
// ----------------------------------------------------------------------------
// MARK: ChangedPropsSet class
// ----------------------------------------------------------------------------
// Defines the list of properties that can support unsolicited update.
//
// Note that {`SPINEL_PROP_LAST_STATUS`, `SPINEL_STATUS_RESET_UNKNOWN`} should be first entry to ensure that RESET is
// reported before any other property update.
//
// Since a `uint32_t` is used as bit-mask to track which entries are in the changed set, we should ensure that the
// number of entries in the list is always less than or equal to 32.
//
const ChangedPropsSet::Entry ChangedPropsSet::mSupportedProps[] =
{
// Spinel property Status (if prop is `LAST_STATUS`) IsFilterable?
{ SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_RESET_UNKNOWN, false }, // 0
{ SPINEL_PROP_STREAM_DEBUG, SPINEL_STATUS_OK, true }, // 1
{ SPINEL_PROP_IPV6_ADDRESS_TABLE, SPINEL_STATUS_OK, true }, // 2
{ SPINEL_PROP_NET_ROLE, SPINEL_STATUS_OK, true }, // 3
{ SPINEL_PROP_IPV6_LL_ADDR, SPINEL_STATUS_OK, true }, // 4
{ SPINEL_PROP_IPV6_ML_ADDR, SPINEL_STATUS_OK, true }, // 5
{ SPINEL_PROP_NET_PARTITION_ID, SPINEL_STATUS_OK, true }, // 6
{ SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, SPINEL_STATUS_OK, true }, // 7
{ SPINEL_PROP_THREAD_LEADER_NETWORK_DATA, SPINEL_STATUS_OK, true }, // 8
{ SPINEL_PROP_THREAD_CHILD_TABLE, SPINEL_STATUS_OK, true }, // 9
{ SPINEL_PROP_THREAD_ON_MESH_NETS, SPINEL_STATUS_OK, true }, // 10
{ SPINEL_PROP_THREAD_OFF_MESH_ROUTES, SPINEL_STATUS_OK, true }, // 11
{ SPINEL_PROP_NET_STACK_UP, SPINEL_STATUS_OK, true }, // 12
{ SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING, SPINEL_STATUS_OK, true }, // 13
{ SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_NOMEM, true }, // 14
{ SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_DROPPED, true }, // 15
#if OPENTHREAD_ENABLE_JAM_DETECTION
{ SPINEL_PROP_JAM_DETECTED, SPINEL_STATUS_OK, true }, // 16
#endif
#if OPENTHREAD_ENABLE_LEGACY
{ SPINEL_PROP_NEST_LEGACY_ULA_PREFIX, SPINEL_STATUS_OK, true }, // 17
{ SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED, SPINEL_STATUS_OK, true }, // 18
#endif
{ SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_FAILURE, false }, // 19
{ SPINEL_PROP_MAC_SCAN_STATE, SPINEL_STATUS_OK, false }, // 20
};
uint8_t ChangedPropsSet::GetNumEntries(void) const
{
return (sizeof(mSupportedProps) / sizeof(mSupportedProps[0]));
}
void ChangedPropsSet::Add(spinel_prop_key_t aPropKey, spinel_status_t aStatus)
{
uint8_t numEntries;
const Entry *entry;
entry = GetSupportedEntries(numEntries);
for (uint8_t index = 0; index < numEntries; index++, entry++)
{
if ((entry->mPropKey == aPropKey) && (entry->mStatus == aStatus))
{
if (!IsEntryFiltered(index))
{
SetBit(mChangedSet, index);
}
break;
}
}
}
otError ChangedPropsSet::EnablePropertyFilter(spinel_prop_key_t aPropKey, bool aEnable)
{
uint8_t numEntries;
const Entry *entry;
bool didFind = false;
entry = GetSupportedEntries(numEntries);
for (uint8_t index = 0; index < numEntries; index++, entry++)
{
if (entry->mFilterable && (entry->mPropKey == aPropKey))
{
if (aEnable)
{
SetBit(mFilterSet, index);
// If filter is enabled for a property, the `mChangedSet` is cleared
// for the same property so to ensure a pending update is also filtered.
ClearBit(mChangedSet, index);
}
else
{
ClearBit(mFilterSet, index);
}
didFind = true;
// Continue the search only if the prop key is `LAST_STATUS`, as
// we have multiple filterable `LAST_STATUS` entries in the table
// with different error status (DROPPED and NOMEM).
if (aPropKey != SPINEL_PROP_LAST_STATUS)
{
break;
}
}
}
return didFind ? OT_ERROR_NONE : OT_ERROR_INVALID_ARGS;
}
bool ChangedPropsSet::IsPropertyFiltered(spinel_prop_key_t aPropKey) const
{
bool isFiltered = false;
uint8_t numEntries;
const Entry *entry;
entry = GetSupportedEntries(numEntries);
for (uint8_t index = 0; index < numEntries; index++, entry++)
{
if (entry->mFilterable && (entry->mPropKey == aPropKey))
{
isFiltered = IsEntryFiltered(index);
break;
}
}
return isFiltered;
}
} // namespace Ncp
} // namespace ot
+208
View File
@@ -0,0 +1,208 @@
/*
* Copyright (c) 2016-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 definitions a spinel interface to the OpenThread stack.
*/
#ifndef CHANGED_PROPS_SET_HPP_
#define CHANGED_PROPS_SET_HPP_
#include <openthread/types.h>
#include "spinel.h"
namespace ot {
namespace Ncp {
/**
* Defines a class to track a set of property/status changes that require update to host. The properties that can
* be added to this set must support sending unsolicited updates. This class also provides mechanism for user
* to block certain filterable properties disallowing the unsolicited update from them.
*
*/
class ChangedPropsSet
{
public:
/**
* Defines an entry in the set/list.
*
*/
struct Entry
{
spinel_prop_key_t mPropKey; ///< The spinel property key.
spinel_status_t mStatus; ///< The spinel status (used only if prop key is `LAST_STATUS`).
bool mFilterable; ///< Indicates whether the entry can be filtered
};
/**
* This constructor initializes the set.
*
*/
ChangedPropsSet(void):
mChangedSet(0),
mFilterSet(0)
{ }
/**
* This method clears the set.
*
*/
void Clear(void) { mChangedSet = 0; }
/**
* This method indicates if the set is empty or not.
*
* @returns TRUE if the set if empty, FALSE otherwise.
*
*/
bool IsEmpty(void) const { return (mChangedSet == 0); }
/**
* This method adds a property to the set. The property added must be in the list of supported properties
* capable of sending unsolicited update, otherwise the input is ignored.
*
* Note that if the property is already in the set, adding it again does not change the set.
*
* @param[in] aPropKey The spinel property key to be added to the set
*
*/
void AddProperty(spinel_prop_key_t aPropKey) { Add(aPropKey, SPINEL_STATUS_OK); }
/**
* This method adds a `LAST_STATUS` update to the set. The update must be in list of supported entries.
*
* @param[in] aStatus The spinel status update to be added to set.
*
*/
void AddLastStatus(spinel_status_t aStatus) { Add(SPINEL_PROP_LAST_STATUS, aStatus); }
/**
* This method returns a pointer to array of entries of supported property/status updates. The list includes
* all properties that can generate unsolicited update.
*
* @param[out] aNumEntries A reference to output the number of entries in the list.
*
* @returns A pointer to the supported entries array.
*
*/
const Entry *GetSupportedEntries(uint8_t &aNumEntries) const {
aNumEntries = GetNumEntries();
return &mSupportedProps[0];
}
/**
* This method returns a pointer to the entry associated with a given index.
*
* @param[in] aIndex The index to an entry.
*
* @returns A pointer to the entry associated with @p aIndex, or NULL if the index is beyond end of array.
*
*/
const Entry *GetEntry(uint8_t aIndex) const {
return (aIndex < GetNumEntries()) ? &mSupportedProps[aIndex] : NULL;
}
/**
* This method indicates if the entry associated with an index is in the set (i.e., it has been changed and
* requires an unsolicited update).
*
* @param[in] aIndex The index to an entry.
*
* @returns TRUE if the entry is in the set, FALSE otherwise.
*
*/
bool IsEntryChanged(uint8_t aIndex) const { return IsBitSet(mChangedSet, aIndex); }
/**
* This method removes an entry associated with an index in the set.
*
* Note that if the property/entry is not in the set, removing it simply does nothing.
*
* @param[in] aIndex Index of entry to be removed.
*
*/
void RemoveEntry(uint8_t aIndex) { ClearBit(mChangedSet, aIndex); }
/**
* This method enables/disables filtering of a given property.
*
* @param[in] aPropKey The property key to filter.
* @param[in] aEnable TRUE to enable filtering, FALSE to disable.
*
* @retval OT_ERROR_NONE Filter state for given property updated successfully.
* @retval OT_ERROR_INVALID_ARGS The given property is not valid (i.e., not capable of unsolicited update).
*
*/
otError EnablePropertyFilter(spinel_prop_key_t aPropKey, bool aEnable);
/**
* This method determines whether filtering is enabled for an entry associated with an index.
*
* @param[in] aIndex Index of entry to be checked.
*
* @returns TRUE if the filter is enabled for the given entry, FALSE otherwise.
*
*/
bool IsEntryFiltered(uint8_t aIndex) const { return IsBitSet(mFilterSet, aIndex); }
/**
* This method determines whether filtering is enabled for a given property key.
*
* @param[in] aPropKey The property key to check.
*
* @returns TRUE if the filter is enabled for the given property, FALSE if the property is not filtered or if
* it is not filterable.
*
*/
bool IsPropertyFiltered(spinel_prop_key_t aPropKey) const;
/**
* This method clears the filter.
*
*/
void ClearFilter(void) { mFilterSet = 0; }
private:
uint8_t GetNumEntries(void) const;
void Add(spinel_prop_key_t aPropKey, spinel_status_t aStatus);
static void SetBit (uint32_t &aBitset, uint8_t aBitIndex) { aBitset |= (1U << aBitIndex); }
static void ClearBit(uint32_t &aBitset, uint8_t aBitIndex) { aBitset &= ~(1U << aBitIndex); }
static bool IsBitSet(uint32_t aBitset, uint8_t aBitIndex) { return (aBitset & (1U << aBitIndex)) != 0; }
static const Entry mSupportedProps[];
uint32_t mChangedSet;
uint32_t mFilterSet;
};
} // namespace Ncp
} // namespace ot
#endif // CHANGED_PROPS_SET_HPP
+737 -6607
View File
File diff suppressed because it is too large Load Diff
+331 -453
View File
@@ -35,17 +35,23 @@
#include <openthread/config.h>
#if OPENTHREAD_MTD || OPENTHREAD_FTD
#include <openthread/ip6.h>
#else
#include <openthread/platform/radio.h>
#endif
#include <openthread/message.h>
#include <openthread/ncp.h>
#include <openthread/types.h>
#include "openthread-core-config.h"
#include "spinel.h"
#include "changed_props_set.hpp"
#include "common/tasklet.hpp"
#include "ncp/ncp_buffer.hpp"
#include "spinel.h"
namespace ot {
namespace Ncp {
#define NCP_COMMAND_HANDLER(name) \
otError CommandHandler_##name( \
@@ -101,13 +107,75 @@ public:
/**
* This static method returns the pointer to the single NCP instance.
*
@returns Pointer to the single NCP instance.
* @returns Pointer to the single NCP instance.
*
*/
static NcpBase *GetNcpInstance(void);
protected:
/**
* This method sends data to host via specifiec stream.
*
*
* @param[in] aStreamId A numeric identifier for the stream to write to.
* If set to '0', will default to the debug stream.
* @param[in] aDataPtr A pointer to the data to send on the stream.
* If aDataLen is non-zero, this param MUST NOT be NULL.
* @param[in] aDataLen The number of bytes of data from aDataPtr to send.
*
* @retval OT_ERROR_NONE The data was queued for delivery to the host.
* @retval OT_ERROR_BUSY There are not enough resources to complete this
* request. This is usually a temporary condition.
* @retval OT_ERROR_INVALID_ARGS The given aStreamId was invalid.
*
*/
otError StreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLen);
#if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
/**
* This method registers peek/poke delegate functions with NCP module.
*
* @param[in] aAllowPeekDelegate Delegate function pointer for peek operation.
* @param[in] aAllowPokeDelegate Delegate function pointer for poke operation.
*
* @retval OT_ERROR_NONE Successfully registered delegate functions.
* @retval OT_ERROR_DISABLED_FEATURE Peek/Poke feature is disabled (by a build-time configuration option).
*
*/
void RegisterPeekPokeDelagates(otNcpDelegateAllowPeekPoke aAllowPeekDelegate,
otNcpDelegateAllowPeekPoke aAllowPokeDelegate);
#endif
#if OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_ENABLE_LEGACY
/**
* This callback is invoked by the legacy stack to notify that a new
* legacy node did join the network.
*
* @param[in] aExtAddr The extended address of the joined node.
*
*/
void HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr);
/**
* This callback is invoked by the legacy stack to notify that the
* legacy ULA prefix has changed.
*
* param[in] aUlaPrefix The changed ULA prefix.
*
*/
void HandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix);
/**
* This method registers a set of legacy handlers with NCP.
*
* @param[in] aHandlers A pointer to a handler struct.
*
*/
void RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers);
#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
protected:
/**
* This method is called to start a new outbound frame.
*
@@ -151,7 +219,8 @@ protected:
/**
* 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.
* 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.
@@ -160,13 +229,10 @@ protected:
otError OutboundFrameEnd(void);
/**
* This method is called by the framer whenever a framing error
* is detected.
* This method is called by the framer whenever a framing error is detected.
*/
void IncrementFrameErrorCounter(void);
protected:
/**
* Called by the subclass to indicate when a frame has been received.
*/
@@ -183,95 +249,6 @@ protected:
bool ShouldDeferHostSend(void);
private:
otError OutboundFrameSend(void);
NcpFrameBuffer::FrameTag GetLastOutboundFrameTag(void);
#if OPENTHREAD_ENABLE_TMF_PROXY && OPENTHREAD_FTD
static void HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort, void *aContext);
void HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort);
#endif // OPENTHREAD_ENABLE_TMF_PROXY && OPENTHREAD_FTD
static void HandleFrameRemovedFromNcpBuffer(void *aContext, NcpFrameBuffer::FrameTag aFrameTag,
NcpFrameBuffer::Priority aPriority, NcpFrameBuffer *aNcpBuffer);
void HandleFrameRemovedFromNcpBuffer(NcpFrameBuffer::FrameTag aFrameTag);
static void HandleDatagramFromStack(otMessage *aMessage, void *aContext);
void HandleDatagramFromStack(otMessage *aMessage);
static void HandleRawFrame(const otRadioFrame *aFrame, void *aContext);
void HandleRawFrame(const otRadioFrame *aFrame);
static void HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aContext);
void HandleActiveScanResult(otActiveScanResult *aResult);
static void HandleEnergyScanResult_Jump(otEnergyScanResult *aResult, void *aContext);
void HandleEnergyScanResult(otEnergyScanResult *aResult);
static void HandleJamStateChange_Jump(bool aJamState, void *aContext);
void HandleJamStateChange(bool aJamState);
static void UpdateChangedProps(Tasklet &aTasklet);
void UpdateChangedProps(void);
void ProcessThreadChangedFlags(void);
static void SendDoneTask(void *aContext);
void SendDoneTask(void);
#if OPENTHREAD_ENABLE_RAW_LINK_API
static void LinkRawReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
void LinkRawReceiveDone(otRadioFrame *aFrame, otError aError);
static void LinkRawTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
void LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
static void LinkRawEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi);
void LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi);
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
static void HandleNetifStateChanged(uint32_t aFlags, void *aContext);
private:
otError OutboundFrameFeedPacked(const char *aPackFormat, ...);
otError OutboundFrameFeedVPacked(const char *aPackFormat, va_list aArgs);
private:
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);
otError HandleCommandPropertySet(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen);
otError HandleCommandPropertyInsert(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen);
otError HandleCommandPropertyRemove(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen);
otError SendLastStatus(uint8_t aHeader, spinel_status_t aLastStatus);
otError GetPropertyHandler_ChannelMaskHelper(uint8_t aHeader, spinel_prop_key_t aKey, uint32_t channel_mask);
private:
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);
private:
typedef otError(NcpBase::*CommandHandlerType)(uint8_t aHeader, unsigned int aCommand, const uint8_t *aArgPtr,
uint16_t aArgLen);
@@ -310,13 +287,88 @@ private:
SetPropertyHandlerType mHandler;
};
static const CommandHandlerEntry mCommandHandlerTable[];
static const GetPropertyHandlerEntry mGetPropertyHandlerTable[];
static const SetPropertyHandlerEntry mSetPropertyHandlerTable[];
static const InsertPropertyHandlerEntry mInsertPropertyHandlerTable[];
static const RemovePropertyHandlerEntry mRemovePropertyHandlerTable[];
otError OutboundFrameSend(void);
// Command Handlers
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);
otError HandleCommandPropertySet(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen);
otError HandleCommandPropertyInsert(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen);
otError HandleCommandPropertyRemove(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen);
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);
void UpdateChangedProps(void);
static void HandleFrameRemovedFromNcpBuffer(void *aContext, NcpFrameBuffer::FrameTag aFrameTag,
NcpFrameBuffer::Priority aPriority, NcpFrameBuffer *aNcpBuffer);
void HandleFrameRemovedFromNcpBuffer(NcpFrameBuffer::FrameTag aFrameTag);
#if OPENTHREAD_ENABLE_RAW_LINK_API
static void LinkRawReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
void LinkRawReceiveDone(otRadioFrame *aFrame, otError aError);
static void LinkRawTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
void LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
static void LinkRawEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi);
void LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi);
static void HandleRawFrame(const otRadioFrame *aFrame, void *aContext);
void HandleRawFrame(const otRadioFrame *aFrame);
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
#if OPENTHREAD_MTD || OPENTHREAD_FTD
static void HandleNetifStateChanged(uint32_t aFlags, void *aContext);
void ProcessThreadChangedFlags(void);
static void HandleDatagramFromStack(otMessage *aMessage, void *aContext);
void HandleDatagramFromStack(otMessage *aMessage);
static void HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aContext);
void HandleActiveScanResult(otActiveScanResult *aResult);
static void HandleEnergyScanResult_Jump(otEnergyScanResult *aResult, void *aContext);
void HandleEnergyScanResult(otEnergyScanResult *aResult);
static void HandleJamStateChange_Jump(bool aJamState, void *aContext);
void HandleJamStateChange(bool aJamState);
static void SendDoneTask(void *aContext);
void SendDoneTask(void);
otError GetPropertyHandler_ChannelMaskHelper(uint8_t aHeader, spinel_prop_key_t aKey, uint32_t channel_mask);
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
static void HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort, void *aContext);
void HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort);
#endif // OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
NCP_COMMAND_HANDLER(NOOP);
NCP_COMMAND_HANDLER(RESET);
@@ -324,66 +376,138 @@ private:
NCP_COMMAND_HANDLER(PROP_VALUE_SET);
NCP_COMMAND_HANDLER(PROP_VALUE_INSERT);
NCP_COMMAND_HANDLER(PROP_VALUE_REMOVE);
NCP_COMMAND_HANDLER(NET_SAVE);
NCP_COMMAND_HANDLER(NET_CLEAR);
NCP_COMMAND_HANDLER(NET_RECALL);
#if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
NCP_COMMAND_HANDLER(PEEK);
NCP_COMMAND_HANDLER(POKE);
#endif
// Property Get Handlers
NCP_GET_PROP_HANDLER(LAST_STATUS);
NCP_GET_PROP_HANDLER(PROTOCOL_VERSION);
NCP_GET_PROP_HANDLER(INTERFACE_TYPE);
NCP_GET_PROP_HANDLER(VENDOR_ID);
NCP_GET_PROP_HANDLER(CAPS);
NCP_GET_PROP_HANDLER(DEBUG_TEST_ASSERT);
NCP_GET_PROP_HANDLER(DEBUG_NCP_LOG_LEVEL);
NCP_SET_PROP_HANDLER(DEBUG_NCP_LOG_LEVEL);
NCP_GET_PROP_HANDLER(NCP_VERSION);
NCP_GET_PROP_HANDLER(INTERFACE_COUNT);
NCP_GET_PROP_HANDLER(POWER_STATE);
NCP_SET_PROP_HANDLER(POWER_STATE);
NCP_GET_PROP_HANDLER(HWADDR);
NCP_GET_PROP_HANDLER(LOCK);
NCP_GET_PROP_HANDLER(HOST_POWER_STATE);
NCP_SET_PROP_HANDLER(HOST_POWER_STATE);
NCP_GET_PROP_HANDLER(UNSOL_UPDATE_FILTER);
NCP_GET_PROP_HANDLER(UNSOL_UPDATE_LIST);
NCP_GET_PROP_HANDLER(PHY_RX_SENSITIVITY);
NCP_GET_PROP_HANDLER(PHY_TX_POWER);
NCP_SET_PROP_HANDLER(PHY_TX_POWER);
NCP_SET_PROP_HANDLER(PHY_CHAN);
NCP_GET_PROP_HANDLER(PHY_CHAN);
NCP_GET_PROP_HANDLER(MAC_15_4_PANID);
NCP_SET_PROP_HANDLER(MAC_15_4_PANID);
NCP_GET_PROP_HANDLER(MAC_15_4_LADDR);
NCP_SET_PROP_HANDLER(MAC_15_4_LADDR);
NCP_GET_PROP_HANDLER(MAC_15_4_SADDR);
#if OPENTHREAD_ENABLE_RAW_LINK_API
NCP_SET_PROP_HANDLER(MAC_15_4_SADDR);
#endif
NCP_GET_PROP_HANDLER(MAC_PROMISCUOUS_MODE);
NCP_SET_PROP_HANDLER(MAC_PROMISCUOUS_MODE);
NCP_GET_PROP_HANDLER(MAC_RAW_STREAM_ENABLED);
NCP_SET_PROP_HANDLER(MAC_RAW_STREAM_ENABLED);
NCP_GET_PROP_HANDLER(MAC_DATA_POLL_PERIOD);
NCP_SET_PROP_HANDLER(MAC_DATA_POLL_PERIOD);
NCP_SET_PROP_HANDLER(UNSOL_UPDATE_FILTER);
NCP_INSERT_PROP_HANDLER(UNSOL_UPDATE_FILTER);
NCP_REMOVE_PROP_HANDLER(UNSOL_UPDATE_FILTER);
#if OPENTHREAD_ENABLE_RAW_LINK_API
NCP_SET_PROP_HANDLER(MAC_SRC_MATCH_ENABLED);
NCP_SET_PROP_HANDLER(MAC_SRC_MATCH_SHORT_ADDRESSES);
NCP_INSERT_PROP_HANDLER(MAC_SRC_MATCH_SHORT_ADDRESSES);
NCP_REMOVE_PROP_HANDLER(MAC_SRC_MATCH_SHORT_ADDRESSES);
NCP_SET_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
NCP_INSERT_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
NCP_REMOVE_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
NCP_GET_PROP_HANDLER(PHY_ENABLED);
NCP_SET_PROP_HANDLER(PHY_ENABLED);
NCP_SET_PROP_HANDLER(STREAM_RAW);
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
// FTD or MTD handlers.
#if OPENTHREAD_MTD || OPENTHREAD_FTD
NCP_COMMAND_HANDLER(NET_SAVE);
NCP_COMMAND_HANDLER(NET_CLEAR);
NCP_COMMAND_HANDLER(NET_RECALL);
NCP_GET_PROP_HANDLER(MAC_EXTENDED_ADDR);
NCP_GET_PROP_HANDLER(MAC_SCAN_MASK);
NCP_SET_PROP_HANDLER(MAC_SCAN_MASK);
NCP_GET_PROP_HANDLER(MAC_SCAN_PERIOD);
NCP_SET_PROP_HANDLER(MAC_SCAN_PERIOD);
NCP_GET_PROP_HANDLER(MAC_SCAN_STATE);
NCP_SET_PROP_HANDLER(MAC_SCAN_STATE);
NCP_GET_PROP_HANDLER(PHY_FREQ);
NCP_GET_PROP_HANDLER(PHY_CHAN_SUPPORTED);
NCP_GET_PROP_HANDLER(PHY_CHAN);
NCP_GET_PROP_HANDLER(PHY_RSSI);
NCP_GET_PROP_HANDLER(PHY_TX_POWER);
NCP_GET_PROP_HANDLER(PHY_RX_SENSITIVITY);
NCP_GET_PROP_HANDLER(MAC_SCAN_STATE);
NCP_GET_PROP_HANDLER(MAC_15_4_PANID);
NCP_GET_PROP_HANDLER(MAC_15_4_LADDR);
NCP_GET_PROP_HANDLER(MAC_15_4_SADDR);
NCP_GET_PROP_HANDLER(MAC_RAW_STREAM_ENABLED);
NCP_GET_PROP_HANDLER(MAC_EXTENDED_ADDR);
NCP_GET_PROP_HANDLER(MAC_DATA_POLL_PERIOD);
NCP_GET_PROP_HANDLER(NET_SAVED);
NCP_GET_PROP_HANDLER(NET_IF_UP);
NCP_SET_PROP_HANDLER(NET_IF_UP);
NCP_GET_PROP_HANDLER(NET_STACK_UP);
NCP_SET_PROP_HANDLER(NET_STACK_UP);
NCP_GET_PROP_HANDLER(NET_ROLE);
NCP_SET_PROP_HANDLER(NET_ROLE);
NCP_GET_PROP_HANDLER(NET_NETWORK_NAME);
NCP_SET_PROP_HANDLER(NET_NETWORK_NAME);
NCP_GET_PROP_HANDLER(NET_XPANID);
NCP_SET_PROP_HANDLER(NET_XPANID);
NCP_GET_PROP_HANDLER(NET_MASTER_KEY);
NCP_SET_PROP_HANDLER(NET_MASTER_KEY);
NCP_GET_PROP_HANDLER(NET_KEY_SEQUENCE_COUNTER);
NCP_SET_PROP_HANDLER(NET_KEY_SEQUENCE_COUNTER);
NCP_GET_PROP_HANDLER(NET_PARTITION_ID);
NCP_GET_PROP_HANDLER(NET_KEY_SWITCH_GUARDTIME);
NCP_SET_PROP_HANDLER(NET_KEY_SWITCH_GUARDTIME);
NCP_GET_PROP_HANDLER(THREAD_LEADER);
NCP_GET_PROP_HANDLER(IPV6_ML_PREFIX);
NCP_SET_PROP_HANDLER(IPV6_ML_PREFIX);
NCP_GET_PROP_HANDLER(IPV6_ML_ADDR);
NCP_GET_PROP_HANDLER(IPV6_LL_ADDR);
NCP_GET_PROP_HANDLER(IPV6_ADDRESS_TABLE);
NCP_INSERT_PROP_HANDLER(IPV6_ADDRESS_TABLE);
NCP_REMOVE_PROP_HANDLER(IPV6_ADDRESS_TABLE);
NCP_GET_PROP_HANDLER(IPV6_ROUTE_TABLE);
NCP_GET_PROP_HANDLER(IPV6_ICMP_PING_OFFLOAD);
NCP_SET_PROP_HANDLER(IPV6_ICMP_PING_OFFLOAD);
NCP_GET_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
NCP_INSERT_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
NCP_REMOVE_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
NCP_GET_PROP_HANDLER(THREAD_RLOC16_DEBUG_PASSTHRU);
NCP_SET_PROP_HANDLER(THREAD_RLOC16_DEBUG_PASSTHRU);
NCP_GET_PROP_HANDLER(THREAD_OFF_MESH_ROUTES);
NCP_GET_PROP_HANDLER(STREAM_NET);
NCP_GET_PROP_HANDLER(MAC_SCAN_MASK);
NCP_GET_PROP_HANDLER(MAC_SCAN_PERIOD);
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_INSERT_PROP_HANDLER(THREAD_OFF_MESH_ROUTES);
NCP_REMOVE_PROP_HANDLER(THREAD_OFF_MESH_ROUTES);
#endif
NCP_GET_PROP_HANDLER(THREAD_ON_MESH_NETS);
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_INSERT_PROP_HANDLER(THREAD_ON_MESH_NETS);
NCP_REMOVE_PROP_HANDLER(THREAD_ON_MESH_NETS);
#endif
NCP_GET_PROP_HANDLER(THREAD_LEADER_ADDR);
NCP_GET_PROP_HANDLER(THREAD_PARENT);
NCP_GET_PROP_HANDLER(THREAD_NEIGHBOR_TABLE);
@@ -397,386 +521,134 @@ private:
NCP_GET_PROP_HANDLER(THREAD_STABLE_NETWORK_DATA_VERSION);
NCP_GET_PROP_HANDLER(THREAD_LEADER_NETWORK_DATA);
NCP_GET_PROP_HANDLER(THREAD_STABLE_LEADER_NETWORK_DATA);
NCP_GET_PROP_HANDLER(MAC_PROMISCUOUS_MODE);
NCP_GET_PROP_HANDLER(THREAD_ASSISTING_PORTS);
NCP_SET_PROP_HANDLER(THREAD_ASSISTING_PORTS);
NCP_INSERT_PROP_HANDLER(THREAD_ASSISTING_PORTS);
NCP_REMOVE_PROP_HANDLER(THREAD_ASSISTING_PORTS);
NCP_GET_PROP_HANDLER(THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_SET_PROP_HANDLER(THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
#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(MSG_BUFFER_COUNTERS);
#if OPENTHREAD_ENABLE_MAC_FILTER
NCP_GET_PROP_HANDLER(MAC_WHITELIST);
NCP_GET_PROP_HANDLER(MAC_WHITELIST_ENABLED);
NCP_GET_PROP_HANDLER(MAC_BLACKLIST);
NCP_SET_PROP_HANDLER(MAC_WHITELIST_ENABLED);
NCP_GET_PROP_HANDLER(MAC_WHITELIST);
NCP_SET_PROP_HANDLER(MAC_WHITELIST);
NCP_INSERT_PROP_HANDLER(MAC_WHITELIST);
NCP_REMOVE_PROP_HANDLER(MAC_WHITELIST);
NCP_INSERT_PROP_HANDLER(MAC_BLACKLIST);
NCP_REMOVE_PROP_HANDLER(MAC_BLACKLIST);
NCP_GET_PROP_HANDLER(MAC_BLACKLIST_ENABLED);
NCP_SET_PROP_HANDLER(MAC_BLACKLIST_ENABLED);
NCP_SET_PROP_HANDLER(MAC_BLACKLIST);
NCP_GET_PROP_HANDLER(MAC_BLACKLIST);
NCP_GET_PROP_HANDLER(MAC_FIXED_RSS);
NCP_SET_PROP_HANDLER(MAC_FIXED_RSS);
NCP_INSERT_PROP_HANDLER(MAC_FIXED_RSS);
NCP_REMOVE_PROP_HANDLER(MAC_FIXED_RSS);
#endif
NCP_GET_PROP_HANDLER(THREAD_MODE);
NCP_SET_PROP_HANDLER(THREAD_MODE);
NCP_GET_PROP_HANDLER(THREAD_CHILD_TIMEOUT);
NCP_GET_PROP_HANDLER(THREAD_RLOC16);
NCP_GET_PROP_HANDLER(THREAD_ON_MESH_NETS);
NCP_GET_PROP_HANDLER(NET_REQUIRE_JOIN_EXISTING);
NCP_GET_PROP_HANDLER(DEBUG_TEST_ASSERT);
NCP_GET_PROP_HANDLER(DEBUG_NCP_LOG_LEVEL);
NCP_SET_PROP_HANDLER(NET_REQUIRE_JOIN_EXISTING);
NCP_GET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_JOINER_FLAG);
NCP_SET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_JOINER_FLAG);
NCP_GET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_ENABLE_FILTERING);
NCP_SET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_ENABLE_FILTERING);
NCP_GET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_PANID);
#if OPENTHREAD_FTD
NCP_GET_PROP_HANDLER(THREAD_CHILD_TABLE);
NCP_GET_PROP_HANDLER(THREAD_LOCAL_LEADER_WEIGHT);
NCP_GET_PROP_HANDLER(THREAD_ROUTER_ROLE_ENABLED);
NCP_GET_PROP_HANDLER(NET_PSKC);
NCP_GET_PROP_HANDLER(THREAD_CHILD_COUNT_MAX);
NCP_GET_PROP_HANDLER(THREAD_ROUTER_UPGRADE_THRESHOLD);
NCP_GET_PROP_HANDLER(THREAD_ROUTER_DOWNGRADE_THRESHOLD);
NCP_GET_PROP_HANDLER(THREAD_ROUTER_SELECTION_JITTER);
NCP_GET_PROP_HANDLER(THREAD_CONTEXT_REUSE_DELAY);
NCP_GET_PROP_HANDLER(THREAD_NETWORK_ID_TIMEOUT);
#endif // #if OPENTHREAD_FTD
NCP_SET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_PANID);
#if OPENTHREAD_ENABLE_COMMISSIONER
NCP_GET_PROP_HANDLER(THREAD_COMMISSIONER_ENABLED);
NCP_SET_PROP_HANDLER(THREAD_COMMISSIONER_ENABLED);
NCP_INSERT_PROP_HANDLER(THREAD_JOINERS);
#endif
NCP_GET_PROP_HANDLER(THREAD_TMF_PROXY_ENABLED);
#if OPENTHREAD_ENABLE_JAM_DETECTION
NCP_GET_PROP_HANDLER(JAM_DETECT_ENABLE);
NCP_GET_PROP_HANDLER(JAM_DETECTED);
NCP_GET_PROP_HANDLER(JAM_DETECT_ENABLE);
NCP_SET_PROP_HANDLER(JAM_DETECT_ENABLE);
NCP_GET_PROP_HANDLER(JAM_DETECT_RSSI_THRESHOLD);
NCP_SET_PROP_HANDLER(JAM_DETECT_RSSI_THRESHOLD);
NCP_GET_PROP_HANDLER(JAM_DETECT_WINDOW);
NCP_SET_PROP_HANDLER(JAM_DETECT_WINDOW);
NCP_GET_PROP_HANDLER(JAM_DETECT_BUSY);
NCP_SET_PROP_HANDLER(JAM_DETECT_BUSY);
NCP_GET_PROP_HANDLER(JAM_DETECT_HISTORY_BITMAP);
#endif
#if OPENTHREAD_ENABLE_LEGACY
NCP_GET_PROP_HANDLER(NEST_LEGACY_ULA_PREFIX);
NCP_SET_PROP_HANDLER(NEST_LEGACY_ULA_PREFIX);
NCP_GET_PROP_HANDLER(NEST_LEGACY_LAST_NODE_JOINED);
#endif
// Property Set Handlers
NCP_SET_PROP_HANDLER(POWER_STATE);
NCP_SET_PROP_HANDLER(HOST_POWER_STATE);
NCP_SET_PROP_HANDLER(PHY_TX_POWER);
NCP_SET_PROP_HANDLER(PHY_CHAN);
NCP_SET_PROP_HANDLER(UNSOL_UPDATE_FILTER);
NCP_SET_PROP_HANDLER(MAC_SCAN_MASK);
NCP_SET_PROP_HANDLER(MAC_SCAN_STATE);
NCP_SET_PROP_HANDLER(MAC_15_4_PANID);
NCP_SET_PROP_HANDLER(MAC_15_4_LADDR);
NCP_SET_PROP_HANDLER(MAC_DATA_POLL_PERIOD);
NCP_SET_PROP_HANDLER(MAC_RAW_STREAM_ENABLED);
#if OPENTHREAD_ENABLE_RAW_LINK_API
NCP_SET_PROP_HANDLER(MAC_15_4_SADDR);
NCP_SET_PROP_HANDLER(STREAM_RAW);
#endif
NCP_SET_PROP_HANDLER(NET_IF_UP);
NCP_SET_PROP_HANDLER(NET_STACK_UP);
NCP_SET_PROP_HANDLER(NET_ROLE);
NCP_SET_PROP_HANDLER(NET_NETWORK_NAME);
NCP_SET_PROP_HANDLER(NET_XPANID);
NCP_SET_PROP_HANDLER(NET_MASTER_KEY);
NCP_SET_PROP_HANDLER(NET_KEY_SEQUENCE_COUNTER);
NCP_SET_PROP_HANDLER(NET_KEY_SWITCH_GUARDTIME);
NCP_SET_PROP_HANDLER(STREAM_NET_INSECURE);
NCP_SET_PROP_HANDLER(STREAM_NET);
NCP_SET_PROP_HANDLER(IPV6_ML_PREFIX);
NCP_SET_PROP_HANDLER(IPV6_ICMP_PING_OFFLOAD);
NCP_SET_PROP_HANDLER(THREAD_RLOC16_DEBUG_PASSTHRU);
NCP_SET_PROP_HANDLER(THREAD_TMF_PROXY_STREAM);
#if OPENTHREAD_ENABLE_RAW_LINK_API
NCP_SET_PROP_HANDLER(PHY_ENABLED);
#endif
NCP_SET_PROP_HANDLER(MAC_PROMISCUOUS_MODE);
NCP_SET_PROP_HANDLER(MAC_SCAN_PERIOD);
#if OPENTHREAD_ENABLE_MAC_FILTER
NCP_SET_PROP_HANDLER(MAC_WHITELIST);
NCP_SET_PROP_HANDLER(MAC_WHITELIST_ENABLED);
NCP_SET_PROP_HANDLER(MAC_BLACKLIST);
NCP_SET_PROP_HANDLER(MAC_BLACKLIST_ENABLED);
NCP_SET_PROP_HANDLER(MAC_FIXED_RSS);
#endif
#if OPENTHREAD_ENABLE_RAW_LINK_API
NCP_SET_PROP_HANDLER(MAC_SRC_MATCH_ENABLED);
NCP_SET_PROP_HANDLER(MAC_SRC_MATCH_SHORT_ADDRESSES);
NCP_SET_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
#endif
NCP_SET_PROP_HANDLER(THREAD_MODE);
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_SET_PROP_HANDLER(THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
#endif
#if OPENTHREAD_FTD
NCP_SET_PROP_HANDLER(NET_PSKC);
NCP_SET_PROP_HANDLER(THREAD_LOCAL_LEADER_WEIGHT);
NCP_SET_PROP_HANDLER(THREAD_CHILD_COUNT_MAX);
NCP_SET_PROP_HANDLER(THREAD_CHILD_TIMEOUT);
NCP_SET_PROP_HANDLER(THREAD_ROUTER_UPGRADE_THRESHOLD);
NCP_SET_PROP_HANDLER(THREAD_ROUTER_DOWNGRADE_THRESHOLD);
NCP_SET_PROP_HANDLER(THREAD_ROUTER_SELECTION_JITTER);
NCP_SET_PROP_HANDLER(THREAD_CONTEXT_REUSE_DELAY);
NCP_SET_PROP_HANDLER(THREAD_NETWORK_ID_TIMEOUT);
NCP_SET_PROP_HANDLER(THREAD_PREFERRED_ROUTER_ID);
NCP_SET_PROP_HANDLER(THREAD_ROUTER_ROLE_ENABLED);
#if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB
NCP_SET_PROP_HANDLER(THREAD_STEERING_DATA);
#endif
#endif // #if OPENTHREAD_FTD
NCP_SET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_JOINER_FLAG);
NCP_SET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_ENABLE_FILTERING);
NCP_SET_PROP_HANDLER(THREAD_DISCOVERY_SCAN_PANID);
NCP_SET_PROP_HANDLER(THREAD_ASSISTING_PORTS);
NCP_SET_PROP_HANDLER(NET_REQUIRE_JOIN_EXISTING);
NCP_SET_PROP_HANDLER(CNTR_RESET);
NCP_SET_PROP_HANDLER(DEBUG_NCP_LOG_LEVEL);
#if OPENTHREAD_ENABLE_COMMISSIONER
NCP_SET_PROP_HANDLER(THREAD_COMMISSIONER_ENABLED);
#endif
NCP_SET_PROP_HANDLER(THREAD_TMF_PROXY_ENABLED);
#if OPENTHREAD_ENABLE_JAM_DETECTION
NCP_SET_PROP_HANDLER(JAM_DETECT_ENABLE);
NCP_SET_PROP_HANDLER(JAM_DETECT_RSSI_THRESHOLD);
NCP_SET_PROP_HANDLER(JAM_DETECT_WINDOW);
NCP_SET_PROP_HANDLER(JAM_DETECT_BUSY);
#endif
#if OPENTHREAD_ENABLE_DIAG
NCP_SET_PROP_HANDLER(NEST_STREAM_MFG);
#endif
#if OPENTHREAD_ENABLE_LEGACY
NCP_SET_PROP_HANDLER(NEST_LEGACY_ULA_PREFIX);
#endif
// Property Insert Handlers
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
NCP_INSERT_PROP_HANDLER(UNSOL_UPDATE_FILTER);
#if OPENTHREAD_ENABLE_RAW_LINK_API
NCP_INSERT_PROP_HANDLER(MAC_SRC_MATCH_SHORT_ADDRESSES);
NCP_INSERT_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
#endif
NCP_INSERT_PROP_HANDLER(IPV6_ADDRESS_TABLE);
NCP_INSERT_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_INSERT_PROP_HANDLER(THREAD_OFF_MESH_ROUTES);
NCP_INSERT_PROP_HANDLER(THREAD_ON_MESH_NETS);
#endif
NCP_INSERT_PROP_HANDLER(THREAD_ASSISTING_PORTS);
#if OPENTHREAD_ENABLE_MAC_FILTER
NCP_INSERT_PROP_HANDLER(MAC_WHITELIST);
NCP_INSERT_PROP_HANDLER(MAC_BLACKLIST);
NCP_INSERT_PROP_HANDLER(MAC_FIXED_RSS);
#endif
#if OPENTHREAD_ENABLE_COMMISSIONER
NCP_INSERT_PROP_HANDLER(THREAD_JOINERS);
#endif
// Property Remove Handlers
NCP_REMOVE_PROP_HANDLER(UNSOL_UPDATE_FILTER);
#if OPENTHREAD_ENABLE_RAW_LINK_API
NCP_REMOVE_PROP_HANDLER(MAC_SRC_MATCH_SHORT_ADDRESSES);
NCP_REMOVE_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
#endif
NCP_REMOVE_PROP_HANDLER(IPV6_ADDRESS_TABLE);
NCP_REMOVE_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_REMOVE_PROP_HANDLER(THREAD_OFF_MESH_ROUTES);
NCP_REMOVE_PROP_HANDLER(THREAD_ON_MESH_NETS);
#endif
NCP_REMOVE_PROP_HANDLER(THREAD_ASSISTING_PORTS);
#if OPENTHREAD_ENABLE_MAC_FILTER
NCP_REMOVE_PROP_HANDLER(MAC_WHITELIST);
NCP_REMOVE_PROP_HANDLER(MAC_BLACKLIST);
NCP_REMOVE_PROP_HANDLER(MAC_FIXED_RSS);
#endif
#if OPENTHREAD_FTD
NCP_GET_PROP_HANDLER(NET_PSKC);
NCP_SET_PROP_HANDLER(NET_PSKC);
NCP_GET_PROP_HANDLER(THREAD_CHILD_TABLE);
NCP_GET_PROP_HANDLER(THREAD_CHILD_COUNT_MAX);
NCP_SET_PROP_HANDLER(THREAD_CHILD_COUNT_MAX);
NCP_SET_PROP_HANDLER(THREAD_CHILD_TIMEOUT);
NCP_GET_PROP_HANDLER(THREAD_CONTEXT_REUSE_DELAY);
NCP_SET_PROP_HANDLER(THREAD_CONTEXT_REUSE_DELAY);
NCP_GET_PROP_HANDLER(THREAD_LOCAL_LEADER_WEIGHT);
NCP_SET_PROP_HANDLER(THREAD_LOCAL_LEADER_WEIGHT);
NCP_GET_PROP_HANDLER(THREAD_NETWORK_ID_TIMEOUT);
NCP_SET_PROP_HANDLER(THREAD_NETWORK_ID_TIMEOUT);
NCP_GET_PROP_HANDLER(THREAD_ROUTER_ROLE_ENABLED);
NCP_SET_PROP_HANDLER(THREAD_ROUTER_ROLE_ENABLED);
NCP_GET_PROP_HANDLER(THREAD_ROUTER_UPGRADE_THRESHOLD);
NCP_SET_PROP_HANDLER(THREAD_ROUTER_UPGRADE_THRESHOLD);
NCP_GET_PROP_HANDLER(THREAD_ROUTER_DOWNGRADE_THRESHOLD);
NCP_SET_PROP_HANDLER(THREAD_ROUTER_DOWNGRADE_THRESHOLD);
NCP_GET_PROP_HANDLER(THREAD_ROUTER_SELECTION_JITTER);
NCP_SET_PROP_HANDLER(THREAD_ROUTER_SELECTION_JITTER);
NCP_SET_PROP_HANDLER(THREAD_PREFERRED_ROUTER_ID);
#if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB
NCP_SET_PROP_HANDLER(THREAD_STEERING_DATA);
#endif
#if OPENTHREAD_ENABLE_TMF_PROXY
NCP_GET_PROP_HANDLER(THREAD_TMF_PROXY_ENABLED);
NCP_SET_PROP_HANDLER(THREAD_TMF_PROXY_ENABLED);
NCP_SET_PROP_HANDLER(THREAD_TMF_PROXY_STREAM);
#endif
NCP_REMOVE_PROP_HANDLER(THREAD_ACTIVE_ROUTER_IDS);
#endif
public:
otError StreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLen);
#if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE
void RegisterPeekPokeDelagates(otNcpDelegateAllowPeekPoke aAllowPeekDelegate,
otNcpDelegateAllowPeekPoke aAllowPokeDelegate);
#endif
#if OPENTHREAD_ENABLE_LEGACY
public:
void HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr);
void HandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix);
void RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers);
#endif
#endif // OPENTHREAD_FTD
protected:
static NcpBase *sNcpInstance;
static spinel_status_t ThreadErrorToSpinelStatus(otError aError);
static uint8_t LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aSecureDataRequests, bool aDeviceType, bool aNetworkData);
otInstance *mInstance;
NcpFrameBuffer mTxFrameBuffer;
private:
/**
* Defines a class to track a set of property/status changes that require update to host. The properties that can
* be added to this set must support sending unsolicited updates. This class also provides mechanism for user
* to block certain filterable properties disallowing the unsolicited update from them.
*
*/
class ChangedPropsSet
{
public:
/**
* Defines an entry in the set/list.
*
*/
struct Entry
{
spinel_prop_key_t mPropKey; ///< The spinel property key.
spinel_status_t mStatus; ///< The spinel status (used only if prop key is `LAST_STATUS`).
bool mFilterable; ///< Indicates whether the entry can be filtered
};
/**
* This constructor initializes the set.
*
*/
ChangedPropsSet(void):
mChangedSet(0),
mFilterSet(0)
{ }
/**
* This method clears the set.
*
*/
void Clear(void) { mChangedSet = 0; }
/**
* This method indicates if the set is empty or not.
*
* @returns TRUE if the set if empty, FALSE otherwise.
*
*/
bool IsEmpty(void) const { return (mChangedSet == 0); }
/**
* This method adds a property to the set. The property added must be in the list of supported properties
* capable of sending unsolicited update, otherwise the input is ignored.
*
* Note that if the property is already in the set, adding it again does not change the set.
*
* @param[in] aPropKey The spinel property key to be added to the set
*
*/
void AddProperty(spinel_prop_key_t aPropKey) { Add(aPropKey, SPINEL_STATUS_OK); }
/**
* This method adds a `LAST_STATUS` update to the set. The update must be in list of supported entries.
*
* @param[in] aStatus The spinel status update to be added to set.
*
*/
void AddLastStatus(spinel_status_t aStatus) { Add(SPINEL_PROP_LAST_STATUS, aStatus); }
/**
* This method returns a pointer to array of entries of supported property/status updates. The list includes
* all properties that can generate unsolicited update.
*
* @param[out] aNumEntries A reference to output the number of entries in the list.
*
* @returns A pointer to the supported entries array.
*
*/
const Entry *GetSupportedEntries(uint8_t &aNumEntries) const {
aNumEntries = GetNumEntries();
return &mSupportedProps[0];
}
/**
* This method returns a pointer to the entry associated with a given index.
*
* @param[in] aIndex The index to an entry.
*
* @returns A pointer to the entry associated with @p aIndex, or NULL if the index is beyond end of array.
*
*/
const Entry *GetEntry(uint8_t aIndex) const {
return (aIndex < GetNumEntries()) ? &mSupportedProps[aIndex] : NULL;
}
/**
* This method indicates if the entry associated with an index is in the set (i.e., it has been changed and
* requires an unsolicited update).
*
* @param[in] aIndex The index to an entry.
*
* @returns TRUE if the entry is in the set, FALSE otherwise.
*
*/
bool IsEntryChanged(uint8_t aIndex) const { return IsBitSet(mChangedSet, aIndex); }
/**
* This method removes an entry associated with an index in the set.
*
* Note that if the property/entry is not in the set, removing it simply does nothing.
*
* @param[in] aIndex Index of entry to be removed.
*
*/
void RemoveEntry(uint8_t aIndex) { ClearBit(mChangedSet, aIndex); }
/**
* This method enables/disables filtering of a given property.
*
* @param[in] aPropKey The property key to filter.
* @param[in] aEnable TRUE to enable filtering, FALSE to disable.
*
* @retval OT_ERROR_NONE Filter state for given property updated successfully.
* @retval OT_ERROR_INVALID_ARGS The given property is not valid (i.e., not capable of unsolicited update).
*
*/
otError EnablePropertyFilter(spinel_prop_key_t aPropKey, bool aEnable);
/**
* This method determines whether filtering is enabled for an entry associated with an index.
*
* @param[in] aIndex Index of entry to be checked.
*
* @returns TRUE if the filter is enabled for the given entry, FALSE otherwise.
*
*/
bool IsEntryFiltered(uint8_t aIndex) const { return IsBitSet(mFilterSet, aIndex); }
/**
* This method determines whether filtering is enabled for a given property key.
*
* @param[in] aPropKey The property key to check.
*
* @returns TRUE if the filter is enabled for the given property, FALSE if the property is not filtered or if
* it is not filterable.
*
*/
bool IsPropertyFiltered(spinel_prop_key_t aPropKey) const;
/**
* This method clears the filter.
*
*/
void ClearFilter(void) { mFilterSet = 0; }
private:
uint8_t GetNumEntries(void) const;
void Add(spinel_prop_key_t aPropKey, spinel_status_t aStatus);
static void SetBit (uint32_t &aBitset, uint8_t aBitIndex) { aBitset |= (1U << aBitIndex); }
static void ClearBit(uint32_t &aBitset, uint8_t aBitIndex) { aBitset &= ~(1U << aBitIndex); }
static bool IsBitSet(uint32_t aBitset, uint8_t aBitIndex) { return (aBitset & (1U << aBitIndex)) != 0; }
static const Entry mSupportedProps[];
uint32_t mChangedSet;
uint32_t mFilterSet;
};
enum
{
kTxBufferSize = OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE, // Tx Buffer size (used by mTxFrameBuffer).
kInvalidScanChannel = -1, // Invalid scan channel.
};
// Command Handlers
static const CommandHandlerEntry mCommandHandlerTable[];
static const GetPropertyHandlerEntry mGetPropertyHandlerTable[];
static const SetPropertyHandlerEntry mSetPropertyHandlerTable[];
static const InsertPropertyHandlerEntry mInsertPropertyHandlerTable[];
static const RemovePropertyHandlerEntry mRemovePropertyHandlerTable[];
spinel_status_t mLastStatus;
uint32_t mSupportedChannelMask;
uint32_t mChannelMask;
@@ -789,6 +661,8 @@ private:
uint32_t mThreadChangedFlags;
ChangedPropsSet mChangedPropsSet;
uint32_t mChangedFlags;
bool mShouldSignalEndOfScan;
spinel_host_power_state_t mHostPowerState;
bool mHostPowerStateInProgress;
NcpFrameBuffer::FrameTag mHostPowerReplyFrameTag;
@@ -815,16 +689,19 @@ private:
int8_t mCurScanChannel;
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
uint32_t mFramingErrorCounter; // Number of improperly formed received spinel frames.
uint32_t mRxSpinelFrameCounter; // Number of received (inbound) spinel frames.
uint32_t mRxSpinelOutOfOrderTidCounter; // Number of out of order received spinel frames (tid increase > 1).
uint32_t mTxSpinelFrameCounter; // Number of sent (outbound) spinel frames.
#if OPENTHREAD_MTD || OPENTHREAD_FTD
uint32_t mInboundSecureIpFrameCounter; // Number of secure inbound data/IP frames.
uint32_t mInboundInsecureIpFrameCounter; // Number of insecure inbound data/IP frames.
uint32_t mOutboundSecureIpFrameCounter; // Number of secure outbound data/IP frames.
uint32_t mOutboundInsecureIpFrameCounter; // Number of insecure outbound data/IP frames.
uint32_t mDroppedOutboundIpFrameCounter; // Number of dropped outbound data/IP frames.
uint32_t mDroppedInboundIpFrameCounter; // Number of dropped inbound data/IP frames.
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
uint32_t mFramingErrorCounter; // Number of improperly formed received spinel frames.
uint32_t mRxSpinelFrameCounter; // Number of received (inbound) spinel frames.
uint32_t mRxSpinelOutOfOrderTidCounter; // Number of out of order received spinel frames (tid increase > 1).
uint32_t mTxSpinelFrameCounter; // Number of sent (outbound) spinel frames.
#if OPENTHREAD_ENABLE_LEGACY
const otNcpLegacyHandlers *mLegacyHandlers;
@@ -835,6 +712,7 @@ private:
};
} // namespace Ncp
} // namespace ot
#endif // NCP_BASE_HPP_
+857
View File
@@ -0,0 +1,857 @@
/*
* Copyright (c) 2016-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 full thread device specified Spinel interface to the OpenThread stack.
*/
#include <openthread/config.h>
#include "ncp_base.hpp"
#include <openthread/diag.h>
#include <openthread/icmp6.h>
#include <openthread/ncp.h>
#include <openthread/openthread.h>
#include <openthread/platform/misc.h>
#include <openthread/platform/radio.h>
#include <openthread/thread_ftd.h>
#if OPENTHREAD_ENABLE_TMF_PROXY
#include <openthread/tmf_proxy.h>
#endif
#include "openthread-instance.h"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#if OPENTHREAD_ENABLE_COMMISSIONER
#include "meshcop/commissioner.hpp"
#endif
#include "net/ip6.hpp"
#if OPENTHREAD_FTD
namespace ot {
namespace Ncp {
otError NcpBase::GetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT8_S,
otThreadGetLocalLeaderWeight(mInstance)
);
}
otError NcpBase::GetPropertyHandler_THREAD_LEADER_WEIGHT(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT8_S,
otThreadGetLeaderWeight(mInstance)
);
}
otError NcpBase::GetPropertyHandler_THREAD_CHILD_TABLE(uint8_t aHeader, spinel_prop_key_t aKey)
{
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)
{
continue;
}
modeFlags = LinkFlagsToFlagByte(
childInfo.mRxOnWhenIdle,
childInfo.mSecureDataRequest,
childInfo.mFullFunction,
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 = OutboundFrameSend());
exit:
mDisableStreamWrite = false;
return error;
}
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_ROLE_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_BOOL_S,
otThreadIsRouterRoleEnabled(mInstance)
);
}
otError NcpBase::SetPropertyHandler_THREAD_ROUTER_ROLE_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
bool enabled;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_BOOL_S,
&enabled
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
otThreadSetRouterRoleEnabled(mInstance, enabled);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::GetPropertyHandler_NET_PSKC(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_DATA_S,
otThreadGetPSKc(mInstance),
sizeof(spinel_net_pskc_t)
);
}
otError NcpBase::SetPropertyHandler_NET_PSKC(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen)
{
const uint8_t *ptr = NULL;
spinel_size_t len;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_DATA_S,
&ptr,
&len
);
VerifyOrExit((parsedLength > 0) && (len == sizeof(spinel_net_pskc_t)), error = OT_ERROR_PARSE);
error = otThreadSetPSKc(mInstance, ptr);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::GetPropertyHandler_THREAD_CHILD_COUNT_MAX(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT8_S,
otThreadGetMaxAllowedChildren(mInstance)
);
}
otError NcpBase::SetPropertyHandler_THREAD_CHILD_COUNT_MAX(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
uint8_t maxChildren = 0;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT8_S,
&maxChildren
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otThreadSetMaxAllowedChildren(mInstance, maxChildren);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_UPGRADE_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT8_S,
otThreadGetRouterUpgradeThreshold(mInstance)
);
}
otError NcpBase::SetPropertyHandler_THREAD_ROUTER_UPGRADE_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
uint8_t threshold = 0;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT8_S,
&threshold
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
otThreadSetRouterUpgradeThreshold(mInstance, threshold);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_DOWNGRADE_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT8_S,
otThreadGetRouterDowngradeThreshold(mInstance)
);
}
otError NcpBase::SetPropertyHandler_THREAD_ROUTER_DOWNGRADE_THRESHOLD(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
uint8_t threshold = 0;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT8_S,
&threshold
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
otThreadSetRouterDowngradeThreshold(mInstance, threshold);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::GetPropertyHandler_THREAD_ROUTER_SELECTION_JITTER(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT8_S,
otThreadGetRouterSelectionJitter(mInstance)
);
}
otError NcpBase::SetPropertyHandler_THREAD_ROUTER_SELECTION_JITTER(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
uint8_t jitter = 0;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT8_S,
&jitter
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
otThreadSetRouterSelectionJitter(mInstance, jitter);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::GetPropertyHandler_THREAD_CONTEXT_REUSE_DELAY(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT32_S,
otThreadGetContextIdReuseDelay(mInstance)
);
}
otError NcpBase::SetPropertyHandler_THREAD_CONTEXT_REUSE_DELAY(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
uint32_t delay = 0;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT32_S,
&delay
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
otThreadSetContextIdReuseDelay(mInstance, delay);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::GetPropertyHandler_THREAD_NETWORK_ID_TIMEOUT(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT8_S,
otThreadGetNetworkIdTimeout(mInstance)
);
}
otError NcpBase::SetPropertyHandler_THREAD_NETWORK_ID_TIMEOUT(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
uint8_t timeout = 0;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT8_S,
&timeout
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
otThreadSetNetworkIdTimeout(mInstance, timeout);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
#if OPENTHREAD_ENABLE_COMMISSIONER
otError NcpBase::GetPropertyHandler_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
{
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
);
}
otError NcpBase::SetPropertyHandler_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr,
uint16_t aValueLen)
{
bool enabled = false;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_BOOL_S,
&enabled
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
if (enabled == false)
{
error = otCommissionerStop(mInstance);
}
else
{
error = otCommissionerStart(mInstance);
}
exit:
OT_UNUSED_VARIABLE(aKey);
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)
{
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);
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
(
SPINEL_DATATYPE_UTF8_S // PSK
SPINEL_DATATYPE_UINT32_S // Timeout
SPINEL_DATATYPE_EUI64_S // Extended address
),
&aPSKd,
&joinerTimeout,
&extAddress
);
if (parsedLength <= 0)
{
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
(
SPINEL_DATATYPE_UTF8_S // PSK
SPINEL_DATATYPE_UINT32_S // Timeout
),
&aPSKd,
&joinerTimeout
);
extAddress = NULL;
}
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
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;
}
#endif // OPENTHREAD_ENABLE_COMMISSIONER
otError NcpBase::SetPropertyHandler_THREAD_LOCAL_LEADER_WEIGHT(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
uint8_t weight;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT8_S,
&weight
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
otThreadSetLocalLeaderWeight(mInstance, weight);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
#if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB
otError NcpBase::SetPropertyHandler_THREAD_STEERING_DATA(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
otExtAddress *extAddress;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_EUI64_S,
&extAddress
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otThreadSetSteeringData(mInstance, extAddress);
exit:
if (error == OT_ERROR_NONE)
{
// 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));
}
return error;
}
#endif // #if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB
otError NcpBase::SetPropertyHandler_THREAD_CHILD_TIMEOUT(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
uint32_t timeout = 0;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT32_S,
&timeout
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
otThreadSetChildTimeout(mInstance, timeout);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::SetPropertyHandler_THREAD_PREFERRED_ROUTER_ID(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
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,
aValueLen,
SPINEL_DATATYPE_UINT8_S,
&routerId
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
error = otThreadReleaseRouterId(mInstance, routerId);
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;
}
#if OPENTHREAD_ENABLE_TMF_PROXY
otError NcpBase::GetPropertyHandler_THREAD_TMF_PROXY_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_BOOL_S,
otTmfProxyIsEnabled(mInstance)
);
}
otError NcpBase::SetPropertyHandler_THREAD_TMF_PROXY_STREAM(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
const uint8_t *framePtr = NULL;
unsigned int frameLen = 0;
uint16_t locator;
uint16_t port;
otMessage *message;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
// THREAD_TMF_PROXY_STREAM requires layer 2 security.
message = otIp6NewMessage(mInstance, true);
VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS);
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
(
SPINEL_DATATYPE_DATA_WLEN_S // Frame data
SPINEL_DATATYPE_UINT16_S // Locator
SPINEL_DATATYPE_UINT16_S // Port
),
&framePtr,
&frameLen,
&locator,
&port
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
SuccessOrExit(error = otMessageAppend(message, framePtr, static_cast<uint16_t>(frameLen)));
error = otTmfProxySend(mInstance, message, locator, port);
// `otTmfProxySend()` takes ownership of `message` (in both success
// or failure cases). `message` is set to NULL so it is not freed at
// exit.
message = NULL;
exit:
if (message != NULL)
{
otMessageFree(message);
}
if (error == OT_ERROR_NONE)
{
if (SPINEL_HEADER_GET_TID(aHeader) != 0)
{
// Only send a successful status update if
// there was a transaction id in the aHeader.
error = SendLastStatus(aHeader, SPINEL_STATUS_OK);
}
}
else
{
error = SendLastStatus(aHeader, ThreadErrorToSpinelStatus(error));
}
OT_UNUSED_VARIABLE(aKey);
return error;
}
otError NcpBase::SetPropertyHandler_THREAD_TMF_PROXY_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
bool enabled;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_BOOL_S,
&enabled
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
if (enabled)
{
error = otTmfProxyStart(mInstance, &NcpBase::HandleTmfProxyStream, this);
}
else
{
error = otTmfProxyStop(mInstance);
}
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
void NcpBase::HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort, void *aContext)
{
static_cast<NcpBase *>(aContext)->HandleTmfProxyStream(aMessage, aLocator, aPort);
}
void NcpBase::HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort)
{
otError error = OT_ERROR_NONE;
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
));
// 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);
}
if (error != OT_ERROR_NONE)
{
mChangedPropsSet.AddLastStatus(SPINEL_STATUS_DROPPED);
mUpdateChangedPropsTask.Post();
}
}
#endif // OPENTHREAD_ENABLE_TMF_PROXY
} // namespace Ncp
} // namespace ot
#endif // OPENTHREAD_FTD
File diff suppressed because it is too large Load Diff
+712
View File
@@ -0,0 +1,712 @@
/*
* Copyright (c) 2016-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 raw link required Spinel interface to the OpenThread stack.
*/
#include <openthread/config.h>
#include "ncp_base.hpp"
#include <stdlib.h>
#include <openthread/diag.h>
#include <openthread/icmp6.h>
#include <openthread/ncp.h>
#include <openthread/openthread.h>
#include <openthread/platform/misc.h>
#include <openthread/platform/radio.h>
#include "openthread-instance.h"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "net/ip6.hpp"
#if OPENTHREAD_ENABLE_RAW_LINK_API
namespace ot {
namespace Ncp {
// ----------------------------------------------------------------------------
// MARK: Raw Link-Layer Datapath Glue
// ----------------------------------------------------------------------------
void NcpBase::LinkRawReceiveDone(otInstance *, otRadioFrame *aFrame, otError aError)
{
sNcpInstance->LinkRawReceiveDone(aFrame, aError);
}
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
));
if (aError == OT_ERROR_NONE)
{
// Append the frame contents
SuccessOrExit(OutboundFrameFeedData(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(OutboundFrameSend());
exit:
return;
}
void NcpBase::LinkRawTransmitDone(otInstance *, otRadioFrame *aFrame,
otRadioFrame *aAckFrame, otError aError)
{
sNcpInstance->LinkRawTransmitDone(aFrame, aAckFrame, aError);
}
void NcpBase::LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
{
if (mCurTransmitTID)
{
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0 | mCurTransmitTID;
bool framePending = (aAckFrame != NULL && static_cast<Mac::Frame *>(aAckFrame)->GetFramePending());
// 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
));
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(OutboundFrameSend());
}
exit:
OT_UNUSED_VARIABLE(aFrame);
return;
}
void NcpBase::LinkRawEnergyScanDone(otInstance *, int8_t aEnergyScanMaxRssi)
{
sNcpInstance->LinkRawEnergyScanDone(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
);
// Clear current scan channel
mCurScanChannel = kInvalidScanChannel;
// Make sure we are back listening on the original receive channel,
// since the energy scan could have been on a different channel.
otLinkRawReceive(mInstance, mCurReceiveChannel, &NcpBase::LinkRawReceiveDone);
// 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
);
}
// ----------------------------------------------------------------------------
// MARK: Raw frame handling
// ----------------------------------------------------------------------------
void NcpBase::HandleRawFrame(const otRadioFrame *aFrame, void *aContext)
{
static_cast<NcpBase *>(aContext)->HandleRawFrame(aFrame);
}
void NcpBase::HandleRawFrame(const otRadioFrame *aFrame)
{
uint16_t flags = 0;
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
if (!mIsRawStreamEnabled)
{
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
));
// Append the frame contents
SuccessOrExit(OutboundFrameFeedData(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
// Skip PHY and Vendor data for now
));
SuccessOrExit(OutboundFrameSend());
exit:
return;
}
otError NcpBase::SetPropertyHandler_MAC_SRC_MATCH_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
bool enabled;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_BOOL_S,
&enabled
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otLinkRawSrcMatchEnable(mInstance, enabled);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::SetPropertyHandler_MAC_SRC_MATCH_SHORT_ADDRESSES(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
otError error = OT_ERROR_NONE;
spinel_status_t spinelError = SPINEL_STATUS_OK;
const uint8_t *data = aValuePtr;
uint16_t dataLen = aValueLen;
// Clear the list first
error = otLinkRawSrcMatchClearShortEntries(mInstance);
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
// Loop through the addresses and add them
while (dataLen >= sizeof(uint16_t))
{
spinel_ssize_t parsedLength;
uint16_t short_address;
parsedLength = spinel_datatype_unpack(
data,
dataLen,
SPINEL_DATATYPE_UINT16_S,
&short_address
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
data += parsedLength;
dataLen -= (uint16_t)parsedLength;
error = otLinkRawSrcMatchAddShortEntry(mInstance, short_address);
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
}
error =
SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
aValuePtr,
aValueLen
);
exit:
if (spinelError != SPINEL_STATUS_OK)
{
error = SendLastStatus(aHeader, spinelError);
}
return error;
}
otError NcpBase::SetPropertyHandler_MAC_SRC_MATCH_EXTENDED_ADDRESSES(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
otError error = OT_ERROR_NONE;
spinel_status_t spinelError = SPINEL_STATUS_OK;
const uint8_t *data = aValuePtr;
uint16_t dataLen = aValueLen;
// Clear the list first
error = otLinkRawSrcMatchClearExtEntries(mInstance);
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
// Loop through the addresses and add them
while (dataLen >= sizeof(otExtAddress))
{
spinel_ssize_t parsedLength;
otExtAddress *extAddress;
parsedLength = spinel_datatype_unpack(
data,
dataLen,
SPINEL_DATATYPE_EUI64_S,
&extAddress
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
data += parsedLength;
dataLen -= (uint16_t)parsedLength;
error = otLinkRawSrcMatchAddExtEntry(mInstance, extAddress);
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
}
error =
SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
aValuePtr,
aValueLen
);
exit:
if (spinelError != SPINEL_STATUS_OK)
{
error = SendLastStatus(aHeader, spinelError);
}
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)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
spinel_status_t spinelError = SPINEL_STATUS_OK;
uint16_t shortAddress;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT16_S,
&shortAddress
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
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)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
spinel_status_t spinelError = SPINEL_STATUS_OK;
otExtAddress *extAddress;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_EUI64_S,
&extAddress
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
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)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
spinel_status_t spinelError = SPINEL_STATUS_OK;
uint16_t short_address;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT16_S,
&short_address
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
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)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
spinel_status_t spinelError = SPINEL_STATUS_OK;
otExtAddress *extAddress = NULL;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_EUI64_S,
&extAddress
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
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;
}
otError NcpBase::GetPropertyHandler_PHY_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_BOOL_S,
otLinkRawIsEnabled(mInstance)
);
}
otError NcpBase::SetPropertyHandler_PHY_ENABLED(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen)
{
bool value = false;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_BOOL_S,
&value
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
if (value == false)
{
// If we have raw stream enabled stop receiving
if (mIsRawStreamEnabled)
{
otLinkRawSleep(mInstance);
}
error = otLinkRawSetEnable(mInstance, false);
}
else
{
error = otLinkRawSetEnable(mInstance, true);
// If we have raw stream enabled already, start receiving
if (error == OT_ERROR_NONE && mIsRawStreamEnabled)
{
error = otLinkRawReceive(mInstance, mCurReceiveChannel, &NcpBase::LinkRawReceiveDone);
}
}
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::GetPropertyHandler_MAC_15_4_SADDR(uint8_t aHeader, spinel_prop_key_t aKey)
{
return SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey,
SPINEL_DATATYPE_UINT16_S,
otLinkGetShortAddress(mInstance)
);
}
otError NcpBase::SetPropertyHandler_MAC_15_4_SADDR(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen)
{
uint16_t shortAddress;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_UINT16_S,
&shortAddress
);
VerifyOrExit(parsedLength > 0, error = OT_ERROR_PARSE);
error = otLinkRawSetShortAddress(mInstance, shortAddress);
exit:
return SendSetPropertyResponse(aHeader, aKey, error);
}
otError NcpBase::SetPropertyHandler_STREAM_RAW(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *aValuePtr,
uint16_t aValueLen)
{
uint8_t *frame_buffer = NULL;
otRadioFrame *frame;
unsigned int frameLen = 0;
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
VerifyOrExit(otLinkRawIsEnabled(mInstance), error = OT_ERROR_INVALID_STATE);
frame = otLinkRawGetTransmitBuffer(mInstance);
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_DATA_WLEN_S
SPINEL_DATATYPE_UINT8_S
SPINEL_DATATYPE_INT8_S,
&frame_buffer,
&frameLen,
&frame->mChannel,
&frame->mPower
);
VerifyOrExit(parsedLength > 0 && frameLen <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_PARSE);
// Cache the transaction ID for async response
mCurTransmitTID = SPINEL_HEADER_GET_TID(aHeader);
// Update frame buffer and length
frame->mLength = static_cast<uint8_t>(frameLen);
memcpy(frame->mPsdu, frame_buffer, frame->mLength);
// TODO: This should be later added in the STREAM_RAW argument to allow user to directly specify it.
frame->mMaxTxAttempts = OPENTHREAD_CONFIG_MAX_TX_ATTEMPTS_DIRECT;
// Pass frame to the radio layer. Note, this fails if we
// haven't enabled raw stream or are already transmitting.
error = otLinkRawTransmit(mInstance, frame, &NcpBase::LinkRawTransmitDone);
exit:
if (error == OT_ERROR_NONE)
{
// Don't do anything here yet. We will complete the transaction when we get a transmit done callback
}
else
{
error = SendLastStatus(aHeader, ThreadErrorToSpinelStatus(error));
}
OT_UNUSED_VARIABLE(aKey);
return error;
}
} // namespace Ncp
} // namespace ot
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
+2
View File
@@ -38,6 +38,7 @@
#include "common/debug.hpp"
namespace ot {
namespace Ncp {
const NcpFrameBuffer::FrameTag NcpFrameBuffer::kInvalidTag = NULL;
@@ -902,4 +903,5 @@ NcpFrameBuffer::FrameTag NcpFrameBuffer::OutFrameGetTag(void)
return IsEmpty() ? kInvalidTag : mReadFrameStart[mReadDirection];
}
} // namespace Ncp
} // namespace ot
+2
View File
@@ -38,6 +38,7 @@
#include <openthread/types.h>
namespace ot {
namespace Ncp {
/**
@@ -626,6 +627,7 @@ private:
uint8_t * mReadMessageTail; // Pointer to end of current part in mMessageBuffer.
};
} // namespace Ncp
} // namespace ot
#endif // NCP_FRAME_BUFFER_HPP_
+2
View File
@@ -53,6 +53,7 @@
#if OPENTHREAD_ENABLE_NCP_SPI
namespace ot {
namespace Ncp {
static otDEFINE_ALIGNED_VAR(sNcpRaw, sizeof(NcpSpi), uint64_t);
@@ -377,6 +378,7 @@ void NcpSpi::HandleRxFrame(void)
}
}
} // namespace Ncp
} // namespace ot
#endif // OPENTHREAD_ENABLE_NCP_SPI
+2
View File
@@ -38,6 +38,7 @@
#include "ncp/ncp_base.hpp"
namespace ot {
namespace Ncp {
class NcpSpi : public NcpBase
{
@@ -105,6 +106,7 @@ private:
uint8_t mEmptyReceiveFrame[kSpiHeaderLength];
};
} // namespace Ncp
} // namespace ot
#endif // NCP_SPI_HPP_
+2
View File
@@ -51,6 +51,7 @@
#if OPENTHREAD_ENABLE_NCP_UART
namespace ot {
namespace Ncp {
static otDEFINE_ALIGNED_VAR(sNcpRaw, sizeof(NcpUart), uint64_t);
@@ -301,6 +302,7 @@ void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat
#endif
#endif // OPENTHREAD_ENABLE_CLI_LOGGING
} // namespace Ncp
} // namespace ot
#endif // OPENTHREAD_ENABLE_NCP_UART
+2
View File
@@ -39,6 +39,7 @@
#include "ncp/ncp_base.hpp"
namespace ot {
namespace Ncp {
class NcpUart : public NcpBase
{
@@ -116,6 +117,7 @@ private:
Tasklet mUartSendTask;
};
} // namespace Ncp
} // namespace ot
#endif // NCP_UART_HPP_
+4 -2
View File
@@ -39,6 +39,7 @@
#include "test_util.h"
namespace ot {
namespace Ncp {
// This module implements unit-test for NcpFrameBuffer class.
@@ -1089,13 +1090,14 @@ void TestFuzzNcpFrameBuffer(void)
testFreeInstance(sInstance);
}
} // namespace Ncp
} // namespace ot
#ifdef ENABLE_TEST_MAIN
int main(void)
{
ot::TestNcpFrameBuffer();
ot::TestFuzzNcpFrameBuffer();
ot::Ncp::TestNcpFrameBuffer();
ot::Ncp::TestFuzzNcpFrameBuffer();
printf("\nAll tests passed.\n");
return 0;
}
+4 -3
View File
@@ -71,10 +71,11 @@ void TestMessageQueue();
void TestPriorityQueue();
// test_ncp_buffer.cpp
namespace ot
{
namespace ot {
namespace Ncp {
void TestNcpFrameBuffer(void);
}
}
// test_timer.cpp
int TestOneTimer();
@@ -162,7 +163,7 @@ namespace ot
TEST_METHOD(TestTenTimers) { ::TestTenTimers(); }
// test_ncp_buffer.cpp
TEST_METHOD(TestNcpFrameBuffer) { ot::TestNcpFrameBuffer(); }
TEST_METHOD(TestNcpFrameBuffer) { ot::Ncp::TestNcpFrameBuffer(); }
// test_toolchain.cpp
TEST_METHOD(test_packed1) { ::test_packed1(); }