1 /* 2 * Copyright (c) 2016-2018, 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 MAC Channel Mask 32 */ 33 34 #ifndef MAC_CHANNEL_MASK_HPP_ 35 #define MAC_CHANNEL_MASK_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <openthread/platform/radio.h> 40 41 #include "common/equatable.hpp" 42 #include "common/numeric_limits.hpp" 43 #include "common/string.hpp" 44 #include "radio/radio.hpp" 45 46 namespace ot { 47 namespace Mac { 48 49 /** 50 * @addtogroup core-mac 51 * 52 * @brief 53 * This module includes definitions for MAC Channel Mask. 54 * 55 * @{ 56 */ 57 58 /** 59 * Defines a channel mask. 60 * 61 * It is a wrapper class around a `uint32_t` bit vector representing a set of channels. 62 */ 63 class ChannelMask : public Unequatable<ChannelMask> 64 { 65 public: 66 /** 67 * This constant specifies the value to pass in `GetNextChannel()` to get the first channel in the mask. 68 */ 69 static constexpr uint8_t kChannelIteratorFirst = 0xff; 70 71 static constexpr uint16_t kInfoStringSize = 45; ///< Recommended buffer size to use with `ToString()`. 72 73 /** 74 * Defines the fixed-length `String` object returned from `ToString()`. 75 */ 76 typedef String<kInfoStringSize> InfoString; 77 78 /** 79 * Initializes a `ChannelMask` instance. 80 */ ChannelMask(void)81 ChannelMask(void) 82 : mMask(0) 83 { 84 } 85 86 /** 87 * Initializes a `ChannelMask` instance with a given mask. 88 * 89 * @param[in] aMask A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). 90 */ ChannelMask(uint32_t aMask)91 explicit ChannelMask(uint32_t aMask) 92 : mMask(aMask) 93 { 94 } 95 96 /** 97 * Clears the channel mask. 98 */ Clear(void)99 void Clear(void) { mMask = 0; } 100 101 /** 102 * Gets the channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). 103 * 104 * @returns The channel mask. 105 */ GetMask(void) const106 uint32_t GetMask(void) const { return mMask; } 107 108 /** 109 * Sets the channel mask. 110 * 111 * @param[in] aMask A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). 112 */ SetMask(uint32_t aMask)113 void SetMask(uint32_t aMask) { mMask = aMask; } 114 115 /** 116 * Indicates if the mask is empty. 117 * 118 * @returns TRUE if the mask is empty, FALSE otherwise. 119 */ IsEmpty(void) const120 bool IsEmpty(void) const { return (mMask == 0); } 121 122 /** 123 * Indicates if the mask contains only a single channel. 124 * 125 * @returns TRUE if channel mask contains a single channel, FALSE otherwise 126 */ IsSingleChannel(void) const127 bool IsSingleChannel(void) const { return ((mMask != 0) && ((mMask & (mMask - 1)) == 0)); } 128 129 /** 130 * Indicates if the mask contains a given channel. 131 * 132 * @param[in] aChannel A channel. 133 * 134 * @returns TRUE if the channel @p aChannel is included in the mask, FALSE otherwise. 135 */ ContainsChannel(uint8_t aChannel) const136 bool ContainsChannel(uint8_t aChannel) const 137 { 138 return (aChannel < BitSizeOf(mMask)) ? ((1UL << aChannel) & mMask) != 0 : false; 139 } 140 141 /** 142 * Adds a channel to the channel mask. 143 * 144 * @param[in] aChannel A channel 145 */ AddChannel(uint8_t aChannel)146 void AddChannel(uint8_t aChannel) 147 { 148 if (aChannel < BitSizeOf(mMask)) 149 { 150 mMask |= (1UL << aChannel); 151 } 152 } 153 154 /** 155 * Removes a channel from the channel mask. 156 * 157 * @param[in] aChannel A channel 158 */ RemoveChannel(uint8_t aChannel)159 void RemoveChannel(uint8_t aChannel) 160 { 161 if (aChannel < BitSizeOf(mMask)) 162 { 163 mMask &= ~(1UL << aChannel); 164 } 165 } 166 167 /** 168 * Updates the channel mask by intersecting it with another mask. 169 * 170 * @param[in] aOtherMask Another channel mask. 171 */ Intersect(const ChannelMask & aOtherMask)172 void Intersect(const ChannelMask &aOtherMask) { mMask &= aOtherMask.mMask; } 173 174 /** 175 * Returns the number of channels in the mask. 176 * 177 * @returns Number of channels in the mask. 178 */ 179 uint8_t GetNumberOfChannels(void) const; 180 181 /** 182 * Gets the next channel in the channel mask. 183 * 184 * Can be used to iterate over all channels in the channel mask. To get the first channel (channel with 185 * lowest number) in the mask the @p aChannel should be set to `kChannelIteratorFirst`. 186 * 187 * @param[in,out] aChannel A reference to a `uint8_t`. 188 * On entry it should contain the previous channel or `kChannelIteratorFirst`. 189 * On exit it contains the next channel. 190 * 191 * @retval kErrorNone Got the next channel, @p aChannel updated successfully. 192 * @retval kErrorNotFound No next channel in the channel mask (note: @p aChannel may be changed). 193 */ 194 Error GetNextChannel(uint8_t &aChannel) const; 195 196 /** 197 * Randomly chooses a channel from the channel mask. 198 * 199 * @returns A randomly chosen channel from the given mask, or `kChannelIteratorFirst` if the mask is empty. 200 */ 201 uint8_t ChooseRandomChannel(void) const; 202 203 /** 204 * Overloads `==` operator to indicate whether two masks are equal. 205 * 206 * @param[in] aAnother A reference to another mask to compare with the current one. 207 * 208 * @returns TRUE if the two masks are equal, FALSE otherwise. 209 */ operator ==(const ChannelMask & aAnother) const210 bool operator==(const ChannelMask &aAnother) const { return (mMask == aAnother.mMask); } 211 212 /** 213 * Converts the channel mask into a human-readable string. 214 * 215 * Examples of possible output: 216 * - empty mask -> "{ }" 217 * - all channels -> "{ 11-26 }" 218 * - single channel -> "{ 20 }" 219 * - multiple ranges -> "{ 11, 14-17, 20-22, 24, 25 }" 220 * - no range -> "{ 14, 21, 26 }" 221 * 222 * @returns An `InfoString` object representing the channel mask. 223 */ 224 InfoString ToString(void) const; 225 226 private: 227 static_assert((Radio::kChannelMin < 32) && (Radio::kChannelMax < 32), 228 "The channel number is larger than 32. `ChannelMask` uses 32 bit mask."); 229 uint32_t mMask; 230 }; 231 232 /** 233 * @} 234 */ 235 236 } // namespace Mac 237 } // namespace ot 238 239 #endif // MAC_CHANNEL_MASK_HPP_ 240