转载自:http://blog.sina.com.cn/s/blog_a6559d920101glcf.html
Wifi 网卡状态
1.
2.
3.
4.
5.
WIFI 访问网络需要的权限
"android.permission.CHANGE_NETWORK_STATE">
修改网络状态的权限
android:name="android.permission.CHANGE_WIFI_STATE">
修改WIFI状态的权限
"android.permission.ACCESS_NETWORK_STATE">
访问网络权限
"android.permission.ACCESS_WIFI_STATE">
访问WIFI权限
WIFI 核心模块
n
由SystemServer启动的时候生成的ConnecttivityService创建,负责启动关闭wpa_supplicant,启动和关闭WifiMonitor线程,把命令下发给wpa_supplicant以及跟新WIFI的状态
n
n
1、读取配置文件
2、初始化配置参数,驱动函数
3、让驱动scan当前所有的bssid
4、检查扫描的参数是否和用户设置的想否
5、如果相符,通知驱动进行权限 认证操作
6、连上AP
n
厂商提供的source,主要进行load firmware和kernel的wireless进行通信
n
主要控制硬件的GPIO和上下电,让CPU和Wifi模组之间通过sdio接口通信
Wifi工作步骤
n
n
n
n
n
n
n
Wifi模块代码总结
n
packages/apps/Settings/src/com/android/settings/wifi
n
frameworks/base/wifi/java/android/net/wifi
frameworks/base/services/java/com/android/server
n
frameworks/base/core/jni/android_net_wifi_Wifi.cpp
n
hardware/libhardware_legacy/wifi/wifi.c
n
external/wpa_supplicant
n
net/wireless
Wifi模块的初始化:
在 SystemServer 启动的时候,会生成一个ConnectivityService 的实例,ConnectivityService 的构造函数会创建WifiService,WifiStateTracker会创建WifiMonitor 接收来自底层的事件,WifiService 和WifiMonitor是整个模块的核心。WifiService 负责启动关闭wpa_supplicant、启动关闭WifiMonitor监视线程和把命令下发给wpa_supplicant,而WifiMonitor 则负责从wpa_supplicant接收事件通知。
Wifi模块的启动:
WirelessSettings 在初始化的时候配置了由WifiEnabler 来处理Wifi 按钮,
当用户按下Wifi 按钮后,Android 会调用WifiEnabler的onPreferenceChange,再由WifiEnabler调用WifiManager 的setWifiEnabled接口函数,通过AIDL,实际调用的是WifiService 的setWifiEnabled 函数,WifiService接着向自身发送一条MESSAGE_ENABLE_WIFI 消息,在处理该消息的代码中做真正的使能工作:首先装载WIFI内核模块(该模块的位置硬编码为"/system/lib/modules/wlan.ko" ), 然后启动wpa_supplicant(配置文件硬编码为"/data/misc/wifi/wpa_supplicant.conf"),再通过WifiStateTracker来启动WifiMonitor 中的监视线程。
查找热点(AP):
(Wifi开启)中讲到Wifi模块开启后会对外发送WIFI_STATE_CHANGED_ACTION。WifiLayer中注册了Action的Receiver。当WifiLayer收到此Action后开始scan的流程,具体如下
当wpa_supplicant 处理完SCAN 命令后,它会向控制通道发送事件通知扫描完成,从wifi_wait_for_event函数会接收到该事件,由此WifiMonitor 中的MonitorThread 会被执行来出来这个事件:
配置 AP 参数:
当用户在 WifiSettings 界面上选择了一个AP 后,会显示配置AP 参数的一个对话框:
Wifi连接:
IP地址的配置:
首先交代开发环境——硬件平台:高通MSM8225,OS:Android2.3.5,无线模块:brodcom BCM4330。
一、WIFI:
二、Bluetooth:
brcm_patchram_plus.c中,里面主要完成了如下事件:1、读取BT的地址。2、执行parse相关命令。3、重启HCI服务,4、设置蓝牙通信的波特率。5、设置hci_pcm
网上关于BT的驱动很少,所以我在开发过程中把其中的步骤记录下来。供大家相互学习讨论。
一、关于BT driver的移植:
1. Enablebluetootch in BoadConfig.mk
2.实现BT电源管理rfkill驱动。
Kernel/driver/bluetooth/bluetooth-power.c
在kernel\arch\arm\mach_msm7x27.c: static int bluetooth_power(inton)中
实现:上电:把bt_reset pin 和bt_reg_on pin 拉低
3. RebuildAndroid image and reboot
命令行测试:
echo 0>/sys/class/rfkill/rfkill0/state
echo 1>/sys/class/rfkill/rfkill0/state
brcm_patchram_plus-d --patchram/etc/firmware/BCM4329B1_002.002.023.0061.0062.hcd/dev/ttyHS0
hciattach -s115200 /dev/ttyHS0 any
没任何错误提示是可以用以下测试
hciconfig hci0up
hcitool scan
4.实现BT睡眠唤醒机制
Kernel\drivers\bluetooth\bluesleep.c一般来说这个文件改动比较少,但可能逻辑上会有些问题。需要小的改动。
在kernel\arch\arm\mach_xxx/board_xxx.c:bluesleep_resources中定义gpio_host_wake(BT唤醒host脚)、gpio_ext_wake(host唤醒BT脚)、host_wake(BT唤醒host的中断号)。
注:各个平台的board_xxx.c文件名字不同,请客户确认
5.系统集成
1)在init.qcom.rc中确认有下面的内容:
service hciattach/system/bin/sh /system/etc/init.qcom.bt.sh
2)修改init.qcom.bt.sh
确认有:
BLUETOOTH_SLEEP_PATH=/proc/bluetooth/sleep/proto
echo 1 >$BLUETOOTH_SLEEP_PATH
/system/bin/hciattach-n /dev/ttyHS0 any 3000000 flow & 改为:
./brcm_patchram_plus--enable_lpm –enable_hci --patchram/system/etc/wifi/BCM4329BT.hcd --baudrate3000000 /dev/ttyHS0&
注掉:高通下载firmware的命令。
6.重新编译system。此时BT应该能运行了。
二、BT的休眠唤醒配置
BT的休眠在driver/bluetooth/bluesleep.c中,首先驱动的名字叫“bluesleep”与arch/arm/mach-msm/board-msm7x30.c相匹配就执行platform_driver_probe(&bluesleep_driver,bluesleep_probe)然后调用static int __init bluesleep_probe(structplatform_device *pdev),这里会配置两个引脚HOST_WAKE_BT &BT_WAKE_HOST
bsi =kzalloc(sizeof(struct bluesleep_info), GFP_KERNEL);
如上代码所示,主要将HOST_WAKE_BT设置为输出脚,BT_WAKE_HOST设置为输入脚并也设置为中断脚,等待BT芯片的唤醒。
然后再bluesleep_init函数中建立BT目录/proc/bluetooth/sleep/读btwake中HOST_WAKE_BT的状态。读出的状态值为0或1。
或在BT目录/proc/bluetooth/sleep/写btwake中HOST_WAKE_BT的状态。写出状态值为0或1。
问:打开wifi,连接wifi热点,提示连接成功,但headbar上不显示wifi图标,back退出wifi设置,再进入,提示wifi已断开。
答:首先现象复现,当现象复现时进入adb shell,然后输入ifconfig 查看是否有wlan0 端口,然后在adb shell中ping192.168.1.101(嵌入式设备的IP),如果能Ping通则说明底层wifi设备与AP是连接通的。所以把问题转向上层。上层在frameworks/base/services/java/com/android/server/ConnectivityService.java文件中查看privatevoid handleDisconnect(NetworkInfo info)函数的实现,问题可能出现在这里。
Part 2
问:出现新热点,需要重启WIFI才可以扫描到。
问:20s内无法连接到WIFI热点。
问:已连接的热点关闭,不会自动连接下一个热点。
答:这些问题都是供应商芯片的firmware没有配置好,所以直接找FAE换掉。
Part 3
问:调试中如果遇到dhd_sdio_probe fail 。
问:发现sdio register timeout 。
答:因为我们用到的WIFI数据通道是SDIO接口,所以要在log信息中查看sdcard是否有加载。没加载的话就看看WIFI芯片的上电(如WIFI_REG_ON这个PIN脚)。
Part 4
问:如果在wifi的设置里面选中wifi选项出现ERRO(或错误)的提示。
答:首先在adb shell中lsmod查看.ko文件是否已经加载。如没加载cat/proc/kmsg查看是否是版本匹配的问题。如遇版本匹配则在kernel/scripts/setlocalversion中将echo“+”中去掉。如果顺利加载了驱动,则要看看MAC地址是否有,并且是否合理。
Part 5
问:发现在WIFI设置选项中有已经选上了wifi并且勾应打上了,过一会出现wifi的勾自动消失。
答:这种情况在adbshell中用ifconfig查看Wlan的接口用的是否是wlan0,有可能是eth0。如果是eth0则在hardware/libhardware_legacy/wifi/wifi.c中的#defineWIFI_DRIVER_MODULE_ARG
Part 6
问:有的路由器不能扫描的到。
答:查看wlan的设置的channel是否在1-14这个频段,因为如果wlan设置成USA模式则channel的范围在1-11之间,channel12,13,14就不会收索的到。所以要在nvram.txt中修改成ccode=ALL,并且在gqcom_cfg.ini中把APCntryCode=ALL。这样应该就可以扫描到所有的channel了。当然如果上层还是没有收索到的话,在Settings.java中也要做相应的修改。
常用的命令:wl channels_in_country
wl chanlist
wl channels
wl country
Part 7
问:【预置条件】:wifi 已连接 wifi sleep policy模式为When screen turnsoff
答:调试分析记录:
1.在frameworks/base/services/java/com/android/server/WifiService.java中修改LCD灭屏后关掉WIFI的时间长短,由以前的2分钟修改为现在的1秒钟。
结果是短时间休眠后唤醒可以顺利连上AP,但经过长时间休眠(如15分钟)后唤醒机器还是无法连接AP。
2.检查Kernel中POWER_ON使能脚,看是否有其它地方被占用过,结果是屏蔽所有其它用到过该脚的代码还是无用。
3.检查CP侧代码,将CP侧POWER_ON引脚由以前的某种特殊功能设置成普通的Output模式,然后AP就可以自由的控制其高低电平了。
修改后的结果还是以无效告终。
4.检查external/wpa_supplicant_6/wpa_supplicant/文件夹下面的代码,检查WEXT驱动代码。结果还是失败。
5.最后在机器休眠15分钟后,用底层命令行来scan、连接等动作的操作,结果根本无法扫描到AP。故把问题集中在驱动底层。经过修改dhd.ko、sdio.bin文件
现在此Bug终于得解。
6.也有问题不出现在驱动dhd.ko文件中,可能出现在mmc驱动中的sdio通道。在函数mmc_pm_notify中当出现PM_POST_SUSPEND或PM_POST_HIBERNATION的情况时就有可能移除掉了sdio通道,所以函数mmc_detect_change(host,0)要加一个判断,当sdio作为wifi通道时就不能移除。移除后的后果就是此Bug。