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"
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 includes definitions for OpenThread radio abstraction.
32  */
33 
34 #ifndef RADIO_HPP_
35 #define RADIO_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/platform/radio.h>
40 
41 #include <openthread/platform/crypto.h>
42 #include "common/locator.hpp"
43 #include "common/non_copyable.hpp"
44 #include "mac/mac_frame.hpp"
45 
46 namespace ot {
47 
48 static constexpr uint32_t kUsPerTenSymbols = OT_US_PER_TEN_SYMBOLS; ///< Time for 10 symbols in units of microseconds
49 static constexpr uint32_t kRadioHeaderShrDuration = 160;            ///< Duration of SHR in us
50 
51 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
52 /**
53  * Minimum CSL period supported in units of 10 symbols.
54  *
55  */
56 static constexpr uint64_t kMinCslPeriod  = OPENTHREAD_CONFIG_MAC_CSL_MIN_PERIOD * 1000 / kUsPerTenSymbols;
57 static constexpr uint64_t kMaxCslTimeout = OPENTHREAD_CONFIG_MAC_CSL_MAX_TIMEOUT;
58 #endif
59 
60 /**
61  * @addtogroup core-radio
62  *
63  * @brief
64  *   This module includes definitions for OpenThread radio abstraction.
65  *
66  * @{
67  *
68  */
69 
70 /**
71  * This class represents an OpenThread radio abstraction.
72  *
73  */
74 class Radio : public InstanceLocator, private NonCopyable
75 {
76     friend class Instance;
77 
78 public:
79     static constexpr uint32_t kSymbolTime = OT_RADIO_SYMBOL_TIME;
80 #if (OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT && OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT)
81     static constexpr uint16_t kNumChannelPages = 2;
82     static constexpr uint32_t kSupportedChannels =
83         OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK | OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
84     static constexpr uint8_t  kChannelMin            = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
85     static constexpr uint8_t  kChannelMax            = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
86     static constexpr uint32_t kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_0_MASK | OT_RADIO_CHANNEL_PAGE_2_MASK;
87 #elif OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
88     static constexpr uint16_t kNumChannelPages       = 1;
89     static constexpr uint32_t kSupportedChannels     = OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK;
90     static constexpr uint8_t  kChannelMin            = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
91     static constexpr uint8_t  kChannelMax            = OT_RADIO_915MHZ_OQPSK_CHANNEL_MAX;
92     static constexpr uint32_t kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_2_MASK;
93 #elif OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
94     static constexpr uint16_t kNumChannelPages       = 1;
95     static constexpr uint32_t kSupportedChannels     = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
96     static constexpr uint8_t  kChannelMin            = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN;
97     static constexpr uint8_t  kChannelMax            = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
98     static constexpr uint32_t kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_0_MASK;
99 #elif OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
100     static constexpr uint16_t kNumChannelPages       = 1;
101     static constexpr uint32_t kSupportedChannels     = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK;
102     static constexpr uint8_t  kChannelMin            = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MIN;
103     static constexpr uint8_t  kChannelMax            = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MAX;
104     static constexpr uint32_t kSupportedChannelPages = (1 << OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE);
105 #endif
106 
107     static constexpr int8_t kInvalidRssi = OT_RADIO_RSSI_INVALID; ///< Invalid RSSI value.
108 
109     static constexpr int8_t kDefaultReceiveSensitivity = -110; ///< Default receive sensitivity (in dBm).
110 
111     static_assert((OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT || OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT ||
112                    OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT),
113                   "OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT "
114                   "or OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT "
115                   "or OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT "
116                   "must be set to 1 to specify the radio mode");
117 
118     /**
119      * This class defines the callbacks from `Radio`.
120      *
121      */
122     class Callbacks : public InstanceLocator
123     {
124         friend class Radio;
125 
126     public:
127         /**
128          * This callback method handles a "Receive Done" event from radio platform.
129          *
130          * @param[in]  aFrame    A pointer to the received frame or `nullptr` if the receive operation failed.
131          * @param[in]  aError    kErrorNone when successfully received a frame,
132          *                       kErrorAbort when reception was aborted and a frame was not received,
133          *                       kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
134          *
135          */
136         void HandleReceiveDone(Mac::RxFrame *aFrame, Error aError);
137 
138         /**
139          * This callback method handles a "Transmit Started" event from radio platform.
140          *
141          * @param[in]  aFrame     The frame that is being transmitted.
142          *
143          */
144         void HandleTransmitStarted(Mac::TxFrame &aFrame);
145 
146         /**
147          * This callback method handles a "Transmit Done" event from radio platform.
148          *
149          * @param[in]  aFrame     The frame that was transmitted.
150          * @param[in]  aAckFrame  A pointer to the ACK frame, `nullptr` if no ACK was received.
151          * @param[in]  aError     kErrorNone when the frame was transmitted,
152          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
153          *                        kErrorChannelAccessFailure tx could not take place due to activity on the
154          *                        channel, kErrorAbort when transmission was aborted for other reasons.
155          *
156          */
157         void HandleTransmitDone(Mac::TxFrame &aFrame, Mac::RxFrame *aAckFrame, Error aError);
158 
159         /**
160          * This callback method handles "Energy Scan Done" event from radio platform.
161          *
162          * This method is used when radio provides OT_RADIO_CAPS_ENERGY_SCAN capability. It is called from
163          * `otPlatRadioEnergyScanDone()`.
164          *
165          * @param[in]  aMaxRssi  The maximum RSSI encountered on the scanned channel.
166          *
167          */
168         void HandleEnergyScanDone(int8_t aMaxRssi);
169 
170 #if OPENTHREAD_CONFIG_DIAG_ENABLE
171         /**
172          * This callback method handles a "Receive Done" event from radio platform when diagnostics mode is enabled.
173          *
174          * @param[in]  aFrame    A pointer to the received frame or `nullptr` if the receive operation failed.
175          * @param[in]  aError    kErrorNone when successfully received a frame,
176          *                       kErrorAbort when reception was aborted and a frame was not received,
177          *                       kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
178          *
179          */
180         void HandleDiagsReceiveDone(Mac::RxFrame *aFrame, Error aError);
181 
182         /**
183          * This callback method handles a "Transmit Done" event from radio platform when diagnostics mode is enabled.
184          *
185          * @param[in]  aFrame     The frame that was transmitted.
186          * @param[in]  aError     kErrorNone when the frame was transmitted,
187          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
188          *                        kErrorChannelAccessFailure tx could not take place due to activity on the
189          *                        channel, kErrorAbort when transmission was aborted for other reasons.
190          *
191          */
192         void HandleDiagsTransmitDone(Mac::TxFrame &aFrame, Error aError);
193 #endif
194 
195     private:
Callbacks(Instance & aInstance)196         explicit Callbacks(Instance &aInstance)
197             : InstanceLocator(aInstance)
198         {
199         }
200     };
201 
202     /**
203      * This constructor initializes the `Radio` object.
204      *
205      * @param[in]  aInstance  A reference to the OpenThread instance.
206      *
207      */
Radio(Instance & aInstance)208     explicit Radio(Instance &aInstance)
209         : InstanceLocator(aInstance)
210         , mCallbacks(aInstance)
211     {
212     }
213 
214     /**
215      * This method gets the radio version string.
216      *
217      * @returns A pointer to the OpenThread radio version.
218      *
219      */
220     const char *GetVersionString(void);
221 
222     /**
223      * This method gets the factory-assigned IEEE EUI-64 for the device.
224      *
225      * @param[out] aIeeeEui64  A reference to `Mac::ExtAddress` to place the factory-assigned IEEE EUI-64.
226      *
227      */
228     void GetIeeeEui64(Mac::ExtAddress &aIeeeEui64);
229 
230     /**
231      * This method gets the radio capabilities.
232      *
233      * @returns The radio capability bit vector (see `OT_RADIO_CAP_*` definitions).
234      *
235      */
236     otRadioCaps GetCaps(void);
237 
238     /**
239      * This method gets the radio receive sensitivity value.
240      *
241      * @returns The radio receive sensitivity value in dBm.
242      *
243      */
244     int8_t GetReceiveSensitivity(void) const;
245 
246 #if OPENTHREAD_RADIO
247     /**
248      * This method initializes the states of the Thread radio.
249      *
250      */
251     void Init(void);
252 #endif
253 
254     /**
255      * This method sets the PAN ID for address filtering.
256      *
257      * @param[in] aPanId     The IEEE 802.15.4 PAN ID.
258      *
259      */
260     void SetPanId(Mac::PanId aPanId);
261 
262     /**
263      * This method sets the Extended Address for address filtering.
264      *
265      * @param[in] aExtAddress  The IEEE 802.15.4 Extended Address stored in little-endian byte order.
266      *
267      */
268     void SetExtendedAddress(const Mac::ExtAddress &aExtAddress);
269 
270     /**
271      * This method sets the Short Address for address filtering.
272      *
273      * @param[in] aShortAddress  The IEEE 802.15.4 Short Address.
274      *
275      */
276     void SetShortAddress(Mac::ShortAddress aShortAddress);
277 
278     /**
279      * This method sets MAC key and key ID.
280      *
281      * @param[in] aKeyIdMode  MAC key ID mode.
282      * @param[in] aKeyId      Current MAC key index.
283      * @param[in] aPrevKey    The previous MAC key.
284      * @param[in] aCurrKey    The current MAC key.
285      * @param[in] aNextKey    The next MAC key.
286      *
287      */
288     void SetMacKey(uint8_t                 aKeyIdMode,
289                    uint8_t                 aKeyId,
290                    const Mac::KeyMaterial &aPrevKey,
291                    const Mac::KeyMaterial &aCurrKey,
292                    const Mac::KeyMaterial &aNextKey);
293 
294     /**
295      * This method sets the current MAC Frame Counter value.
296      *
297      * @param[in] aMacFrameCounter  The MAC Frame Counter value.
298      *
299      */
SetMacFrameCounter(uint32_t aMacFrameCounter)300     void SetMacFrameCounter(uint32_t aMacFrameCounter)
301     {
302         otPlatRadioSetMacFrameCounter(GetInstancePtr(), aMacFrameCounter);
303     }
304 
305     /**
306      * This method sets the current MAC Frame Counter value only if the new given value is larger than the current
307      * value.
308      *
309      * @param[in] aMacFrameCounter  The MAC Frame Counter value.
310      *
311      */
SetMacFrameCounterIfLarger(uint32_t aMacFrameCounter)312     void SetMacFrameCounterIfLarger(uint32_t aMacFrameCounter)
313     {
314         otPlatRadioSetMacFrameCounterIfLarger(GetInstancePtr(), aMacFrameCounter);
315     }
316 
317     /**
318      * This method gets the radio's transmit power in dBm.
319      *
320      * @param[out] aPower    A reference to output the transmit power in dBm.
321      *
322      * @retval kErrorNone             Successfully retrieved the transmit power.
323      * @retval kErrorNotImplemented   Transmit power configuration via dBm is not implemented.
324      *
325      */
326     Error GetTransmitPower(int8_t &aPower);
327 
328     /**
329      * This method sets the radio's transmit power in dBm.
330      *
331      * @param[in] aPower     The transmit power in dBm.
332      *
333      * @retval kErrorNone             Successfully set the transmit power.
334      * @retval kErrorNotImplemented   Transmit power configuration via dBm is not implemented.
335      *
336      */
337     Error SetTransmitPower(int8_t aPower);
338 
339     /**
340      * This method gets the radio's CCA ED threshold in dBm.
341      *
342      * @param[in] aThreshold    The CCA ED threshold in dBm.
343      *
344      * @retval kErrorNone             A reference to output the CCA ED threshold in dBm.
345      * @retval kErrorNotImplemented   CCA ED threshold configuration via dBm is not implemented.
346      *
347      */
348     Error GetCcaEnergyDetectThreshold(int8_t &aThreshold);
349 
350     /**
351      * This method sets the radio's CCA ED threshold in dBm.
352      *
353      * @param[in] aThreshold    The CCA ED threshold in dBm.
354      *
355      * @retval kErrorNone             Successfully set the CCA ED threshold.
356      * @retval kErrorNotImplemented   CCA ED threshold configuration via dBm is not implemented.
357      *
358      */
359     Error SetCcaEnergyDetectThreshold(int8_t aThreshold);
360 
361     /**
362      * This method gets the status of promiscuous mode.
363      *
364      * @retval TRUE   Promiscuous mode is enabled.
365      * @retval FALSE  Promiscuous mode is disabled.
366      *
367      */
368     bool GetPromiscuous(void);
369 
370     /**
371      * This method enables or disables promiscuous mode.
372      *
373      * @param[in]  aEnable   TRUE to enable or FALSE to disable promiscuous mode.
374      *
375      */
376     void SetPromiscuous(bool aEnable);
377 
378     /**
379      * This method returns the current state of the radio.
380      *
381      * This function is not required by OpenThread. It may be used for debugging and/or application-specific purposes.
382      *
383      * @note This function may be not implemented. In this case it always returns OT_RADIO_STATE_INVALID state.
384      *
385      * @return  Current state of the radio.
386      *
387      */
388     otRadioState GetState(void);
389 
390     /**
391      * This method enables the radio.
392      *
393      * @retval kErrorNone     Successfully enabled.
394      * @retval kErrorFailed   The radio could not be enabled.
395      *
396      */
397     Error Enable(void);
398 
399     /**
400      * This method disables the radio.
401      *
402      * @retval kErrorNone           Successfully transitioned to Disabled.
403      * @retval kErrorInvalidState   The radio was not in sleep state.
404      *
405      */
406     Error Disable(void);
407 
408     /**
409      * This method indicates whether radio is enabled or not.
410      *
411      * @returns TRUE if the radio is enabled, FALSE otherwise.
412      *
413      */
414     bool IsEnabled(void);
415 
416     /**
417      * This method transitions the radio from Receive to Sleep (turn off the radio).
418      *
419      * @retval kErrorNone          Successfully transitioned to Sleep.
420      * @retval kErrorBusy          The radio was transmitting.
421      * @retval kErrorInvalidState  The radio was disabled.
422      *
423      */
424     Error Sleep(void);
425 
426     /**
427      * This method transitions the radio from Sleep to Receive (turn on the radio).
428      *
429      * @param[in]  aChannel   The channel to use for receiving.
430      *
431      * @retval kErrorNone          Successfully transitioned to Receive.
432      * @retval kErrorInvalidState  The radio was disabled or transmitting.
433      *
434      */
435     Error Receive(uint8_t aChannel);
436 
437 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
438     /**
439      * This method updates the CSL sample time in radio.
440      *
441      * @param[in]  aCslSampleTime  The CSL sample time.
442      *
443      */
444     void UpdateCslSampleTime(uint32_t aCslSampleTime);
445 
446     /**
447      * This method schedules a radio reception window at a specific time and duration.
448      *
449      * @param[in]  aChannel   The radio channel on which to receive.
450      * @param[in]  aStart     The receive window start time, in microseconds.
451      * @param[in]  aDuration  The receive window duration, in microseconds.
452      *
453      * @retval kErrorNone    Successfully scheduled receive window.
454      * @retval kErrorFailed  The receive window could not be scheduled.
455      *
456      */
457     Error ReceiveAt(uint8_t aChannel, uint32_t aStart, uint32_t aDuration);
458 
459     /** This method enables CSL sampling in radio.
460      *
461      * @param[in]  aCslPeriod    CSL period, 0 for disabling CSL.
462      * @param[in]  aShortAddr    The short source address of CSL receiver's peer.
463      * @param[in]  aExtAddr      The extended source address of CSL receiver's peer.
464      *
465      * @note Platforms should use CSL peer addresses to include CSL IE when generating enhanced acks.
466      *
467      * @retval  kErrorNotImplemented Radio driver doesn't support CSL.
468      * @retval  kErrorFailed         Other platform specific errors.
469      * @retval  kErrorNone           Successfully enabled or disabled CSL.
470      *
471      */
472     Error EnableCsl(uint32_t aCslPeriod, otShortAddress aShortAddr, const otExtAddress *aExtAddr);
473 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
474 
475 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
476     /**
477      * Get the current accuracy, in units of ± ppm, of the clock used for scheduling CSL operations.
478      *
479      * @note Platforms may optimize this value based on operational conditions (i.e.: temperature).
480      *
481      * @returns The current CSL rx/tx scheduling drift, in units of ± ppm.
482      *
483      */
484     uint8_t GetCslAccuracy(void);
485 
486     /**
487      * Get the fixed uncertainty of the Device for scheduling CSL operations in units of 10 microseconds.
488      *
489      * @returns The CSL Uncertainty in units of 10 us.
490      *
491      */
492     uint8_t GetCslUncertainty(void);
493 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
494 
495     /**
496      * This method gets the radio transmit frame buffer.
497      *
498      * OpenThread forms the IEEE 802.15.4 frame in this buffer then calls `Transmit()` to request transmission.
499      *
500      * @returns A reference to the transmit frame buffer.
501      *
502      */
503     Mac::TxFrame &GetTransmitBuffer(void);
504 
505     /**
506      * This method starts the transmit sequence on the radio.
507      *
508      * The caller must form the IEEE 802.15.4 frame in the buffer provided by `GetTransmitBuffer()` before
509      * requesting transmission.  The channel and transmit power are also included in the frame.
510      *
511      * @param[in] aFrame     A reference to the frame to be transmitted.
512      *
513      * @retval kErrorNone          Successfully transitioned to Transmit.
514      * @retval kErrorInvalidState  The radio was not in the Receive state.
515      *
516      */
517     Error Transmit(Mac::TxFrame &aFrame);
518 
519     /**
520      * This method gets the most recent RSSI measurement.
521      *
522      * @returns The RSSI in dBm when it is valid.  127 when RSSI is invalid.
523      *
524      */
525     int8_t GetRssi(void);
526 
527     /**
528      * This method begins the energy scan sequence on the radio.
529      *
530      * This function is used when radio provides OT_RADIO_CAPS_ENERGY_SCAN capability.
531      *
532      * @param[in] aScanChannel   The channel to perform the energy scan on.
533      * @param[in] aScanDuration  The duration, in milliseconds, for the channel to be scanned.
534      *
535      * @retval kErrorNone            Successfully started scanning the channel.
536      * @retval kErrorBusy            The radio is performing energy scanning.
537      * @retval kErrorNotImplemented  The radio doesn't support energy scanning.
538      *
539      */
540     Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
541 
542     /**
543      * This method enables/disables source address match feature.
544      *
545      * The source address match feature controls how the radio layer decides the "frame pending" bit for acks sent in
546      * response to data request commands from children.
547      *
548      * If disabled, the radio layer must set the "frame pending" on all acks to data request commands.
549      *
550      * If enabled, the radio layer uses the source address match table to determine whether to set or clear the "frame
551      * pending" bit in an ack to a data request command.
552      *
553      * The source address match table provides the list of children for which there is a pending frame. Either a short
554      * address or an extended/long address can be added to the source address match table.
555      *
556      * @param[in]  aEnable     Enable/disable source address match feature.
557      *
558      */
559     void EnableSrcMatch(bool aEnable);
560 
561     /**
562      * This method adds a short address to the source address match table.
563      *
564      * @param[in]  aShortAddress  The short address to be added.
565      *
566      * @retval kErrorNone     Successfully added short address to the source match table.
567      * @retval kErrorNoBufs   No available entry in the source match table.
568      *
569      */
570     Error AddSrcMatchShortEntry(Mac::ShortAddress aShortAddress);
571 
572     /**
573      * This method adds an extended address to the source address match table.
574      *
575      * @param[in]  aExtAddress  The extended address to be added stored in little-endian byte order.
576      *
577      * @retval kErrorNone     Successfully added extended address to the source match table.
578      * @retval kErrorNoBufs   No available entry in the source match table.
579      *
580      */
581     Error AddSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress);
582 
583     /**
584      * This method removes a short address from the source address match table.
585      *
586      * @param[in]  aShortAddress  The short address to be removed.
587      *
588      * @retval kErrorNone       Successfully removed short address from the source match table.
589      * @retval kErrorNoAddress  The short address is not in source address match table.
590      *
591      */
592     Error ClearSrcMatchShortEntry(Mac::ShortAddress aShortAddress);
593 
594     /**
595      * This method removes an extended address from the source address match table.
596      *
597      * @param[in]  aExtAddress  The extended address to be removed stored in little-endian byte order.
598      *
599      * @retval kErrorNone       Successfully removed the extended address from the source match table.
600      * @retval kErrorNoAddress  The extended address is not in source address match table.
601      *
602      */
603     Error ClearSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress);
604 
605     /**
606      * This method clears all short addresses from the source address match table.
607      *
608      */
609     void ClearSrcMatchShortEntries(void);
610 
611     /**
612      * This method clears all the extended/long addresses from source address match table.
613      *
614      */
615     void ClearSrcMatchExtEntries(void);
616 
617     /**
618      * This method gets the radio supported channel mask that the device is allowed to be on.
619      *
620      * @returns The radio supported channel mask.
621      *
622      */
623     uint32_t GetSupportedChannelMask(void);
624 
625     /**
626      * This method gets the radio preferred channel mask that the device prefers to form on.
627      *
628      * @returns The radio preferred channel mask.
629      *
630      */
631     uint32_t GetPreferredChannelMask(void);
632 
633 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
634     /**
635      * This method enables/disables or updates Enhanced-ACK Based Probing in radio for a specific Initiator.
636      *
637      * After Enhanced-ACK Based Probing is configured by a specific Probing Initiator, the Enhanced-ACK sent to that
638      * node should include Vendor-Specific IE containing Link Metrics data. This method informs the radio to
639      * starts/stops to collect Link Metrics data and include Vendor-Specific IE that containing the data
640      * in Enhanced-ACK sent to that Probing Initiator.
641      *
642      * @param[in]  aLinkMetrics  This parameter specifies what metrics to query. Per spec 4.11.3.4.4.6, at most 2
643      *                           metrics can be specified. The probing would be disabled if @p `aLinkMetrics` is
644      *                           bitwise 0.
645      * @param[in]  aShortAddress The short address of the the probing Initiator.
646      * @param[in]  aExtAddress   The extended source address of the probing Initiator.
647      *
648      * @retval kErrorNone            Successfully enable/disable or update Enhanced-ACK Based Probing for a specific
649      *                               Initiator.
650      * @retval kErrorInvalidArgs     @p aDataLength or @p aExtAddr is not valid.
651      * @retval kErrorNotImplemented  Radio driver doesn't support Enhanced-ACK Probing.
652      *
653      */
ConfigureEnhAckProbing(otLinkMetrics aLinkMetrics,const Mac::ShortAddress & aShortAddress,const Mac::ExtAddress & aExtAddress)654     Error ConfigureEnhAckProbing(otLinkMetrics            aLinkMetrics,
655                                  const Mac::ShortAddress &aShortAddress,
656                                  const Mac::ExtAddress   &aExtAddress)
657     {
658         return otPlatRadioConfigureEnhAckProbing(GetInstancePtr(), aLinkMetrics, aShortAddress, &aExtAddress);
659     }
660 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
661 
662     /**
663      * This method checks if a given channel is valid as a CSL channel.
664      *
665      * @retval true   The channel is valid.
666      * @retval false  The channel is invalid.
667      *
668      */
IsCslChannelValid(uint8_t aCslChannel)669     static bool IsCslChannelValid(uint8_t aCslChannel)
670     {
671         return ((aCslChannel == 0) ||
672                 ((kChannelMin == aCslChannel) || ((kChannelMin < aCslChannel) && (aCslChannel <= kChannelMax))));
673     }
674 
675 private:
GetInstancePtr(void) const676     otInstance *GetInstancePtr(void) const { return reinterpret_cast<otInstance *>(&InstanceLocator::GetInstance()); }
677 
678     Callbacks mCallbacks;
679 };
680 
681 //---------------------------------------------------------------------------------------------------------------------
682 // Radio APIs that are always mapped to the same `otPlatRadio` function (independent of the link type)
683 
GetVersionString(void)684 inline const char *Radio::GetVersionString(void) { return otPlatRadioGetVersionString(GetInstancePtr()); }
685 
GetIeeeEui64(Mac::ExtAddress & aIeeeEui64)686 inline void Radio::GetIeeeEui64(Mac::ExtAddress &aIeeeEui64)
687 {
688     otPlatRadioGetIeeeEui64(GetInstancePtr(), aIeeeEui64.m8);
689 }
690 
GetSupportedChannelMask(void)691 inline uint32_t Radio::GetSupportedChannelMask(void) { return otPlatRadioGetSupportedChannelMask(GetInstancePtr()); }
692 
GetPreferredChannelMask(void)693 inline uint32_t Radio::GetPreferredChannelMask(void) { return otPlatRadioGetPreferredChannelMask(GetInstancePtr()); }
694 
695 //---------------------------------------------------------------------------------------------------------------------
696 // If IEEE 802.15.4 is among supported radio links, provide inline
697 // mapping of `Radio` method to related `otPlatRadio` functions.
698 
699 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
700 
GetCaps(void)701 inline otRadioCaps Radio::GetCaps(void) { return otPlatRadioGetCaps(GetInstancePtr()); }
702 
GetReceiveSensitivity(void) const703 inline int8_t Radio::GetReceiveSensitivity(void) const { return otPlatRadioGetReceiveSensitivity(GetInstancePtr()); }
704 
SetPanId(Mac::PanId aPanId)705 inline void Radio::SetPanId(Mac::PanId aPanId) { otPlatRadioSetPanId(GetInstancePtr(), aPanId); }
706 
SetMacKey(uint8_t aKeyIdMode,uint8_t aKeyId,const Mac::KeyMaterial & aPrevKey,const Mac::KeyMaterial & aCurrKey,const Mac::KeyMaterial & aNextKey)707 inline void Radio::SetMacKey(uint8_t                 aKeyIdMode,
708                              uint8_t                 aKeyId,
709                              const Mac::KeyMaterial &aPrevKey,
710                              const Mac::KeyMaterial &aCurrKey,
711                              const Mac::KeyMaterial &aNextKey)
712 {
713     otRadioKeyType aKeyType;
714 
715 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
716     aKeyType = OT_KEY_TYPE_KEY_REF;
717 #else
718     aKeyType = OT_KEY_TYPE_LITERAL_KEY;
719 #endif
720 
721     otPlatRadioSetMacKey(GetInstancePtr(), aKeyIdMode, aKeyId, &aPrevKey, &aCurrKey, &aNextKey, aKeyType);
722 }
723 
GetTransmitPower(int8_t & aPower)724 inline Error Radio::GetTransmitPower(int8_t &aPower) { return otPlatRadioGetTransmitPower(GetInstancePtr(), &aPower); }
725 
SetTransmitPower(int8_t aPower)726 inline Error Radio::SetTransmitPower(int8_t aPower) { return otPlatRadioSetTransmitPower(GetInstancePtr(), aPower); }
727 
GetCcaEnergyDetectThreshold(int8_t & aThreshold)728 inline Error Radio::GetCcaEnergyDetectThreshold(int8_t &aThreshold)
729 {
730     return otPlatRadioGetCcaEnergyDetectThreshold(GetInstancePtr(), &aThreshold);
731 }
732 
SetCcaEnergyDetectThreshold(int8_t aThreshold)733 inline Error Radio::SetCcaEnergyDetectThreshold(int8_t aThreshold)
734 {
735     return otPlatRadioSetCcaEnergyDetectThreshold(GetInstancePtr(), aThreshold);
736 }
737 
GetPromiscuous(void)738 inline bool Radio::GetPromiscuous(void) { return otPlatRadioGetPromiscuous(GetInstancePtr()); }
739 
SetPromiscuous(bool aEnable)740 inline void Radio::SetPromiscuous(bool aEnable) { otPlatRadioSetPromiscuous(GetInstancePtr(), aEnable); }
741 
GetState(void)742 inline otRadioState Radio::GetState(void) { return otPlatRadioGetState(GetInstancePtr()); }
743 
Enable(void)744 inline Error Radio::Enable(void) { return otPlatRadioEnable(GetInstancePtr()); }
745 
Disable(void)746 inline Error Radio::Disable(void) { return otPlatRadioDisable(GetInstancePtr()); }
747 
IsEnabled(void)748 inline bool Radio::IsEnabled(void) { return otPlatRadioIsEnabled(GetInstancePtr()); }
749 
Sleep(void)750 inline Error Radio::Sleep(void) { return otPlatRadioSleep(GetInstancePtr()); }
751 
Receive(uint8_t aChannel)752 inline Error Radio::Receive(uint8_t aChannel) { return otPlatRadioReceive(GetInstancePtr(), aChannel); }
753 
754 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
UpdateCslSampleTime(uint32_t aCslSampleTime)755 inline void Radio::UpdateCslSampleTime(uint32_t aCslSampleTime)
756 {
757     otPlatRadioUpdateCslSampleTime(GetInstancePtr(), aCslSampleTime);
758 }
759 
ReceiveAt(uint8_t aChannel,uint32_t aStart,uint32_t aDuration)760 inline Error Radio::ReceiveAt(uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
761 {
762     return otPlatRadioReceiveAt(GetInstancePtr(), aChannel, aStart, aDuration);
763 }
764 
EnableCsl(uint32_t aCslPeriod,otShortAddress aShortAddr,const otExtAddress * aExtAddr)765 inline Error Radio::EnableCsl(uint32_t aCslPeriod, otShortAddress aShortAddr, const otExtAddress *aExtAddr)
766 {
767     return otPlatRadioEnableCsl(GetInstancePtr(), aCslPeriod, aShortAddr, aExtAddr);
768 }
769 #endif
770 
771 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
GetCslAccuracy(void)772 inline uint8_t Radio::GetCslAccuracy(void) { return otPlatRadioGetCslAccuracy(GetInstancePtr()); }
773 #endif
774 
775 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
GetCslUncertainty(void)776 inline uint8_t Radio::GetCslUncertainty(void) { return otPlatRadioGetCslUncertainty(GetInstancePtr()); }
777 #endif
778 
GetTransmitBuffer(void)779 inline Mac::TxFrame &Radio::GetTransmitBuffer(void)
780 {
781     return *static_cast<Mac::TxFrame *>(otPlatRadioGetTransmitBuffer(GetInstancePtr()));
782 }
783 
GetRssi(void)784 inline int8_t Radio::GetRssi(void) { return otPlatRadioGetRssi(GetInstancePtr()); }
785 
EnergyScan(uint8_t aScanChannel,uint16_t aScanDuration)786 inline Error Radio::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
787 {
788     return otPlatRadioEnergyScan(GetInstancePtr(), aScanChannel, aScanDuration);
789 }
790 
EnableSrcMatch(bool aEnable)791 inline void Radio::EnableSrcMatch(bool aEnable) { otPlatRadioEnableSrcMatch(GetInstancePtr(), aEnable); }
792 
AddSrcMatchShortEntry(Mac::ShortAddress aShortAddress)793 inline Error Radio::AddSrcMatchShortEntry(Mac::ShortAddress aShortAddress)
794 {
795     return otPlatRadioAddSrcMatchShortEntry(GetInstancePtr(), aShortAddress);
796 }
797 
AddSrcMatchExtEntry(const Mac::ExtAddress & aExtAddress)798 inline Error Radio::AddSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress)
799 {
800     return otPlatRadioAddSrcMatchExtEntry(GetInstancePtr(), &aExtAddress);
801 }
802 
ClearSrcMatchShortEntry(Mac::ShortAddress aShortAddress)803 inline Error Radio::ClearSrcMatchShortEntry(Mac::ShortAddress aShortAddress)
804 {
805     return otPlatRadioClearSrcMatchShortEntry(GetInstancePtr(), aShortAddress);
806 }
807 
ClearSrcMatchExtEntry(const Mac::ExtAddress & aExtAddress)808 inline Error Radio::ClearSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress)
809 {
810     return otPlatRadioClearSrcMatchExtEntry(GetInstancePtr(), &aExtAddress);
811 }
812 
ClearSrcMatchShortEntries(void)813 inline void Radio::ClearSrcMatchShortEntries(void) { otPlatRadioClearSrcMatchShortEntries(GetInstancePtr()); }
814 
ClearSrcMatchExtEntries(void)815 inline void Radio::ClearSrcMatchExtEntries(void) { otPlatRadioClearSrcMatchExtEntries(GetInstancePtr()); }
816 
817 #else //----------------------------------------------------------------------------------------------------------------
818 
GetCaps(void)819 inline otRadioCaps Radio::GetCaps(void)
820 {
821     return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_TRANSMIT_RETRIES;
822 }
823 
GetReceiveSensitivity(void) const824 inline int8_t Radio::GetReceiveSensitivity(void) const { return kDefaultReceiveSensitivity; }
825 
SetPanId(Mac::PanId)826 inline void Radio::SetPanId(Mac::PanId) {}
827 
SetExtendedAddress(const Mac::ExtAddress &)828 inline void Radio::SetExtendedAddress(const Mac::ExtAddress &) {}
829 
SetShortAddress(Mac::ShortAddress)830 inline void Radio::SetShortAddress(Mac::ShortAddress) {}
831 
SetMacKey(uint8_t,uint8_t,const Mac::KeyMaterial &,const Mac::KeyMaterial &,const Mac::KeyMaterial &)832 inline void Radio::SetMacKey(uint8_t,
833                              uint8_t,
834                              const Mac::KeyMaterial &,
835                              const Mac::KeyMaterial &,
836                              const Mac::KeyMaterial &)
837 {
838 }
839 
GetTransmitPower(int8_t &)840 inline Error Radio::GetTransmitPower(int8_t &) { return kErrorNotImplemented; }
841 
SetTransmitPower(int8_t)842 inline Error Radio::SetTransmitPower(int8_t) { return kErrorNotImplemented; }
843 
GetCcaEnergyDetectThreshold(int8_t &)844 inline Error Radio::GetCcaEnergyDetectThreshold(int8_t &) { return kErrorNotImplemented; }
845 
SetCcaEnergyDetectThreshold(int8_t)846 inline Error Radio::SetCcaEnergyDetectThreshold(int8_t) { return kErrorNotImplemented; }
847 
GetPromiscuous(void)848 inline bool Radio::GetPromiscuous(void) { return false; }
849 
SetPromiscuous(bool)850 inline void Radio::SetPromiscuous(bool) {}
851 
GetState(void)852 inline otRadioState Radio::GetState(void) { return OT_RADIO_STATE_DISABLED; }
853 
Enable(void)854 inline Error Radio::Enable(void) { return kErrorNone; }
855 
Disable(void)856 inline Error Radio::Disable(void) { return kErrorInvalidState; }
857 
IsEnabled(void)858 inline bool Radio::IsEnabled(void) { return true; }
859 
Sleep(void)860 inline Error Radio::Sleep(void) { return kErrorNone; }
861 
Receive(uint8_t)862 inline Error Radio::Receive(uint8_t) { return kErrorNone; }
863 
864 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
UpdateCslSampleTime(uint32_t)865 inline void Radio::UpdateCslSampleTime(uint32_t) {}
866 
ReceiveAt(uint8_t,uint32_t,uint32_t)867 inline Error Radio::ReceiveAt(uint8_t, uint32_t, uint32_t) { return kErrorNone; }
868 
EnableCsl(uint32_t,otShortAddress aShortAddr,const otExtAddress *)869 inline Error Radio::EnableCsl(uint32_t, otShortAddress aShortAddr, const otExtAddress *)
870 {
871     return kErrorNotImplemented;
872 }
873 #endif
874 
875 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
GetCslAccuracy(void)876 inline uint8_t Radio::GetCslAccuracy(void) { return UINT8_MAX; }
877 
GetCslUncertainty(void)878 inline uint8_t Radio::GetCslUncertainty(void) { return UINT8_MAX; }
879 #endif
880 
GetTransmitBuffer(void)881 inline Mac::TxFrame &Radio::GetTransmitBuffer(void)
882 {
883     return *static_cast<Mac::TxFrame *>(otPlatRadioGetTransmitBuffer(GetInstancePtr()));
884 }
885 
Transmit(Mac::TxFrame &)886 inline Error Radio::Transmit(Mac::TxFrame &) { return kErrorAbort; }
887 
GetRssi(void)888 inline int8_t Radio::GetRssi(void) { return kInvalidRssi; }
889 
EnergyScan(uint8_t,uint16_t)890 inline Error Radio::EnergyScan(uint8_t, uint16_t) { return kErrorNotImplemented; }
891 
EnableSrcMatch(bool)892 inline void Radio::EnableSrcMatch(bool) {}
893 
AddSrcMatchShortEntry(Mac::ShortAddress)894 inline Error Radio::AddSrcMatchShortEntry(Mac::ShortAddress) { return kErrorNone; }
895 
AddSrcMatchExtEntry(const Mac::ExtAddress &)896 inline Error Radio::AddSrcMatchExtEntry(const Mac::ExtAddress &) { return kErrorNone; }
897 
ClearSrcMatchShortEntry(Mac::ShortAddress)898 inline Error Radio::ClearSrcMatchShortEntry(Mac::ShortAddress) { return kErrorNone; }
899 
ClearSrcMatchExtEntry(const Mac::ExtAddress &)900 inline Error Radio::ClearSrcMatchExtEntry(const Mac::ExtAddress &) { return kErrorNone; }
901 
ClearSrcMatchShortEntries(void)902 inline void Radio::ClearSrcMatchShortEntries(void) {}
903 
ClearSrcMatchExtEntries(void)904 inline void Radio::ClearSrcMatchExtEntries(void) {}
905 
906 #endif // #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
907 
908 } // namespace ot
909 
910 #endif // RADIO_HPP_
911