void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
{
int res; if (wpa_s->p2p_mgmt) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Ignore scan request (%d.%06d sec) on p2p_mgmt interface",
sec, usec);
return;
} res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s,
NULL);
if (res == 1) {
wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d.%06d sec",
sec, usec);
} else if (res == 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "Ignore new scan request for %d.%06d sec since an earlier request is scheduled to trigger sooner",
sec, usec);
} else {
wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d.%06d sec",
sec, usec);
eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
}
} static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct wpa_ssid *ssid;
int ret, p2p_in_prog;
struct wpabuf *extra_ie = NULL;
struct wpa_driver_scan_params params;
struct wpa_driver_scan_params *scan_params;
size_t max_ssids;
int connect_without_scan = 0; wpa_s->ignore_post_flush_scan_res = 0;
// 接口未使能
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
return;
} if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
return;
}
// 如果正在扫描, 推迟本次扫描
if (wpa_s->scanning) {
/*
* If we are already in scanning state, we shall reschedule the
* the incoming scan request.
*/
wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Reschedule the incoming scan req");
wpa_supplicant_req_scan(wpa_s, 1, 0);
return;
}
// 查看是否有使能的ssid
if (!wpa_supplicant_enabled_networks(wpa_s) &&
wpa_s->scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
return;
} if (wpa_s->conf->ap_scan != 0 &&
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - "
"overriding ap_scan configuration");
wpa_s->conf->ap_scan = 0;
wpas_notify_ap_scan_changed(wpa_s);
} if (wpa_s->conf->ap_scan == 0) {
wpa_supplicant_gen_assoc_event(wpa_s);
return;
} ssid = NULL;
if (wpa_s->scan_req != MANUAL_SCAN_REQ &&
wpa_s->connect_without_scan) {
connect_without_scan = 1;
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
if (ssid == wpa_s->connect_without_scan)
break;
}
} p2p_in_prog = wpas_p2p_in_progress(wpa_s);
if (p2p_in_prog && p2p_in_prog != 2 &&
(!ssid ||
(ssid->mode != WPAS_MODE_AP && ssid->mode != WPAS_MODE_P2P_GO))) {
wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress");
wpa_supplicant_req_scan(wpa_s, 5, 0);
return;
} /*
* Don't cancel the scan based on ongoing PNO; defer it. Some scans are
* used for changing modes inside wpa_supplicant (roaming,
* auto-reconnect, etc). Discarding the scan might hurt these processes.
* The normal use case for PNO is to suspend the host immediately after
* starting PNO, so the periodic 100 ms attempts to run the scan do not
* normally happen in practice multiple times, i.e., this is simply
* restarting scanning once the host is woken up and PNO stopped.
*/
if (wpa_s->pno || wpa_s->pno_sched_pending) {
wpa_dbg(wpa_s, MSG_DEBUG, "Defer scan - PNO is in progress");
wpa_supplicant_req_scan(wpa_s, 0, 100000);
return;
} if (wpa_s->conf->ap_scan == 2)
max_ssids = 1;
else {
max_ssids = wpa_s->max_scan_ssids;
if (max_ssids > WPAS_MAX_SCAN_SSIDS)
max_ssids = WPAS_MAX_SCAN_SSIDS;
} wpa_s->last_scan_req = wpa_s->scan_req;
wpa_s->scan_req = NORMAL_SCAN_REQ;
// 如果设置了connect_without_scan, 连接之前选择的网络,不进行扫描,直接关联
if (connect_without_scan) {
wpa_s->connect_without_scan = NULL;
if (ssid) {
wpa_printf(MSG_DEBUG, "Start a pre-selected network "
"without scan step");
wpa_supplicant_associate(wpa_s, NULL, ssid);
return;
}
} os_memset(&params, 0, sizeof(params));
// 设置状态为扫描
wpa_s->scan_prev_wpa_state = wpa_s->wpa_state;
if (wpa_s->wpa_state == WPA_DISCONNECTED ||
wpa_s->wpa_state == WPA_INACTIVE)
wpa_supplicant_set_state(wpa_s, WPA_SCANNING); /*
* If autoscan has set its own scanning parameters
*/
if (wpa_s->autoscan_params != NULL) {
scan_params = wpa_s->autoscan_params;
goto scan;
} if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
wpa_set_ssids_from_scan_req(wpa_s, &params, max_ssids)) {
wpa_printf(MSG_DEBUG, "Use specific SSIDs from SCAN command");
goto ssid_list_set;
} ...... /* Find the starting point from which to continue scanning */
// 查找开始扫描的ssid
ssid = wpa_s->conf->ssid;
// 从这里看,应该是链表里面下一个ssid
if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
while (ssid) {
if (ssid == wpa_s->prev_scan_ssid) {
ssid = ssid->next;
break;
}
ssid = ssid->next;
}
} if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
#ifdef CONFIG_AP
!wpa_s->ap_iface &&
#endif /* CONFIG_AP */
wpa_s->conf->ap_scan == 2) {
wpa_s->connect_without_scan = NULL;
wpa_s->prev_scan_wildcard = 0;
wpa_supplicant_assoc_try(wpa_s, ssid);
return;
} else if (wpa_s->conf->ap_scan == 2) {
/*
* User-initiated scan request in ap_scan == 2; scan with
* wildcard SSID.
*/
ssid = NULL;
} else if (wpa_s->reattach && wpa_s->current_ssid != NULL) {
// 实行单信道,单个ssid扫描。难道是漫游的操作?
// reassoicate重关联
/*
* Perform single-channel single-SSID scan for
* reassociate-to-same-BSS operation.
*/
/* Setup SSID */
ssid = wpa_s->current_ssid;
wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
ssid->ssid, ssid->ssid_len);
params.ssids[0].ssid = ssid->ssid;
params.ssids[0].ssid_len = ssid->ssid_len;
params.num_ssids = 1; /*
* Allocate memory for frequency array, allocate one extra
* slot for the zero-terminator.
*/
params.freqs = os_malloc(sizeof(int) * 2);
if (params.freqs) {
params.freqs[0] = wpa_s->assoc_freq;
params.freqs[1] = 0;
} /*
* Reset the reattach flag so that we fall back to full scan if
* this scan fails.
*/
wpa_s->reattach = 0;
} else {
struct wpa_ssid *start = ssid, *tssid;
int freqs_set = 0;
if (ssid == NULL && max_ssids > 1)
ssid = wpa_s->conf->ssid;
// 获取配置文件中的ssid
while (ssid) {
if (!wpas_network_disabled(wpa_s, ssid) &&
ssid->scan_ssid) {
wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
ssid->ssid, ssid->ssid_len);
params.ssids[params.num_ssids].ssid =
ssid->ssid;
params.ssids[params.num_ssids].ssid_len =
ssid->ssid_len;
params.num_ssids++;
// 达到所能支持的最大ssid个数,退出循环
if (params.num_ssids + 1 >= max_ssids)
break;
}
ssid = ssid->next;
if (ssid == start)
break;
if (ssid == NULL && max_ssids > 1 &&
start != wpa_s->conf->ssid)
ssid = wpa_s->conf->ssid;
} if (wpa_s->scan_id_count &&
wpa_s->last_scan_req == MANUAL_SCAN_REQ)
wpa_set_scan_ssids(wpa_s, &params, max_ssids); for (tssid = wpa_s->conf->ssid;
wpa_s->last_scan_req != MANUAL_SCAN_REQ && tssid;
tssid = tssid->next) {
// 网络关闭,不进行扫描
if (wpas_network_disabled(wpa_s, tssid))
continue;
if ((params.freqs || !freqs_set) && tssid->scan_freq) {
int_array_concat(&params.freqs,
tssid->scan_freq);
} else {
os_free(params.freqs);
params.freqs = NULL;
}
freqs_set = 1;
}
// 对频率进行排序
int_array_sort_unique(params.freqs);
} if (ssid && max_ssids == 1) {
/*
* If the driver is limited to 1 SSID at a time interleave
* wildcard SSID scans with specific SSID scans to avoid
* waiting a long time for a wildcard scan.
*/
if (!wpa_s->prev_scan_wildcard) {
params.ssids[0].ssid = NULL;
params.ssids[0].ssid_len = 0;
wpa_s->prev_scan_wildcard = 1;
wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for "
"wildcard SSID (Interleave with specific)");
} else {
wpa_s->prev_scan_ssid = ssid;
wpa_s->prev_scan_wildcard = 0;
wpa_dbg(wpa_s, MSG_DEBUG,
"Starting AP scan for specific SSID: %s",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
}
} else if (ssid) {
/* max_ssids > 1 */ wpa_s->prev_scan_ssid = ssid;
wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
"the scan request");
params.num_ssids++;
} else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
wpa_s->manual_scan_passive && params.num_ssids == 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request");
} else if (wpa_s->conf->passive_scan) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Use passive scan based on configuration");
} else {
wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
params.num_ssids++;
wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard "
"SSID");
} ssid_list_set:
wpa_supplicant_optimize_freqs(wpa_s, &params);
extra_ie = wpa_supplicant_extra_ies(wpa_s);
// 手动发起的扫描
if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
wpa_s->manual_scan_only_new) {
wpa_printf(MSG_DEBUG,
"Request driver to clear scan cache due to manual only_new=1 scan");
params.only_new_results = 1;
} if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL &&
wpa_s->manual_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels");
params.freqs = wpa_s->manual_scan_freqs;
wpa_s->manual_scan_freqs = NULL;
} if (params.freqs == NULL && wpa_s->select_network_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Limit select_network scan to specified channels");
params.freqs = wpa_s->select_network_scan_freqs;
wpa_s->select_network_scan_freqs = NULL;
}
// 参数里面的频率为空
// 优化扫描,基于的频率列表
if (params.freqs == NULL && wpa_s->next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
"generated frequency list");
params.freqs = wpa_s->next_scan_freqs;
} else
os_free(wpa_s->next_scan_freqs);
wpa_s->next_scan_freqs = NULL;
wpa_setband_scan_freqs(wpa_s, &params); /* See if user specified frequencies. If so, scan only those. */
if (wpa_s->conf->freq_list && !params.freqs) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Optimize scan based on conf->freq_list");
int_array_concat(&params.freqs, wpa_s->conf->freq_list);
} /* Use current associated channel? */
// 是否只扫描当前信道
if (wpa_s->conf->scan_cur_freq && !params.freqs) {
unsigned int num = wpa_s->num_multichan_concurrent; params.freqs = os_calloc(num + 1, sizeof(int));
if (params.freqs) {
num = get_shared_radio_freqs(wpa_s, params.freqs, num);
if (num > 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the "
"current operating channels since "
"scan_cur_freq is enabled");
} else {
os_free(params.freqs);
params.freqs = NULL;
}
}
} params.filter_ssids = wpa_supplicant_build_filter_ssids(
wpa_s->conf, &params.num_filter_ssids);
if (extra_ie) {
params.extra_ies = wpabuf_head(extra_ie);
params.extra_ies_len = wpabuf_len(extra_ie);
} ... if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) &&
wpa_s->wpa_state <= WPA_SCANNING) {
params.mac_addr_rand = 1;
if (wpa_s->mac_addr_scan) {
params.mac_addr = wpa_s->mac_addr_scan;
params.mac_addr_mask = wpa_s->mac_addr_scan + ETH_ALEN;
}
} if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) {
struct wpa_bss *bss; params.bssid = wpa_s->next_scan_bssid;
bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid);
if (bss && bss->ssid_len && params.num_ssids == 1 &&
params.ssids[0].ssid_len == 0) {
params.ssids[0].ssid = bss->ssid;
params.ssids[0].ssid_len = bss->ssid_len;
wpa_dbg(wpa_s, MSG_DEBUG,
"Scan a previously specified BSSID " MACSTR
" and SSID %s",
MAC2STR(params.bssid),
wpa_ssid_txt(bss->ssid, bss->ssid_len));
} else {
wpa_dbg(wpa_s, MSG_DEBUG,
"Scan a previously specified BSSID " MACSTR,
MAC2STR(params.bssid));
}
} scan_params = &params; scan:
...
ret = wpa_supplicant_trigger_scan(wpa_s, scan_params); if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
!wpa_s->manual_scan_freqs) {
/* Restore manual_scan_freqs for the next attempt */
wpa_s->manual_scan_freqs = params.freqs;
params.freqs = NULL;
} wpabuf_free(extra_ie);
os_free(params.freqs);
os_free(params.filter_ssids); if (ret) {
wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
if (wpa_s->scan_prev_wpa_state != wpa_s->wpa_state)
wpa_supplicant_set_state(wpa_s,
wpa_s->scan_prev_wpa_state);
/* Restore scan_req since we will try to scan again */
wpa_s->scan_req = wpa_s->last_scan_req;
wpa_supplicant_req_scan(wpa_s, 1, 0);
} else {
wpa_s->scan_for_connection = 0;
#ifdef CONFIG_INTERWORKING
wpa_s->interworking_fast_assoc_tried = 0;
#endif /* CONFIG_INTERWORKING */
if (params.bssid)
os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
}
} wpa_supplicant_trigger_scan
--> wpas_trigger_scan_cb
--> wpa_drv_scan(wpa_s, params);
--> wpa_s->driver->scan2(wpa_s->drv_priv, params); external\wpa_supplicant_8\src\drivers\driver_nl80211.c
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
.get_bssid = wpa_driver_nl80211_get_bssid,
.get_ssid = wpa_driver_nl80211_get_ssid,
.set_key = driver_nl80211_set_key,
.scan2 = driver_nl80211_scan2,
...
} static int driver_nl80211_scan2(void *priv,
struct wpa_driver_scan_params *params)
{
struct i802_bss *bss = priv;
#ifdef CONFIG_DRIVER_NL80211_QCA
struct wpa_driver_nl80211_data *drv = bss->drv; /*
* Do a vendor specific scan if possible. If only_new_results is
* set, do a normal scan since a kernel (cfg80211) BSS cache flush
* cannot be achieved through a vendor scan. The below condition may
* need to be modified if new scan flags are added in the future whose
* functionality can only be achieved through a normal scan.
*/
if (drv->scan_vendor_cmd_avail && !params->only_new_results)
return wpa_driver_nl80211_vendor_scan(bss, params);
#endif /* CONFIG_DRIVER_NL80211_QCA */
return wpa_driver_nl80211_scan(bss, params);
} external\wpa_supplicant_8\hostapd\src\drivers\driver_nl80211_scan.c
int wpa_driver_nl80211_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
int ret = -1, timeout;
struct nl_msg *msg = NULL; wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
drv->scan_for_auth = 0; if (TEST_FAIL())
return -1; msg = nl80211_scan_common(bss, NL80211_CMD_TRIGGER_SCAN, params);
if (!msg)
return -1; if (params->p2p_probe) {
struct nlattr *rates; wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates"); rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
if (rates == NULL)
goto fail; /*
* Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
* by masking out everything else apart from the OFDM rates 6,
* 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
* rates are left enabled.
*/
if (nla_put(msg, NL80211_BAND_2GHZ, 8,
"\x0c\x12\x18\x24\x30\x48\x60\x6c"))
goto fail;
nla_nest_end(msg, rates); if (nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE))
goto fail;
} if (params->bssid) {
wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: "
MACSTR, MAC2STR(params->bssid));
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
goto fail;
} ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
"(%s)", ret, strerror(-ret));
if (drv->hostapd && is_ap_interface(drv->nlmode)) {
enum nl80211_iftype old_mode = drv->nlmode; /*
* mac80211 does not allow scan requests in AP mode, so
* try to do this in station mode.
*/
if (wpa_driver_nl80211_set_mode(
bss, NL80211_IFTYPE_STATION))
goto fail; if (wpa_driver_nl80211_scan(bss, params)) {
wpa_driver_nl80211_set_mode(bss, old_mode);
goto fail;
} /* Restore AP mode when processing scan results */
drv->ap_scan_as_station = old_mode;
ret = 0;
} else
goto fail;
} drv->scan_state = SCAN_REQUESTED;
/* Not all drivers generate "scan completed" wireless event, so try to
* read results after a timeout. */
// 扫描超时时间,超时之后读取结果。
timeout = 10;
if (drv->scan_complete_events) {
/*
* The driver seems to deliver events to notify when scan is
* complete, so use longer timeout to avoid race conditions
* with scanning and following association request.
*/
timeout = 30;
}
wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
"seconds", ret, timeout);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
drv, drv->ctx);
drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN; fail:
nlmsg_free(msg);
return ret;
} static struct nl_msg *
nl80211_scan_common(struct i802_bss *bss, u8 cmd,
struct wpa_driver_scan_params *params)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
size_t i;
u32 scan_flags = 0; msg = nl80211_cmd_msg(bss, 0, cmd);
if (!msg)
return NULL; if (params->num_ssids) {
struct nlattr *ssids; ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
if (ssids == NULL)
goto fail;
for (i = 0; i < params->num_ssids; i++) {
wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
params->ssids[i].ssid,
params->ssids[i].ssid_len);
if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
params->ssids[i].ssid))
goto fail;
}
nla_nest_end(msg, ssids);
} else {
wpa_printf(MSG_DEBUG, "nl80211: Passive scan requested");
} if (params->extra_ies) {
wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
params->extra_ies, params->extra_ies_len);
if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,
params->extra_ies))
goto fail;
}
// 扫描频率
if (params->freqs) {
struct nlattr *freqs;
freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
if (freqs == NULL)
goto fail;
for (i = 0; params->freqs[i]; i++) {
wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
"MHz", params->freqs[i]);
if (nla_put_u32(msg, i + 1, params->freqs[i]))
goto fail;
}
nla_nest_end(msg, freqs);
} os_free(drv->filter_ssids);
drv->filter_ssids = params->filter_ssids;
params->filter_ssids = NULL;
drv->num_filter_ssids = params->num_filter_ssids; if (params->only_new_results) {
wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH");
scan_flags |= NL80211_SCAN_FLAG_FLUSH;
} if (params->low_priority && drv->have_low_prio_scan) {
wpa_printf(MSG_DEBUG,
"nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY");
scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
} if (params->mac_addr_rand) {
wpa_printf(MSG_DEBUG,
"nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR");
scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR; if (params->mac_addr) {
wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR,
MAC2STR(params->mac_addr));
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
params->mac_addr))
goto fail;
} if (params->mac_addr_mask) {
wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: "
MACSTR, MAC2STR(params->mac_addr_mask));
if (nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
params->mac_addr_mask))
goto fail;
}
} if (params->duration) {
if (!(drv->capa.rrm_flags &
WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL) ||
nla_put_u16(msg, NL80211_ATTR_MEASUREMENT_DURATION,
params->duration))
goto fail; if (params->duration_mandatory &&
nla_put_flag(msg,
NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY))
goto fail;
} if (scan_flags &&
nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags))
goto fail; return msg; fail:
nlmsg_free(msg);
return NULL;
}

