Linux UVC driver 独立交叉编译记录

前言

https://linuxtv.org/
官网介绍如下:

Typical usage is:

git clone git://linuxtv.org/media_build.git
cd media_build
./build
make install

这个是针对你当前运行的linux环境的编译。下面介绍下如何针对指定的内核版本进行交叉编译。

1.下载项目源码:

git clone git://linuxtv.org/media_build.git
cd media_build
anzyelay@ubuntu:media_build$ ls devel_scripts/
analyze_build.pl  gen_rename_patch.pl  README  rename_patch.sh
anzyelay@ubuntu:media_build$ ls linux/
Makefile  patches_for_kernel.pl  use_dir.pl  version_patch.pl
anzyelay@ubuntu:media_build$ ls v4l/
compat.h  Kconfig.misc  Kconfig.sound    Makefile         Makefile.mm     obsolete.txt  versions.txt
firmware  Kconfig.mm    Kconfig.staging  Makefile.kernel  Makefile.sound  scripts

2.项目文件media_build几点说明

anzyelay@ubuntu:media_build$ ls
backports  COPYING        dvb-firmwares.tar.bz2  linux     modules.order   README          v4l
build      devel_scripts  INSTALL                Makefile  Module.symvers  README.patches
  • v4l:编译出来的文件都在此目录下,其中的.c文件都是链接到../linux里的
  • linux:下载和解压出的驱动源代码目录,原文件仅有makefile,和三个脚本文件
    patches_for_kernel.pl检测当前内核所需要的补丁文件,(其实就是读取Backport.txt,只要kernel version<[x.x.xx],就加入到要打的补丁行列)

  • backports:回溯补丁文件夹,简言之就是下载的uvc驱动源码是最新的内核函数,要倒回到旧版本的内核源码就需要反向打补丁了,所以叫了这么个名字.因此看说明(Backport.txt)上解释的是打的补丁要高于或等于当前版本的栏目.

3.指定内核版本或内核源码目录:

在此之前需要在你指定的内核源码中设置好交叉环境编译执行一次,然后再执行make modules_prepare生成Module.symvers文件,为外部模块编译做好准备工作,然后后面才能正常编译
指定方法详情可以make help查看

  • 方法1 :
    make release DIR=内核源码目录
    执行结果如下

    anzyelay@ubuntu:media_build$ make release DIR=/home/anzyelay/Desktop/arm/linux-3.6.6-gcc.4.9.4
    make -C /home/anzyelay/Desktop/media_build/v4l release
    make[1]: Entering directory `/home/anzyelay/Desktop/media_build/v4l'
    Searching in /home/anzyelay/Desktop/arm/linux-3.6.6-gcc.4.9.4/Makefile for kernel version.
    Forcing compiling to version 3.6.6
    make[1]: Leaving directory `/home/anzyelay/Desktop/media_build/v4l'
    
  • 方法2 :
    make release VER=版本号(如:3.5.0-54-generic)
    但这方法要先做好/lib/modules/3.5.0-54-generic/build的指向。
    具体做法:内核源码同样编译执行好,也要make modules_prepare,然后将源码连接到此目录:

    ln -s /path/to/kerne-src /lib/modules/3.5.0-54-generic/build

    如果你直接在编译内核源码后make modules_install了,那就不需要了手动ln了,它会自动完成上述操作。
    指定了源码后,后面在执行makefile时,会引用内核源码顶层的makefile里的变量和规则,如此就可以实现交叉编译了.

4.下载驱动并编译安装

4.1 使用默认自动执行

./build

这里包括了下面的步骤:
1.检查下载最新UVC驱动并解压,
2.检测指定内核所需要的backport补丁(我直接理解成逆向补丁),并打补丁
3 执行配置脚本生成默认配置Kconfig, .config和makefile文件等
4 编译

注:如果是使用此方法的话make menuconfig不能在执行前做配置,因为当前的v4l下还没有uvc驱动源码,无法生成Kconfig文件,所以要先执行一次再配置才行.

