鸿蒙 WiFi 扫描流程(2)

接着上篇没有记录完的,我们继续梳理,需要上一篇做基础的请看:鸿蒙 WiFi 扫描流程(1)
上一篇我们讲到 scan_service.cpp 里面的 SingleScan 方法,继续这个方法往下看:

// foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_service.cppbool ScanService::SingleScan(ScanConfig &scanConfig)
{WIFI_LOGI("Enter ScanService::SingleScan.\n");#ifndef OHOS_ARCH_LITEif (!standByListerner.AllowScan()) {WIFI_LOGE("Scan not allowed when device in standby state.\n");return WIFI_OPT_FAILED;}
#endifGetAllowBandFreqsControlInfo(scanConfig.scanBand, scanConfig.scanFreqs);                   ---> 哪个Bandif ((scanConfig.scanBand == SCAN_BAND_UNSPECIFIED) && (scanConfig.scanFreqs.empty())) {WIFI_LOGE("Have no allowed band or freq.\n");return false;}InterScanConfig interConfig;interConfig.fullScanFlag = scanConfig.fullScanFlag;interConfig.hiddenNetworkSsid.assign(scanConfig.hiddenNetworkSsid.begin(), scanConfig.hiddenNetworkSsid.end());interConfig.scanStyle = scanConfig.scanStyle;/* Specified frequency */if (scanConfig.scanBand == SCAN_BAND_UNSPECIFIED) {interConfig.scanFreqs.assign(scanConfig.scanFreqs.begin(), scanConfig.scanFreqs.end());/** When band is SCAN_BAND_BOTH_WITH_DFS, need to scan all frequency,* scanFreqs can be empty.*/} else if (scanConfig.scanBand != SCAN_BAND_BOTH_WITH_DFS) {/* Converting frequency bands to frequencies. */if (!GetBandFreqs(scanConfig.scanBand, interConfig.scanFreqs)) {WIFI_LOGE("GetBandFreqs failed.\n");return false;}}/* Save the configuration. */int requestIndex = StoreRequestScanConfig(scanConfig, interConfig);if (requestIndex == MAX_SCAN_CONFIG_STORE_INDEX) {WIFI_LOGE("StoreRequestScanConfig failed.\n");return false;}std::unique_lock<std::mutex> lock(scanConfigMapMutex);if (pScanStateMachine == nullptr) {WIFI_LOGE("pScanStateMachine is null.\n");return false;}/* Construct a message. */   // 去状态机里面处理这个消息InternalMessage *interMessage =pScanStateMachine->CreateMessage(static_cast<int>(CMD_START_COMMON_SCAN), requestIndex);if (interMessage == nullptr) {scanConfigMap.erase(requestIndex);WIFI_LOGE("CreateMessage failed.\n");return false;}if (!AddScanMessageBody(interMessage, interConfig)) {scanConfigMap.erase(requestIndex);MessageManage::GetInstance().ReclaimMsg(interMessage);WIFI_LOGE("AddScanMessageBody failed.\n");return false;}pScanStateMachine->SendMessage(interMessage);return true;
}//foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_state_machine.cpp
bool ScanStateMachine::HardwareReady::ExecuteStateMsg(InternalMessage *msg)
{WIFI_LOGI("ScanStateMachine::HardwareReady::ExecuteStateMsg.\n");if (msg == nullptr) {WIFI_LOGE("msg is null.\n");return true;}switch (msg->GetMessageName()) {case CMD_START_COMMON_SCAN:      ---》 处理这个消息pScanStateMachine->CommonScanRequestProcess(msg);return true;case CMD_START_PNO_SCAN:pScanStateMachine->PnoScanRequestProcess(msg);return true;default:return false;}
}
// 发起 CommonScanRequestProcess 流程
void ScanStateMachine::CommonScanRequestProcess(InternalMessage *interMessage)
{WIFI_LOGI("ScanStateMachine::CommonScanRequestProcess.\n");int requestIndex = 0;InterScanConfig scanConfig;if (!GetCommonScanRequestInfo(interMessage, requestIndex, scanConfig)) {ReportCommonScanFailed(requestIndex);return;}if (!VerifyScanStyle(scanConfig.scanStyle)) {WIFI_LOGE("invalid scan type");return;}{std::unique_lock<std::shared_mutex> guard(lock);waitingScans.insert(std::pair<int, InterScanConfig>(requestIndex, scanConfig));}StartNewCommonScan();
}void ScanStateMachine::StartNewCommonScan()
{WIFI_LOGI("Enter ScanStateMachine::StartNewCommonScan.\n");{std::shared_lock<std::shared_mutex> guard(lock);if (waitingScans.size() == 0) {ContinuePnoScanProcess();return;}ClearRunningScanSettings();bool hasFullScan = false;/* Traverse the request list and combine parameters */std::map<int, InterScanConfig>::iterator configIter = waitingScans.begin();for (; configIter != waitingScans.end(); ++configIter) {runningScanSettings.scanStyle = MergeScanStyle(runningScanSettings.scanStyle, configIter->second.scanStyle);std::vector<std::string>::iterator hiddenIter = configIter->second.hiddenNetworkSsid.begin();/* Remove duplicate hidden list */for (; hiddenIter != configIter->second.hiddenNetworkSsid.end(); ++hiddenIter) {if (std::find(runningScanSettings.hiddenNetworkSsid.begin(),runningScanSettings.hiddenNetworkSsid.end(),*hiddenIter) != runningScanSettings.hiddenNetworkSsid.end()) {continue;}runningScanSettings.hiddenNetworkSsid.push_back(*hiddenIter);}if (!hasFullScan) {/* When scanFreqs is empty, it means that scan all frequenties */if (configIter->second.scanFreqs.empty()) {runningScanSettings.scanFreqs.clear();runningFullScanFlag = true;hasFullScan = true;} else {std::vector<int>::iterator freqIter = configIter->second.scanFreqs.begin();/* Repetitions are eliminated */for (; freqIter != configIter->second.scanFreqs.end(); ++freqIter) {if (std::find(runningScanSettings.scanFreqs.begin(),runningScanSettings.scanFreqs.end(),*freqIter) != runningScanSettings.scanFreqs.end()) {continue;}runningScanSettings.scanFreqs.push_back(*freqIter);}}}}}if (!StartSingleCommonScan(runningScanSettings)) {       ---》 继续看这个ReportCommonScanFailedAndClear(false);ContinuePnoScanProcess();return;}std::unique_lock<std::shared_mutex> guard(lock);runningScans.swap(waitingScans);waitingScans.clear();SwitchState(commonScanningState);WIFI_LOGI("StartNewCommonScan success.\n");
}bool ScanStateMachine::StartSingleCommonScan(WifiScanParam &scanParam)
{WIFI_LOGI("Enter ScanStateMachine::StartSingleCommonScan.\n");for (auto freqIter = scanParam.scanFreqs.begin(); freqIter != scanParam.scanFreqs.end(); ++freqIter) {WIFI_LOGI("freq is %{public}d.\n", *freqIter);}for (auto hiddenIter = scanParam.hiddenNetworkSsid.begin(); hiddenIter != scanParam.hiddenNetworkSsid.end();++hiddenIter) {WIFI_LOGI("hidden ssid is %{public}s.\n", SsidAnonymize(*hiddenIter).c_str());}WIFI_LOGI("Begin call Scan.\n");WifiErrorNo ret = WifiStaHalInterface::GetInstance().Scan(scanParam);      ---> 是不是很熟悉,要通过idl_clientif ((ret != WIFI_IDL_OPT_OK) && (ret != WIFI_IDL_OPT_SCAN_BUSY)) {WIFI_LOGE("WifiStaHalInterface::GetInstance().scan failed.");return false;}WIFI_LOGI("End call Scan.\n");/** Start the timer. If no result is returned for a long time, the scanning* fails*/StartTimer(static_cast<int>(WAIT_SCAN_RESULT_TIMER), MAX_WAIT_SCAN_RESULT_TIME);return true;
}

