4- v4l2——basic ioctl io口的控制

来源:互联网 发布:粉笔事业单位做题软件 编辑:程序博客网 时间:2024/05/04 02:40

v4l2驱动编写篇三--基本I/O处理 
如果有人在video for linux API规范上花了我时间的话,他肯定已经注意到了一个问题,那就是V4L2大量使用了ioctl接口。视频硬件有大量的可操作旋钮,可能比其它任何处理都要多。视频流要与许多参数相联系,而且有很大一部分处理要通过硬件进行。试图在硬件支持模式之外运行视频会导致性能很差,甚至根本任何性能。所以我们不得不揭露硬件的许多特性,结束应用的混杂模式。

1、新旧ioctl
传统上来讲,视频驱动中包含的ioctl()函数一般会长得像一部小说,而函数所得到的结论也往往比小说更令人满意来,他们往往在中间有很多延迟(这句话完 全不明白什么意思)。所以V4L2的API在2.6.18版本的内核开始做出了改变。冗长的ioctl函数被替换成了一个大的回调函数的集合,每个回调函 数实现自己的ioctl函数。实际上,在2.6.19-rc3中,有79个这样的回调函数。而幸运的是,多数驱动并不需实现所有的回调函数,甚至都不是大部分回调函数。

在ioctl()函数中发生的事情都放到了drivers/media/video/videodev.c里面。这部分代码处理数据在内核和用户空间之间 的传输并分派特定的ioctl调用到驱动。要使用它的话,只要把video_device中ioctl()video_ioctl2()调用代替。 实际上,多数驱动也要把它当成unlocked_ioctl()来用。Video4Linux2层的锁可以对其进行处理,而且驱动也应该在合适的地方加 锁。 

2、查询硬件性能
你的驱动第一个可能要实现的回调函数是:

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" */   driver域应该被填充设备驱动的名字
 __u8 card[32]; /* i.e. "Hauppauge WinTV" */card域应该被填充这个设备的硬件描述信息
 __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ 总线的详细信息
 __u32   version;        /* should use KERNEL_VERSION() */version域用来保存驱动的版本号
 __u32 capabilities; /* Device capabilities */
 __u32 reserved[4];
};
 
3.并不是所有的驱动都消耗精力去处理bus_info域,这些驱动通常使用下面这个方法
   springf(cap->bus_info, "PCI:%s", pci_name(&my_dev));
 
5.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 */ 异步IO
#define V4L2_CAP_STREAMING              0x04000000  /* streaming I/O ioctls */流IO控制
 
6.最后一个域(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个回调函数。特别的,我们要开始看看与硬件协商一组操作模式的过程。


0 0
原创粉丝点击