V4L2驱动的移植与应用

V4L2(video for linux) 可以支持多种设备,它可以有以下5种接口:

  1、视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.下面也是着重讲解这种应用;

  2、视频输出接口(video output interface):可以驱动计算机的外围视频图像设备——像可以输出电视信号格式的设备;
  3、直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU;
  4、视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号;
  5、收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流;
  V4L2驱动的主要功能是使程序有发现设备的能力和操作设备.它主要是用过一系列的回调函数来实现这些功能.像设置高频头的频率,帧频,视频压缩格式和图像像参数等等.
  一、V4L2的移植
  V4L2提供了三种不同的API来传输外围设备和用户空间的数据.下面就vivi(drivers/media/video/vivi.c)来讲解一个V4L2驱动的编写.注意它是一个虚拟的设备驱动,没有与实际的硬件打交道.

  1、分析几个重要数据结构:
  vivi.c包含头文件v4l2-device.h和v4l2-ioctl.h,其中v4l2-device.h中包含了v4l2-subdev.h,v4l2-subdev.h中又包含了v4l2-common.h,v4l2-common.h中包含了v4l2-dev.h.
  在v4l2-dev.h中定义了结构体video_device和v4l2_file_operations;
  在v4l2-ioctl.h中定义了结构体v4l2_ioctl_ops;
  在v4l2-device.h中定义了结构体v4l2_device;
  

1) vivi_fops

 
01static const struct v4l2_file_operations vivi_fops = {
02 
03.owner = THIS_MODULE,
04.open = vivi_open,
05.release = vivi_close,
06.read = vivi_read,
07.poll = vivi_poll,
08.ioctl = video_ioctl2, /* V4L2 ioctl handler */
09.mmap = vivi_mmap,
10};
2) vivi_ioctl_ops
 
01static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
02 
03.vidioc_querycap = vidioc_querycap,
04 
05.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
06 
07.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
08 
09.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
10 
11.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
12 
13.vidioc_reqbufs = vidioc_reqbufs,
14 
15.vidioc_querybuf = vidioc_querybuf,
16 
17.vidioc_qbuf = vidioc_qbuf,
18 
19.vidioc_dqbuf = vidioc_dqbuf,
20 
21.vidioc_s_std = vidioc_s_std,
22 
23.vidioc_enum_input = vidioc_enum_input,
24 
25.vidioc_g_input = vidioc_g_input,
26 
27.vidioc_s_input = vidioc_s_input,
28 
29.vidioc_queryctrl = vidioc_queryctrl,
30 
31.vidioc_g_ctrl = vidioc_g_ctrl,
32 
33.vidioc_s_ctrl = vidioc_s_ctrl,
34 
35.vidioc_streamon = vidioc_streamon,
36 
37.vidioc_streamoff = vidioc_streamoff,
38 
39#ifdef CONFIG_VIDEO_V4L1_COMPAT
40 
41.vidiocgmbuf = vidiocgmbuf,
42 
43#endif
44 
45};
3) vivi_template
 
01static struct video_device vivi_template = {
02 
03.name = "vivi",
04.fops = &vivi_fops,
05.ioctl_ops = &vivi_ioctl_ops,
06.minor = -1,
07.release = video_device_release,
08.tvnorms = V4L2_STD_525_60,
09.current_norm = V4L2_STD_NTSC_M,
10};
        其中函数vivi_xxx和vidioc_xxx都是在vivi.c中实现的。如果要基于某个硬件来实现V4L2的接口,那这些函数就需要调用硬件的驱动去实现。        4) vivi_dev
 
01struct vivi_dev {
02struct list_head vivi_devlist; //内核双向链表,在内核数据结构里有描述
03struct semaphore lock; //信号量,防止竞态访问
04int users; //用户数量计数
05/* various device info */
06unsigned int resources;
07struct video_device video_dev; //这个成员是这个结构的核心,用面向对象的话来说就是基类
08struct vivi_dmaqueue vidq; //DMA队列
09/* Several counters */
10int h,m,s,us,jiffies; //定时器定义
11char timestr[13]; //其它一些资源变量.
12};
        像这样变义的结构在Linux C 中很普遍,这也是利用C来实现面向对象编程的强大方法。建立这个结构对象之后,所有的操作都是基于这个结构,或者这个结构派生出的来的其它结构。        5) vivi_fh
 
01struct vivi_fh {
02struct vivi_dev *dev;
03 
04/* video capture */
05struct vivi_fmt *fmt;
06unsigned intwidth,height;
07struct videobuf_queue vb_vidq;
08 
09enum v4l2_buf_type type;
10};
          这个结构即是vivi_dev结构的更深层次封装,基于那个结构加入了更多的描述信息,如视频制式、视频画面大小、视频缓冲队列等等。在open的时候,会把这个结构赋给file结构中的private_data域。在释放设备时注销.其它的像ioctl,mmap,read,write等等都会用到这个结构,其实整个模块的编写的cdev差不多。只是视频设备的基类是video_device,而字符设备的基类是cdev而已。        2、数据传输方式:        在设备与应用程序之间有三种数据传输方式:        1)read与write这种方式,它像其它设备驱动一样,但是这种方式很慢,对于数据视频流不能满足其要求;        2)直接的内存访问,可以通过其映射方式来传输(IO数据流,交换指向缓冲区指针的方法);这是视频设备通常用的方法,采用mmap()的方法,即有内核空间里开辟内存,再在程序里把这部分的内存映射到程序空间。如果有设备内存,即直接映射到设备的内核,这种性能更高。         3)异步IO口访问,但是这种方法在V4L2模块中还没有实现。(重要:需要确认)         vivi中的mmap是利用第二种方法来实现的,这也是视频设备常用的方法:
 
01static int
02vivi_mmap(struct file *file, struct vm_area_struct * vma)
03{
04struct vivi_fh *fh = file->private_data;
05int ret;
06 
07dprintk (1,"mmap called, vma=0x%08lx/n",(unsignedlong)vma);
08 
09ret=videobuf_mmap_mapper(&fh->vb_vidq, vma);
10 
11dprintk (1,"vma start=0x%08lx, size=%ld, ret=%d/n",
12(unsigned long)vma->vm_start,
13(unsigned long)vma->vm_end-(unsignedlong)vma->vm_start,
14ret);
15 
16return ret;
17}
videobuf_mmap_mapper(&fh->vb_vidq, vma); 这个核心函数把设备的I/O内存或者设备内存映射到系统为它开辟的虚拟内存。        3、操控设备的实现: ioctl
 
1static int vivi_ioctl(struct inode *inode, struct file *file, unsignedint cmd, unsignedlong arg){
2return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl);
3}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值