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