如何解决在 V4L2 处理程序设置后添加自定义 V4L2 控件
总结
我目前正在尝试在 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;
}
此代码段在有效调用 v4l2_ctrl_handler_setup
和 v4l2_async_register_subdev
后运行。
问题
是否可以在设备注册后添加自定义 V4L2 控件?如果是这样,我的方法有什么问题导致控件不显示?
更多信息
此驱动程序是使用 NVIDIA 的 Tegracam V2 框架实现的,该框架抽象了 V4L2 设置代码,包括添加控件,目前它没有公开添加自定义 V4L2 控件的能力,这是这种方法背后的原因。
解决方法
这可能来得有点晚,因为您已经标记了一个解决方案,但我相信我有一个可以提供帮助的解决方案。我将尽力解释我是如何向 tegracamv2 框架添加自定义控件的。
很遗憾,您无法在 v4l2_async_register_subdev
注册子设备后添加控件,但是您可以使用 v4l2sd_internal_ops
结构的 tc_dev
字段中定义的注册回调挂钩到异步框架.这允许您定义自己的控制处理程序,然后将其添加到来自 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;
,
在跟踪调用堆栈后,我找到了这个顺序(箭头代表调用,链接指向 Linux 源代码)。
v4l2_async_register_subdev -> v4l2_async_match_notify -> v4l2_device_register_subdev -> v4l2_ctrl_add_handler
最后一个函数 (v4l2_ctrl_add_handler) 执行并将 V4L2 控件从一个处理程序复制到另一个处理程序。
因此,如果在调用 Phaser
之前未添加 V4L2 控件,则该控件将不会被复制到不同的设备,因此将不是有效的可用选项。
因此,根据我的发现,不可以在设备注册后添加 V4L2 控件。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。