今日在筆記本電腦ThinkBook 14 IML接入TP-LINK的TL-WDN7200H AC 1900雙頻高增益無線USB網卡,支持2.4GHz 600Mbps+5GHz 1300Mbps。
Windows10是免安裝驅動直接可以支持的。但在CentOS Linux 8系統卻遇到了麻煩,並無相關驅動支持,無法使用。
查看當前內核版本:
[root@centos ~]# uname -a
Linux centos 4.18.0-147.6.el8.x86_64 #1 SMP Tue Oct 15 15:19:32 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
注意:要記住版本號4.18.0,稍後編譯時修改代碼要用。
尋思想通過自行編譯驅動來解決,先要找到芯片廠商型號。
列出USB:
[root@centos ~]# lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 5986:2113 Acer, Inc
Bus 001 Device 004: ID 27c6:55a4
Bus 001 Device 003: ID 18f8:1286 [Maxxter]
Bus 001 Device 002: ID 2357:0106 TP-Link
Bus 001 Device 006: ID 8087:0aaa Intel Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
看到Bus 001 Device 002: ID 2357:0106 TP-Link,提取ID 2357:0106,查找信息得知是無線USB網卡芯片廠商是realtek,型號是8814au。
在github找到Realtek 8814AU USB WiFi driver,下載編譯。
注意:要找到這個版本rtl8814au v4.3.21_17997.20160531,不要找最新版本。
編譯出現第一個錯誤:
/tmp/rtl8814au/os_dep/linux/os_intfs.c:914:22: error: initialization of ‘u16 (*)(struct net_device *, struct sk_buff *, struct net_device *, u16 (*)(struct net_device *, struct sk_buff *, struct net_device *))’ {aka ‘short unsigned int (*)(struct net_device *, struct sk_buff *, struct net_device *, short unsigned int (*)(struct net_device *, struct sk_buff *, struct net_device *))’} from incompatible pointer type ‘u16 (*)(struct net_device *, struct sk_buff *, void *, u16 (*)(struct net_device *, struct sk_buff *, struct net_device *))’ {aka ‘short unsigned int (*)(struct net_device *, struct sk_buff *, void *, short unsigned int (*)(struct net_device *, struct sk_buff *, struct net_device *))’} [-Werror=incompatible-pointer-types]
.ndo_select_queue = rtw_select_queue,
^~~~~~~~~~~~~~~~
/tmp/rtl8814au/os_dep/linux/os_intfs.c:914:22: note: (near initialization for ‘rtw_netdev_ops.ndo_select_queue’)
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:313: /tmp/rtl8814au/os_dep/linux/os_intfs.o] Error 1
make[1]: *** [Makefile:1547: _module_/tmp/rtl8814au] Error 2
make[1]: Leaving directory '/usr/src/kernels/4.18.0-147.6.el8.x86_64'
make: *** [Makefile:1699: modules] Error 2
打開rtl8814au目錄下os_dep/linux/os_intfs.c文件,定位到rtw_select_queue函數:
static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
, void *accel_priv
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
, select_queue_fallback_t fallback
#endif
#endif
)
改成如下即可:
static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
, struct net_device *sb_dev
#else
, void *accel_priv
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) & LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
, select_queue_fallback_t fallback
#endif
#endif
)
繼續編譯發現第二個錯誤:
/tmp/rtl8814au/os_dep/linux/rtw_android.c: In function ‘rtw_android_priv_cmd’:
/tmp/rtl8814au/os_dep/linux/rtw_android.c:615:62: error: macro "access_ok" passed 3 arguments, but takes just 2
if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
^
/tmp/rtl8814au/os_dep/linux/rtw_android.c:615:7: error: ‘access_ok’ undeclared (first use in this function)
if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
^~~~~~~~~
/tmp/rtl8814au/os_dep/linux/rtw_android.c:615:7: note: each undeclared identifier is reported only once for each function it appears in
make[2]: *** [scripts/Makefile.build:313: /tmp/rtl8814au/os_dep/linux/rtw_android.o] Error 1
make[1]: *** [Makefile:1547: _module_/tmp/rtl8814au] Error 2
make[1]: Leaving directory '/usr/src/kernels/4.18.0-147.6.el8.x86_64'
make: *** [Makefile:1699: modules] Error 2
打開rtl8814au目錄下os_dep/linux/rtw_android.c文件,定位到rtw_android_priv_cmd函數:
if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
改成如下即可:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
if (!access_ok(priv_cmd.buf, priv_cmd.total_len)) {
#else
if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {
#endif
繼續編譯正常通過了!
最後可看到已經生成8814au.ko:
LD [M] /tmp/rtl8814au/8814au.o
Building modules, stage 2.
MODPOST 1 modules
CC /tmp/rtl8814au/8814au.mod.o
LD [M] /tmp/rtl8814au/8814au.ko
make[1]: Leaving directory '/usr/src/kernels/4.18.0-147.6.el8.x86_64'
安裝後使用加載模塊:
modprobe 8814au
cat /proc/kmsg可看到:
<4>[19967.549960] RTL871X: module init start
<4>[19967.549961] RTL871X: rtl8814au v4.3.21_17997.20160531
<4>[19967.671171] RTL871X: rtw_ndev_init(wlan0) if1 mac_addr=08:1f:71:24:64:8a
<6>[19967.671505] usbcore: registered new interface driver rtl8814au
<4>[19967.671507] RTL871X: module init ret=0
<6>[19967.682791] rtl8814au 1-3:1.0 wlp0s20f0u3: renamed from wlan0
<6>[19967.697724] IPv6: ADDRCONF(NETDEV_UP): wlp0s20f0u3: link is not ready
<6>[19968.104292] IPv6: ADDRCONF(NETDEV_UP): wlp0s20f0u3: link is not ready
<6>[19968.106996] IPv6: ADDRCONF(NETDEV_UP): wlp0s20f0u3: link is not ready
<6>[19968.121708] IPv6: ADDRCONF(NETDEV_UP): wlp0s20f0u3: link is not ready
<4>[19971.176837] RTL871X: nolinked power save enter
<6>[19971.191472] IPv6: ADDRCONF(NETDEV_UP): wlp0s20f0u3: link is not ready
<4>[19971.617442] RTL871X: nolinked power save leave
<4>[19974.653364] RTL871X: rtw_set_802_11_connect(wlp0s20f0u3) fw_state=0x00000008
<4>[19974.859910] RTL871X: start auth
<4>[19974.862100] RTL871X: auth success, start assoc
<4>[19974.880289] RTL871X: rtw_cfg80211_indicate_connect(wlp0s20f0u3) BSS not found !!
<4>[19974.880316] RTL871X: assoc success
<4>[19975.010392] RTL871X: recv eapol packet
<4>[19975.010619] RTL871X: send eapol packet
<4>[19975.013448] RTL871X: recv eapol packet
<4>[19975.013527] RTL871X: send eapol packet
<4>[19975.013596] RTL871X: set pairwise key camid:4, addr:74:05:a5:01:23:45, kid:0, type:AES
<6>[19975.013730] IPv6: ADDRCONF(NETDEV_CHANGE): wlp0s20f0u3: link becomes ready
<4>[19975.014452] RTL871X: set group key camid:5, addr:74:05:a5:01:23:45, kid:2, type:AES
已經可以正常連接到WIFI上網了!
注:本文爲Toyo Lau原創,未經許可不得在任何平臺轉載。如需轉載,與作者聯繫~ 如果對linux學習中遇到疑問,可以直接加linux交流QQ羣734638086,或關注微信公衆號:技術訓練營(微信ID:TechBootcamp),獲取更多資訊~