• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
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 <cerrno>
17 #include <cstdint>
18 #include <cstdio>
19 #include <fcntl.h>
20 #include <sys/socket.h>
21 #include <linux/rtnetlink.h>
22 #include <netpacket/packet.h>
23 #include <linux/filter.h>
24 #include <linux/pkt_sched.h>
25 #include <netlink/genl/genl.h>
26 #include <netlink/genl/family.h>
27 #include <netlink/genl/ctrl.h>
28 #include <netlink/object-api.h>
29 #include <netlink/netlink.h>
30 #include <netlink/socket.h>
31 #include <netlink/attr.h>
32 #include <netlink/handlers.h>
33 #include <netlink/msg.h>
34 #include <dirent.h>
35 #include <net/if.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <string>
39 #include "wifi_hal.h"
40 #include "wifi_scan.h"
41 #include "common.h"
42 #include "cpp_bindings.h"
43 
SetExtFeatureFlag(const uint8_t * extFeatureFlagsBytes,uint32_t extFeatureFlagsLen,uint32_t extFeatureFlag)44 static bool SetExtFeatureFlag(const uint8_t *extFeatureFlagsBytes, uint32_t extFeatureFlagsLen, uint32_t extFeatureFlag)
45 {
46     uint32_t extFeatureFlagBytePos;
47     uint32_t extFeatureFlagBitPos;
48 
49     if (extFeatureFlagsBytes == nullptr || extFeatureFlagsLen == 0) {
50         HDF_LOGE("param is NULL.");
51         return false;
52     }
53     extFeatureFlagBytePos = extFeatureFlag / BITNUMS_OF_ONE_BYTE;
54     extFeatureFlagBitPos = extFeatureFlag % BITNUMS_OF_ONE_BYTE;
55     if (extFeatureFlagBytePos >= extFeatureFlagsLen) {
56         return false;
57     }
58     return extFeatureFlagsBytes[extFeatureFlagBytePos] & (1U << extFeatureFlagBitPos);
59 }
60 
61 class GetWiphyIndexCommand : public WifiCommand {
62 public:
GetWiphyIndexCommand(wifiInterfaceHandle handle,uint32_t * wiphyIndex)63     GetWiphyIndexCommand(wifiInterfaceHandle handle, uint32_t *wiphyIndex)
64         : WifiCommand("GetWiphyIndexCommand", handle, 0)
65         {
66         mWiphyIndex = wiphyIndex;
67     }
Create()68     int Create() override
69     {
70         int ret;
71 
72         ret = mMsg.Create(FamilyId(), NL80211_CMD_GET_WIPHY, NLM_F_DUMP, 0);
73         if (ret < 0) {
74             HDF_LOGE("Can't create message to send to driver - %{public}d", ret);
75             return ret;
76         }
77         ret = mMsg.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
78         if (ret < 0) {
79             HDF_LOGE("put ifaceid fail %{public}d", IfaceId());
80             return ret;
81         }
82         return HAL_SUCCESS;
83     }
84 protected:
HandleResponse(WifiEvent & reply)85     int HandleResponse(WifiEvent& reply) override
86     {
87         struct nlattr **attr = reply.Attributes();
88 
89         if (!attr[NL80211_ATTR_WIPHY]) {
90             HDF_LOGE("HandleResponse: wiphy info missing!");
91             return NL_SKIP;
92         }
93         *mWiphyIndex = nla_get_u32(attr[NL80211_ATTR_WIPHY]);
94         return NL_SKIP;
95     }
96 private:
97     uint32_t *mWiphyIndex;
98 };
99 
WifiGetWiphyIndex(wifiInterfaceHandle handle,uint32_t * wiphyIndex)100 static int WifiGetWiphyIndex(wifiInterfaceHandle handle, uint32_t *wiphyIndex)
101 {
102     GetWiphyIndexCommand command(handle, wiphyIndex);
103     auto lock = ReadLockData();
104     return command.RequestResponse();
105 }
106 
107 class GetWiphyInfoCommand : public WifiCommand {
108 public:
GetWiphyInfoCommand(wifiInterfaceHandle handle,uint32_t wiphyIndex)109     GetWiphyInfoCommand(wifiInterfaceHandle handle, uint32_t wiphyIndex)
110         : WifiCommand("GetWiphyInfoCommand", handle, 0)
111     {
112         mWiphyIndex = wiphyIndex;
113         if (memset_s(&mWiphyInfo, sizeof(WiphyInfo), 0, sizeof(WiphyInfo)) != EOK) {
114             HDF_LOGE("memset mWiphyInfo failed");
115         }
116     }
Create()117     int Create() override
118     {
119         int ret;
120 
121         ret = mMsg.Create(FamilyId(), NL80211_CMD_GET_WIPHY, 0, 0);
122         if (ret < 0) {
123             HDF_LOGE("Can't create message to send to driver - %{public}d", ret);
124             return ret;
125         }
126         ret = mMsg.PutU32(NL80211_ATTR_WIPHY, mWiphyIndex);
127         if (ret < 0) {
128             return ret;
129         }
130         return HAL_SUCCESS;
131     }
132 
GetWiphyInfo()133     WiphyInfo &GetWiphyInfo()
134     {
135         return mWiphyInfo;
136     }
137 protected:
HandleResponse(WifiEvent & reply)138     int HandleResponse(WifiEvent& reply) override
139     {
140         struct nlattr **attr = reply.Attributes();
141         uint32_t featureFlags = 0;
142         uint8_t *extFeatureFlagsBytes = nullptr;
143         uint32_t extFeatureFlagsLen = 0;
144 
145         if (attr[NL80211_ATTR_MAX_NUM_SCAN_SSIDS] != nullptr) {
146             mWiphyInfo.scanCapabilities.maxNumScanSsids = nla_get_u8(attr[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
147         }
148         if (attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS] != nullptr) {
149             mWiphyInfo.scanCapabilities.maxNumSchedScanSsids = nla_get_u8(attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
150         }
151         if (attr[NL80211_ATTR_MAX_MATCH_SETS] != nullptr) {
152             mWiphyInfo.scanCapabilities.maxMatchSets = nla_get_u8(attr[NL80211_ATTR_MAX_MATCH_SETS]);
153         }
154         if (attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS] != nullptr) {
155             mWiphyInfo.scanCapabilities.maxNumScanPlans = nla_get_u32(attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS]);
156         }
157         if (attr[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL] != nullptr) {
158             mWiphyInfo.scanCapabilities.maxScanPlanInterval = nla_get_u32(attr[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL]);
159         }
160         if (attr[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS] != nullptr) {
161             mWiphyInfo.scanCapabilities.maxScanPlanIterations =
162                 nla_get_u32(attr[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]);
163         }
164         if (attr[NL80211_ATTR_FEATURE_FLAGS] != nullptr) {
165             featureFlags = nla_get_u32(attr[NL80211_ATTR_FEATURE_FLAGS]);
166         }
167         mWiphyInfo.wiphyFeatures.supportsRandomMacSchedScan = featureFlags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
168         if (attr[NL80211_ATTR_EXT_FEATURES] != nullptr) {
169             extFeatureFlagsBytes = reinterpret_cast<uint8_t *>(nla_data(attr[NL80211_ATTR_EXT_FEATURES]));
170             extFeatureFlagsLen = static_cast<uint32_t>(nla_len(attr[NL80211_ATTR_EXT_FEATURES]));
171             mWiphyInfo.wiphyFeatures.supportsLowPowerOneshotScan =
172                 SetExtFeatureFlag(extFeatureFlagsBytes, extFeatureFlagsLen, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
173             mWiphyInfo.wiphyFeatures.supportsExtSchedScanRelativeRssi =
174                 SetExtFeatureFlag(extFeatureFlagsBytes, extFeatureFlagsLen,
175                     NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
176         }
177         return NL_SKIP;
178     }
179 private:
180     uint32_t mWiphyIndex;
181     WiphyInfo mWiphyInfo;
182 };
183 
WifiGetWiphyInfo(wifiInterfaceHandle handle,uint32_t wiphyIndex,WiphyInfo & wiphyInfo)184 static int WifiGetWiphyInfo(wifiInterfaceHandle handle, uint32_t wiphyIndex, WiphyInfo &wiphyInfo)
185 {
186     GetWiphyInfoCommand command(handle, wiphyIndex);
187     auto lock = ReadLockData();
188     command.RequestResponse();
189     wiphyInfo = command.GetWiphyInfo();
190     return HAL_SUCCESS;
191 }
192 
193 class ScanCommand : public WifiCommand {
194     const OHOS::HDI::Wlan::Chip::V2_0::ScanParams mScanParams;
195     WiphyInfo mWiphyInfo;
196 public:
ScanCommand(wifiInterfaceHandle iface,const OHOS::HDI::Wlan::Chip::V2_0::ScanParams & scanParams,WiphyInfo & wiphyInfo)197     ScanCommand(wifiInterfaceHandle iface,
198         const OHOS::HDI::Wlan::Chip::V2_0::ScanParams& scanParams,
199         WiphyInfo &wiphyInfo)
200         : WifiCommand("ScanCommand", iface, 0), mScanParams(scanParams), mWiphyInfo(wiphyInfo)
201     { }
202 
CreateSetupRequest(WifiRequest & request)203     int CreateSetupRequest(WifiRequest& request)
204     {
205         int result = request.Create(FamilyId(), NL80211_CMD_TRIGGER_SCAN, 0, 0);
206         int i = 0;
207 
208         if (result < 0) {
209             return result;
210         }
211         result = request.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
212         if (result < 0) {
213             return result;
214         }
215         nlattr *ssid = request.AttrStart(NL80211_ATTR_SCAN_SSIDS);
216 
217         /* chip nedd add an empty ssid for a wildcard scan */
218         request.Put(1, nullptr, 0);
219         i += 1;
220         for (auto iter = mScanParams.ssids.begin(); iter != mScanParams.ssids.end(); ++iter) {
221             if (i >= mWiphyInfo.scanCapabilities.maxNumScanSsids) {
222                 HDF_LOGI("Skip the excess hidden ssids for scan");
223                 break;
224             }
225             request.Put(i + 1, (void *)(*iter).c_str(), (*iter).length());
226             i++;
227         }
228         request.AttrEnd(ssid);
229         i = 0;
230         nlattr *freqs = request.AttrStart(NL80211_ATTR_SCAN_FREQUENCIES);
231         for (auto iter = mScanParams.freqs.begin(); iter != mScanParams.freqs.end(); ++iter) {
232             request.PutU32(i + 1, (*iter));
233             i++;
234         }
235         request.AttrEnd(freqs);
236 
237         if (!mScanParams.extraIes.empty()) {
238             request.Put(NL80211_ATTR_IE, (void *)mScanParams.extraIes.c_str(), mScanParams.extraIes.length());
239         }
240 
241         if (!mScanParams.bssid.empty()) {
242             request.Put(NL80211_ATTR_MAC, (void *)mScanParams.bssid.c_str(), mScanParams.bssid.length());
243         }
244         return HAL_SUCCESS;
245     }
246 
Start()247     int Start()
248     {
249         HDF_LOGI("start scan");
250         WifiRequest request(FamilyId(), IfaceId());
251         int result = CreateSetupRequest(request);
252         if (result != HAL_SUCCESS) {
253             HDF_LOGE("failed to create setup request; result = %{public}d", result);
254             return result;
255         }
256         auto lock = ReadLockData();
257         result = RequestResponse(request);
258         if (result < 0) {
259             HDF_LOGE("failed to configure setup; result = %{public}d", result);
260             return result;
261         }
262         return HAL_SUCCESS;
263     }
264 };
265 
266 
WifiStartScan(wifiInterfaceHandle handle,const OHOS::HDI::Wlan::Chip::V2_0::ScanParams & scanParam)267 WifiError WifiStartScan(wifiInterfaceHandle handle,
268     const OHOS::HDI::Wlan::Chip::V2_0::ScanParams& scanParam)
269 {
270     uint32_t wiphyIndex;
271     WiphyInfo wiphyInfo;
272     if (!handle) {
273         HDF_LOGE("Handle is null");
274         return HAL_INVALID_ARGS;
275     }
276     if (WifiGetWiphyIndex(handle, &wiphyIndex) < 0) {
277         HDF_LOGE("can not get wiphyIndex");
278         return HAL_NONE;
279     }
280     if (WifiGetWiphyInfo(handle, wiphyIndex, wiphyInfo) < 0) {
281         HDF_LOGE("can not get wiphyInfo");
282         return HAL_NONE;
283     }
284     ScanCommand scanCommand(handle, scanParam, wiphyInfo);
285     return (WifiError)scanCommand.Start();
286 }
287 
288 class PnoScanCommand : public WifiCommand {
289     const OHOS::HDI::Wlan::Chip::V2_0::PnoScanParams mPnoScanParams;
290     WiphyInfo mWiphyInfo;
291 public:
PnoScanCommand(wifiInterfaceHandle iface,const OHOS::HDI::Wlan::Chip::V2_0::PnoScanParams & pnoScanParams,WiphyInfo & wiphyInfo)292     PnoScanCommand(wifiInterfaceHandle iface,
293         const OHOS::HDI::Wlan::Chip::V2_0::PnoScanParams& pnoScanParams,
294         WiphyInfo &wiphyInfo)
295         : WifiCommand("PnoScanCommand", iface, 0), mPnoScanParams(pnoScanParams), mWiphyInfo(wiphyInfo)
296     { }
297 
CreateSetupRequest(WifiRequest & request)298     int CreateSetupRequest(WifiRequest& request)
299     {
300         int result = request.Create(FamilyId(), NL80211_CMD_START_SCHED_SCAN, 0, 0);
301         if (result < 0) {
302             return result;
303         }
304         result = request.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
305         if (result < 0) {
306             return result;
307         }
308         if (ProcessMatchSsidToMsg(request) != HAL_SUCCESS || ProcessSsidToMsg(request) != HAL_SUCCESS ||
309             ProcessScanPlanToMsg(request) != HAL_SUCCESS || ProcessReqflagsToMsg(request) != HAL_SUCCESS) {
310             HDF_LOGE("%{public}s: Fill parameters to netlink failed.", __FUNCTION__);
311             return HAL_NOT_AVAILABLE;
312         }
313         return HAL_SUCCESS;
314     }
315 
ProcessMatchSsidToMsg(WifiRequest & request)316     int ProcessMatchSsidToMsg(WifiRequest& request)
317     {
318         nlattr *nestedMatchSsid = request.AttrStart(NL80211_ATTR_SCHED_SCAN_MATCH);
319         int i = 0;
320         for (auto iter = mPnoScanParams.savedssids.begin(); iter != mPnoScanParams.savedssids.end(); ++iter) {
321             if (i >= mWiphyInfo.scanCapabilities.maxNumSchedScanSsids) {
322                 HDF_LOGI("Skip the excess saved ssids for pnoscan");
323                 break;
324             }
325             nlattr *nest = request.AttrStart(i);
326             request.Put(NL80211_SCHED_SCAN_MATCH_ATTR_SSID, (void *)(*iter).c_str(), (*iter).length());
327             request.PutU32(NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, mPnoScanParams.min5gRssi);
328             i++;
329             request.AttrEnd(nest);
330         }
331         request.AttrEnd(nestedMatchSsid);
332         return HAL_SUCCESS;
333     }
334 
ProcessSsidToMsg(WifiRequest & request)335     int ProcessSsidToMsg(WifiRequest& request)
336     {
337         nlattr *hiddenSsid = request.AttrStart(NL80211_ATTR_SCAN_SSIDS);
338         int i = 0;
339         for (auto iter = mPnoScanParams.savedssids.begin(); iter != mPnoScanParams.savedssids.end(); ++iter) {
340             if (i >= mWiphyInfo.scanCapabilities.maxNumScanSsids) {
341                 HDF_LOGI("Skip the excess hidden ssids for pnoscan");
342                 break;
343             }
344             request.Put(i, (void *)(*iter).c_str(), (*iter).length());
345             i++;
346         }
347         request.AttrEnd(hiddenSsid);
348         return HAL_SUCCESS;
349     }
350 
ProcessScanPlanToMsg(WifiRequest & request)351     int ProcessScanPlanToMsg(WifiRequest& request)
352     {
353         bool supportNumScanPlans = (mWiphyInfo.scanCapabilities.maxNumScanPlans >= 2);
354         bool supportScanPlanInterval = (mWiphyInfo.scanCapabilities.maxScanPlanInterval * MS_PER_SECOND >=
355             (uint32_t)mPnoScanParams.scanIntervalMs * SLOW_SCAN_INTERVAL_MULTIPLIER);
356         bool supportScanPlanIterations = (mWiphyInfo.scanCapabilities.maxScanPlanIterations >= FAST_SCAN_ITERATIONS);
357 
358         if (supportNumScanPlans && supportScanPlanInterval && supportScanPlanIterations) {
359             nlattr *nestedPlan = request.AttrStart(NL80211_ATTR_SCHED_SCAN_PLANS);
360             nlattr *plan = request.AttrStart(SCHED_SCAN_PLANS_ATTR_INDEX1);
361             request.PutU32(NL80211_SCHED_SCAN_PLAN_INTERVAL, mPnoScanParams.scanIntervalMs);
362             request.PutU32(NL80211_SCHED_SCAN_PLAN_ITERATIONS, mPnoScanParams.scanIterations);
363             request.AttrEnd(plan);
364             plan = request.AttrStart(SCHED_SCAN_PLANS_ATTR_INDEX2);
365             request.PutU32(NL80211_SCHED_SCAN_PLAN_INTERVAL,
366                 mPnoScanParams.scanIntervalMs * SLOW_SCAN_INTERVAL_MULTIPLIER);
367             request.AttrEnd(plan);
368             request.AttrEnd(nestedPlan);
369         } else {
370             request.PutU32(NL80211_ATTR_SCHED_SCAN_INTERVAL, mPnoScanParams.scanIntervalMs * MS_PER_SECOND);
371         }
372         return HAL_SUCCESS;
373     }
374 
ProcessReqflagsToMsg(WifiRequest & request)375     int ProcessReqflagsToMsg(WifiRequest& request)
376     {
377         uint32_t scanFlag = 0;
378         if (mWiphyInfo.wiphyFeatures.supportsExtSchedScanRelativeRssi) {
379             struct nl80211_bss_select_rssi_adjust rssiAdjust;
380             (void)memset_s(&rssiAdjust, sizeof(rssiAdjust), 0, sizeof(rssiAdjust));
381             rssiAdjust.band = NL80211_BAND_2GHZ;
382             rssiAdjust.delta = mPnoScanParams.min2gRssi - mPnoScanParams.min5gRssi;
383             nl_msg *msg = request.GetMessage();
384             nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST, sizeof(rssiAdjust), &rssiAdjust);
385         }
386         if (mWiphyInfo.wiphyFeatures.supportsRandomMacSchedScan) {
387             scanFlag |= NL80211_SCAN_FLAG_RANDOM_ADDR;
388         }
389         if (mWiphyInfo.wiphyFeatures.supportsLowPowerOneshotScan) {
390             scanFlag |= NL80211_SCAN_FLAG_LOW_POWER;
391         }
392         if (scanFlag != 0) {
393             request.PutU32(NL80211_ATTR_SCAN_FLAGS, scanFlag);
394         }
395         int i = 0;
396         nlattr *freqs = request.AttrStart(NL80211_ATTR_SCAN_FREQUENCIES);
397         for (auto iter = mPnoScanParams.freqs.begin(); iter != mPnoScanParams.freqs.end(); ++iter) {
398             request.PutU32(i + 1, (*iter));
399             i++;
400         }
401         request.AttrEnd(freqs);
402         return HAL_SUCCESS;
403     }
404 
Start()405     int Start()
406     {
407         HDF_LOGD("start pno scan");
408         WifiRequest request(FamilyId(), IfaceId());
409         int result = CreateSetupRequest(request);
410         if (result != HAL_SUCCESS) {
411             HDF_LOGE("failed to create setup request; result = %{public}d", result);
412             return result;
413         }
414         auto lock = ReadLockData();
415         result = RequestResponse(request);
416         if (result < 0) {
417             HDF_LOGE("failed to configure setup; result = %{public}d", result);
418             return result;
419         }
420         return HAL_SUCCESS;
421     }
422 };
423 
424 class StopPnoScanCommand : public WifiCommand {
425 public:
StopPnoScanCommand(wifiInterfaceHandle handle)426     explicit StopPnoScanCommand(wifiInterfaceHandle handle)
427         : WifiCommand("StopPnoScanCommand", handle, 0) {
428     }
Create()429     int Create() override
430     {
431         int ret;
432 
433         ret = mMsg.Create(FamilyId(), NL80211_CMD_STOP_SCHED_SCAN, 0, 0);
434         if (ret < 0) {
435             HDF_LOGE("Can't create message to send to driver - %{public}d", ret);
436             return ret;
437         }
438         ret = mMsg.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
439         if (ret < 0) {
440             HDF_LOGE("put ifaceid fail %{public}d", IfaceId());
441             return ret;
442         }
443         return HAL_SUCCESS;
444     }
445 };
446 
447 
WifiStartPnoScan(wifiInterfaceHandle handle,const OHOS::HDI::Wlan::Chip::V2_0::PnoScanParams & pnoScanParam)448 WifiError WifiStartPnoScan(wifiInterfaceHandle handle,
449     const OHOS::HDI::Wlan::Chip::V2_0::PnoScanParams& pnoScanParam)
450 {
451     uint32_t wiphyIndex;
452     WiphyInfo wiphyInfo;
453     if (!handle) {
454         HDF_LOGE("Handle is null");
455         return HAL_INVALID_ARGS;
456     }
457     if (WifiGetWiphyIndex(handle, &wiphyIndex) < 0) {
458         HDF_LOGE("can not get wiphyIndex");
459         return HAL_NONE;
460     }
461     if (WifiGetWiphyInfo(handle, wiphyIndex, wiphyInfo) < 0) {
462         HDF_LOGE("can not get wiphyInfo");
463         return HAL_NONE;
464     }
465     PnoScanCommand pnoScanCommand(handle, pnoScanParam, wiphyInfo);
466     return (WifiError)pnoScanCommand.Start();
467 }
468 
WifiStopPnoScan(wifiInterfaceHandle handle)469 WifiError WifiStopPnoScan(wifiInterfaceHandle handle)
470 {
471     if (!handle) {
472         HDF_LOGE("Handle is null");
473         return HAL_INVALID_ARGS;
474     }
475     StopPnoScanCommand stopPnoScanCommand(handle);
476     auto lock = ReadLockData();
477     return (WifiError)stopPnoScanCommand.RequestResponse();
478 }
479 
480 class GetScanResultsCommand : public WifiCommand {
481 public:
GetScanResultsCommand(wifiInterfaceHandle handle)482     explicit GetScanResultsCommand(wifiInterfaceHandle handle)
483         : WifiCommand("GetScanResultsCommand", handle, 0) {
484     }
Create()485     int Create() override
486     {
487         int ret;
488 
489         ret = mMsg.Create(FamilyId(), NL80211_CMD_GET_SCAN, NLM_F_DUMP, 0);
490         if (ret < 0) {
491             HDF_LOGE("Can't create message to send to driver - %{public}d", ret);
492             return ret;
493         }
494         ret = mMsg.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
495         if (ret < 0) {
496             HDF_LOGE("put ifaceid fail %{public}d", IfaceId());
497             return ret;
498         }
499 
500         return HAL_SUCCESS;
501     }
GetScanResultsInfo()502     std::vector<OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo> &GetScanResultsInfo()
503     {
504         return mscanResults;
505     }
506 protected:
HandleResponse(WifiEvent & reply)507     int HandleResponse(WifiEvent& reply) override
508     {
509         OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo scanResult;
510         struct nlattr **attr = reply.Attributes();
511         struct nlattr *bssAttr[NL80211_BSS_MAX + 1];
512         static struct nla_policy bssPolicy[NL80211_BSS_MAX + 1];
513         memset_s(bssPolicy, sizeof(bssPolicy), 0, sizeof(bssPolicy));
514         bssPolicy[NL80211_BSS_FREQUENCY].type = NLA_U32;
515         bssPolicy[NL80211_BSS_TSF].type = NLA_U64;
516         bssPolicy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
517         bssPolicy[NL80211_BSS_CAPABILITY].type = NLA_U16;
518         bssPolicy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
519         bssPolicy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
520         bssPolicy[NL80211_BSS_STATUS].type = NLA_U32;
521         bssPolicy[NL80211_BSS_SEEN_MS_AGO].type = NLA_U32;
522 
523         if (!attr[NL80211_ATTR_BSS]) {
524             return NL_SKIP;
525         }
526         if (nla_parse_nested(bssAttr, NL80211_BSS_MAX, attr[NL80211_ATTR_BSS], bssPolicy)) {
527             HDF_LOGE("failed to parse nested attributes");
528             return NL_SKIP;
529         }
530         if (HandleBssAttr(bssAttr, scanResult) != HAL_SUCCESS) {
531             return NL_SKIP;
532         }
533         mscanResults.push_back(scanResult);
534         return NL_SKIP;
535     }
536 
HandleBssAttr(struct nlattr ** bssAttr,OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo & scanResult)537     int HandleBssAttr(struct nlattr **bssAttr, OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo &scanResult)
538     {
539         if (bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]) {
540             uint8_t *ie =  reinterpret_cast<uint8_t*>(nla_data(bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]));
541             int ieLen =  static_cast<int32_t>(nla_len(bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]));
542             std::vector<uint8_t> ieVec(ie, ie + ieLen);
543             scanResult.ie = ieVec;
544         }
545         if (bssAttr[NL80211_BSS_BEACON_IES]) {
546             uint8_t *beaconIe = reinterpret_cast<uint8_t*>(nla_data(bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]));
547             int beaconIeLen = static_cast<int32_t>(nla_len(bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]));
548             std::vector<uint8_t> beaconIeVec(beaconIe, beaconIe + beaconIeLen);
549             scanResult.beaconIe = beaconIeVec;
550         }
551         if (bssAttr[NL80211_BSS_BSSID]) {
552             uint8_t *bssid = reinterpret_cast<uint8_t*>(nla_data(bssAttr[NL80211_BSS_BSSID]));
553             std::vector<uint8_t> bssidVec(bssid, bssid + ETH_ADDR_LEN);
554             scanResult.bssid = bssidVec;
555         }
556         if (bssAttr[NL80211_BSS_FREQUENCY]) {
557             scanResult.freq = nla_get_u32(bssAttr[NL80211_BSS_FREQUENCY]);
558         }
559         if (bssAttr[NL80211_BSS_BEACON_INTERVAL]) {
560             scanResult.beaconInterval = nla_get_u16(bssAttr[NL80211_BSS_BEACON_INTERVAL]);
561         }
562         if (bssAttr[NL80211_BSS_CAPABILITY]) {
563             scanResult.caps = nla_get_u16(bssAttr[NL80211_BSS_CAPABILITY]);
564         }
565         if (bssAttr[NL80211_BSS_SIGNAL_MBM]) {
566             scanResult.level = (int32_t)nla_get_u32(bssAttr[NL80211_BSS_SIGNAL_MBM]) / SIGNAL_LEVEL_CONFFICIENT;
567             scanResult.flags |= SCAN_LEVEL_DBM | SCAN_QUAL_INVALID;
568         } else if (bssAttr[NL80211_BSS_SIGNAL_UNSPEC]) {
569             scanResult.level = (int32_t)nla_get_u8(bssAttr[NL80211_BSS_SIGNAL_UNSPEC]);
570             scanResult.flags |= SCAN_QUAL_INVALID;
571         } else {
572             scanResult.flags |= SCAN_LEVEL_INVALID | SCAN_QUAL_INVALID;
573         }
574         if (bssAttr[NL80211_BSS_TSF]) {
575             scanResult.tsf = nla_get_u64(bssAttr[NL80211_BSS_TSF]);
576         }
577         if (bssAttr[NL80211_BSS_BEACON_TSF]) {
578             uint64_t tsf = nla_get_u64(bssAttr[NL80211_BSS_BEACON_TSF]);
579             if (tsf > scanResult.tsf) {
580                 scanResult.tsf = tsf;
581             }
582         }
583         if (bssAttr[NL80211_BSS_SEEN_MS_AGO]) {
584             scanResult.age = nla_get_u32(bssAttr[NL80211_BSS_SEEN_MS_AGO]);
585         }
586         return HAL_SUCCESS;
587     }
588 
589 private:
590     std::vector<OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo> mscanResults;
591 };
592 
WifiGetScanInfo(wifiInterfaceHandle handle,std::vector<OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo> & mscanResults)593 WifiError WifiGetScanInfo(wifiInterfaceHandle handle,
594     std::vector<OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo>& mscanResults)
595 {
596     if (!handle) {
597         HDF_LOGE("Handle is null");
598         return HAL_INVALID_ARGS;
599     }
600     GetScanResultsCommand command(handle);
601     auto lock = ReadLockData();
602     WifiError status = (WifiError)command.RequestResponse();
603     if (status == HAL_SUCCESS) {
604         HDF_LOGE("command.RequestResponse() return %{public}d", status);
605     }
606     mscanResults = command.GetScanResultsInfo();
607     return status;
608 }
609 
610