2.15. V4L2 控制¶
2.15.1. 简介¶
V4L2 控制 API 看起来足够简单,但很快就变得很难在驱动程序中正确实现。 但是,处理控件所需的大部分代码实际上并非特定于驱动程序,可以移动到 V4L 核心框架。
毕竟,驱动程序开发人员唯一感兴趣的部分是
如何添加控件?
如何设置控件的值?(即 s_ctrl)
偶尔
如何获取控件的值?(即 g_volatile_ctrl)
如何验证用户建议的控件值?(即 try_ctrl)
其余部分是可以在中心完成的事情。
创建控制框架是为了在中心位置实现有关控件的 V4L2 规范的所有规则。 并使驱动程序开发人员的生活尽可能轻松。
请注意,控制框架依赖于 V4L2 驱动程序的 v4l2_device
结构和子设备驱动程序的 struct v4l2_subdev
结构。
2.15.2. 框架中的对象¶
有两个主要对象
v4l2_ctrl
对象描述控件属性并跟踪控件的值(当前值和建议的新值)。
v4l2_ctrl_handler
是跟踪控件的对象。 它维护一个它拥有的 v4l2_ctrl 对象列表和另一个对控件的引用列表,可能指向其他处理程序拥有的控件。
2.15.3. V4L2 和子设备驱动程序的基本用法¶
准备驱动程序
#include <media/v4l2-ctrls.h>
1.1) 将处理程序添加到驱动程序的顶层结构
对于 V4L2 驱动程序
struct foo_dev {
...
struct v4l2_device v4l2_dev;
...
struct v4l2_ctrl_handler ctrl_handler;
...
};
对于子设备驱动程序
struct foo_dev {
...
struct v4l2_subdev sd;
...
struct v4l2_ctrl_handler ctrl_handler;
...
};
1.2) 初始化处理程序
v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
第二个参数是一个提示,告诉函数该处理程序预计处理多少个控件。 它将基于此信息分配一个哈希表。 这只是一个提示。
1.3) 将控制处理程序挂接到驱动程序中
对于 V4L2 驱动程序
foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler;
对于子设备驱动程序
foo->sd.ctrl_handler = &foo->ctrl_handler;
1.4) 最后清理处理程序
v4l2_ctrl_handler_free(&foo->ctrl_handler);
添加控件
通过调用 v4l2_ctrl_new_std()
添加非菜单控件
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s32 min, s32 max, u32 step, s32 def);
通过调用 v4l2_ctrl_new_std_menu()
添加菜单和整数菜单控件
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s32 max, s32 skip_mask, s32 def);
通过调用 v4l2_ctrl_new_std_menu_items()
添加具有驱动程序特定菜单的菜单控件
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(
struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
s32 skip_mask, s32 def, const char * const *qmenu);
通过调用 v4l2_ctrl_new_std_compound()
添加标准复合控件
struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, u32 id,
const union v4l2_ctrl_ptr p_def);
通过调用 v4l2_ctrl_new_int_menu()
添加具有驱动程序特定菜单的整数菜单控件
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s32 max, s32 def, const s64 *qmenu_int);
这些函数通常在 v4l2_ctrl_handler_init()
之后立即调用
static const s64 exp_bias_qmenu[] = {
-2, -1, 0, 1, 2
};
static const char * const test_pattern[] = {
"Disabled",
"Vertical Bars",
"Solid Black",
"Solid White",
};
v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
V4L2_CID_CONTRAST, 0, 255, 1, 128);
v4l2_ctrl_new_std_menu(&foo->ctrl_handler, &foo_ctrl_ops,
V4L2_CID_POWER_LINE_FREQUENCY,
V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
v4l2_ctrl_new_int_menu(&foo->ctrl_handler, &foo_ctrl_ops,
V4L2_CID_EXPOSURE_BIAS,
ARRAY_SIZE(exp_bias_qmenu) - 1,
ARRAY_SIZE(exp_bias_qmenu) / 2 - 1,
exp_bias_qmenu);
v4l2_ctrl_new_std_menu_items(&foo->ctrl_handler, &foo_ctrl_ops,
V4L2_CID_TEST_PATTERN, ARRAY_SIZE(test_pattern) - 1, 0,
0, test_pattern);
...
if (foo->ctrl_handler.error) {
int err = foo->ctrl_handler.error;
v4l2_ctrl_handler_free(&foo->ctrl_handler);
return err;
}
v4l2_ctrl_new_std()
函数返回指向新控件的 v4l2_ctrl 指针,但是如果不需要在控件操作之外访问该指针,则无需存储它。
v4l2_ctrl_new_std()
函数将根据控件 ID 填充大多数字段,但最小值、最大值、步长和默认值除外。 这些在最后四个参数中传递。 这些值是特定于驱动程序的,而诸如类型、名称、标志之类的控件属性都是全局的。 控件的当前值将设置为默认值。
v4l2_ctrl_new_std_menu()
函数非常相似,但用于菜单控件。 没有最小参数,因为对于菜单控件,该参数始终为 0,并且没有步长,而是有一个 skip_mask 参数:如果位 X 为 1,则跳过菜单项 X。
v4l2_ctrl_new_int_menu()
函数创建一个新的标准整数菜单控件,其中菜单中包含驱动程序特定的项目。 它与 v4l2_ctrl_new_std_menu 的不同之处在于它没有掩码参数,而是将一个有符号的 64 位整数数组作为最后一个参数,该数组构成一个精确的菜单项列表。
v4l2_ctrl_new_std_menu_items()
函数与 v4l2_ctrl_new_std_menu 非常相似,但是采用了一个额外的参数 qmenu,该参数是用于其他标准菜单控件的驱动程序特定菜单。 此控件的一个很好的例子是捕获/显示/传感器设备的测试模式控件,这些设备具有生成测试模式的功能。 这些测试模式是硬件特定的,因此菜单的内容会因设备而异。
请注意,如果发生错误,该函数将返回 NULL 或错误,并将 ctrl_handler->error 设置为错误代码。 如果已经设置了 ctrl_handler->error,那么它将只返回而不执行任何操作。 如果无法分配内部数据结构,则 v4l2_ctrl_handler_init 也是如此。
这使得初始化处理程序并添加所有控件,最后只检查错误代码变得很容易。 节省了很多重复的错误检查。
建议以升序控件 ID 添加控件:这样会更快一些。
可选地强制初始控件设置
v4l2_ctrl_handler_setup(&foo->ctrl_handler);
这将无条件地为所有控件调用 s_ctrl。 实际上,这会将硬件初始化为默认的控件值。 建议您这样做,因为这可以确保内部数据结构和硬件同步。
最后:实现
v4l2_ctrl_ops
static const struct v4l2_ctrl_ops foo_ctrl_ops = {
.s_ctrl = foo_s_ctrl,
};
通常,您只需要 s_ctrl
static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
write_reg(0x123, ctrl->val);
break;
case V4L2_CID_CONTRAST:
write_reg(0x456, ctrl->val);
break;
}
return 0;
}
使用 v4l2_ctrl 指针作为参数调用控制操作。 新的控件值已经过验证,因此您所需要做的就是实际更新硬件寄存器。
您完成了! 这对于我们拥有的大多数驱动程序来说已经足够了。 无需对控件值进行任何验证,或实现 QUERYCTRL、QUERY_EXT_CTRL 和 QUERYMENU。 并且会自动支持 G/S_CTRL 以及 G/TRY/S_EXT_CTRLS。
注意
其余部分讨论了更高级的控制主题和场景。 实际上,如上所述的基本用法对于大多数驱动程序来说已经足够了。
2.15.4. 继承子设备控件¶
当子设备通过调用 v4l2_device_register_subdev()
注册到 V4L2 驱动程序,并且 v4l2_subdev 和 v4l2_device 的 ctrl_handler 字段都被设置时,子设备的控件也会自动在 V4L2 驱动程序中可用。如果子设备驱动程序包含 V4L2 驱动程序中已存在的控件,则这些控件将被跳过(因此 V4L2 驱动程序始终可以覆盖子设备控件)。
这里发生的是,v4l2_device_register_subdev()
调用 v4l2_ctrl_add_handler()
将子设备的控件添加到 v4l2_device 的控件中。
2.15.5. 访问控制值¶
以下联合体在控制框架内部用于访问控制值
union v4l2_ctrl_ptr {
s32 *p_s32;
s64 *p_s64;
char *p_char;
void *p;
};
v4l2_ctrl 结构包含以下字段,可用于访问当前值和新值
s32 val;
struct {
s32 val;
} cur;
union v4l2_ctrl_ptr p_new;
union v4l2_ctrl_ptr p_cur;
如果控件具有简单的 s32 类型,则
&ctrl->val == ctrl->p_new.p_s32
&ctrl->cur.val == ctrl->p_cur.p_s32
对于所有其他类型,请使用 ctrl->p_cur.p
在控制操作中,你可以自由使用这些。val 和 cur.val 的含义是不言自明的。p_char 指针指向长度为 ctrl->maximum + 1 的字符缓冲区,并且始终以 0 结尾。
除非控件被标记为易失性,否则 p_cur 字段指向当前缓存的控制值。当你创建一个新控件时,此值与默认值相同。调用 v4l2_ctrl_handler_setup()
后,此值将传递给硬件。通常最好调用此函数。
每当设置新值时,新值会自动缓存。这意味着大多数驱动程序不需要实现 g_volatile_ctrl() 操作。例外情况是返回易失性寄存器的控件,例如持续变化的信号强度读数。在这种情况下,你需要像这样实现 g_volatile_ctrl
static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->val = read_reg(0x123);
break;
}
}
请注意,你也在 g_volatile_ctrl 中使用“新值”联合体。一般来说,需要实现 g_volatile_ctrl 的控件是只读控件。如果它们不是只读的,则当控件更改时不会生成 V4L2_EVENT_CTRL_CH_VALUE。
要将控件标记为易失性,你必须设置 V4L2_CTRL_FLAG_VOLATILE
ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
if (ctrl)
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
对于 try/s_ctrl,新值(即用户传递的值)会被填充,你可以在 try_ctrl 中修改它们,或者在 s_ctrl 中设置它们。“cur”联合体包含当前值,你也可以使用它(但不能更改!)。
如果 s_ctrl 返回 0 (OK),则控制框架会将新的最终值复制到“cur”联合体。
在 g_volatile/s/try_ctrl 中,你可以访问同一处理程序拥有的所有控件的值,因为处理程序的锁已被持有。如果你需要访问其他处理程序拥有的控件的值,则必须非常小心,不要引入死锁。
在控制操作之外,你必须通过辅助函数在驱动程序中安全地获取或设置单个控件值
s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
这些函数通过控制框架,就像 VIDIOC_G/S_CTRL ioctl 一样。但是,不要在控制操作 g_volatile/s/try_ctrl 中使用这些,因为这些辅助函数也会锁定处理程序,这将导致死锁。
你也可以自己获取处理程序锁
mutex_lock(&state->ctrl_handler.lock);
pr_info("String value is '%s'\n", ctrl1->p_cur.p_char);
pr_info("Integer value is '%s'\n", ctrl2->cur.val);
mutex_unlock(&state->ctrl_handler.lock);
2.15.7. 自定义控件¶
可以使用 v4l2_ctrl_new_custom()
创建驱动程序特定的控件
static const struct v4l2_ctrl_config ctrl_filter = {
.ops = &ctrl_custom_ops,
.id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
.name = "Spatial Filter",
.type = V4L2_CTRL_TYPE_INTEGER,
.flags = V4L2_CTRL_FLAG_SLIDER,
.max = 15,
.step = 1,
};
ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_filter, NULL);
最后一个参数是 priv 指针,可以将其设置为驱动程序特定的私有数据。
v4l2_ctrl_config 结构还有一个字段用于设置 is_private 标志。
如果未设置 name 字段,则框架将假定这是一个标准控件,并相应地填充 name、type 和 flags 字段。
2.15.8. 活动和抓取的控件¶
如果控件之间存在更复杂的关系,则可能需要激活和停用控件。例如,如果 Chroma AGC 控件处于开启状态,则 Chroma Gain 控件处于非活动状态。也就是说,你可以设置它,但只要自动增益控制处于开启状态,硬件就不会使用该值。通常,用户界面可以禁用此类输入字段。
你可以使用 v4l2_ctrl_activate()
设置“活动”状态。默认情况下,所有控件都是活动的。请注意,框架不会检查此标志。它仅用于 GUI。该函数通常在 s_ctrl 中调用。
另一个标志是“抓取”标志。抓取的控件意味着你无法更改它,因为它正在被某些资源使用。典型的例子是 MPEG 比特率控件,在捕获进行时无法更改。
如果使用 v4l2_ctrl_grab()
将控件设置为“抓取”,则如果尝试设置此控件,框架将返回 -EBUSY。v4l2_ctrl_grab()
函数通常在驱动程序启动或停止流式传输时调用。
2.15.9. 控件集群¶
默认情况下,所有控件都是彼此独立的。但是在更复杂的场景中,你可能会得到从一个控件到另一个控件的依赖关系。在这种情况下,你需要“集群”它们
struct foo {
struct v4l2_ctrl_handler ctrl_handler;
#define AUDIO_CL_VOLUME (0)
#define AUDIO_CL_MUTE (1)
struct v4l2_ctrl *audio_cluster[2];
...
};
state->audio_cluster[AUDIO_CL_VOLUME] =
v4l2_ctrl_new_std(&state->ctrl_handler, ...);
state->audio_cluster[AUDIO_CL_MUTE] =
v4l2_ctrl_new_std(&state->ctrl_handler, ...);
v4l2_ctrl_cluster(ARRAY_SIZE(state->audio_cluster), state->audio_cluster);
从现在开始,每当设置(或“获取”或“尝试”)属于同一集群的一个或多个控件时,只会调用第一个控件(本例中为“volume”)的控件操作。你实际上创建了一个新的复合控件。类似于 C 中“struct”的工作方式。
因此,当以 V4L2_CID_AUDIO_VOLUME 作为参数调用 s_ctrl 时,你应该设置属于 audio_cluster 的所有两个控件
static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler);
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME: {
struct v4l2_ctrl *mute = ctrl->cluster[AUDIO_CL_MUTE];
write_reg(0x123, mute->val ? 0 : ctrl->val);
break;
}
case V4L2_CID_CONTRAST:
write_reg(0x456, ctrl->val);
break;
}
return 0;
}
在上面的示例中,以下对于 VOLUME 情况是等效的
ctrl == ctrl->cluster[AUDIO_CL_VOLUME] == state->audio_cluster[AUDIO_CL_VOLUME]
ctrl->cluster[AUDIO_CL_MUTE] == state->audio_cluster[AUDIO_CL_MUTE]
实际上,像这样使用集群数组会变得非常繁琐。因此,可以使用以下等效方法
struct {
/* audio cluster */
struct v4l2_ctrl *volume;
struct v4l2_ctrl *mute;
};
匿名结构用于清楚地“集群”这两个控件指针,但它没有其他用途。效果与创建包含两个控件指针的数组相同。所以你可以直接这样做
state->volume = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
state->mute = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
v4l2_ctrl_cluster(2, &state->volume);
在 foo_s_ctrl 中,你可以直接使用这些指针:state->mute->val。
请注意,集群中的控件可能为 NULL。例如,如果由于某种原因从未添加静音(因为硬件不支持该特定功能),则静音将为 NULL。因此,在这种情况下,我们有一个包含 2 个控件的集群,其中实际上只实例化了 1 个。唯一的限制是集群的第一个控件必须始终存在,因为它是集群的“主”控件。主控件是标识集群并提供用于该集群的 v4l2_ctrl_ops 结构指针的控件。
显然,集群数组中的所有控件都必须初始化为有效的控件或 NULL。
在极少数情况下,你可能想知道用户实际明确设置了集群中的哪些控件。为此,你可以检查每个控件的“is_new”标志。例如,在音量/静音集群的情况下,如果用户仅为静音调用 VIDIOC_S_CTRL,则静音控件的“is_new”标志将被设置。如果用户为静音和音量控件调用 VIDIOC_S_EXT_CTRLS,则两个控件的“is_new”标志都将为 1。
从 v4l2_ctrl_handler_setup()
调用时,“is_new”标志始终为 1。
2.15.10. 使用自动集群处理自动增益/增益类型控件¶
一种常见的控件集群类型是处理“auto-foo/foo”类型控件的集群。典型的例子是自动增益/增益、自动曝光/曝光、自动白平衡/红色平衡/蓝色平衡。在所有情况下,你都有一个控件来确定另一个控件是由硬件自动处理,还是由用户手动控制。
如果集群处于自动模式,则手动控件应标记为非活动状态和易失性。读取易失性控件时,g_volatile_ctrl 操作应返回硬件自动模式自动设置的值。
如果将集群置于手动模式,则手动控件应再次变为活动状态,并且清除易失性标志(因此,在手动模式下不再调用 g_volatile_ctrl)。此外,在切换到手动模式之前,将由自动模式确定的当前值复制为新的手动值。
最后,应为自动控件设置 V4L2_CTRL_FLAG_UPDATE,因为更改该控件会影响手动控件的控件标志。
为了简化此操作,引入了 v4l2_ctrl_cluster 的特殊变体
void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
u8 manual_val, bool set_volatile);
前两个参数与 v4l2_ctrl_cluster 相同。第三个参数告诉框架哪个值将集群切换到手动模式。最后一个参数将可选地为非自动控制设置 V4L2_CTRL_FLAG_VOLATILE 标志。如果它为 false,则手动控制永远不是易失的。如果硬件不提供读取自动模式确定的值的选项(例如,如果自动增益开启,硬件不允许您获取当前的增益值),则通常会使用该选项。
集群的第一个控件被认为是“自动”控件。
使用此函数将确保您无需处理所有复杂的标志和易失性处理。
2.15.11. VIDIOC_LOG_STATUS 支持¶
此 ioctl 允许您将驱动程序的当前状态转储到内核日志。 v4l2_ctrl_handler_log_status(ctrl_handler, prefix) 可用于将给定处理程序拥有的控件的值转储到日志。您也可以提供前缀。如果前缀没有以空格结尾,则将为您添加“: ”。
2.15.12. 不同视频节点的不同处理程序¶
通常,V4L2 驱动程序只有一个全局用于所有视频节点的控件处理程序。但是,您也可以为不同的视频节点指定不同的控件处理程序。您可以通过手动设置 struct video_device
的 ctrl_handler 字段来实现。
如果没有涉及子设备,那没有问题,但是如果涉及子设备,则需要阻止子设备控件自动合并到全局控件处理程序。您只需将 struct v4l2_device
中的 ctrl_handler 字段设置为 NULL 即可。现在,v4l2_device_register_subdev()
将不再合并子设备控件。
添加每个子设备后,您必须手动调用 v4l2_ctrl_add_handler,将子设备的控件处理程序 (sd->ctrl_handler) 添加到所需的控件处理程序。此控件处理程序可能是特定于 video_device 的,也可能是特定于 video_device 子集的。例如:无线电设备节点只有音频控件,而视频和 VBI 设备节点共享用于音频和视频控件的相同控件处理程序。
如果希望一个处理程序(例如,用于无线电设备节点)具有另一个处理程序(例如,用于视频设备节点)的子集,则应首先将控件添加到第一个处理程序,将其他控件添加到第二个处理程序,最后将第一个处理程序添加到第二个处理程序。例如
v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_VOLUME, ...);
v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...);
v4l2_ctrl_add_handler(&video_ctrl_handler, &radio_ctrl_handler, NULL);
v4l2_ctrl_add_handler()
的最后一个参数是一个过滤器函数,允许您过滤将添加哪些控件。如果您想添加所有控件,请将其设置为 NULL。
或者您可以将特定控件添加到处理程序
volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...);
您不应该做的是为两个处理程序创建两个相同的控件。例如
v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_AUDIO_MUTE, ...);
这样做会很糟糕,因为使无线电静音不会更改视频静音控件。规则是为每个可以扭动的硬件“旋钮”设置一个控件。
2.15.13. 查找控件¶
通常,您自己创建了控件,并且可以将 struct v4l2_ctrl
指针存储到您自己的结构中。
但是,有时您需要从您不拥有的另一个处理程序中查找控件。例如,如果您必须从子设备查找音量控制。
您可以通过调用 v4l2_ctrl_find 来实现
struct v4l2_ctrl *volume;
volume = v4l2_ctrl_find(sd->ctrl_handler, V4L2_CID_AUDIO_VOLUME);
由于 v4l2_ctrl_find 将锁定处理程序,因此您必须小心使用它的位置。例如,这不是一个好主意
struct v4l2_ctrl_handler ctrl_handler;
v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);
v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...);
...并在 video_ops.s_ctrl 中
case V4L2_CID_BRIGHTNESS:
contrast = v4l2_find_ctrl(&ctrl_handler, V4L2_CID_CONTRAST);
...
当框架调用 s_ctrl 时,ctrl_handler.lock 已被获取,因此尝试从同一处理程序中查找另一个控件将导致死锁。
建议不要从控件操作内部使用此函数。
2.15.14. 防止控件继承¶
当使用 v4l2_ctrl_add_handler 将一个控件处理程序添加到另一个控件处理程序时,默认情况下,一个控件处理程序中的所有控件都将合并到另一个控件处理程序中。但是,子设备可能具有对于某些高级嵌入式系统有意义的低级控件,但在消费级硬件中使用时则不然。在这种情况下,您希望将这些低级控件保留在子设备本地。您只需将控件的 “is_private” 标志设置为 1 即可实现此目的
static const struct v4l2_ctrl_config ctrl_private = {
.ops = &ctrl_custom_ops,
.id = V4L2_CID_...,
.name = "Some Private Control",
.type = V4L2_CTRL_TYPE_INTEGER,
.max = 15,
.step = 1,
.is_private = 1,
};
ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_private, NULL);
当调用 v4l2_ctrl_add_handler 时,将跳过这些控件。
2.15.15. V4L2_CTRL_TYPE_CTRL_CLASS 控件¶
GUI 可以使用此类型的控件来获取控件类的名称。功能齐全的 GUI 可以创建一个具有多个选项卡的对话框,每个选项卡包含属于特定控件类的控件。可以通过查询 ID 为 <控件类 | 1> 的特殊控件来查找每个选项卡的名称。
驱动程序不必关心这一点。每当添加属于新控件类的第一个控件时,框架都会自动添加此类型的控件。
2.15.16. 添加通知回调¶
有时,当子设备驱动程序的控件发生更改时,平台或桥接驱动程序需要收到通知。您可以通过调用此函数来设置通知回调
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl,
void (*notify)(struct v4l2_ctrl *ctrl, void *priv), void *priv);
每当给定控件的值发生更改时,将调用通知回调,并传入一个指向该控件的指针和使用 v4l2_ctrl_notify 传递的 priv 指针。请注意,调用通知函数时会保持控件的处理程序锁。
每个控件处理程序只能有一个通知函数。任何尝试设置另一个通知函数的尝试都将导致 WARN_ON。
2.15.17. v4l2_ctrl 函数和数据结构¶
-
union v4l2_ctrl_ptr¶
指向控件值的指针。
定义:
union v4l2_ctrl_ptr {
s32 *p_s32;
s64 *p_s64;
u8 *p_u8;
u16 *p_u16;
u32 *p_u32;
char *p_char;
struct v4l2_ctrl_mpeg2_sequence *p_mpeg2_sequence;
struct v4l2_ctrl_mpeg2_picture *p_mpeg2_picture;
struct v4l2_ctrl_mpeg2_quantisation *p_mpeg2_quantisation;
struct v4l2_ctrl_fwht_params *p_fwht_params;
struct v4l2_ctrl_h264_sps *p_h264_sps;
struct v4l2_ctrl_h264_pps *p_h264_pps;
struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix;
struct v4l2_ctrl_h264_slice_params *p_h264_slice_params;
struct v4l2_ctrl_h264_decode_params *p_h264_decode_params;
struct v4l2_ctrl_h264_pred_weights *p_h264_pred_weights;
struct v4l2_ctrl_vp8_frame *p_vp8_frame;
struct v4l2_ctrl_hevc_sps *p_hevc_sps;
struct v4l2_ctrl_hevc_pps *p_hevc_pps;
struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params;
struct v4l2_ctrl_vp9_compressed_hdr *p_vp9_compressed_hdr_probs;
struct v4l2_ctrl_vp9_frame *p_vp9_frame;
struct v4l2_ctrl_hdr10_cll_info *p_hdr10_cll;
struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering;
struct v4l2_area *p_area;
struct v4l2_ctrl_av1_sequence *p_av1_sequence;
struct v4l2_ctrl_av1_tile_group_entry *p_av1_tile_group_entry;
struct v4l2_ctrl_av1_frame *p_av1_frame;
struct v4l2_ctrl_av1_film_grain *p_av1_film_grain;
void *p;
const void *p_const;
};
成员
p_s32
指向 32 位有符号值的指针。
p_s64
指向 64 位有符号值的指针。
p_u8
指向 8 位无符号值的指针。
p_u16
指向 16 位无符号值的指针。
p_u32
指向 32 位无符号值的指针。
p_char
指向字符串的指针。
p_mpeg2_sequence
指向 MPEG2 序列结构的指针。
p_mpeg2_picture
指向 MPEG2 图片结构的指针。
p_mpeg2_quantisation
指向 MPEG2 量化数据结构的指针。
p_fwht_params
指向 FWHT 无状态参数结构的指针。
p_h264_sps
指向
struct v4l2_ctrl_h264_sps
的指针。p_h264_pps
指向
struct v4l2_ctrl_h264_pps
的指针。p_h264_scaling_matrix
p_h264_slice_params
p_h264_decode_params
p_h264_pred_weights
p_vp8_frame
指向 VP8 帧参数结构的指针。
p_hevc_sps
指向 HEVC 序列参数集结构的指针。
p_hevc_pps
指向 HEVC 图片参数集结构的指针。
p_hevc_slice_params
指向 HEVC 切片参数结构的指针。
p_vp9_compressed_hdr_probs
指向 VP9 帧压缩头概率结构的指针。
p_vp9_frame
指向 VP9 帧参数结构的指针。
p_hdr10_cll
指向 HDR10 内容亮度级别结构的指针。
p_hdr10_mastering
指向 HDR10 母版显示结构的指针。
p_area
指向区域的指针。
p_av1_sequence
指向 AV1 序列结构的指针。
p_av1_tile_group_entry
指向 AV1 图块组条目结构的指针。
p_av1_frame
指向 AV1 帧结构的指针。
p_av1_film_grain
指向 AV1 胶片颗粒结构的指针。
p
指向复合值的指针。
p_const
指向常量复合值的指针。
-
union v4l2_ctrl_ptr v4l2_ctrl_ptr_create(void *ptr)¶
从 void 指针返回 v4l2_ctrl_ptr 的辅助函数
参数
void *ptr
void 指针
-
struct v4l2_ctrl_ops¶
驱动程序必须提供的控件操作。
定义:
struct v4l2_ctrl_ops {
int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
int (*try_ctrl)(struct v4l2_ctrl *ctrl);
int (*s_ctrl)(struct v4l2_ctrl *ctrl);
};
成员
g_volatile_ctrl
获取此控件的新值。通常仅与易失性(且通常是只读的)控件相关,例如返回不断变化的当前信号强度的控件。如果未设置,则将返回当前缓存的值。
try_ctrl
测试控件的值是否有效。仅当通常的最小/最大/步长检查不足时才相关。
s_ctrl
实际设置新的控件值。 s_ctrl 是强制性的。调用这些操作时,会持有 ctrl->handler->lock,因此没有其他人可以访问该处理程序拥有的控件。
-
struct v4l2_ctrl_type_ops¶
驱动程序必须提供的控件类型操作。
定义:
struct v4l2_ctrl_type_ops {
bool (*equal)(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr1, union v4l2_ctrl_ptr ptr2);
void (*init)(const struct v4l2_ctrl *ctrl, u32 from_idx, union v4l2_ctrl_ptr ptr);
void (*log)(const struct v4l2_ctrl *ctrl);
int (*validate)(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr);
};
成员
equal
如果所有 ctrl->elems 数组元素相等,则返回 true。
init
从 from_idx 到 ctrl->elems 初始化数组元素的值。
log
记录值。
validate
验证 ctrl->new_elems 数组元素的值。成功时返回 0,否则返回负值。
-
v4l2_ctrl_notify_fnc¶
Typedef:用于通知参数的 typedef,当控件值发生更改时应调用该函数。
语法
void v4l2_ctrl_notify_fnc (struct v4l2_ctrl *ctrl, void *priv)
参数
struct v4l2_ctrl *ctrl
指向
v4l2_ctrl
结构的指针void *priv
控件私有数据
描述
此 typedef 定义用作 v4l2_ctrl_notify()
的参数,并用作 v4l2_ctrl_handler
结构体的参数。
-
struct v4l2_ctrl¶
控件结构。
定义:
struct v4l2_ctrl {
struct list_head node;
struct list_head ev_subs;
struct v4l2_ctrl_handler *handler;
struct v4l2_ctrl **cluster;
unsigned int ncontrols;
unsigned int done:1;
unsigned int is_new:1;
unsigned int has_changed:1;
unsigned int is_private:1;
unsigned int is_auto:1;
unsigned int is_int:1;
unsigned int is_string:1;
unsigned int is_ptr:1;
unsigned int is_array:1;
unsigned int is_dyn_array:1;
unsigned int has_volatiles:1;
unsigned int call_notify:1;
unsigned int manual_mode_value:8;
const struct v4l2_ctrl_ops *ops;
const struct v4l2_ctrl_type_ops *type_ops;
u32 id;
const char *name;
enum v4l2_ctrl_type type;
s64 minimum, maximum, default_value;
u32 elems;
u32 elem_size;
u32 new_elems;
u32 dims[V4L2_CTRL_MAX_DIMS];
u32 nr_of_dims;
union {
u64 step;
u64 menu_skip_mask;
};
union {
const char * const *qmenu;
const s64 *qmenu_int;
};
unsigned long flags;
void *priv;
void *p_array;
u32 p_array_alloc_elems;
s32 val;
struct {
s32 val;
} cur;
union v4l2_ctrl_ptr p_def;
union v4l2_ctrl_ptr p_new;
union v4l2_ctrl_ptr p_cur;
};
成员
node
列表节点。
ev_subs
控件事件订阅列表。
handler
拥有该控件的处理程序。
cluster
指向群组数组的开始位置。
ncontrols
群组数组中控件的数量。
done
内部标志:为每个已处理的控件设置。
is_new
当用户为此控件指定新值时设置。当从
v4l2_ctrl_handler_setup()
调用时也会设置。驱动程序不应设置此标志。has_changed
当当前值与新值不同时设置。驱动程序不应使用此标志。
is_private
如果设置,则此控件是其处理程序私有的,不会添加到任何其他处理程序。驱动程序可以设置此标志。
is_auto
如果设置,则此控件选择其他群组成员是处于“自动”模式还是“手动”模式。这用于自动增益/增益类型的群组。驱动程序不应直接设置此标志。
is_int
如果设置,则此控件具有简单的整数值(即,它使用 ctrl->val)。
is_string
如果设置,则此控件的类型为
V4L2_CTRL_TYPE_STRING
。is_ptr
如果设置,则此控件是一个数组,并且/或类型 >=
V4L2_CTRL_COMPOUND_TYPES
,并且/或类型为V4L2_CTRL_TYPE_STRING
。换句话说,struct v4l2_ext_control
使用字段 p 指向数据。is_array
如果设置,则此控件包含 N 维数组。
is_dyn_array
如果设置,则此控件包含动态大小的一维数组。如果设置了此标志,则还会设置 is_array。
has_volatiles
如果设置,则群组的一个或多个成员是易变的。驱动程序不应修改此标志。
call_notify
如果设置,则只要控件的值发生更改,就调用处理程序的通知函数。
manual_mode_value
如果设置了 is_auto 标志,则此值是 auto 控件的值,它确定该控件是否处于手动模式。因此,如果 auto 控件的值等于此值,则整个群组处于手动模式。驱动程序不应直接设置此标志。
ops
控件操作。
type_ops
控件类型操作。
id
控件 ID。
name
控件名称。
type
控件类型。
minimum
控件的最小值。
maximum
控件的最大值。
default_value
控件的默认值。
elems
N 维数组中元素的数量。
elem_size
控件的大小(以字节为单位)。
new_elems
p_new 中元素的数量。这与 elems 相同,但动态数组除外。在这种情况下,它在 1 到 p_array_alloc_elems 的范围内。
dims
每个维度的大小。
nr_of_dims
dims 中的维度数。
{unnamed_union}
匿名
step
非菜单控件的控件步长值。
menu_skip_mask
菜单控件的控件跳过掩码。这使得跳过无效的菜单项变得容易。如果设置了位 X,则会跳过菜单项 X。当然,这仅适用于菜单项 <= 32 的菜单。没有接近该数量的菜单,所以这没问题。如果我们将来需要更多,那么必须将其扩展到 u64 或位数组。
{unnamed_union}
匿名
qmenu
所有菜单项的 const char * 数组。为空字符串 (“”) 的数组条目对应于不存在的菜单项(这是除了上面的 menu_skip_mask 之外)。最后一个条目必须为 NULL。仅当 type 为
V4L2_CTRL_TYPE_MENU
时使用。qmenu_int
一个用于存储整数菜单项的 64 位整数数组。数组大小必须等于菜单大小,例如: 。仅当 type 为
V4L2_CTRL_TYPE_INTEGER_MENU
时使用。flags
控件的标志。
priv
控件的私有指针。供驱动程序使用。它不受控件框架的影响。请注意,删除控件时不会释放此指针。如果需要这样做,则可以添加一个新的内部位字段,以告知框架释放此指针。
p_array
指向已分配数组的指针。仅当 is_array 为 true 时有效。
p_array_alloc_elems
为当前值和新值分配的数组中的元素数量。因此,p_array 的实际大小为 2 * p_array_alloc_elems * elem_size。仅当 is_array 为 true 时有效。
val
控件的新 s32 值。
cur
用于存储当前值的结构。
cur.val
控件的当前值,如果 type 通过 u32 整数表示(请参阅
enum v4l2_ctrl_type
)。p_def
控件的默认值,通过联合表示,该联合提供了一种通过指针访问控件类型的标准方法(仅适用于复合控件)。
p_new
控件的新值,通过联合表示,该联合提供了一种通过指针访问控件类型的标准方法。
p_cur
控件的当前值,通过联合表示,该联合提供了一种通过指针访问控件类型的标准方法。
-
struct v4l2_ctrl_ref¶
控件引用。
定义:
struct v4l2_ctrl_ref {
struct list_head node;
struct v4l2_ctrl_ref *next;
struct v4l2_ctrl *ctrl;
struct v4l2_ctrl_helper *helper;
bool from_other_dev;
bool req_done;
bool p_req_valid;
bool p_req_array_enomem;
u32 p_req_array_alloc_elems;
u32 p_req_elems;
union v4l2_ctrl_ptr p_req;
};
成员
node
已排序列表的列表节点。
next
哈希的单链表节点。
ctrl
实际的控件信息。
helper
指向 helper 结构的指针。在
v4l2-ctrl.c
的prepare_ext_ctrls
函数中内部使用。from_other_dev
如果为 true,则 ctrl 是在与
struct v4l2_ctrl_handler
不同的设备中定义的。req_done
内部标志:如果包含此控件引用的控件处理程序绑定到媒体请求,则当应用控件时会设置此标志。这可以防止两次应用具有多个控件的群组中的控件(当应用群组的第一个控件时,它们都会被应用)。
p_req_valid
如果设置,则 p_req 包含请求的控件值。
p_req_array_enomem
如果设置,则 p_req 无效,因为为数组分配空间失败。尝试读取此值将导致 ENOMEM。仅当 ctrl->is_array 为 true 时有效。
p_req_array_alloc_elems
为数组分配的元素数量。仅当 p_req_valid 和 ctrl->is_array 为 true 时有效。
p_req_elems
p_req 中元素的数量。这与 ctrl->elems 相同,但动态数组除外。在这种情况下,它在 1 到 p_req_array_alloc_elems 的范围内。仅当 p_req_valid 为 true 时有效。
p_req
如果包含此控件引用的控件处理程序绑定到媒体请求,则此指针指向在执行请求时必须应用的控件的值,或者指向请求完成时控件的值。如果 p_req_valid 为 false,则从未为此请求设置此控件,并且当应用此请求时,不会更新该控件。
描述
每个控件处理程序都有一个这些引用的列表。list_head 用于保持所有控件的按控件 ID 排序的列表,而 next 指针用于将控件链接到哈希的存储桶中。
-
struct v4l2_ctrl_handler¶
控件处理程序跟踪所有控件:包括处理程序拥有的控件和从其他处理程序继承的控件。
定义:
struct v4l2_ctrl_handler {
struct mutex _lock;
struct mutex *lock;
struct list_head ctrls;
struct list_head ctrl_refs;
struct v4l2_ctrl_ref *cached;
struct v4l2_ctrl_ref **buckets;
v4l2_ctrl_notify_fnc notify;
void *notify_priv;
u16 nr_of_buckets;
int error;
bool request_is_queued;
struct list_head requests;
struct list_head requests_queued;
struct media_request_object req_obj;
};
成员
_lock
“lock” 的默认值。
lock
用于控制对此处理程序及其控件的访问的锁。可以在初始化后立即由用户替换。
ctrls
此处理程序拥有的控件列表。
ctrl_refs
控件引用列表。
cached
上次找到的控件引用。通常需要多次使用相同的控件,因此这是一种简单的优化。
buckets
哈希的存储桶。允许快速查找控件。
notify
每当控件值更改时调用的通知回调。请注意,调用通知函数时会持有处理程序的锁!
notify_priv
作为参数传递给 v4l2_ctrl 通知回调。
nr_of_buckets
数组中的存储桶总数。
error
第一次控件添加失败的错误代码。
request_is_queued
如果请求已排队,则为 True。
requests
用于跟踪打开的控件处理程序请求对象的列表。对于父控件处理程序(req_obj.ops == NULL),这是列表头。当删除父控件处理程序时,它必须取消绑定并放置所有这些请求,因为它们引用父控件处理程序。
requests_queued
已排队请求的列表。这确定了应用这些控件的顺序。请求完成后,会将其从此列表中删除。
req_obj
struct media_request_object
,用于链接到struct media_request
。此请求对象有一个引用计数。
-
struct v4l2_ctrl_config¶
控件配置结构。
定义:
struct v4l2_ctrl_config {
const struct v4l2_ctrl_ops *ops;
const struct v4l2_ctrl_type_ops *type_ops;
u32 id;
const char *name;
enum v4l2_ctrl_type type;
s64 min;
s64 max;
u64 step;
s64 def;
union v4l2_ctrl_ptr p_def;
u32 dims[V4L2_CTRL_MAX_DIMS];
u32 elem_size;
u32 flags;
u64 menu_skip_mask;
const char * const *qmenu;
const s64 *qmenu_int;
unsigned int is_private:1;
};
成员
ops
控件操作。
type_ops
控件类型操作。仅复合控件需要。
id
控件 ID。
name
控件名称。
type
控件类型。
min
控件的最小值。
max
控件的最大值。
step
非菜单控件的控件步长值。
def
控件的默认值。
p_def
复合控件的默认控制值。
dims
每个维度的大小。
elem_size
控件的大小(以字节为单位)。
flags
控件的标志。
menu_skip_mask
菜单控件的控制跳过掩码。这使得跳过无效的菜单项变得容易。如果设置了位 X,则跳过菜单项 X。当然,这仅适用于菜单项数量 <= 64 的菜单。没有菜单接近这个数量,所以这是可以的。如果我们将来需要更多,则必须将其扩展为位数组。
qmenu
所有菜单项的 const char * 数组。空字符串 (“”) 的数组条目对应于不存在的菜单项(这是对上面的 menu_skip_mask 的补充)。最后一个条目必须为 NULL。
qmenu_int
类型为 V4L2_CTRL_TYPE_INTEGER_MENU 的所有菜单项的 const s64 整数数组。
is_private
如果设置,则此控件是其处理程序的私有控件,不会添加到任何其他处理程序。
-
void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags)¶
根据控件 ID 填充控件字段。
参数
u32 id
控件的 ID
const char **name
指向字符串的指针,该字符串将填充控件的名称
enum v4l2_ctrl_type *type
用于存储控件类型的指针
s64 *min
用于存储控件最小值的指针
s64 *max
用于存储控件最大值的指针
u64 *step
用于存储控件步长的指针
s64 *def
用于存储控件默认值的指针
u32 *flags
用于存储要在控件上使用的标志的指针
描述
这适用于所有标准 V4L2 控件。对于非标准控件,它只会填充给定的参数,并且 name 内容将设置为 NULL
。
此函数将覆盖 name、type 和 flags 的内容。min、max、step 和 def 的内容可能会根据类型进行修改。
注意
不要在驱动程序中使用!它仅在内部用于向后兼容的控件处理。一旦所有驱动程序都转换为使用新的控件框架,此函数将不再导出。
-
int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl, unsigned int nr_of_controls_hint, struct lock_class_key *key, const char *name)¶
初始化控制处理程序。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
unsigned int nr_of_controls_hint
此处理程序预期引用的控件数量的提示。这是总数,因此包括任何继承的控件。它不必非常精确,但如果偏差太大,则要么浪费内存(分配了太多存储桶),要么控件查找速度变慢(分配的存储桶不足,因此有更多慢速列表查找)。不过,它始终有效。
struct lock_class_key *key
如果设置了 CONFIG_LOCKDEP,则由锁验证器使用。
const char *name
如果设置了 CONFIG_LOCKDEP,则由锁验证器使用。
描述
注意
永远不要直接使用此调用,始终使用 v4l2_ctrl_handler_init()
宏,该宏隐藏了 key 和 name 参数。
返回
如果无法分配存储桶,则返回错误。此错误也会存储在 hdl->error 中。
-
v4l2_ctrl_handler_init¶
v4l2_ctrl_handler_init (hdl, nr_of_controls_hint)
用于创建静态结构
lock_class_key
并调用v4l2_ctrl_handler_init_class()
的辅助函数
参数
hdl
控制处理程序。
nr_of_controls_hint
此处理程序预期引用的控件数量的提示。这是总数,因此包括任何继承的控件。它不必非常精确,但如果偏差太大,则要么浪费内存(分配了太多存储桶),要么控件查找速度变慢(分配的存储桶不足,因此有更多慢速列表查找)。不过,它始终有效。
描述
此辅助函数创建一个静态结构 lock_class_key
并调用 v4l2_ctrl_handler_init_class()
,为锁验证器提供适当的名称。
使用此辅助函数初始化控制处理程序。
-
void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)¶
释放处理程序拥有的所有控件并释放控件列表。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
描述
如果 hdl == NULL,则不执行任何操作。
参数
struct v4l2_ctrl *ctrl
要锁定的控件。
参数
struct v4l2_ctrl *ctrl
要解锁的控件。
-
int __v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)¶
为属于处理程序的所有控件调用 s_ctrl 操作,以将硬件初始化为当前控件值。调用者负责代表
__v4l2_ctrl_handler_setup()
获取控制处理程序互斥锁。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
描述
按钮控件将被跳过,只读控件也是如此。
如果 hdl == NULL,则只返回 0。
-
int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)¶
为属于处理程序的所有控件调用 s_ctrl 操作,以将硬件初始化为当前控件值。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
描述
按钮控件将被跳过,只读控件也是如此。
如果 hdl == NULL,则只返回 0。
-
void v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl, const char *prefix)¶
记录处理程序拥有的所有控件。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
const char *prefix
记录控制值时使用的前缀。如果前缀末尾没有空格,则会在前缀后添加“: ”。 如果 prefix == NULL,则不使用前缀。
描述
用于 VIDIOC_LOG_STATUS。
如果 hdl == NULL,则不执行任何操作。
-
struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_config *cfg, void *priv)¶
分配并初始化一个新的自定义 V4L2 控制。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
const struct v4l2_ctrl_config *cfg
控制的配置数据。
void *priv
控制的驱动程序特定私有数据。
描述
如果无法分配 v4l2_ctrl
结构,则返回 NULL,并且 hdl->error 设置为错误代码(如果尚未设置)。
-
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, s64 min, s64 max, u64 step, s64 def)¶
分配并初始化一个新的标准 V4L2 非菜单控件。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
const struct v4l2_ctrl_ops *ops
控件操作。
u32 id
控件 ID。
s64 min
控件的最小值。
s64 max
控件的最大值。
u64 step
控件的步长值
s64 def
控件的默认值。
描述
如果无法分配 v4l2_ctrl
结构,或者控制 ID 未知,则返回 NULL,并且 hdl->error 设置为相应的错误代码(如果尚未设置)。
如果 id 指的是菜单控件,则此函数将返回 NULL。
添加菜单控件时使用 v4l2_ctrl_new_std_menu()
。
分配并初始化一个新的标准 V4L2 菜单控件。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
const struct v4l2_ctrl_ops *ops
控件操作。
u32 id
控件 ID。
u8 max
控件的最大值。
u64 mask
菜单控件的控制跳过掩码。这使得跳过无效的菜单项变得容易。如果设置了位 X,则跳过菜单项 X。当然,这仅适用于菜单项数量 <= 64 的菜单。没有菜单接近这个数量,所以这是可以的。如果我们将来需要更多,则必须将其扩展为位数组。
u8 def
控件的默认值。
描述
与 v4l2_ctrl_new_std()
相同,但 min 设置为 0,并且 mask 值确定要跳过哪些菜单项。
如果 id 指的是非菜单控件,则此函数将返回 NULL。
使用驱动程序特定菜单创建一个新的标准 V4L2 菜单控件。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
const struct v4l2_ctrl_ops *ops
控件操作。
u32 id
控件 ID。
u8 max
控件的最大值。
u64 mask
菜单控件的控制跳过掩码。这使得跳过无效的菜单项变得容易。如果设置了位 X,则跳过菜单项 X。当然,这仅适用于菜单项数量 <= 64 的菜单。没有菜单接近这个数量,所以这是可以的。如果我们将来需要更多,则必须将其扩展为位数组。
u8 def
控件的默认值。
const char * const *qmenu
新菜单。
描述
与 v4l2_ctrl_new_std_menu()
相同,但 qmenu 将是此控件的驱动程序特定菜单。
-
struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, const union v4l2_ctrl_ptr p_def)¶
分配并初始化一个新的标准 V4L2 复合控件。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
const struct v4l2_ctrl_ops *ops
控件操作。
u32 id
控件 ID。
const union v4l2_ctrl_ptr p_def
控件的默认值。
描述
与 v4l2_ctrl_new_std()
相同,但由于 p_def 字段,支持复合控件。 使用 v4l2_ctrl_ptr_create()
从指针创建 p_def。 如果复合控件的默认值应全部为零,则使用 v4l2_ctrl_ptr_create(NULL)。
创建一个新的标准 V4L2 整数菜单控件。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
const struct v4l2_ctrl_ops *ops
控件操作。
u32 id
控件 ID。
u8 max
控件的最大值。
u8 def
控件的默认值。
const s64 *qmenu_int
控件的菜单项。
描述
与 v4l2_ctrl_new_std_menu()
相同,但 mask 设置为 0,并且它还接受一个整数数组作为参数,该数组确定菜单项。
如果 id 指的是非整数菜单控件,则此函数将返回 NULL
。
-
v4l2_ctrl_filter¶
Typedef:用于定义添加控件处理程序时要使用的过滤器函数的 Typedef。
语法
bool v4l2_ctrl_filter (const struct v4l2_ctrl *ctrl)
参数
const struct v4l2_ctrl *ctrl
指向结构体
v4l2_ctrl
的指针。
-
int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_handler *add, v4l2_ctrl_filter filter, bool from_other_dev)¶
将处理程序 add 中的所有控件添加到处理程序 hdl。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
struct v4l2_ctrl_handler *add
您想要添加到 hdl 控制处理程序的控制处理程序。
v4l2_ctrl_filter filter
此函数将过滤应添加哪些控件。
bool from_other_dev
如果为 true,则 add 中的控件是在与 hdl 不同的设备中定义的。
描述
如果两个处理程序中的任何一个是 NULL 指针,则不执行任何操作。如果 filter 为 NULL,则会添加所有控件。否则,只会添加 filter 返回 true 的那些控件。如果发生错误,hdl->error 将设置为错误代码(如果尚未设置)。
参数
const struct v4l2_ctrl *ctrl
被过滤的控件。
描述
对于任何对无线电设备节点有效的控件,这将返回 true。这些是所有 V4L2_CID_AUDIO_* 用户控件和所有 FM 发射器类控件。
此函数将与 v4l2_ctrl_add_handler()
一起使用。
参数
unsigned int ncontrols
此集群中的控件数。
struct v4l2_ctrl **controls
大小为 ncontrols 的集群控制数组。
-
void v4l2_ctrl_auto_cluster(unsigned int ncontrols, struct v4l2_ctrl **controls, u8 manual_val, bool set_volatile)¶
将集群中的所有控件标记为属于该集群,并将其设置为自动/手动类型处理。
参数
unsigned int ncontrols
此集群中的控件数。
struct v4l2_ctrl **controls
大小为 ncontrols 的集群控制数组。第一个控件必须是“自动”控件(例如,自动增益、自动曝光等)。
u8 manual_val
集群中第一个控件的值,该值等于手动设置。
bool set_volatile
如果为 true,则除第一个自动控件外的所有控件都将是易失的。
描述
用于控件组,其中一个控件选择一些自动功能,而其他控件仅在自动功能关闭(手动模式)时才处于活动状态。典型示例:自动增益与增益,自动白平衡与红色和蓝色平衡等。
这些控件的行为如下
当自动控件设置为自动时,任何手动控件都将设置为非活动状态,并且任何读取都将调用 g_volatile_ctrl(如果该控件被标记为易失的)。
当自动控件设置为手动时,任何手动控件都将被标记为活动状态,并且任何读取都将仅返回当前值,而无需通过 g_volatile_ctrl。
此外,此函数将在自动控件上设置 V4L2_CTRL_FLAG_UPDATE
标志,如果自动控件处于自动模式,则在手动控件上设置 V4L2_CTRL_FLAG_INACTIVE
标志。
-
struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)¶
查找具有给定 ID 的控件。
参数
struct v4l2_ctrl_handler *hdl
控制处理程序。
u32 id
要查找的控件 ID。
描述
如果 hdl == NULL,则也会返回 NULL。将锁定处理程序,因此请勿从 v4l2_ctrl_ops
内部使用。
参数
struct v4l2_ctrl *ctrl
要(取消)激活的控件。
bool active
如果控件应变为活动状态,则为 True。
描述
这将以原子方式设置或清除 V4L2_CTRL_FLAG_INACTIVE 标志。如果 ctrl == NULL,则不执行任何操作。这通常会从 s_ctrl op 中调用。之后将生成 V4L2_EVENT_CTRL 事件。
此函数假定控制处理程序已锁定。
参数
struct v4l2_ctrl *ctrl
要(取消)激活的控件。
bool grabbed
如果控件应变为已捕获状态,则为 True。
描述
这将以原子方式设置或清除 V4L2_CTRL_FLAG_GRABBED 标志。如果 ctrl == NULL,则不执行任何操作。之后将生成 V4L2_EVENT_CTRL 事件。这通常会在驱动程序中启动或停止流式传输时调用。
此函数假定控制处理程序已由调用方锁定。
参数
struct v4l2_ctrl *ctrl
要(取消)激活的控件。
bool grabbed
如果控件应变为已捕获状态,则为 True。
描述
这将以原子方式设置或清除 V4L2_CTRL_FLAG_GRABBED 标志。如果 ctrl == NULL,则不执行任何操作。之后将生成 V4L2_EVENT_CTRL 事件。这通常会在驱动程序中启动或停止流式传输时调用。
此函数假定控制处理程序未锁定,并且将自行获取锁。
-
int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, s64 min, s64 max, u64 step, s64 def)¶
v4l2_ctrl_modify_range()
的解锁变体
参数
struct v4l2_ctrl *ctrl
要更新的控件。
s64 min
控件的最小值。
s64 max
控件的最大值。
u64 step
控件的步长值
s64 def
控件的默认值。
描述
动态更新控件的范围。这适用于控件类型 INTEGER、BOOLEAN、MENU、INTEGER MENU 和 BITMASK。对于菜单控件,step 值被解释为 menu_skip_mask。
如果某个范围参数对于此控件类型无效,则返回错误。
调用方负责代表 __v4l2_ctrl_modify_range()
获取控制处理程序互斥锁。
参数
struct v4l2_ctrl *ctrl
要更新的控件。
s64 min
控件的最小值。
s64 max
控件的最大值。
u64 step
控件的步长值
s64 def
控件的默认值。
描述
动态更新控件的范围。这适用于控件类型 INTEGER、BOOLEAN、MENU、INTEGER MENU 和 BITMASK。对于菜单控件,step 值被解释为 menu_skip_mask。
如果某个范围参数对于此控件类型无效,则返回错误。
此函数假定控制处理程序未锁定,并且将自行获取锁。
参数
struct v4l2_ctrl *ctrl
要更新的控件。
u32 dims[V4L2_CTRL_MAX_DIMS]
控制的新维度。
描述
动态更新数组控制的维度。即使维度未更改,数组的元素也会重置为其默认值。
如果 dims 对此控制无效,则会返回错误。
调用者负责代表 __v4l2_ctrl_modify_dimensions()
获取控制处理程序的互斥锁。
注意
当在挂起的请求中使用相同控制时调用此函数未经测试。它应该可以工作(具有错误控制大小的请求会静默地删除该控制),但这会非常令人困惑。
参数
struct v4l2_ctrl *ctrl
要更新的控件。
u32 dims[V4L2_CTRL_MAX_DIMS]
控制的新维度。
描述
动态更新数组控制的维度。即使维度未更改,数组的元素也会重置为其默认值。
如果 dims 对此控制类型无效,则会返回错误。
此函数假定控制处理程序未锁定,并且将自行获取锁。
注意
当在挂起的请求中使用相同控制时调用此函数未经测试。它应该可以工作(具有错误控制大小的请求会静默地删除该控制),但这会非常令人困惑。
-
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)¶
用于为控制设置通知回调的函数。
参数
struct v4l2_ctrl *ctrl
控制。
v4l2_ctrl_notify_fnc notify
回调函数。
void *priv
回调私有句柄,作为参数传递给回调。
描述
此函数为控制设置回调函数。如果 ctrl 为 NULL,则它将不执行任何操作。如果 notify 为 NULL,则将删除通知回调。
只能有一个通知。如果已存在另一个通知,则会发出 WARN_ON,并且该函数将不执行任何操作。
-
const char *v4l2_ctrl_get_name(u32 id)¶
获取控制的名称
参数
u32 id
控件 ID。
描述
此函数返回给定控制 ID 的名称,如果它不是已知的控制,则返回 NULL。
获取控制的菜单字符串数组
参数
u32 id
控件 ID。
描述
此函数返回给定控制 ID 的以 NULL 结尾的菜单字符串数组名称,如果它不是已知的菜单控制,则返回 NULL。
获取控制的整数菜单数组
参数
u32 id
控件 ID。
u32 *len
整数数组的大小。
描述
此函数返回给定控制 ID 的整数数组,如果它不是已知的整数菜单控制,则返回 NULL。
参数
struct v4l2_ctrl *ctrl
控制。
描述
此函数通过控制框架安全地返回控制的值。此函数将锁定控制的处理程序,因此不能在 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于整数类型控制。
-
int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)¶
v4l2_ctrl_s_ctrl()
的非锁变体。
参数
struct v4l2_ctrl *ctrl
控制。
s32 val
新值。
描述
此函数通过控制框架安全地设置控制的新值。此函数假定控制的处理程序已锁定,允许在 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于整数类型控制。
参数
struct v4l2_ctrl *ctrl
控制。
s32 val
新值。
描述
此函数通过控制框架安全地设置控制的新值。此函数将锁定控制的处理程序,因此不能在 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于整数类型控制。
参数
struct v4l2_ctrl *ctrl
控制。
描述
此函数通过控制框架安全地返回控制的值。此函数将锁定控制的处理程序,因此不能在 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于 64 位整数类型控制。
-
int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)¶
v4l2_ctrl_s_ctrl_int64()
的非锁变体。
参数
struct v4l2_ctrl *ctrl
控制。
s64 val
新值。
描述
此函数通过控制框架安全地设置控制的新值。此函数假定控制的处理程序已锁定,允许在 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于 64 位整数类型控制。
参数
struct v4l2_ctrl *ctrl
控制。
s64 val
新值。
描述
此函数通过控制框架安全地设置控制的新值。此函数将锁定控制的处理程序,因此不能在 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于 64 位整数类型控制。
-
int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)¶
v4l2_ctrl_s_ctrl_string()
的非锁定变体。
参数
struct v4l2_ctrl *ctrl
控制。
const char *s
新的字符串。
描述
此函数通过控制框架安全地设置控件的新字符串。此函数假定控件的处理程序已被锁定,允许从 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于字符串类型的控件。
参数
struct v4l2_ctrl *ctrl
控制。
const char *s
新的字符串。
描述
此函数通过控制框架安全地设置控件的新字符串。此函数将锁定控件的处理程序,因此不能从 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于字符串类型的控件。
-
int __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl, enum v4l2_ctrl_type type, const void *p)¶
设置复合控件的非锁定变体。
参数
struct v4l2_ctrl *ctrl
控制。
enum v4l2_ctrl_type type
数据的类型。
const void *p
新的复合有效载荷。
描述
此函数通过控制框架安全地设置控件的新复合有效载荷。此函数假定控件的处理程序已被锁定,允许从 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于复合类型的控件。
-
int v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl, enum v4l2_ctrl_type type, const void *p)¶
用于从驱动程序内部设置复合控件的辅助函数。
参数
struct v4l2_ctrl *ctrl
控制。
enum v4l2_ctrl_type type
数据的类型。
const void *p
新的复合有效载荷。
描述
此函数通过控制框架安全地设置控件的新复合有效载荷。此函数将锁定控件的处理程序,因此不能从 v4l2_ctrl_ops
函数内部使用。
此函数仅适用于复合类型的控件。
-
void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new)¶
用作
struct v4l2_subscribed_event_ops
replace() 的回调的函数
参数
struct v4l2_event *old
指向带有报告事件的
v4l2_event
结构的指针;const struct v4l2_event *new
指向带有修改事件的
v4l2_event
结构的指针;
-
void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new)¶
用作
struct v4l2_subscribed_event_ops
merge() 的回调的函数
参数
const struct v4l2_event *old
指向带有报告事件的
v4l2_event
结构的指针;struct v4l2_event *new
指向带有合并事件的
v4l2_event
结构的指针;
参数
struct file *file
指向
struct file
的指针void *fh
未使用。保留只是为了与
struct v4l2_ioctl_ops
.vidioc_log_status 期望的参数兼容。
描述
可以用作 vidioc_log_status 函数,该函数仅转储与文件句柄关联的所有控件。
-
int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)¶
订阅一个事件
参数
struct v4l2_fh *fh
指向
struct v4l2_fh
的指针const struct v4l2_event_subscription *sub
指向
struct v4l2_event_subscription
的指针
描述
可以用作 vidioc_subscribe_event 函数,该函数仅订阅控件事件。
-
__poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait)¶
用作 poll() 回调的函数。该函数仅轮询控件事件。
参数
struct file *file
指向
struct file
的指针struct poll_table_struct *wait
指向 struct poll_table_struct 的指针
-
int v4l2_ctrl_request_setup(struct media_request *req, struct v4l2_ctrl_handler *parent)¶
在请求中应用控件值的辅助函数
参数
struct media_request *req
请求
struct v4l2_ctrl_handler *parent
父控件处理程序(
media_request_object_find()
中的 “priv”)
描述
这是一个辅助函数,用于使用请求中包含的控制值调用控制处理程序的 s_ctrl 回调。 请注意,这种在请求中应用控制值的方法仅适用于内存到内存的设备。
-
void v4l2_ctrl_request_complete(struct media_request *req, struct v4l2_ctrl_handler *parent)¶
完成控制处理程序请求对象
参数
struct media_request *req
请求
struct v4l2_ctrl_handler *parent
父控件处理程序(
media_request_object_find()
中的 “priv”)
描述
此函数应在每个可能与请求对象关联的控制处理程序上调用,即支持请求的驱动程序的控制处理程序。
该函数首先获取控制处理程序中任何易失性控件的值,并将它们附加到请求。然后,该函数完成请求对象。
-
struct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req, struct v4l2_ctrl_handler *parent)¶
在请求中查找控制处理程序
参数
struct media_request *req
请求
struct v4l2_ctrl_handler *parent
父控件处理程序(
media_request_object_find()
中的 “priv”)
描述
此函数在请求中查找控制处理程序。 如果未找到,则可能返回 NULL。 完成后,必须使用返回的处理程序指针调用 v4l2_ctrl_request_hdl_put()
。
如果请求未处于 VALIDATING 或 QUEUED 状态,则此函数将始终返回 NULL。
请注意,在 VALIDATING 状态下,req_queue_mutex 被持有,因此无法从请求中添加或删除对象。
在 QUEUED 状态下,将由驱动程序来确保这一点。
-
void v4l2_ctrl_request_hdl_put(struct v4l2_ctrl_handler *hdl)¶
释放控制处理程序
-
struct v4l2_ctrl *v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)¶
查找具有给定 ID 的控件。
参数
struct v4l2_ctrl_handler *hdl
来自请求的控制处理程序。
u32 id
要查找的控件的 ID。
描述
如果此控件是请求的一部分,则此函数返回指向该控件的指针,否则返回 NULL。
-
int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)¶
用于实现 VIDIOC_QUERYCTRL ioctl 的辅助函数
参数
struct v4l2_ctrl_handler *hdl
指向
struct v4l2_ctrl_handler
的指针struct v4l2_queryctrl *qc
指向
struct v4l2_queryctrl
的指针
描述
如果 hdl == NULL,则它们都将返回 -EINVAL。
-
int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)¶
用于实现 VIDIOC_QUERY_EXT_CTRL ioctl 的辅助函数
参数
struct v4l2_ctrl_handler *hdl
指向
struct v4l2_ctrl_handler
的指针struct v4l2_query_ext_ctrl *qc
指向
struct v4l2_query_ext_ctrl
的指针
描述
如果 hdl == NULL,则它们都将返回 -EINVAL。
用于实现 VIDIOC_QUERYMENU ioctl 的辅助函数
参数
struct v4l2_ctrl_handler *hdl
指向
struct v4l2_ctrl_handler
的指针struct v4l2_querymenu *qm
指向
struct v4l2_querymenu
的指针
描述
如果 hdl == NULL,则它们都将返回 -EINVAL。
-
int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl)¶
用于实现 VIDIOC_G_CTRL ioctl 的辅助函数
参数
struct v4l2_ctrl_handler *hdl
指向
struct v4l2_ctrl_handler
的指针struct v4l2_control *ctrl
指向
struct v4l2_control
的指针
描述
如果 hdl == NULL,则它们都将返回 -EINVAL。
-
int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl)¶
用于实现 VIDIOC_S_CTRL ioctl 的辅助函数
参数
struct v4l2_fh *fh
指向
struct v4l2_fh
的指针struct v4l2_ctrl_handler *hdl
指向
struct v4l2_ctrl_handler
的指针struct v4l2_control *ctrl
指向
struct v4l2_control
的指针
描述
如果 hdl == NULL,则它们都将返回 -EINVAL。
-
int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, struct media_device *mdev, struct v4l2_ext_controls *c)¶
用于实现 VIDIOC_G_EXT_CTRLS ioctl 的辅助函数
参数
struct v4l2_ctrl_handler *hdl
指向
struct v4l2_ctrl_handler
的指针struct video_device *vdev
指向
struct video_device
的指针struct media_device *mdev
指向
struct media_device
的指针struct v4l2_ext_controls *c
指向
struct v4l2_ext_controls
的指针
描述
如果 hdl == NULL,则它们都将返回 -EINVAL。
-
int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, struct media_device *mdev, struct v4l2_ext_controls *c)¶
用于实现 VIDIOC_TRY_EXT_CTRLS ioctl 的辅助函数
参数
struct v4l2_ctrl_handler *hdl
指向
struct v4l2_ctrl_handler
的指针struct video_device *vdev
指向
struct video_device
的指针struct media_device *mdev
指向
struct media_device
的指针struct v4l2_ext_controls *c
指向
struct v4l2_ext_controls
的指针
描述
如果 hdl == NULL,则它们都将返回 -EINVAL。
-
int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, struct video_device *vdev, struct media_device *mdev, struct v4l2_ext_controls *c)¶
用于实现 VIDIOC_S_EXT_CTRLS ioctl 的辅助函数
参数
struct v4l2_fh *fh
指向
struct v4l2_fh
的指针struct v4l2_ctrl_handler *hdl
指向
struct v4l2_ctrl_handler
的指针struct video_device *vdev
指向
struct video_device
的指针struct media_device *mdev
指向
struct media_device
的指针struct v4l2_ext_controls *c
指向
struct v4l2_ext_controls
的指针
描述
如果 hdl == NULL,则它们都将返回 -EINVAL。
-
int v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub)¶
用于实现作为
struct v4l2_subdev_core_ops
subscribe_event 函数的辅助函数,该函数仅订阅控制事件。
参数
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针struct v4l2_fh *fh
指向
struct v4l2_fh
的指针struct v4l2_event_subscription *sub
指向
struct v4l2_event_subscription
的指针
-
int v4l2_ctrl_subdev_log_status(struct v4l2_subdev *sd)¶
记录子设备的控制句柄拥有的所有控件。
参数
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针
-
int v4l2_ctrl_new_fwnode_properties(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ctrl_ops, const struct v4l2_fwnode_device_properties *p)¶
为设备属性注册控件
参数
struct v4l2_ctrl_handler *hdl
指向要注册控件的
struct v4l2_ctrl_handler
的指针const struct v4l2_ctrl_ops *ctrl_ops
指向要注册控件的
struct v4l2_ctrl_ops
的指针const struct v4l2_fwnode_device_properties *p
描述
此函数使用 p 参数中包含的属性值,如果该属性已设置为某个值,则注册与设备属性关联的控件。
当前解析和注册以下 v4l2 控件: - V4L2_CID_CAMERA_ORIENTATION - V4L2_CID_CAMERA_SENSOR_ROTATION;
调用者使用 hdl 控制句柄已注册的控件不会被覆盖。调用者应在调用此函数之前注册他们想要自己处理的控件。
返回
成功时返回 0,失败时返回负错误代码。
-
bool v4l2_ctrl_type_op_equal(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr1, union v4l2_ctrl_ptr ptr2)¶
默认的 v4l2_ctrl_type_ops equal 回调。
参数
const struct v4l2_ctrl *ctrl
v4l2_ctrl 指针。
union v4l2_ctrl_ptr ptr1
v4l2 控制值。
union v4l2_ctrl_ptr ptr2
v4l2 控制值。
返回
如果值相等,则为 true,否则为 false。
-
void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, union v4l2_ctrl_ptr ptr)¶
默认的 v4l2_ctrl_type_ops init 回调。
参数
const struct v4l2_ctrl *ctrl
v4l2_ctrl 指针。
u32 from_idx
起始元素索引。
union v4l2_ctrl_ptr ptr
v4l2 控制值。
返回
void
参数
const struct v4l2_ctrl *ctrl
v4l2_ctrl 指针。
返回
void
-
int v4l2_ctrl_type_op_validate(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr)¶
默认的 v4l2_ctrl_type_ops 验证回调函数。
参数
const struct v4l2_ctrl *ctrl
v4l2_ctrl 指针。
union v4l2_ctrl_ptr ptr
v4l2 控制值。
返回
成功时返回 0,失败时返回负错误代码。