4.2 手动分步执行

  • 下载uvc驱动:
    • 方法1:手动自行选择版本下载–下载地址
    • 方法2:make download (自行下载最新版)
      新驱动可能有问题,我就遇上了补丁跟源码对应不上的.换了个旧的OK了,所以如果不对可以多试几个不同版本的驱动
  • 解压打补丁
    make untar
    make apply_patches
  • 配置
    make menuconfig

    这里项目代码打补丁后在v4l/Kconfig里有个小错误要解决,见下面的error1,执行make menuconfig 可能会出错.
    注:似乎在media_build目录下做menuconfig配置,有时不起作用,要在你指定的内核源码处修改配置才能起到作用,我重新来了一遍,把内核里的Multimedia support选项关了,在media_build的配置中选上了一样不编译,真奇怪。
    只能说内核里的配置选项会影响到譔项目本身的配置。

  • 编译
    make -jN

    编译成功后不要急,在执行一次make,看看有没有输出警告undefined,有的话要处理不然加载出现 Unknown symbol,

4.3 安装

make install

网上说的使用INSTALL_MOD_PATH我试过没用。它就是默认安装在/lib/modules/kernel-version/下的。似乎项目并没有给我们提供安装路径的控制变量.不信自己可以看安装脚本,还有strip这个也无法更改,要自已手动更换下PC上的链接.不然会出无法识别文件,因为是arm版的文件嘛.

anzyelay@ubuntu:media_build$ ls /lib/modules/3.6.6/
kernel             modules.dep          modules.inputmap   modules.seriomap     modules.usbmap
modules.alias      modules.dep.bin      modules.isapnpmap  modules.softdep
modules.alias.bin  modules.devname      modules.ofmap      modules.symbols
modules.ccwmap     modules.ieee1394map  modules.pcimap     modules.symbols.bin

5 error

5.1 make menuconfig时出现 :./Kconfig:n: unknown option “xxx”

