1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "wifi_channel_helper.h"
17 #include "wifi_config_center.h"
18 #include "wifi_logger.h"
19 #include "wifi_settings.h"
20 #ifdef HDI_CHIP_INTERFACE_SUPPORT
21 #include "hal_device_manage.h"
22 #endif
23 
24 namespace OHOS {
25 namespace Wifi {
26 DEFINE_WIFILOG_LABEL("WifiChannelHelper");
27 
28 constexpr int FREQ_2G_MIN = 2412;
29 constexpr int FREQ_2G_MAX = 2472;
30 constexpr int FREQ_5G_MIN = 5170;
31 constexpr int FREQ_5G_MAX = 5825;
32 constexpr int CHANNEL_14_FREQ = 2484;
33 constexpr int CHANNEL_14 = 14;
34 constexpr int CENTER_FREQ_DIFF = 5;
35 constexpr int CHANNEL_2G_MIN = 1;
36 constexpr int CHANNEL_2G_MAX = 14;  // 2484
37 constexpr int CHANNEL_5G_MIN = 34;
38 constexpr int CHANNEL_5G_MAX = 165;  // 5825
39 constexpr int FREQ_CHANNEL_1 = 2412;
40 constexpr int FREQ_CHANNEL_34 = 5170;
41 constexpr int FREQ_2G_MIN_RANGE = 2400;
42 constexpr int FREQ_2G_MAX_RANGE = 2500;
43 constexpr int FREQ_5G_MIN_RANGE = 4900;
44 constexpr int FREQ_5G_MAX_RANGE = 5900;
45 
WifiChannelHelper()46 WifiChannelHelper::WifiChannelHelper()
47 {
48     UpdateValidFreqs();
49 }
50 
GetInstance()51 WifiChannelHelper &WifiChannelHelper::GetInstance()
52 {
53     static WifiChannelHelper gWifiChannelHelper;
54     return gWifiChannelHelper;
55 }
56 
GetValidBands(std::vector<BandType> & bands)57 int WifiChannelHelper::GetValidBands(std::vector<BandType> &bands)
58 {
59     std::unique_lock<std::mutex> lock(mMutex);
60     auto it = mValidChannels.find(BandType::BAND_2GHZ);
61     if (it != mValidChannels.end() && it->second.size() > 0) {
62         bands.push_back(BandType::BAND_2GHZ);
63     }
64     it = mValidChannels.find(BandType::BAND_5GHZ);
65     if (it != mValidChannels.end() && it->second.size() > 0) {
66         bands.push_back(BandType::BAND_5GHZ);
67     }
68     return 0;
69 }
70 
SetValidChannels(const ChannelsTable & channelsInfo)71 int WifiChannelHelper::SetValidChannels(const ChannelsTable &channelsInfo)
72 {
73     std::unique_lock<std::mutex> lock(mMutex);
74     mValidChannels = channelsInfo;
75     return 0;
76 }
77 
GetValidChannels(ChannelsTable & channelsInfo)78 int WifiChannelHelper::GetValidChannels(ChannelsTable &channelsInfo)
79 {
80     std::unique_lock<std::mutex> lock(mMutex);
81     channelsInfo = mValidChannels;
82     return 0;
83 }
84 
UpdateValidChannels(std::string ifaceName,int instId)85 void WifiChannelHelper::UpdateValidChannels(std::string ifaceName, int instId)
86 {
87     WIFI_LOGI("enter UpdateValidChannels");
88     ChannelsTable chanTbs;
89     std::vector<int> freqs2G;
90     std::vector<int> freqs5G;
91     int band = static_cast<int>(BandType::BAND_2GHZ);
92 #ifdef HDI_CHIP_INTERFACE_SUPPORT
93     if (!DelayedSingleton<HalDeviceManager>::GetInstance()->GetFrequenciesByBand(ifaceName, band, freqs2G)) {
94         WIFI_LOGE("get 2g frequencies failed.");
95         WifiSettings::GetInstance().SetDefaultFrequenciesByCountryBand(BandType::BAND_2GHZ, freqs2G, instId);
96     }
97 #endif
98     band = static_cast<int>(BandType::BAND_5GHZ);
99 #ifdef HDI_CHIP_INTERFACE_SUPPORT
100     if (!DelayedSingleton<HalDeviceManager>::GetInstance()->GetFrequenciesByBand(ifaceName, band, freqs5G)) {
101         WIFI_LOGE("get 5g frequencies failed.");
102     }
103 #endif
104     std::vector<int32_t> supp2Gfreqs(freqs2G.begin(), freqs2G.end());
105     std::vector<int32_t> supp5Gfreqs(freqs5G.begin(), freqs5G.end());
106     for (auto iter = supp2Gfreqs.begin(); iter != supp2Gfreqs.end(); iter++) {
107         int32_t channel = TransformFrequencyIntoChannel(*iter);
108         if (channel == INVALID_FREQ_OR_CHANNEL) {
109             continue;
110         }
111         chanTbs[BandType::BAND_2GHZ].push_back(channel);
112     }
113     for (auto iter = supp5Gfreqs.begin(); iter != supp5Gfreqs.end(); iter++) {
114         int32_t channel = TransformFrequencyIntoChannel(*iter);
115         if (channel == INVALID_FREQ_OR_CHANNEL) {
116             continue;
117         }
118         chanTbs[BandType::BAND_5GHZ].push_back(channel);
119     }
120     if (SetValidChannels(chanTbs)) {
121         WIFI_LOGE("%{public}s, fail to SetValidChannels", __func__);
122     }
123 }
124 
UpdateValidFreqs()125 void WifiChannelHelper::UpdateValidFreqs()
126 {
127     std::vector<int> freqs2G;
128     std::vector<int> freqs5G;
129     std::vector<int> freqsDfs;
130     std::string ifaceName = WifiConfigCenter::GetInstance().GetStaIfaceName();
131     int band = static_cast<int>(ScanBandType::SCAN_BAND_24_GHZ);
132 #ifdef HDI_CHIP_INTERFACE_SUPPORT
133     if (!DelayedSingleton<HalDeviceManager>::GetInstance()->GetFrequenciesByBand(ifaceName, band, freqs2G)) {
134         WIFI_LOGE("get 2g frequencies failed.");
135     }
136 #endif
137     band = static_cast<int>(ScanBandType::SCAN_BAND_5_GHZ);
138 #ifdef HDI_CHIP_INTERFACE_SUPPORT
139     if (!DelayedSingleton<HalDeviceManager>::GetInstance()->GetFrequenciesByBand(ifaceName, band, freqs5G)) {
140         WIFI_LOGE("get 5g frequencies failed.");
141     }
142 #endif
143     band = static_cast<int>(ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY);
144 #ifdef HDI_CHIP_INTERFACE_SUPPORT
145     if (!DelayedSingleton<HalDeviceManager>::GetInstance()->GetFrequenciesByBand(ifaceName, band, freqsDfs)) {
146         WIFI_LOGE("get 5g frequencies failed.");
147     }
148 #endif
149     mValidFreqs[ScanBandType::SCAN_BAND_24_GHZ] = freqs2G;
150     mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ] = freqs5G;
151     mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY] = freqsDfs;
152 }
153 
GetAvailableScanFreqs(ScanBandType band,std::vector<int32_t> & freqs)154 bool WifiChannelHelper::GetAvailableScanFreqs(ScanBandType band, std::vector<int32_t>& freqs)
155 {
156     switch (band) {
157         case ScanBandType::SCAN_BAND_24_GHZ: {
158             freqs.assign(mValidFreqs[ScanBandType::SCAN_BAND_24_GHZ].begin(),
159                 mValidFreqs[ScanBandType::SCAN_BAND_24_GHZ].end());
160             return true;
161         }
162         case ScanBandType::SCAN_BAND_5_GHZ: {
163             freqs.assign(mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ].begin(),
164                 mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ].end());
165             return true;
166         }
167         case ScanBandType::SCAN_BAND_BOTH: {
168             freqs.insert(freqs.end(), mValidFreqs[ScanBandType::SCAN_BAND_24_GHZ].begin(),
169                 mValidFreqs[ScanBandType::SCAN_BAND_24_GHZ].end());
170             freqs.insert(freqs.end(), mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ].begin(),
171                 mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ].end());
172             return true;
173         }
174         case ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY: {
175             freqs.assign(mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY].begin(),
176                 mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY].end());
177             return true;
178         }
179         case ScanBandType::SCAN_BAND_5_GHZ_WITH_DFS: {
180             freqs.insert(freqs.end(), mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ].begin(),
181                 mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ].end());
182             freqs.insert(freqs.end(), mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY].begin(),
183                 mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY].end());
184             return true;
185         }
186         case ScanBandType::SCAN_BAND_BOTH_WITH_DFS: {
187             freqs.insert(freqs.end(), mValidFreqs[ScanBandType::SCAN_BAND_24_GHZ].begin(),
188                 mValidFreqs[ScanBandType::SCAN_BAND_24_GHZ].end());
189             freqs.insert(freqs.end(), mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ].begin(),
190                 mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ].end());
191             freqs.insert(freqs.end(), mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY].begin(),
192                 mValidFreqs[ScanBandType::SCAN_BAND_5_GHZ_DFS_ONLY].end());
193             return true;
194         }
195         default:
196             WIFI_LOGE("bandType(%{public}d) is error.\n", band);
197             return false;
198     }
199 }
200 
IsFreqDbac(int freqA,int freqB)201 bool WifiChannelHelper::IsFreqDbac(int freqA, int freqB)
202 {
203     if (freqA == freqB) {
204         return false;
205     }
206     if (IsValid5GHz(freqA) && IsValid5GHz(freqB)) {
207         return true;
208     }
209     if (IsValid24GHz(freqA) && IsValid24GHz(freqB)) {
210         return true;
211     }
212     return false;
213 }
214 
IsChannelDbac(int channelA,int channelB)215 bool WifiChannelHelper::IsChannelDbac(int channelA, int channelB)
216 {
217     if (channelA == channelB) {
218         return false;
219     }
220     if (IsValid5GChannel(channelA) && IsValid5GChannel(channelB)) {
221         return true;
222     }
223     if (IsValid24GChannel(channelA) && IsValid24GChannel(channelB)) {
224         return true;
225     }
226     return false;
227 }
228 
TransformFrequencyIntoChannel(const std::vector<int> & freqVector,std::vector<int> & chanVector)229 void WifiChannelHelper::TransformFrequencyIntoChannel(const std::vector<int> &freqVector, std::vector<int> &chanVector)
230 {
231     int channel;
232     for (size_t i = 0; i < freqVector.size(); ++i) {
233         channel = TransformFrequencyIntoChannel(freqVector[i]);
234         if (channel == -1) {
235             LOGW("Invalid Freq:%d", freqVector[i]);
236             continue;
237         }
238         chanVector.push_back(channel);
239     }
240 }
241 
TransformFrequencyIntoChannel(int freq)242 int WifiChannelHelper::TransformFrequencyIntoChannel(int freq)
243 {
244     if (freq >= FREQ_2G_MIN && freq <= FREQ_2G_MAX) {
245         return (freq - FREQ_2G_MIN) / CENTER_FREQ_DIFF + CHANNEL_2G_MIN;
246     } else if (freq == CHANNEL_14_FREQ) {
247         return CHANNEL_14;
248     } else if (freq >= FREQ_5G_MIN && freq <= FREQ_5G_MAX) {
249         return (freq - FREQ_5G_MIN) / CENTER_FREQ_DIFF + CHANNEL_5G_MIN;
250     }
251     return -1;
252 }
253 
TransformChannelToFrequency(int channel)254 int WifiChannelHelper::TransformChannelToFrequency(int channel)
255 {
256     WIFI_LOGI("ChannelToFrequency: %{public}d", channel);
257     if (channel >= CHANNEL_2G_MIN && channel <= CHANNEL_2G_MAX) {
258         return ((channel - CHANNEL_2G_MIN) * CENTER_FREQ_DIFF + FREQ_CHANNEL_1);
259     }
260     if (CHANNEL_5G_MIN <= channel && channel <= CHANNEL_5G_MAX) {
261         return ((channel - CHANNEL_5G_MIN) * CENTER_FREQ_DIFF + FREQ_CHANNEL_34);
262     }
263     return INVALID_FREQ_OR_CHANNEL;
264 }
265 
TransformFreqToBand(int freq)266 BandType WifiChannelHelper::TransformFreqToBand(int freq)
267 {
268     if (freq <= CHANNEL_14_FREQ) {
269         return BandType::BAND_2GHZ;
270     } else if (freq <= FREQ_5G_MAX) {
271         return BandType::BAND_5GHZ;
272     }
273     return BandType::BAND_NONE;  // not supported currently 6/60GHZ
274 }
275 
TransformChannelToBand(int channel)276 BandType WifiChannelHelper::TransformChannelToBand(int channel)
277 {
278     if (channel <= CHANNEL_2G_MAX) {
279         return BandType::BAND_2GHZ;
280     } else if (channel <= CHANNEL_5G_MAX) {
281         return BandType::BAND_5GHZ;
282     }
283     return BandType::BAND_NONE;  // not supported currently 6/60GHZ
284 }
285 
IsValid24GHz(int freq)286 bool WifiChannelHelper::IsValid24GHz(int freq)
287 {
288     return freq > FREQ_2G_MIN_RANGE && freq < FREQ_2G_MAX_RANGE;
289 }
290 
IsValid5GHz(int freq)291 bool WifiChannelHelper::IsValid5GHz(int freq)
292 {
293     return freq > FREQ_5G_MIN_RANGE && freq < FREQ_5G_MAX_RANGE;
294 }
295 
IsValid24GChannel(int channel)296 bool WifiChannelHelper::IsValid24GChannel(int channel)
297 {
298     return channel >= CHANNEL_2G_MIN && channel <= CHANNEL_2G_MAX;
299 }
300 
IsValid5GChannel(int channel)301 bool WifiChannelHelper::IsValid5GChannel(int channel)
302 {
303     return channel >= CHANNEL_5G_MIN && channel <= CHANNEL_5G_MAX;
304 }
305 
306 } // namespace Wifi
307 } // namespace OHOS
308