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 <limits.h> 40 #include <openthread/platform/radio.h> 41 42 #include "common/equatable.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 /** 60 * This class defines a channel mask. 61 * 62 * It is a wrapper class around a `uint32_t` bit vector representing a set of channels. 63 * 64 */ 65 class ChannelMask : public Unequatable<ChannelMask> 66 { 67 public: 68 /** 69 * This constant specifies the value to pass in `GetNextChannel()` to get the first channel in the mask. 70 * 71 */ 72 static constexpr uint8_t kChannelIteratorFirst = 0xff; 73 74 static constexpr uint16_t kInfoStringSize = 45; ///< Recommended buffer size to use with `ToString()`. 75 76 /** 77 * This type defines the fixed-length `String` object returned from `ToString()`. 78 * 79 */ 80 typedef String<kInfoStringSize> InfoString; 81 82 /** 83 * This constructor initializes a `ChannelMask` instance. 84 * 85 */ ChannelMask(void)86 ChannelMask(void) 87 : mMask(0) 88 { 89 } 90 91 /** 92 * This constructor initializes a `ChannelMask` instance with a given mask. 93 * 94 * @param[in] aMask A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). 95 * 96 */ ChannelMask(uint32_t aMask)97 explicit ChannelMask(uint32_t aMask) 98 : mMask(aMask) 99 { 100 } 101 102 /** 103 * This method clears the channel mask. 104 * 105 */ Clear(void)106 void Clear(void) { mMask = 0; } 107 108 /** 109 * This method gets the channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). 110 * 111 * @returns The channel mask. 112 * 113 */ GetMask(void) const114 uint32_t GetMask(void) const { return mMask; } 115 116 /** 117 * This method sets the channel mask. 118 * 119 * @param[in] aMask A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on). 120 * 121 */ SetMask(uint32_t aMask)122 void SetMask(uint32_t aMask) { mMask = aMask; } 123 124 /** 125 * This method indicates if the mask is empty. 126 * 127 * @returns TRUE if the mask is empty, FALSE otherwise. 128 * 129 */ IsEmpty(void) const130 bool IsEmpty(void) const { return (mMask == 0); } 131 132 /** 133 * This method indicates if the mask contains only a single channel. 134 * 135 * @returns TRUE if channel mask contains a single channel, FALSE otherwise 136 * 137 */ IsSingleChannel(void) const138 bool IsSingleChannel(void) const { return ((mMask != 0) && ((mMask & (mMask - 1)) == 0)); } 139 140 /** 141 * This method indicates if the mask contains a given channel. 142 * 143 * @param[in] aChannel A channel. 144 * 145 * @returns TRUE if the channel @p aChannel is included in the mask, FALSE otherwise. 146 * 147 */ ContainsChannel(uint8_t aChannel) const148 bool ContainsChannel(uint8_t aChannel) const 149 { 150 return (aChannel < sizeof(mMask) * CHAR_BIT) ? ((1UL << aChannel) & mMask) != 0 : false; 151 } 152 153 /** 154 * This method adds a channel to the channel mask. 155 * 156 * @param[in] aChannel A channel 157 * 158 */ AddChannel(uint8_t aChannel)159 void AddChannel(uint8_t aChannel) 160 { 161 if (aChannel < sizeof(mMask) * CHAR_BIT) 162 { 163 mMask |= (1UL << aChannel); 164 } 165 } 166 167 /** 168 * This method removes a channel from the channel mask. 169 * 170 * @param[in] aChannel A channel 171 * 172 */ RemoveChannel(uint8_t aChannel)173 void RemoveChannel(uint8_t aChannel) 174 { 175 if (aChannel < sizeof(mMask) * CHAR_BIT) 176 { 177 mMask &= ~(1UL << aChannel); 178 } 179 } 180 181 /** 182 * This method updates the channel mask by intersecting it with another mask. 183 * 184 * @param[in] aOtherMask Another channel mask. 185 * 186 */ Intersect(const ChannelMask & aOtherMask)187 void Intersect(const ChannelMask &aOtherMask) { mMask &= aOtherMask.mMask; } 188 189 /** 190 * This method returns the number of channels in the mask. 191 * 192 * @returns Number of channels in the mask. 193 * 194 */ 195 uint8_t GetNumberOfChannels(void) const; 196 197 /** 198 * This method gets the next channel in the channel mask. 199 * 200 * This method can be used to iterate over all channels in the channel mask. To get the first channel (channel with 201 * lowest number) in the mask the @p aChannel should be set to `kChannelIteratorFirst`. 202 * 203 * @param[inout] aChannel A reference to a `uint8_t`. 204 * On entry it should contain the previous channel or `kChannelIteratorFirst`. 205 * On exit it contains the next channel. 206 * 207 * @retval kErrorNone Got the next channel, @p aChannel updated successfully. 208 * @retval kErrorNotFound No next channel in the channel mask (note: @p aChannel may be changed). 209 * 210 */ 211 Error GetNextChannel(uint8_t &aChannel) const; 212 213 /** 214 * This method randomly chooses a channel from the channel mask. 215 * 216 * @returns A randomly chosen channel from the given mask, or `kChannelIteratorFirst` if the mask is empty. 217 * 218 */ 219 uint8_t ChooseRandomChannel(void) const; 220 221 /** 222 * This method overloads `==` operator to indicate whether two masks are equal. 223 * 224 * @param[in] aAnother A reference to another mask to compare with the current one. 225 * 226 * @returns TRUE if the two masks are equal, FALSE otherwise. 227 * 228 */ operator ==(const ChannelMask & aAnother) const229 bool operator==(const ChannelMask &aAnother) const { return (mMask == aAnother.mMask); } 230 231 /** 232 * This method converts the channel mask into a human-readable string. 233 * 234 * Examples of possible output: 235 * - empty mask -> "{ }" 236 * - all channels -> "{ 11-26 }" 237 * - single channel -> "{ 20 }" 238 * - multiple ranges -> "{ 11, 14-17, 20-22, 24, 25 }" 239 * - no range -> "{ 14, 21, 26 }" 240 * 241 * @returns An `InfoString` object representing the channel mask. 242 * 243 */ 244 InfoString ToString(void) const; 245 246 private: 247 static_assert((Radio::kChannelMin < 32) && (Radio::kChannelMax < 32), 248 "The channel number is larger than 32. `ChannelMask` uses 32 bit mask."); 249 uint32_t mMask; 250 }; 251 252 /** 253 * @} 254 * 255 */ 256 257 } // namespace Mac 258 } // namespace ot 259 260 #endif // MAC_CHANNEL_MASK_HPP_ 261