diff --git a/include/openthread-types.h b/include/openthread-types.h index f60710dfc..cf5a0a04e 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -215,6 +215,12 @@ enum OT_SECURITY_POLICY_BEACONS = 1 << 3, ///< Beacons enabled }; +/** + * This type represents Channel Mask Page 0. + * + */ +typedef uint32_t otChannelMaskPage0; + /** * This type represents the IEEE 802.15.4 PAN ID. * @@ -340,29 +346,31 @@ typedef struct otEnergyScanResult */ typedef struct otOperationalDataset { - uint64_t mActiveTimestamp; ///< Active Timestamp - uint64_t mPendingTimestamp; ///< Pending Timestamp - otMasterKey mMasterKey; ///< Network Master Key - otNetworkName mNetworkName; ///< Network Name - otExtendedPanId mExtendedPanId; ///< Extended PAN ID - otMeshLocalPrefix mMeshLocalPrefix; ///< Mesh Local Prefix - uint32_t mDelay; ///< Delay Timer - otPanId mPanId; ///< PAN ID - uint16_t mChannel; ///< Channel - otPSKc mPSKc; ///< PSKc - otSecurityPolicy mSecurityPolicy; ///< Security Policy + uint64_t mActiveTimestamp; ///< Active Timestamp + uint64_t mPendingTimestamp; ///< Pending Timestamp + otMasterKey mMasterKey; ///< Network Master Key + otNetworkName mNetworkName; ///< Network Name + otExtendedPanId mExtendedPanId; ///< Extended PAN ID + otMeshLocalPrefix mMeshLocalPrefix; ///< Mesh Local Prefix + uint32_t mDelay; ///< Delay Timer + otPanId mPanId; ///< PAN ID + uint16_t mChannel; ///< Channel + otPSKc mPSKc; ///< PSKc + otSecurityPolicy mSecurityPolicy; ///< Security Policy + otChannelMaskPage0 mChannelMaskPage0; ///< Channel Mask Page 0 - bool mIsActiveTimestampSet : 1; ///< TRUE if Active Timestamp is set, FALSE otherwise. - bool mIsPendingTimestampSet : 1; ///< TRUE if Pending Timestamp is set, FALSE otherwise. - bool mIsMasterKeySet : 1; ///< TRUE if Network Master Key is set, FALSE otherwise. - bool mIsNetworkNameSet : 1; ///< TRUE if Network Name is set, FALSE otherwise. - bool mIsExtendedPanIdSet : 1; ///< TRUE if Extended PAN ID is set, FALSE otherwise. - bool mIsMeshLocalPrefixSet : 1; ///< TRUE if Mesh Local Prefix is set, FALSE otherwise. - bool mIsDelaySet : 1; ///< TRUE if Delay Timer is set, FALSE otherwise. - bool mIsPanIdSet : 1; ///< TRUE if PAN ID is set, FALSE otherwise. - bool mIsChannelSet : 1; ///< TRUE if Channel is set, FALSE otherwise. - bool mIsPSKcSet : 1; ///< TRUE if PSKc is set, FALSE otherwise. - bool mIsSecurityPolicySet : 1; ///< TRUE if Security Policy is set, FALSE otherwise. + bool mIsActiveTimestampSet : 1; ///< TRUE if Active Timestamp is set, FALSE otherwise. + bool mIsPendingTimestampSet : 1; ///< TRUE if Pending Timestamp is set, FALSE otherwise. + bool mIsMasterKeySet : 1; ///< TRUE if Network Master Key is set, FALSE otherwise. + bool mIsNetworkNameSet : 1; ///< TRUE if Network Name is set, FALSE otherwise. + bool mIsExtendedPanIdSet : 1; ///< TRUE if Extended PAN ID is set, FALSE otherwise. + bool mIsMeshLocalPrefixSet : 1; ///< TRUE if Mesh Local Prefix is set, FALSE otherwise. + bool mIsDelaySet : 1; ///< TRUE if Delay Timer is set, FALSE otherwise. + bool mIsPanIdSet : 1; ///< TRUE if PAN ID is set, FALSE otherwise. + bool mIsChannelSet : 1; ///< TRUE if Channel is set, FALSE otherwise. + bool mIsPSKcSet : 1; ///< TRUE if PSKc is set, FALSE otherwise. + bool mIsSecurityPolicySet : 1; ///< TRUE if Security Policy is set, FALSE otherwise. + bool mIsChannelMaskPage0Set : 1; ///< TRUE if Channel Mask Page 0 is set, FALSE otherwise. } otOperationalDataset; /** diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index 502eed822..66644e4cd 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -55,6 +55,7 @@ const DatasetCommand Dataset::sCommands[] = { "active", &ProcessActive }, { "activetimestamp", &ProcessActiveTimestamp }, { "channel", &ProcessChannel }, + { "channelmask", &ProcessChannelMask }, { "clear", &ProcessClear }, { "commit", &ProcessCommit }, { "delay", &ProcessDelay }, @@ -99,6 +100,11 @@ ThreadError Dataset::Print(otOperationalDataset &aDataset) sServer->OutputFormat("Channel: %d\r\n", aDataset.mChannel); } + if (aDataset.mIsChannelMaskPage0Set) + { + sServer->OutputFormat("Channel Mask Page 0: %x\r\n", aDataset.mChannelMaskPage0); + } + if (aDataset.mIsDelaySet) { sServer->OutputFormat("Delay: %d\r\n", aDataset.mDelay); @@ -261,6 +267,21 @@ exit: return error; } +ThreadError Dataset::ProcessChannelMask(otInstance *aInstance, int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + long value; + + VerifyOrExit(argc > 0, error = kThreadError_Parse); + SuccessOrExit(error = Interpreter::ParseLong(argv[0], value)); + sDataset.mChannelMaskPage0 = static_cast(value); + sDataset.mIsChannelMaskPage0Set = true; + (void)aInstance; + +exit: + return error; +} + ThreadError Dataset::ProcessClear(otInstance *aInstance, int argc, char *argv[]) { memset(&sDataset, 0, sizeof(sDataset)); diff --git a/src/cli/cli_dataset.hpp b/src/cli/cli_dataset.hpp index c72f51335..c4159336b 100644 --- a/src/cli/cli_dataset.hpp +++ b/src/cli/cli_dataset.hpp @@ -77,6 +77,7 @@ private: static ThreadError ProcessActive(otInstance *aInstance, int argc, char *argv[]); static ThreadError ProcessActiveTimestamp(otInstance *aInstance, int argc, char *argv[]); static ThreadError ProcessChannel(otInstance *aInstance, int argc, char *argv[]); + static ThreadError ProcessChannelMask(otInstance *aInstance, int argc, char *argv[]); static ThreadError ProcessClear(otInstance *aInstance, int argc, char *argv[]); static ThreadError ProcessCommit(otInstance *aInstance, int argc, char *argv[]); static ThreadError ProcessDelay(otInstance *aInstance, int argc, char *argv[]); diff --git a/src/core/thread/meshcop_dataset.cpp b/src/core/thread/meshcop_dataset.cpp index 0784546b6..1379247a8 100644 --- a/src/core/thread/meshcop_dataset.cpp +++ b/src/core/thread/meshcop_dataset.cpp @@ -121,6 +121,30 @@ void Dataset::Get(otOperationalDataset &aDataset) break; } + case Tlv::kChannelMask: + { + uint8_t length = cur->GetLength(); + const uint8_t *entry = reinterpret_cast(cur) + sizeof(Tlv); + const uint8_t *entryEnd = entry + length; + + while (entry < entryEnd) + { + if (reinterpret_cast(entry)->GetChannelPage() == 0) + { + uint8_t i = sizeof(ChannelMaskEntry); + aDataset.mChannelMaskPage0 = static_cast(entry[i] | (entry[i + 1] << 8) | + (entry[i + 2] << 16) | (entry[i + 3] << 24)); + aDataset.mIsChannelMaskPage0Set = true; + break; + } + + entry += (reinterpret_cast(entry)->GetMaskLength() + + sizeof(ChannelMaskEntry)); + } + + break; + } + case Tlv::kDelayTimer: { const DelayTimerTlv *tlv = static_cast(cur); @@ -239,6 +263,30 @@ ThreadError Dataset::Set(const otOperationalDataset &aDataset, bool aActive) Set(tlv); } + if (aDataset.mIsChannelMaskPage0Set) + { + OT_TOOL_PACKED_BEGIN + struct + { + MeshCoP::ChannelMaskTlv tlv; + MeshCoP::ChannelMaskEntry entry; + uint8_t mask[sizeof(aDataset.mChannelMaskPage0)]; + } OT_TOOL_PACKED_END channelMask; + + channelMask.tlv.Init(); + channelMask.tlv.SetLength(sizeof(MeshCoP::ChannelMaskEntry) + sizeof(aDataset.mChannelMaskPage0)); + + channelMask.entry.SetChannelPage(0); + channelMask.entry.SetMaskLength(sizeof(aDataset.mChannelMaskPage0)); + + for (uint8_t index = 0; index < sizeof(aDataset.mChannelMaskPage0); index++) + { + channelMask.mask[index] = (aDataset.mChannelMaskPage0 >> (8 * index)) & 0xff; + } + + Set(channelMask.tlv); + } + if (aDataset.mIsDelaySet) { MeshCoP::DelayTimerTlv tlv;