From 053557ca7258949b842edcff77507524fd963a27 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 9 Feb 2018 11:22:37 -0800 Subject: [PATCH] [ncp] add Channel Manager related properties (#2545) This commit defines new spinel properties related to Channel Manager feature and implements their get/set handler in `NcpBase` --- src/ncp/ncp_base.cpp | 14 ++++++++++ src/ncp/ncp_base.hpp | 11 +++++++- src/ncp/ncp_base_ftd.cpp | 60 ++++++++++++++++++++++++++++++++++++++++ src/ncp/ncp_base_mtd.cpp | 30 ++++++++++++-------- src/ncp/spinel.c | 16 +++++++++++ src/ncp/spinel.h | 48 ++++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 12 deletions(-) diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index e52ef3450..b286fcbd5 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -243,6 +243,11 @@ const NcpBase::PropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] = #if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB NCP_GET_PROP_HANDLER_ENTRY(THREAD_STEERING_DATA), #endif +#if OPENTHREAD_ENABLE_CHANNEL_MANAGER + NCP_GET_PROP_HANDLER_ENTRY(CHANNEL_MANAGER_NEW_CHANNEL), + NCP_GET_PROP_HANDLER_ENTRY(CHANNEL_MANAGER_DELAY), + NCP_GET_PROP_HANDLER_ENTRY(CHANNEL_MANAGER_SUPPORTED_CHANNELS), +#endif #endif // OPENTHREAD_FTD #if OPENTHREAD_ENABLE_RAW_LINK_API @@ -338,6 +343,11 @@ const NcpBase::PropertyHandlerEntry NcpBase::mSetPropertyHandlerTable[] = NCP_SET_PROP_HANDLER_ENTRY(THREAD_PENDING_DATASET), NCP_SET_PROP_HANDLER_ENTRY(THREAD_MGMT_ACTIVE_DATASET), NCP_SET_PROP_HANDLER_ENTRY(THREAD_MGMT_PENDING_DATASET), +#if OPENTHREAD_ENABLE_CHANNEL_MANAGER + NCP_SET_PROP_HANDLER_ENTRY(CHANNEL_MANAGER_NEW_CHANNEL), + NCP_SET_PROP_HANDLER_ENTRY(CHANNEL_MANAGER_DELAY), + NCP_SET_PROP_HANDLER_ENTRY(CHANNEL_MANAGER_SUPPORTED_CHANNELS), +#endif #endif // #if OPENTHREAD_FTD }; @@ -1798,6 +1808,10 @@ otError NcpBase::GetPropertyHandler_CAPS(void) SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_CHANNEL_MONITOR)); #endif +#if OPENTHREAD_ENABLE_CHANNEL_MANAGER && OPENTHREAD_FTD + SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_CHANNEL_MANAGER)); +#endif + #if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_ERROR_RATE_TRACKING)); #endif diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 04931bcab..bd56e1ab6 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -276,7 +276,8 @@ protected: static void SendDoneTask(void *aContext); void SendDoneTask(void); - otError EncodeChannelMask(uint32_t channel_mask); + otError EncodeChannelMask(uint32_t aChannelMask); + otError DecodeChannelMask(uint32_t &aChannelMask); otError EncodeOperationalDataset(const otOperationalDataset &aDataset); #if OPENTHREAD_FTD @@ -659,6 +660,14 @@ protected: NCP_SET_PROP_HANDLER(THREAD_PENDING_DATASET); NCP_SET_PROP_HANDLER(THREAD_MGMT_ACTIVE_DATASET); NCP_SET_PROP_HANDLER(THREAD_MGMT_PENDING_DATASET); +#if OPENTHREAD_ENABLE_CHANNEL_MANAGER + NCP_GET_PROP_HANDLER(CHANNEL_MANAGER_NEW_CHANNEL); + NCP_SET_PROP_HANDLER(CHANNEL_MANAGER_NEW_CHANNEL); + NCP_GET_PROP_HANDLER(CHANNEL_MANAGER_DELAY); + NCP_SET_PROP_HANDLER(CHANNEL_MANAGER_DELAY); + NCP_GET_PROP_HANDLER(CHANNEL_MANAGER_SUPPORTED_CHANNELS); + NCP_SET_PROP_HANDLER(CHANNEL_MANAGER_SUPPORTED_CHANNELS); +#endif #endif // OPENTHREAD_FTD diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp index f887452a4..a474a0732 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -32,6 +32,9 @@ #include "ncp_base.hpp" +#if OPENTHREAD_ENABLE_CHANNEL_MANAGER +#include +#endif #include #include #include @@ -856,6 +859,63 @@ exit: return error; } +#if OPENTHREAD_ENABLE_CHANNEL_MANAGER + +otError NcpBase::GetPropertyHandler_CHANNEL_MANAGER_NEW_CHANNEL(void) +{ + return mEncoder.WriteUint8(otChannelManagerGetRequestedChannel(mInstance)); +} + +otError NcpBase::SetPropertyHandler_CHANNEL_MANAGER_NEW_CHANNEL(void) +{ + uint8_t channel; + otError error = OT_ERROR_NONE; + + SuccessOrExit(error = mDecoder.ReadUint8(channel)); + + error = otChannelManagerRequestChannelChange(mInstance, channel); + +exit: + return error; +} + +otError NcpBase::GetPropertyHandler_CHANNEL_MANAGER_DELAY(void) +{ + return mEncoder.WriteUint16(otChannelManagerGetDelay(mInstance)); +} + +otError NcpBase::SetPropertyHandler_CHANNEL_MANAGER_DELAY(void) +{ + uint16_t delay; + otError error = OT_ERROR_NONE; + + SuccessOrExit(error = mDecoder.ReadUint16(delay)); + + error = otChannelManagerSetDelay(mInstance, delay); + +exit: + return error; +} + +otError NcpBase::GetPropertyHandler_CHANNEL_MANAGER_SUPPORTED_CHANNELS(void) +{ + return EncodeChannelMask(otChannelManagerGetSupportedChannels(mInstance)); +} + +otError NcpBase::SetPropertyHandler_CHANNEL_MANAGER_SUPPORTED_CHANNELS(void) +{ + uint32_t channelMask = 0; + otError error = OT_ERROR_NONE; + + SuccessOrExit(error = DecodeChannelMask(channelMask)); + otChannelManagerSetSupportedChannels(mInstance, channelMask); + +exit: + return error; +} + +#endif // OPENTHREAD_ENABLE_CHANNEL_MANAGER + } // namespace Ncp } // namespace ot diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index a0d22d6af..719c2c486 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -2525,6 +2525,23 @@ exit: return error; } +otError NcpBase::DecodeChannelMask(uint32_t &aChannelMask) +{ + otError error = OT_ERROR_NONE; + uint8_t channel; + + aChannelMask = 0; + + while (!mDecoder.IsAllReadInStruct()) + { + SuccessOrExit(error = mDecoder.ReadUint8(channel)); + VerifyOrExit(channel <= 31, error = OT_ERROR_INVALID_ARGS); + aChannelMask |= (1U << channel); + } + +exit: + return error; +} otError NcpBase::GetPropertyHandler_MAC_SCAN_MASK(void) { @@ -2535,18 +2552,9 @@ otError NcpBase::SetPropertyHandler_MAC_SCAN_MASK(void) { uint32_t newMask = 0; otError error = OT_ERROR_NONE; - const uint8_t *valuePtr; - uint16_t valueLen; - SuccessOrExit(error = mDecoder.ReadData(valuePtr, valueLen)); - - for (; valueLen != 0; valueLen--, valuePtr++) - { - VerifyOrExit(valuePtr[0] <= 31, error = OT_ERROR_INVALID_ARGS); - VerifyOrExit((mSupportedChannelMask & (1 << valuePtr[0])) != 0, error = OT_ERROR_INVALID_ARGS); - - newMask |= (1 << valuePtr[0]); - } + SuccessOrExit(error = DecodeChannelMask(newMask)); + VerifyOrExit((~mSupportedChannelMask & newMask) == 0, error = OT_ERROR_INVALID_ARGS); mChannelMask = newMask; diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index d95a43f63..4f4cc1751 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -1585,6 +1585,18 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "PROP_STREAM_NET_INSECURE"; break; + case SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL: + ret = "PROP_CHANNEL_MANAGER_NEW_CHANNEL"; + break; + + case SPINEL_PROP_CHANNEL_MANAGER_DELAY: + ret = "PROP_CHANNEL_MANAGER_DELAY"; + break; + + case SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS: + ret = "PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS"; + break; + case SPINEL_PROP_UART_BITRATE: ret = "PROP_UART_BITRATE"; break; @@ -2136,6 +2148,10 @@ const char *spinel_capability_to_cstr(unsigned int capability) ret = "CAP_CHANNEL_MONITOR"; break; + case SPINEL_CAP_CHANNEL_MANAGER: + ret = "CAP_CHANNEL_MANAGER"; + break; + case SPINEL_CAP_ERROR_RATE_TRACKING: ret = "CAP_ERROR_RATE_TRACKING"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index b2226063e..611fc7670 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -419,6 +419,7 @@ enum SPINEL_CAP_OOB_STEERING_DATA = (SPINEL_CAP_OPENTHREAD__BEGIN + 2), SPINEL_CAP_CHANNEL_MONITOR = (SPINEL_CAP_OPENTHREAD__BEGIN + 3), SPINEL_CAP_ERROR_RATE_TRACKING = (SPINEL_CAP_OPENTHREAD__BEGIN + 4), + SPINEL_CAP_CHANNEL_MANAGER = (SPINEL_CAP_OPENTHREAD__BEGIN + 5), SPINEL_CAP_OPENTHREAD__END = 640, SPINEL_CAP_THREAD__BEGIN = 1024, @@ -1420,6 +1421,53 @@ typedef enum SPINEL_PROP_STREAM_NET_INSECURE = SPINEL_PROP_STREAM__BEGIN + 3, ///< [dD] SPINEL_PROP_STREAM__END = 0x80, + SPINEL_PROP_OPENTHREAD__BEGIN = 0x1900, + + /// Channel Manager - Channel Change New Channel + /** Format: `C` (read-write) + * + * Required capability: SPINEL_CAP_CHANNEL_MANAGER + * + * Setting this property triggers the Channel Manager to start + * a channel change process. The network switches to the given + * channel after the specified delay (see `CHANNEL_MANAGER_DELAY`). + * + * A subsequent write to this property will cancel an ongoing + * (previously requested) channel change. + * + */ + SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL + = SPINEL_PROP_OPENTHREAD__BEGIN + 0, + + /// Channel Manager - Channel Change Delay + /** Format 'S' + * Units: seconds + * + * Required capability: SPINEL_CAP_CHANNEL_MANAGER + * + * This property specifies the delay (in seconds) to be used for + * a channel change request. + * + * The delay should preferably be longer than maximum data poll + * interval used by all sleepy-end-devices within the Thread + * network. + * + */ + SPINEL_PROP_CHANNEL_MANAGER_DELAY = SPINEL_PROP_OPENTHREAD__BEGIN + 1, + + /// Channel Manager Supported Channels + /** Format 'A(C)' + * + * Required capability: SPINEL_CAP_CHANNEL_MANAGER + * + * This property specifies the list of supported channels. + * + */ + SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS + = SPINEL_PROP_OPENTHREAD__BEGIN + 2, + + SPINEL_PROP_OPENTHREAD__END = 0x2000, + /// UART Bitrate /** Format: `L` *