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     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
116 
117     instance.Get<Mac::Mac>().SetExtAddress(AsCoreType(aExtAddress));
118 
119     instance.Get<Mle::MleRouter>().UpdateLinkLocalAddress();
120 
121 exit:
122     return error;
123 }
124 
otLinkGetFactoryAssignedIeeeEui64(otInstance * aInstance,otExtAddress * aEui64)125 void otLinkGetFactoryAssignedIeeeEui64(otInstance *aInstance, otExtAddress *aEui64)
126 {
127     AsCoreType(aInstance).Get<Radio>().GetIeeeEui64(AsCoreType(aEui64));
128 }
129 
otLinkGetPanId(otInstance * aInstance)130 otPanId otLinkGetPanId(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mac::Mac>().GetPanId(); }
131 
otLinkSetPanId(otInstance * aInstance,otPanId aPanId)132 otError otLinkSetPanId(otInstance *aInstance, otPanId aPanId)
133 {
134     Error     error    = kErrorNone;
135     Instance &instance = AsCoreType(aInstance);
136 
137     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
138 
139     instance.Get<Mac::Mac>().SetPanId(aPanId);
140     instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
141     instance.Get<MeshCoP::PendingDatasetManager>().Clear();
142 
143 exit:
144     return error;
145 }
146 
otLinkGetPollPeriod(otInstance * aInstance)147 uint32_t otLinkGetPollPeriod(otInstance *aInstance)
148 {
149     return AsCoreType(aInstance).Get<DataPollSender>().GetKeepAlivePollPeriod();
150 }
151 
otLinkSetPollPeriod(otInstance * aInstance,uint32_t aPollPeriod)152 otError otLinkSetPollPeriod(otInstance *aInstance, uint32_t aPollPeriod)
153 {
154     return AsCoreType(aInstance).Get<DataPollSender>().SetExternalPollPeriod(aPollPeriod);
155 }
156 
otLinkSendDataRequest(otInstance * aInstance)157 otError otLinkSendDataRequest(otInstance *aInstance)
158 {
159     return AsCoreType(aInstance).Get<DataPollSender>().SendDataPoll();
160 }
161 
otLinkGetShortAddress(otInstance * aInstance)162 otShortAddress otLinkGetShortAddress(otInstance *aInstance)
163 {
164     return AsCoreType(aInstance).Get<Mac::Mac>().GetShortAddress();
165 }
166 
otLinkGetMaxFrameRetriesDirect(otInstance * aInstance)167 uint8_t otLinkGetMaxFrameRetriesDirect(otInstance *aInstance)
168 {
169     return AsCoreType(aInstance).Get<Mac::Mac>().GetMaxFrameRetriesDirect();
170 }
171 
otLinkSetMaxFrameRetriesDirect(otInstance * aInstance,uint8_t aMaxFrameRetriesDirect)172 void otLinkSetMaxFrameRetriesDirect(otInstance *aInstance, uint8_t aMaxFrameRetriesDirect)
173 {
174     AsCoreType(aInstance).Get<Mac::Mac>().SetMaxFrameRetriesDirect(aMaxFrameRetriesDirect);
175 }
176 
177 #if OPENTHREAD_FTD
178 
otLinkGetMaxFrameRetriesIndirect(otInstance * aInstance)179 uint8_t otLinkGetMaxFrameRetriesIndirect(otInstance *aInstance)
180 {
181     return AsCoreType(aInstance).Get<Mac::Mac>().GetMaxFrameRetriesIndirect();
182 }
183 
otLinkSetMaxFrameRetriesIndirect(otInstance * aInstance,uint8_t aMaxFrameRetriesIndirect)184 void otLinkSetMaxFrameRetriesIndirect(otInstance *aInstance, uint8_t aMaxFrameRetriesIndirect)
185 {
186     AsCoreType(aInstance).Get<Mac::Mac>().SetMaxFrameRetriesIndirect(aMaxFrameRetriesIndirect);
187 }
188 
189 #endif // OPENTHREAD_FTD
190 
otLinkGetFrameCounter(otInstance * aInstance)191 uint32_t otLinkGetFrameCounter(otInstance *aInstance)
192 {
193     return AsCoreType(aInstance).Get<Mac::SubMac>().GetFrameCounter();
194 }
195 
196 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
197 
otLinkFilterGetAddressMode(otInstance * aInstance)198 otMacFilterAddressMode otLinkFilterGetAddressMode(otInstance *aInstance)
199 {
200     return MapEnum(AsCoreType(aInstance).Get<Mac::Filter>().GetMode());
201 }
202 
otLinkFilterSetAddressMode(otInstance * aInstance,otMacFilterAddressMode aMode)203 void otLinkFilterSetAddressMode(otInstance *aInstance, otMacFilterAddressMode aMode)
204 {
205     AsCoreType(aInstance).Get<Mac::Filter>().SetMode(MapEnum(aMode));
206 }
207 
otLinkFilterAddAddress(otInstance * aInstance,const otExtAddress * aExtAddress)208 otError otLinkFilterAddAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
209 {
210     return AsCoreType(aInstance).Get<Mac::Filter>().AddAddress(AsCoreType(aExtAddress));
211 }
212 
otLinkFilterRemoveAddress(otInstance * aInstance,const otExtAddress * aExtAddress)213 void otLinkFilterRemoveAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
214 {
215     AsCoreType(aInstance).Get<Mac::Filter>().RemoveAddress(AsCoreType(aExtAddress));
216 }
217 
otLinkFilterClearAddresses(otInstance * aInstance)218 void otLinkFilterClearAddresses(otInstance *aInstance)
219 {
220     return AsCoreType(aInstance).Get<Mac::Filter>().ClearAddresses();
221 }
222 
otLinkFilterGetNextAddress(otInstance * aInstance,otMacFilterIterator * aIterator,otMacFilterEntry * aEntry)223 otError otLinkFilterGetNextAddress(otInstance *aInstance, otMacFilterIterator *aIterator, otMacFilterEntry *aEntry)
224 {
225     AssertPointerIsNotNull(aIterator);
226     AssertPointerIsNotNull(aEntry);
227 
228     return AsCoreType(aInstance).Get<Mac::Filter>().GetNextAddress(*aIterator, *aEntry);
229 }
230 
otLinkFilterAddRssIn(otInstance * aInstance,const otExtAddress * aExtAddress,int8_t aRss)231 otError otLinkFilterAddRssIn(otInstance *aInstance, const otExtAddress *aExtAddress, int8_t aRss)
232 {
233     return AsCoreType(aInstance).Get<Mac::Filter>().AddRssIn(AsCoreType(aExtAddress), aRss);
234 }
235 
otLinkFilterRemoveRssIn(otInstance * aInstance,const otExtAddress * aExtAddress)236 void otLinkFilterRemoveRssIn(otInstance *aInstance, const otExtAddress *aExtAddress)
237 {
238     AsCoreType(aInstance).Get<Mac::Filter>().RemoveRssIn(AsCoreType(aExtAddress));
239 }
240 
otLinkFilterSetDefaultRssIn(otInstance * aInstance,int8_t aRss)241 void otLinkFilterSetDefaultRssIn(otInstance *aInstance, int8_t aRss)
242 {
243     AsCoreType(aInstance).Get<Mac::Filter>().SetDefaultRssIn(aRss);
244 }
245 
otLinkFilterClearDefaultRssIn(otInstance * aInstance)246 void otLinkFilterClearDefaultRssIn(otInstance *aInstance)
247 {
248     AsCoreType(aInstance).Get<Mac::Filter>().ClearDefaultRssIn();
249 }
250 
otLinkFilterClearAllRssIn(otInstance * aInstance)251 void otLinkFilterClearAllRssIn(otInstance *aInstance) { AsCoreType(aInstance).Get<Mac::Filter>().ClearAllRssIn(); }
252 
otLinkFilterGetNextRssIn(otInstance * aInstance,otMacFilterIterator * aIterator,otMacFilterEntry * aEntry)253 otError otLinkFilterGetNextRssIn(otInstance *aInstance, otMacFilterIterator *aIterator, otMacFilterEntry *aEntry)
254 {
255     AssertPointerIsNotNull(aIterator);
256     AssertPointerIsNotNull(aEntry);
257 
258     return AsCoreType(aInstance).Get<Mac::Filter>().GetNextRssIn(*aIterator, *aEntry);
259 }
260 
261 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
otLinkSetRadioFilterEnabled(otInstance * aInstance,bool aFilterEnabled)262 void otLinkSetRadioFilterEnabled(otInstance *aInstance, bool aFilterEnabled)
263 {
264     return AsCoreType(aInstance).Get<Mac::Mac>().SetRadioFilterEnabled(aFilterEnabled);
265 }
266 
otLinkIsRadioFilterEnabled(otInstance * aInstance)267 bool otLinkIsRadioFilterEnabled(otInstance *aInstance)
268 {
269     return AsCoreType(aInstance).Get<Mac::Mac>().IsRadioFilterEnabled();
270 }
271 #endif
272 
273 #endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
274 
otLinkConvertRssToLinkQuality(otInstance * aInstance,int8_t aRss)275 uint8_t otLinkConvertRssToLinkQuality(otInstance *aInstance, int8_t aRss)
276 {
277     return LinkQualityForLinkMargin(AsCoreType(aInstance).Get<Mac::Mac>().ComputeLinkMargin(aRss));
278 }
279 
otLinkConvertLinkQualityToRss(otInstance * aInstance,uint8_t aLinkQuality)280 int8_t otLinkConvertLinkQualityToRss(otInstance *aInstance, uint8_t aLinkQuality)
281 {
282     return GetTypicalRssForLinkQuality(AsCoreType(aInstance).Get<Mac::Mac>().GetNoiseFloor(),
283                                        static_cast<LinkQuality>(aLinkQuality));
284 }
285 
286 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
otLinkGetTxDirectRetrySuccessHistogram(otInstance * aInstance,uint8_t * aNumberOfEntries)287 const uint32_t *otLinkGetTxDirectRetrySuccessHistogram(otInstance *aInstance, uint8_t *aNumberOfEntries)
288 {
289     AssertPointerIsNotNull(aNumberOfEntries);
290 
291     return AsCoreType(aInstance).Get<Mac::Mac>().GetDirectRetrySuccessHistogram(*aNumberOfEntries);
292 }
293 
otLinkGetTxIndirectRetrySuccessHistogram(otInstance * aInstance,uint8_t * aNumberOfEntries)294 const uint32_t *otLinkGetTxIndirectRetrySuccessHistogram(otInstance *aInstance, uint8_t *aNumberOfEntries)
295 {
296     const uint32_t *histogram = nullptr;
297 
298     AssertPointerIsNotNull(aNumberOfEntries);
299 
300 #if OPENTHREAD_FTD
301     histogram = AsCoreType(aInstance).Get<Mac::Mac>().GetIndirectRetrySuccessHistogram(*aNumberOfEntries);
302 #else
303     OT_UNUSED_VARIABLE(aInstance);
304     *aNumberOfEntries = 0;
305 #endif
306 
307     return histogram;
308 }
309 
otLinkResetTxRetrySuccessHistogram(otInstance * aInstance)310 void otLinkResetTxRetrySuccessHistogram(otInstance *aInstance)
311 {
312     AsCoreType(aInstance).Get<Mac::Mac>().ResetRetrySuccessHistogram();
313 }
314 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
315 
otLinkSetPcapCallback(otInstance * aInstance,otLinkPcapCallback aPcapCallback,void * aCallbackContext)316 void otLinkSetPcapCallback(otInstance *aInstance, otLinkPcapCallback aPcapCallback, void *aCallbackContext)
317 {
318     AsCoreType(aInstance).Get<Mac::Mac>().SetPcapCallback(aPcapCallback, aCallbackContext);
319 }
320 
otLinkIsPromiscuous(otInstance * aInstance)321 bool otLinkIsPromiscuous(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mac::Mac>().IsPromiscuous(); }
322 
otLinkSetPromiscuous(otInstance * aInstance,bool aPromiscuous)323 otError otLinkSetPromiscuous(otInstance *aInstance, bool aPromiscuous)
324 {
325     Error     error    = kErrorNone;
326     Instance &instance = AsCoreType(aInstance);
327 
328     // cannot enable IEEE 802.15.4 promiscuous mode if the Thread interface is enabled
329     VerifyOrExit(!instance.Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
330 
331     instance.Get<Mac::Mac>().SetPromiscuous(aPromiscuous);
332 
333 exit:
334     return error;
335 }
336 
otLinkSetEnabled(otInstance * aInstance,bool aEnable)337 otError otLinkSetEnabled(otInstance *aInstance, bool aEnable)
338 {
339     Error     error    = kErrorNone;
340     Instance &instance = AsCoreType(aInstance);
341 
342     // cannot disable the link layer if the Thread interface is enabled
343     VerifyOrExit(!instance.Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
344 
345     instance.Get<Mac::Mac>().SetEnabled(aEnable);
346 
347 exit:
348     return error;
349 }
350 
otLinkIsEnabled(otInstance * aInstance)351 bool otLinkIsEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mac::Mac>().IsEnabled(); }
352 
otLinkGetCounters(otInstance * aInstance)353 const otMacCounters *otLinkGetCounters(otInstance *aInstance)
354 {
355     return &AsCoreType(aInstance).Get<Mac::Mac>().GetCounters();
356 }
357 
otLinkResetCounters(otInstance * aInstance)358 void otLinkResetCounters(otInstance *aInstance) { AsCoreType(aInstance).Get<Mac::Mac>().ResetCounters(); }
359 
otLinkActiveScan(otInstance * aInstance,uint32_t aScanChannels,uint16_t aScanDuration,otHandleActiveScanResult aCallback,void * aCallbackContext)360 otError otLinkActiveScan(otInstance              *aInstance,
361                          uint32_t                 aScanChannels,
362                          uint16_t                 aScanDuration,
363                          otHandleActiveScanResult aCallback,
364                          void                    *aCallbackContext)
365 {
366     return AsCoreType(aInstance).Get<Mac::Mac>().ActiveScan(aScanChannels, aScanDuration, aCallback, aCallbackContext);
367 }
368 
otLinkIsActiveScanInProgress(otInstance * aInstance)369 bool otLinkIsActiveScanInProgress(otInstance *aInstance)
370 {
371     return AsCoreType(aInstance).Get<Mac::Mac>().IsActiveScanInProgress();
372 }
373 
otLinkEnergyScan(otInstance * aInstance,uint32_t aScanChannels,uint16_t aScanDuration,otHandleEnergyScanResult aCallback,void * aCallbackContext)374 otError otLinkEnergyScan(otInstance              *aInstance,
375                          uint32_t                 aScanChannels,
376                          uint16_t                 aScanDuration,
377                          otHandleEnergyScanResult aCallback,
378                          void                    *aCallbackContext)
379 {
380     return AsCoreType(aInstance).Get<Mac::Mac>().EnergyScan(aScanChannels, aScanDuration, aCallback, aCallbackContext);
381 }
382 
otLinkIsEnergyScanInProgress(otInstance * aInstance)383 bool otLinkIsEnergyScanInProgress(otInstance *aInstance)
384 {
385     return AsCoreType(aInstance).Get<Mac::Mac>().IsEnergyScanInProgress();
386 }
387 
otLinkIsInTransmitState(otInstance * aInstance)388 bool otLinkIsInTransmitState(otInstance *aInstance)
389 {
390     return AsCoreType(aInstance).Get<Mac::Mac>().IsInTransmitState();
391 }
392 
otLinkGetCcaFailureRate(otInstance * aInstance)393 uint16_t otLinkGetCcaFailureRate(otInstance *aInstance)
394 {
395     return AsCoreType(aInstance).Get<Mac::Mac>().GetCcaFailureRate();
396 }
397 
398 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
otLinkIsCslEnabled(otInstance * aInstance)399 bool otLinkIsCslEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mac::Mac>().IsCslEnabled(); }
400 
otLinkIsCslSupported(otInstance * aInstance)401 bool otLinkIsCslSupported(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mac::Mac>().IsCslSupported(); }
402 
otLinkGetCslChannel(otInstance * aInstance)403 uint8_t otLinkGetCslChannel(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mac::Mac>().GetCslChannel(); }
404 
otLinkSetCslChannel(otInstance * aInstance,uint8_t aChannel)405 otError otLinkSetCslChannel(otInstance *aInstance, uint8_t aChannel)
406 {
407     Error error = kErrorNone;
408 
409     VerifyOrExit(Radio::IsCslChannelValid(aChannel), error = kErrorInvalidArgs);
410 
411     AsCoreType(aInstance).Get<Mac::Mac>().SetCslChannel(aChannel);
412 
413 exit:
414     return error;
415 }
416 
otLinkGetCslPeriod(otInstance * aInstance)417 uint32_t otLinkGetCslPeriod(otInstance *aInstance)
418 {
419     return Mac::Mac::CslPeriodToUsec(AsCoreType(aInstance).Get<Mac::Mac>().GetCslPeriod());
420 }
421 
otLinkSetCslPeriod(otInstance * aInstance,uint32_t aPeriod)422 otError otLinkSetCslPeriod(otInstance *aInstance, uint32_t aPeriod)
423 {
424     Error    error = kErrorNone;
425     uint16_t periodInTenSymbolsUnit;
426 
427     if (aPeriod == 0)
428     {
429         periodInTenSymbolsUnit = 0;
430     }
431     else
432     {
433         VerifyOrExit((aPeriod % kUsPerTenSymbols) == 0, error = kErrorInvalidArgs);
434         periodInTenSymbolsUnit = ClampToUint16(aPeriod / kUsPerTenSymbols);
435         VerifyOrExit(periodInTenSymbolsUnit >= kMinCslPeriod, error = kErrorInvalidArgs);
436     }
437 
438     AsCoreType(aInstance).Get<Mac::Mac>().SetCslPeriod(periodInTenSymbolsUnit);
439 
440 exit:
441     return error;
442 }
443 
otLinkGetCslTimeout(otInstance * aInstance)444 uint32_t otLinkGetCslTimeout(otInstance *aInstance)
445 {
446     return AsCoreType(aInstance).Get<Mle::MleRouter>().GetCslTimeout();
447 }
448 
otLinkSetCslTimeout(otInstance * aInstance,uint32_t aTimeout)449 otError otLinkSetCslTimeout(otInstance *aInstance, uint32_t aTimeout)
450 {
451     Error error = kErrorNone;
452 
453     VerifyOrExit(kMaxCslTimeout >= aTimeout, error = kErrorInvalidArgs);
454     AsCoreType(aInstance).Get<Mle::MleRouter>().SetCslTimeout(aTimeout);
455 
456 exit:
457     return error;
458 }
459 
460 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
461 
462 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
otLinkSendEmptyData(otInstance * aInstance)463 otError otLinkSendEmptyData(otInstance *aInstance)
464 {
465     return AsCoreType(aInstance).Get<MeshForwarder>().SendEmptyMessage();
466 }
467 #endif
468 
otLinkSetRegion(otInstance * aInstance,uint16_t aRegionCode)469 otError otLinkSetRegion(otInstance *aInstance, uint16_t aRegionCode)
470 {
471     return AsCoreType(aInstance).Get<Mac::Mac>().SetRegion(aRegionCode);
472 }
473 
otLinkGetRegion(otInstance * aInstance,uint16_t * aRegionCode)474 otError otLinkGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
475 {
476     Error error;
477 
478     if (aRegionCode == nullptr)
479     {
480         error = kErrorInvalidArgs;
481     }
482     else
483     {
484         error = AsCoreType(aInstance).Get<Mac::Mac>().GetRegion(*aRegionCode);
485     }
486 
487     return error;
488 }
489