• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

八、V4L2 ioctl 控制接口 调用流程

武飞扬头像
zzsyxl
帮助1

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

V4L2 ioctl 控制接口 调用流程

当 使用v4l2打开配置好video节点后,还可能需要对设备进行参数 sensor 或者ISP的参数配置,例如自动对焦、自动曝光、亮度、对比度、锐度、色度、白平衡、测试图案等等

V4L2_CID_BRIGHTNESS

我们举例 设置亮度

static void set_sensor_brightness(int videofd, int brightness)
{
    struct v4l2_control ctrl;

    ctrl.id = V4L2_CID_BRIGHTNESS;
    ctrl.value = brightness;

    if (-1 == ioctl (videofd, VIDIOC_S_CTRL, &ctrl)) {
        printf("Do sensor brightness failed\n");
    }
}

VIDIOC_S_CTRL跟前面七、V4L2 ioctl 标准接口 调用流程 一样
不过ret = info->func(ops, file, fh, arg); 函数调用的是 v4l_s_ctrl

v4l_s_ctrl

static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
{
	struct video_device *vfd = video_devdata(file);
	struct v4l2_control *p = arg;
	struct v4l2_fh *vfh =
                test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
	struct v4l2_ext_controls ctrls;
    struct v4l2_ext_control ctrl;

        if (vfh && vfh->ctrl_handler)
                return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p);
        if (vfd->ctrl_handler)
                return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p);
        if (ops->vidioc_s_ctrl)
                return ops->vidioc_s_ctrl(file, fh, p);
        if (ops->vidioc_s_ext_ctrls == NULL)
                return -ENOTTY;

        ctrls.which = V4L2_CTRL_ID2WHICH(p->id);
        ctrls.count = 1;
        ctrls.controls = &ctrl;
        ctrl.id = p->id;
        ctrl.value = p->value;
        if (check_ext_ctrls(&ctrls, 1))
                return ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
        return -EINVAL;
}
学新通

v4l2_s_ctrl(vfh, vfh->ctrl_handler, p);

int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
                                        struct v4l2_control *control)
{
        struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
        struct v4l2_ext_control c = { control->id };
        int ret;

        if (ctrl == NULL || !ctrl->is_int)
                return -EINVAL;

        if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
                return -EACCES;

        c.value = control->value;
        ret = set_ctrl_lock(fh, ctrl, &c);
        control->value = c.value;
        return ret;
}
学新通

set_ctrl_lock

static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
                         struct v4l2_ext_control *c)
{
        int ret;

        v4l2_ctrl_lock(ctrl);
        user_to_new(c, ctrl);
        ret = set_ctrl(fh, ctrl, 0);
        if (!ret)
                cur_to_user(c, ctrl);
        v4l2_ctrl_unlock(ctrl);
        return ret;
}

set_ctrl

static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
{
        struct v4l2_ctrl *master = ctrl->cluster[0];
        int ret;
        int i;

        /* Reset the 'is_new' flags of the cluster */
        for (i = 0; i < master->ncontrols; i  )
                if (master->cluster[i])
                        master->cluster[i]->is_new = 0;

        ret = validate_new(ctrl, ctrl->p_new);
        if (ret)
                return ret;

        /* For autoclusters with volatiles that are switched from auto to
           manual mode we have to update the current volatile values since
           those will become the initial manual values after such a switch. */
        if (master->is_auto && master->has_volatiles && ctrl == master &&
            !is_cur_manual(master) && ctrl->val == master->manual_mode_value)
                update_from_auto_cluster(master);

        ctrl->is_new = 1;
        return try_or_set_cluster(fh, master, true, ch_flags);
}
学新通

try_or_set_cluster

static int try_or_set_cluster(struct v4l2_fh *fh, struct v4l2_ctrl *master,
                              bool set, u32 ch_flags)
{
   ...
    ret = call_op(master, s_ctrl);
}

#define has_op(master, op) \
        (master->ops && master->ops->op)
#define call_op(master, op) \
        (has_op(master, op) ? master->ops->op(master) : 0)
//这里面的master就是 v4l2_ctrl,指向的ops就是 初始化增加一个ctrl的

那这个call_op(master, op)最终的调用地方就是到
static int xxx_v4l2_ctrl_s_ctrl_standard( struct v4l2_ctrl *ctrl )
{
    switch ( ctrl->id ) {
    	case V4L2_CID_BRIGHTNESS:
        	xxx
        break;
}
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakbji
系列文章
更多 icon
同类精品
更多 icon
继续加载