rtl8188eus Linux驱动移植
rlt8188eus作为无线USB网卡,可以给我们的Linux设备提供无线上网能力,也能配置为AP,给其它无线设备提供上网能力。在使用较低版本的内核时,内核中不含rtl8188eus
驱动,因此尝试自己移植,这里记录移植过程和遇到的问题。
1. 下载源码
直接google搜索rtl8188eus github
,能够搜索出来非常多的rtl8188eu
相关的仓库。找到start和fork数量最多的仓库,下载其源码。
也尝试过其它的仓库
,编译出来的驱动在连接Wi-Fi时会报警告,导致连接不上wifi,日志如下:
RTW: <=== rtw_ips_pwr_up.............. in 780ms
RTW: nolinked power save leave
RTW: ==> ips_leave.....LED(0x00028282)...
RTW: SetHwReg8188E:(HW_VAR_CHECK_TXBUF)TXBUF Empty(1) in 0 ms
RTW: survey done event(33) band:0 for wlan0
RTW: rtw_indicate_scan_done(wlan0)
RTW: ==>rtw_ps_processor .fw_state(8)
RTW: ==>ips_enter cnts:19
RTW: nolinked power save enter
RTW: ===> rtw_ips_pwr_down...................
RTW: ====> rtw_ips_dev_unload...
RTW: usb_read_port_cancel
RTW: usb_read_port_complete() RX Warning! bDriverStopped(False) OR bSurpriseRemoved(False)
RTW: usb_read_port_complete() RX Warning! bDriverStopped(False) OR bSurpriseRemoved(False)
RTW: usb_read_port_complete() RX Warning! bDriverStopped(False) OR bSurpriseRemoved(False)
RTW: usb_read_port_complete() RX Warning! bDriverStopped(False) OR bSurpriseRemoved(False)
RTW: usb_read_port_complete() RX Warning! bDriverStopped(False) OR bSurpriseRemoved(False)
RTW: usb_read_port_complete() RX Warning! bDriverStopped(False) OR bSurpriseRemoved(False)
RTW: usb_read_port_complete() RX Warning! bDriverStopped(False) OR bSurpriseRemoved(False)
RTW: usb_read_port_complete() RX Warning! bDriverStopped(False) OR bSurpriseRemoved(False)
RTW: usb_write_port_cancel
RTW: ==> rtl8188eu_hal_deinit
RTW: bkeepfwalive(0)
RTW: SetHwReg: bMacPwrCtrlOn=0
RTW: <=== rtw_ips_pwr_down..................... in 130ms
后面尝试使用截图内容的仓库,就没有问题了。并且这个仓库是带固件的,在使用无限网卡时,需要用到这个固件。
2. 编译驱动
编译驱动前,需要在内核中配置这个驱动依赖的模块,否则会在编译时报警告,一些符号未定义。其中这些符号就是该驱动依赖的内核模块。在不配置相关依赖的情况下,编译好的驱动在装载时,会报和编译时一样的错误,导致装载失败。因此如果编译时报警告了,根据相关符号找到内核中的模块,勾选上,并重新编译内核。
2.1 内核配置
我这里使用的内核版本是3.4
,默认配置了两个与该模块相关的驱动。这里将它们勾选为编译进内核中。
配置支持WI-FI设备
模块路径:
│ Location:
│ -> Device Drivers
│ -> Network device support (NETDEVICES [=y])
│ -> Wireless LAN (WLAN [=y])
配置如下:
可以看到内核中有 rtl8188cu
的驱动,但是没有 rtl8188eus
的。
配置支持IEEE 802.11
模块路径:
│ Location:
│ -> Networking support (NET [=y])
│ -> Wireless (WIRELESS [=y])
配置如下:
这里也是讲这些勾选为编译进内核中。
解决编译问题
完成上述配置后,编译还是会报一个警告:
LD [M] /media/data/library/temp/rtl8188eus/8188eu.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "__aeabi_unwind_cpp_pr1" [/media/data/library/temp/rtl8188eus/8188eu.ko] undefined!
WARNING: "__aeabi_unwind_cpp_pr0" [/media/data/library/temp/rtl8188eus/8188eu.ko] undefined!
CC /media/data/library/temp/rtl8188eus/8188eu.mod.o
LD [M] /media/data/library/temp/rtl8188eus/8188eu.ko
make[1]: Leaving directory '/media/data/workspace/buildroot-2022.02.8/output/build/linux-3.4.y'
如果不解决这个警告,在insmod模块时,就会因为找到不到这两个符号导致报错。位置在Kernel hacking
下面:
2.2 交叉编译环境配置
由于是要运行在我的Hisi板子上,因此需要交叉编译。我这里使用交叉编译工具链是Buildroot下载生成的,内核使用的时候Hi SDK中的 3.4
内核。
为什么前面要在内核中配置驱动呢?如果完成所有必须驱动的配置,那么编译过程将不会有任何警告。猜测,这里的Makefile其实会去读内核中的配置。
因为要反复的测试编译,我这里写了一个脚本set_env.sh
来配置交叉编译环境,主要就是配置环境变量。
#!/bin/bash
export USER_EXTRA_CFLAGS=-fno-exceptions
export ARCH=arm
export CROSS_COMPILE=/media/data/workspace/buildroot-2022.02.8/output/host/opt/ext-toolchain/bin/arm-none-linux-gnueabi-
export KVER=3.4.35
export KSRC="/media/data/workspace/buildroot-2022.02.8/output/build/linux-3.4.y"
cd $(pwd)
sed -i 's\KSRC := /lib/modules/$(KVER)/build\KSRC ?= /lib/modules/$(KVER)/build\g' Makefile
注意这里需要修改Makefile中SRC变量配置,因为有默认配置,自己设置的参数会被覆盖不起作用,因此将Makefile中的都改成?=
,防止KSRC参数被覆盖。因为我开始设置了这个参数,在编译时,怎么都不生效,在Makefile中的最后面的位置加入这个参数才生效,后来就发现是被默认配置给覆盖了。
进入到源码目录执行这个脚本,一定要用source
执行,否则全局变量不会生效。
source ../set_env.sh
2.3 编译
执行:
make -j12
编译成功:
make ARCH=arm CROSS_COMPILE=/media/data/workspace/buildroot-2022.02.8/output/host/opt/ext-toolchain/bin/arm-none-linux-gnueabi- -C /media/data/workspace/buildroot-2022.02.8/output/build/linux-3.4.y M=/media/data/library/temp/rtl8188eu modules
make[1]: Entering directory '/media/data/workspace/buildroot-2022.02.8/output/build/linux-3.4.y'
CC [M] /media/data/library/temp/rtl8188eu/core/rtw_ioctl_set.o
CC [M] /media/data/library/temp/rtl8188eu/core/rtw_iol.o
CC [M] /media/data/library/temp/rtl8188eu/core/rtw_led.o
CC [M] /media/data/library/temp/rtl8188eu/core/rtw_mlme.o
.......................
CC [M] /media/data/library/temp/rtl8188eu/os_dep/usb_ops_linux.o
CC [M] /media/data/library/temp/rtl8188eu/os_dep/xmit_linux.o
LD [M] /media/data/library/temp/rtl8188eu/8188eu.o
Building modules, stage 2.
MODPOST 1 modules
CC /media/data/library/temp/rtl8188eu/8188eu.mod.o
LD [M] /media/data/library/temp/rtl8188eu/8188eu.ko
make[1]: Leaving directory '/media/data/workspace/buildroot-2022.02.8/output/build/linux-3.4.y'
3. 测试
烧录重新编译的内核。将8188eu.ko
和rtl8188eufw.bin
复制到开发板上。
8188eu.ko
存放路径:
/lib/module/$(uname -r)
rtl8188eufw.bin
存放路径:
/lib/firmware/rtlwifi
装载驱动:
# modprobe 8188eu
Chip Version Info: CHIP_8188E_Normal_Chip_TSMC_D_CUT_1T1R_RomVer(0)
EEPROM ID = 0x8129
usbcore: registered new interface driver r8188eu
# R8188EU: Firmware Version 11, SubVersion 1, Signature 0x88e1
MAC Address = e0:e1:a9:97:49:90
ioctl[SIOCSIWAP]: Operation not permitted
wlan0: Trying to associate with 80:ea:07:0e:2f:7d (SSID='Duapple_AP' freq=2437 MHz)
wlan0: Association request to the driver failed
R8188EU: INFO assoc success
wlan0: Associated with 80:ea:07:0e:2f:7d
wlan0: WPA: Key negotiation completed with 80:ea:07:0e:2f:7d [PTK=CCMP GTK=CCMP]
wlan0: CTRL-EVENT-CONNECTED - Connection to 80:ea:07:0e:2f:7d completed [id=0 id_str=]
出现最前面的4行日志,说明驱动已经加载成功,并且识别到USB无线网卡。后面是我提前配置好了wpa_supplicant,因此,只要wlan0出来了,就能够自动连接上Wi-Fi。
默认是没有dhcp获取IP地址的,这里手动执行dhcp来获取路由器分配的IP:
# udhcpc -i wlan0
udhcpc: started, v1.35.0
udhcpc: broadcasting discover
udhcpc: broadcasting select for 192.168.0.104, server 192.168.0.1
udhcpc: lease of 192.168.0.104 obtained from 192.168.0.1, lease time 7200
deleting routers
adding dns 192.168.1.1
adding dns 192.168.0.1
配置DNS服务器,并测试网络:
# echo "nameserver 8.8.8.8" > /etc/resolv.conf
# ping baidu.com
PING baidu.com (39.156.66.10): 56 data bytes
64 bytes from 39.156.66.10: seq=0 ttl=51 time=100.215 ms
64 bytes from 39.156.66.10: seq=1 ttl=51 time=111.678 ms
64 bytes from 39.156.66.10: seq=2 ttl=51 time=125.347 ms
64 bytes from 39.156.66.10: seq=3 ttl=51 time=140.730 ms
^C
--- baidu.com ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 100.215/119.492/140.730 ms
如果网络不通,请检查路由表是否设置wlan0为默认路由。没有设置使用ip route
完成配置。
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 wlan0
0.0.0.0 0.0.0.0 0.0.0.0 U 1001002 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1005 0 0 wlan0
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 wlan0
192.168.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
4. 集成到内核
由于每次烧录根文件系统都要重新加入这个驱动,因此考虑将其集成到内核中,直接将其编译进内核或者和打包到Buildroot中。
我这里使用了Buildroot来构建根文件系统,因此也可以直接将上面的驱动和固件放到output/target
目录下,对应的位置。这样也能将驱动和固件直接打包到根文件系统中。
未完…
更新:2023-11-08
buildroot中支持了这个模块的驱动,因此可以直接使用buildroot中的驱动。
编译后:
# pwd
/lib/modules/3.4.35
# ls extra/
8188eu.ko
开机会默认加载驱动,生成wlan0。
需要注意的是,当将8188eu驱动加入编译后,可能会忘记在kernel中打开相应的驱动支持。这个时候再去添加kernel中需要的驱动,会导致8188eu驱动不会重新编译,这是使用buildroot需要注意的地方,有些模块不会导致重新编译,进而无法实现一些功能。
比如我的驱动配置的没有问题,但是启动,就是会报错。如下:
这个时候,只需要把 output/build/rt8188eu*********
编译目录删掉,重新编译即可。再启动,则不会报出这个错误。