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::V1_0::ScanParams mScanParams;
195 WiphyInfo mWiphyInfo;
196 public:
ScanCommand(wifiInterfaceHandle iface,const OHOS::HDI::Wlan::Chip::V1_0::ScanParams & scanParams,WiphyInfo & wiphyInfo)197 ScanCommand(wifiInterfaceHandle iface,
198 const OHOS::HDI::Wlan::Chip::V1_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::V1_0::ScanParams & scanParam)267 WifiError WifiStartScan(wifiInterfaceHandle handle,
268 const OHOS::HDI::Wlan::Chip::V1_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::V1_0::PnoScanParams mPnoScanParams;
290 WiphyInfo mWiphyInfo;
291 public:
PnoScanCommand(wifiInterfaceHandle iface,const OHOS::HDI::Wlan::Chip::V1_0::PnoScanParams & pnoScanParams,WiphyInfo & wiphyInfo)292 PnoScanCommand(wifiInterfaceHandle iface,
293 const OHOS::HDI::Wlan::Chip::V1_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::V1_0::PnoScanParams & pnoScanParam)448 WifiError WifiStartPnoScan(wifiInterfaceHandle handle,
449 const OHOS::HDI::Wlan::Chip::V1_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::V1_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::V1_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::V1_0::ScanResultsInfo & scanResult)537 int HandleBssAttr(struct nlattr **bssAttr, OHOS::HDI::Wlan::Chip::V1_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::V1_0::ScanResultsInfo> mscanResults;
591 };
592
WifiGetScanInfo(wifiInterfaceHandle handle,std::vector<OHOS::HDI::Wlan::Chip::V1_0::ScanResultsInfo> & mscanResults)593 WifiError WifiGetScanInfo(wifiInterfaceHandle handle,
594 std::vector<OHOS::HDI::Wlan::Chip::V1_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