前言
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.