具体如下:

    ./Kconfig:519: syntax error
    ./Kconfig:518: unknown option "Say"
    ./Kconfig:519: unknown option "To"
    ./Kconfig:520: unknown option "called"
    ./Kconfig:523: syntax error
    ./Kconfig:522:warning: multi-line strings not supported
    ./Kconfig:522: unknown option "If"
    make[1]: *** [menuconfig] Error 1
    make[1]: Leaving directory `/home/anzyelay/Desktop/media_build/v4l'
    make: *** [menuconfig] Error 2

这个是./v4l/kconfig这个文件的第518行有点格式问题

 508 # IR_HIX5HD2 disabled for insufficient kernel version
 509 config IR_HIX5HD2
 510     tristate "Hisilicon hix5hd2 IR remote control"
 511     depends on RC_CORE
 512     default n
 513     depends on VIDEO_KERNEL_VERSION
 514     ---help---
 515       WARNING! This driver needs at least kernel 3.10.0!  It may not
 516       compile or work correctly on your kernel, which is too old.
 517 
 518      Say Y here if you want to use hisilicon hix5hd2 remote control.                           
 519      To compile this driver as a module, choose M here: the module will be
 520      called ir-hix5hd2.
 521 
 522      If you're not sure, select N here
 523 

修改下就好了

5.2 make install 时出现strip: Unable to recognise the format of the input file xxx

具体如下:

strip: Unable to recognise the format of the input file `/lib/modules/3.6.6/kernel/drivers/media//cec-edid.ko'
strip: Unable to recognise the format of the input file `/lib/modules/3.6.6/kernel/drivers/media//media.ko'

这个是strip要用arm-linux-strip才行。它这里默认是用的Pc版的,所以无法安装,我找了N久也没找到此控制命令的环境变量,不知道如何处理了,我用了最笨的法子,直接暂时把strip的连接指向arm-linux-strip版,安装完好再恢复回来。

5.3 frame_vector: module license ‘unspecified’ taints kernel.

frame_vector 缺少 MODULE_LICENSE(“GPL”)申明
在frame_vector.c文件中加入即可MODULE_LICENSE(“GPL”);

5.4 加载驱动时出现:Unknown symbol xxx

在插入摄像头自动加载驱动时出现如下错误:

videobuf2_vmalloc: Unknown symbol dma_buf_vmap (err 0)
videobuf2_vmalloc: Unknown symbol dma_buf_export_named (err 0)
videobuf2_vmalloc: Unknown symbol dma_buf_vunmap (err 0)

上网查知如下说明:

> 如果模块在编译过程中出现没有定义的变量(编译过程中显示*.*undefined!)警告时, 这样编译出来的ko在最后插入时候将报以下错误(unknown symbol,can’t insert)

回到项目中再次make时确实出现这些警告。

WARNING: "dma_buf_vunmap" [/home/anzyelay/Desktop/media_build/v4l/videobuf2-vmalloc.ko] undefined!
WARNING: "dma_buf_export_named" [/home/anzyelay/Desktop/media_build/v4l/videobuf2-vmalloc.ko] undefined!
WARNING: "dma_buf_vmap" [/home/anzyelay/Desktop/media_build/v4l/videobuf2-vmalloc.ko] undefined!
WARNING: "dma_buf_fd" [/home/anzyelay/Desktop/media_build/v4l/videobuf2-core.ko] undefined!
WARNING: "dma_buf_put" [/home/anzyelay/Desktop/media_build/v4l/videobuf2-core.ko] undefined!
WARNING: "dma_buf_get" [/home/anzyelay/Desktop/media_build/v4l/videobuf2-core.ko] undefined!

搜索 dma_buf_vunmap发现如下

./backports/v3.1_no_dma_buf_h.patch: void *dma_buf_vmap(struct dma_buf *);
./backports/v3.1_no_dma_buf_h.patch:+static inline void *dma_buf_vmap(struct dma_buf *dmabuf)

前面说过backports是补丁存放文件夹,既然有补丁,那会不会是没打上补丁呢?看看补丁文件发现是a/include/linux/dma-buf.h文件,直接打开./linux/include/linux/dma-buf.h看了下果然是没有打上补丁,那就手动打吧

cd linux
patch -p1 < ../backports/v3.1_no_dma_buf_h.patch

再次make,警告消失

5.3 WARNING “xxx” [xx.ko] undefined

... ...
WARNING: "clk_enable" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_disable" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_put" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_get_rate" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_round_rate" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_get" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_set_rate" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "dma_buf_export_named" [/home/anzyelay/Desktop/media_build.pc/v4l/videobuf2-vmalloc.ko] undefined!
WARNING: "split_page" [/home/anzyelay/Desktop/media_build.pc/v4l/videobuf2-dma-sg.ko] undefined!
WARNING: "dma_buf_export_named" [/home/anzyelay/Desktop/media_build.pc/v4l/videobuf2-dma-sg.ko] undefined!
WARNING: "nsecs_to_jiffies" [/home/anzyelay/Desktop/media_build.pc/v4l/gpio-ir-recv.ko] undefined!
make[2]: Leaving directory `/usr/src/linux-headers-3.5.0-54-generic'
./scripts/rmmod.pl check
found 281 modules
make[1]: Leaving directory `/home/anzyelay/Desktop/media_build.pc/v4l'

dma_buf_export_named解决如下 :

anzyelay@ubuntu:media_build.pc$ grep dma_buf_export_named . -r
./linux/include/linux/dma-buf.h:struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
./linux/include/linux/dma-buf.h:    dma_buf_export_named(priv, ops, size, flags, KBUILD_MODNAME, resv)
Binary file ./v4l/videobuf2-dma-sg.ko matches
Binary file ./v4l/videobuf2-vmalloc.ko matches
Binary file ./v4l/videobuf2-dma-sg.o matches
Binary file ./v4l/videobuf2-vmalloc.o matches
./backports/v4.0_dma_buf_export.patch:+struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
./backports/v4.0_dma_buf_export.patch:+ dma_buf_export_named(priv, ops, size, flags, KBUILD_MODNAME, resv)
anzyelay@ubuntu:media_build.pc$ cd linux/
anzyelay@ubuntu:linux$ patch -p1 < ../backports/v4.0_dma_buf_export.patch 
patching file drivers/media/v4l2-core/videobuf2-dma-contig.c
Reversed (or previously applied) patch detected!  Assume -R? [n] yes
Hunk #1 succeeded at 389 (offset -13 lines).
Hunk #2 succeeded at 402 (offset -13 lines).
patching file drivers/media/v4l2-core/videobuf2-dma-sg.c
Reversed (or previously applied) patch detected!  Assume -R? [n] yes
Hunk #1 succeeded at 526 (offset -63 lines).
patching file drivers/media/v4l2-core/videobuf2-vmalloc.c
Reversed (or previously applied) patch detected!  Assume -R? [n] yes
Hunk #1 succeeded at 354 (offset -18 lines).
patching file include/linux/dma-buf.h
Reversed (or previously applied) patch detected!  Assume -R? [n] yes
Hunk #1 succeeded at 219 (offset 11 lines).
anzyelay@ubuntu:linux$ cd ..
anzyelay@ubuntu:linux$ make
  ... ...
  MODPOST 281 modules
WARNING: "clk_enable" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_disable" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_put" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_get_rate" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_round_rate" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_get" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "clk_set_rate" [/home/anzyelay/Desktop/media_build.pc/v4l/videodev.ko] undefined!
WARNING: "split_page" [/home/anzyelay/Desktop/media_build.pc/v4l/videobuf2-dma-sg.ko] undefined!
WARNING: "nsecs_to_jiffies" [/home/anzyelay/Desktop/media_build.pc/v4l/gpio-ir-recv.ko] undefined!
make[2]: Leaving directory `/usr/src/linux-headers-3.5.0-54-generic'
./scripts/rmmod.pl check
found 281 modules
make[1]: Leaving directory `/home/anzyelay/Desktop/media_build.pc/v4l'

dma_buf_export_named这个错误是补丁错了,删除原来打的补丁就行了。
其它的几个clk的错误与补丁没关了,同样grep了下发现有v4l2_clk_enable,怀疑驱动本身做了修改,定位下发现
./linux/drivers/media/v4l2-core/v4l2-clk.c 里有所有上述函数,但都有个前缀v4l2_,所以试着更改代码。如下:

替换代码:

anzyelay@ubuntu:media_build.pc$ sed -i "s/\<clk_enable/v4l2_clk_enable/g" `grep '\<clk_enable' ./linux/ -rl`
anzyelay@ubuntu:media_build.pc$ sed -i "s/\<clk_disable/v4l2_clk_disable/g" `grep '\<clk_disable' ./linux/ -rl`
anzyelay@ubuntu:media_build.pc$ sed -i "s/\<clk_put/v4l2_clk_put/g" `grep '\<clk_put' ./linux/ -rl`
anzyelay@ubuntu:media_build.pc$ sed -i "s/\<clk_put/v4l2_clk_put/g" `grep '\<clk_put' ./linux/ -rl`

....

这里有个错误,那就是把linux/drivers/media/v4l2-core/v4l2-clk.c 里的正常的clk_xxx函数也给变了,在替换前先将此文件移开,换完了在拖回来吧。好吧,试验后错误还是一样的,没效果 。。。怎么办??

查看了下旧版的文件终于解决了:
是linux/drivers/media/v4l2-core/v4l2-clk.c这个文件的问题:
将里面用到clk_xx函数的地方全屏蔽了就OK了。
需要的可以直接去复制
https://git.kernel.org/cgit/linux/kernel/git/mchehab/linux-media.git/tree/drivers/media/v4l2-core/v4l2-clk.c?h=media-v3.17-rc6
真是IMBA.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值