rtl8821ce linux驱动 内核,RTL8821CE 无线网卡/蓝牙驱动的编译 Linux Kernel 5.0.0-20

RTL8821CE 在Linux Kernel 5.0 上并没有相关驱动,蓝牙设备虽可以识别但无法使用,而WiFi设备都不能识别出来。

在搜索引擎中搜索一番,找到了一个可行的回答,但是这个回答是2017年给出的,有些过时了。但是基本思路还是不变的,只要稍作修改就可成功编译驱动程序。

从 chili555 的回答中给出的下载链接下载驱动源代码压缩包(所在项目还在继续开发,本文使用的是2019年8月初下载的源代码)。

按照 chili555给出的步骤操作,在执行make命令前,要修改一下Makefile.mk和rtl8821ce.mk两个文件内的路径配置,只要把文件内的所有$(srctree)/删去就行了。

示例(行首的-表示修改前的代码,+表示修改后的代码。):

-EXTRA_CFLAGS += -I$(srctree)/$(src)/platform

+EXTRA_CFLAGS += -I$(src)/platform

_PLATFORM_FILES := platform/platform_ops.o

-EXTRA_CFLAGS += -I$(srctree)/$(src)/hal/btc

+EXTRA_CFLAGS += -I$(src)/hal/btc

编译时出现了以下错误,错误原因是函数签名不符。

注意:这里的os_intfs.c文件是我修改过的,出错的1470行对应于原始文件中的1467行。

CC [M] /home/name/nv/rtl8821ce/os_dep/linux/os_intfs.o

/home/name/nv/rtl8821ce/os_dep/linux/os_intfs.c:1470:22: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]

.ndo_select_queue = rtw_select_queue,

^~~~~~~~~~~~~~~~

/home/name/nv/rtl8821ce/os_dep/linux/os_intfs.c:1470:22: note: (near initialization for ‘rtw_netdev_ops.ndo_select_queue’)

cc1: some warnings being treated as errors

在源代码中找到出错代码所在的结构体名称net_device_ops。

//rtl8821ce/os_dep/linux/os_intfs.c:1459

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))

static const struct net_device_ops rtw_netdev_ops = {

//...

.ndo_start_xmit = rtw_xmit_entry,

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))

.ndo_select_queue= rtw_select_queue, //error: initialization from incompatible pointer type

#endif

.ndo_set_mac_address = rtw_net_set_mac_address,

//...

};

#endif

在搜索引擎搜索一番后找到了net_device_ops的声明,在头文件netdevice.h中。

发现两函数的函数签名不一致,os_intfs.c中的函数实现少了第四个形参select_queue_fallback_t fallback。

/*

/usr/src/linux-headers-5.0.0-20/include/linux/netdevice.h:1247

*/

struct net_device_ops {

//......

u16(*ndo_select_queue)(struct net_device *dev,

struct sk_buff *skb,

struct net_device *sb_dev,

select_queue_fallback_t fallback);

//......

}

/*

rtl8821ce/os_dep/linux/os_intfs.c:1325

*/

static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)

, struct net_device *sb_dev

#endif

)

{

_adapter*padapter = rtw_netdev_priv(dev);

struct mlme_priv *pmlmepriv = &padapter->mlmepriv;

skb->priority = rtw_classify8021d(skb);

if (pmlmepriv->acm_mask != 0)

skb->priority = qos_acm(pmlmepriv->acm_mask, skb->priority);

return rtw_1d_to_queue[skb->priority];

}

现在考虑如何修补这个函数实现。幸好在函数体中并没有用到第四个形参,因而直接把缺少的形参添上就可以了(可能会引入一些BUG)。

下面是rtl8821ce/os_dep/linux/os_intfs.c的修改内容变化(由diff -u生成)。

@@ -1323,9 +1323,8 @@ unsigned int rtw_classify8021d(struct sk_buff *skb)

static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb

-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)

,struct net_device *sb_dev

-#endif

+ ,select_queue_fallback_t fallback

)

{

_adapter*padapter = rtw_netdev_priv(dev);

之后,再进行编译,得到下面的输出,表示编译通过了。之后就可以安装和加载模块了。注意只有关闭了安全启动,才能加载未签名的内核模块。可以参考我的这篇随笔Linux内核模块在安全启动模式下的签名和安装,自签名模块并加载。

LD [M] /home/name/nv/rtl8821ce/8821ce.o

Building modules, stage 2.

MODPOST 1 modules

CC /home/name/nv/rtl8821ce/8821ce.mod.o

LD [M] /home/name/nv/rtl8821ce/8821ce.ko

相关链接:

你可能感兴趣的:(rtl8821ce,linux驱动,内核)