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