尝试在 3.11 内核上编译 rtl8187l 驱动

楼主有一块卡皇 USB 网卡,Realtek 8187L 系列,09 年购入,现在依旧在服役。虽然这款无线网卡的驱动已经内置到内核里了,但是却有不少的毛病,比如信号不好,有掉线的情况发生,于是我想我几年前也编译过这个驱动,索性编译一个好了,没想到这却是折腾的开始。。。好了,题外话少说,现在进入正题

在 Realtek 的官方网站上有 8187 系列的 Linux 版本驱动下载,是 2012 年更新的版本,支持 3.0~3.2 的内核。但是内核更新了这么久,官方的驱动是否还能使用?在我的 openSUSE 13.1 下进行编译,情况如下

make[1]: Entering directory `/usr/src/linux-3.11.10-17-obj/x86_64/desktop'
  CC [M]  /home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.o
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:153:22: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtl8187_usb_probe’
 static int __devinit rtl8187_usb_probe(struct usb_interface *intf,
                      ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:155:23: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtl8187_usb_disconnect’
 static void __devexit rtl8187_usb_disconnect(struct usb_interface *intf);
                       ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:168:12: error: ‘rtl8187_usb_probe’ undeclared here (not in a function)
  .probe  = rtl8187_usb_probe,           
            ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:169:16: error: ‘rtl8187_usb_disconnect’ undeclared here (not in a function)
  .disconnect = rtl8187_usb_disconnect,   
                ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c: In function ‘rtl8180_proc_module_init’:
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:427:2: error: implicit declaration of function ‘create_proc_entry’ -Werror=implicit-function-declaration]
  rtl8180_proc=create_proc_entry(RTL8187_MODULE_NAME, S_IFDIR, init_net.proc_net);
  ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:427:14: warning: assignment makes pointer from integer without a cast [enabled by default]
  rtl8180_proc=create_proc_entry(RTL8187_MODULE_NAME, S_IFDIR, init_net.proc_net);
              ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c: In function ‘rtl8180_proc_init_one’:
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:461:16: warning: assignment makes pointer from integer without a cast [enabled by default]
  priv->dir_dev = create_proc_entry(dev->name, 
                ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:479:2: error: implicit declaration of function ‘create_proc_read_entry’ -Werror=implicit-function-declaration]
  e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
  ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:479:4: warning: assignment makes pointer from integer without a cast [enabled by default]
  e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
    ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:489:4: warning: assignment makes pointer from integer without a cast [enabled by default]
  e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
    ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:518:4: warning: assignment makes pointer from integer without a cast [enabled by default]
  e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
    ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c: In function ‘rtl8180_tx’:
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:1382:12: warning: cast from pointer to integer of different size -Wpointer-to-int-cast]
  u8 seg = ((u32)txbuf % 4);
            ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c: In function ‘rtl8187_usb_initendpoints’:
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:1588:14: warning: cast from pointer to integer of different size -Wpointer-to-int-cast]
   seg_size = (u32)ptrcontext->transfer_buffer % 4;
              ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c: At top level:
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:3762:22: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtl8187_usb_probe’
 static int __devinit rtl8187_usb_probe(struct usb_interface *intf,
                      ^
/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.c:3862:23: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtl8187_usb_disconnect’
 static void __devexit rtl8187_usb_disconnect(struct usb_interface *intf)
                       ^
cc1: some warnings being treated as errors
make[4]: *** [/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187/r8187_core.o] Error 1
make[3]: *** [_module_/home/cheng/rtl8187L_linux_1041.0209.2012/rtl8187] Error 2
make[2]: *** [sub-make] Error 2
make[1]: *** [all] Error 2
make[1]: Leaving directory `/usr/src/linux-3.11.10-17-obj/x86_64/desktop'
make: *** [all] Error 2

官方的驱动早已不能编译成功。怎么破?
虽然我是小白,看不懂编译是什么错误,不过有 Google 嘛。于是上网搜索了一下,发现在 Ubuntu 论坛上有人提出了解决方案 ubuntuforums.org/showthread.php?p=12775665#post12775665 在"r8187.h" 文件的开头加入

#ifndef __devinit
#define __devinit
#define __devexit
#endif

更改之后满怀信心再次编译,可还是错误:

