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