【问题标题】:Adding custom V4L2 Controls After V4L2 handler setup在 V4L2 处理程序设置后添加自定义 V4L2 控件
【发布时间】:2021-05-04 14:49:48
【问题描述】:

总结

我目前正在尝试在 Linux 内核驱动程序中调用 v4l2_ctrl_handler_setup 后将自定义 V4L2 控件添加到 V4L2 设备。但是似乎没有添加控件(运行v4l2-ctl --list-ctrls 时不显示)。以下是我尝试采用的一般方法。

static int add_custom_v4l2_ctrls(struct tegracam_device *tc_dev)
{
    struct camera_common_data *s_data = tc_dev->s_data;
    struct v4l2_ctrl_handler *ctrl_handler = s_data->ctrl_handler;
    struct v4l2_ctrl *ctrl;
    int err = 0;

    static struct v4l2_ctrl_config my_control = {
        .ops = &my_custom_ctrl_ops,
        .id = TEGRA_CAMERA_CID_BASE+150,
        .name = "My control",
        .type = V4L2_CTRL_TYPE_INTEGER,
        .flags = V4L2_CTRL_FLAG_SLIDER,
        .min = 0,
        .max = 1,
        .def = 0,
        .step = 1,
    };

    // Increment number of controls
    tc_dev->numctrls++;
    s_data->numctrls++;

    ctrl = v4l2_ctrl_new_custom(ctrl_handler, &my_control, NULL);
    if(ctrl == NULL) {
        dev_err(tc_dev->dev, "Failed to init ctrl");
        return -EIO;
    }

    // err = v4l2_ctrl_handler_setup(ctrl_handler);
    if(err) {
        printk("FAILED");
    }

    return 0;
}

此代码 sn-p 在有效调用 v4l2_ctrl_handler_setupv4l2_async_register_subdev 后运行。

问题

是否可以在设备注册后添加自定义 V4L2 控件?如果是这样,我的方法有什么问题导致控件不显示?

更多信息

此驱动程序是使用 NVIDIA 的 Tegracam V2 框架实现的,该框架抽象了 V4L2 设置代码,包括添加控件,目前它不公开添加自定义 V4L2 控件的能力,这是这种方法背后的原因。

【问题讨论】:

    标签: linux-kernel linux-device-driver nvidia-jetson tegra


    【解决方案1】:

    这可能来得有点晚,因为您已经标记了一个解决方案,但我相信我有一个可以提供帮助的解决方案。我会尽力解释我是如何将自定义控件添加到 tegracamv2 框架的。

    不幸的是,在v4l2_async_register_subdev 注册子设备后,您无法添加控件,但是,您可以使用tc_dev 结构的v4l2sd_internal_ops 字段中定义的注册回调挂钩到异步框架。这允许您定义自己的控制处理程序,然后将其从 tegracam 框架添加到控制处理程序,然后将其添加到 v4l2 设备。

    我最近为此苦苦挣扎,我发现这是我唯一的解决方案,除了在 tegracam 框架中修补对 v4l2_async_register_subdev 的调用并在添加控件后手动调用它(这是未经测试的)。

    相关代码(假设数组为ctrl_config,但展示了这个想法。我还假设你已经定义了ctrl_ops和configs。):

    static int my_subdev_register(struct v4l2_subdev *sd)
    {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct camera_common_data *s_data = to_camera_common_data(&client->dev);
        struct my_priv *priv = (struct my_priv *)s_data->priv;
        struct v4l2_ctrl *ctrl;
        int err, i, num_ctrls;
    
        // setup custom controls
        num_ctrls = ARRAY_SIZE(ctrl_config_list);
        v4l2_ctrl_handler_init(&priv->ctrl_handler, num_ctrls);
    
        for (i = 0; i < num_ctrls; i++) {
            ctrl = v4l2_ctrl_new_custom(&priv->ctrl_handler,
                &ctrl_config_list[i], NULL);
            if (ctrl == NULL) {
                dev_err(&client->dev, "Failed to init %s ctrl\n",
                    ctrl_config_list[i].name);
                continue;
            }
            if (err)
                return err;
            // I believe storing the pointer is technically optional
            priv->ctrls[i] = ctrl;
        }
    
        priv->num_ctrls = num_ctrls;
        //This is where the magic happens
        err = v4l2_ctrl_add_handler(
                sd->ctrl_handler,
                &priv->ctrl_handler,
                NULL);
        if (err)
            goto error;
        return 0;
    error:
        v4l2_ctrl_handler_free(&priv->ctrl_handler);
        return err;
    }
    ...
    static const struct v4l2_subdev_internal_ops my_subdev_internal_ops = {
        .registered = my_subdev_register,
    };
    
    

    然后在探测函数中在tegracam_device_register 之前包含以下内容。 (但不会在tegracam_v4l2subdev_register之前调用。)

    tc_dev->sensor_ops = &my_subdev_internal_ops;
    

    【讨论】:

    • 感谢您的建议,我最终稍微调整了 tegracam 源,以便用户可以指定自定义命令列表,然后 tegracam 添加到 V4L2,类似于 V1 中处理自定义命令的方式tegracam 框架。
    【解决方案2】:

    在跟踪调用堆栈后,我找到了这个顺序(箭头代表调用,链接指向 Linux 源代码)。

    v4l2_async_register_subdev -> v4l2_async_match_notify -> v4l2_device_register_subdev -> v4l2_ctrl_add_handler

    最后一个函数 (v4l2_ctrl_add_handler) 通过并将 V4L2 控件从一个处理程序复制到另一个处理程序。

    因此,如果在调用 v4l2_async_register_subdev 之前未添加 V4L2 控件,则该控件将不会被复制到不同的设备,因此将不是可用的有效选项。

    所以从我发现的总结来看,不,在设备注册后不可能添加 V4L2 控件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      • 2014-11-22
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      • 1970-01-01
      • 2020-10-05
      相关资源
      最近更新 更多