2018-11-14

Android WiFi 扫描流程分析(wpa_supplicant)的更多相关文章

  1. Android WiFi 扫描流程分析(wpa_supplicant选择网络)

    扫描流程 1.如果之前就已经有相关记录,优化扫描,扫描记录部分的频率信道. 2.如果1中的扫描没有结果,清除黑名单中的进行选择. 3.如果2中没有结果,进行所有频率的信道进行扫描 相关log参考: h ...

  2. Android WIFI 启动流程(TIP^^)

    前几天因为解决一堆Bug,没时间写.我不会每天都写,就是为了存档一些资料. 内容来源:工作中接触到的+高手博客+文档(Books)=自己理解 仅限参考^^ 此博客是上一个<<Android ...

  3. android wifi ANR问题分析总结

    android wifi ANR问题分析总结 1 看看main进程阻塞在那里? 2 调用关系的函数阻塞在那里? 3 最终阻塞函数的阻塞前的log以及状态

  4. Android WIFI 启动流程

    参考:http://blog.chinaunix.net/uid-26215986-id-3260413.html 一. WIFI 工作步骤 1. Wifi模块初始化 2. Wifi启动 3. 查找热 ...

  5. android PakageManagerService启动流程分析

    PakageManagerService的启动流程图 1.PakageManagerService概述 PakageManagerService是android系统中一个核心的服务,它负责系统中Pac ...

  6. android WiFi ASSOC_REJECT 流程跟踪

    Android设备在于AP关联时,如果AP返回关联拒绝帧,Android设别会把AP加入黑名单中. 黑名单中的设备将会在扫描时,延时一段时间放在后面处理. 代码以及log基于SDM450, Andro ...

  7. Android 呼吸灯流程分析

    一.Android呼吸灯Driver实现 1.注册驱动 代码位置:mediatek/kernel/drivers/leds/leds_drv.c 602static struct platform_d ...

  8. android Camera 数据流程分析

    这篇文章主要针对其数据流程进行分析.Camera一般用于图像浏览.拍照和视频录制.这里先对图像浏览和拍照的数据流进行分析,后面再对视频电话部分进行分析. 1.针对HAL层对摄像头数据处理补充一下 Li ...

  9. Android SDCard Mount 流程分析

    前段时间对Android 的SDCard unmount 流程进行了几篇简短的分析,由于当时只是纸上谈兵,没有实际上的跟进,可能会有一些误导人或者小错误.今天重新梳理了头绪,针对mount的流程再重新 ...

