1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements the OpenThread Thread API (for both FTD and MTD).
32  */
33 
34 #include "openthread-core-config.h"
35 
36 #if OPENTHREAD_FTD || OPENTHREAD_MTD
37 
38 #include <openthread/thread.h>
39 
40 #include "common/as_core_type.hpp"
41 #include "common/debug.hpp"
42 #include "common/locator_getters.hpp"
43 #include "common/uptime.hpp"
44 #include "thread/version.hpp"
45 
46 using namespace ot;
47 
otThreadGetChildTimeout(otInstance * aInstance)48 uint32_t otThreadGetChildTimeout(otInstance *aInstance)
49 {
50     return AsCoreType(aInstance).Get<Mle::MleRouter>().GetTimeout();
51 }
52 
otThreadSetChildTimeout(otInstance * aInstance,uint32_t aTimeout)53 void otThreadSetChildTimeout(otInstance *aInstance, uint32_t aTimeout)
54 {
55     AsCoreType(aInstance).Get<Mle::MleRouter>().SetTimeout(aTimeout);
56 }
57 
otThreadGetExtendedPanId(otInstance * aInstance)58 const otExtendedPanId *otThreadGetExtendedPanId(otInstance *aInstance)
59 {
60     return &AsCoreType(aInstance).Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId();
61 }
62 
otThreadSetExtendedPanId(otInstance * aInstance,const otExtendedPanId * aExtendedPanId)63 otError otThreadSetExtendedPanId(otInstance *aInstance, const otExtendedPanId *aExtendedPanId)
64 {
65     Error                         error    = kErrorNone;
66     Instance                     &instance = AsCoreType(aInstance);
67     const MeshCoP::ExtendedPanId &extPanId = AsCoreType(aExtendedPanId);
68 
69     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
70 
71     instance.Get<MeshCoP::ExtendedPanIdManager>().SetExtPanId(extPanId);
72 
73     instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
74     instance.Get<MeshCoP::PendingDatasetManager>().Clear();
75 
76 exit:
77     return error;
78 }
79 
otThreadGetLeaderRloc(otInstance * aInstance,otIp6Address * aLeaderRloc)80 otError otThreadGetLeaderRloc(otInstance *aInstance, otIp6Address *aLeaderRloc)
81 {
82     Error error = kErrorNone;
83 
84     VerifyOrExit(!AsCoreType(aInstance).Get<Mle::Mle>().HasRloc16(Mle::kInvalidRloc16), error = kErrorDetached);
85     AsCoreType(aInstance).Get<Mle::Mle>().GetLeaderRloc(AsCoreType(aLeaderRloc));
86 
87 exit:
88     return error;
89 }
90 
otThreadGetLinkMode(otInstance * aInstance)91 otLinkModeConfig otThreadGetLinkMode(otInstance *aInstance)
92 {
93     otLinkModeConfig config;
94 
95     AsCoreType(aInstance).Get<Mle::MleRouter>().GetDeviceMode().Get(config);
96 
97     return config;
98 }
99 
otThreadSetLinkMode(otInstance * aInstance,otLinkModeConfig aConfig)100 otError otThreadSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig)
101 {
102     return AsCoreType(aInstance).Get<Mle::MleRouter>().SetDeviceMode(Mle::DeviceMode(aConfig));
103 }
104 
otThreadGetNetworkKey(otInstance * aInstance,otNetworkKey * aNetworkKey)105 void otThreadGetNetworkKey(otInstance *aInstance, otNetworkKey *aNetworkKey)
106 {
107     AsCoreType(aInstance).Get<KeyManager>().GetNetworkKey(AsCoreType(aNetworkKey));
108 }
109 
110 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
otThreadGetNetworkKeyRef(otInstance * aInstance)111 otNetworkKeyRef otThreadGetNetworkKeyRef(otInstance *aInstance)
112 {
113     return AsCoreType(aInstance).Get<KeyManager>().GetNetworkKeyRef();
114 }
115 #endif
116 
otThreadSetNetworkKey(otInstance * aInstance,const otNetworkKey * aKey)117 otError otThreadSetNetworkKey(otInstance *aInstance, const otNetworkKey *aKey)
118 {
119     Error     error    = kErrorNone;
120     Instance &instance = AsCoreType(aInstance);
121 
122     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
123 
124     instance.Get<KeyManager>().SetNetworkKey(AsCoreType(aKey));
125 
126     instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
127     instance.Get<MeshCoP::PendingDatasetManager>().Clear();
128 
129 exit:
130     return error;
131 }
132 
133 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
otThreadSetNetworkKeyRef(otInstance * aInstance,otNetworkKeyRef aKeyRef)134 otError otThreadSetNetworkKeyRef(otInstance *aInstance, otNetworkKeyRef aKeyRef)
135 {
136     Error     error    = kErrorNone;
137     Instance &instance = AsCoreType(aInstance);
138 
139     VerifyOrExit(aKeyRef != 0, error = kErrorInvalidArgs);
140 
141     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
142 
143     instance.Get<KeyManager>().SetNetworkKeyRef((aKeyRef));
144     instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
145     instance.Get<MeshCoP::PendingDatasetManager>().Clear();
146 
147 exit:
148     return error;
149 }
150 #endif
151 
otThreadGetRloc(otInstance * aInstance)152 const otIp6Address *otThreadGetRloc(otInstance *aInstance)
153 {
154     return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetMeshLocalRloc();
155 }
156 
otThreadGetMeshLocalEid(otInstance * aInstance)157 const otIp6Address *otThreadGetMeshLocalEid(otInstance *aInstance)
158 {
159     return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetMeshLocalEid();
160 }
161 
otThreadGetMeshLocalPrefix(otInstance * aInstance)162 const otMeshLocalPrefix *otThreadGetMeshLocalPrefix(otInstance *aInstance)
163 {
164     return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetMeshLocalPrefix();
165 }
166 
otThreadSetMeshLocalPrefix(otInstance * aInstance,const otMeshLocalPrefix * aMeshLocalPrefix)167 otError otThreadSetMeshLocalPrefix(otInstance *aInstance, const otMeshLocalPrefix *aMeshLocalPrefix)
168 {
169     Error error = kErrorNone;
170 
171     VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
172 
173     AsCoreType(aInstance).Get<Mle::MleRouter>().SetMeshLocalPrefix(AsCoreType(aMeshLocalPrefix));
174     AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Clear();
175     AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Clear();
176 
177 exit:
178     return error;
179 }
180 
otThreadGetLinkLocalIp6Address(otInstance * aInstance)181 const otIp6Address *otThreadGetLinkLocalIp6Address(otInstance *aInstance)
182 {
183     return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetLinkLocalAddress();
184 }
185 
otThreadGetLinkLocalAllThreadNodesMulticastAddress(otInstance * aInstance)186 const otIp6Address *otThreadGetLinkLocalAllThreadNodesMulticastAddress(otInstance *aInstance)
187 {
188     return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetLinkLocalAllThreadNodesAddress();
189 }
190 
otThreadGetRealmLocalAllThreadNodesMulticastAddress(otInstance * aInstance)191 const otIp6Address *otThreadGetRealmLocalAllThreadNodesMulticastAddress(otInstance *aInstance)
192 {
193     return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetRealmLocalAllThreadNodesAddress();
194 }
195 
otThreadGetServiceAloc(otInstance * aInstance,uint8_t aServiceId,otIp6Address * aServiceAloc)196 otError otThreadGetServiceAloc(otInstance *aInstance, uint8_t aServiceId, otIp6Address *aServiceAloc)
197 {
198     Error error = kErrorNone;
199 
200     VerifyOrExit(!AsCoreType(aInstance).Get<Mle::Mle>().HasRloc16(Mle::kInvalidRloc16), error = kErrorDetached);
201     AsCoreType(aInstance).Get<Mle::Mle>().GetServiceAloc(aServiceId, AsCoreType(aServiceAloc));
202 
203 exit:
204     return error;
205 }
206 
otThreadGetNetworkName(otInstance * aInstance)207 const char *otThreadGetNetworkName(otInstance *aInstance)
208 {
209     return AsCoreType(aInstance).Get<MeshCoP::NetworkNameManager>().GetNetworkName().GetAsCString();
210 }
211 
otThreadSetNetworkName(otInstance * aInstance,const char * aNetworkName)212 otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName)
213 {
214     Error error = kErrorNone;
215 
216     VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
217 
218 #if !OPENTHREAD_CONFIG_ALLOW_EMPTY_NETWORK_NAME
219     // Thread interfaces support a zero length name internally for backwards compatibility, but new names
220     // must be at least one valid character long.
221     VerifyOrExit(nullptr != aNetworkName && aNetworkName[0] != '\0', error = kErrorInvalidArgs);
222 #endif
223 
224     error = AsCoreType(aInstance).Get<MeshCoP::NetworkNameManager>().SetNetworkName(aNetworkName);
225     AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Clear();
226     AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Clear();
227 
228 exit:
229     return error;
230 }
231 
232 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
otThreadGetDomainName(otInstance * aInstance)233 const char *otThreadGetDomainName(otInstance *aInstance)
234 {
235     return AsCoreType(aInstance).Get<MeshCoP::NetworkNameManager>().GetDomainName().GetAsCString();
236 }
237 
otThreadSetDomainName(otInstance * aInstance,const char * aDomainName)238 otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName)
239 {
240     Error error = kErrorNone;
241 
242     VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
243 
244     error = AsCoreType(aInstance).Get<MeshCoP::NetworkNameManager>().SetDomainName(aDomainName);
245 
246 exit:
247     return error;
248 }
249 
250 #if OPENTHREAD_CONFIG_DUA_ENABLE
otThreadSetFixedDuaInterfaceIdentifier(otInstance * aInstance,const otIp6InterfaceIdentifier * aIid)251 otError otThreadSetFixedDuaInterfaceIdentifier(otInstance *aInstance, const otIp6InterfaceIdentifier *aIid)
252 {
253     Error error = kErrorNone;
254 
255     if (aIid)
256     {
257         error = AsCoreType(aInstance).Get<DuaManager>().SetFixedDuaInterfaceIdentifier(AsCoreType(aIid));
258     }
259     else
260     {
261         AsCoreType(aInstance).Get<DuaManager>().ClearFixedDuaInterfaceIdentifier();
262     }
263 
264     return error;
265 }
266 
otThreadGetFixedDuaInterfaceIdentifier(otInstance * aInstance)267 const otIp6InterfaceIdentifier *otThreadGetFixedDuaInterfaceIdentifier(otInstance *aInstance)
268 {
269     Instance                       &instance = AsCoreType(aInstance);
270     const otIp6InterfaceIdentifier *iid      = nullptr;
271 
272     if (instance.Get<DuaManager>().IsFixedDuaInterfaceIdentifierSet())
273     {
274         iid = &instance.Get<DuaManager>().GetFixedDuaInterfaceIdentifier();
275     }
276 
277     return iid;
278 }
279 #endif // OPENTHREAD_CONFIG_DUA_ENABLE
280 
281 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
282 
otThreadGetKeySequenceCounter(otInstance * aInstance)283 uint32_t otThreadGetKeySequenceCounter(otInstance *aInstance)
284 {
285     return AsCoreType(aInstance).Get<KeyManager>().GetCurrentKeySequence();
286 }
287 
otThreadSetKeySequenceCounter(otInstance * aInstance,uint32_t aKeySequenceCounter)288 void otThreadSetKeySequenceCounter(otInstance *aInstance, uint32_t aKeySequenceCounter)
289 {
290     AsCoreType(aInstance).Get<KeyManager>().SetCurrentKeySequence(
291         aKeySequenceCounter, KeyManager::kForceUpdate | KeyManager::kGuardTimerUnchanged);
292 }
293 
otThreadGetKeySwitchGuardTime(otInstance * aInstance)294 uint16_t otThreadGetKeySwitchGuardTime(otInstance *aInstance)
295 {
296     return AsCoreType(aInstance).Get<KeyManager>().GetKeySwitchGuardTime();
297 }
298 
otThreadSetKeySwitchGuardTime(otInstance * aInstance,uint16_t aKeySwitchGuardTime)299 void otThreadSetKeySwitchGuardTime(otInstance *aInstance, uint16_t aKeySwitchGuardTime)
300 {
301     AsCoreType(aInstance).Get<KeyManager>().SetKeySwitchGuardTime(aKeySwitchGuardTime);
302 }
303 
otThreadBecomeDetached(otInstance * aInstance)304 otError otThreadBecomeDetached(otInstance *aInstance)
305 {
306     return AsCoreType(aInstance).Get<Mle::MleRouter>().BecomeDetached();
307 }
308 
otThreadBecomeChild(otInstance * aInstance)309 otError otThreadBecomeChild(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mle::MleRouter>().BecomeChild(); }
310 
otThreadGetNextNeighborInfo(otInstance * aInstance,otNeighborInfoIterator * aIterator,otNeighborInfo * aInfo)311 otError otThreadGetNextNeighborInfo(otInstance *aInstance, otNeighborInfoIterator *aIterator, otNeighborInfo *aInfo)
312 {
313     AssertPointerIsNotNull(aIterator);
314 
315     return AsCoreType(aInstance).Get<NeighborTable>().GetNextNeighborInfo(*aIterator, AsCoreType(aInfo));
316 }
317 
otThreadGetDeviceRole(otInstance * aInstance)318 otDeviceRole otThreadGetDeviceRole(otInstance *aInstance)
319 {
320     return MapEnum(AsCoreType(aInstance).Get<Mle::MleRouter>().GetRole());
321 }
322 
otThreadDeviceRoleToString(otDeviceRole aRole)323 const char *otThreadDeviceRoleToString(otDeviceRole aRole) { return Mle::RoleToString(MapEnum(aRole)); }
324 
otThreadGetLeaderData(otInstance * aInstance,otLeaderData * aLeaderData)325 otError otThreadGetLeaderData(otInstance *aInstance, otLeaderData *aLeaderData)
326 {
327     Error error = kErrorNone;
328 
329     AssertPointerIsNotNull(aLeaderData);
330 
331     VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsAttached(), error = kErrorDetached);
332     *aLeaderData = AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderData();
333 
334 exit:
335     return error;
336 }
337 
otThreadGetLeaderRouterId(otInstance * aInstance)338 uint8_t otThreadGetLeaderRouterId(otInstance *aInstance)
339 {
340     return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderId();
341 }
342 
otThreadGetLeaderWeight(otInstance * aInstance)343 uint8_t otThreadGetLeaderWeight(otInstance *aInstance)
344 {
345     return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderData().GetWeighting();
346 }
347 
otThreadGetPartitionId(otInstance * aInstance)348 uint32_t otThreadGetPartitionId(otInstance *aInstance)
349 {
350     return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderData().GetPartitionId();
351 }
352 
otThreadGetRloc16(otInstance * aInstance)353 uint16_t otThreadGetRloc16(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mle::MleRouter>().GetRloc16(); }
354 
otThreadGetParentInfo(otInstance * aInstance,otRouterInfo * aParentInfo)355 otError otThreadGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo)
356 {
357     return AsCoreType(aInstance).Get<Mle::Mle>().GetParentInfo(AsCoreType(aParentInfo));
358 }
359 
otThreadGetParentAverageRssi(otInstance * aInstance,int8_t * aParentRssi)360 otError otThreadGetParentAverageRssi(otInstance *aInstance, int8_t *aParentRssi)
361 {
362     Error error = kErrorNone;
363 
364     AssertPointerIsNotNull(aParentRssi);
365 
366     *aParentRssi = AsCoreType(aInstance).Get<Mle::MleRouter>().GetParent().GetLinkInfo().GetAverageRss();
367 
368     VerifyOrExit(*aParentRssi != Radio::kInvalidRssi, error = kErrorFailed);
369 
370 exit:
371     return error;
372 }
373 
otThreadGetParentLastRssi(otInstance * aInstance,int8_t * aLastRssi)374 otError otThreadGetParentLastRssi(otInstance *aInstance, int8_t *aLastRssi)
375 {
376     Error error = kErrorNone;
377 
378     AssertPointerIsNotNull(aLastRssi);
379 
380     *aLastRssi = AsCoreType(aInstance).Get<Mle::MleRouter>().GetParent().GetLinkInfo().GetLastRss();
381 
382     VerifyOrExit(*aLastRssi != Radio::kInvalidRssi, error = kErrorFailed);
383 
384 exit:
385     return error;
386 }
387 
otThreadSearchForBetterParent(otInstance * aInstance)388 otError otThreadSearchForBetterParent(otInstance *aInstance)
389 {
390     return AsCoreType(aInstance).Get<Mle::Mle>().SearchForBetterParent();
391 }
392 
otThreadSetEnabled(otInstance * aInstance,bool aEnabled)393 otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled)
394 {
395     Error error = kErrorNone;
396 
397     if (aEnabled)
398     {
399         error = AsCoreType(aInstance).Get<Mle::MleRouter>().Start();
400     }
401     else
402     {
403         AsCoreType(aInstance).Get<Mle::MleRouter>().Stop();
404     }
405 
406     return error;
407 }
408 
otThreadGetVersion(void)409 uint16_t otThreadGetVersion(void) { return kThreadVersion; }
410 
otThreadIsSingleton(otInstance * aInstance)411 bool otThreadIsSingleton(otInstance *aInstance)
412 {
413     bool isSingleton = false;
414 
415 #if OPENTHREAD_FTD
416     isSingleton = AsCoreType(aInstance).Get<Mle::MleRouter>().IsSingleton();
417 #else
418     OT_UNUSED_VARIABLE(aInstance);
419 #endif
420 
421     return isSingleton;
422 }
423 
otThreadDiscover(otInstance * aInstance,uint32_t aScanChannels,uint16_t aPanId,bool aJoiner,bool aEnableEui64Filtering,otHandleActiveScanResult aCallback,void * aCallbackContext)424 otError otThreadDiscover(otInstance              *aInstance,
425                          uint32_t                 aScanChannels,
426                          uint16_t                 aPanId,
427                          bool                     aJoiner,
428                          bool                     aEnableEui64Filtering,
429                          otHandleActiveScanResult aCallback,
430                          void                    *aCallbackContext)
431 {
432     return AsCoreType(aInstance).Get<Mle::DiscoverScanner>().Discover(
433         Mac::ChannelMask(aScanChannels), aPanId, aJoiner, aEnableEui64Filtering,
434         /* aFilterIndexes (use hash of factory EUI64) */ nullptr, aCallback, aCallbackContext);
435 }
436 
otThreadSetJoinerAdvertisement(otInstance * aInstance,uint32_t aOui,const uint8_t * aAdvData,uint8_t aAdvDataLength)437 otError otThreadSetJoinerAdvertisement(otInstance    *aInstance,
438                                        uint32_t       aOui,
439                                        const uint8_t *aAdvData,
440                                        uint8_t        aAdvDataLength)
441 {
442     return AsCoreType(aInstance).Get<Mle::DiscoverScanner>().SetJoinerAdvertisement(aOui, aAdvData, aAdvDataLength);
443 }
444 
otThreadIsDiscoverInProgress(otInstance * aInstance)445 bool otThreadIsDiscoverInProgress(otInstance *aInstance)
446 {
447     return AsCoreType(aInstance).Get<Mle::DiscoverScanner>().IsInProgress();
448 }
449 
otThreadGetIp6Counters(otInstance * aInstance)450 const otIpCounters *otThreadGetIp6Counters(otInstance *aInstance)
451 {
452     return &AsCoreType(aInstance).Get<MeshForwarder>().GetCounters();
453 }
454 
otThreadResetIp6Counters(otInstance * aInstance)455 void otThreadResetIp6Counters(otInstance *aInstance) { AsCoreType(aInstance).Get<MeshForwarder>().ResetCounters(); }
456 
457 #if OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE
otThreadGetTimeInQueueHistogram(otInstance * aInstance,uint16_t * aNumBins,uint32_t * aBinInterval)458 const uint32_t *otThreadGetTimeInQueueHistogram(otInstance *aInstance, uint16_t *aNumBins, uint32_t *aBinInterval)
459 {
460     AssertPointerIsNotNull(aNumBins);
461     AssertPointerIsNotNull(aBinInterval);
462 
463     return AsCoreType(aInstance).Get<MeshForwarder>().GetTimeInQueueHistogram(*aNumBins, *aBinInterval);
464 }
465 
otThreadGetMaxTimeInQueue(otInstance * aInstance)466 uint32_t otThreadGetMaxTimeInQueue(otInstance *aInstance)
467 {
468     return AsCoreType(aInstance).Get<MeshForwarder>().GetMaxTimeInQueue();
469 }
470 
otThreadResetTimeInQueueStat(otInstance * aInstance)471 void otThreadResetTimeInQueueStat(otInstance *aInstance)
472 {
473     return AsCoreType(aInstance).Get<MeshForwarder>().ResetTimeInQueueStat();
474 }
475 #endif
476 
otThreadGetMleCounters(otInstance * aInstance)477 const otMleCounters *otThreadGetMleCounters(otInstance *aInstance)
478 {
479     return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetCounters();
480 }
481 
otThreadResetMleCounters(otInstance * aInstance)482 void otThreadResetMleCounters(otInstance *aInstance) { AsCoreType(aInstance).Get<Mle::MleRouter>().ResetCounters(); }
483 
484 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
otThreadRegisterParentResponseCallback(otInstance * aInstance,otThreadParentResponseCallback aCallback,void * aContext)485 void otThreadRegisterParentResponseCallback(otInstance                    *aInstance,
486                                             otThreadParentResponseCallback aCallback,
487                                             void                          *aContext)
488 {
489     AsCoreType(aInstance).Get<Mle::MleRouter>().RegisterParentResponseStatsCallback(aCallback, aContext);
490 }
491 #endif
492 
493 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
otThreadLocateAnycastDestination(otInstance * aInstance,const otIp6Address * aAnycastAddress,otThreadAnycastLocatorCallback aCallback,void * aContext)494 otError otThreadLocateAnycastDestination(otInstance                    *aInstance,
495                                          const otIp6Address            *aAnycastAddress,
496                                          otThreadAnycastLocatorCallback aCallback,
497                                          void                          *aContext)
498 {
499     return AsCoreType(aInstance).Get<AnycastLocator>().Locate(AsCoreType(aAnycastAddress), aCallback, aContext);
500 }
501 
otThreadIsAnycastLocateInProgress(otInstance * aInstance)502 bool otThreadIsAnycastLocateInProgress(otInstance *aInstance)
503 {
504     return AsCoreType(aInstance).Get<AnycastLocator>().IsInProgress();
505 }
506 #endif
507 
otThreadDetachGracefully(otInstance * aInstance,otDetachGracefullyCallback aCallback,void * aContext)508 otError otThreadDetachGracefully(otInstance *aInstance, otDetachGracefullyCallback aCallback, void *aContext)
509 {
510     return AsCoreType(aInstance).Get<Mle::MleRouter>().DetachGracefully(aCallback, aContext);
511 }
512 
513 #if OPENTHREAD_CONFIG_DYNAMIC_STORE_FRAME_AHEAD_COUNTER_ENABLE
otThreadSetStoreFrameCounterAhead(otInstance * aInstance,uint32_t aStoreFrameCounterAhead)514 void otThreadSetStoreFrameCounterAhead(otInstance *aInstance, uint32_t aStoreFrameCounterAhead)
515 {
516     return AsCoreType(aInstance).Get<Mle::Mle>().SetStoreFrameCounterAhead(aStoreFrameCounterAhead);
517 }
518 
otThreadGetStoreFrameCounterAhead(otInstance * aInstance)519 uint32_t otThreadGetStoreFrameCounterAhead(otInstance *aInstance)
520 {
521     return AsCoreType(aInstance).Get<Mle::Mle>().GetStoreFrameCounterAhead();
522 }
523 #endif
524 
525 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
526 
527 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
otConvertDurationInSecondsToString(uint32_t aDuration,char * aBuffer,uint16_t aSize)528 void otConvertDurationInSecondsToString(uint32_t aDuration, char *aBuffer, uint16_t aSize)
529 {
530     StringWriter writer(aBuffer, aSize);
531 
532     Uptime::UptimeToString(Uptime::SecToMsec(aDuration), writer, /* aIncludeMsec */ false);
533 }
534 #endif
535