三、video设备初始化

一、V4L2应用层调用流程
二、V4L2设备注册
三、video设备初始化
四、V4L2 control结构框架图
五、v4l2 ctrl 函数初始化—增加标准接口v4l2_ctrl_new_std
六、v4l2 ctrl 函数初始化—增加自定义接口v4l2_ctrl_new_custom
七、V4L2 ioctl 标准接口 调用流程
八、V4L2 ioctl 控制接口 调用流程

video_device结构体

struct video_device
{
#if defined (CONFIG_MEDIA_CONTROLLER)
	struct media_entity entity;
    struct media_intf_devnode *intf_devnode;
    struct media_pipeline pipe;
#endif
    const struct v4l2_file_operations *fops;
    u32 device_caps;
    
    /* sysfs */
    struct device dev;
    struct cdev *cdev;
    
    struct v4l2_device *v4l2_dev;
    struct device *dev_parent;
    
    struct v4l2_ctrl_handler *ctrl_handler;
    struct vb2_queue *queue;
    struct v4l2_prio_state *prio;
    
    /* device info */
    char name[32];
    int vfl_type;
    int vfl_dir;
    int minor;
    u16 num;
    unsigned long flags;
    int index;
    
    /* V4L2 file handles */
    spinlock_t		fh_lock;
    struct list_head	fh_list;
    int dev_debug;
    v4l2_std_id tvnorms;
    
    /* callbacks */
    void (*release)(struct video_device *vdev);
    const struct v4l2_ioctl_ops *ioctl_ops;
    
    DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
    DECLARE_BITMAP(disable_locking, BASE_VIDIOC_PRIVATE);
    struct mutex *lock;
};

video设备也是一个字符设备,具备字符设备的open、close、read、wirte、ioctl功能

v4l2_file_operations结构体初始化定义

struct v4l2_file_operations xxx_fops = {
    .owner = THIS_MODULE,
    .open = xxx_open,
    .release = xxx_close,
    .read = xxx_read,
    .poll = xxx_p_poll, 
    .unlocked_ioctl = video_ioctl2,
    .mmap = xxx_mmap,
};  

v4l2_ioctl_ops结构体初始化定义

struct v4l2_ioctl_ops xxx_v4l2_ioctl_ops = {
    .vidioc_querycap = xxx_v4l2_querycap,

    /* Per-stream config operations */
    .vidioc_g_fmt_vid_cap_mplane = xxx_v4l2_g_fmt_vid_cap,
    .vidioc_enum_fmt_vid_cap = xxx_v4l2_enum_fmt_vid_cap,
    .vidioc_try_fmt_vid_cap_mplane = xxx_v4l2_try_fmt_vid_cap,
    .vidioc_s_fmt_vid_cap_mplane = xxx_v4l2_s_fmt_vid_cap,

    .vidioc_g_fmt_vid_cap = xxx_v4l2_g_fmt_vid_cap,
    .vidioc_enum_fmt_vid_cap = xxx_v4l2_enum_fmt_vid_cap,
    .vidioc_try_fmt_vid_cap = xxx_v4l2_try_fmt_vid_cap,
    .vidioc_s_fmt_vid_cap = xxx_v4l2_s_fmt_vid_cap,
    .vidioc_enum_framesizes = xxx_v4l2_enum_framesizes,

    /* Per-stream control operations */
    .vidioc_streamon = xxx_v4l2_streamon,
    .vidioc_streamoff = xxx_v4l2_streamoff,

    /* input control */
    .vidioc_enum_input = xxx_v4l2_enum_input,
    .vidioc_g_input = xxx_v4l2_g_input,
    .vidioc_s_input = xxx_v4l2_s_input,

    /* vb2 customization for multi-stream support */
    .vidioc_reqbufs = xxx_v4l2_reqbufs,

    .vidioc_querybuf = xxx_v4l2_querybuf,
    .vidioc_qbuf = xxx_v4l2_qbuf,
    .vidioc_dqbuf = xxx_v4l2_dqbuf,

    /* v4l2 event ioctls */
    .vidioc_log_status = xxx_ctrl_log_status,
    .vidioc_subscribe_event = xxx_ctrl_subscribe_event,
    .vidioc_unsubscribe_event = xxx_event_unsubscribe,

    /* crop ioctls */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
    .vidioc_g_selection = xxx_v4l2_g_selection,
    .vidioc_s_selection = xxx_v4l2_s_selection,
    .vidioc_g_pixelaspect = xxx_v4l2_g_pixelaspect,
#else
    .vidioc_cropcap = xxx_v4l2_cropcap,
    .vidioc_g_crop = xxx_v4l2_g_crop,
    .vidioc_s_crop = xxx_v4l2_s_crop,
#endif
    .vidioc_expbuf = xxx_v4l2_expbuf,
};

以上的xxx函数都是各个平台最终实现的函数功能,左边的由用户程序调用到kernel驱动最终调用到平台函数

video_register_device注册

struct video_device *vdev;
    vdev= &dev->video_dev;
    strlcpy( vfd->name, "xxx", sizeof( vfd->name ) );
    vdev->fops = &xxx_v4l2_fops;
    vdev->ioctl_ops = &xxx_v4l2_ioctl_ops;
    vdev->release = video_device_release_empty;
    vdev->v4l2_dev = dev->v4l2_dev;
    vdev->queue = NULL; // queue will be customized in file handle
    vdev->tvnorms = tvnorms_cap;
    vdev->vfl_type = VFL_TYPE_GRABBER;
    vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
    //VFL_TYPE_GRABBER代表注册的是video节点
    //0代表的是注册video0节点
    video_register_device( vdev, VFL_TYPE_GRABBER, 0);//代表创建注册video0节点
static inline int __must_check video_register_device(struct video_device *vdev, int type, int nr)
{
	return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);
}
int __video_register_device(struct video_device *vdev, int type, int nr, int warn_if_nr_use, struct module *owner)
{
	...
	/* v4l2_fh support */
	spin_lock_init(&vdev->fh_lock);
	INIT_LIST_HEAD(&vdev->fh_list);
	switch(type)
	{
		case VFL_TYPE_GRABBER:
			name_base = "video";
			break;
	}
	...
	vdev->vfl_type = type;
	vdev->cdev = NULL;
	if (vdev->dev_parent == NULL)
		vdev->dev_parent = vdev->v4l2_dev->dev;
	if (vdev->ctrl_handler == NULL)
		vdev->ctrl_handler = vdev->vdev_dev->ctrl_handler;
	if (vdev->prio == NULL)
		vdev->prio = &vdev->v4l2_dev->prio;
	
	switch (type) {
		case VFL_TYPE_GRABBER:
			minor_offset = 0;
			minor_cnt = 64;
			break;
	}
	...
	vdev->minor = i + minor_offset;
	vdev->num = nr;
	    devnode_set(vdev);
    video_device[vdev->minor] = vdev;//把vdev保存到了 video_device[x]
    ...
    vdev->cdev->ops = &v4l2_fops;
    ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
    vdev->dev.class = &video_class;
    vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
    vdev->dev.parent = vdev->dev_parent;
    dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
    ret = device_register(&vdev->dev);
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值