继续看下代码,WifiStaHalInterface里面的 Scan 方法:
foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/idl_client/wifi_sta_hal_interface.cpp

WifiErrorNo WifiStaHalInterface::Scan(const WifiScanParam &scanParam)
{CHECK_NULL_AND_RETURN(mIdlClient, WIFI_IDL_OPT_FAILED);return mIdlClient->Scan(scanParam);
}// foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/idl_client/wifi_idl_client.cpp
WifiErrorNo WifiIdlClient::Scan(const WifiScanParam &scanParam)
{CHECK_CLIENT_NOT_NULL;ScanSettings settings;if (memset_s(&settings, sizeof(settings), 0, sizeof(settings)) != EOK) {return WIFI_IDL_OPT_FAILED;}bool bfail = false;do {if (scanParam.hiddenNetworkSsid.size() > 0) {settings.hiddenSsidSize = scanParam.hiddenNetworkSsid.size();settings.hiddenSsid = ConVectorToCArrayString(scanParam.hiddenNetworkSsid);if (settings.hiddenSsid == nullptr) {bfail = true;break;}}if (scanParam.scanFreqs.size() > 0) {settings.freqSize = scanParam.scanFreqs.size();settings.freqs = (int *)calloc(settings.freqSize, sizeof(int));if (settings.freqs == nullptr) {bfail = true;break;}for (int i = 0; i < settings.freqSize; ++i) {settings.freqs[i] = scanParam.scanFreqs[i];}}if (scanParam.scanStyle > 0) {settings.scanStyle = scanParam.scanStyle;}} while (0);WifiErrorNo err = WIFI_IDL_OPT_FAILED;if (!bfail) {err = StartScan(&settings);      ---> 向 Hal 发起扫描}if (settings.freqs != nullptr) {free(settings.freqs);settings.freqs = nullptr;}if (settings.hiddenSsid != nullptr) {for (int i = 0; i < settings.hiddenSsidSize; ++i) {free(settings.hiddenSsid[i]);settings.hiddenSsid[i] = nullptr;}free(settings.hiddenSsid);settings.hiddenSsid = nullptr;}return err;
}
// 中间省略了 RPC的调用,代码可以看wifi_hal_crpc_server类,处理客户端请求,然后根据请求找到对应的函数,在调用HAL的方法
// 直接看调用的HAL方法:foundation/communication/wifi/wifi/services/wifi_standard/wifi_hal/wifi_hal_sta_interface.c
WifiErrorNo StartScan(const ScanSettings *settings)
{LOGD("Ready to start scan with param.");
#ifdef HDI_INTERFACE_SUPPORTint ret = HdiStartScan(settings);
#elseWifiWpaStaInterface *pStaIfc = GetWifiStaInterface(0);if (pStaIfc == NULL) {return WIFI_HAL_SUPPLICANT_NOT_INIT;}int ret = pStaIfc->wpaCliCmdScan(pStaIfc, settings);    ---> 往supplicant 发送命令if (ret < 0) {LOGE("StartScan failed! ret=%{public}d", ret);return WIFI_HAL_FAILED;}
#endifif (ret == WIFI_HAL_SCAN_BUSY) {LOGD("StartScan return scan busy");return WIFI_HAL_SCAN_BUSY;}LOGD("StartScan successfully!");return WIFI_HAL_SUCCESS;
}// int (*wpaCliCmdScan)(WifiWpaStaInterface *p, const ScanSettings *settings);
// wifi/services/wifi_standard/wifi_hal/wifi_hal_module/wpa_supplicant_hal/wpa_sta_hal/wifi_supplicant_hal.c
static int WpaCliCmdScan(WifiWpaStaInterface *this, const ScanSettings *settings)
{if (this == NULL) {LOGE("WpaCliCmdScan, this is NULL!");return -1;}/* Invalidate expired scan results */WpaCliCmdBssFlush(this);unsigned len = CMD_BUFFER_SIZE;unsigned expectedLen = 0;if (settings != NULL) {expectedLen = AssignCmdLen(this, settings);}if (expectedLen >= len) {len = expectedLen + 1;}char *pcmd = (char *)calloc(len, sizeof(char));if (pcmd == NULL) {LOGE("WpaCliCmdScan, pcmd is NULL!");return -1;}int pos = 0;int res = 0;if (settings != NULL) {if (settings->scanStyle == SCAN_TYPE_PNO && settings->isStartPnoScan) {res = snprintf_s(pcmd, len, len - 1, "IFNAME=%s set pno 1", this->ifname);} else if (settings->scanStyle == SCAN_TYPE_PNO && !settings->isStartPnoScan) {res = snprintf_s(pcmd, len, len - 1, "IFNAME=%s set pno 0", this->ifname);} else {res = snprintf_s(pcmd, len, len - 1, "IFNAME=%s SCAN", this->ifname);}}if (res < 0) {LOGE("WpaCliCmdScan, snprintf_s error!");free(pcmd);return -1;}pos += res;if (settings != NULL && ConcatScanSetting(settings, pcmd + pos, len - pos) < 0) {LOGE("snprintf scan settings error");free(pcmd);return -1;}char buf[REPLY_BUF_SMALL_LENGTH] = {0};if (WpaCliCmd(pcmd, buf, sizeof(buf)) != 0) {      ---》 命令下发free(pcmd);return -1;}free(pcmd);if (strncmp(buf, "FAIL-BUSY", strlen("FAIL-BUSY")) == 0) {LOGE("WpaCliCmdScan, WpaCliCmd return FAIL-BUSY!");return FAIL_BUSY;}return 0;
}// foundation/communication/wifi/wifi/services/wifi_standard/wifi_hal/wifi_hal_module/wpa_supplicant_hal/wifi_wpa_common.c
int WpaCliCmd(const char *cmd, char *buf, size_t bufLen)
{if (cmd == NULL || buf == NULL || bufLen <= 0) {LOGE("WpaCliCmd, invalid parameters!");return -1;}WpaCtrl *ctrl = GetWpaCtrl();if (ctrl == NULL || ctrl->pSend == NULL) {LOGE("WpaCliCmd, ctrl/ctrl->pSend is NULL!");return -1;}size_t len = bufLen - 1;LOGI("wpa_ctrl_request -> cmd: %{private}s", cmd);int ret = wpa_ctrl_request(ctrl->pSend, cmd, strlen(cmd), buf, &len, NULL);if (ret == WPA_CMD_RETURN_TIMEOUT) {LOGE("[%{private}s] command timed out.", cmd);return WPA_CMD_RETURN_TIMEOUT;} else if (ret < 0) {LOGE("[%{private}s] command failed.", cmd);return -1;}buf[len] = '\0';LOGI("wpa_ctrl_request -> buf: %{private}s", buf);if (strncmp(buf, "FAIL\n", strlen("FAIL\n")) == 0 ||strncmp(buf, "UNKNOWN COMMAND\n", strlen("UNKNOWN COMMAND\n")) == 0) {LOGE("%{private}s request success, but response %{public}s", cmd, buf);return -1;}return 0;
}

