1 /*
2  *    Copyright (c) 2019, 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" AND
17  *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20  *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /**
29  * @file
30  *   This file implements the radio platform callbacks into OpenThread and default/weak radio platform APIs.
31  */
32 
33 #include <openthread/instance.h>
34 #include <openthread/platform/time.h>
35 
36 #include "common/code_utils.hpp"
37 #include "common/instance.hpp"
38 #include "radio/radio.hpp"
39 
40 using namespace ot;
41 
42 //---------------------------------------------------------------------------------------------------------------------
43 // otPlatRadio callbacks
44 
45 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
46 
otPlatRadioReceiveDone(otInstance * aInstance,otRadioFrame * aFrame,Error aError)47 extern "C" void otPlatRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, Error aError)
48 {
49     Instance &    instance = *static_cast<Instance *>(aInstance);
50     Mac::RxFrame *rxFrame  = static_cast<Mac::RxFrame *>(aFrame);
51 
52     VerifyOrExit(instance.IsInitialized());
53 
54 #if OPENTHREAD_CONFIG_MULTI_RADIO
55     if (rxFrame != nullptr)
56     {
57         rxFrame->SetRadioType(Mac::kRadioTypeIeee802154);
58     }
59 #endif
60 
61     instance.Get<Radio::Callbacks>().HandleReceiveDone(rxFrame, aError);
62 
63 exit:
64     return;
65 }
66 
otPlatRadioTxStarted(otInstance * aInstance,otRadioFrame * aFrame)67 extern "C" void otPlatRadioTxStarted(otInstance *aInstance, otRadioFrame *aFrame)
68 {
69     Instance &    instance = *static_cast<Instance *>(aInstance);
70     Mac::TxFrame &txFrame  = *static_cast<Mac::TxFrame *>(aFrame);
71 
72     VerifyOrExit(instance.IsInitialized());
73 
74 #if OPENTHREAD_CONFIG_MULTI_RADIO
75     txFrame.SetRadioType(Mac::kRadioTypeIeee802154);
76 #endif
77 
78     instance.Get<Radio::Callbacks>().HandleTransmitStarted(txFrame);
79 
80 exit:
81     return;
82 }
83 
otPlatRadioTxDone(otInstance * aInstance,otRadioFrame * aFrame,otRadioFrame * aAckFrame,Error aError)84 extern "C" void otPlatRadioTxDone(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, Error aError)
85 {
86     Instance &    instance = *static_cast<Instance *>(aInstance);
87     Mac::TxFrame &txFrame  = *static_cast<Mac::TxFrame *>(aFrame);
88     Mac::RxFrame *ackFrame = static_cast<Mac::RxFrame *>(aAckFrame);
89 
90     VerifyOrExit(instance.IsInitialized());
91 
92 #if OPENTHREAD_CONFIG_MULTI_RADIO
93     if (ackFrame != nullptr)
94     {
95         ackFrame->SetRadioType(Mac::kRadioTypeIeee802154);
96     }
97 
98     txFrame.SetRadioType(Mac::kRadioTypeIeee802154);
99 #endif
100 
101     instance.Get<Radio::Callbacks>().HandleTransmitDone(txFrame, ackFrame, aError);
102 
103 exit:
104     return;
105 }
106 
otPlatRadioEnergyScanDone(otInstance * aInstance,int8_t aEnergyScanMaxRssi)107 extern "C" void otPlatRadioEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi)
108 {
109     Instance &instance = *static_cast<Instance *>(aInstance);
110 
111     VerifyOrExit(instance.IsInitialized());
112     instance.Get<Radio::Callbacks>().HandleEnergyScanDone(aEnergyScanMaxRssi);
113 
114 exit:
115     return;
116 }
117 
118 #if OPENTHREAD_CONFIG_DIAG_ENABLE
otPlatDiagRadioReceiveDone(otInstance * aInstance,otRadioFrame * aFrame,Error aError)119 extern "C" void otPlatDiagRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, Error aError)
120 {
121     Instance &    instance = *static_cast<Instance *>(aInstance);
122     Mac::RxFrame *rxFrame  = static_cast<Mac::RxFrame *>(aFrame);
123 
124 #if OPENTHREAD_CONFIG_MULTI_RADIO
125     if (rxFrame != nullptr)
126     {
127         rxFrame->SetRadioType(Mac::kRadioTypeIeee802154);
128     }
129 #endif
130 
131     instance.Get<Radio::Callbacks>().HandleDiagsReceiveDone(rxFrame, aError);
132 }
133 
otPlatDiagRadioTransmitDone(otInstance * aInstance,otRadioFrame * aFrame,Error aError)134 extern "C" void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, Error aError)
135 {
136     Instance &    instance = *static_cast<Instance *>(aInstance);
137     Mac::TxFrame &txFrame  = *static_cast<Mac::TxFrame *>(aFrame);
138 
139 #if OPENTHREAD_CONFIG_MULTI_RADIO
140     txFrame.SetRadioType(Mac::kRadioTypeIeee802154);
141 #endif
142 
143     instance.Get<Radio::Callbacks>().HandleDiagsTransmitDone(txFrame, aError);
144 }
145 #endif
146 
147 #else // #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
148 
otPlatRadioReceiveDone(otInstance *,otRadioFrame *,Error)149 extern "C" void otPlatRadioReceiveDone(otInstance *, otRadioFrame *, Error)
150 {
151 }
152 
otPlatRadioTxStarted(otInstance *,otRadioFrame *)153 extern "C" void otPlatRadioTxStarted(otInstance *, otRadioFrame *)
154 {
155 }
156 
otPlatRadioTxDone(otInstance *,otRadioFrame *,otRadioFrame *,Error)157 extern "C" void otPlatRadioTxDone(otInstance *, otRadioFrame *, otRadioFrame *, Error)
158 {
159 }
160 
otPlatRadioEnergyScanDone(otInstance *,int8_t)161 extern "C" void otPlatRadioEnergyScanDone(otInstance *, int8_t)
162 {
163 }
164 
165 #if OPENTHREAD_CONFIG_DIAG_ENABLE
otPlatDiagRadioReceiveDone(otInstance *,otRadioFrame *,Error)166 extern "C" void otPlatDiagRadioReceiveDone(otInstance *, otRadioFrame *, Error)
167 {
168 }
169 
otPlatDiagRadioTransmitDone(otInstance *,otRadioFrame *,Error)170 extern "C" void otPlatDiagRadioTransmitDone(otInstance *, otRadioFrame *, Error)
171 {
172 }
173 #endif
174 
175 #endif // // #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
176 
177 //---------------------------------------------------------------------------------------------------------------------
178 // Default/weak implementation of radio platform APIs
179 
otPlatRadioGetSupportedChannelMask(otInstance * aInstance)180 OT_TOOL_WEAK uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance)
181 {
182     OT_UNUSED_VARIABLE(aInstance);
183 
184     return Radio::kSupportedChannels;
185 }
186 
otPlatRadioGetPreferredChannelMask(otInstance * aInstance)187 OT_TOOL_WEAK uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance)
188 {
189     return otPlatRadioGetSupportedChannelMask(aInstance);
190 }
191 
otPlatRadioGetVersionString(otInstance * aInstance)192 OT_TOOL_WEAK const char *otPlatRadioGetVersionString(otInstance *aInstance)
193 {
194     OT_UNUSED_VARIABLE(aInstance);
195     return otGetVersionString();
196 }
197 
otPlatRadioGetState(otInstance * aInstance)198 OT_TOOL_WEAK otRadioState otPlatRadioGetState(otInstance *aInstance)
199 {
200     OT_UNUSED_VARIABLE(aInstance);
201 
202     return OT_RADIO_STATE_INVALID;
203 }
204 
otPlatRadioSetMacKey(otInstance * aInstance,uint8_t aKeyIdMode,uint8_t aKeyId,const otMacKey * aPrevKey,const otMacKey * aCurrKey,const otMacKey * aNextKey)205 OT_TOOL_WEAK void otPlatRadioSetMacKey(otInstance *    aInstance,
206                                        uint8_t         aKeyIdMode,
207                                        uint8_t         aKeyId,
208                                        const otMacKey *aPrevKey,
209                                        const otMacKey *aCurrKey,
210                                        const otMacKey *aNextKey)
211 {
212     OT_UNUSED_VARIABLE(aInstance);
213     OT_UNUSED_VARIABLE(aKeyIdMode);
214     OT_UNUSED_VARIABLE(aKeyId);
215     OT_UNUSED_VARIABLE(aPrevKey);
216     OT_UNUSED_VARIABLE(aCurrKey);
217     OT_UNUSED_VARIABLE(aNextKey);
218 }
219 
otPlatRadioSetMacFrameCounter(otInstance * aInstance,uint32_t aMacFrameCounter)220 OT_TOOL_WEAK void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter)
221 {
222     OT_UNUSED_VARIABLE(aInstance);
223     OT_UNUSED_VARIABLE(aMacFrameCounter);
224 }
225 
otPlatTimeGet(void)226 OT_TOOL_WEAK uint64_t otPlatTimeGet(void)
227 {
228     return UINT64_MAX;
229 }
230 
otPlatRadioGetNow(otInstance * aInstance)231 OT_TOOL_WEAK uint64_t otPlatRadioGetNow(otInstance *aInstance)
232 {
233     OT_UNUSED_VARIABLE(aInstance);
234 
235     return UINT64_MAX;
236 }
237 
otPlatRadioGetBusSpeed(otInstance * aInstance)238 OT_TOOL_WEAK uint32_t otPlatRadioGetBusSpeed(otInstance *aInstance)
239 {
240     OT_UNUSED_VARIABLE(aInstance);
241 
242     return 0;
243 }
244 
otPlatRadioGetCslAccuracy(otInstance * aInstance)245 OT_TOOL_WEAK uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance)
246 {
247     OT_UNUSED_VARIABLE(aInstance);
248 
249     return UINT8_MAX;
250 }
251 
otPlatRadioGetCslClockUncertainty(otInstance * aInstance)252 OT_TOOL_WEAK uint8_t otPlatRadioGetCslClockUncertainty(otInstance *aInstance)
253 {
254     OT_UNUSED_VARIABLE(aInstance);
255 
256     return OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT;
257 }
258 
otPlatRadioGetFemLnaGain(otInstance * aInstance,int8_t * aGain)259 OT_TOOL_WEAK Error otPlatRadioGetFemLnaGain(otInstance *aInstance, int8_t *aGain)
260 {
261     OT_UNUSED_VARIABLE(aInstance);
262     OT_UNUSED_VARIABLE(aGain);
263 
264     return kErrorNotImplemented;
265 }
266 
otPlatRadioSetFemLnaGain(otInstance * aInstance,int8_t aGain)267 OT_TOOL_WEAK Error otPlatRadioSetFemLnaGain(otInstance *aInstance, int8_t aGain)
268 {
269     OT_UNUSED_VARIABLE(aInstance);
270     OT_UNUSED_VARIABLE(aGain);
271 
272     return kErrorNotImplemented;
273 }
274 
otPlatRadioSetChannelMaxTransmitPower(otInstance * aInstance,uint8_t aChannel,int8_t aMaxPower)275 OT_TOOL_WEAK Error otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel, int8_t aMaxPower)
276 {
277     OT_UNUSED_VARIABLE(aInstance);
278     OT_UNUSED_VARIABLE(aChannel);
279     OT_UNUSED_VARIABLE(aMaxPower);
280 
281     return kErrorNotImplemented;
282 }
283 
otPlatRadioSetRegion(otInstance * aInstance,uint16_t aRegionCode)284 OT_TOOL_WEAK Error otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
285 {
286     OT_UNUSED_VARIABLE(aInstance);
287     OT_UNUSED_VARIABLE(aRegionCode);
288 
289     return kErrorNotImplemented;
290 }
291 
otPlatRadioGetRegion(otInstance * aInstance,uint16_t * aRegionCode)292 OT_TOOL_WEAK Error otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
293 {
294     OT_UNUSED_VARIABLE(aInstance);
295     OT_UNUSED_VARIABLE(aRegionCode);
296 
297     return kErrorNotImplemented;
298 }
299 
otPlatRadioReceiveAt(otInstance * aInstance,uint8_t aChannel,uint32_t aStart,uint32_t aDuration)300 OT_TOOL_WEAK Error otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
301 {
302     OT_UNUSED_VARIABLE(aInstance);
303     OT_UNUSED_VARIABLE(aChannel);
304     OT_UNUSED_VARIABLE(aStart);
305     OT_UNUSED_VARIABLE(aDuration);
306 
307     return kErrorNotImplemented;
308 }
309