相关文章推荐

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:&lt;short bgscan interval in seconds&gt;:<&lt;signal strength threshold&gt;:&lt;long interval&gt;[:&lt;database file name&gt;]"
    
    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

     
    推荐文章