blob: 200ab5b257ecb2900c6a5fc95aff00b2bb46aeaa [file] [log] [blame]
/*
* Copyright (c) 2016-2018, 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 MAC Channel Mask
*/
#ifndef MAC_CHANNEL_MASK_HPP_
#define MAC_CHANNEL_MASK_HPP_
#include "openthread-core-config.h"
#include <limits.h>
#include <openthread/platform/radio.h>
#include "common/equatable.hpp"
#include "common/string.hpp"
#include "radio/radio.hpp"
namespace ot {
namespace Mac {
/**
* @addtogroup core-mac
*
* @brief
* This module includes definitions for MAC Channel Mask.
*
* @{
*
*/
/**
* This class defines a channel mask.
*
* It is a wrapper class around a `uint32_t` bit vector representing a set of channels.
*
*/
class ChannelMask : public Unequatable<ChannelMask>
{
public:
/**
* This constant specifies the value to pass in `GetNextChannel()` to get the first channel in the mask.
*
*/
static constexpr uint8_t kChannelIteratorFirst = 0xff;
static constexpr uint16_t kInfoStringSize = 45; ///< Recommended buffer size to use with `ToString()`.
/**
* This type defines the fixed-length `String` object returned from `ToString()`.
*
*/
typedef String<kInfoStringSize> InfoString;
/**
* This constructor initializes a `ChannelMask` instance.
*
*/
ChannelMask(void)
: mMask(0)
{
}
/**
* This constructor initializes a `ChannelMask` instance with a given mask.
*
* @param[in] aMask A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on).
*
*/
explicit ChannelMask(uint32_t aMask)
: mMask(aMask)
{
}
/**
* This method clears the channel mask.
*
*/
void Clear(void) { mMask = 0; }
/**
* This method gets the channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on).
*
* @returns The channel mask.
*
*/
uint32_t GetMask(void) const { return mMask; }
/**
* This method sets the channel mask.
*
* @param[in] aMask A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on).
*
*/
void SetMask(uint32_t aMask) { mMask = aMask; }
/**
* This method indicates if the mask is empty.
*
* @returns TRUE if the mask is empty, FALSE otherwise.
*
*/
bool IsEmpty(void) const { return (mMask == 0); }
/**
* This method indicates if the mask contains only a single channel.
*
* @returns TRUE if channel mask contains a single channel, FALSE otherwise
*
*/
bool IsSingleChannel(void) const { return ((mMask != 0) && ((mMask & (mMask - 1)) == 0)); }
/**
* This method indicates if the mask contains a given channel.
*
* @param[in] aChannel A channel.
*
* @returns TRUE if the channel @p aChannel is included in the mask, FALSE otherwise.
*
*/
bool ContainsChannel(uint8_t aChannel) const
{
return (aChannel < sizeof(mMask) * CHAR_BIT) ? ((1UL << aChannel) & mMask) != 0 : false;
}
/**
* This method adds a channel to the channel mask.
*
* @param[in] aChannel A channel
*
*/
void AddChannel(uint8_t aChannel)
{
if (aChannel < sizeof(mMask) * CHAR_BIT)
{
mMask |= (1UL << aChannel);
}
}
/**
* This method removes a channel from the channel mask.
*
* @param[in] aChannel A channel
*
*/
void RemoveChannel(uint8_t aChannel)
{
if (aChannel < sizeof(mMask) * CHAR_BIT)
{
mMask &= ~(1UL << aChannel);
}
}
/**
* This method updates the channel mask by intersecting it with another mask.
*
* @param[in] aOtherMask Another channel mask.
*
*/
void Intersect(const ChannelMask &aOtherMask) { mMask &= aOtherMask.mMask; }
/**
* This method returns the number of channels in the mask.
*
* @returns Number of channels in the mask.
*
*/
uint8_t GetNumberOfChannels(void) const;
/**
* This method gets the next channel in the channel mask.
*
* This method can be used to iterate over all channels in the channel mask. To get the first channel (channel with
* lowest number) in the mask the @p aChannel should be set to `kChannelIteratorFirst`.
*
* @param[in,out] aChannel A reference to a `uint8_t`.
* On entry it should contain the previous channel or `kChannelIteratorFirst`.
* On exit it contains the next channel.
*
* @retval kErrorNone Got the next channel, @p aChannel updated successfully.
* @retval kErrorNotFound No next channel in the channel mask (note: @p aChannel may be changed).
*
*/
Error GetNextChannel(uint8_t &aChannel) const;
/**
* This method randomly chooses a channel from the channel mask.
*
* @returns A randomly chosen channel from the given mask, or `kChannelIteratorFirst` if the mask is empty.
*
*/
uint8_t ChooseRandomChannel(void) const;
/**
* This method overloads `==` operator to indicate whether two masks are equal.
*
* @param[in] aAnother A reference to another mask to compare with the current one.
*
* @returns TRUE if the two masks are equal, FALSE otherwise.
*
*/
bool operator==(const ChannelMask &aAnother) const { return (mMask == aAnother.mMask); }
/**
* This method converts the channel mask into a human-readable string.
*
* Examples of possible output:
* - empty mask -> "{ }"
* - all channels -> "{ 11-26 }"
* - single channel -> "{ 20 }"
* - multiple ranges -> "{ 11, 14-17, 20-22, 24, 25 }"
* - no range -> "{ 14, 21, 26 }"
*
* @returns An `InfoString` object representing the channel mask.
*
*/
InfoString ToString(void) const;
private:
static_assert((Radio::kChannelMin < 32) && (Radio::kChannelMax < 32),
"The channel number is larger than 32. `ChannelMask` uses 32 bit mask.");
uint32_t mMask;
};
/**
* @}
*
*/
} // namespace Mac
} // namespace ot
#endif // MAC_CHANNEL_MASK_HPP_