到此我们就看到命令发送到wpa,然后wpa 收到命令后去做扫描动作,那扫描到结果如何通知上层呢?下一篇我们继续记录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/670441.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python基础知识:Python函数的定义、创建与调用

Python本质上是一种编程语言&#xff0c;通过编写运行代码的方式实现工作目标。读者可以想象&#xff0c;如果针对机器学习或数据统计分析的每种方法或统计量计算都要用户自行编写代码&#xff0c;那么显然在很多情况下是无法满足用户便捷开展分析的要求的&#xff0c;用户体验…

docer compose部署simple-docker

简介 一个看似简陋但是功能足够用的docker管理工具 安装 创建目录 mkdir -p /opt/simple-docker cd /opt/simple-docker 创建并启动容器 编写docker-compose.yml文件,内容如下 version: 3 services: redis: image: redis:latest restart: always web: image: registry.cn-…

HR看了都想点开的简历:吸睛模板+撰写技巧

工作致富的第一步&#xff1a;写一份好的简历。一个独特、简单、清晰的个人简历模板可以更好地吸引雇主的注意和兴趣&#xff0c;并帮助你在许多求职者中脱颖而出。如何制作一份令人印象深刻的简历&#xff1f;巧妙地使用个人简历模板是一个不错的选择。在本文中&#xff0c;我…

