• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Link API.
32  */
33 
34 #include "openthread-core-config.h"
35 
36 #include <openthread/link.h>
37 
38 #include "common/as_core_type.hpp"
39 #include "common/locator_getters.hpp"
40 #include "mac/mac.hpp"
41 #include "radio/radio.hpp"
42 
43 using namespace ot;
44 
otLinkGetChannel(otInstance * aInstance)45 uint8_t otLinkGetChannel(otInstance *aInstance)
46 {
47     Instance &instance = AsCoreType(aInstance);
48     uint8_t   channel;
49 
50 #if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
51     if (instance.Get<Mac::LinkRaw>().IsEnabled())
52     {
53         channel = instance.Get<Mac::LinkRaw>().GetChannel();
54     }
55     else
56 #endif
57     {
58         channel = instance.Get<Mac::Mac>().GetPanChannel();
59     }
60 
61     return channel;
62 }
63 
otLinkSetChannel(otInstance * aInstance,uint8_t aChannel)64 otError otLinkSetChannel(otInstance *aInstance, uint8_t aChannel)
65 {
66     Error     error;
67     Instance &instance = AsCoreType(aInstance);
68 
69 #if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
70     if (instance.Get<Mac::LinkRaw>().IsEnabled())
71     {
72         error = instance.Get<Mac::LinkRaw>().SetChannel(aChannel);
73         ExitNow();
74     }
75 #endif
76 
77     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
78 
79     SuccessOrExit(error = instance.Get<Mac::Mac>().SetPanChannel(aChannel));
80     instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
81     instance.Get<MeshCoP::PendingDatasetManager>().Clear();
82 
83 exit:
84     return error;
85 }
86 
otLinkGetSupportedChannelMask(otInstance * aInstance)87 uint32_t otLinkGetSupportedChannelMask(otInstance *aInstance)
88 {
89     return AsCoreType(aInstance).Get<Mac::Mac>().GetSupportedChannelMask().GetMask();
90 }
91 
otLinkSetSupportedChannelMask(otInstance * aInstance,uint32_t aChannelMask)92 otError otLinkSetSupportedChannelMask(otInstance *aInstance, uint32_t aChannelMask)
93 {
94     Error     error    = kErrorNone;
95     Instance &instance = AsCoreType(aInstance);
96 
97     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
98 
99     instance.Get<Mac::Mac>().SetSupportedChannelMask(Mac::ChannelMask(aChannelMask));
100 
101 exit:
102     return error;
103 }
104 
otLinkGetExtendedAddress(otInstance * aInstance)105 const otExtAddress *otLinkGetExtendedAddress(otInstance *aInstance)
106 {
107     return &AsCoreType(aInstance).Get<Mac::Mac>().GetExtAddress();
108 }
109 
otLinkSetExtendedAddress(otInstance * aInstance,const otExtAddress * aExtAddress)110 otError otLinkSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
111 {
112     Error     error    = kErrorNone;
113     Instance &instance = AsCoreType(aInstance);
114 
115     OT_ASSERT(aExtAddress != nullptr);
116     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
117 
118     instance.Get<Mac::Mac>().SetExtAddress(AsCoreType(aExtAddress));
119 
120     instance.Get<Mle::MleRouter>().UpdateLinkLocalAddress();
121 
122 exit:
123     return error;
124 }
125 
otLinkGetFactoryAssignedIeeeEui64(otInstance * aInstance,otExtAddress * aEui64)126 void otLinkGetFactoryAssignedIeeeEui64(otInstance *aInstance, otExtAddress *aEui64)
127 {
128     AsCoreType(aInstance).Get<Radio>().GetIeeeEui64(AsCoreType(aEui64));
129 }
130 
otLinkGetPanId(otInstance * aInstance)131 otPanId otLinkGetPanId(otInstance *aInstance)
132 {
133     return AsCoreType(aInstance).Get<Mac::Mac>().GetPanId();
134 }
135 
otLinkSetPanId(otInstance * aInstance,otPanId aPanId)136 otError otLinkSetPanId(otInstance *aInstance, otPanId aPanId)
137 {
138     Error     error    = kErrorNone;
139     Instance &instance = AsCoreType(aInstance);
140 
141     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
142 
143     instance.Get<Mac::Mac>().SetPanId(aPanId);
144     instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
145     instance.Get<MeshCoP::PendingDatasetManager>().Clear();
146 
147 exit:
148     return error;
149 }
150 
otLinkGetPollPeriod(otInstance * aInstance)151 uint32_t otLinkGetPollPeriod(otInstance *aInstance)
152 {
153     return AsCoreType(aInstance).Get<DataPollSender>().GetKeepAlivePollPeriod();
154 }
155 
otLinkSetPollPeriod(otInstance * aInstance,uint32_t aPollPeriod)156 otError otLinkSetPollPeriod(otInstance *aInstance, uint32_t aPollPeriod)
157 {
158     return AsCoreType(aInstance).Get<DataPollSender>().SetExternalPollPeriod(aPollPeriod);
159 }
160 
otLinkSendDataRequest(otInstance * aInstance)161 otError otLinkSendDataRequest(otInstance *aInstance)
162 {
163     return AsCoreType(aInstance).Get<DataPollSender>().SendDataPoll();
164 }
165 
otLinkGetShortAddress(otInstance * aInstance)166 otShortAddress otLinkGetShortAddress(otInstance *aInstance)
167 {
168     return AsCoreType(aInstance).Get<Mac::Mac>().GetShortAddress();
169 }
170 
otLinkGetMaxFrameRetriesDirect(otInstance * aInstance)171 uint8_t otLinkGetMaxFrameRetriesDirect(otInstance *aInstance)
172 {
173     return AsCoreType(aInstance).Get<Mac::Mac>().GetMaxFrameRetriesDirect();
174 }
175 
otLinkSetMaxFrameRetriesDirect(otInstance * aInstance,uint8_t aMaxFrameRetriesDirect)176 void otLinkSetMaxFrameRetriesDirect(otInstance *aInstance, uint8_t aMaxFrameRetriesDirect)
177 {
178     AsCoreType(aInstance).Get<Mac::Mac>().SetMaxFrameRetriesDirect(aMaxFrameRetriesDirect);
179 }
180 
181 #if OPENTHREAD_FTD
182 
otLinkGetMaxFrameRetriesIndirect(otInstance * aInstance)183 uint8_t otLinkGetMaxFrameRetriesIndirect(otInstance *aInstance)
184 {
185     return AsCoreType(aInstance).Get<Mac::Mac>().GetMaxFrameRetriesIndirect();
186 }
187 
otLinkSetMaxFrameRetriesIndirect(otInstance * aInstance,uint8_t aMaxFrameRetriesIndirect)188 void otLinkSetMaxFrameRetriesIndirect(otInstance *aInstance, uint8_t aMaxFrameRetriesIndirect)
189 {
190     AsCoreType(aInstance).Get<Mac::Mac>().SetMaxFrameRetriesIndirect(aMaxFrameRetriesIndirect);
191 }
192 
193 #endif // OPENTHREAD_FTD
194 
195 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
196 
otLinkFilterGetAddressMode(otInstance * aInstance)197 otMacFilterAddressMode otLinkFilterGetAddressMode(otInstance *aInstance)
198 {
199     return MapEnum(AsCoreType(aInstance).Get<Mac::Filter>().GetMode());
200 }
201 
otLinkFilterSetAddressMode(otInstance * aInstance,otMacFilterAddressMode aMode)202 void otLinkFilterSetAddressMode(otInstance *aInstance, otMacFilterAddressMode aMode)
203 {
204     AsCoreType(aInstance).Get<Mac::Filter>().SetMode(MapEnum(aMode));
205 }
206 
otLinkFilterAddAddress(otInstance * aInstance,const otExtAddress * aExtAddress)207 otError otLinkFilterAddAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
208 {
209     OT_ASSERT(aExtAddress != nullptr);
210 
211     return AsCoreType(aInstance).Get<Mac::Filter>().AddAddress(AsCoreType(aExtAddress));
212 }
213 
otLinkFilterRemoveAddress(otInstance * aInstance,const otExtAddress * aExtAddress)214 void otLinkFilterRemoveAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
215 {
216     OT_ASSERT(aExtAddress != nullptr);
217 
218     AsCoreType(aInstance).Get<Mac::Filter>().RemoveAddress(AsCoreType(aExtAddress));
219 }
220 
otLinkFilterClearAddresses(otInstance * aInstance)221 void otLinkFilterClearAddresses(otInstance *aInstance)
222 {
223     return AsCoreType(aInstance).Get<Mac::Filter>().ClearAddresses();
224 }
225 
otLinkFilterGetNextAddress(otInstance * aInstance,otMacFilterIterator * aIterator,otMacFilterEntry * aEntry)226 otError otLinkFilterGetNextAddress(otInstance *aInstance, otMacFilterIterator *aIterator, otMacFilterEntry *aEntry)
227 {
228     OT_ASSERT(aIterator != nullptr && aEntry != nullptr);
229 
230     return AsCoreType(aInstance).Get<Mac::Filter>().GetNextAddress(*aIterator, *aEntry);
231 }
232 
otLinkFilterAddRssIn(otInstance * aInstance,const otExtAddress * aExtAddress,int8_t aRss)233 otError otLinkFilterAddRssIn(otInstance *aInstance, const otExtAddress *aExtAddress, int8_t aRss)
234 {
235     OT_ASSERT(aExtAddress != nullptr);
236 
237     return AsCoreType(aInstance).Get<Mac::Filter>().AddRssIn(AsCoreType(aExtAddress), aRss);
238 }
239 
otLinkFilterRemoveRssIn(otInstance * aInstance,const otExtAddress * aExtAddress)240 void otLinkFilterRemoveRssIn(otInstance *aInstance, const otExtAddress *aExtAddress)
241 {
242     OT_ASSERT(aExtAddress != nullptr);
243 
244     AsCoreType(aInstance).Get<Mac::Filter>().RemoveRssIn(AsCoreType(aExtAddress));
245 }
246 
otLinkFilterSetDefaultRssIn(otInstance * aInstance,int8_t aRss)247 void otLinkFilterSetDefaultRssIn(otInstance *aInstance, int8_t aRss)
248 {
249     AsCoreType(aInstance).Get<Mac::Filter>().SetDefaultRssIn(aRss);
250 }
251 
otLinkFilterClearDefaultRssIn(otInstance * aInstance)252 void otLinkFilterClearDefaultRssIn(otInstance *aInstance)
253 {
254     AsCoreType(aInstance).Get<Mac::Filter>().ClearDefaultRssIn();
255 }
256 
otLinkFilterClearAllRssIn(otInstance * aInstance)257 void otLinkFilterClearAllRssIn(otInstance *aInstance)
258 {
259     AsCoreType(aInstance).Get<Mac::Filter>().ClearAllRssIn();
260 }
261 
otLinkFilterGetNextRssIn(otInstance * aInstance,otMacFilterIterator * aIterator,otMacFilterEntry * aEntry)262 otError otLinkFilterGetNextRssIn(otInstance *aInstance, otMacFilterIterator *aIterator, otMacFilterEntry *aEntry)
263 {
264     OT_ASSERT(aIterator != nullptr && aEntry != nullptr);
265 
266     return AsCoreType(aInstance).Get<Mac::Filter>().GetNextRssIn(*aIterator, *aEntry);
267 }
268 
269 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
otLinkSetRadioFilterEnabled(otInstance * aInstance,bool aFilterEnabled)270 void otLinkSetRadioFilterEnabled(otInstance *aInstance, bool aFilterEnabled)
271 {
272     return AsCoreType(aInstance).Get<Mac::Mac>().SetRadioFilterEnabled(aFilterEnabled);
273 }
274 
otLinkIsRadioFilterEnabled(otInstance * aInstance)275 bool otLinkIsRadioFilterEnabled(otInstance *aInstance)
276 {
277     return AsCoreType(aInstance).Get<Mac::Mac>().IsRadioFilterEnabled();
278 }
279 #endif
280 
281 #endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
282 
otLinkConvertRssToLinkQuality(otInstance * aInstance,int8_t aRss)283 uint8_t otLinkConvertRssToLinkQuality(otInstance *aInstance, int8_t aRss)
284 {
285     return LinkQualityInfo::ConvertRssToLinkQuality(AsCoreType(aInstance).Get<Mac::Mac>().GetNoiseFloor(), aRss);
286 }
287 
otLinkConvertLinkQualityToRss(otInstance * aInstance,uint8_t aLinkQuality)288 int8_t otLinkConvertLinkQualityToRss(otInstance *aInstance, uint8_t aLinkQuality)
289 {
290     return LinkQualityInfo::ConvertLinkQualityToRss(AsCoreType(aInstance).Get<Mac::Mac>().GetNoiseFloor(),
291                                                     static_cast<LinkQuality>(aLinkQuality));
292 }
293 
294 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
otLinkGetTxDirectRetrySuccessHistogram(otInstance * aInstance,uint8_t * aNumberOfEntries)295 const uint32_t *otLinkGetTxDirectRetrySuccessHistogram(otInstance *aInstance, uint8_t *aNumberOfEntries)
296 {
297     return AsCoreType(aInstance).Get<Mac::Mac>().GetDirectRetrySuccessHistogram(*aNumberOfEntries);
298 }
299 
otLinkGetTxIndirectRetrySuccessHistogram(otInstance * aInstance,uint8_t * aNumberOfEntries)300 const uint32_t *otLinkGetTxIndirectRetrySuccessHistogram(otInstance *aInstance, uint8_t *aNumberOfEntries)
301 {
302     const uint32_t *histogram = nullptr;
303 
304 #if OPENTHREAD_FTD
305     histogram = AsCoreType(aInstance).Get<Mac::Mac>().GetIndirectRetrySuccessHistogram(*aNumberOfEntries);
306 #else
307     OT_UNUSED_VARIABLE(aInstance);
308     *aNumberOfEntries = 0;
309 #endif
310 
311     return histogram;
312 }
313 
otLinkResetTxRetrySuccessHistogram(otInstance * aInstance)314 void otLinkResetTxRetrySuccessHistogram(otInstance *aInstance)
315 {
316     AsCoreType(aInstance).Get<Mac::Mac>().ResetRetrySuccessHistogram();
317 }
318 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
319 
otLinkSetPcapCallback(otInstance * aInstance,otLinkPcapCallback aPcapCallback,void * aCallbackContext)320 void otLinkSetPcapCallback(otInstance *aInstance, otLinkPcapCallback aPcapCallback, void *aCallbackContext)
321 {
322     AsCoreType(aInstance).Get<Mac::Mac>().SetPcapCallback(aPcapCallback, aCallbackContext);
323 }
324 
otLinkIsPromiscuous(otInstance * aInstance)325 bool otLinkIsPromiscuous(otInstance *aInstance)
326 {
327     return AsCoreType(aInstance).Get<Mac::Mac>().IsPromiscuous();
328 }
329 
otLinkSetPromiscuous(otInstance * aInstance,bool aPromiscuous)330 otError otLinkSetPromiscuous(otInstance *aInstance, bool aPromiscuous)
331 {
332     Error     error    = kErrorNone;
333     Instance &instance = AsCoreType(aInstance);
334 
335     // cannot enable IEEE 802.15.4 promiscuous mode if the Thread interface is enabled
336     VerifyOrExit(!instance.Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
337 
338     instance.Get<Mac::Mac>().SetPromiscuous(aPromiscuous);
339 
340 exit:
341     return error;
342 }
343 
otLinkSetEnabled(otInstance * aInstance,bool aEnable)344 otError otLinkSetEnabled(otInstance *aInstance, bool aEnable)
345 {
346     Error     error    = kErrorNone;
347     Instance &instance = AsCoreType(aInstance);
348 
349     // cannot disable the link layer if the Thread interface is enabled
350     VerifyOrExit(!instance.Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
351 
352     instance.Get<Mac::Mac>().SetEnabled(aEnable);
353 
354 exit:
355     return error;
356 }
357 
otLinkIsEnabled(otInstance * aInstance)358 bool otLinkIsEnabled(otInstance *aInstance)
359 {
360     return AsCoreType(aInstance).Get<Mac::Mac>().IsEnabled();
361 }
362 
otLinkGetCounters(otInstance * aInstance)363 const otMacCounters *otLinkGetCounters(otInstance *aInstance)
364 {
365     return &AsCoreType(aInstance).Get<Mac::Mac>().GetCounters();
366 }
367 
otLinkResetCounters(otInstance * aInstance)368 void otLinkResetCounters(otInstance *aInstance)
369 {
370     AsCoreType(aInstance).Get<Mac::Mac>().ResetCounters();
371 }
372 
otLinkActiveScan(otInstance * aInstance,uint32_t aScanChannels,uint16_t aScanDuration,otHandleActiveScanResult aCallback,void * aCallbackContext)373 otError otLinkActiveScan(otInstance *             aInstance,
374                          uint32_t                 aScanChannels,
375                          uint16_t                 aScanDuration,
376                          otHandleActiveScanResult aCallback,
377                          void *                   aCallbackContext)
378 {
379     return AsCoreType(aInstance).Get<Mac::Mac>().ActiveScan(aScanChannels, aScanDuration, aCallback, aCallbackContext);
380 }
381 
otLinkIsActiveScanInProgress(otInstance * aInstance)382 bool otLinkIsActiveScanInProgress(otInstance *aInstance)
383 {
384     return AsCoreType(aInstance).Get<Mac::Mac>().IsActiveScanInProgress();
385 }
386 
otLinkEnergyScan(otInstance * aInstance,uint32_t aScanChannels,uint16_t aScanDuration,otHandleEnergyScanResult aCallback,void * aCallbackContext)387 otError otLinkEnergyScan(otInstance *             aInstance,
388                          uint32_t                 aScanChannels,
389                          uint16_t                 aScanDuration,
390                          otHandleEnergyScanResult aCallback,
391                          void *                   aCallbackContext)
392 {
393     return AsCoreType(aInstance).Get<Mac::Mac>().EnergyScan(aScanChannels, aScanDuration, aCallback, aCallbackContext);
394 }
395 
otLinkIsEnergyScanInProgress(otInstance * aInstance)396 bool otLinkIsEnergyScanInProgress(otInstance *aInstance)
397 {
398     return AsCoreType(aInstance).Get<Mac::Mac>().IsEnergyScanInProgress();
399 }
400 
otLinkIsInTransmitState(otInstance * aInstance)401 bool otLinkIsInTransmitState(otInstance *aInstance)
402 {
403     return AsCoreType(aInstance).Get<Mac::Mac>().IsInTransmitState();
404 }
405 
otLinkGetCcaFailureRate(otInstance * aInstance)406 uint16_t otLinkGetCcaFailureRate(otInstance *aInstance)
407 {
408     return AsCoreType(aInstance).Get<Mac::Mac>().GetCcaFailureRate();
409 }
410 
411 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
otLinkCslGetChannel(otInstance * aInstance)412 uint8_t otLinkCslGetChannel(otInstance *aInstance)
413 {
414     return AsCoreType(aInstance).Get<Mac::Mac>().GetCslChannel();
415 }
416 
otLinkCslSetChannel(otInstance * aInstance,uint8_t aChannel)417 otError otLinkCslSetChannel(otInstance *aInstance, uint8_t aChannel)
418 {
419     Error error = kErrorNone;
420 
421     VerifyOrExit(Radio::IsCslChannelValid(aChannel), error = kErrorInvalidArgs);
422 
423     AsCoreType(aInstance).Get<Mac::Mac>().SetCslChannel(aChannel);
424 
425 exit:
426     return error;
427 }
428 
otLinkCslGetPeriod(otInstance * aInstance)429 uint16_t otLinkCslGetPeriod(otInstance *aInstance)
430 {
431     return AsCoreType(aInstance).Get<Mac::Mac>().GetCslPeriod();
432 }
433 
otLinkCslSetPeriod(otInstance * aInstance,uint16_t aPeriod)434 otError otLinkCslSetPeriod(otInstance *aInstance, uint16_t aPeriod)
435 {
436     Error error = kErrorNone;
437 
438     VerifyOrExit((aPeriod == 0 || kMinCslPeriod <= aPeriod), error = kErrorInvalidArgs);
439     AsCoreType(aInstance).Get<Mac::Mac>().SetCslPeriod(aPeriod);
440 
441 exit:
442     return error;
443 }
444 
otLinkCslGetTimeout(otInstance * aInstance)445 uint32_t otLinkCslGetTimeout(otInstance *aInstance)
446 {
447     return AsCoreType(aInstance).Get<Mle::MleRouter>().GetCslTimeout();
448 }
449 
otLinkCslSetTimeout(otInstance * aInstance,uint32_t aTimeout)450 otError otLinkCslSetTimeout(otInstance *aInstance, uint32_t aTimeout)
451 {
452     Error error = kErrorNone;
453 
454     VerifyOrExit(kMaxCslTimeout >= aTimeout, error = kErrorInvalidArgs);
455     AsCoreType(aInstance).Get<Mle::MleRouter>().SetCslTimeout(aTimeout);
456 
457 exit:
458     return error;
459 }
460 
461 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
462 
463 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
otLinkSendEmptyData(otInstance * aInstance)464 otError otLinkSendEmptyData(otInstance *aInstance)
465 {
466     return AsCoreType(aInstance).Get<MeshForwarder>().SendEmptyMessage();
467 }
468 #endif
469