接着上篇没有记录完的,我们继续梳理,需要上一篇做基础的请看:鸿蒙 WiFi 扫描流程(1)
上一篇我们讲到 scan_service.cpp 里面的 SingleScan 方法,继续这个方法往下看:
cpp
// foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_service.cpp
bool ScanService::SingleScan(ScanConfig &scanConfig)
{
WIFI_LOGI("Enter ScanService::SingleScan.\n");
#ifndef OHOS_ARCH_LITE
if (!standByListerner.AllowScan()) {
WIFI_LOGE("Scan not allowed when device in standby state.\n");
return WIFI_OPT_FAILED;
}
#endif
GetAllowBandFreqsControlInfo(scanConfig.scanBand, scanConfig.scanFreqs); ---> 哪个Band
if ((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_client
if ((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
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_SUPPORT
int ret = HdiStartScan(settings);
#else
WifiWpaStaInterface *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;
}
#endif
if (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 收到命令后去做扫描动作,那扫描到结果如何通知上层呢?下一篇我们继续记录。