【genius_platform软件平台开发】第五十五讲:Linux系统之V4L2视频驱动-ioctl函数代码详解

  • v4l2视频驱动的一些命令都是通过ioctl函数来实现的,比如:VIDIOC_QUERYCAP、VIDIOC_QBUF、VIDIOC_DQBUF、VIDIOC_STREAMON、VIDIOC_STREAMOFF等

1. ioctl

1.1 什么是ioctl

  • 概述: ioctl是设备驱动程序中对设备的 I/O通道进行管理的接口函数

  • 所谓对 I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。

  • 作用: 一个字符设备驱动通常会实现设备打开关闭等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。例:当你用 readwrite不能完成某一功能时,就用 ioctl来操作。
    配合一些头文件(v4l2-controls.h / videodev2.h),根据命令,实现对摄像头的操作,如:白平衡、聚焦、曝光、饱和度、亮度

#include <sys/ioctl.h>  //需要引用的头文件

//参数一:文件描述符
//参数二:设备驱动命令,执行对应操作
//参数三:根据参数二变化
int ioctl(int fd, int cmd, ...) ;

1.1 v4l2_ioctl函数

  • 只要是命令都会涉及到v4l2_ioctl方法的处理,源代码如下:
static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    // 
	struct video_device *vdev = video_devdata(filp);
	int ret = -ENODEV;

	if (vdev->fops->unlocked_ioctl) {
		struct mutex *lock = v4l2_ioctl_get_lock(vdev, cmd);

		if (lock && mutex_lock_interruptible(lock))
			return -ERESTARTSYS;
		if (video_is_registered(vdev))
			ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
			//关联文件为:./ambarella/kernel/linux-4.14/drivers/media/v4l2-core/v4l2-ioctl.c:2956:long video_ioctl2(struct file *file,
		if (lock)
			mutex_unlock(lock);
	} else
		ret = -ENOTTY;

	return ret;
}

1.2 video_ioctl2函数

v4l2-ioctl.c:文件的long video_ioctl2函数如下:

long video_ioctl2(struct file *file,
               unsigned int cmd, unsigned long arg)
{
        return video_usercopy(file, cmd, arg, __video_do_ioctl);
        // 关联文件为:./ambarella/kernel/linux-4.14/include/media/v4l2-ioctl.h:711:long int video_usercopy(struct file *file, unsigned int cmd,
}

1.3 video_usercopy函数

v4l2-ioctl.c:文件的 video_usercopy函数:

long video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, v4l2_kioctl func)
{
     ...
	// 前面都是一些检查,发现是写命令则把数据从用户空间拷贝到内核空间
	      if (copy_from_user(parg, (void __user *)arg, n))
	              goto out;
	...
    /* Handles IOCTL */
     err = func(file, cmd, parg);
}

1.4 __video_fo_ioctl函数


static long __video_do_ioctl(struct file *file,
		unsigned int cmd, void *arg)
{
	...
	default_info.ioctl = cmd;
	default_info.flags = 0;
	default_info.debug = v4l_print_default;
	info = &default_info;
	...
    // 重点执行下面的函数指针
	write_only = _IOC_DIR(cmd) == _IOC_WRITE;
	if (info->flags & INFO_FL_STD) {
		typedef int (*vidioc_op)(struct file *file, void *fh, void *p);
		const void *p = vfd->ioctl_ops;
		const vidioc_op *vidioc = p + info->u.offset;

		ret = (*vidioc)(file, fh, arg);
	} else if (info->flags & INFO_FL_FUNC) {
		ret = info->u.func(ops, file, fh, arg);
	} else if (!ops->vidioc_default) {
		ret = -ENOTTY;
	} else {
		ret = ops->vidioc_default(file, fh,
			vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
			cmd, arg);
	}

	return ret;
}
  • v4l2驱动复杂就在这些 ioctl 上,下面按照应用层与驱动的交互顺序来具体的分析这些 ioctl

2. ioctl 流程深入分析

应用空间的一个视频 app 与驱动的交互流程大致如下图所示
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隨意的風

如果你觉得有帮助,期待你的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值