当前位置:编程学习 > C/C++ >>

v4l2 编程接口(二) — driver

V4L2 驱动随着硬件的变化也越来越复杂,现在大部分设备有里面包含了多个IC, 在/dev目录下不仅要建立 V4L2 的节点,而且还需要建立如:DVB、ALSA、FB、I2C、input等设备节点。事实上 V4L2 驱动需要支持音频/视频的混音/编码/解码等IC所以比其他驱动都要复杂很多,通常这些IC通过 i2c 总线连接到主板,这些设备都统称为sub-devices。在很长的一段时间里 V4L2 被限制只能在 video_device 结构体里面创建,并且用video_buf 控制视频缓存,这意味着所有的驱动创建自己的实例都将连接到自己的sub-devices,这些工作通常很复杂并经常引起错误,许多常见的代码因为缺乏一个框架而无法重构。因此这个框架建立起了基本的机制,所有的驱动都需要和这个框架结合以便共用其中的函数。因此 V4L2  框架作了相应的优化:它有一个 v4l2_device 结构作为设备实例,一个v4l2_subdev 结构作为子设备实例,video_device 结构包含了v4l2_device 节点,以后将会有一个 v4l2_fh 的结构作为与文件句柄的实例。每个设备都采用 v4l2_device 结构来表示。非常简单的设备都可以申请这个结构,但通常会将这个结构嵌入一个更大的结构中。
1、 video_device
在 v4l2 中用 struct video_device 代表一个视频设备,该结构说明如下:
[cpp] 
struct video_device 

    /* 设备操作合集 */ 
    const struct v4l2_file_operations *fops; 
 
    /* sysfs节点 */ 
    struct device dev;      /* v4l device */ 
    struct cdev *cdev;      /* 字符设备节点 */ 
 
    /* Set either parent or v4l2_dev if your driver uses v4l2_device */ 
    struct device *parent;      /* 父设备 */ 
    struct v4l2_device *v4l2_dev;   /* v4l2_device parent */ 
 
    /* 设备信息 */ 
    char name[32]; 
    int vfl_type; 
    /* 如果注册失败 minor 将被设置为 -1 */ 
    int minor; 
    u16 num; 
    /* 需要用位操作 flags */ 
    unsigned long flags; 
    /* attribute to differentiate multiple indices on one physical device */ 
    int index; 
 
    int debug;          /* Activates debug level*/ 
 
    /* Video standard vars */ 
    v4l2_std_id tvnorms;        /* Supported tv norms */ 
    v4l2_std_id current_norm;   /* Current tvnorm */ 
 
    /* 释放设备的回调函数 */ 
    void (*release)(struct video_device *vdev); 
 
    /* ioctl 回调函数 */ 
    const struct v4l2_ioctl_ops *ioctl_ops; 
}; 
其中 
struct cdev { 
    struct kobject kobj;    /* 内核对象 */ 
    struct module *owner; 
    const struct file_operations *ops;  /* 设备操作合集 */ 
    struct list_head list; 
    dev_t dev; 
    unsigned int count; 
}; 
 
struct v4l2_file_operations { 
    struct module *owner; 
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);        /* 读数据 */ 
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); /* 写数据 */ 
    unsigned int (*poll) (struct file *, struct poll_table_struct *);        /* 同步操作 */ 
    long (*ioctl) (struct file *, unsigned int, unsigned long);              /* 特殊命令 */ 
    long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); 
    unsigned long (*get_unmapped_area) (struct file *, unsigned long, 
                unsigned long, unsigned long, unsigned long); 
    int (*mmap) (struct file *, struct vm_area_struct *);                    /* 内存映射 */ 
    int (*open) (struct file *);                                             /* 打开设备 */ 
    int (*release) (struct file *);                                          /* 释放设备 */ 
}; 
视频设备在 linux 中作为字符设备出现,域 cdev 与 /dev/videox 节点关联,打开节点就相当于执行cdev 的 open 函数,cdev 的 ops 域即 file_operations 的一些接口在经过一定的参数过滤后最终都调用了video_device 的 fops 域即v4l2_file_operations的成员,所以在编写驱动程序的时候需要实现 v4l2_file_operations 的接口:其中 open 用于打开视频设备, read 接口用于读取视频数据,poll 接口用于视频流的同步,mmap 将视频设备的保存数据的内存空间的物理地址映射到用户空间,ioctl 用于向视频设备发送命令并查询相关信息(ioctl 一般设置为 v4l2 提供的 video_ioctl2 函数,并最终调用 video_device 的 ioctl_ops 域即 v4l2_ioctl_ops),通常需要实现的 ioctl 接口如下:
[cpp] 
static const struct v4l2_ioctl_ops xxx_cam_ioctl_ops = { 
    .vidioc_querycap         = vidioc_querycap, 
    .vidioc_enum_input       = vidioc_enum_input, 
    .vidioc_g_input          = vidioc_g_input, 
    .vidioc_s_input          = vidioc_s_input, 
    .vidioc_queryctrl        = vidioc_queryctrl, 
    .vidioc_s_ctrl           = vidioc_s_ctrl, 
    .vidioc_g_ctrl           = vidioc_g_ctrl, 
    .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, 
    .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap, 
    .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap, 
    .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap, 
    .vidioc_reqbufs          = vidioc_reqbufs, 
    .vidioc_querybuf         = vidioc_querybuf, 
    .vidioc_qbuf             = vidioc_qbuf, 
    .vidioc_dqbuf            = vidioc_dqbuf, 
    .vidioc_streamon         = vidioc_streamon, 
    .vidioc_streamoff &nbs
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,