diff --git a/include/openthread.h b/include/openthread.h index b670f811c..ea5ec44a0 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -1746,6 +1746,10 @@ OTAPI void OTCALL otSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRou * @param[in] aChildId The Child ID or RLOC16 for the attached child. * @param[out] aChildInfo A pointer to where the child information is placed. * + * @retavl kThreadError_None @p aChildInfo was successfully updated with the info for the given ID. + * @retval kThreadError_NotFound No valid child with this Child ID. + * @retavl kThreadError_InvalidArgs If @p aChildInfo is NULL. + * */ OTAPI ThreadError OTCALL otGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChildInfo *aChildInfo); @@ -1756,6 +1760,13 @@ OTAPI ThreadError OTCALL otGetChildInfoById(otInstance *aInstance, uint16_t aChi * @param[in] aChildIndex The table index. * @param[out] aChildInfo A pointer to where the child information is placed. * + * @retavl kThreadError_None @p aChildInfo was successfully updated with the info for the given index. + * @retval kThreadError_NotFound No valid child at this index. + * @retavl kThreadError_InvalidArgs Either @p aChildInfo is NULL, or @p aChildIndex is out of range (higher + * than max table index). + * + * @sa otGetMaxAllowedChildren + * */ OTAPI ThreadError OTCALL otGetChildInfoByIndex(otInstance *aInstance, uint8_t aChildIndex, otChildInfo *aChildInfo); diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 84fa9ef06..fdb1e86b8 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -356,6 +356,7 @@ void Interpreter::ProcessChild(int argc, char *argv[]) { ThreadError error = kThreadError_None; otChildInfo childInfo; + uint8_t maxChildren; long value; bool isTable = false; @@ -369,7 +370,9 @@ void Interpreter::ProcessChild(int argc, char *argv[]) sServer->OutputFormat("+-----+--------+------------+------------+--------+------+-+-+-+-+------------------+\r\n"); } - for (uint8_t i = 0; ; i++) + maxChildren = otGetMaxAllowedChildren(mInstance); + + for (uint8_t i = 0; i < maxChildren ; i++) { if (otGetChildInfoByIndex(mInstance, i, &childInfo) != kThreadError_None) { diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 679161a12..5ed80f99f 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -3335,7 +3335,7 @@ ThreadError MleRouter::GetChildInfoById(uint16_t aChildId, otChildInfo &aChildIn } VerifyOrExit((child = FindChild(aChildId)) != NULL, error = kThreadError_NotFound); - GetChildInfo(*child, aChildInfo); + error = GetChildInfo(*child, aChildInfo); exit: return error; @@ -3346,7 +3346,7 @@ ThreadError MleRouter::GetChildInfoByIndex(uint8_t aChildIndex, otChildInfo &aCh ThreadError error = kThreadError_None; VerifyOrExit(aChildIndex < mMaxChildrenAllowed, error = kThreadError_InvalidArgs); - GetChildInfo(mChildren[aChildIndex], aChildInfo); + error = GetChildInfo(mChildren[aChildIndex], aChildInfo); exit: return error; @@ -3425,26 +3425,29 @@ exit: return error; } -void MleRouter::GetChildInfo(Child &aChild, otChildInfo &aChildInfo) +ThreadError MleRouter::GetChildInfo(Child &aChild, otChildInfo &aChildInfo) { + ThreadError error = kThreadError_None; + + VerifyOrExit(aChild.mState == Neighbor::kStateValid, error = kThreadError_NotFound); + memset(&aChildInfo, 0, sizeof(aChildInfo)); + memcpy(&aChildInfo.mExtAddress, &aChild.mMacAddr, sizeof(aChildInfo.mExtAddress)); + aChildInfo.mTimeout = aChild.mTimeout; + aChildInfo.mRloc16 = aChild.mValid.mRloc16; + aChildInfo.mChildId = GetChildId(aChild.mValid.mRloc16); + aChildInfo.mNetworkDataVersion = aChild.mNetworkDataVersion; + aChildInfo.mAge = Timer::MsecToSec(Timer::GetNow() - aChild.mLastHeard); + aChildInfo.mLinkQualityIn = aChild.mLinkInfo.GetLinkQuality(mNetif.GetMac().GetNoiseFloor()); + aChildInfo.mAverageRssi = aChild.mLinkInfo.GetAverageRss(); - if (aChild.mState == Neighbor::kStateValid) - { - memcpy(&aChildInfo.mExtAddress, &aChild.mMacAddr, sizeof(aChildInfo.mExtAddress)); - aChildInfo.mTimeout = aChild.mTimeout; - aChildInfo.mRloc16 = aChild.mValid.mRloc16; - aChildInfo.mChildId = GetChildId(aChild.mValid.mRloc16); - aChildInfo.mNetworkDataVersion = aChild.mNetworkDataVersion; - aChildInfo.mAge = Timer::MsecToSec(Timer::GetNow() - aChild.mLastHeard); - aChildInfo.mLinkQualityIn = aChild.mLinkInfo.GetLinkQuality(mNetif.GetMac().GetNoiseFloor()); - aChildInfo.mAverageRssi = aChild.mLinkInfo.GetAverageRss(); + aChildInfo.mRxOnWhenIdle = (aChild.mMode & ModeTlv::kModeRxOnWhenIdle) != 0; + aChildInfo.mSecureDataRequest = (aChild.mMode & ModeTlv::kModeSecureDataRequest) != 0; + aChildInfo.mFullFunction = (aChild.mMode & ModeTlv::kModeFFD) != 0; + aChildInfo.mFullNetworkData = (aChild.mMode & ModeTlv::kModeFullNetworkData) != 0; - aChildInfo.mRxOnWhenIdle = (aChild.mMode & ModeTlv::kModeRxOnWhenIdle) != 0; - aChildInfo.mSecureDataRequest = (aChild.mMode & ModeTlv::kModeSecureDataRequest) != 0; - aChildInfo.mFullFunction = (aChild.mMode & ModeTlv::kModeFFD) != 0; - aChildInfo.mFullNetworkData = (aChild.mMode & ModeTlv::kModeFullNetworkData) != 0; - } +exit: + return error; } ThreadError MleRouter::GetRouterInfo(uint16_t aRouterId, otRouterInfo &aRouterInfo) diff --git a/src/core/thread/mle_router_ftd.hpp b/src/core/thread/mle_router_ftd.hpp index 9cbe22b78..1099d7acc 100644 --- a/src/core/thread/mle_router_ftd.hpp +++ b/src/core/thread/mle_router_ftd.hpp @@ -616,7 +616,7 @@ private: ThreadError AppendRoute(Message &aMessage); ThreadError AppendActiveDataset(Message &aMessage); ThreadError AppendPendingDataset(Message &aMessage); - void GetChildInfo(Child &aChild, otChildInfo &aChildInfo); + ThreadError GetChildInfo(Child &aChild, otChildInfo &aChildInfo); ThreadError HandleDetachStart(void); ThreadError HandleChildStart(otMleAttachFilter aFilter); ThreadError HandleLinkRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 87f40018c..a372c9606 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -2328,7 +2328,7 @@ ThreadError NcpBase::GetPropertyHandler_THREAD_CHILD_TABLE(uint8_t header, spine { ThreadError errorCode = kThreadError_None; otChildInfo childInfo; - uint8_t index; + uint8_t maxChildren; uint8_t modeFlags; mDisableStreamWrite = true; @@ -2336,58 +2336,60 @@ ThreadError NcpBase::GetPropertyHandler_THREAD_CHILD_TABLE(uint8_t header, spine SuccessOrExit(errorCode = OutboundFrameBegin()); SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key)); - index = 0; + maxChildren = otGetMaxAllowedChildren(mInstance); - while (otGetChildInfoByIndex(mInstance, index, &childInfo) == kThreadError_None) + for (uint8_t index = 0; index < maxChildren; index++) { - if (childInfo.mTimeout > 0) + errorCode = otGetChildInfoByIndex(mInstance, index, &childInfo); + + if (errorCode != kThreadError_None) { - modeFlags = 0; - - if (childInfo.mRxOnWhenIdle) - { - modeFlags |= kThreadMode_RxOnWhenIdle; - } - - if (childInfo.mSecureDataRequest) - { - modeFlags |= kThreadMode_SecureDataRequest; - } - - if (childInfo.mFullFunction) - { - modeFlags |= kThreadMode_FullFunctionDevice; - } - - if (childInfo.mFullNetworkData) - { - modeFlags |= kThreadMode_FullNetworkData; - } - - SuccessOrExit( - errorCode = OutboundFrameFeedPacked( - "T(" - 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) - ")", - childInfo.mExtAddress.m8, - childInfo.mRloc16, - childInfo.mTimeout, - childInfo.mAge, - childInfo.mNetworkDataVersion, - childInfo.mLinkQualityIn, - childInfo.mAverageRssi, - modeFlags - )); + continue; } - index++; + modeFlags = 0; + + if (childInfo.mRxOnWhenIdle) + { + modeFlags |= kThreadMode_RxOnWhenIdle; + } + + if (childInfo.mSecureDataRequest) + { + modeFlags |= kThreadMode_SecureDataRequest; + } + + if (childInfo.mFullFunction) + { + modeFlags |= kThreadMode_FullFunctionDevice; + } + + if (childInfo.mFullNetworkData) + { + modeFlags |= kThreadMode_FullNetworkData; + } + + SuccessOrExit( + errorCode = OutboundFrameFeedPacked( + "T(" + 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) + ")", + childInfo.mExtAddress.m8, + childInfo.mRloc16, + childInfo.mTimeout, + childInfo.mAge, + childInfo.mNetworkDataVersion, + childInfo.mLinkQualityIn, + childInfo.mAverageRssi, + modeFlags + )); } SuccessOrExit(errorCode = OutboundFrameSend());