随机推荐

  1. spring cloud 项目相关集成简介

    Spring Cloud Config 配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置,目前支持本地存储.Git以及Subversion. Spring Cloud Bus 事件.消 ...

  2. 关于casperjs的wait方法的执行顺序

    var casper = require('casper').create({ viewportSize:{ width:1920, height:1080 } }); var url1 = 'htt ...

  3. 每日英语:A Chinese Father’s Most Important Job

    When it comes to parenting, Chinese fathers say the most important role they play is that of the fam ...

  4. spring c3p0 配置

      spring c3p0 配置   <?xml version="1.0" encoding="UTF-8"?> <beansxmlns=& ...

  5. scala工程导入报错:scalatest_2.10-1.9.1.jar is cross-compiled with an incompatible version of Scala (2.10).

    错误原因: The Scala IDE tries to check if binary incompatible Scala libraries have been inadvertently mi ...

  6. JAVA-JSP内置对象之out对象进行页面输出

    相关资料:<21天学通Java Web开发> out对象 out对象进行页面输出1.通过out对象的print()方法和println()方法进行页而输出.2.不同的println()方法 ...

  7. js实现完美身份证号有效性验证(转)

    转载自:http://www.cnblogs.com/lzrabbit/archive/2011/10/23/2221643.html 最近需要对身份证合法性进行验证,实名验证是不指望了,不过原来的验 ...

  8. [转]MySQL-5.7 Update语句详解

    原文地址:https://www.cnblogs.com/tongxiaoda/p/7908977.html .语法 (1)单表 UPDATE [LOW_PRIORITY] [IGNORE] tabl ...

  9. 负数在计算机中的表示 Byte-128

    本文转载: http://blog.csdn.net/njuitjf/article/details/4585247 原码:将一个整数,转换成二进制,就是其原码.如单字节的5的原码为:0000 010 ...

  10. andrdoi示例项目SampleSyncAdapter分析

    概述 在sdk目录下有个示例项目SampleSyncAdapter,演示了 用户授权和同步适配器的一些内容,是个学习的很好范例.我读了很久,很多地方没搞明白,先把理解的一些记录下来. 通过学习该示例, ...