blob: 0b551670d494ad17d84aab37299ca50a70dcbc09 [file] [log] [blame]
/*
* Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for OpenThread radio abstraction.
*/
#ifndef RADIO_HPP_
#define RADIO_HPP_
#include "openthread-core-config.h"
#include <openthread/platform/radio.h>
#include "common/locator.hpp"
#include "mac/mac_frame.hpp"
#include "utils/static_assert.hpp"
namespace ot {
/**
* @addtogroup core-radio
*
* @brief
* This module includes definitions for OpenThread radio abstraction.
*
* @{
*
*/
/**
* This class represents an OpenThread radio abstraction.
*
*/
class Radio : public InstanceLocator
{
friend class Instance;
public:
/**
* This enumeration defines the IEEE 802.15.4 channel related parameters.
*
*/
enum
{
#if (OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT && OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT)
kNumChannelPages = 2,
kSupportedChannels = OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK | OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK,
kChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN,
kChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX,
kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_0_MASK | OT_RADIO_CHANNEL_PAGE_2_MASK,
#elif OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
kNumChannelPages = 1,
kSupportedChannels = OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK,
kChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN,
kChannelMax = OT_RADIO_915MHZ_OQPSK_CHANNEL_MAX,
kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_2_MASK,
#elif OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
kNumChannelPages = 1,
kSupportedChannels = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK,
kChannelMin = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN,
kChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX,
kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_0_MASK,
#endif
};
OT_STATIC_ASSERT((OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT || OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT),
"OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT or OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT "
"must be set to 1 to specify the radio mode");
/**
* This class defines the callbacks from `Radio`.
*
*/
class Callbacks : public InstanceLocator
{
friend class Radio;
public:
/**
* This callback method handles a "Receive Done" event from radio platform.
*
* @param[in] aFrame A pointer to the received frame or NULL if the receive operation failed.
* @param[in] aError OT_ERROR_NONE when successfully received a frame,
* OT_ERROR_ABORT when reception was aborted and a frame was not received,
* OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space.
*
*/
void HandleReceiveDone(Mac::RxFrame *aFrame, otError aError);
/**
* This callback method handles a "Transmit Started" event from radio platform.
*
* @param[in] aFrame The frame that is being transmitted.
*
*/
void HandleTransmitStarted(Mac::TxFrame &aFrame);
/**
* This callback method handles a "Transmit Done" event from radio platform.
*
* @param[in] aFrame The frame that was transmitted.
* @param[in] aAckFrame A pointer to the ACK frame, NULL if no ACK was received.
* @param[in] aError OT_ERROR_NONE when the frame was transmitted,
* OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
* OT_ERROR_CHANNEL_ACCESS_FAILURE tx could not take place due to activity on the
* channel, OT_ERROR_ABORT when transmission was aborted for other reasons.
*
*/
void HandleTransmitDone(Mac::TxFrame &aFrame, Mac::RxFrame *aAckFrame, otError aError);
/**
* This callback method handles "Energy Scan Done" event from radio platform.
*
* This method is used when radio provides OT_RADIO_CAPS_ENERGY_SCAN capability. It is called from
* `otPlatRadioEnergyScanDone()`.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aEnergyScanMaxRssi The maximum RSSI encountered on the scanned channel.
*
*/
void HandleEnergyScanDone(int8_t aMaxRssi);
#if OPENTHREAD_CONFIG_DIAG_ENABLE
/**
* This callback method handles a "Receive Done" event from radio platform when diagnostics mode is enabled.
*
* @param[in] aFrame A pointer to the received frame or NULL if the receive operation failed.
* @param[in] aError OT_ERROR_NONE when successfully received a frame,
* OT_ERROR_ABORT when reception was aborted and a frame was not received,
* OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space.
*
*/
void HandleDiagsReceiveDone(Mac::RxFrame *aFrame, otError aError);
/**
* This callback method handles a "Transmit Done" event from radio platform when diagnostics mode is enabled.
*
* @param[in] aFrame The frame that was transmitted.
* @param[in] aError OT_ERROR_NONE when the frame was transmitted,
* OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
* OT_ERROR_CHANNEL_ACCESS_FAILURE tx could not take place due to activity on the
* channel, OT_ERROR_ABORT when transmission was aborted for other reasons.
*
*/
void HandleDiagsTransmitDone(Mac::TxFrame &aFrame, otError aError);
#endif
private:
explicit Callbacks(Instance &aInstance)
: InstanceLocator(aInstance)
{
}
};
/**
* This constructor initializes the `Radio` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
Radio(Instance &aInstance)
: InstanceLocator(aInstance)
, mCallbacks(aInstance)
{
}
/**
* This method gets the radio capabilities.
*
* @returns The radio capability bit vector (see `OT_RADIO_CAP_*` definitions).
*
*/
otRadioCaps GetCaps(void) { return otPlatRadioGetCaps(GetInstance()); }
/**
* This method gets the radio version string.
*
* @returns A pointer to the OpenThread radio version.
*
*/
const char *GetVersionString(void) { return otPlatRadioGetVersionString(GetInstance()); }
/**
* This method gets the radio receive sensitivity value.
*
* @returns The radio receive sensitivity value in dBm.
*
*/
int8_t GetReceiveSensitivity(void) { return otPlatRadioGetReceiveSensitivity(GetInstance()); }
/**
* This method gets the factory-assigned IEEE EUI-64 for the device.
*
* @param[out] aIeeeEui64 A reference to `Mac::ExtAddress` to place the factory-assigned IEEE EUI-64.
*
*/
void GetIeeeEui64(Mac::ExtAddress &aIeeeEui64) { otPlatRadioGetIeeeEui64(GetInstance(), aIeeeEui64.m8); }
/**
* This method sets the PAN ID for address filtering.
*
* @param[in] aPanId The IEEE 802.15.4 PAN ID.
*
*/
void SetPanId(Mac::PanId aPanId) { otPlatRadioSetPanId(GetInstance(), aPanId); }
/**
* This method sets the Extended Address for address filtering.
*
* @param[in] aExtAddress The IEEE 802.15.4 Extended Address stored in little-endian byte order.
*
*/
void SetExtendedAddress(const Mac::ExtAddress &aExtAddress)
{
otPlatRadioSetExtendedAddress(GetInstance(), &aExtAddress);
}
/**
* This method sets the Short Address for address filtering.
*
* @param[in] aShortAddress The IEEE 802.15.4 Short Address.
*
*/
void SetShortAddress(Mac::ShortAddress aShortAddress) { otPlatRadioSetShortAddress(GetInstance(), aShortAddress); }
/**
* This method gets the radio's transmit power in dBm.
*
* @param[out] aPower A reference to output the transmit power in dBm.
*
* @retval OT_ERROR_NONE Successfully retrieved the transmit power.
* @retval OT_ERROR_NOT_IMPLEMENTED Transmit power configuration via dBm is not implemented.
*
*/
otError GetTransmitPower(int8_t &aPower) { return otPlatRadioGetTransmitPower(GetInstance(), &aPower); }
/**
* This method sets the radio's transmit power in dBm.
*
* @param[in] aPower The transmit power in dBm.
*
* @retval OT_ERROR_NONE Successfully set the transmit power.
* @retval OT_ERROR_NOT_IMPLEMENTED Transmit power configuration via dBm is not implemented.
*
*/
otError SetTransmitPower(int8_t aPower) { return otPlatRadioSetTransmitPower(GetInstance(), aPower); }
/**
* This method gets the radio's CCA ED threshold in dBm.
*
* @param[in] aThreshold The CCA ED threshold in dBm.
*
* @retval OT_ERROR_NONE A reference to output the CCA ED threshold in dBm.
* @retval OT_ERROR_NOT_IMPLEMENTED CCA ED threshold configuration via dBm is not implemented.
*
*/
otError GetCcaEnergyDetectThreshold(int8_t &aThreshold)
{
return otPlatRadioGetCcaEnergyDetectThreshold(GetInstance(), &aThreshold);
}
/**
* This method sets the radio's CCA ED threshold in dBm.
*
* @param[in] aThreshold The CCA ED threshold in dBm.
*
* @retval OT_ERROR_NONE Successfully set the CCA ED threshold.
* @retval OT_ERROR_NOT_IMPLEMENTED CCA ED threshold configuration via dBm is not implemented.
*
*/
otError SetCcaEnergyDetectThreshold(int8_t aThreshold)
{
return otPlatRadioSetCcaEnergyDetectThreshold(GetInstance(), aThreshold);
}
/**
* This method gets the status of promiscuous mode.
*
* @retval TRUE Promiscuous mode is enabled.
* @retval FALSE Promiscuous mode is disabled.
*
*/
bool GetPromiscuous(void) { return otPlatRadioGetPromiscuous(GetInstance()); }
/**
* This method enables or disables promiscuous mode.
*
* @param[in] aEnable TRUE to enable or FALSE to disable promiscuous mode.
*
*/
void SetPromiscuous(bool aEnable) { otPlatRadioSetPromiscuous(GetInstance(), aEnable); }
/**
* This method returns the current state of the radio.
*
* This function is not required by OpenThread. It may be used for debugging and/or application-specific purposes.
*
* @note This function may be not implemented. In this case it always returns OT_RADIO_STATE_INVALID state.
*
* @return Current state of the radio.
*
*/
otRadioState GetState(void) { return otPlatRadioGetState(GetInstance()); }
/**
* This method enables the radio.
*
* @retval OT_ERROR_NONE Successfully enabled.
* @retval OT_ERROR_FAILED The radio could not be enabled.
*
*/
otError Enable(void) { return otPlatRadioEnable(GetInstance()); }
/**
* This method disables the radio.
*
* @retval OT_ERROR_NONE Successfully transitioned to Disabled.
* @retval OT_ERROR_INVALID_STATE The radio was not in sleep state.
*
*/
otError Disable(void) { return otPlatRadioDisable(GetInstance()); }
/**
* This method indicates whether radio is enabled or not.
*
* @returns TRUE if the radio is enabled, FALSE otherwise.
*
*/
bool IsEnabled(void) { return otPlatRadioIsEnabled(GetInstance()); }
/**
* This method transitions the radio from Receive to Sleep (turn off the radio).
*
* @retval OT_ERROR_NONE Successfully transitioned to Sleep.
* @retval OT_ERROR_BUSY The radio was transmitting.
* @retval OT_ERROR_INVALID_STATE The radio was disabled.
*
*/
otError Sleep(void) { return otPlatRadioSleep(GetInstance()); }
/**
* This method transitions the radio from Sleep to Receive (turn on the radio).
*
* @param[in] aChannel The channel to use for receiving.
*
* @retval OT_ERROR_NONE Successfully transitioned to Receive.
* @retval OT_ERROR_INVALID_STATE The radio was disabled or transmitting.
*
*/
otError Receive(uint8_t aChannel) { return otPlatRadioReceive(GetInstance(), aChannel); }
/**
* This method gets the radio transmit frame buffer.
*
* OpenThread forms the IEEE 802.15.4 frame in this buffer then calls `Transmit()` to request transmission.
*
* @returns A reference to the transmit frame buffer.
*
*/
Mac::TxFrame &GetTransmitBuffer(void)
{
return *static_cast<Mac::TxFrame *>(otPlatRadioGetTransmitBuffer(GetInstance()));
}
/**
* This method starts the transmit sequence on the radio.
*
* The caller must form the IEEE 802.15.4 frame in the buffer provided by `GetTransmitBuffer()` before
* requesting transmission. The channel and transmit power are also included in the frame.
*
* @param[in] aFrame A reference to the frame to be transmitted.
*
* @retval OT_ERROR_NONE Successfully transitioned to Transmit.
* @retval OT_ERROR_INVALID_STATE The radio was not in the Receive state.
*
*/
otError Transmit(Mac::TxFrame &aFrame) { return otPlatRadioTransmit(GetInstance(), &aFrame); }
/**
* This method gets the most recent RSSI measurement.
*
* @returns The RSSI in dBm when it is valid. 127 when RSSI is invalid.
*
*/
int8_t GetRssi(void) { return otPlatRadioGetRssi(GetInstance()); }
/**
* This method begins the energy scan sequence on the radio.
*
* This function is used when radio provides OT_RADIO_CAPS_ENERGY_SCAN capability.
*
* @param[in] aScanChannel The channel to perform the energy scan on.
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
*
* @retval OT_ERROR_NONE Successfully started scanning the channel.
* @retval OT_ERROR_NOT_IMPLEMENTED The radio doesn't support energy scanning.
*
*/
otError EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
{
return otPlatRadioEnergyScan(GetInstance(), aScanChannel, aScanDuration);
}
/**
* This method enables/disables source address match feature.
*
* The source address match feature controls how the radio layer decides the "frame pending" bit for acks sent in
* response to data request commands from children.
*
* If disabled, the radio layer must set the "frame pending" on all acks to data request commands.
*
* If enabled, the radio layer uses the source address match table to determine whether to set or clear the "frame
* pending" bit in an ack to a data request command.
*
* The source address match table provides the list of children for which there is a pending frame. Either a short
* address or an extended/long address can be added to the source address match table.
*
* @param[in] aEnable Enable/disable source address match feature.
*
*/
void EnableSrcMatch(bool aEnable) { return otPlatRadioEnableSrcMatch(GetInstance(), aEnable); }
/**
* This method adds a short address to the source address match table.
*
* @param[in] aShortAddress The short address to be added.
*
* @retval OT_ERROR_NONE Successfully added short address to the source match table.
* @retval OT_ERROR_NO_BUFS No available entry in the source match table.
*
*/
otError AddSrcMatchShortEntry(Mac::ShortAddress aShortAddress)
{
return otPlatRadioAddSrcMatchShortEntry(GetInstance(), aShortAddress);
}
/**
* This method adds an extended address to the source address match table.
*
* @param[in] aExtAddress The extended address to be added stored in little-endian byte order.
*
* @retval OT_ERROR_NONE Successfully added extended address to the source match table.
* @retval OT_ERROR_NO_BUFS No available entry in the source match table.
*
*/
otError AddSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress)
{
return otPlatRadioAddSrcMatchExtEntry(GetInstance(), &aExtAddress);
}
/**
* This method removes a short address from the source address match table.
*
* @param[in] aShortAddress The short address to be removed.
*
* @retval OT_ERROR_NONE Successfully removed short address from the source match table.
* @retval OT_ERROR_NO_ADDRESS The short address is not in source address match table.
*
*/
otError ClearSrcMatchShortEntry(Mac::ShortAddress aShortAddress)
{
return otPlatRadioClearSrcMatchShortEntry(GetInstance(), aShortAddress);
}
/**
* This method removes an extended address from the source address match table.
*
* @param[in] aExtAddress The extended address to be removed stored in little-endian byte order.
*
* @retval OT_ERROR_NONE Successfully removed the extended address from the source match table.
* @retval OT_ERROR_NO_ADDRESS The extended address is not in source address match table.
*
*/
otError ClearSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress)
{
return otPlatRadioClearSrcMatchExtEntry(GetInstance(), &aExtAddress);
}
/**
* This method clears all short addresses from the source address match table.
*
*/
void ClearSrcMatchShortEntries(void) { otPlatRadioClearSrcMatchShortEntries(GetInstance()); }
/**
* This method clears all the extended/long addresses from source address match table.
*
*/
void ClearSrcMatchExtEntries(void) { otPlatRadioClearSrcMatchExtEntries(GetInstance()); }
/**
* This method gets the radio supported channel mask that the device is allowed to be on.
*
* @returns The radio supported channel mask.
*
*/
uint32_t GetSupportedChannelMask(void) { return otPlatRadioGetSupportedChannelMask(GetInstance()); }
/**
* This method gets the radio preferred channel mask that the device prefers to form on.
*
* @returns The radio preferred channel mask.
*
*/
uint32_t GetPreferredChannelMask(void) { return otPlatRadioGetPreferredChannelMask(GetInstance()); }
private:
otInstance *GetInstance(void) { return reinterpret_cast<otInstance *>(&InstanceLocator::GetInstance()); }
Callbacks mCallbacks;
};
} // namespace ot
#endif // RADIO_HPP_