解决wifi 无法开启– 软体启动流程修改

wifi 启动流程

系统根据以下流程开启wifi

  1、载入wifi kernel module

wifi kernel module 中,主要是透过ioctl 的方式与user space 下运行的wpa_supplicant 进行沟通。另外在硬体的实现上,由于CPU 需要有另一个介面与wifi chip 进行沟通,如wifi firmware 的载入、command request 以及资料的传送/接收。目前较为常用的界面为4bit SDIO (Secure Digital I/O)

   2、启动wpa_supplicant

运行于user space 下的一个service,可以在init.rc 下启动并初始化这个service。当然在启动以及关闭wifi 时也会一起启动以及关闭。

  3、创建interface

建立wpa_supplicant 以及wifi kernel module interface 作为实现wifi 的各种操作如找寻适当AP (Access Point)secure method (WPAWPA2 WEP) 或建立/解除与AP 的连线。

 问题描述

user 通过UI setting去启动wifi 时,wifi 找不到任何AP 且画面一直停留在scanning…的状态此问题有可能是AP 信号太弱或是security method 不对。但除了这些之外,本文想引出另一个思考的方向软体启动流程不对引发的问题。

问题分析

重新检视上述启动流程,可以发现wifi kernel module 是在kernel space 进行载入而wpa_supplicant 是在user space 下启动的。如果要正确地控制其启动流程,较常见的方法是程式中透过cat /proc/modules。如果可以在/proc/modules 中读取到 module name,代表wifi kernel module 已经载入完成。但显然在笔者的开发经验上,这样的方法上并不能适用于所有的平台。在这样的情况下,如果在user space 中因为对wifi kernel module 确实的载入完成时间有任何的误判而提前启动wpa_supplicant,将会使得wpa_supplicant 找不到wifi device 而会有如以下的error logs 出现

I/wpa_supplicant( 677): rfkill: Cannot open RFKILL control device

E/wpa_supplicant( 677): Could not read interface wlan0 flags: No such device

E/wpa_supplicant( 677): WEXT: Could not set interface 'wlan0' UP

E/wpa_supplicant( 677): wlan0: Failed to initialize driver interface

 问题分析方法

  1. 可以在adb shell 中透过手动方式运行启动流程。这可以帮助分析以及厘清问题。假如可以利用手动方式启动,则可以确认在软体中可能是因为kernel module 载入时间过长而发生问题。

a). 可利用以下command load/unload/list module

$ insmod /system/lib/modules/wlan.ko  (Insert module)

$ rmmod wlan.ko (Remove module)

$ lsmod (list module)

b). 可利用以下command start/stop wpa_supplicant

$ start wpa_supplicant

$ stop wpa_supplicant

解决方法

  1. kernel space 里增加flag 来检查kernel driver 是否已经载入完成。并且透过set property 的方式记录在prop file , 这种方式可以确保user space 启动wpa_supplicant 的时间。
  2. 如果你无法从kernel space 去完成上述动作,那可能只能加一些 Timeout 或是delay 来解决这个问题。

你可能感兴趣的:(wifi)