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