线性代数:矩阵的初等变换

目录 一、初等行变换 行阶梯 / 行最简 性质 二、矩阵的标准型 三、矩阵的等价 四、初等矩阵 五、重要性质与定理 一、初等行变换 行阶梯 / 行最简 性质 二、矩阵的标准型 三、矩阵的等价 四、初等矩阵 五、重要性质与定理

Java快速输入输出的实现

在Java编程中&#xff0c;我们经常需要从标准输入读取数据&#xff0c;或者将结果输出到标准输出。为了提高输入输出的效率&#xff0c;我们可以使用快速输入输出的方法。下面是一个示例类Read&#xff0c;它提供了一系列方法来实现快速的输入输出操作。 import java.io.*;cla…

Git - 每次 git pull/push 时需要账号和密码解决方案

问题描述 在提交项目代码或者拉取代码的时候&#xff0c;每次 git 都要输入用户名密码&#xff0c;很烦~ 解决方案 让服务器记下来用户名和密码&#xff0c;此时输入一次&#xff0c;以后再 git push /pull 的时候就不用再输账号和密码了 # 配置 git 记录用户名和密码 git c…

租游戏服务器多少钱1个月?一年价格多少?

游戏服务器租用多少钱一年&#xff1f;1个月游戏服务器费用多少&#xff1f;阿里云游戏服务器26元1个月、腾讯云游戏服务器32元&#xff0c;游戏服务器配置从4核16G、4核32G、8核32G、16核64G等配置可选&#xff0c;可以选择轻量应用服务器和云服务器&#xff0c;阿腾云atengyu…