make[1]: Entering directory `/usr/src/linux-3.11.10-17-obj/x86_64/desktop'
  CC [M]  /home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.o
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c: In function ‘rtl8180_proc_module_init’:
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:427:5: error: implicit declaration of function ‘create_proc_entry’ -Werror=implicit-function-declaration]
     rtl8180_proc=create_proc_entry(RTL8187_MODULE_NAME, S_IFDIR, init_net.proc_net);
     ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:427:17: warning: assignment makes pointer from integer without a cast [enabled by default]
     rtl8180_proc=create_proc_entry(RTL8187_MODULE_NAME, S_IFDIR, init_net.proc_net);
                 ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c: In function ‘rtl8180_proc_init_one’:
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:461:19: warning: assignment makes pointer from integer without a cast [enabled by default]
     priv->dir_dev = create_proc_entry(dev->name,
                   ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:479:5: error: implicit declaration of function ‘create_proc_read_entry’ -Werror=implicit-function-declaration]
     e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
     ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:479:7: warning: assignment makes pointer from integer without a cast [enabled by default]
     e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
       ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:489:7: warning: assignment makes pointer from integer without a cast [enabled by default]
     e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
       ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:518:7: warning: assignment makes pointer from integer without a cast [enabled by default]
     e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
       ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c: In function ‘rtl8180_tx’:
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:1382:15: warning: cast from pointer to integer of different size -Wpointer-to-int-cast]
     u8 seg = ((u32)txbuf % 4);
               ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c: In function ‘rtl8187_usb_initendpoints’:
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.c:1588:20: warning: cast from pointer to integer of different size -Wpointer-to-int-cast]
         seg_size = (u32)ptrcontext->transfer_buffer % 4;
                    ^
cc1: some warnings being treated as errors
make[4]: *** [/home/cheng/rtl8187-Linux-Driver-master/rtl8187/r8187_core.o] Error 1
make[3]: *** [_module_/home/cheng/rtl8187-Linux-Driver-master/rtl8187] Error 2
make[2]: *** [sub-make] Error 2
make[1]: *** [all] Error 2
make[1]: Leaving directory `/usr/src/linux-3.11.10-17-obj/x86_64/desktop'
make: *** [all] Error 2

这回我发现是由于没有申明 create_proc_entry 这个函数,去 Google 一搜发现在 3.10 内核之后将 create_proc_entry 去除了,改为 proc_create 函数了。于是我将函数一一进行更改,改完之后编译还是出错,这次是什么错误呢

/home/cheng/rtl8187-Linux-Driver-master/rtl8187/../ieee80211/ieee80211_module.c:320:6: error: dereferencing pointer to incomplete type
     e->read_proc = show_debug_level;
      ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/../ieee80211/ieee80211_module.c:321:6: error: dereferencing pointer to incomplete type
     e->write_proc = store_debug_level;
      ^
/home/cheng/rtl8187-Linux-Driver-master/rtl8187/../ieee80211/ieee80211_module.c:322:6: error: dereferencing pointer to incomplete type
     e->data = NULL;
      ^
make[4]: *** [/home/cheng/rtl8187-Linux-Driver-master/rtl8187/../ieee80211/ieee80211_module.o] Error 1
make[3]: *** [_module_/home/cheng/rtl8187-Linux-Driver-master/rtl8187] Error 2
make[2]: *** [sub-make] Error 2
make[1]: *** [all] Error 2
make[1]: Leaving directory `/usr/src/linux-3.11.10-17-obj/x86_64/desktop'
make: *** [all] Error 2

事情到这里我彻底没有办法了。。由于我对系统编程知之甚少,而且对硬件驱动完全不知,实在是没有办法再改动源代码了。在此向论坛的各位大牛求助,能否帮忙一起将此驱动在 3.10 版本内核和之后的版本中编译通过。先行谢过各位!

@lledu

你确定你 create_proc_entry 到 proc_create 的修改是正确的?

这可不是简单的替换函数啊,proc_create 多了个参数呢。

可以参考 broadcom-wl 的补丁:

launchpadlibrarian.net/153741153/0008-add-support-to-linux-3.12.0.patch

谢谢玛格丽特苏的回复。这个函数的使用方法我也在网络上搜索过(水平有限,没看明白),我是这么更改的:

rtl8180_proc=proc_create(RTL8187_MODULE_NAME, S_IFDIR, NULL, &proc_net); 

原来是这样的:

rtl8180_proc=create_proc_entry(RTL8187_MODULE_NAME, S_IFDIR, proc_net); 

是不是这里有问题?

你改错了。正确的我也不会,看看 wl 那个 patch 吧。

折腾了这么几天回论坛告知一下进展。驱动成功编译,成功安装。但是开始连接的时候就 kernel panic,重启之后发现文件系统损坏。fsck 之后未果,现准备重装。。

这就是典型的 no zuo no die why you try…