* Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <fcntl.h>
#include <sys/socket.h>
#include <linux/rtnetlink.h>
#include <netpacket/packet.h>
#include <linux/filter.h>
#include <linux/pkt_sched.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <netlink/object-api.h>
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/attr.h>
#include <netlink/handlers.h>
#include <netlink/msg.h>
#include <dirent.h>
#include <net/if.h>
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include "wifi_hal.h"
#include "wifi_scan.h"
#include "common.h"
#include "cpp_bindings.h"
static bool SetExtFeatureFlag(const uint8_t *extFeatureFlagsBytes, uint32_t extFeatureFlagsLen, uint32_t extFeatureFlag)
{
uint32_t extFeatureFlagBytePos;
uint32_t extFeatureFlagBitPos;
if (extFeatureFlagsBytes == nullptr || extFeatureFlagsLen == 0) {
HDF_LOGE("param is NULL.");
return false;
}
extFeatureFlagBytePos = extFeatureFlag / BITNUMS_OF_ONE_BYTE;
extFeatureFlagBitPos = extFeatureFlag % BITNUMS_OF_ONE_BYTE;
if (extFeatureFlagBytePos >= extFeatureFlagsLen) {
return false;
}
return extFeatureFlagsBytes[extFeatureFlagBytePos] & (1U << extFeatureFlagBitPos);
}
class GetWiphyIndexCommand : public WifiCommand {
public:
GetWiphyIndexCommand(wifiInterfaceHandle handle, uint32_t *wiphyIndex)
: WifiCommand("GetWiphyIndexCommand", handle, 0)
{
mWiphyIndex = wiphyIndex;
}
int Create() override
{
int ret;
ret = mMsg.Create(FamilyId(), NL80211_CMD_GET_WIPHY, NLM_F_DUMP, 0);
if (ret < 0) {
HDF_LOGE("Can't create message to send to driver - %{public}d", ret);
return ret;
}
ret = mMsg.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
if (ret < 0) {
HDF_LOGE("put ifaceid fail %{public}d", IfaceId());
return ret;
}
return HAL_SUCCESS;
}
protected:
int HandleResponse(WifiEvent& reply) override
{
struct nlattr **attr = reply.Attributes();
if (!attr[NL80211_ATTR_WIPHY]) {
HDF_LOGE("HandleResponse: wiphy info missing!");
return NL_SKIP;
}
*mWiphyIndex = nla_get_u32(attr[NL80211_ATTR_WIPHY]);
return NL_SKIP;
}
private:
uint32_t *mWiphyIndex;
};
static int WifiGetWiphyIndex(wifiInterfaceHandle handle, uint32_t *wiphyIndex)
{
GetWiphyIndexCommand command(handle, wiphyIndex);
auto lock = ReadLockData();
return command.RequestResponse();
}
class GetWiphyInfoCommand : public WifiCommand {
public:
GetWiphyInfoCommand(wifiInterfaceHandle handle, uint32_t wiphyIndex)
: WifiCommand("GetWiphyInfoCommand", handle, 0)
{
mWiphyIndex = wiphyIndex;
if (memset_s(&mWiphyInfo, sizeof(WiphyInfo), 0, sizeof(WiphyInfo)) != EOK) {
HDF_LOGE("memset mWiphyInfo failed");
}
}
int Create() override
{
int ret;
ret = mMsg.Create(FamilyId(), NL80211_CMD_GET_WIPHY, 0, 0);
if (ret < 0) {
HDF_LOGE("Can't create message to send to driver - %{public}d", ret);
return ret;
}
ret = mMsg.PutU32(NL80211_ATTR_WIPHY, mWiphyIndex);
if (ret < 0) {
return ret;
}
return HAL_SUCCESS;
}
WiphyInfo &GetWiphyInfo()
{
return mWiphyInfo;
}
protected:
int HandleResponse(WifiEvent& reply) override
{
struct nlattr **attr = reply.Attributes();
uint32_t featureFlags = 0;
uint8_t *extFeatureFlagsBytes = nullptr;
uint32_t extFeatureFlagsLen = 0;
if (attr[NL80211_ATTR_MAX_NUM_SCAN_SSIDS] != nullptr) {
mWiphyInfo.scanCapabilities.maxNumScanSsids = nla_get_u8(attr[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
}
if (attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS] != nullptr) {
mWiphyInfo.scanCapabilities.maxNumSchedScanSsids = nla_get_u8(attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
}
if (attr[NL80211_ATTR_MAX_MATCH_SETS] != nullptr) {
mWiphyInfo.scanCapabilities.maxMatchSets = nla_get_u8(attr[NL80211_ATTR_MAX_MATCH_SETS]);
}
if (attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS] != nullptr) {
mWiphyInfo.scanCapabilities.maxNumScanPlans = nla_get_u32(attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS]);
}
if (attr[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL] != nullptr) {
mWiphyInfo.scanCapabilities.maxScanPlanInterval = nla_get_u32(attr[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL]);
}
if (attr[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS] != nullptr) {
mWiphyInfo.scanCapabilities.maxScanPlanIterations =
nla_get_u32(attr[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]);
}
if (attr[NL80211_ATTR_FEATURE_FLAGS] != nullptr) {
featureFlags = nla_get_u32(attr[NL80211_ATTR_FEATURE_FLAGS]);
}
mWiphyInfo.wiphyFeatures.supportsRandomMacSchedScan = featureFlags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
if (attr[NL80211_ATTR_EXT_FEATURES] != nullptr) {
extFeatureFlagsBytes = reinterpret_cast<uint8_t *>(nla_data(attr[NL80211_ATTR_EXT_FEATURES]));
extFeatureFlagsLen = static_cast<uint32_t>(nla_len(attr[NL80211_ATTR_EXT_FEATURES]));
mWiphyInfo.wiphyFeatures.supportsLowPowerOneshotScan =
SetExtFeatureFlag(extFeatureFlagsBytes, extFeatureFlagsLen, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
mWiphyInfo.wiphyFeatures.supportsExtSchedScanRelativeRssi =
SetExtFeatureFlag(extFeatureFlagsBytes, extFeatureFlagsLen,
NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
}
return NL_SKIP;
}
private:
uint32_t mWiphyIndex;
WiphyInfo mWiphyInfo;
};
static int WifiGetWiphyInfo(wifiInterfaceHandle handle, uint32_t wiphyIndex, WiphyInfo &wiphyInfo)
{
GetWiphyInfoCommand command(handle, wiphyIndex);
auto lock = ReadLockData();
command.RequestResponse();
wiphyInfo = command.GetWiphyInfo();
return HAL_SUCCESS;
}
class ScanCommand : public WifiCommand {
const OHOS::HDI::Wlan::Chip::V2_0::ScanParams mScanParams;
WiphyInfo mWiphyInfo;
public:
ScanCommand(wifiInterfaceHandle iface,
const OHOS::HDI::Wlan::Chip::V2_0::ScanParams& scanParams,
WiphyInfo &wiphyInfo)
: WifiCommand("ScanCommand", iface, 0), mScanParams(scanParams), mWiphyInfo(wiphyInfo)
{ }
int CreateSetupRequest(WifiRequest& request)
{
int result = request.Create(FamilyId(), NL80211_CMD_TRIGGER_SCAN, 0, 0);
int i = 0;
if (result < 0) {
return result;
}
result = request.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
if (result < 0) {
return result;
}
nlattr *ssid = request.AttrStart(NL80211_ATTR_SCAN_SSIDS);
request.Put(1, nullptr, 0);
i += 1;
for (auto iter = mScanParams.ssids.begin(); iter != mScanParams.ssids.end(); ++iter) {
if (i >= mWiphyInfo.scanCapabilities.maxNumScanSsids) {
HDF_LOGI("Skip the excess hidden ssids for scan");
break;
}
request.Put(i + 1, (void *)(*iter).c_str(), (*iter).length());
i++;
}
request.AttrEnd(ssid);
i = 0;
nlattr *freqs = request.AttrStart(NL80211_ATTR_SCAN_FREQUENCIES);
for (auto iter = mScanParams.freqs.begin(); iter != mScanParams.freqs.end(); ++iter) {
request.PutU32(i + 1, (*iter));
i++;
}
request.AttrEnd(freqs);
if (!mScanParams.extraIes.empty()) {
request.Put(NL80211_ATTR_IE, (void *)mScanParams.extraIes.c_str(), mScanParams.extraIes.length());
}
if (!mScanParams.bssid.empty()) {
request.Put(NL80211_ATTR_MAC, (void *)mScanParams.bssid.c_str(), mScanParams.bssid.length());
}
return HAL_SUCCESS;
}
int Start()
{
HDF_LOGI("start scan");
WifiRequest request(FamilyId(), IfaceId());
int result = CreateSetupRequest(request);
if (result != HAL_SUCCESS) {
HDF_LOGE("failed to create setup request; result = %{public}d", result);
return result;
}
auto lock = ReadLockData();
result = RequestResponse(request);
if (result < 0) {
HDF_LOGE("failed to configure setup; result = %{public}d", result);
return result;
}
return HAL_SUCCESS;
}
};
WifiError WifiStartScan(wifiInterfaceHandle handle,
const OHOS::HDI::Wlan::Chip::V2_0::ScanParams& scanParam)
{
uint32_t wiphyIndex;
WiphyInfo wiphyInfo;
if (!handle) {
HDF_LOGE("Handle is null");
return HAL_INVALID_ARGS;
}
if (WifiGetWiphyIndex(handle, &wiphyIndex) < 0) {
HDF_LOGE("can not get wiphyIndex");
return HAL_NONE;
}
if (WifiGetWiphyInfo(handle, wiphyIndex, wiphyInfo) < 0) {
HDF_LOGE("can not get wiphyInfo");
return HAL_NONE;
}
ScanCommand scanCommand(handle, scanParam, wiphyInfo);
return (WifiError)scanCommand.Start();
}
class PnoScanCommand : public WifiCommand {
const OHOS::HDI::Wlan::Chip::V2_0::PnoScanParams mPnoScanParams;
WiphyInfo mWiphyInfo;
public:
PnoScanCommand(wifiInterfaceHandle iface,
const OHOS::HDI::Wlan::Chip::V2_0::PnoScanParams& pnoScanParams,
WiphyInfo &wiphyInfo)
: WifiCommand("PnoScanCommand", iface, 0), mPnoScanParams(pnoScanParams), mWiphyInfo(wiphyInfo)
{ }
int CreateSetupRequest(WifiRequest& request)
{
int result = request.Create(FamilyId(), NL80211_CMD_START_SCHED_SCAN, 0, 0);
if (result < 0) {
return result;
}
result = request.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
if (result < 0) {
return result;
}
if (ProcessMatchSsidToMsg(request) != HAL_SUCCESS || ProcessSsidToMsg(request) != HAL_SUCCESS ||
ProcessScanPlanToMsg(request) != HAL_SUCCESS || ProcessReqflagsToMsg(request) != HAL_SUCCESS) {
HDF_LOGE("%{public}s: Fill parameters to netlink failed.", __FUNCTION__);
return HAL_NOT_AVAILABLE;
}
return HAL_SUCCESS;
}
int ProcessMatchSsidToMsg(WifiRequest& request)
{
nlattr *nestedMatchSsid = request.AttrStart(NL80211_ATTR_SCHED_SCAN_MATCH);
int i = 0;
for (auto iter = mPnoScanParams.savedssids.begin(); iter != mPnoScanParams.savedssids.end(); ++iter) {
if (i >= mWiphyInfo.scanCapabilities.maxNumSchedScanSsids) {
HDF_LOGI("Skip the excess saved ssids for pnoscan");
break;
}
nlattr *nest = request.AttrStart(i);
request.Put(NL80211_SCHED_SCAN_MATCH_ATTR_SSID, (void *)(*iter).c_str(), (*iter).length());
request.PutU32(NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, mPnoScanParams.min5gRssi);
i++;
request.AttrEnd(nest);
}
request.AttrEnd(nestedMatchSsid);
return HAL_SUCCESS;
}
int ProcessSsidToMsg(WifiRequest& request)
{
nlattr *hiddenSsid = request.AttrStart(NL80211_ATTR_SCAN_SSIDS);
int i = 0;
for (auto iter = mPnoScanParams.savedssids.begin(); iter != mPnoScanParams.savedssids.end(); ++iter) {
if (i >= mWiphyInfo.scanCapabilities.maxNumScanSsids) {
HDF_LOGI("Skip the excess hidden ssids for pnoscan");
break;
}
request.Put(i, (void *)(*iter).c_str(), (*iter).length());
i++;
}
request.AttrEnd(hiddenSsid);
return HAL_SUCCESS;
}
int ProcessScanPlanToMsg(WifiRequest& request)
{
bool supportNumScanPlans = (mWiphyInfo.scanCapabilities.maxNumScanPlans >= 2);
bool supportScanPlanInterval = (mWiphyInfo.scanCapabilities.maxScanPlanInterval * MS_PER_SECOND >=
(uint32_t)mPnoScanParams.scanIntervalMs * SLOW_SCAN_INTERVAL_MULTIPLIER);
bool supportScanPlanIterations = (mWiphyInfo.scanCapabilities.maxScanPlanIterations >= FAST_SCAN_ITERATIONS);
if (supportNumScanPlans && supportScanPlanInterval && supportScanPlanIterations) {
nlattr *nestedPlan = request.AttrStart(NL80211_ATTR_SCHED_SCAN_PLANS);
nlattr *plan = request.AttrStart(SCHED_SCAN_PLANS_ATTR_INDEX1);
request.PutU32(NL80211_SCHED_SCAN_PLAN_INTERVAL, mPnoScanParams.scanIntervalMs);
request.PutU32(NL80211_SCHED_SCAN_PLAN_ITERATIONS, mPnoScanParams.scanIterations);
request.AttrEnd(plan);
plan = request.AttrStart(SCHED_SCAN_PLANS_ATTR_INDEX2);
request.PutU32(NL80211_SCHED_SCAN_PLAN_INTERVAL,
mPnoScanParams.scanIntervalMs * SLOW_SCAN_INTERVAL_MULTIPLIER);
request.AttrEnd(plan);
request.AttrEnd(nestedPlan);
} else {
request.PutU32(NL80211_ATTR_SCHED_SCAN_INTERVAL, mPnoScanParams.scanIntervalMs * MS_PER_SECOND);
}
return HAL_SUCCESS;
}
int ProcessReqflagsToMsg(WifiRequest& request)
{
uint32_t scanFlag = 0;
if (mWiphyInfo.wiphyFeatures.supportsExtSchedScanRelativeRssi) {
struct nl80211_bss_select_rssi_adjust rssiAdjust;
(void)memset_s(&rssiAdjust, sizeof(rssiAdjust), 0, sizeof(rssiAdjust));
rssiAdjust.band = NL80211_BAND_2GHZ;
rssiAdjust.delta = mPnoScanParams.min2gRssi - mPnoScanParams.min5gRssi;
nl_msg *msg = request.GetMessage();
nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST, sizeof(rssiAdjust), &rssiAdjust);
}
if (mWiphyInfo.wiphyFeatures.supportsRandomMacSchedScan) {
scanFlag |= NL80211_SCAN_FLAG_RANDOM_ADDR;
}
if (mWiphyInfo.wiphyFeatures.supportsLowPowerOneshotScan) {
scanFlag |= NL80211_SCAN_FLAG_LOW_POWER;
}
if (scanFlag != 0) {
request.PutU32(NL80211_ATTR_SCAN_FLAGS, scanFlag);
}
int i = 0;
nlattr *freqs = request.AttrStart(NL80211_ATTR_SCAN_FREQUENCIES);
for (auto iter = mPnoScanParams.freqs.begin(); iter != mPnoScanParams.freqs.end(); ++iter) {
request.PutU32(i + 1, (*iter));
i++;
}
request.AttrEnd(freqs);
return HAL_SUCCESS;
}
int Start()
{
HDF_LOGD("start pno scan");
WifiRequest request(FamilyId(), IfaceId());
int result = CreateSetupRequest(request);
if (result != HAL_SUCCESS) {
HDF_LOGE("failed to create setup request; result = %{public}d", result);
return result;
}
auto lock = ReadLockData();
result = RequestResponse(request);
if (result < 0) {
HDF_LOGE("failed to configure setup; result = %{public}d", result);
return result;
}
return HAL_SUCCESS;
}
};
class StopPnoScanCommand : public WifiCommand {
public:
explicit StopPnoScanCommand(wifiInterfaceHandle handle)
: WifiCommand("StopPnoScanCommand", handle, 0) {
}
int Create() override
{
int ret;
ret = mMsg.Create(FamilyId(), NL80211_CMD_STOP_SCHED_SCAN, 0, 0);
if (ret < 0) {
HDF_LOGE("Can't create message to send to driver - %{public}d", ret);
return ret;
}
ret = mMsg.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
if (ret < 0) {
HDF_LOGE("put ifaceid fail %{public}d", IfaceId());
return ret;
}
return HAL_SUCCESS;
}
};
WifiError WifiStartPnoScan(wifiInterfaceHandle handle,
const OHOS::HDI::Wlan::Chip::V2_0::PnoScanParams& pnoScanParam)
{
uint32_t wiphyIndex;
WiphyInfo wiphyInfo;
if (!handle) {
HDF_LOGE("Handle is null");
return HAL_INVALID_ARGS;
}
if (WifiGetWiphyIndex(handle, &wiphyIndex) < 0) {
HDF_LOGE("can not get wiphyIndex");
return HAL_NONE;
}
if (WifiGetWiphyInfo(handle, wiphyIndex, wiphyInfo) < 0) {
HDF_LOGE("can not get wiphyInfo");
return HAL_NONE;
}
PnoScanCommand pnoScanCommand(handle, pnoScanParam, wiphyInfo);
return (WifiError)pnoScanCommand.Start();
}
WifiError WifiStopPnoScan(wifiInterfaceHandle handle)
{
if (!handle) {
HDF_LOGE("Handle is null");
return HAL_INVALID_ARGS;
}
StopPnoScanCommand stopPnoScanCommand(handle);
auto lock = ReadLockData();
return (WifiError)stopPnoScanCommand.RequestResponse();
}
class GetScanResultsCommand : public WifiCommand {
public:
explicit GetScanResultsCommand(wifiInterfaceHandle handle)
: WifiCommand("GetScanResultsCommand", handle, 0) {
}
int Create() override
{
int ret;
ret = mMsg.Create(FamilyId(), NL80211_CMD_GET_SCAN, NLM_F_DUMP, 0);
if (ret < 0) {
HDF_LOGE("Can't create message to send to driver - %{public}d", ret);
return ret;
}
ret = mMsg.PutU32(NL80211_ATTR_IFINDEX, IfaceId());
if (ret < 0) {
HDF_LOGE("put ifaceid fail %{public}d", IfaceId());
return ret;
}
return HAL_SUCCESS;
}
std::vector<OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo> &GetScanResultsInfo()
{
return mscanResults;
}
protected:
int HandleResponse(WifiEvent& reply) override
{
OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo scanResult;
struct nlattr **attr = reply.Attributes();
struct nlattr *bssAttr[NL80211_BSS_MAX + 1];
static struct nla_policy bssPolicy[NL80211_BSS_MAX + 1];
memset_s(bssPolicy, sizeof(bssPolicy), 0, sizeof(bssPolicy));
bssPolicy[NL80211_BSS_FREQUENCY].type = NLA_U32;
bssPolicy[NL80211_BSS_TSF].type = NLA_U64;
bssPolicy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
bssPolicy[NL80211_BSS_CAPABILITY].type = NLA_U16;
bssPolicy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
bssPolicy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
bssPolicy[NL80211_BSS_STATUS].type = NLA_U32;
bssPolicy[NL80211_BSS_SEEN_MS_AGO].type = NLA_U32;
if (!attr[NL80211_ATTR_BSS]) {
return NL_SKIP;
}
if (nla_parse_nested(bssAttr, NL80211_BSS_MAX, attr[NL80211_ATTR_BSS], bssPolicy)) {
HDF_LOGE("failed to parse nested attributes");
return NL_SKIP;
}
if (HandleBssAttr(bssAttr, scanResult) != HAL_SUCCESS) {
return NL_SKIP;
}
mscanResults.push_back(scanResult);
return NL_SKIP;
}
int HandleBssAttr(struct nlattr **bssAttr, OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo &scanResult)
{
if (bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]) {
uint8_t *ie = reinterpret_cast<uint8_t*>(nla_data(bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]));
int ieLen = static_cast<int32_t>(nla_len(bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]));
std::vector<uint8_t> ieVec(ie, ie + ieLen);
scanResult.ie = ieVec;
}
if (bssAttr[NL80211_BSS_BEACON_IES]) {
uint8_t *beaconIe = reinterpret_cast<uint8_t*>(nla_data(bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]));
int beaconIeLen = static_cast<int32_t>(nla_len(bssAttr[NL80211_BSS_INFORMATION_ELEMENTS]));
std::vector<uint8_t> beaconIeVec(beaconIe, beaconIe + beaconIeLen);
scanResult.beaconIe = beaconIeVec;
}
if (bssAttr[NL80211_BSS_BSSID]) {
uint8_t *bssid = reinterpret_cast<uint8_t*>(nla_data(bssAttr[NL80211_BSS_BSSID]));
std::vector<uint8_t> bssidVec(bssid, bssid + ETH_ADDR_LEN);
scanResult.bssid = bssidVec;
}
if (bssAttr[NL80211_BSS_FREQUENCY]) {
scanResult.freq = nla_get_u32(bssAttr[NL80211_BSS_FREQUENCY]);
}
if (bssAttr[NL80211_BSS_BEACON_INTERVAL]) {
scanResult.beaconInterval = nla_get_u16(bssAttr[NL80211_BSS_BEACON_INTERVAL]);
}
if (bssAttr[NL80211_BSS_CAPABILITY]) {
scanResult.caps = nla_get_u16(bssAttr[NL80211_BSS_CAPABILITY]);
}
if (bssAttr[NL80211_BSS_SIGNAL_MBM]) {
scanResult.level = (int32_t)nla_get_u32(bssAttr[NL80211_BSS_SIGNAL_MBM]) / SIGNAL_LEVEL_CONFFICIENT;
scanResult.flags |= SCAN_LEVEL_DBM | SCAN_QUAL_INVALID;
} else if (bssAttr[NL80211_BSS_SIGNAL_UNSPEC]) {
scanResult.level = (int32_t)nla_get_u8(bssAttr[NL80211_BSS_SIGNAL_UNSPEC]);
scanResult.flags |= SCAN_QUAL_INVALID;
} else {
scanResult.flags |= SCAN_LEVEL_INVALID | SCAN_QUAL_INVALID;
}
if (bssAttr[NL80211_BSS_TSF]) {
scanResult.tsf = nla_get_u64(bssAttr[NL80211_BSS_TSF]);
}
if (bssAttr[NL80211_BSS_BEACON_TSF]) {
uint64_t tsf = nla_get_u64(bssAttr[NL80211_BSS_BEACON_TSF]);
if (tsf > scanResult.tsf) {
scanResult.tsf = tsf;
}
}
if (bssAttr[NL80211_BSS_SEEN_MS_AGO]) {
scanResult.age = nla_get_u32(bssAttr[NL80211_BSS_SEEN_MS_AGO]);
}
return HAL_SUCCESS;
}
private:
std::vector<OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo> mscanResults;
};
WifiError WifiGetScanInfo(wifiInterfaceHandle handle,
std::vector<OHOS::HDI::Wlan::Chip::V2_0::ScanResultsInfo>& mscanResults)
{
if (!handle) {
HDF_LOGE("Handle is null");
return HAL_INVALID_ARGS;
}
GetScanResultsCommand command(handle);
auto lock = ReadLockData();
WifiError status = (WifiError)command.RequestResponse();
if (status == HAL_SUCCESS) {
HDF_LOGE("command.RequestResponse() return %{public}d", status);
}
mscanResults = command.GetScanResultsInfo();
return status;
}