IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    为树莓派交叉编译 8192eu 网卡驱动

    依云发表于 2015-09-13 18:43:48
    love 0

    本文来自依云's Blog,转载请注明。

    最近打算把闲置了许久的树莓派重新利用起来。交给它的第一个任务是:做路由器。于是去弄了个 USB 无线网卡,型号是 TP-Link WN823N 版本 2.0。买的时候没注意,拿到手才知道这款需要自行安装驱动。还得使用特制版本的 hostapd。

    驱动名叫 8192eu,或者 rtl8192eu,随便啦。GitHub 上有多个版本,我使用的是 Mange/rtl8192eu-linux-driver。因为 gcc 及内核更新的原因,需要修改两处:

    diff --git a/Makefile b/Makefile
    index 0c800f8..85058fa 100644
    --- a/Makefile
    +++ b/Makefile
    @@ -13,6 +13,7 @@ EXTRA_CFLAGS += -Wno-unused-label
     EXTRA_CFLAGS += -Wno-unused-parameter
     EXTRA_CFLAGS += -Wno-unused-function
     EXTRA_CFLAGS += -Wno-unused
    +EXTRA_CFLAGS += -Wno-date-time
    
     #EXTRA_CFLAGS += -Wno-uninitialized
    
    diff --git a/os_dep/linux/rtw_android.c b/os_dep/linux/rtw_android.c
    index 98f0d31..8a2ee56 100644
    --- a/os_dep/linux/rtw_android.c
    +++ b/os_dep/linux/rtw_android.c
    @@ -337,7 +337,7 @@ int rtw_android_cmdstr_to_num(char *cmdstr)
     {
            int cmd_num;
            for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
    -               if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
    +               if(0 == strncasecmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
                            break;
    
            return cmd_num;
    

    然后,本文的主题来了:我需要 ARM 版的驱动!因为我的树莓派没有键盘也没有显示器,也没有网线什么的。除了电源和 SD 卡,它只有一块无线网卡了。所以只能交叉编译了。

    本来呢,内核使用的构建系统非常棒,一切都会很顺利的。但是,我不要先交叉编译个 ARM 版内核。于是我遇到了这个问题。scripts 目录下的二进制文件是编译模块的时候需要执行的,然而我的机器并不能执行 ARM 版本的二进制。

    好吧,不就是一些小程序么。把我本机的复制过去就可以跑了嘛。结果开心地看着各种源码文件被编译成目标文件之后,遇到了这么个错误:

    FATAL: section header offset=11258999068426292 in file '/ldata/DATA/src/rtl8192eu-linux-driver/8192eu.o' is bigger than filesize=1094666
    

    大概是因为我的系统是 64 位的,然而 ARM 是 32 位的吧。不过我没兴趣去找一个 i686 版本的 modpost 来尝试了。真要在我笔记本上跑 ARM 程序又不是不可以,我们有 qemu 嘛。虽然是模拟器,不过我不觉得它会比在我那树莓派上运行慢 :-)

    以下是整个完整的步骤:

    首先说明一点,我使用的是 Arch Linux ARM。树莓派官方提供的 Raspberry 镜像里东西太多了,我的 SD 卡放不下我也用不着。而且它是基于 Debian Wheezy 的,没有 systemd 可用。

    新建一个目录rpi,开始啦!

    因为要运行 ARM 版的 modpost 程序,我们先下载树莓派的 gcc-libs、glibc,并解压出其 /usr/lib 下的文件:

    wget https://mirrors.ustc.edu.cn/archlinuxarm/armv6h/core/gcc-libs-5.2.0-2-armv6h.pkg.tar.xz https://mirrors.ustc.edu.cn/archlinuxarm/armv6h/core/gcc-libs-5.2.0-2-armv6h.pkg.tar.xz.sig https://mirrors.ustc.edu.cn/archlinuxarm/armv6h/core/glibc-2.22-1-armv6h.pkg.tar.xz https://mirrors.ustc.edu.cn/archlinuxarm/armv6h/core/glibc-2.22-1-armv6h.pkg.tar.xz.sig
    gpg --verify glibc-2.22-1-armv6h.pkg.tar.xz.sig
    tar xf glibc-2.22-1-armv6h.pkg.tar.xz usr/lib || true
    gpg --verify gcc-libs-5.2.0-2-armv6h.pkg.tar.xz.sig
    tar xf gcc-libs-5.2.0-2-armv6h.pkg.tar.xz usr/lib
    [[ ! -f lib ]] && ln -s usr/lib lib
    

    要编译内核模块,当然少不了 linux-*-headers 包了:

    wget https://mirrors.ustc.edu.cn/archlinuxarm/armv6h/core/linux-raspberrypi-headers-4.1.6-3-armv6h.pkg.tar.xz https://mirrors.ustc.edu.cn/archlinuxarm/armv6h/core/linux-raspberrypi-headers-4.1.6-3-armv6h.pkg.tar.xz.sig
    gpg --verify linux-raspberrypi-headers-4.1.6-3-armv6h.pkg.tar.xz.sig
    tar xf linux-raspberrypi-headers-4.1.6-3-armv6h.pkg.tar.xz usr
    

    不必每次更新 gcc-libs 和 glibc,只要它们能跑 modpost 程序就可以了。但是内核头文件是要和系统上运行的内核匹配的。

    我们删掉 ARM 版的 scripts 目录,换上本机的版本。但是 modpost 例外。同时要修改 Makefile.modpost,使之使用 qemu-arm 来运行 modpost 程序:

    pushd usr/lib/modules/4.1.6-3-ARCH/build
    mv scripts/mod/modpost .
    rm -rf scripts
    cp -r /usr/lib/modules/$(uname -r)/build/scripts .
    sed -i '/^modpost =/s/scripts/qemu-arm scripts/' scripts/Makefile.modpost
    mv modpost scripts/mod
    popd
    

    最后就可以编译啦。把交叉编译工具链(签名)的路径加到 $PATH 里去。还要设置 QEMU_LD_PREFIX 到我们解压出来的那些文件所在的目录好让 qemu-arm 能够找到需要的库文件。然后进入驱动目录,开始编译!

    path+=/ldata/DATA/soft/arm-lilydjwg-linux-gnueabi/bin
    export QEMU_LD_PREFIX=$PWD
    cd ../rtl8192eu-linux-driver
    make CROSS_COMPILE=arm-lilydjwg-linux-gnueabi- KSRC=../rpi/usr/lib/modules/4.1.6-3-ARCH/build ARCH=arm
    gzip 8192eu.ko
    

    就酱。

    试错几次之后,终于把配置写对了,于是我看到树莓派的 Wi-Fi 灯闪动了,随即从系统日志看到 hostapd 和 dnsmasq 都报告它连上网了~然后 ssh 登陆过去:

    Last login: Tue Jun 11 22:57:29 2013 from 192.168.2.101
    

    两年零三个月没进去过了呢。然后,我换 USTC 源,执行了pacman -Syu!跨越两年零三个月的滚动更新,然而除了很多配置文件有新版本需要手工合并外,并没有发生什么特别的事情,就更没有滚挂了=w=

    后来我也尝试在树莓派上直接编译内核模块(因为内核升级了嘛)。结果表明,交叉编译是正确的选择!在树莓派上编译这个模块的时间,我的笔记本估计可以编译出整个内核了……

    这是我编译的 8192eu 模块 及签名文件,对应内核版本 4.1.6。


    至于 hostapd,下载这个,把其中的wpa_supplicant_hostapd-0.8_rtw_r7048.20130424.tar.gz里hostapd目录下的东西编译了就好。只需要指定CC变量就可以交叉编译成功。

    这是我编译的 hostapd 及签名文件。配置文件中要写driver=rtl871xdrv。



沪ICP备19023445号-2号
友情链接