1 /*
2 * Copyright (c) 2020, 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 radio apis on posix platform.
32 */
33
34 #include "platform-posix.h"
35
36 #include <string.h>
37
38 #include <openthread/logging.h>
39 #include <openthread/platform/diag.h>
40
41 #include "common/code_utils.hpp"
42 #include "common/new.hpp"
43 #include "posix/platform/radio.hpp"
44 #include "posix/platform/spinel_driver_getter.hpp"
45 #include "posix/platform/spinel_manager.hpp"
46 #include "utils/parse_cmdline.hpp"
47
48 #if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
49 #include "configuration.hpp"
50 static ot::Posix::Configuration sConfig;
51 #endif
52
53 static ot::Posix::Radio sRadio;
54
55 namespace ot {
56 namespace Posix {
57
58 namespace {
platformRadioInit(const char * aUrl)59 extern "C" void platformRadioInit(const char *aUrl) { sRadio.Init(aUrl); }
60 } // namespace
61
62 const char Radio::kLogModuleName[] = "Radio";
63
Radio(void)64 Radio::Radio(void)
65 : mRadioUrl(nullptr)
66 , mRadioSpinel()
67 #if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
68 , mRcpCapsDiag(mRadioSpinel)
69 #endif
70 #if OPENTHREAD_POSIX_CONFIG_TMP_STORAGE_ENABLE
71 , mTmpStorage()
72 #endif
73 {
74 }
75
Init(const char * aUrl)76 void Radio::Init(const char *aUrl)
77 {
78 bool resetRadio;
79 bool skipCompatibilityCheck;
80 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
81 bool aEnableRcpTimeSync = true;
82 #else
83 bool aEnableRcpTimeSync = false;
84 #endif
85 struct ot::Spinel::RadioSpinelCallbacks callbacks;
86
87 mRadioUrl.Init(aUrl);
88 VerifyOrDie(mRadioUrl.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
89
90 memset(&callbacks, 0, sizeof(callbacks));
91 #if OPENTHREAD_CONFIG_DIAG_ENABLE
92 callbacks.mDiagReceiveDone = otPlatDiagRadioReceiveDone;
93 callbacks.mDiagTransmitDone = otPlatDiagRadioTransmitDone;
94 #endif // OPENTHREAD_CONFIG_DIAG_ENABLE
95 callbacks.mEnergyScanDone = otPlatRadioEnergyScanDone;
96 callbacks.mBusLatencyChanged = otPlatRadioBusLatencyChanged;
97 callbacks.mReceiveDone = otPlatRadioReceiveDone;
98 callbacks.mTransmitDone = otPlatRadioTxDone;
99 callbacks.mTxStarted = otPlatRadioTxStarted;
100 #if OPENTHREAD_POSIX_CONFIG_TMP_STORAGE_ENABLE
101 callbacks.mSaveRadioSpinelMetrics = SaveRadioSpinelMetrics;
102 callbacks.mRestoreRadioSpinelMetrics = RestoreRadioSpinelMetrics;
103 callbacks.mRadioSpinelMetricsContext = this;
104 mTmpStorage.Init();
105 #endif
106
107 resetRadio = !mRadioUrl.HasParam("no-reset");
108 skipCompatibilityCheck = mRadioUrl.HasParam("skip-rcp-compatibility-check");
109
110 mRadioSpinel.SetCallbacks(callbacks);
111 mRadioSpinel.Init(skipCompatibilityCheck, resetRadio, &GetSpinelDriver(),
112 (skipCompatibilityCheck ? 0 : kRequiredRadioCaps), aEnableRcpTimeSync);
113
114 ProcessRadioUrl(mRadioUrl);
115 }
116
Deinit(void)117 void Radio::Deinit(void)
118 {
119 mRadioSpinel.Deinit();
120
121 #if OPENTHREAD_POSIX_CONFIG_TMP_STORAGE_ENABLE
122 mTmpStorage.Deinit();
123 #endif
124 }
125
ProcessRadioUrl(const RadioUrl & aRadioUrl)126 void Radio::ProcessRadioUrl(const RadioUrl &aRadioUrl)
127 {
128 const char *region;
129 int8_t value;
130
131 if (aRadioUrl.HasParam("ncp-dataset"))
132 {
133 LogCrit("The argument \"ncp-dataset\" is no longer supported");
134 DieNow(OT_ERROR_FAILED);
135 }
136
137 if (aRadioUrl.HasParam("fem-lnagain"))
138 {
139 SuccessOrDie(aRadioUrl.ParseInt8("fem-lnagain", value));
140 SuccessOrDie(mRadioSpinel.SetFemLnaGain(value));
141 }
142
143 if (aRadioUrl.HasParam("cca-threshold"))
144 {
145 SuccessOrDie(aRadioUrl.ParseInt8("cca-threshold", value));
146 SuccessOrDie(mRadioSpinel.SetCcaEnergyDetectThreshold(value));
147 }
148
149 if ((region = aRadioUrl.GetValue("region")) != nullptr)
150 {
151 uint16_t regionCode;
152
153 VerifyOrDie(strnlen(region, 3) == 2, OT_EXIT_INVALID_ARGUMENTS);
154 regionCode = static_cast<uint16_t>(static_cast<uint16_t>(region[0]) << 8) + static_cast<uint16_t>(region[1]);
155 SuccessOrDie(otPlatRadioSetRegion(gInstance, regionCode));
156 }
157
158 if (aRadioUrl.HasParam("bus-latency"))
159 {
160 uint32_t busLatency;
161 SuccessOrDie(aRadioUrl.ParseUint32("bus-latency", busLatency));
162 mRadioSpinel.SetBusLatency(busLatency);
163 }
164
165 ProcessMaxPowerTable(aRadioUrl);
166
167 #if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
168 {
169 const char *enableCoex = aRadioUrl.GetValue("enable-coex");
170 if (enableCoex != nullptr)
171 {
172 SuccessOrDie(mRadioSpinel.SetCoexEnabled(enableCoex[0] != '0'));
173 }
174 }
175 #endif // OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
176 }
177
ProcessMaxPowerTable(const RadioUrl & aRadioUrl)178 void Radio::ProcessMaxPowerTable(const RadioUrl &aRadioUrl)
179 {
180 OT_UNUSED_VARIABLE(aRadioUrl);
181
182 #if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
183 otError error;
184 constexpr int8_t kPowerDefault = 30; // Default power 1 watt (30 dBm).
185 const char *str = nullptr;
186 char *pSave = nullptr;
187 uint8_t channel = ot::Radio::kChannelMin;
188 int8_t power = kPowerDefault;
189 const char *maxPowerTable;
190
191 VerifyOrExit((maxPowerTable = aRadioUrl.GetValue("max-power-table")) != nullptr);
192
193 for (str = strtok_r(const_cast<char *>(maxPowerTable), ",", &pSave);
194 str != nullptr && channel <= ot::Radio::kChannelMax; str = strtok_r(nullptr, ",", &pSave))
195 {
196 power = static_cast<int8_t>(strtol(str, nullptr, 0));
197 error = mRadioSpinel.SetChannelMaxTransmitPower(channel, power);
198 VerifyOrDie((error == OT_ERROR_NONE) || (error == OT_ERROR_NOT_IMPLEMENTED), OT_EXIT_FAILURE);
199 if (error == OT_ERROR_NOT_IMPLEMENTED)
200 {
201 LogWarn("The RCP doesn't support setting the max transmit power");
202 }
203
204 ++channel;
205 }
206
207 // Use the last power if omitted.
208 while (channel <= ot::Radio::kChannelMax)
209 {
210 error = mRadioSpinel.SetChannelMaxTransmitPower(channel, power);
211 VerifyOrDie((error == OT_ERROR_NONE) || (error == OT_ERROR_NOT_IMPLEMENTED), OT_ERROR_FAILED);
212 if (error == OT_ERROR_NOT_IMPLEMENTED)
213 {
214 LogWarn("The RCP doesn't support setting the max transmit power");
215 }
216
217 ++channel;
218 }
219
220 VerifyOrDie(str == nullptr, OT_EXIT_INVALID_ARGUMENTS);
221
222 exit:
223 return;
224 #endif // OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
225 }
226
227 } // namespace Posix
228 } // namespace ot
229
GetRadioSpinel(void)230 ot::Spinel::RadioSpinel &GetRadioSpinel(void) { return sRadio.GetRadioSpinel(); }
231
232 #if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
GetRcpCapsDiag(void)233 ot::Posix::RcpCapsDiag &GetRcpCapsDiag(void) { return sRadio.GetRcpCapsDiag(); }
234 #endif
235
platformRadioDeinit(void)236 void platformRadioDeinit(void) { sRadio.Deinit(); }
237
platformRadioHandleStateChange(otInstance * aInstance,otChangedFlags aFlags)238 void platformRadioHandleStateChange(otInstance *aInstance, otChangedFlags aFlags)
239 {
240 if (OT_CHANGED_THREAD_NETIF_STATE & aFlags)
241 {
242 GetRadioSpinel().SetTimeSyncState(otIp6IsEnabled(aInstance));
243 }
244 }
245
otPlatRadioGetIeeeEui64(otInstance * aInstance,uint8_t * aIeeeEui64)246 void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
247 {
248 OT_UNUSED_VARIABLE(aInstance);
249 SuccessOrDie(GetRadioSpinel().GetIeeeEui64(aIeeeEui64));
250 }
251
otPlatRadioSetPanId(otInstance * aInstance,uint16_t panid)252 void otPlatRadioSetPanId(otInstance *aInstance, uint16_t panid)
253 {
254 OT_UNUSED_VARIABLE(aInstance);
255 SuccessOrDie(GetRadioSpinel().SetPanId(panid));
256 }
257
otPlatRadioSetExtendedAddress(otInstance * aInstance,const otExtAddress * aAddress)258 void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress)
259 {
260 OT_UNUSED_VARIABLE(aInstance);
261 otExtAddress addr;
262
263 for (size_t i = 0; i < sizeof(addr); i++)
264 {
265 addr.m8[i] = aAddress->m8[sizeof(addr) - 1 - i];
266 }
267
268 SuccessOrDie(GetRadioSpinel().SetExtendedAddress(addr));
269 }
270
otPlatRadioSetShortAddress(otInstance * aInstance,uint16_t aAddress)271 void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress)
272 {
273 OT_UNUSED_VARIABLE(aInstance);
274 SuccessOrDie(GetRadioSpinel().SetShortAddress(aAddress));
275 }
276
otPlatRadioSetAlternateShortAddress(otInstance * aInstance,uint16_t aAddress)277 void otPlatRadioSetAlternateShortAddress(otInstance *aInstance, uint16_t aAddress)
278 {
279 OT_UNUSED_VARIABLE(aInstance);
280 SuccessOrDie(GetRadioSpinel().SetAlternateShortAddress(aAddress));
281 }
282
otPlatRadioSetPromiscuous(otInstance * aInstance,bool aEnable)283 void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
284 {
285 OT_UNUSED_VARIABLE(aInstance);
286 SuccessOrDie(GetRadioSpinel().SetPromiscuous(aEnable));
287 }
288
otPlatRadioIsEnabled(otInstance * aInstance)289 bool otPlatRadioIsEnabled(otInstance *aInstance)
290 {
291 OT_UNUSED_VARIABLE(aInstance);
292 return GetRadioSpinel().IsEnabled();
293 }
294
otPlatRadioEnable(otInstance * aInstance)295 otError otPlatRadioEnable(otInstance *aInstance) { return GetRadioSpinel().Enable(aInstance); }
296
otPlatRadioDisable(otInstance * aInstance)297 otError otPlatRadioDisable(otInstance *aInstance)
298 {
299 OT_UNUSED_VARIABLE(aInstance);
300 return GetRadioSpinel().Disable();
301 }
302
otPlatRadioSleep(otInstance * aInstance)303 otError otPlatRadioSleep(otInstance *aInstance)
304 {
305 OT_UNUSED_VARIABLE(aInstance);
306 return GetRadioSpinel().Sleep();
307 }
308
otPlatRadioReceive(otInstance * aInstance,uint8_t aChannel)309 otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
310 {
311 OT_UNUSED_VARIABLE(aInstance);
312
313 otError error;
314
315 SuccessOrExit(error = GetRadioSpinel().Receive(aChannel));
316
317 exit:
318 return error;
319 }
320
otPlatRadioTransmit(otInstance * aInstance,otRadioFrame * aFrame)321 otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
322 {
323 OT_UNUSED_VARIABLE(aInstance);
324 return GetRadioSpinel().Transmit(*aFrame);
325 }
326
otPlatRadioGetTransmitBuffer(otInstance * aInstance)327 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
328 {
329 OT_UNUSED_VARIABLE(aInstance);
330 return &GetRadioSpinel().GetTransmitFrame();
331 }
332
otPlatRadioGetRssi(otInstance * aInstance)333 int8_t otPlatRadioGetRssi(otInstance *aInstance)
334 {
335 OT_UNUSED_VARIABLE(aInstance);
336 return GetRadioSpinel().GetRssi();
337 }
338
otPlatRadioGetCaps(otInstance * aInstance)339 otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
340 {
341 OT_UNUSED_VARIABLE(aInstance);
342 return GetRadioSpinel().GetRadioCaps();
343 }
344
otPlatRadioGetVersionString(otInstance * aInstance)345 const char *otPlatRadioGetVersionString(otInstance *aInstance)
346 {
347 OT_UNUSED_VARIABLE(aInstance);
348 return GetRadioSpinel().GetVersion();
349 }
350
otPlatRadioGetPromiscuous(otInstance * aInstance)351 bool otPlatRadioGetPromiscuous(otInstance *aInstance)
352 {
353 OT_UNUSED_VARIABLE(aInstance);
354 return GetRadioSpinel().IsPromiscuous();
355 }
356
platformRadioUpdateFdSet(otSysMainloopContext * aContext)357 void platformRadioUpdateFdSet(otSysMainloopContext *aContext)
358 {
359 uint64_t now = otPlatTimeGet();
360 uint64_t deadline = GetRadioSpinel().GetNextRadioTimeRecalcStart();
361
362 if (GetRadioSpinel().IsTransmitting())
363 {
364 uint64_t txRadioEndUs = GetRadioSpinel().GetTxRadioEndUs();
365
366 if (txRadioEndUs < deadline)
367 {
368 deadline = txRadioEndUs;
369 }
370 }
371
372 if (now < deadline)
373 {
374 uint64_t remain = deadline - now;
375
376 if (remain < (static_cast<uint64_t>(aContext->mTimeout.tv_sec) * OT_US_PER_S +
377 static_cast<uint64_t>(aContext->mTimeout.tv_usec)))
378 {
379 aContext->mTimeout.tv_sec = static_cast<time_t>(remain / OT_US_PER_S);
380 aContext->mTimeout.tv_usec = static_cast<suseconds_t>(remain % OT_US_PER_S);
381 }
382 }
383 else
384 {
385 aContext->mTimeout.tv_sec = 0;
386 aContext->mTimeout.tv_usec = 0;
387 }
388
389 if (GetRadioSpinel().IsTransmitDone())
390 {
391 aContext->mTimeout.tv_sec = 0;
392 aContext->mTimeout.tv_usec = 0;
393 }
394 }
395
396 #if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeRadioProcess(otInstance * aInstance,const struct VirtualTimeEvent * aEvent)397 void virtualTimeRadioProcess(otInstance *aInstance, const struct VirtualTimeEvent *aEvent)
398 {
399 OT_UNUSED_VARIABLE(aInstance);
400 GetRadioSpinel().Process(aEvent);
401 }
402 #else
platformRadioProcess(otInstance * aInstance,const otSysMainloopContext * aContext)403 void platformRadioProcess(otInstance *aInstance, const otSysMainloopContext *aContext)
404 {
405 OT_UNUSED_VARIABLE(aInstance);
406
407 GetRadioSpinel().Process(aContext);
408 }
409 #endif // OPENTHREAD_POSIX_VIRTUAL_TIME
410
otPlatRadioEnableSrcMatch(otInstance * aInstance,bool aEnable)411 void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
412 {
413 OT_UNUSED_VARIABLE(aInstance);
414 SuccessOrDie(GetRadioSpinel().EnableSrcMatch(aEnable));
415 }
416
otPlatRadioAddSrcMatchShortEntry(otInstance * aInstance,uint16_t aShortAddress)417 otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress)
418 {
419 OT_UNUSED_VARIABLE(aInstance);
420 return GetRadioSpinel().AddSrcMatchShortEntry(aShortAddress);
421 }
422
otPlatRadioAddSrcMatchExtEntry(otInstance * aInstance,const otExtAddress * aExtAddress)423 otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
424 {
425 OT_UNUSED_VARIABLE(aInstance);
426 otExtAddress addr;
427
428 for (size_t i = 0; i < sizeof(addr); i++)
429 {
430 addr.m8[i] = aExtAddress->m8[sizeof(addr) - 1 - i];
431 }
432
433 return GetRadioSpinel().AddSrcMatchExtEntry(addr);
434 }
435
otPlatRadioClearSrcMatchShortEntry(otInstance * aInstance,uint16_t aShortAddress)436 otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress)
437 {
438 OT_UNUSED_VARIABLE(aInstance);
439 return GetRadioSpinel().ClearSrcMatchShortEntry(aShortAddress);
440 }
441
otPlatRadioClearSrcMatchExtEntry(otInstance * aInstance,const otExtAddress * aExtAddress)442 otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
443 {
444 OT_UNUSED_VARIABLE(aInstance);
445 otExtAddress addr;
446
447 for (size_t i = 0; i < sizeof(addr); i++)
448 {
449 addr.m8[i] = aExtAddress->m8[sizeof(addr) - 1 - i];
450 }
451
452 return GetRadioSpinel().ClearSrcMatchExtEntry(addr);
453 }
454
otPlatRadioClearSrcMatchShortEntries(otInstance * aInstance)455 void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance)
456 {
457 OT_UNUSED_VARIABLE(aInstance);
458 SuccessOrDie(GetRadioSpinel().ClearSrcMatchShortEntries());
459 }
460
otPlatRadioClearSrcMatchExtEntries(otInstance * aInstance)461 void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
462 {
463 OT_UNUSED_VARIABLE(aInstance);
464 SuccessOrDie(GetRadioSpinel().ClearSrcMatchExtEntries());
465 }
466
otPlatRadioEnergyScan(otInstance * aInstance,uint8_t aScanChannel,uint16_t aScanDuration)467 otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
468 {
469 OT_UNUSED_VARIABLE(aInstance);
470 return GetRadioSpinel().EnergyScan(aScanChannel, aScanDuration);
471 }
472
otPlatRadioGetTransmitPower(otInstance * aInstance,int8_t * aPower)473 otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
474 {
475 OT_UNUSED_VARIABLE(aInstance);
476 assert(aPower != nullptr);
477 return GetRadioSpinel().GetTransmitPower(*aPower);
478 }
479
otPlatRadioSetTransmitPower(otInstance * aInstance,int8_t aPower)480 otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
481 {
482 OT_UNUSED_VARIABLE(aInstance);
483 return GetRadioSpinel().SetTransmitPower(aPower);
484 }
485
otPlatRadioGetCcaEnergyDetectThreshold(otInstance * aInstance,int8_t * aThreshold)486 otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
487 {
488 OT_UNUSED_VARIABLE(aInstance);
489 assert(aThreshold != nullptr);
490 return GetRadioSpinel().GetCcaEnergyDetectThreshold(*aThreshold);
491 }
492
otPlatRadioSetCcaEnergyDetectThreshold(otInstance * aInstance,int8_t aThreshold)493 otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
494 {
495 OT_UNUSED_VARIABLE(aInstance);
496 return GetRadioSpinel().SetCcaEnergyDetectThreshold(aThreshold);
497 }
498
otPlatRadioGetFemLnaGain(otInstance * aInstance,int8_t * aGain)499 otError otPlatRadioGetFemLnaGain(otInstance *aInstance, int8_t *aGain)
500 {
501 OT_UNUSED_VARIABLE(aInstance);
502 assert(aGain != nullptr);
503 return GetRadioSpinel().GetFemLnaGain(*aGain);
504 }
505
otPlatRadioSetFemLnaGain(otInstance * aInstance,int8_t aGain)506 otError otPlatRadioSetFemLnaGain(otInstance *aInstance, int8_t aGain)
507 {
508 OT_UNUSED_VARIABLE(aInstance);
509 return GetRadioSpinel().SetFemLnaGain(aGain);
510 }
511
otPlatRadioGetReceiveSensitivity(otInstance * aInstance)512 int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
513 {
514 OT_UNUSED_VARIABLE(aInstance);
515 return GetRadioSpinel().GetReceiveSensitivity();
516 }
517
518 #if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
otPlatRadioSetCoexEnabled(otInstance * aInstance,bool aEnabled)519 otError otPlatRadioSetCoexEnabled(otInstance *aInstance, bool aEnabled)
520 {
521 OT_UNUSED_VARIABLE(aInstance);
522 return GetRadioSpinel().SetCoexEnabled(aEnabled);
523 }
524
otPlatRadioIsCoexEnabled(otInstance * aInstance)525 bool otPlatRadioIsCoexEnabled(otInstance *aInstance)
526 {
527 OT_UNUSED_VARIABLE(aInstance);
528 return GetRadioSpinel().IsCoexEnabled();
529 }
530
otPlatRadioGetCoexMetrics(otInstance * aInstance,otRadioCoexMetrics * aCoexMetrics)531 otError otPlatRadioGetCoexMetrics(otInstance *aInstance, otRadioCoexMetrics *aCoexMetrics)
532 {
533 OT_UNUSED_VARIABLE(aInstance);
534
535 otError error = OT_ERROR_NONE;
536
537 VerifyOrExit(aCoexMetrics != nullptr, error = OT_ERROR_INVALID_ARGS);
538
539 error = GetRadioSpinel().GetCoexMetrics(*aCoexMetrics);
540
541 exit:
542 return error;
543 }
544 #endif
545
546 #if OPENTHREAD_CONFIG_DIAG_ENABLE
547 static otPlatDiagOutputCallback sDiagOutputCallback = nullptr;
548 static void *sDiagCallbackContext = nullptr;
549 static char *sDiagOutput = nullptr;
550 static uint16_t sDiagOutputLen = 0;
551
handleDiagOutput(const char * aFormat,va_list aArguments,void * aContext)552 static void handleDiagOutput(const char *aFormat, va_list aArguments, void *aContext)
553 {
554 OT_UNUSED_VARIABLE(aContext);
555 int charsWritten;
556
557 VerifyOrExit((sDiagOutput != nullptr) && (sDiagOutputLen > 0));
558 charsWritten = vsnprintf(sDiagOutput, sDiagOutputLen, aFormat, aArguments);
559 VerifyOrExit(charsWritten > 0);
560 charsWritten = (sDiagOutputLen <= charsWritten) ? sDiagOutputLen : charsWritten;
561 sDiagOutput += charsWritten;
562 sDiagOutputLen -= charsWritten;
563
564 exit:
565 return;
566 }
567
setDiagOutput(char * aOutput,size_t aSize)568 static void setDiagOutput(char *aOutput, size_t aSize)
569 {
570 sDiagOutput = aOutput;
571 sDiagOutputLen = static_cast<uint16_t>(aSize);
572 GetRadioSpinel().SetDiagOutputCallback(handleDiagOutput, nullptr);
573 }
574
freeDiagOutput(void)575 static void freeDiagOutput(void)
576 {
577 sDiagOutput = nullptr;
578 sDiagOutputLen = 0;
579 GetRadioSpinel().SetDiagOutputCallback(sDiagOutputCallback, sDiagCallbackContext);
580 }
581
otPlatDiagSetOutputCallback(otInstance * aInstance,otPlatDiagOutputCallback aCallback,void * aContext)582 void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext)
583 {
584 OT_UNUSED_VARIABLE(aInstance);
585
586 sDiagOutputCallback = aCallback;
587 sDiagCallbackContext = aContext;
588
589 GetRadioSpinel().SetDiagOutputCallback(aCallback, aContext);
590 #if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
591 GetRcpCapsDiag().SetDiagOutputCallback(aCallback, aContext);
592 #endif
593 }
594
otPlatDiagProcess(otInstance * aInstance,uint8_t aArgsLength,char * aArgs[])595 otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
596 {
597 OT_UNUSED_VARIABLE(aInstance);
598 otError error = OT_ERROR_NONE;
599 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE] = {'\0'};
600 char *cur = cmd;
601 char *end = cmd + sizeof(cmd);
602
603 #if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
604 if (strcmp(aArgs[0], "rcpcaps") == 0)
605 {
606 error = GetRcpCapsDiag().DiagProcess(aArgs, aArgsLength);
607 ExitNow();
608 }
609 #endif
610
611 if (strcmp(aArgs[0], "radiospinel") == 0)
612 {
613 error = GetRadioSpinel().RadioSpinelDiagProcess(aArgs, aArgsLength);
614 ExitNow();
615 }
616
617 for (uint8_t index = 0; (index < aArgsLength) && (cur < end); index++)
618 {
619 cur += snprintf(cur, static_cast<size_t>(end - cur), "%s ", aArgs[index]);
620 }
621
622 // deliver the platform specific diags commands to radio only ncp.
623 error = GetRadioSpinel().PlatDiagProcess(cmd);
624
625 exit:
626 return error;
627 }
628
otPlatDiagModeSet(bool aMode)629 void otPlatDiagModeSet(bool aMode)
630 {
631 SuccessOrExit(GetRadioSpinel().PlatDiagProcess(aMode ? "start" : "stop"));
632 GetRadioSpinel().SetDiagEnabled(aMode);
633
634 exit:
635 return;
636 }
637
otPlatDiagModeGet(void)638 bool otPlatDiagModeGet(void) { return GetRadioSpinel().IsDiagEnabled(); }
639
otPlatDiagTxPowerSet(int8_t aTxPower)640 void otPlatDiagTxPowerSet(int8_t aTxPower)
641 {
642 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
643
644 snprintf(cmd, sizeof(cmd), "power %d", aTxPower);
645 SuccessOrExit(GetRadioSpinel().PlatDiagProcess(cmd));
646
647 exit:
648 return;
649 }
650
otPlatDiagChannelSet(uint8_t aChannel)651 void otPlatDiagChannelSet(uint8_t aChannel)
652 {
653 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
654
655 snprintf(cmd, sizeof(cmd), "channel %d", aChannel);
656 SuccessOrExit(GetRadioSpinel().PlatDiagProcess(cmd));
657
658 exit:
659 return;
660 }
661
otPlatDiagGpioSet(uint32_t aGpio,bool aValue)662 otError otPlatDiagGpioSet(uint32_t aGpio, bool aValue)
663 {
664 otError error;
665 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
666
667 snprintf(cmd, sizeof(cmd), "gpio set %d %d", aGpio, aValue);
668 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
669
670 exit:
671 return error;
672 }
673
otPlatDiagGpioGet(uint32_t aGpio,bool * aValue)674 otError otPlatDiagGpioGet(uint32_t aGpio, bool *aValue)
675 {
676 otError error;
677 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
678 char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
679 char *str;
680
681 setDiagOutput(output, sizeof(output));
682
683 snprintf(cmd, sizeof(cmd), "gpio get %d", aGpio);
684 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
685 VerifyOrExit((str = strtok(output, "\r")) != nullptr, error = OT_ERROR_FAILED);
686 *aValue = static_cast<bool>(atoi(str));
687
688 exit:
689 freeDiagOutput();
690
691 return error;
692 }
693
otPlatDiagGpioSetMode(uint32_t aGpio,otGpioMode aMode)694 otError otPlatDiagGpioSetMode(uint32_t aGpio, otGpioMode aMode)
695 {
696 otError error;
697 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
698
699 snprintf(cmd, sizeof(cmd), "gpio mode %d %s", aGpio, aMode == OT_GPIO_MODE_INPUT ? "in" : "out");
700 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
701
702 exit:
703 return error;
704 }
705
otPlatDiagGpioGetMode(uint32_t aGpio,otGpioMode * aMode)706 otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
707 {
708 otError error;
709 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
710 char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
711 char *str;
712
713 setDiagOutput(output, sizeof(output));
714
715 snprintf(cmd, sizeof(cmd), "gpio mode %d", aGpio);
716 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
717 VerifyOrExit((str = strtok(output, "\r")) != nullptr, error = OT_ERROR_FAILED);
718
719 if (strcmp(str, "in") == 0)
720 {
721 *aMode = OT_GPIO_MODE_INPUT;
722 }
723 else if (strcmp(str, "out") == 0)
724 {
725 *aMode = OT_GPIO_MODE_OUTPUT;
726 }
727 else
728 {
729 error = OT_ERROR_FAILED;
730 }
731
732 exit:
733 freeDiagOutput();
734
735 return error;
736 }
737
otPlatDiagRadioGetPowerSettings(otInstance * aInstance,uint8_t aChannel,int16_t * aTargetPower,int16_t * aActualPower,uint8_t * aRawPowerSetting,uint16_t * aRawPowerSettingLength)738 otError otPlatDiagRadioGetPowerSettings(otInstance *aInstance,
739 uint8_t aChannel,
740 int16_t *aTargetPower,
741 int16_t *aActualPower,
742 uint8_t *aRawPowerSetting,
743 uint16_t *aRawPowerSettingLength)
744 {
745 OT_UNUSED_VARIABLE(aInstance);
746 static constexpr uint16_t kRawPowerStringSize = OPENTHREAD_CONFIG_POWER_CALIBRATION_RAW_POWER_SETTING_SIZE * 2 + 1;
747 static constexpr uint16_t kFmtStringSize = 100;
748
749 otError error;
750 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
751 char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
752 int targetPower;
753 int actualPower;
754 char rawPowerSetting[kRawPowerStringSize];
755 char fmt[kFmtStringSize];
756
757 assert((aTargetPower != nullptr) && (aActualPower != nullptr) && (aRawPowerSetting != nullptr) &&
758 (aRawPowerSettingLength != nullptr));
759
760 setDiagOutput(output, sizeof(output));
761
762 snprintf(cmd, sizeof(cmd), "powersettings %d", aChannel);
763 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
764 snprintf(fmt, sizeof(fmt), "TargetPower(0.01dBm): %%d\r\nActualPower(0.01dBm): %%d\r\nRawPowerSetting: %%%us\r\n",
765 kRawPowerStringSize);
766 VerifyOrExit(sscanf(output, fmt, &targetPower, &actualPower, rawPowerSetting) == 3, error = OT_ERROR_FAILED);
767 SuccessOrExit(
768 error = ot::Utils::CmdLineParser::ParseAsHexString(rawPowerSetting, *aRawPowerSettingLength, aRawPowerSetting));
769 *aTargetPower = static_cast<int16_t>(targetPower);
770 *aActualPower = static_cast<int16_t>(actualPower);
771
772 exit:
773 freeDiagOutput();
774
775 return error;
776 }
777
otPlatDiagRadioSetRawPowerSetting(otInstance * aInstance,const uint8_t * aRawPowerSetting,uint16_t aRawPowerSettingLength)778 otError otPlatDiagRadioSetRawPowerSetting(otInstance *aInstance,
779 const uint8_t *aRawPowerSetting,
780 uint16_t aRawPowerSettingLength)
781 {
782 OT_UNUSED_VARIABLE(aInstance);
783
784 otError error;
785 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
786 int nbytes;
787
788 assert(aRawPowerSetting != nullptr);
789
790 nbytes = snprintf(cmd, sizeof(cmd), "rawpowersetting ");
791
792 for (uint16_t i = 0; i < aRawPowerSettingLength; i++)
793 {
794 nbytes += snprintf(cmd + nbytes, sizeof(cmd) - static_cast<size_t>(nbytes), "%02x", aRawPowerSetting[i]);
795 VerifyOrExit(nbytes < static_cast<int>(sizeof(cmd)), error = OT_ERROR_INVALID_ARGS);
796 }
797
798 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
799
800 exit:
801 return error;
802 }
803
otPlatDiagRadioGetRawPowerSetting(otInstance * aInstance,uint8_t * aRawPowerSetting,uint16_t * aRawPowerSettingLength)804 otError otPlatDiagRadioGetRawPowerSetting(otInstance *aInstance,
805 uint8_t *aRawPowerSetting,
806 uint16_t *aRawPowerSettingLength)
807 {
808 OT_UNUSED_VARIABLE(aInstance);
809 otError error;
810 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
811 char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
812 char *str;
813
814 assert((aRawPowerSetting != nullptr) && (aRawPowerSettingLength != nullptr));
815
816 setDiagOutput(output, sizeof(output));
817
818 snprintf(cmd, sizeof(cmd), "rawpowersetting");
819 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
820 VerifyOrExit((str = strtok(output, "\r")) != nullptr, error = OT_ERROR_FAILED);
821 SuccessOrExit(error = ot::Utils::CmdLineParser::ParseAsHexString(str, *aRawPowerSettingLength, aRawPowerSetting));
822
823 exit:
824 freeDiagOutput();
825
826 return error;
827 }
828
otPlatDiagRadioRawPowerSettingEnable(otInstance * aInstance,bool aEnable)829 otError otPlatDiagRadioRawPowerSettingEnable(otInstance *aInstance, bool aEnable)
830 {
831 OT_UNUSED_VARIABLE(aInstance);
832
833 otError error;
834 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
835
836 snprintf(cmd, sizeof(cmd), "rawpowersetting %s", aEnable ? "enable" : "disable");
837 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
838
839 exit:
840 return error;
841 }
842
otPlatDiagRadioTransmitCarrier(otInstance * aInstance,bool aEnable)843 otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable)
844 {
845 OT_UNUSED_VARIABLE(aInstance);
846
847 otError error;
848 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
849
850 snprintf(cmd, sizeof(cmd), "cw %s", aEnable ? "start" : "stop");
851 SuccessOrExit(error = GetRadioSpinel().PlatDiagProcess(cmd));
852
853 exit:
854 return error;
855 }
856
otPlatDiagRadioTransmitStream(otInstance * aInstance,bool aEnable)857 otError otPlatDiagRadioTransmitStream(otInstance *aInstance, bool aEnable)
858 {
859 OT_UNUSED_VARIABLE(aInstance);
860
861 char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
862
863 snprintf(cmd, sizeof(cmd), "stream %s", aEnable ? "start" : "stop");
864 return GetRadioSpinel().PlatDiagProcess(cmd);
865 }
866
otPlatDiagRadioReceived(otInstance * aInstance,otRadioFrame * aFrame,otError aError)867 void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
868 {
869 OT_UNUSED_VARIABLE(aInstance);
870 OT_UNUSED_VARIABLE(aFrame);
871 OT_UNUSED_VARIABLE(aError);
872 }
873
otPlatDiagAlarmCallback(otInstance * aInstance)874 void otPlatDiagAlarmCallback(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); }
875 #endif // OPENTHREAD_CONFIG_DIAG_ENABLE
876
otPlatRadioGetSupportedChannelMask(otInstance * aInstance)877 uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance)
878 {
879 OT_UNUSED_VARIABLE(aInstance);
880
881 uint32_t channelMask;
882
883 #if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
884 if (sConfig.IsValid())
885 {
886 channelMask = sConfig.GetSupportedChannelMask();
887 }
888 else
889 #endif
890 {
891 channelMask = GetRadioSpinel().GetRadioChannelMask(false);
892 }
893
894 return channelMask;
895 }
896
otPlatRadioGetPreferredChannelMask(otInstance * aInstance)897 uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance)
898 {
899 OT_UNUSED_VARIABLE(aInstance);
900
901 uint32_t channelMask;
902
903 #if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
904 if (sConfig.IsValid())
905 {
906 channelMask = sConfig.GetPreferredChannelMask();
907 }
908 else
909 #endif
910 {
911 channelMask = GetRadioSpinel().GetRadioChannelMask(true);
912 }
913
914 return channelMask;
915 }
916
otPlatRadioGetState(otInstance * aInstance)917 otRadioState otPlatRadioGetState(otInstance *aInstance)
918 {
919 OT_UNUSED_VARIABLE(aInstance);
920 return GetRadioSpinel().GetState();
921 }
922
otPlatRadioSetMacKey(otInstance * aInstance,uint8_t aKeyIdMode,uint8_t aKeyId,const otMacKeyMaterial * aPrevKey,const otMacKeyMaterial * aCurrKey,const otMacKeyMaterial * aNextKey,otRadioKeyType aKeyType)923 void otPlatRadioSetMacKey(otInstance *aInstance,
924 uint8_t aKeyIdMode,
925 uint8_t aKeyId,
926 const otMacKeyMaterial *aPrevKey,
927 const otMacKeyMaterial *aCurrKey,
928 const otMacKeyMaterial *aNextKey,
929 otRadioKeyType aKeyType)
930 {
931 SuccessOrDie(GetRadioSpinel().SetMacKey(aKeyIdMode, aKeyId, aPrevKey, aCurrKey, aNextKey));
932 OT_UNUSED_VARIABLE(aInstance);
933 OT_UNUSED_VARIABLE(aKeyType);
934 }
935
otPlatRadioSetMacFrameCounter(otInstance * aInstance,uint32_t aMacFrameCounter)936 void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter)
937 {
938 SuccessOrDie(GetRadioSpinel().SetMacFrameCounter(aMacFrameCounter, /* aSetIfLarger */ false));
939 OT_UNUSED_VARIABLE(aInstance);
940 }
941
otPlatRadioSetMacFrameCounterIfLarger(otInstance * aInstance,uint32_t aMacFrameCounter)942 void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacFrameCounter)
943 {
944 SuccessOrDie(GetRadioSpinel().SetMacFrameCounter(aMacFrameCounter, /* aSetIfLarger */ true));
945 OT_UNUSED_VARIABLE(aInstance);
946 }
947
otPlatRadioGetNow(otInstance * aInstance)948 uint64_t otPlatRadioGetNow(otInstance *aInstance)
949 {
950 OT_UNUSED_VARIABLE(aInstance);
951 return GetRadioSpinel().GetNow();
952 }
953
otPlatRadioGetBusSpeed(otInstance * aInstance)954 uint32_t otPlatRadioGetBusSpeed(otInstance *aInstance)
955 {
956 OT_UNUSED_VARIABLE(aInstance);
957 return GetRadioSpinel().GetBusSpeed();
958 }
959
otPlatRadioGetBusLatency(otInstance * aInstance)960 uint32_t otPlatRadioGetBusLatency(otInstance *aInstance)
961 {
962 OT_UNUSED_VARIABLE(aInstance);
963 return GetRadioSpinel().GetBusLatency();
964 }
965
966 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
otPlatRadioGetCslAccuracy(otInstance * aInstance)967 uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance)
968 {
969 OT_UNUSED_VARIABLE(aInstance);
970
971 return GetRadioSpinel().GetCslAccuracy();
972 }
973 #endif
974
975 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
otPlatRadioGetCslUncertainty(otInstance * aInstance)976 uint8_t otPlatRadioGetCslUncertainty(otInstance *aInstance)
977 {
978 OT_UNUSED_VARIABLE(aInstance);
979
980 return GetRadioSpinel().GetCslUncertainty();
981 }
982 #endif
983
otPlatRadioSetChannelMaxTransmitPower(otInstance * aInstance,uint8_t aChannel,int8_t aMaxPower)984 otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel, int8_t aMaxPower)
985 {
986 OT_UNUSED_VARIABLE(aInstance);
987 return GetRadioSpinel().SetChannelMaxTransmitPower(aChannel, aMaxPower);
988 }
989
990 #if OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
otPlatRadioAddCalibratedPower(otInstance * aInstance,uint8_t aChannel,int16_t aActualPower,const uint8_t * aRawPowerSetting,uint16_t aRawPowerSettingLength)991 otError otPlatRadioAddCalibratedPower(otInstance *aInstance,
992 uint8_t aChannel,
993 int16_t aActualPower,
994 const uint8_t *aRawPowerSetting,
995 uint16_t aRawPowerSettingLength)
996 {
997 OT_UNUSED_VARIABLE(aInstance);
998 return GetRadioSpinel().AddCalibratedPower(aChannel, aActualPower, aRawPowerSetting, aRawPowerSettingLength);
999 }
1000
otPlatRadioClearCalibratedPowers(otInstance * aInstance)1001 otError otPlatRadioClearCalibratedPowers(otInstance *aInstance)
1002 {
1003 OT_UNUSED_VARIABLE(aInstance);
1004 return GetRadioSpinel().ClearCalibratedPowers();
1005 }
1006
otPlatRadioSetChannelTargetPower(otInstance * aInstance,uint8_t aChannel,int16_t aTargetPower)1007 otError otPlatRadioSetChannelTargetPower(otInstance *aInstance, uint8_t aChannel, int16_t aTargetPower)
1008 {
1009 OT_UNUSED_VARIABLE(aInstance);
1010 return GetRadioSpinel().SetChannelTargetPower(aChannel, aTargetPower);
1011 }
1012 #endif
1013
otPlatRadioSetRegion(otInstance * aInstance,uint16_t aRegionCode)1014 otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
1015 {
1016 OT_UNUSED_VARIABLE(aInstance);
1017
1018 otError error;
1019
1020 #if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
1021 if (sConfig.IsValid())
1022 {
1023 error = sConfig.SetRegion(aRegionCode);
1024 }
1025 else
1026 #endif
1027 {
1028 error = GetRadioSpinel().SetRadioRegion(aRegionCode);
1029 }
1030
1031 return error;
1032 }
1033
otPlatRadioGetRegion(otInstance * aInstance,uint16_t * aRegionCode)1034 otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
1035 {
1036 OT_UNUSED_VARIABLE(aInstance);
1037
1038 otError error;
1039
1040 #if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
1041 if (sConfig.IsValid())
1042 {
1043 *aRegionCode = sConfig.GetRegion();
1044 error = OT_ERROR_NONE;
1045 }
1046 else
1047 #endif
1048 {
1049 error = GetRadioSpinel().GetRadioRegion(aRegionCode);
1050 }
1051
1052 return error;
1053 }
1054
1055 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
otPlatRadioConfigureEnhAckProbing(otInstance * aInstance,otLinkMetrics aLinkMetrics,const otShortAddress aShortAddress,const otExtAddress * aExtAddress)1056 otError otPlatRadioConfigureEnhAckProbing(otInstance *aInstance,
1057 otLinkMetrics aLinkMetrics,
1058 const otShortAddress aShortAddress,
1059 const otExtAddress *aExtAddress)
1060 {
1061 OT_UNUSED_VARIABLE(aInstance);
1062
1063 return GetRadioSpinel().ConfigureEnhAckProbing(aLinkMetrics, aShortAddress, *aExtAddress);
1064 }
1065 #endif
1066
otPlatRadioReceiveAt(otInstance * aInstance,uint8_t aChannel,uint32_t aStart,uint32_t aDuration)1067 otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
1068 {
1069 OT_UNUSED_VARIABLE(aInstance);
1070 OT_UNUSED_VARIABLE(aChannel);
1071 OT_UNUSED_VARIABLE(aStart);
1072 OT_UNUSED_VARIABLE(aDuration);
1073 return OT_ERROR_NOT_IMPLEMENTED;
1074 }
1075
1076 #if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
otPlatResetToBootloader(otInstance * aInstance)1077 otError otPlatResetToBootloader(otInstance *aInstance)
1078 {
1079 OT_UNUSED_VARIABLE(aInstance);
1080
1081 return GetRadioSpinel().SendReset(SPINEL_RESET_BOOTLOADER);
1082 }
1083 #endif
1084
otSysGetRadioSpinelMetrics(void)1085 const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void) { return &GetRadioSpinel().GetRadioSpinelMetrics(); }
1086
otSysGetRcpInterfaceMetrics(void)1087 const otRcpInterfaceMetrics *otSysGetRcpInterfaceMetrics(void)
1088 {
1089 return sRadio.GetSpinelInterface().GetRcpInterfaceMetrics();
1090 }
1091
1092 #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
otSysSetRcpRestorationEnabled(bool aEnabled)1093 void otSysSetRcpRestorationEnabled(bool aEnabled) { return GetRadioSpinel().SetRcpRestorationEnabled(aEnabled); }
1094 #endif
1095