一、前言
在调试wifi驱动的时候会遇到很多坑,相信每个调试驱动的工程师都深有体会吧。wifi驱动涉及到linux和android两个大层面,任意一个环节出错都有可能导致wifi驱动不能正常工作,现在我总结一下我在移植wifi驱动的时候所遇到的坑。
1.sdio接口的wifi驱动rtl8723bs安装后只提示驱动安装成功,但平台设备驱动注册失败。
错误信息如下:
root@smdk4x12:/system/lib/modules # insmod wlan.ko
[ 454.470096] RTL871X: module init start
[ 454.472372] RTL871X: rtl8723bs v4.4.0_17166.20160322_BTCOEX20151223-654a
[ 454.479104] RTL871X: build time: Sep 11 2017 23:49:09
[ 454.484104] RTL871X: rtl8723bs BT-Coex version = BTCOEX20151223-654a
[ 454.490748] RTL871X: ## Calling platform_driver_register
[ 455.495153] RTL871X: rtw_android_wifictrl_func_add: platform_driver_register timeout
[ 455.501544] RTL871X: module init ret=0
root@smdk4x12:/system/lib/modules #
问题分析和解决:
出现这个原因是因为linux系统检测不到这个sdio设备,没有调用平台设备的探测函数:probe。而sdio的设备驱动还需要一根cd线触发,通知linux系统有sdio设备接入,这时linux系统才会调用probe函数。这个cd线是利用sdio总线里的gpio来检测的,这是特定的gpio,理论上不能用别的io代替。
要对应地在linux系统里面配置sdio的cd引脚
通过配置cd脚后,当cd脚拉低,在linux上会打印调试信息的:
2|shell@smdk4x12:/ $ [ 780.545219] *******mmc2: inserted!!!!!******
[ 780.629082] mmc2: new high speed SDIO card at address 0001
在linux的系统目录下可以看到sdio的设备:
当拔出cd脚,同样也会打印调试信息:
|shell@smdk4x12:/ $ [ 820.596837] mmc2: card 0001 removed
[ 820.630223] *******mmc2: inserted!!!!!******
[ 820.685222] *******mmc2: inserted!!!!!******
[ 820.740234] *******mmc2: inserted!!!!!******
[ 820.795249] *******mmc2: inserted!!!!!******
如果你提前安装了wifi驱动,使用命令insmod wlan.ko,后面如果你把cd脚拉低后,系统会自动加载wifi驱动。
root@smdk4x12:/system/lib/modules # [ 860.525217] *******mmc2: inserted!!!!!******
[ 860.609268] mmc2: new high speed SDIO card at address 0001
[ 860.618972] RTL871X: rtw_hal_config_rftype RF_Type is 3 TotalTxPath is 1
[ 860.624660] RTL871X: Chip Version Info: CHIP_8723B_Normal_Chip_TSMC_F_CUT_1T1R_RomVer(0)
[ 860.642052] RTL871X: SetHwReg8723B: bMacPwrCtrlOn=1
[ 860.646977] RTL871X: PowerOnCheck: val_mix:0x0000063f, res:0x0000063f
[ 860.652052] RTL871X: PowerOnCheck: 0x100 the result of cmd52 and cmd53 is the same.
[ 860.659897] RTL871X: PowerOnCheck: 0x1B8 test Pass.
[ 860.665556] RTL871X: ReadAdapterInfo8723BS, 0x4e=0xe2
[ 860.669719] RTL871X: EEPROM type is E-FUSE
[ 860.674604] RTL871X: hal_EfuseSwitchToBank: Efuse switch bank to 0
[ 860.818585] RTL871X: hal_ReadEFuse_WiFi: data end at address=0xab
[ 860.823229] RTL871X: Efuse Realmap:
[ 860.826732]
[ 860.828155] 29 81 03 7C 51 08 28 00 62 07 0D 45 10 00 00 00
[ 860.833797] 2F 2F 2F 2F 2F 2F 33 33 33 32 32 0D FF FF FF FF
[ 860.839443] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
[ 860.845100] FF FF FF FF FF FF FF FF FF FF 28 28 28 28 28 28
[ 860.850728] 28 28 28 28 28 00 FF FF FF FF FF FF FF FF FF FF
[ 860.856365] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
[ 860.862007] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
[ 860.867649] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
[ 860.873291] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
[ 860.878933] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
[ 860.884575] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
[ 860.890217] FF FF FF FF FF FF FF FF 20 3B 1F 00 00 00 FF FF
[ 860.895859] FF 29 20 11 00 00 00 FF 00 FF 12 FF FF FF FF FF
[ 860.901501] 3E 10 01 02 23 00 00 FF 20 04 4C 02 23 B7 21 02
[ 860.907173] 0C 00 22 04 00 08 00 32 FF 21 02 0C 00 22 2A 01
[ 860.917264] 01 00 00 00 00 00 00 00 00 00 00 00 02 00 FF FF
[ 860.926334] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
2.wifi驱动编译成功了,但是安卓系统无法正常调用
rtl8723的驱动移植是分两步进行的,分别是linux层和安卓层,linux层的只需要把wifi驱动编译成ko的模块文件,把它拷贝到linux系统里面使用insmod就能安装,但是安卓系统无法直接调用,必须通过安卓系统与其对接才行。安卓系统是通过hal层的wifi_realtek.c文件里的inmod函数来代替人工的insmod,这样的话加载和卸载模块都由安卓系统掌控。
如果遇到wifi驱动加载不成功,要检查下面几个可能:1.wifi模块的目录设置是否正确。2.wifi驱动在linux下用命令是否能正常安装。3.wifi驱动是否到到正确的目录。4.wifi驱动的目录用户组是不是wifi,读写权限是否是可读可写。5.wifi模块的用户组是否是wifi,读写权限是否是可读可写。通过init.rc文件里面添加初始化文件夹和文件的配置信息,可以达到上述的效果,安卓系统一开机就执行目录和文件的属性设置,保证对驱动正确加载和读写。配置信息如下:
# for wifi prepare
chmod 0770 /system/lib/modules
chown wifi wifi /system/lib/modules
chown wifi wifi /system/lib/modules/wlan.ko
mkdir /system/etc/wifi 0770 wifi wifi
chmod 0770 /system/etc/wifi
chmod 0660 /system/etc/wifi/wpa_supplicant.conf
chown wifi wifi /system/etc/wifi/wpa_supplicant.conf
# wpa_supplicant socket
mkdir /data/misc/wifi 0770 wifi wifi
mkdir /data/misc/wifi/sockets 0770 wifi wifi
chmod 0770 /data/misc/wifi
chmod 0660 /data/misc/wifi/wpa_supplicant.conf
但是千万别添加下面的配置信息
#mkdir /data/system/wpa_supplicant 0771 wifi wifi
#chmod 0771 /data/system/wpa_supplicant
否则加载驱动的时候会找不到wlan0,提示错误信息如下:
09-19 17:21:44.770 1567-1604/system_process D/WifiHW: check_wifi_ifname_from_proc: find p2p0
09-19 17:21:44.770 1567-1604/system_process D/WifiHW: check_wifi_ifname_from_proc: find lo
09-19 17:21:44.770 1567-1604/system_process D/WifiHW: check_wifi_ifname_from_proc: find rmnet0
09-19 17:21:44.770 1567-1604/system_process D/WifiHW: check_wifi_ifname_from_proc: find sit0
09-19 17:21:44.770 1567-1604/system_process D/WifiHW: check_wifi_ifname_from_proc: find ip6tnl0
09-19 17:21:44.770 1567-1604/system_process D/WifiHW: check_wifi_ifname_from_proc: find wlan0
09-19 17:21:44.770 1567-1604/system_process D/WifiHW: check_wifi_ifname_from_proc: find p2p0
09-19 17:21:44.795 2458-2458/? I/wpa_supplicant: define REALTEK_WIFI_VENDOR
09-19 17:21:44.810 1567-1604/system_process D/WifiMonitor: startMonitoring(wlan0) with mConnected = false
09-19 17:21:44.820 1567-1604/system_process E/WifiHW: Unable to open connection to supplicant on "/data/misc/wifi/sockets/wlan0": No such file or directory
09-19 17:21:45.815 1567-1604/system_process E/WifiHW: Unable to open connection to supplicant on "/data/misc/wifi/sockets/wlan0": No such file or directory
09-19 17:21:46.825 1567-1604/system_process D/WifiConfigStore: Loading config and enabling all networks
09-19 17:21:46.830 1567-1604/system_process E/WifiConfigStore: Error parsing configurationjava.io.FileNotFoundException: /data/misc/wifi/ipconfig.txt: open failed: ENOENT (No such file or directory)
09-19 17:21:46.845 1567-1604/system_process E/WifiStateMachine: Failed to set device name smdk4x12
09-19 17:21:46.850 1567-1604/system_process E/WifiStateMachine: Failed to set manufacturer SMDK4X12 by TOPEET (www.topeetboard.com)
09-19 17:21:46.850 1567-1604/system_process E/WifiStateMachine: Failed to set model name Android On SMDK4X12
09-19 17:21:46.850 1567-1604/system_process E/WifiStateMachine: Failed to set model number Android On SMDK4X12
09-19 17:21:46.855 1567-1604/system_process E/WifiStateMachine: Failed to set serial number
09-19 17:21:46.855 1567-1604/system_process E/WifiStateMachine: Failed to set WPS config methods
09-19 17:21:46.860 1567-1604/system_process E/WifiStateMachine: Failed to set primary device type 10-0050F204-5
09-19 17:21:46.875 1567-1603/system_process D/WifiMonitor: startMonitoring(p2p0) with mConnected = true
09-19 17:21:46.885 1567-1604/system_process E/WifiStateMachine: Failed to set frequency band 0
09-19 17:21:46.895 1567-1603/system_process E/WifiP2pService: Unexpected loss of p2p socket connection
可是你即使一次又一次确认目录“/data/misc/wifi/sockets/wlan0”下是有wlan0,文件夹的目录属性及用户组都很正常,可是安卓系统就是找不到wlan0,这是一个很令人抓狂的问题。最后通过谷歌找到老外的说明,说是如果新建了
/data/system/wpa_supplicant
这个目录,会导致wpa_supplicant功能失效,因为hardware/libhardware_legacy/wifi/wifi.c 会检测是否存在目录“/data/system/wpa_supplicant”,如果有则会传递一个错误的参数给函数“wpa_ctrl_open()”,一般unix系统才需要目录“/data/system/wpa_supplicant”,安卓系统千万不要新建这个目录。
最后谨记wifi驱动和相关的系统文件目录的用户组都必须是wifi,且必须是可读可写,不然的话在加载驱动或者开启wifi的时候会出现莫名其妙的问题。
3.如何调试wifi驱动
(1)通过安装驱动后查看系统文件,如果系统文件有驱动和设备都齐全则代表驱动安装成功,且linux可以根据设备加载对应的驱动。下面有sdio和usb两种接口的wifi模块,它在linux上有不同的表现。
下面是sdio接口:
下面的USB接口:
(2)通过各种命令查看linux下的网络信息来验证wifi模块是否正常驱动
第一个是netcfg命令,它可以查看当前网络哪些网络设备是否开启,ip地址是否分配
root@smdk4x12:/system/lib/modules # netcfg
lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
rmnet0 DOWN 0.0.0.0/0 0x00001002 4e:c0:15:04:86:ea
sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
ip6tnl0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
wlan0 UP 192.168.16.62/24 0x00001043 54:c9:df:ca:a0:bc
p2p0 UP 0.0.0.0/0 0x00001003 56:c9:df:ca:a0:bc
第二个命令是iwconfig, 它可以查看网络设备的详细信息。
root@smdk4x12:/system/lib/modules # iwconfig
rmnet0 no wireless extensions.
sit0 no wireless extensions.
ip6tnl0 no wireless extensions.
wlan0 IEEE 802.11bgn ESSID:"\xE9\xAA\x8A\xE5\xBA\xAD\xE6\x99\xBA\xE8\x83\xBD\xE5\xAE\xB6\xE5\xB1\x85\xE4\xBA\x8C\xE6\xA5\xBC" Nickname:"<WIFI@REALTEK>"
Mode:Managed Frequency:2.452 GHz Access Point: D4:EE:07:40:5C:EA
Bit Rate:150 Mb/s Sensitivity:0/0
Retry:off RTS thr:off Fragment thr:off
Encryption key:****-****-****-****-****-****-****-**** Security mode:open
Power Management:off
Link Quality=99/100 Signal level=-67 dBm Noise level=0 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
p2p0 unassociated Nickname:"<WIFI@REALTEK>"
Mode:Managed Frequency=2.412 GHz Access Point: Not-Associated
Sensitivity:0/0
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/100 Signal level=0 dBm Noise level=0 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
第三个命令是iwlist,这个命令可以扫描wifi设备,如果wifi模块正常的话是可以扫描到路由器的ssid
iwlist wlan0 scan
(3)通过查看安卓系统输出的logcat信息和linux调试串口的信息可以知道驱动或者设备是否正常工作。
(4)iwlist iwconfig iwpriv 这三个命令可以在安卓源码中生成
<1>tar zxvf wireless_tools.30.rtl.tar.gz
<2>cp wireless_tools.30.rtl <ANDROID_SDK>/external/
<3>cd <ANDROID_SDK>
<4>make iwconfig iwlist iwpriv
或者在“device/softwinner/tulip-t1/tulip_t1.mk”文件中添加相关编译选项
PRODUCT_PACKAGES += \
iwconfig \
iwlist \
iwpriv