###1. wpa_supplicant_scan()
WPAS 中, 扫描任务由 wpa_supplicant_scan() 来完成
通过向 eloop 核心注册timeout事件, 到期后触发 wpa_supplicant_scan()执行, 实现了定时扫描, 若循环触发定时扫描, 则还可以实现周期扫描
WPAS 中有4个接口来控制 wpa_supplicant_scan 任务:
- wpa_supplicant_update_scan_int() 更新扫描间隔时间
- wpa_supplicant_req_scan() 开始调度扫描任务
- wpa_supplicant_cancel_scan() 停止调度扫描任务
- wpas_scan_scheduled() 扫描任务是否被调度
###2. WPAS 中的周期扫描
若当前未连接到AP, 且 WPAS 不处于DISCONNECTED的状态, 并且保存了未被disable的AP, 则WPAS会发起周期扫描
周期扫描的 间隔时间存储在 struct wpa_supplicant.scan_interval 成员中:
- 初始值为10秒
- 可以通过 wpa_cli 的“SCAN_INTERVAL” cmd 来设置间隔时间 (android framework中设置为15s)
如下情况会终止周期扫描
- 在连接上AP后, 会停止周期扫描
- android上, 灭屏后, 会设置PNO扫描, 因此也会停止WPAS的周期扫
###3. sched scan
如果wifi driver支持sched scan的话, WPAS可以使用sched scan来进行定时扫描
sched scan 的扫描间隔存储在 struct wpa_supplicant.sched_scan_interval 中
- 默认值为10s
- 可以在wpa_supplicant.conf中使用“sched_scan_interval”项来配置
- android上在 “frameworks/base/core/res/res/values/config.xml” 中的 “config_wifi_supplicant_scan_interval” 项设置
WPAS中的 sched scan 的接口为:
//设置定时扫描间隔并且开始扫描
int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params,
int interval)
//停止定时扫描
int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
//这两个接口是通过调用上述2个接口实现的, 会自动处理 MAX_SCAN_SSID 的问题
int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
//同上2个接口, 但是延时开始定时扫描
int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
int sec, int usec)
void wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s)
###4. PNO scan
PNO (Prefered Network Offloading) 机制使得上层应用可以请求wifi firmware扫描指定的ssid:
- 上层应用给出一份 SSID 列表给wifi firmware
- 在进入 early suspend时, 开始PNO扫描, 在late resume之后停止扫描
PNO 通常用于在android设备灭屏后, 未连接AP, 但是保存了AP的情况下进行扫描, 以选择合适的AP并且连接
PNO是利用上述的sched scan来实现的, 因此, 其默认的扫描间隔即是 sched scan 的默认扫描间隔, 为了省电考虑, 通常, PNO 扫描的时间是指数递增的, 例如, 设定递增次数为6, 则
- 以默认值10s扫描6次
- 以20s扫描6次
- 以40s扫描6次
- 以80s扫描6次
- 以160s扫描6次
- 以320s扫描6次
- 以320s间隔扫描, 直到停止PNO
在WPAS中使用 “set pno” cmd 来开关PNO scan
set pno 1
set pno 0
不同的wifi driver, 实现的PNO接口也有所差异, 支持的具体参数也可能有差别
android中可以在“frameworks/base/core/res/res/values/config.xml”中利用 “config_wifi_background_scan_support”项来配置是否使用 PNO 扫描
android上PNO扫描被称为background scan, 请不要和WPAS的background scan混淆
###5. background scan
当STA在ESS(有多个BSS)中移动时,在信号不好的情况下, 需要要从一个BSS漫游到另一个BSS, 为了增强漫游的无缝体验(在扫描过程中, STA不能收发数据帧), STA可以采用background scan(定时扫描一小段时间, 或者空闲时才扫描)
WPAS使用模块的形式来实现bgscan, 每一种bgscan的实现都需要实现如下的接口
struct bgscan_ops {
const char *name;
void * (*init)(struct wpa_supplicant *wpa_s, const char *params, const struct wpa_ssid *ssid);
void (*deinit)(void *priv);
int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res);
void (*notify_beacon_loss)(void *priv);
void (*notify_signal_change)(void *priv, int above,
int current_signal,
int current_noise,
int current_txrate);
};
WPAS 使用如下的接口来 开启/停止 bgscan
void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
WPAS当前支持如下2种bgscan的实现:
- bgscan simple : 需要配置编译选项 “CONFIG_BGSCAN_SIMPLE”
- bgscan learn : 需要配置编译选项 “CONFIG_BGSCAN_LEARN”
在编译所需的 bgscn 模块后, 在使用时还需要在 wpa_supplicant.conf 进行配置, 其语法为
// bgscan simple
bgscan="simple:<short bgscan interval in seconds>:<signal strength threshold>:<long interval>"
// bgscan learn
bgscan="learn:<short bgscan interval in seconds>:<<signal strength threshold>:<long interval>[:<database file name>]"
例如:
bgscan="simple:30:-45:300"
bgscan="learn:30:-45:300:/etc/wpa_supplicant/network1.bgscan"
使用如下的方式来 disable bgscan
bgscan=""
若打开了 bgscan, WPAS 在进入 COMPLETED 状态后开启 bgscan, 小于 ASSOCIATED 状态后, 关闭 bgscan
wifi roaming可以在WPAS中实现, 也可以在 wifi driver 或者 wifi firmware中实现,因此要根据需要来配置bgscan
###6. autoscan
autoscan 类似于 bgscan, 但是 autoscan 是在 DISCNONECT 和 INACTIVE 状态下工作
WPAS 以模块的方式来实现,autoscan, 每一种autoscan的实现需要提供如下的接口:
struct autoscan_ops {
const char *name;
void * (*init)(struct wpa_supplicant *wpa_s, const char *params);
void (*deinit)(void *priv);
int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res);
};
WPAS使用如下的接口来 开启/停止 autoscan
void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
WPAS 当前支持2种autoscan的实现:
- exponential : 扫描间隔指数递增, 编译时需要打开 CONFIG_AUTOSCAN_EXPONENTIAL
- periodic : 扫描间隔固定, 编译时需要打开CONFIG_AUTOSCAN_PERIODIC
使用 autoscan 还需要在 wpa_supplicant.conf 中进行配置, 例如
// 扫描间隔指数递增, 3,9, 27...300 s
autoscan=exponential:3:300
// 扫描间隔固定为30s
autoscan=periodic:30
若开启了autoscan, 则 在进入 DISCONNECT 或者 INACTIVE 状态后, 开启 autoscan, 进入 AUTHENTICATING 状态后停止 autoscan