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