• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2024, 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 #include <openthread/platform/radio.h>
30 
31 #include "nexus_core.hpp"
32 #include "nexus_node.hpp"
33 
34 namespace ot {
35 namespace Nexus {
36 
37 //---------------------------------------------------------------------------------------------------------------------
38 // otPlatRadio APIs
39 
40 extern "C" {
41 
otPlatRadioGetCaps(otInstance * aInstance)42 otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
43 {
44     OT_UNUSED_VARIABLE(aInstance);
45     return OT_RADIO_CAPS_NONE;
46 }
47 
otPlatRadioGetReceiveSensitivity(otInstance * aInstance)48 int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
49 {
50     OT_UNUSED_VARIABLE(aInstance);
51     return Radio::kRadioSensetivity;
52 }
53 
otPlatRadioGetIeeeEui64(otInstance * aInstance,uint8_t * aIeeeEui64)54 void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
55 {
56     uint32_t nodeId = AsNode(aInstance).GetInstance().GetId();
57 
58     memset(aIeeeEui64, 0, sizeof(Mac::ExtAddress));
59 
60     aIeeeEui64[6] = (nodeId >> 8) & 0xff;
61     aIeeeEui64[7] = nodeId & 0xff;
62 }
63 
otPlatRadioSetPanId(otInstance * aInstance,otPanId aPanId)64 void otPlatRadioSetPanId(otInstance *aInstance, otPanId aPanId) { AsNode(aInstance).mRadio.mPanId = aPanId; }
65 
otPlatRadioSetExtendedAddress(otInstance * aInstance,const otExtAddress * aExtAddress)66 void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
67 {
68     AsNode(aInstance).mRadio.mExtAddress.Set(aExtAddress->m8, Mac::ExtAddress::kReverseByteOrder);
69 }
70 
otPlatRadioSetShortAddress(otInstance * aInstance,otShortAddress aShortAddress)71 void otPlatRadioSetShortAddress(otInstance *aInstance, otShortAddress aShortAddress)
72 {
73     AsNode(aInstance).mRadio.mShortAddress = aShortAddress;
74 }
75 
otPlatRadioGetPromiscuous(otInstance * aInstance)76 bool otPlatRadioGetPromiscuous(otInstance *aInstance) { return AsNode(aInstance).mRadio.mPromiscuous; }
77 
otPlatRadioSetPromiscuous(otInstance * aInstance,bool aEnable)78 void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) { AsNode(aInstance).mRadio.mPromiscuous = aEnable; }
79 
otPlatRadioGetState(otInstance * aInstance)80 otRadioState otPlatRadioGetState(otInstance *aInstance) { return AsNode(aInstance).mRadio.mState; }
81 
otPlatRadioEnable(otInstance * aInstance)82 otError otPlatRadioEnable(otInstance *aInstance)
83 {
84     Error  error = kErrorNone;
85     Radio &radio = AsNode(aInstance).mRadio;
86 
87     VerifyOrExit(radio.mState == Radio::kStateDisabled, error = kErrorFailed);
88     radio.mState = Radio::kStateSleep;
89 
90 exit:
91     return error;
92 }
93 
otPlatRadioDisable(otInstance * aInstance)94 otError otPlatRadioDisable(otInstance *aInstance)
95 {
96     AsNode(aInstance).mRadio.mState = Radio::kStateDisabled;
97     return kErrorNone;
98 }
99 
otPlatRadioIsEnabled(otInstance * aInstance)100 bool otPlatRadioIsEnabled(otInstance *aInstance) { return AsNode(aInstance).mRadio.mState != Radio::kStateDisabled; }
101 
otPlatRadioSleep(otInstance * aInstance)102 otError otPlatRadioSleep(otInstance *aInstance)
103 {
104     Error  error = kErrorNone;
105     Radio &radio = AsNode(aInstance).mRadio;
106 
107     VerifyOrExit(radio.mState != Radio::kStateDisabled, error = kErrorInvalidState);
108     VerifyOrExit(radio.mState != Radio::kStateTransmit, error = kErrorBusy);
109     radio.mState = Radio::kStateSleep;
110 
111 exit:
112     return error;
113 }
114 
otPlatRadioReceive(otInstance * aInstance,uint8_t aChannel)115 otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
116 {
117     Error  error = kErrorNone;
118     Radio &radio = AsNode(aInstance).mRadio;
119 
120     VerifyOrExit(radio.mState != Radio::kStateDisabled, error = kErrorInvalidState);
121     radio.mState   = Radio::kStateReceive;
122     radio.mChannel = aChannel;
123 
124 exit:
125     return error;
126 }
127 
otPlatRadioGetTransmitBuffer(otInstance * aInstance)128 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) { return &AsNode(aInstance).mRadio.mTxFrame; }
129 
otPlatRadioTransmit(otInstance * aInstance,otRadioFrame * aFrame)130 otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
131 {
132     Error  error = kErrorNone;
133     Radio &radio = AsNode(aInstance).mRadio;
134 
135     VerifyOrExit(radio.mState == Radio::kStateReceive, error = kErrorInvalidState);
136     OT_ASSERT(aFrame == &AsNode(aInstance).mRadio.mTxFrame);
137     radio.mState = Radio::kStateTransmit;
138 
139     Core::Get().MarkPendingAction();
140 
141 exit:
142     return error;
143 }
144 
otPlatRadioGetRssi(otInstance * aInstance)145 int8_t otPlatRadioGetRssi(otInstance *aInstance)
146 {
147     OT_UNUSED_VARIABLE(aInstance);
148     return Radio::kRadioSensetivity;
149 }
150 
otPlatRadioEnableSrcMatch(otInstance * aInstance,bool aEnable)151 void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
152 {
153     AsNode(aInstance).mRadio.mSrcMatchEnabled = aEnable;
154 }
155 
otPlatRadioAddSrcMatchShortEntry(otInstance * aInstance,otShortAddress aShortAddress)156 otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, otShortAddress aShortAddress)
157 {
158     Error  error = kErrorNone;
159     Radio &radio = AsNode(aInstance).mRadio;
160 
161     VerifyOrExit(!radio.mSrcMatchShortEntries.Contains(aShortAddress));
162     error = radio.mSrcMatchShortEntries.PushBack(aShortAddress);
163 
164 exit:
165     return error;
166 }
167 
otPlatRadioAddSrcMatchExtEntry(otInstance * aInstance,const otExtAddress * aExtAddress)168 otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
169 {
170     Error           error = kErrorNone;
171     Radio          &radio = AsNode(aInstance).mRadio;
172     Mac::ExtAddress extAddress;
173 
174     extAddress.Set(aExtAddress->m8, Mac::ExtAddress::kReverseByteOrder);
175 
176     VerifyOrExit(!radio.mSrcMatchExtEntries.Contains(extAddress));
177     error = radio.mSrcMatchExtEntries.PushBack(extAddress);
178 
179 exit:
180     return error;
181 }
182 
otPlatRadioClearSrcMatchShortEntry(otInstance * aInstance,otShortAddress aShortAddress)183 otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, otShortAddress aShortAddress)
184 {
185     Error     error = kErrorNone;
186     Radio    &radio = AsNode(aInstance).mRadio;
187     uint16_t *entry;
188 
189     entry = radio.mSrcMatchShortEntries.Find(aShortAddress);
190     VerifyOrExit(entry != nullptr, error = kErrorNoAddress);
191 
192     radio.mSrcMatchShortEntries.Remove(*entry);
193 
194 exit:
195     return error;
196 }
197 
otPlatRadioClearSrcMatchExtEntry(otInstance * aInstance,const otExtAddress * aExtAddress)198 otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
199 {
200     Error            error = kErrorNone;
201     Radio           &radio = AsNode(aInstance).mRadio;
202     Mac::ExtAddress  extAddress;
203     Mac::ExtAddress *entry;
204 
205     extAddress.Set(aExtAddress->m8, Mac::ExtAddress::kReverseByteOrder);
206 
207     entry = radio.mSrcMatchExtEntries.Find(extAddress);
208     VerifyOrExit(entry != nullptr, error = kErrorNoAddress);
209 
210     radio.mSrcMatchExtEntries.Remove(*entry);
211 
212 exit:
213     return error;
214 }
215 
otPlatRadioClearSrcMatchShortEntries(otInstance * aInstance)216 void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance)
217 {
218     AsNode(aInstance).mRadio.mSrcMatchShortEntries.Clear();
219 }
220 
otPlatRadioClearSrcMatchExtEntries(otInstance * aInstance)221 void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) { AsNode(aInstance).mRadio.mSrcMatchExtEntries.Clear(); }
222 
223 // Not supported
224 
otPlatRadioEnergyScan(otInstance *,uint8_t,uint16_t)225 otError otPlatRadioEnergyScan(otInstance *, uint8_t, uint16_t) { return kErrorNotImplemented; }
226 
otPlatRadioGetTransmitPower(otInstance *,int8_t *)227 otError otPlatRadioGetTransmitPower(otInstance *, int8_t *) { return kErrorNotImplemented; }
otPlatRadioSetTransmitPower(otInstance *,int8_t)228 otError otPlatRadioSetTransmitPower(otInstance *, int8_t) { return kErrorNotImplemented; }
otPlatRadioGetCcaEnergyDetectThreshold(otInstance *,int8_t *)229 otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *, int8_t *) { return kErrorNotImplemented; }
otPlatRadioSetCcaEnergyDetectThreshold(otInstance *,int8_t)230 otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *, int8_t) { return kErrorNotImplemented; }
otPlatRadioGetFemLnaGain(otInstance *,int8_t *)231 otError otPlatRadioGetFemLnaGain(otInstance *, int8_t *) { return kErrorNotImplemented; }
otPlatRadioSetFemLnaGain(otInstance *,int8_t)232 otError otPlatRadioSetFemLnaGain(otInstance *, int8_t) { return kErrorNotImplemented; }
otPlatRadioIsCoexEnabled(otInstance *)233 bool    otPlatRadioIsCoexEnabled(otInstance *) { return false; }
otPlatRadioSetCoexEnabled(otInstance *,bool)234 otError otPlatRadioSetCoexEnabled(otInstance *, bool) { return kErrorNotImplemented; }
otPlatRadioGetCoexMetrics(otInstance *,otRadioCoexMetrics *)235 otError otPlatRadioGetCoexMetrics(otInstance *, otRadioCoexMetrics *) { return kErrorNotImplemented; }
otPlatRadioEnableCsl(otInstance *,uint32_t,otShortAddress,const otExtAddress *)236 otError otPlatRadioEnableCsl(otInstance *, uint32_t, otShortAddress, const otExtAddress *) { return kErrorNone; }
otPlatRadioResetCsl(otInstance *)237 otError otPlatRadioResetCsl(otInstance *) { return kErrorNotImplemented; }
otPlatRadioUpdateCslSampleTime(otInstance *,uint32_t)238 void    otPlatRadioUpdateCslSampleTime(otInstance *, uint32_t) {}
otPlatRadioGetCslAccuracy(otInstance *)239 uint8_t otPlatRadioGetCslAccuracy(otInstance *) { return 0; }
otPlatRadioSetChannelTargetPower(otInstance *,uint8_t,int16_t)240 otError otPlatRadioSetChannelTargetPower(otInstance *, uint8_t, int16_t) { return kErrorNotImplemented; }
otPlatRadioClearCalibratedPowers(otInstance *)241 otError otPlatRadioClearCalibratedPowers(otInstance *) { return kErrorNotImplemented; }
otPlatRadioAddCalibratedPower(otInstance *,uint8_t,int16_t,const uint8_t *,uint16_t)242 otError otPlatRadioAddCalibratedPower(otInstance *, uint8_t, int16_t, const uint8_t *, uint16_t)
243 {
244     return kErrorNotImplemented;
245 }
246 
247 } // extern "C"
248 
249 //---------------------------------------------------------------------------------------------------------------------
250 // Radio
251 
CanReceiveOnChannel(uint8_t aChannel) const252 bool Radio::CanReceiveOnChannel(uint8_t aChannel) const
253 {
254     bool canRx = false;
255 
256     switch (mState)
257     {
258     case kStateReceive:
259     case kStateTransmit:
260         break;
261     default:
262         ExitNow();
263     }
264 
265     VerifyOrExit(mChannel == aChannel);
266     canRx = true;
267 
268 exit:
269     return canRx;
270 }
271 
Matches(const Mac::Address & aAddress,Mac::PanId aPanId) const272 bool Radio::Matches(const Mac::Address &aAddress, Mac::PanId aPanId) const
273 {
274     bool matches = false;
275 
276     if (aAddress.IsShort())
277     {
278         VerifyOrExit(aAddress.IsBroadcast() || aAddress.GetShort() == mShortAddress);
279     }
280     else if (aAddress.IsExtended())
281     {
282         VerifyOrExit(aAddress.GetExtended() == mExtAddress);
283     }
284 
285     if ((aPanId != Mac::kPanIdBroadcast) && (mPanId != Mac::kPanIdBroadcast))
286     {
287         VerifyOrExit(mPanId == aPanId);
288     }
289 
290     matches = true;
291 
292 exit:
293     return matches;
294 }
295 
HasFramePendingFor(const Mac::Address & aAddress) const296 bool Radio::HasFramePendingFor(const Mac::Address &aAddress) const
297 {
298     bool hasPending = false;
299 
300     if (!mSrcMatchEnabled)
301     {
302         // Always mark frame pending when `SrcMatch` is disabled.
303         hasPending = true;
304         ExitNow();
305     }
306 
307     if (aAddress.IsShort())
308     {
309         hasPending = mSrcMatchShortEntries.Contains(aAddress.GetShort());
310     }
311     else if (aAddress.IsExtended())
312     {
313         hasPending = mSrcMatchExtEntries.Contains(aAddress.GetExtended());
314     }
315 
316 exit:
317     return hasPending;
318 }
319 
320 //---------------------------------------------------------------------------------------------------------------------
321 // Radio::Frame
322 
Frame(void)323 Radio::Frame::Frame(void)
324 {
325     ClearAllBytes(*this);
326     mPsdu = &mPsduBuffer[0];
327 }
328 
Frame(const Frame & aFrame)329 Radio::Frame::Frame(const Frame &aFrame)
330 {
331     ClearAllBytes(*this);
332     mPsdu = &mPsduBuffer[0];
333 
334     mLength    = aFrame.mLength;
335     mChannel   = aFrame.mChannel;
336     mRadioType = aFrame.mRadioType;
337     memcpy(mPsdu, aFrame.mPsdu, mLength);
338 }
339 
340 } // namespace Nexus
341 } // namespace ot
342