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