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