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 */

#define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
#define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
#define V4L2_CAP_STREAMING              0x04000000  /* streaming I/O ioctls */

 

最后一个域(reserved)是保留的。V4L2规则要求要求reserved被置为0, 但是, 因为video_ioctl2()设置了整个的结构体为0,所以这个就不用我们操心了。

 

可以在“vivi”这个驱动中找到一个典型的应用:

static int vidioc_querycap(struct file *file, void  *priv,
     struct v4l2_capability *cap)
{
 struct vivi_fh  *fh  = priv;
 struct vivi_dev *dev = fh->dev;

 strcpy(cap->driver, "vivi");
 strcpy(cap->card, "vivi");
 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
 cap->version = VIVI_VERSION;
 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
    V4L2_CAP_STREAMING     |
    V4L2_CAP_READWRITE;
 return 0;
}

考虑到这个回调函数的出现,我们希望应用程序使用它,避免要求设备完成它们不可能完成的功能。然而,在你编程的有限经验中,应用程序不会花太多的精力来关注VIDIOC_QUERYCAP调用。

 

另一个可选而又不常被是实现的回调函数是:

     int (*vidioc_log_status)       (struct file *file, void *fh);

这个函数用来实现VIDIOC_LOG_STATUS调用,作为视频应用程序编写者的调试助手。当调用时,它应该打印藐视驱动及其硬件的当前状态信息。这个信息应该足够充分以便帮助迷糊的应用程序开发者弄明白为什么视频显示一片空白。

 

 下一部分开始剩下的77个回调函数。特别的,我们要开始看看与硬件协商一组操作模式的过程。


原文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值