[原创] EDIMAX N150 EW-7611ULB蓝牙/wifi驱动移植及调试
1. 简介
- 蓝牙/wifi二合一模块
- 模块型号:
EDIMAX N150 EW-7611ULB
- 购买链接
- 适配平台:
树莓派CM4
2. 获取驱动源码
- 购买时随包装附赠一保存驱动源码和文档的光盘
3. 蓝牙驱动移植
3.1 驱动源码路径
Linux -> Linux_BT_USB_v3.1_20150526_8723BU_BTCOEX_20150119-5844_Edimax
-> Linux_BT_USB_v3.1_20150526_8723BU_BTCOEX_20150119-5844_Edimax
3.2 修改Makefile
- 蓝牙驱动的源码放在两个目录中
8723BU
和bluetooth_usb_driver
, 共有三个Makefile
文件需要修改:顶层Makefile
+8723BU/Makefile
+bluetooth_usb_driver/Makefile
- 跨平台移植驱动,需要交叉编译,交叉编译使用的Linux内核源码版本为
5.4.83
- 务必首先阅读
Readme.txt
- 修改
顶层Makefile
如下:
SRC_DIR := ./bluetooth_usb_driver
# 内核源码目录
MDL_DIR := /home/jun/share/work/mptcp/arm/linux_build
# 编译完成后的驱动保存目录
DRV_DIR := ./driver
FIRMWARE_DIR := 8723BU
##########################################
install:
make -C $(FIRMWARE_DIR) -s
- rm $(DRV_DIR)/*.ko
mkdir -p $(DRV_DIR)
make -C $(SRC_DIR) -s
cp -f $(SRC_DIR)/rtk_btusb.ko $(DRV_DIR)/rtk_btusb.ko
make -C $(SRC_DIR) clean -s
echo "compile rtk_btusb success!"
##########################################
uninstall:
make -C $(FIRMWARE_DIR) clean -s
rm -f $(DRV_DIR)/rtk_btusb.ko
echo "rm rtk_btusb.ko success!"
##########################################
- 修改
8723BU/Makefile
如下:
# 编译完成后驱动保存目录
FW_DIR := ../driver
FW_NAME := rtl8723b_fw
CF_NAME := rtl8723bu_config
all:
@echo "Copy RTL8723BU fw/config to $(FW_DIR)"
mkdir -p $(FW_DIR)/$(FW_NAME)
mkdir -p $(FW_DIR)/$(CF_NAME)
cp -f $(FW_NAME) $(FW_DIR)/$(FW_NAME)
cp -f $(CF_NAME) $(FW_DIR)/$(CF_NAME)
clean:
rm -f $(FW_DIR)/$(FW_NAME)
rm -f $(FW_DIR)/$(CF_NAME)
- 修改
bluetooth_usb_driver/Makefile
如下:
# 交叉编译目标平台
ARCH := arm
# 交叉编译工具
CROSS_COMPILE := aarch64-linux-gnu-
# 编译完成后驱动保存目录
BUILD_DIR := ../driver
ifneq ($(KERNELRELEASE),)
obj-m := rtk_btusb.o
rtk_btusb-y = rtk_coex.o rtk_bt.o
else
PWD := $(shell pwd)
# 内核源码保存目录
KDIR := /home/jun/share/work/mptcp/arm/linux_build
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules -s
cp *.ko $(BUILD_DIR)
clean:
rm -rf *.o *.mod.c *.mod.o *.ko *.symvers *.order *.a
endif
3.3 编译
make install
3.4 编译错误解决
3.4.1 错误一:struct hci_ctrl
类型不匹配
/bluetooth_usb_driver/rtk_coex.c:452:18: error: ‘struct hci_ctrl’ has no member named ‘req_start’; did you mean ‘req_flags’?
错误原因:
-
在
5.4.83
及较新版本的内核中,struct hci_crtl
的定义发生了变化struct hci_ctrl { u16 opcode; u8 req_flags; u8 req_event; union { hci_req_complete_t req_complete; hci_req_complete_skb_t req_complete_skb; }; };
-
旧的
req_start
功能由req_flags
替代,设置方法如下bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
解决方法:
- 将
rtk_corx.c
第452行中的bt_cb(skb)->hci.req_start = true;
修改为bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
3.4.2 错误二:setup_timer
未声明
bluetooth_usb_driver/rtk_coex.c:537:3: error: implicit declaration of function ‘setup_timer’; did you mean ‘sk_stop_timer’? [-Werror=implicit-function-declaration]
错误原因:
5.4.83
版本内核相较于旧版本的内核,将setup_timer
替换为了timer_setup
解决方法:
- 将驱动源码中的所有
setup_timer
函数都替换为timer_setup
3.4.3 错误三:timer_setup
参数类型不匹配
timer.h:125:27: error: passing argument 2 of ‘init_timer_key’ from incompatible pointer type [-Werror=incompatible-pointer-types]
init_timer_key((_timer), (_fn), (_flags), NULL, NULL)
错误原因:
-
在
5.4.83
版本内核中timer_setup
声明如下:void init_timer_key(struct timer_list *timer, void (*func)(struct timer_list *), unsigned int flags, const char *name, struct lock_class_key *key); #define __init_timer(_timer, _fn, _flags) \ init_timer_key((_timer), (_fn), (_flags), NULL, NULL) #define timer_setup(timer, callback, flags) \ __init_timer((timer), (callback), (flags))
-
可见
timer_setup
的第二个参数为void (*func)(struct timer_list *)
的回调函数指针 -
而在蓝牙驱动源码中,
timer_setup
的第二个参数为void (*func)(unsigned long)
类型函数指针
解决方法:
-
对驱动源码中所有
timer_setup
函数的第二个参数进行强制类型转换 -
在
bluetooth_usb_driver/rtk_coex.h
中添加如下声明typedef void (*p_func)(struct timer_list *);
-
在
timer_setup
函数中添加强制类型转换,示例如下:timer_setup(&(btrtl_coex.a2dp_count_timer),(p_func)count_a2dp_packet_timeout, 0);
3.4.4 错误四:struct usb_interface
中没有成员pm_usage_cnt
bluetooth_usb_driver/rtk_bt.c:720:29: error: ‘struct usb_interface’ has no member named ‘pm_usage_cnt’
atomic_read(&(data->intf->pm_usage_cnt)));
错误原因:
-
5.4.83
版本内核中struct usb_interface
声明如下, 确实没有成员pm_usage_cnt
struct usb_interface { struct usb_host_interface *altsetting; struct usb_host_interface *cur_altsetting; unsigned num_altsetting; struct usb_interface_assoc_descriptor *intf_assoc; int minor; enum usb_interface_condition condition; unsigned sysfs_files_created:1; unsigned ep_devs_created:1; unsigned unregistering:1; unsigned needs_remote_wakeup:1; unsigned needs_altsetting0:1; unsigned needs_binding:1; unsigned resetting_device:1; unsigned authorized:1; struct device dev; struct device *usb_dev; struct work_struct reset_ws; };
解决方法:
- 阅读驱动源码发现,所有使用
pm_usage_cnt
成员的地方都是DEBUG日志打印,并不会影响程序运行,如下
- 既然不会影响程序运行,将相关日志输出全部注释得了,修改
rtk_bt.c
如下:
3.5 重新编译
make install
- 编译完成后,会在顶层目录中生成一个
driver
目录,编译好的驱动rtk_btusb.ko
就保存在这个目录下
3.6 安装驱动
-
安装
rtk_btusb.ko
# insmod rtk_btusb.ko
-
查看
dmesg
日志# dmesg [ 82.735104] rtk_btusb: Realtek Bluetooth USB driver ver 3.1 [ 82.735118] rtk_btcoex: rtk_btcoex_init: version: 1.2 [ 82.735125] rtk_btcoex: create workqueue [ 82.735630] rtk_btcoex: alloc buffers 1792, 2432 for ev and l2 [ 82.735832] usbcore: registered new interface driver rtk_btusb
-
hciconfig
查看蓝牙设备
3.7 使用蓝牙播放音乐
-
参考链接
https://wiretuts.com/connecting-bluetooth-audio-device-to-raspberry-pi (必看)
-
安装相关工具
sudo apt-get install pulseaudio pulseaudio-utils pulseaudio-module-bluetooth 或 sudo apt-get install pulseaudio*
-
修改
/lib/systemd/system/bluetooth.service
文件,在ExecStart
配置中增加参数-C
-
添加用户
pi
到组lp
sudo usermod -a -G lp pi
-
重启
reboot
-
启动
pulseaudio
进程, 最好在串口终端中执行此命令,否则可能会因为X11 forwarding
的问题导致执行失败sudo pulseaudio --start
- 查看
bluetoothd
进程是否存在,必须先启动该进程,才能通过bluetoothctl
命令对蓝牙进行控制
-
使用
bluetoothctl
命令连接蓝牙scan on
扫描蓝牙设备pair
和指定的蓝牙设备进行配对connect
和配对成功的蓝牙设备进行连接
-
命令行播放音乐
-
参考链接
-
安装
sox
和libsox-fmt-all
$ sudo apt-get install sox $ sudo apt-get install sox libsox-fmt-all
-
播放音乐, 测试成功(默认是最大音量播放,小心!!!耳朵都震聋鸟!!!)
# play music.mp3 music.mp3: File Size: 8.06M Bit Rate: 327k Encoding: MPEG audio Channels: 2 @ 16-bit Track: 2 Samplerate: 44100Hz Album: 吉他之路 Replaygain: off Artist: 王坚 Duration: 00:03:17.26 Title: 天空之城(木吉他版) In:16.2% 00:00:31.95 [00:02:45.31] Out:1.41M [ =====|====- ] Hd:2.3 Clip:0
-
4. WIFI驱动移植
4.1 相关资料路径
-
务必阅读
readme.txt
-
务必阅读
document
目录下的相关文档 -
官方驱动暂不支持
3.19.3
版本以上的内核,并且驱动移植工作量太大了,github
上有大佬已经移植好的驱动,直接使用github
上的源码吧,但是可以阅读官方的文档,学习一下如何配置wifi -
github
项目链接
4.2 wifi驱动编译
- 注意:使用的是github上的驱动源码,并不是该模块官方的驱动源码
4.2.1 下载并解压
$ unzip rtl8723bu-master.zip
$ cd rtl8723bu-master/
4.2.2 修改Makefile
-
在
Platform Related
中添加一新的平台arm64
,并将其它的平台都设置为n
CONFIG_PLATFORM_ARM64 = y
-
添加
arm64
平台交叉编译相关配置ifeq ($(CONFIG_PLATFORM_ARM64), y) EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 EXTRA_CFLAGS += -DRTW_USE_CFG80211_STA_EVENT # only enable when kernel >= 3.2 EXTRA_CFLAGS += -DCONFIG_P2P_IPS ARCH := arm64 CROSS_COMPILE := /usr/arm/CodeSourcery/aarch64-linux-gnu/bin/aarch64-linux-gnu- KSRC := /home/jun/share/work/mptcp_kernel/ig10/linux_build_5.4_raspios_mptcp endif
4.2.3 编译
make
编译
$ make
- 编译完成后会生成一个驱动文件
8723bu.ko
4.2.4 安装驱动
-
将
8723bu.ko
拷贝到目标主机中,insmod
安装# insmod 8723bu.ko
-
接入wifi模块,使用
lsusb
查看
-
ifconfig
查看,(为什么有两个wlan ???)
4.2.5 启用2.4G AP
-
编写
hostapd.conf
如下interface=wlan0 ctrl_interface=/var/run/hostapd country_code=CN ssid=TEST # 名称 wpa=0 # 不加密 wpa_passphrase=12345678 driver=nl80211 bridge=br0 beacon_int=100 hw_mode=g channel=6 ieee80211n=1 wme_enabled=1 wpa_key_mgmt=WPA-PSK wpa_pairwise=CCMP max_num_sta=8 wpa_group_rekey=86400 ignore_broadcast_ssid=0
-
启动
hostapd
进程# hostapd ./hostapd.conf
-
使用手机连接,能够连接成功,但是无法获取IP,因为我们还没有给AP配置
dhcp server
-
配置
dhcp server
和 路由后,测速效果如下:(上行竟然比下行还好?)
4.2.6 启用5G AP
- 该模组不支持5G频段
4.2.7 启用Station Mode
模式
- 该模组不支持
Station Mode
模式
【本人原创文章,转载请注明出处!!!】
【禁止转载到CSDN !!!】