日期:2014-05-16  浏览次数:20774 次

V4L2 Linux驱动简介(3)基本I/O原理
       如果有人在video for linux API规范上花了我时间的话,他肯定已经注意到了一个问题,那就是V4L2大量使用了ioctl接口。视频硬件有大量的可操作旋钮,可能比其它任何处设都 要多。视频流要与许多参数相联系,而且有很大一部分处理要通过硬件进行。不使用硬件有良好支持模式可能导致表现不好,甚至根本没有表现。所以我们不得不揭 露硬件的许多特性,而对最终应用表现得怪异一点。
    传统上来讲,视频驱动中包含的ioctl()函数一般会长得像一部小说,而函数所得到的结论也往 往比小说更令人满意来,他们往往在中间拖了很多(这句话完全不明白什么意思)。所以V4L2的API在2.6.18版本的内核开始做出了改变。冗长的 ioctl函数被替换成了一个大的回调函数的集合,每个回调函数实现自己的ioctl函数。实际上,在2.6.19-rc3中,有79个这样的回调函数。 而幸运的是,多数驱动并不需实现所有的回调函数,甚至都不是大部分回调函数。
    在ioctl()函数中发生的事情都放到了 drivers/media/video/videodev.c里面。这部分代码处理数据在内核和用户空间之间的传输并把ioctl调用发送给驱动。要使 用它的话,只要把video_device中的video_ioctl2()做为ioctl()来调用就行了。实际上,多数驱动也要把它当成 unlocked_ioctl()来用。Video4Linux2层的锁可以对其进行处理,而且驱动也应该在合适的地方加锁。(这一段没看明白,乱写的)

 

你的驱动第一个可能要实现的回调函数是:

int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);

这 个函数处理VIDIOC_QUERYCAP ioctl(), 只是简单问问“你是谁?你能干什么?”实现它是V4L2驱动的责任。在这个函数中,和所有其他V4L2回调函数一样, 参数priv是file->private_data域的内容;通常的实现是在open()的时候把它指向驱动中表示设备的内部结构。

 

驱动应该负责填充cap结构并且返回“0或者负的错误码”值。如果成功返回,则V4L2层会负责把回复拷贝到用户空间。

 

v4l2_capability结构(定义在<linux/videodev2.h>中)是这样的:

struct v4l2_capability {
 __u8 driver[16]; /* i.e. "bttv" */
 __u8 card[32]; /* i.e. "Hauppauge WinTV" */
 __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */
 __u32   version;        /* should use KERNEL_VERSION() */
 __u32 capabilities; /* Device capabilities */
 __u32 reserved[4];
};

 

其中driver域应该被填充设备驱动的名字,card域应该被填充这个设备的硬件描述信息。并不是所有的驱动都消耗精力去处理bus_info域,这些驱动通常使用下面这个方法:

   springf(cap->bus_info, "PCI:%s", pci_name(&my_dev));

version域用来保存驱动的版本号。capabilities域是一个位掩码用来描述驱动能做的不同的事情:

/* Values for 'capabilities' field */
#define V4L2_CAP_VIDEO_CAPTURE  0x00000001  /* Is a video capture device */
#define V4L2_CAP_VIDEO_OUTPUT  0x00000002  /* Is a video output device */
#define V4L2_CAP_VIDEO_OVERLAY  0x00000004  /* Can do video overlay */
#define V4L2_CAP_VBI_CAPTURE  0x00000010  /* Is a raw VBI capture device */
#define V4L2_CAP_VBI_OUTPUT  0x00000020  /* Is a raw VBI output device */
#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040  /* Is a sliced VBI capture device */
#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080  /* Is a sliced VBI output device */
#define V4L2_CAP_RDS_CAPTURE  0x00000100  /* RDS data capture */
#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200  /* Can do video output overlay */
#define V4L2_CAP_HW_FREQ_SEEK  0x00000400  /* Can do hardware frequency seek  */

#define V4L2_CAP_TUNER   0x00010000  /* has a tuner */
#define V4L2_CAP_AUDIO   0x00020000  /* has audio support */
#define V4L2_CAP_RADIO   0x00040000  /* is a radio device *