SpringBoot注解--04--01--注解@Mapper在IDEA中自动注入警告的解决方案

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 问题原因 解决方案方法1&#xff1a;为 Autowired 注解设置required false方法2&#xff1a;用 Resource 替换 Autowired方法3&#xff1a;在Mapper接口上加上Repo…

跟着pink老师前端入门教程-day19

一、移动WEB开发之流式布局 1、 移动端基础 1.1 浏览器现状 PC端常见浏览器&#xff1a;360浏览器、谷歌浏览器、火狐浏览器、QQ浏览器、百度浏览器、搜狗浏览器、IE浏览器。 移动端常见浏览器&#xff1a;UC浏览器&#xff0c;QQ浏览器&#xff0c;欧朋浏览器&#xff0…

论文阅读-Transformer-based language models for software vulnerability detection

「分享了一批文献给你&#xff0c;请您通过浏览器打开 https://www.ivysci.com/web/share/biblios/D2xqz52xQJ4RKceFXAFaDU/ 您还可以一键导入到 ivySCI 文献管理软件阅读&#xff0c;并在论文中引用 」 本文主旨&#xff1a;本文提出了一个系统的框架来利用基于Transformer的语…

Kubernetes实战(二十五)-快速下载k8s.gcr.io,gcr.io,quay.io镜像

1 背景 在云计算和云原生的环境下&#xff0c;不可避免的会使用很多镜像创建容器&#xff0c;其中有些镜像只有谷歌镜像仓库才有&#xff0c;但是国内不可以直接下载谷歌仓库的镜像&#xff0c;下面推荐几种方法&#xff0c; k8s.gcr.io/gcr.io 是谷歌的镜像仓库&#xff0c;…

LaTeX基本公式语法

Markdown支持通过LaTeX插入复杂的数学公式。 行内公式与块级公式 行内公式&#xff1a;使用一对美元符号$...$标记&#xff1a; 欧拉公式可以表示为 e i π 1 0 e^{i\pi} 1 0 eiπ10&#xff0c;这是一个著名的等式。 块级公式&#xff1a;使用一对双美元符号$$...$$标记…

宠物空气净化器适合养猫家庭吗?除猫毛好的猫用空气净化器推荐

宠物掉毛是一个普遍存在的问题&#xff0c;尤其在脱毛季节&#xff0c;毛发似乎无处不在。这给家中的小孩和老人带来了很多麻烦&#xff0c;他们容易流鼻涕、过敏等不适。此外&#xff0c;宠物有时还会不规矩地拉扯和撒尿&#xff0c;这股气味实在是难以忍受。家人们对宠物的存…

Java——Arrays常用方法

Arrays常用方法 Java 中的 Arrays 类提供了一系列静态方法&#xff0c;可以用来操作数组。 1. sort() 方法——默认升序排序 Arrays.sort() 方法用于对数组进行排序。该方法有多个重载版本&#xff0c;可以对不同类型的数组进行排序。 public static void sort(int[] arr) …

算法学习——LeetCode力扣哈希表篇2

算法学习——LeetCode力扣哈希表篇2 454. 四数相加 II 454. 四数相加 II - 力扣&#xff08;LeetCode&#xff09; 描述 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 …

Springboot启动出现Waiting for changelog lock...问题

今天在开发的时候&#xff0c;Springboot启动的时候出现Waiting for changelog lock…问题. 问题原因&#xff1a;该问题就是发生了数据库的死锁问题&#xff0c;可能是由于一个杀死的liquibase进程没有释放它对DATABASECHANGELOGLOCK表的锁定&#xff0c;导致服务启动失败&…

我的世界Java版服务器如何搭建并实现与好友远程联机Minecarft教程

文章目录 1. 安装JAVA2. MCSManager安装3.局域网访问MCSM4.创建我的世界服务器5.局域网联机测试6.安装cpolar内网穿透7. 配置公网访问地址8.远程联机测试9. 配置固定远程联机端口地址9.1 保留一个固定tcp地址9.2 配置固定公网TCP地址9.3 使用固定公网地址远程联机 本教程主要介…

项目中日志采集实践:技术、工具与最佳实践

目录 引言 一. 选择合适的日志框架 二. 配置日志框架 三. 使用适当的日志级别 1、日志级别概述 2、选择适当的日志级别 &#xff08;这里以logbkck为例&#xff09; 3、动态调整日志级别 四、 结合日志上下文信息 1. 使用 SLF4J MDC 2. 使用 Log4j 2 的 ThreadContext…

「深度学习」循环神经网络RNN

一、序列模型的例子 二、数学符号定义 X^{(i)<t>}&#xff1a;训练样本 i 的输入序列的第 t 个元素。 T_{X}^{i}&#xff1a;训练样本 i 的输入序列的长度。 Y^{(i)<t>}&#xff1a;训练样本 i 的输出序列的第 t 个元素。 T_{Y}^{i}&#xff1a;训练样本 i 的输…

Error: Unable to authenticate using the provided code. Please try again.

今天弄这个firebase cli的时候一直登陆不进去 都到了最后一步了&#xff0c;但是输入完code还是不成功 原来是因为开了梯子&#xff0c;代理不成功&#xff0c;要在 复制命令到对应的窗口粘贴就行&#xff0c;然后重复之前的命令就行 我复制出来的命令是 set http_proxyhttp…