2.7. V4L2 子设备¶
许多驱动程序需要与子设备通信。这些设备可以执行各种任务,但最常见的是处理音频和/或视频复用、编码或解码。对于网络摄像头,常见的子设备是传感器和摄像头控制器。
通常这些是 I2C 设备,但不一定。为了为驱动程序提供与这些子设备的一致接口,创建了 v4l2_subdev
结构体 (v4l2-subdev.h)。
每个子设备驱动程序都必须有一个 v4l2_subdev
结构体。这个结构体可以是独立的,用于简单的子设备,或者如果需要存储更多状态信息,它可能会嵌入到更大的结构体中。通常有一个低级设备结构体(例如,i2c_client
),其中包含内核设置的设备数据。建议使用 v4l2_set_subdevdata()
将该指针存储在 v4l2_subdev
的私有数据中。这使得从 v4l2_subdev
到实际的低级总线特定设备数据变得容易。
您还需要一种从低级结构体到 v4l2_subdev
的方法。对于常见的 i2c_client 结构体,使用 i2c_set_clientdata() 调用来存储一个 v4l2_subdev
指针,对于其他总线,您可能必须使用其他方法。
桥接器可能还需要存储每个子设备的私有数据,例如指向特定于桥接器的每个子设备的私有数据的指针。v4l2_subdev
结构体为此目的提供了主机私有数据,可以使用 v4l2_get_subdev_hostdata()
和 v4l2_set_subdev_hostdata()
访问。
从桥接器驱动程序的角度来看,您加载子设备模块并以某种方式获取 v4l2_subdev
指针。对于 i2c 设备,这很容易:您调用 i2c_get_clientdata()
。对于其他总线,需要执行类似的操作。存在用于 I2C 总线上子设备的辅助函数,它们为您完成大部分棘手的工作。
每个 v4l2_subdev
包含子设备驱动程序可以实现(或如果不可用则保留为 NULL
)的函数指针。由于子设备可以执行如此多的不同操作,并且您不希望最终得到一个庞大的操作结构体,其中只实现了少数几个操作,因此函数指针根据类别进行排序,并且每个类别都有自己的操作结构体。
顶层操作结构体包含指向类别操作结构体的指针,如果子设备驱动程序不支持该类别的任何内容,则这些指针可能为 NULL。
它看起来像这样
struct v4l2_subdev_core_ops {
int (*log_status)(struct v4l2_subdev *sd);
int (*init)(struct v4l2_subdev *sd, u32 val);
...
};
struct v4l2_subdev_tuner_ops {
...
};
struct v4l2_subdev_audio_ops {
...
};
struct v4l2_subdev_video_ops {
...
};
struct v4l2_subdev_pad_ops {
...
};
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_pad_ops *video;
};
核心操作对于所有子设备都是通用的,其他类别根据子设备实现。例如,视频设备不太可能支持音频操作,反之亦然。
此设置限制了函数指针的数量,同时仍然可以轻松添加新的操作和类别。
子设备驱动程序使用以下方法初始化 v4l2_subdev
结构体
v4l2_subdev_init
(sd
, &ops
)。
之后,您需要使用唯一名称初始化 sd
->name 并设置模块所有者。如果您使用 i2c 辅助函数,则会为您完成此操作。
如果需要与媒体框架集成,则必须通过调用 media_entity_pads_init()
来初始化嵌入在 v4l2_subdev
结构体(实体字段)中的 media_entity
结构体,如果该实体有焊盘
struct media_pad *pads = &my_sd->pads;
int err;
err = media_entity_pads_init(&sd->entity, npads, pads);
焊盘数组必须已预先初始化。无需手动设置 struct media_entity
函数和名称字段,但如果需要,必须初始化修订字段。
当子设备设备节点(如果有)打开/关闭时,将自动获取/释放对实体的引用。
在销毁子设备之前,不要忘记清理媒体实体
media_entity_cleanup(&sd->entity);
如果子设备驱动程序实现接收器焊盘,则子设备驱动程序可以在 v4l2_subdev_pad_ops
中设置 link_validate 字段,以提供其自己的链接验证函数。对于管道中的每个链接,都会调用链接接收端的 link_validate 焊盘操作。在这两种情况下,驱动程序仍然负责验证子设备和视频节点之间格式配置的正确性。
如果未设置 link_validate 操作,则会改为使用默认函数 v4l2_subdev_link_validate_default()
。此函数确保链接的源和接收器上的宽度、高度和媒体总线像素代码相等。子设备驱动程序也可以自由使用此函数来执行上述检查以及他们自己的检查。
2.7.1. 子设备注册¶
目前有两种方法可以向 V4L2 内核注册子设备。第一种(传统)可能性是让桥接器驱动程序注册子设备。当桥接器驱动程序具有与其连接的子设备的完整信息,并且确切知道何时注册它们时,可以这样做。对于内部子设备,例如 SoC 内的视频数据处理单元或复杂的 PCI(e) 板,USB 摄像头中的摄像头传感器或连接到 SoC 的摄像头传感器,它们通常在其平台数据中将有关它们的信息传递给桥接器驱动程序,通常属于这种情况。
但是,在某些情况下,子设备必须与桥接设备异步注册。这种配置的一个示例是基于设备树的系统,其中有关子设备的信息独立于桥接设备提供给系统,例如,当子设备在 DT 中定义为 I2C 设备节点时。以下进一步描述了第二种情况中使用的 API。
使用一种或另一种注册方法仅影响探测过程,运行时桥接器-子设备交互在两种情况下都是相同的。
2.7.1.1. 注册同步子设备¶
在同步情况下,设备(桥接器)驱动程序需要使用 v4l2_device 注册 v4l2_subdev
。
如果子设备模块在注册之前消失,则此操作可能会失败。成功调用此函数后,subdev->dev 字段会指向 v4l2_device
。
如果 v4l2_device 父设备具有非 NULL 的 mdev 字段,则子设备实体将自动注册到媒体设备。
可以使用以下方式注销子设备:
之后可以卸载子设备模块,并且 sd
->dev == NULL
。
2.7.1.2. 注册异步子设备¶
在异步情况下,子设备探测的调用可以独立于桥接驱动程序的可用性。然后,子设备驱动程序必须验证是否满足成功探测的所有要求。这可能包括检查主时钟的可用性。如果任何条件不满足,驱动程序可能会决定返回 -EPROBE_DEFER
来请求进一步的重新探测尝试。一旦满足所有条件,应使用 v4l2_async_register_subdev()
函数注册子设备。注销使用 v4l2_async_unregister_subdev()
调用执行。以这种方式注册的子设备存储在子设备的全局列表中,随时可以被桥接驱动程序拾取。
驱动程序必须在通过 v4l2_async_register_subdev()
注册子设备之前完成子设备的所有初始化,包括启用运行时 PM。这是因为子设备在注册后即可访问。
2.7.1.3. 异步子设备通知器¶
桥接驱动程序反过来必须注册一个通知器对象。这是使用 v4l2_async_nf_register()
调用执行的。要注销通知器,驱动程序必须调用 v4l2_async_nf_unregister()
。在释放未注册通知器的内存之前,必须通过调用 v4l2_async_nf_cleanup()
来进行清理。
在注册通知器之前,桥接驱动程序必须做两件事:首先,必须使用 v4l2_async_nf_init()
初始化通知器。其次,桥接驱动程序可以开始形成桥接设备运行所需的异步连接描述符列表。v4l2_async_nf_add_fwnode()
、v4l2_async_nf_add_fwnode_remote()
和 v4l2_async_nf_add_i2c()
异步连接描述符描述与外部子设备的连接,这些子设备的驱动程序尚未被探测。基于异步连接,当相关的子设备可用时,可能会创建媒体数据或辅助链接。可能有一个或多个与给定子设备的异步连接,但这在将连接添加到通知器时是未知的。当找到匹配的异步子设备时,异步连接会一个接一个地绑定。
2.7.1.4. 子设备的异步子设备通知器¶
注册异步子设备的驱动程序也可以注册异步通知器。这被称为异步子设备通知器,其过程与桥接驱动程序的过程类似,不同之处在于通知器使用 v4l2_async_subdev_nf_init()
初始化。只有在 V4L2 设备可用后,子设备通知器才能完成,即存在通过异步子设备和通知器到非异步子设备通知器的路径。
2.7.1.5. 用于相机传感器驱动程序的异步子设备注册助手¶
v4l2_async_register_subdev_sensor()
是传感器驱动程序注册其自己的异步连接的辅助函数,但它还会注册一个通知器,并进一步为固件中发现的镜头和闪光灯设备注册异步连接。使用 v4l2_async_unregister_subdev()
,子设备的通知器会与异步子设备一起注销和清理。
2.7.1.6. 异步子设备通知器示例¶
这些函数分配一个异步连接描述符,该描述符的类型为结构体 v4l2_async_connection
,嵌入到驱动程序特定的结构体中。&struct v4l2_async_connection
应为此结构体的第一个成员。
struct my_async_connection {
struct v4l2_async_connection asc;
...
};
struct my_async_connection *my_asc;
struct fwnode_handle *ep;
...
my_asc = v4l2_async_nf_add_fwnode_remote(¬ifier, ep,
struct my_async_connection);
fwnode_handle_put(ep);
if (IS_ERR(my_asc))
return PTR_ERR(my_asc);
2.7.1.7. 异步子设备通知器回调¶
然后,V4L2 核心将使用这些连接描述符来将异步注册的子设备与它们匹配。如果检测到匹配项,则会调用 .bound()
通知器回调。在所有连接都绑定后,将调用 .complete() 回调。当从系统中移除连接时,将调用 .unbind()
方法。所有三个回调都是可选的。
驱动程序可以在其驱动程序特定的 v4l2_async_connection
包装器中存储任何类型的自定义数据。如果任何数据在释放结构时需要特殊处理,驱动程序必须实现 .destroy()
通知器回调。框架将在释放 v4l2_async_connection
之前调用它。
2.7.2. 调用子设备操作¶
使用 v4l2_subdev
的优点在于它是一个通用结构,不包含任何关于底层硬件的知识。因此,驱动程序可能包含多个使用 I2C 总线的子设备,但也可能包含一个通过 GPIO 引脚控制的子设备。这种区别仅在设置设备时才相关,但是一旦注册了子设备,它就完全透明了。
注册子设备后,您可以直接调用 ops 函数:
err = sd->ops->core->g_std(sd, &norm);
但最好和更方便的是使用此宏:
err = v4l2_subdev_call(sd, core, g_std, &norm);
如果 sd
为 NULL
,则宏将执行正确的 NULL
指针检查并返回 -ENODEV
;如果 sd
->core 或 sd
->core->g_std 为 NULL
,则返回 -ENOIOCTLCMD
;否则返回 sd
->ops->core->g_std ops 的实际结果。
也可以调用所有或部分子设备:
v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm);
任何不支持此操作的子设备都会被跳过,并且错误结果会被忽略。如果想要检查错误,请使用此功能。
err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm);
除了 -ENOIOCTLCMD
之外的任何错误都会导致循环退出并返回该错误。如果没有发生错误(除了 -ENOIOCTLCMD
),则返回 0。
两个调用的第二个参数都是一个组 ID。如果为 0,则会调用所有子设备。如果为非零值,则只会调用组 ID 与该值匹配的子设备。在桥接驱动程序注册子设备之前,它可以将 sd
->grp_id 设置为任何它想要的值(默认值为 0)。此值由桥接驱动程序拥有,子设备驱动程序永远不会修改或使用它。
组 ID 使桥接驱动程序能够更好地控制回调的调用方式。例如,一个板上可能有多个音频芯片,每个芯片都能够改变音量。但通常,当用户想要改变音量时,只会实际使用其中一个。您可以将该子设备的组 ID 设置为例如 AUDIO_CONTROLLER,并在调用 v4l2_device_call_all()
时将其指定为组 ID 值。这确保了它只会发送到需要它的子设备。
如果子设备需要将其事件通知给它的 v4l2_device 父设备,那么它可以调用 v4l2_subdev_notify(sd, notification, arg)
。此宏会检查是否定义了 notify()
回调,如果未定义则返回 -ENODEV
。否则,将返回 notify()
调用的结果。
2.8. V4L2 子设备用户空间 API¶
桥接驱动程序传统上会向用户空间公开一个或多个视频节点,并通过 v4l2_subdev_ops
操作来响应视频节点操作,从而控制子设备。这会向应用程序隐藏底层硬件的复杂性。对于复杂的设备,可能需要比视频节点提供的更精细的设备控制。在这些情况下,实现 媒体控制器 API 的桥接驱动程序可以选择直接从用户空间访问子设备操作。
可以在 /dev
中创建名为 v4l-subdev
X 的设备节点,以直接访问子设备。如果子设备支持直接用户空间配置,则必须在注册之前设置 V4L2_SUBDEV_FL_HAS_DEVNODE
标志。
在注册子设备后,v4l2_device
驱动程序可以通过调用 v4l2_device_register_subdev_nodes()
,为所有标记为 V4L2_SUBDEV_FL_HAS_DEVNODE
的已注册子设备创建设备节点。当子设备注销时,这些设备节点将自动删除。
该设备节点处理 V4L2 API 的一个子集。
VIDIOC_QUERYCTRL
, VIDIOC_QUERYMENU
, VIDIOC_G_CTRL
, VIDIOC_S_CTRL
, VIDIOC_G_EXT_CTRLS
, VIDIOC_S_EXT_CTRLS
和 VIDIOC_TRY_EXT_CTRLS
这些控制 ioctl 与 V4L2 中定义的相同。它们的行为相同,唯一的例外是它们只处理在子设备中实现的控制。根据驱动程序的不同,这些控制也可以通过一个(或多个)V4L2 设备节点访问。
VIDIOC_DQEVENT
, VIDIOC_SUBSCRIBE_EVENT
和 VIDIOC_UNSUBSCRIBE_EVENT
这些事件 ioctl 与 V4L2 中定义的相同。它们的行为相同,唯一的例外是它们只处理由子设备生成的事件。根据驱动程序的不同,这些事件也可以由一个(或多个)V4L2 设备节点报告。
想要使用事件的子设备驱动程序需要在注册子设备之前设置
v4l2_subdev
.flags 的V4L2_SUBDEV_FL_HAS_EVENTS
。注册后,可以像往常一样在v4l2_subdev
.devnode 设备节点上排队事件。为了正确支持事件,还实现了
poll()
文件操作。
私有 ioctl
上述列表中未包含的所有 ioctl 都通过 core::ioctl 操作直接传递给子设备驱动程序。
2.9. 只读子设备用户空间 API¶
通过直接调用 v4l2_subdev_ops
结构实现的内核 API 控制其连接的子设备的桥接驱动程序,通常不希望用户空间能够通过子设备设备节点更改相同的参数,因此通常不注册任何设备节点。
有时,通过只读 API 向用户空间报告当前的子设备配置是有用的,该 API 不允许应用程序更改设备参数,但允许与子设备设备节点交互以检查它们。
例如,为了实现基于计算摄影的相机,用户空间需要知道每个支持的输出分辨率的详细相机传感器配置(在跳过、合并、裁剪和缩放方面)。为了支持此类用例,桥接驱动程序可以通过只读 API 将子设备操作公开给用户空间。
要为所有注册时设置了 V4L2_SUBDEV_FL_HAS_DEVNODE
的子设备创建只读设备节点,v4l2_device
驱动程序应调用 v4l2_device_register_ro_subdev_nodes()
。
对于使用 v4l2_device_register_ro_subdev_nodes()
注册的子设备设备节点,用户空间应用程序对以下 ioctl 的访问受到限制。
VIDIOC_SUBDEV_S_FMT
, VIDIOC_SUBDEV_S_CROP
, VIDIOC_SUBDEV_S_SELECTION
这些 ioctl 仅允许在只读子设备设备节点上用于 V4L2_SUBDEV_FORMAT_TRY 格式和选择矩形。
VIDIOC_SUBDEV_S_FRAME_INTERVAL
, VIDIOC_SUBDEV_S_DV_TIMINGS
, VIDIOC_SUBDEV_S_STD
不允许在只读子设备节点上使用这些 ioctl。
如果 ioctl 不允许,或者要修改的格式设置为 V4L2_SUBDEV_FORMAT_ACTIVE
,则核心会返回负错误代码,并且 errno 变量设置为 -EPERM
。
2.10. I2C 子设备驱动程序¶
由于这些驱动程序非常常见,因此可以使用特殊的辅助函数来简化这些驱动程序的使用 (v4l2-common.h
)。
向 I2C 驱动程序添加 v4l2_subdev
支持的推荐方法是将 v4l2_subdev
结构嵌入到为每个 I2C 设备实例创建的状态结构中。非常简单的设备没有状态结构,在这种情况下,您可以直接创建一个 v4l2_subdev
。
典型的状态结构如下所示(其中 “chipname” 替换为芯片的名称)
struct chipname_state {
struct v4l2_subdev sd;
... /* additional state fields */
};
按如下方式初始化 v4l2_subdev
结构
v4l2_i2c_subdev_init(&state->sd, client, subdev_ops);
此函数将填充 v4l2_subdev
的所有字段,并确保 v4l2_subdev
和 i2c_client 都相互指向。
您还应该添加一个辅助内联函数,以便从 v4l2_subdev
指针转到 chipname_state 结构
static inline struct chipname_state *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct chipname_state, sd);
}
使用此函数从 v4l2_subdev
结构转到 i2c_client
结构
struct i2c_client *client = v4l2_get_subdevdata(sd);
使用此函数从 i2c_client
转到 v4l2_subdev
结构
struct v4l2_subdev *sd = i2c_get_clientdata(client);
请确保在调用 remove()
回调函数时调用 v4l2_device_unregister_subdev()
(sd
)。这将从桥接驱动程序中注销子设备。即使子设备从未注册,也可以安全地调用此函数。
你需要这样做是因为当桥接驱动程序销毁 i2c 适配器时,会调用该适配器上 i2c 设备的 remove()
回调函数。之后,相应的 v4l2_subdev 结构将失效,因此必须先注销它们。从 remove()
回调函数中调用 v4l2_device_unregister_subdev()
(sd
) 可确保始终正确执行此操作。
桥接驱动程序还有一些辅助函数可以使用
struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter,
"module_foo", "chipid", 0x36, NULL);
这会加载给定的模块(如果不需要加载模块,则可以为 NULL
),并使用给定的 i2c_adapter
和芯片/地址参数调用 i2c_new_client_device()
。如果一切顺利,它会将子设备注册到 v4l2_device。
你还可以使用 v4l2_i2c_new_subdev()
的最后一个参数来传递它应该探测的可能的 I2C 地址数组。只有在前一个参数为 0 时才会使用这些探测地址。非零参数表示你知道确切的 i2c 地址,因此在这种情况下不会进行探测。
如果发生错误,这两个函数都返回 NULL
。
请注意,你传递给 v4l2_i2c_new_subdev()
的 chipid 通常与模块名称相同。它允许你指定芯片变体,例如“saa7114”或“saa7115”。但通常 i2c 驱动程序会自动检测到这一点。chipid 的使用需要在稍后更仔细地研究。它在 i2c 驱动程序之间有所不同,因此可能会令人困惑。要查看支持哪些芯片变体,你可以查看 i2c 驱动程序代码中的 i2c_device_id 表。此表列出了所有可能性。
还有一个辅助函数
v4l2_i2c_new_subdev_board()
使用一个 i2c_board_info
结构,该结构传递给 i2c 驱动程序并替换 irq、platform_data 和 addr 参数。
如果子设备支持 s_config core ops,则会在子设备设置完成后使用 irq 和 platform_data 参数调用该操作。
v4l2_i2c_new_subdev()
函数将在内部调用 v4l2_i2c_new_subdev_board()
,使用 client_type
和 addr
填充一个 i2c_board_info
结构。
2.11. 集中管理的子设备活动状态¶
传统上,V4L2 子设备驱动程序维护活动设备配置的内部状态。这通常实现为例如一个 struct v4l2_mbus_framefmt
数组,每个 pad 一个条目,对于裁剪和合成矩形也是如此。
除了活动配置之外,每个子设备文件句柄都有一个由 V4L2 内核管理的 struct v4l2_subdev_state
,其中包含尝试配置。
为了简化子设备驱动程序,V4L2 子设备 API 现在可选地支持由 v4l2_subdev_state
表示的集中管理的活动配置。状态的一个实例(包含活动设备配置)作为 v4l2_subdev
结构的一部分存储在子设备本身中,而内核将一个尝试状态与每个打开的文件句柄相关联,以存储与该文件句柄相关的尝试配置。
子设备驱动程序可以通过在注册子设备之前调用 v4l2_subdev_init_finalize()
来选择使用状态来管理其活动配置。它们还必须调用 v4l2_subdev_cleanup()
以在注销子设备之前释放所有已分配的资源。内核会自动为每个打开的文件句柄分配和初始化一个状态,以存储尝试配置,并在关闭文件句柄时释放它。
使用 ACTIVE 和 TRY 格式 的 V4L2 子设备操作通过“state”参数接收要操作的正确状态。调用者必须通过调用 v4l2_subdev_lock_state()
和 v4l2_subdev_unlock_state()
来锁定和解锁状态。调用者可以通过使用 v4l2_subdev_call_state_active()
宏调用子设备操作来实现这一点。
不接收状态参数的操作隐式地作用于子设备活动状态,驱动程序可以通过调用 v4l2_subdev_lock_and_get_active_state()
来独占访问该状态。同样,必须通过调用 v4l2_subdev_unlock_state()
来释放子设备活动状态。
驱动程序绝不能手动访问存储在 v4l2_subdev
或文件句柄中的状态,而无需使用指定辅助函数。
虽然 V4L2 内核将正确的尝试或活动状态传递给子设备操作,但许多现有的设备驱动程序在使用 v4l2_subdev_call()
调用操作时会传递 NULL 状态。这种遗留结构导致子设备驱动程序出现问题,这些驱动程序让 V4L2 内核管理活动状态,因为它们希望接收适当的状态作为参数。为了帮助将子设备驱动程序转换为托管活动状态,而无需同时转换所有调用者,v4l2_subdev_call()
中添加了一个额外的包装层,该层通过使用 v4l2_subdev_lock_and_get_active_state()
获取和锁定被调用者的活动状态来处理 NULL 情况,并在调用后解锁状态。
整个子设备状态实际上分为三个部分:v4l2_subdev_state、子设备控件和子设备驱动程序的内部状态。将来,这些部分应合并为一个状态。目前,我们需要一种方法来处理这些部分的锁定。这可以通过共享一个锁来实现。v4l2_ctrl_handler 已经通过其“lock”指针支持这一点,并且状态也使用了相同的模型。驱动程序可以在调用 v4l2_subdev_init_finalize()
之前执行以下操作
sd->ctrl_handler->lock = &priv->mutex;
sd->state_lock = &priv->mutex;
这将驱动程序的私有互斥锁在控件和状态之间共享。
2.12. 流、多路复用媒体 pad 和内部路由¶
子设备驱动程序可以通过设置 V4L2_SUBDEV_FL_STREAMS 子设备标志并实现对集中管理的子设备活动状态、路由和基于流的配置的支持来实施对多路复用流的支持。
2.13. V4L2 子设备函数和数据结构¶
-
struct v4l2_decode_vbi_line¶
用于 decode_vbi_line
定义:
struct v4l2_decode_vbi_line {
u32 is_second_field;
u8 *p;
u32 line;
u32 type;
};
成员
is_second_field
对于第一个(奇数)场设置为 0;对于第二个(偶数)场设置为 1。
p
指向解码器中切片 VBI 数据的指针。退出时,指向有效载荷的开头。
line
切片 VBI 数据的行号 (1-23)
type
VBI 服务类型 (V4L2_SLICED_*)。如果未找到服务,则为 0
-
enum v4l2_subdev_io_pin_bits¶
子设备外部 IO 引脚配置位
常量
V4L2_SUBDEV_IO_PIN_DISABLE
禁用引脚配置。假定为 ENABLE。
V4L2_SUBDEV_IO_PIN_OUTPUT
如果引脚为输出,则设置此项。
V4L2_SUBDEV_IO_PIN_INPUT
如果引脚为输入,则设置此项。
V4L2_SUBDEV_IO_PIN_SET_VALUE
通过
struct v4l2_subdev_io_pin_config
->value 设置输出值。V4L2_SUBDEV_IO_PIN_ACTIVE_LOW
引脚有效位为第 0 位。否则,假定为高电平有效。
-
struct v4l2_subdev_io_pin_config¶
子设备外部 IO 引脚配置
定义:
struct v4l2_subdev_io_pin_config {
u32 flags;
u8 pin;
u8 function;
u8 value;
u8 strength;
};
成员
flags
此引脚配置的标志位掩码,其位由
enum v4l2_subdev_io_pin_bits
定义。pin
要配置的芯片外部 IO 引脚
function
要路由到 IO 引脚的内部信号焊盘/功能
value
引脚的初始值 - 例如,GPIO 输出值
strength
引脚驱动强度
-
struct v4l2_subdev_core_ops¶
为子设备定义核心操作回调
定义:
struct v4l2_subdev_core_ops {
int (*log_status)(struct v4l2_subdev *sd);
int (*s_io_pin_config)(struct v4l2_subdev *sd, size_t n, struct v4l2_subdev_io_pin_config *pincfg);
int (*init)(struct v4l2_subdev *sd, u32 val);
int (*load_fw)(struct v4l2_subdev *sd);
int (*reset)(struct v4l2_subdev *sd, u32 val);
int (*s_gpio)(struct v4l2_subdev *sd, u32 val);
long (*command)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
#ifdef CONFIG_COMPAT;
long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg);
#endif;
#ifdef CONFIG_VIDEO_ADV_DEBUG;
int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
int (*s_register)(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg);
#endif;
int (*s_power)(struct v4l2_subdev *sd, int on);
int (*interrupt_service_routine)(struct v4l2_subdev *sd, u32 status, bool *handled);
int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub);
int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub);
};
成员
log_status
用于 VIDIOC_LOG_STATUS() ioctl 处理程序代码的回调。
s_io_pin_config
为将不同内部信号焊盘复用到 IO 引脚的芯片配置一个或多个芯片 I/O 引脚。此函数接受一个指向 ‘n’ 个引脚配置条目数组的指针,每个引脚都有一个配置条目。此函数可以在子设备初始化以外的时间调用。
init
将传感器寄存器初始化为某种合理的默认值。不要用于新的驱动程序,并且应在现有驱动程序中删除。
load_fw
加载固件。
reset
通用重置命令。参数选择要重置的子系统。传递 0 将始终重置整个芯片。除非先在 linux-media 邮件列表中讨论,否则不要用于新的驱动程序。通常不应有任何理由重置设备。
s_gpio
设置 GPIO 引脚。现在非常简单,如果需要,可能需要使用方向参数进行扩展。
command
由内核驱动程序调用,以便调用子设备驱动程序内部具有单独回调的函数。
ioctl
在 V4L2 核心的 ioctl() 系统调用处理程序的末尾调用。用于为驱动程序上使用的私有 ioctl 提供支持。
compat_ioctl32
当 32 位应用程序使用 64 位内核时调用,以便修复从/向用户空间传递的数据。
g_register
用于 VIDIOC_DBG_G_REGISTER() ioctl 处理程序代码的回调。
s_register
用于 VIDIOC_DBG_S_REGISTER() ioctl 处理程序代码的回调。
s_power
使子设备进入省电模式(on == 0)或正常操作模式(on == 1)。已弃用。请参阅 编写摄像头传感器驱动程序。pre_streamon 和 post_streamoff 回调可用于在调用 s_stream 之前将总线设置为例如 LP-11 模式。
interrupt_service_routine
当由于此子设备而引发中断状态时,由桥接芯片的中断服务处理程序调用,以便此子设备可以处理细节。它可以计划稍后执行的工作。它不得休眠。从 IRQ 上下文调用。
subscribe_event
由驱动程序使用,以请求控制框架在控件的值更改时发出警告。
unsubscribe_event
从控制框架中删除事件订阅。
-
struct v4l2_subdev_tuner_ops¶
当 v4l 设备以无线电模式打开时使用的回调。
定义:
struct v4l2_subdev_tuner_ops {
int (*standby)(struct v4l2_subdev *sd);
int (*s_radio)(struct v4l2_subdev *sd);
int (*s_frequency)(struct v4l2_subdev *sd, const struct v4l2_frequency *freq);
int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
int (*enum_freq_bands)(struct v4l2_subdev *sd, struct v4l2_frequency_band *band);
int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
int (*s_tuner)(struct v4l2_subdev *sd, const struct v4l2_tuner *vt);
int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
int (*s_modulator)(struct v4l2_subdev *sd, const struct v4l2_modulator *vm);
int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type);
int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config);
};
成员
standby
使调谐器进入待机模式。下次使用时会自动唤醒。
s_radio
将调谐器切换到无线电模式的回调。驱动程序应在调谐器操作应在无线电模式下操作时显式调用它,然后才能处理它。用于同时具有 AM/FM 无线电接收器和电视的设备。
s_frequency
用于 VIDIOC_S_FREQUENCY() ioctl 处理程序代码的回调。
g_frequency
用于 VIDIOC_G_FREQUENCY() ioctl 处理程序代码的回调。必须填写 freq->type。通常由
video_ioctl2()
或桥接驱动程序完成。enum_freq_bands
用于 VIDIOC_ENUM_FREQ_BANDS() ioctl 处理程序代码的回调。
g_tuner
用于 VIDIOC_G_TUNER() ioctl 处理程序代码的回调。
s_tuner
用于 VIDIOC_S_TUNER() ioctl 处理程序代码的回调。必须填写 vt->type。通常由 video_ioctl2 或桥接驱动程序完成。
g_modulator
用于 VIDIOC_G_MODULATOR() ioctl 处理程序代码的回调。
s_modulator
用于 VIDIOC_S_MODULATOR() ioctl 处理程序代码的回调。
s_type_addr
设置调谐器类型及其 I2C 地址。
s_config
设置 tda9887 的特定内容,例如 port1、port2 和 qss
描述
注意
在同时具有 AM/FM 和电视的设备上,驱动程序必须显式调用 s_radio,以便在调谐器应切换到无线电模式时,才能处理其他需要它的 struct v4l2_subdev_tuner_ops
。此类用法的示例是
static void s_frequency(void *priv, const struct v4l2_frequency *f)
{
...
if (f.type == V4L2_TUNER_RADIO)
v4l2_device_call_all(v4l2_dev, 0, tuner, s_radio);
...
v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency);
}
-
struct v4l2_subdev_audio_ops¶
用于音频相关设置的回调
定义:
struct v4l2_subdev_audio_ops {
int (*s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_i2s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_stream)(struct v4l2_subdev *sd, int enable);
};
成员
s_clock_freq
设置音频时钟输出的频率(以 Hz 为单位)。用于将音频处理器从属到视频解码器,确保音频和视频保持同步。频率的常用值为 48000、44100 或 32000 Hz。如果不支持该频率,则返回 -EINVAL。
s_i2s_clock_freq
以 bps 为单位设置 I2S 速度。这用于提供一种标准方法来选择由某些板设计中的数字音频流驱动的 I2S 时钟。频率的常用值为 1024000 和 2048000。如果不支持该频率,则返回
-EINVAL
。s_routing
用于定义音频芯片的输入和/或输出引脚以及任何其他配置数据。切勿尝试在此级别使用用户级别的输入 ID(例如,复合、S-Video、调谐器)。i2c 设备不应知道输入引脚是否连接到复合连接器,因为在其他板或平台上它可能连接到完全不同的东西。调用驱动程序负责将用户级别输入映射到 i2c 设备上的正确引脚。
s_stream
用于通知音频代码流将开始或已停止。
-
struct v4l2_mbus_frame_desc_entry_csi2¶
定义:
struct v4l2_mbus_frame_desc_entry_csi2 {
u8 vc;
u8 dt;
};
成员
vc
CSI-2 虚拟通道
dt
CSI-2 数据类型 ID
-
enum v4l2_mbus_frame_desc_flags¶
媒体总线帧描述标志
常量
V4L2_MBUS_FRAME_DESC_FL_LEN_MAX
指示
struct v4l2_mbus_frame_desc_entry
->length 字段指定最大数据长度。
V4L2_MBUS_FRAME_DESC_FL_BLOB
指示格式没有行偏移,即接收器应使用 1D DMA。
-
struct v4l2_mbus_frame_desc_entry¶
媒体总线帧描述结构
定义:
struct v4l2_mbus_frame_desc_entry {
enum v4l2_mbus_frame_desc_flags flags;
u32 stream;
u32 pixelcode;
u32 length;
union {
struct v4l2_mbus_frame_desc_entry_csi2 csi2;
} bus;
};
成员
flags
位掩码标志,由
enum v4l2_mbus_frame_desc_flags
定义。stream
路由配置中的流
pixelcode
媒体总线像素代码,如果未设置 flags
FRAME_DESC_FL_BLOB
,则有效。length
每个帧的八位字节数,如果设置了 flags
V4L2_MBUS_FRAME_DESC_FL_LEN_MAX
,则有效。bus
总线特定的帧描述符参数
bus.csi2
CSI-2 特定的总线配置
-
enum v4l2_mbus_frame_desc_type¶
媒体总线帧描述类型
常量
V4L2_MBUS_FRAME_DESC_TYPE_UNDEFINED
未定义的帧描述类型。驱动程序不应使用此类型,它是为了向后兼容。
V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL
并行媒体总线。
V4L2_MBUS_FRAME_DESC_TYPE_CSI2
CSI-2 媒体总线。帧描述参数必须在
struct v4l2_mbus_frame_desc_entry
->csi2 中设置。
-
struct v4l2_mbus_frame_desc¶
媒体总线数据帧描述
定义:
struct v4l2_mbus_frame_desc {
enum v4l2_mbus_frame_desc_type type;
struct v4l2_mbus_frame_desc_entry entry[V4L2_FRAME_DESC_ENTRY_MAX];
unsigned short num_entries;
};
成员
type
entry
帧描述符数组
num_entries
entry 数组中的条目数
-
enum v4l2_subdev_pre_streamon_flags¶
pre_streamon 子设备核心操作的标志
常量
V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP
在调用 s_stream() 之前将发射器设置为 LP-11 或 LP-111 模式。
-
struct v4l2_subdev_video_ops¶
当 v4l 设备以视频模式打开时使用的回调。
定义:
struct v4l2_subdev_video_ops {
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags);
int (*g_std)(struct v4l2_subdev *sd, v4l2_std_id *norm);
int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm);
int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
int (*g_std_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_tvnorms)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_tvnorms_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
int (*s_stream)(struct v4l2_subdev *sd, int enable);
int (*g_pixelaspect)(struct v4l2_subdev *sd, struct v4l2_fract *aspect);
int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf, unsigned int *size);
int (*pre_streamon)(struct v4l2_subdev *sd, u32 flags);
int (*post_streamoff)(struct v4l2_subdev *sd);
};
成员
s_routing
请参阅 audio_ops 中的 s_routing,只是此版本用于视频设备。
s_crystal_freq
设置用于以 Hz 为单位生成时钟的晶体的频率。一个额外的标志字段允许设备特定的时钟频率分频器等配置。如果未使用,则将标志设置为 0。如果不支持该频率,则返回 -EINVAL。
g_std
用于 VIDIOC_G_STD() ioctl 处理程序代码的回调。
s_std
用于 VIDIOC_S_STD() ioctl 处理程序代码的回调。
s_std_output
为视频输出设备设置 v4l2_std_id。视频输入设备将忽略此设置。
g_std_output
获取视频输出设备的当前标准。视频输入设备将忽略此设置。
querystd
用于 VIDIOC_QUERYSTD() ioctl 处理程序代码的回调。
g_tvnorms
获取视频捕获设备支持的所有标准的
v4l2_std_id
。视频输出设备将忽略此设置。g_tvnorms_output
获取视频输出设备支持的所有标准的 v4l2_std_id。视频捕获设备将忽略此设置。
g_input_status
获取输入状态。与
struct v4l2_input
中的状态字段相同s_stream
在子设备上启动 (enabled == 1) 或停止 (enabled == 0) 流传输。停止失败将移除流传输启动时获取的任何资源,但驱动程序仍会返回错误代码。调用者应跟踪子设备状态,且不应启动或停止已启动或已停止的子设备。另请参阅 v4l2-subdev.c 中的 call_s_stream 包装器。
此回调已弃用。新驱动程序应改为实现
v4l2_subdev_pad_ops.enable_streams
和v4l2_subdev_pad_ops.disable_streams
操作,并对v4l2_subdev_video_ops.s_stream
操作使用 v4l2_subdev_s_stream_helper 来支持旧用户。驱动程序也不应直接调用 .s_stream() 子设备操作,而应使用
v4l2_subdev_enable_streams()
和v4l2_subdev_disable_streams()
辅助函数。g_pixelaspect
用于返回像素宽高比的回调函数。
s_rx_buffer
为子设备设置一个主机分配的内存缓冲区。子设备可以将 size 调整为较小的值,并且不得将超过 size 原始值的数据从 data 开始写入缓冲区。
pre_streamon
可以在实际启动流传输之前调用,以帮助初始化总线。当前的用法是在流传输之前将 CSI-2 发射器设置为 LP-11 或 LP-111 模式。请参阅
enum v4l2_subdev_pre_streamon_flags
。如果 pre_streamon 无法按照 flags 参数的指示执行操作,则应返回错误。特别是,-EACCES 表示不支持该操作。对于每次成功调用 pre_streamon,调用者都应调用 post_streamoff。
post_streamoff
在停止流传输后调用,但仅当先前调用过 pre_streamon 时才调用。
-
struct v4l2_subdev_vbi_ops¶
当 v4l 设备通过 vbi 设备节点以视频模式打开时使用的回调函数。
定义:
struct v4l2_subdev_vbi_ops {
int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line);
int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data);
int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data);
int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap);
int (*s_raw_fmt)(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
int (*g_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
int (*s_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
};
成员
decode_vbi_line
支持切片 VBI 的视频解码器需要实现此 ioctl。
struct v4l2_decode_vbi_line
的字段 p 设置为解码器生成的 VBI 数据的开始位置。然后,驱动程序解析切片的 VBI 数据,并相应地设置结构中的其他字段。指针 p 更新为指向有效负载的开始位置,该位置可以逐字复制到struct v4l2_sliced_vbi_data
的 data 字段中。如果没有找到有效的 VBI 数据,则返回时 type 字段设置为 0。s_vbi_data
用于在视频信号上生成 VBI 信号。
struct v4l2_sliced_vbi_data
填充了应输出的数据包。请注意,如果将 line 字段设置为 0,则禁用该 VBI 信号。如果没有找到有效的 VBI 数据,则返回时 type 字段设置为 0。g_vbi_data
用于从回读寄存器获取切片的 VBI 数据包。并非所有视频解码器都支持此功能。如果由于回读寄存器包含无效或错误数据而没有可用数据,则返回
-EIO
。请注意,您必须填写“id”成员和“field”成员(以确定应获取第一个或第二个场的 CC 数据)。g_sliced_vbi_cap
用于 VIDIOC_G_SLICED_VBI_CAP() ioctl 处理程序代码的回调函数。
s_raw_fmt
为原始 VBI 设置视频编码器/解码器。
g_sliced_fmt
检索当前的切片 VBI 设置。
s_sliced_fmt
设置切片的 VBI 设置。
-
struct v4l2_subdev_sensor_ops¶
v4l2-子设备传感器操作
定义:
struct v4l2_subdev_sensor_ops {
int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines);
int (*g_skip_frames)(struct v4l2_subdev *sd, u32 *frames);
};
成员
g_skip_top_lines
要跳过的图像顶部行数。某些传感器需要这样做,这些传感器总是会损坏输出图像的顶部几行,或者在其中发送其元数据。
g_skip_frames
在流启动时要跳过的帧数。对于在打开时会生成错误帧的错误传感器,这是必需的。
-
enum v4l2_subdev_ir_mode¶
描述支持的 IR 类型
常量
V4L2_SUBDEV_IR_MODE_PULSE_WIDTH
IR 使用 struct ir_raw_event 记录
-
struct v4l2_subdev_ir_parameters¶
用于 IR TX 或 TX 的参数
定义:
struct v4l2_subdev_ir_parameters {
unsigned int bytes_per_data_element;
enum v4l2_subdev_ir_mode mode;
bool enable;
bool interrupt_enable;
bool shutdown;
bool modulation;
u32 max_pulse_width;
unsigned int carrier_freq;
unsigned int duty_cycle;
bool invert_level;
bool invert_carrier_sense;
u32 noise_filter_min_width;
unsigned int carrier_range_lower;
unsigned int carrier_range_upper;
u32 resolution;
};
成员
bytes_per_data_element
在读取或写入调用中每个数据元素占用的字节数。
mode
由
enum v4l2_subdev_ir_mode
定义的 IR 模式。enable
如果为 true,则设备处于活动状态
interrupt_enable
如果为 true,则启用 IR 中断
shutdown
如果为 true:将硬件设置为低功耗/无功耗,false:正常模式
modulation
如果为 true,则使用载波,如果为 false:基带
max_pulse_width
最大脉冲宽度,以纳秒为单位,仅对基带信号有效
carrier_freq
载波频率,以赫兹为单位,仅对调制信号有效
duty_cycle
占空比百分比,仅对调制信号有效
invert_level
反转信号电平
invert_carrier_sense
将 0/空格作为载波突发发送。仅在 TX 中使用。
noise_filter_min_width
有效脉冲的最小时间,以纳秒为单位。仅用于 RX。
carrier_range_lower
较低的载波范围,以赫兹为单位,仅对调制信号有效。仅用于 RX。
carrier_range_upper
较高的载波范围,以赫兹为单位,仅对调制信号有效。仅用于 RX。
resolution
接收分辨率,以纳秒为单位。仅用于 RX。
-
struct v4l2_subdev_ir_ops¶
用于 IR 子设备的操作
定义:
struct v4l2_subdev_ir_ops {
int (*rx_read)(struct v4l2_subdev *sd, u8 *buf, size_t count, ssize_t *num);
int (*rx_g_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*rx_s_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*tx_write)(struct v4l2_subdev *sd, u8 *buf, size_t count, ssize_t *num);
int (*tx_g_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*tx_s_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
};
成员
rx_read
读取接收到的代码或脉冲宽度数据。语义类似于非阻塞 read() 调用。
rx_g_parameters
获取 IR 接收器的当前操作参数和状态。
rx_s_parameters
设置 IR 接收器的当前操作参数和状态。建议先调用 [rt]x_g_parameters 以填充当前状态,然后仅更改需要更改的字段。返回时,将返回设备的实际操作参数和状态。请注意,硬件限制可能会阻止实际设置与请求的设置匹配 - 例如,当请求 36,000 Hz 时,实际载波设置为 35,904 Hz。当 shutdown 参数为 true 时,则是一个例外。将返回最后使用的操作参数,但硬件的实际状态可能不同,以便在 shutdown 为 true 时最大限度地减少功耗和处理。
tx_write
写入要传输的代码或脉冲宽度数据。语义类似于非阻塞 write() 调用。
tx_g_parameters
获取 IR 发射器的当前操作参数和状态。
tx_s_parameters
设置 IR 发射器的当前操作参数和状态。建议先调用 [rt]x_g_parameters 以填充当前状态,然后仅更改需要更改的字段。返回时,将返回设备的实际操作参数和状态。请注意,硬件限制可能会阻止实际设置与请求的设置匹配 - 例如,当请求 36,000 Hz 时,实际载波设置为 35,904 Hz。当 shutdown 参数为 true 时,则是一个例外。将返回最后使用的操作参数,但硬件的实际状态可能不同,以便在 shutdown 为 true 时最大限度地减少功耗和处理。
-
struct v4l2_subdev_pad_config¶
用于存储子设备衬垫信息。
定义:
struct v4l2_subdev_pad_config {
struct v4l2_mbus_framefmt format;
struct v4l2_rect crop;
struct v4l2_rect compose;
struct v4l2_fract interval;
};
成员
format
crop
要用于裁剪的
struct v4l2_rect
compose
要用于合成的
struct v4l2_rect
interval
帧间隔
-
struct v4l2_subdev_stream_config¶
用于存储流配置。
定义:
struct v4l2_subdev_stream_config {
u32 pad;
u32 stream;
bool enabled;
struct v4l2_mbus_framefmt fmt;
struct v4l2_rect crop;
struct v4l2_rect compose;
struct v4l2_fract interval;
};
成员
pad
衬垫编号
stream
stream number
enabled
是否已使用
v4l2_subdev_enable_streams()
启用流fmt
crop
要用于裁剪的
struct v4l2_rect
compose
要用于合成的
struct v4l2_rect
interval
帧间隔
描述
此结构存储流的配置。
-
struct v4l2_subdev_stream_configs¶
流配置的集合。
定义:
struct v4l2_subdev_stream_configs {
u32 num_configs;
struct v4l2_subdev_stream_config *configs;
};
成员
num_configs
config 中的条目数。
configs
-
struct v4l2_subdev_krouting¶
子设备路由表
定义:
struct v4l2_subdev_krouting {
unsigned int len_routes;
unsigned int num_routes;
struct v4l2_subdev_route *routes;
};
成员
len_routes
路由数组的长度,以路由为单位
num_routes
路由的数量
routes
struct v4l2_subdev_route
描述
此结构包含子设备的路由表。
-
struct v4l2_subdev_state¶
用于存储子设备状态信息。
定义:
struct v4l2_subdev_state {
struct mutex _lock;
struct mutex *lock;
struct v4l2_subdev *sd;
struct v4l2_subdev_pad_config *pads;
struct v4l2_subdev_krouting routing;
struct v4l2_subdev_stream_configs stream_configs;
};
成员
_lock
‘lock’ 的默认值
lock
状态的互斥锁。可以由用户替换。
sd
与状态相关的子设备
pads
routing
子设备的路由表
stream_configs
流配置(仅适用于 V4L2_SUBDEV_FL_STREAMS)
描述
只有当主参数的 ‘which’ 字段设置为 V4L2_SUBDEV_FORMAT_TRY
时,此结构才需要传递给 pad op。对于 V4L2_SUBDEV_FORMAT_ACTIVE
,传递 NULL
是安全的。
-
struct v4l2_subdev_pad_ops¶
v4l2-子设备 pad 级别操作
定义:
struct v4l2_subdev_pad_ops {
int (*enum_mbus_code)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code);
int (*enum_frame_size)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_size_enum *fse);
int (*enum_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval_enum *fie);
int (*get_fmt)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_format *format);
int (*set_fmt)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_format *format);
int (*get_selection)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel);
int (*set_selection)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel);
int (*get_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *interval);
int (*set_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *interval);
int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*s_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*g_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*query_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*dv_timings_cap)(struct v4l2_subdev *sd, struct v4l2_dv_timings_cap *cap);
int (*enum_dv_timings)(struct v4l2_subdev *sd, struct v4l2_enum_dv_timings *timings);
#ifdef CONFIG_MEDIA_CONTROLLER;
int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt);
#endif ;
int (*get_frame_desc)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *fd);
int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *fd);
int (*get_mbus_config)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_config *config);
int (*set_routing)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state,enum v4l2_subdev_format_whence which, struct v4l2_subdev_krouting *route);
int (*enable_streams)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, u32 pad, u64 streams_mask);
int (*disable_streams)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, u32 pad, u64 streams_mask);
};
成员
enum_mbus_code
用于 VIDIOC_SUBDEV_ENUM_MBUS_CODE() ioctl 处理程序代码的回调。
enum_frame_size
用于 VIDIOC_SUBDEV_ENUM_FRAME_SIZE() ioctl 处理程序代码的回调。
enum_frame_interval
用于 VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL() ioctl 处理程序代码的回调。
get_fmt
用于 VIDIOC_SUBDEV_G_FMT() ioctl 处理程序代码的回调。
set_fmt
用于 VIDIOC_SUBDEV_S_FMT() ioctl 处理程序代码的回调。
get_selection
用于 VIDIOC_SUBDEV_G_SELECTION() ioctl 处理程序代码的回调。
set_selection
用于 VIDIOC_SUBDEV_S_SELECTION() ioctl 处理程序代码的回调。
get_frame_interval
用于 VIDIOC_SUBDEV_G_FRAME_INTERVAL() ioctl 处理程序代码的回调。
set_frame_interval
用于 VIDIOC_SUBDEV_S_FRAME_INTERVAL() ioctl 处理程序代码的回调。
get_edid
用于 VIDIOC_SUBDEV_G_EDID() ioctl 处理程序代码的回调。
set_edid
用于 VIDIOC_SUBDEV_S_EDID() ioctl 处理程序代码的回调。
s_dv_timings
在子设备中设置自定义 dv 时序。当子设备能够在硬件中设置详细的时序信息以生成/检测视频信号时使用此方法。
g_dv_timings
在子设备中获取自定义 dv 时序。
query_dv_timings
用于 VIDIOC_QUERY_DV_TIMINGS() ioctl 处理程序代码的回调。
dv_timings_cap
用于 VIDIOC_SUBDEV_DV_TIMINGS_CAP() ioctl 处理程序代码的回调。
enum_dv_timings
用于 VIDIOC_SUBDEV_ENUM_DV_TIMINGS() ioctl 处理程序代码的回调。
link_validate
由媒体控制器代码使用,以检查属于管道的链接是否可用于流。
get_frame_desc
获取当前低级媒体总线帧参数。
set_frame_desc
设置低级媒体总线帧参数,fd 数组可能会被子设备驱动程序调整以适应设备的功能。
get_mbus_config
获取远程子设备的媒体总线配置。媒体总线配置通常在子设备探测时从固件接口检索,立即应用于硬件,并最终由驱动程序调整。远程子设备(通常是视频接收器)应使用此操作来查询发送端的总线配置,以便相应地调整自己的配置。调用者应确保从远程端获取尽可能最新的配置,可能会在即将开始流传输时调用此操作。如果调用的 pad 索引无效或发生不可恢复的故障,则操作应失败。
set_routing
启用或禁用子设备路由表中描述的数据连接路由。实现此操作的子设备必须设置 V4L2_SUBDEV_FL_STREAMS 标志。
enable_streams
在给定的源 pad 上启用 streams_mask 中定义的流。实现此操作的子设备必须使用子设备核心提供的活动状态管理(通过在初始化时调用
v4l2_subdev_init_finalize()
启用)。不要直接调用,而应使用v4l2_subdev_enable_streams()
。仅支持单个流而不设置 V4L2_SUBDEV_CAP_STREAMS 子设备功能标志的驱动程序可以忽略掩码参数。
disable_streams
在给定的源 pad 上禁用 streams_mask 中定义的流。实现此操作的子设备必须使用子设备核心提供的活动状态管理(通过在初始化时调用
v4l2_subdev_init_finalize()
启用)。不要直接调用,而应使用v4l2_subdev_disable_streams()
。仅支持单个流而不设置 V4L2_SUBDEV_CAP_STREAMS 子设备功能标志的驱动程序可以忽略掩码参数。
-
struct v4l2_subdev_ops¶
子设备操作
定义:
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_vbi_ops *vbi;
const struct v4l2_subdev_ir_ops *ir;
const struct v4l2_subdev_sensor_ops *sensor;
const struct v4l2_subdev_pad_ops *pad;
};
成员
core
指向
struct v4l2_subdev_core_ops
的指针。可以为NULL
tuner
指向
struct v4l2_subdev_tuner_ops
的指针。可以为NULL
audio
指向
struct v4l2_subdev_audio_ops
的指针。可以为NULL
video
指向
struct v4l2_subdev_video_ops
的指针。可以为NULL
vbi
指向
struct v4l2_subdev_vbi_ops
的指针。可以为NULL
ir
指向
struct v4l2_subdev_ir_ops
的指针。可以为NULL
sensor
指向
struct v4l2_subdev_sensor_ops
的指针。可以为NULL
pad
指向
struct v4l2_subdev_pad_ops
的指针。可以为NULL
-
struct v4l2_subdev_internal_ops¶
V4L2 子设备内部操作
定义:
struct v4l2_subdev_internal_ops {
int (*init_state)(struct v4l2_subdev *sd, struct v4l2_subdev_state *state);
int (*registered)(struct v4l2_subdev *sd);
void (*unregistered)(struct v4l2_subdev *sd);
int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
int (*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
void (*release)(struct v4l2_subdev *sd);
};
成员
init_state
将子设备状态初始化为默认值
registered
在此子设备注册时调用。调用时,v4l2_dev 字段将设置为正确的 v4l2_device。
unregistered
在此子设备注销时调用。调用时,v4l2_dev 字段仍设置为正确的 v4l2_device。
open
当应用程序打开子设备设备节点时调用。
close
当子设备设备节点关闭时调用。请注意,可能在 unregistered 之后调用 close!
release
当子设备的最后一个用户消失时调用。这发生在 unregistered 回调之后,以及 v4l-subdevX 设备节点的最后一个打开的文件句柄被关闭时。如果没有为此子设备创建设备节点,则 release 回调会在 unregistered 回调之后立即调用。release 回调通常用于释放包含 v4l2_subdev 结构的内存。对于任何设置了 V4L2_SUBDEV_FL_HAS_DEVNODE 标志的子设备来说,几乎是必需的。
描述
注意
永远不要从驱动程序中调用此操作,只有 v4l2 框架才能调用这些操作。
-
struct v4l2_subdev_platform_data¶
稳压器配置结构
定义:
struct v4l2_subdev_platform_data {
struct regulator_bulk_data *regulators;
int num_regulators;
void *host_priv;
};
成员
regulators
用于打开/关闭子设备的可选稳压器
num_regulators
稳压器的数量
host_priv
特定于某个视频主机设备的每个子设备数据
-
struct v4l2_subdev¶
描述 V4L2 子设备
定义:
struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER);
struct media_entity entity;
#endif;
struct list_head list;
struct module *owner;
bool owner_v4l2_dev;
u32 flags;
struct v4l2_device *v4l2_dev;
const struct v4l2_subdev_ops *ops;
const struct v4l2_subdev_internal_ops *internal_ops;
struct v4l2_ctrl_handler *ctrl_handler;
char name[52];
u32 grp_id;
void *dev_priv;
void *host_priv;
struct video_device *devnode;
struct device *dev;
struct fwnode_handle *fwnode;
struct list_head async_list;
struct list_head async_subdev_endpoint_list;
struct v4l2_async_notifier *subdev_notifier;
struct list_head asc_list;
struct v4l2_subdev_platform_data *pdata;
struct mutex *state_lock;
struct led_classdev *privacy_led;
struct v4l2_subdev_state *active_state;
u64 enabled_pads;
bool s_stream_enabled;
};
成员
entity
指向
struct media_entity
的指针list
子设备的列表
owner
所有者与驱动程序的
struct device
所有者相同。owner_v4l2_dev
如果
sd->owner
与 v4l2_dev->dev 的所有者匹配,则为 true。由v4l2_device_register_subdev()
初始化。flags
子设备标志。可以是:
V4L2_SUBDEV_FL_IS_I2C
- 如果此子设备是 i2c 设备,则设置此标志;V4L2_SUBDEV_FL_IS_SPI
- 如果此子设备是 spi 设备,则设置此标志;V4L2_SUBDEV_FL_HAS_DEVNODE
- 如果此子设备需要设备节点,则设置此标志;V4L2_SUBDEV_FL_HAS_EVENTS
- 如果此子设备生成事件,则设置此标志。v4l2_dev
指向结构体
v4l2_device
的指针ops
指向结构体
v4l2_subdev_ops
的指针internal_ops
指向结构体
v4l2_subdev_internal_ops
的指针。永远不要从驱动程序内部调用这些内部操作!ctrl_handler
此子设备的控制句柄。可以为 NULL。
name
子设备的名称。请注意,名称必须唯一。
grp_id
可用于对相似的子设备进行分组。该值是驱动程序特定的。
dev_priv
指向私有数据的指针
host_priv
指向子设备所连接的设备的私有数据的指针。
devnode
子设备设备节点
dev
指向物理设备的指针(如果有)
fwnode
子设备的 fwnode_handle,通常与 dev->of_node->fwnode 或 dev->fwnode 相同(以非 NULL 为准)。
async_list
将此子设备链接到全局 subdev_list 或 notifier->done_list 列表。
async_subdev_endpoint_list
在
struct v4l2_async_subdev_endpoint
的 async_subdev_endpoint_entry 中的列表条目。subdev_notifier
使用
v4l2_async_register_subdev_sensor()
为子设备隐式注册的子设备通知器。asc_list
异步连接列表,即
struct v4l2_async_connection
.subdev_entry。pdata
子设备平台数据的公共部分
state_lock
指向用于所有子设备状态的锁的指针,由驱动程序设置。这是可选的。如果为 NULL,则每个状态实例将获得自己的锁。
privacy_led
指向用于传感器隐私 LED 的 LED classdev 的可选指针。
active_state
子设备的活动状态(对于在内部跟踪状态的子设备为 NULL)。通过调用
v4l2_subdev_init_finalize()
初始化。enabled_pads
由
v4l2_subdev_enable_streams()
和v4l2_subdev_disable_streams()
辅助函数用于回退情况的已启用 pad 的位掩码。s_stream_enabled
跟踪是否已使用 s_stream 启用流。这仅用于 call_s_stream() 的内部使用。
描述
子设备驱动程序的每个实例都应创建此结构,无论是独立的还是嵌入在更大的结构中。
此结构应由 v4l2_subdev_init()
或其变体之一初始化: v4l2_spi_subdev_init()
, v4l2_i2c_subdev_init()
。
-
media_entity_to_v4l2_subdev¶
media_entity_to_v4l2_subdev (ent)
从嵌入其中的
struct media_entity
返回struct v4l2_subdev
。
参数
ent
指向
struct media_entity
的指针。
-
vdev_to_v4l2_subdev¶
vdev_to_v4l2_subdev (vdev)
从嵌入其中的
struct video_device
返回struct v4l2_subdev
。
参数
vdev
指向
struct video_device
的指针
-
struct v4l2_subdev_fh¶
用于存储每个文件句柄的子设备信息
定义:
struct v4l2_subdev_fh {
struct v4l2_fh vfh;
struct module *owner;
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API);
struct v4l2_subdev_state *state;
u64 client_caps;
#endif;
};
成员
vfh
指向
struct v4l2_fh
的指针owner
指向此文件句柄所有者的模块的指针
state
指向
struct v4l2_subdev_state
的指针client_caps
V4L2_SUBDEV_CLIENT_CAP_*
的位掩码
-
to_v4l2_subdev_fh¶
to_v4l2_subdev_fh (fh)
从嵌入其中的
struct v4l2_fh
返回struct v4l2_subdev_fh
。
参数
fh
指向
struct v4l2_fh
的指针
-
void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)¶
设置 V4L2 设备私有设备数据
参数
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针void *p
指向要存储的私有设备数据的指针。
-
void *v4l2_get_subdevdata(const struct v4l2_subdev *sd)¶
获取 V4L2 设备私有设备数据
-
void v4l2_set_subdev_hostdata(struct v4l2_subdev *sd, void *p)¶
设置 V4L2 设备私有主机数据
参数
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针void *p
指向要存储的私有数据的指针。
-
void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)¶
获取 V4L2 设备私有数据
-
int v4l2_subdev_get_fwnode_pad_1_to_1(struct media_entity *entity, struct fwnode_endpoint *endpoint)¶
从子设备 fwnode 端点获取 pad 编号,假设端口与 pad 之间是 1:1 映射
参数
struct media_entity *entity
指向子设备实体的指针
struct fwnode_endpoint *endpoint
指向已解析的 fwnode 端点的指针
描述
此函数可以用作子设备的 .get_fwnode_pad 操作,这些子设备将端口号和 pad 索引 1:1 映射。如果端点归子设备所有,则该函数返回端点端口号。
成功时返回端点端口号,否则返回负错误代码。
-
int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, struct media_link *link, struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt)¶
验证媒体链接
参数
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针struct media_link *link
指向
struct media_link
的指针struct v4l2_subdev_format *source_fmt
指向
struct v4l2_subdev_format
的指针struct v4l2_subdev_format *sink_fmt
指向
struct v4l2_subdev_format
的指针
描述
此函数确保链接的源和目标上的宽度、高度和媒体总线像素代码相等。
-
int v4l2_subdev_link_validate(struct media_link *link)¶
验证媒体链接
参数
struct media_link *link
指向
struct media_link
的指针
描述
此函数调用子设备的 link_validate 操作来验证媒体链接是否对流传输有效。它还在内部调用 v4l2_subdev_link_validate_default()
以确保链接的源和目标上的宽度、高度和媒体总线像素代码相等。
该函数可以用作 v4l2_subdev 实例的直接 media_entity_ops.link_validate
实现。它支持子设备之间的所有链接,以及子设备和视频设备之间的链接,前提是视频设备也实现了它们的 media_entity_ops.link_validate
操作。
-
bool v4l2_subdev_has_pad_interdep(struct media_entity *entity, unsigned int pad0, unsigned int pad1)¶
子设备的 MC has_pad_interdep 实现
参数
struct media_entity *entity
指向
struct media_entity
的指针unsigned int pad0
第一个 pad 的 pad 编号
unsigned int pad1
第二个 pad 的 pad 编号
描述
此函数是针对实现多路复用流 API 的子设备(由 V4L2_SUBDEV_FL_STREAMS 子设备标志指示)的 media_entity_operations.has_pad_interdep 操作的实现。
如果 pad0 和 pad1 之间存在活动路由,则认为两个 pad 是相互依赖的。
-
struct v4l2_subdev_state *__v4l2_subdev_state_alloc(struct v4l2_subdev *sd, const char *lock_name, struct lock_class_key *key)¶
分配 v4l2_subdev_state
参数
struct v4l2_subdev *sd
指向要为其分配状态的
struct v4l2_subdev
的指针。const char *lock_name
状态锁的名称
struct lock_class_key *key
锁的 lock_class_key
描述
当不再需要状态时,必须调用 __v4l2_subdev_state_free()
。
不要由驱动程序直接调用。
-
void __v4l2_subdev_state_free(struct v4l2_subdev_state *state)¶
释放 v4l2_subdev_state
参数
struct v4l2_subdev_state *state
要释放的 v4l2_subdev_state。
描述
不要由驱动程序直接调用。
-
v4l2_subdev_init_finalize¶
v4l2_subdev_init_finalize (sd)
完成子设备的初始化
参数
sd
子设备
描述
此函数完成子设备的初始化,包括为子设备分配活动状态。
使用集中式活动状态的子设备驱动程序必须在初始化子设备结构并调用 media_entity_pads_init()
后,但在注册子设备之前调用此函数。
当删除子设备时,用户必须调用 v4l2_subdev_cleanup()
。
-
void v4l2_subdev_cleanup(struct v4l2_subdev *sd)¶
释放子设备分配的资源
参数
struct v4l2_subdev *sd
子设备
描述
清理 V4L2 异步子设备。如果已使用 v4l2_async_subdev_endpoint_add()
或 v4l2_subdev_init_finalize()
将资源与其关联,则必须在子设备释放时作为其一部分调用此函数。
-
v4l2_subdev_state_get_format¶
v4l2_subdev_state_get_format (state, pad, ...)
获取指向流格式的指针
参数
state
子设备状态
pad
pad ID
...
流 ID(可选参数)
描述
这会在子设备状态中返回指向给定 pad + 流的 struct v4l2_mbus_framefmt
的指针。
对于不了解流的驱动程序,将返回相应 pad 的格式。如果 pad 不存在,则返回 NULL。
-
v4l2_subdev_state_get_crop¶
v4l2_subdev_state_get_crop (state, pad, ...)
获取指向流裁剪矩形的指针
参数
state
子设备状态
pad
pad ID
...
流 ID(可选参数)
描述
这会在子设备状态中返回指向给定 pad + 流的裁剪矩形的指针。
对于不了解流的驱动程序,将返回相应 pad 的裁剪矩形。如果 pad 不存在,则返回 NULL。
-
v4l2_subdev_state_get_compose¶
v4l2_subdev_state_get_compose (state, pad, ...)
获取指向流合成矩形的指针
参数
state
子设备状态
pad
pad ID
...
流 ID(可选参数)
描述
这会在子设备状态中返回指向给定 pad + 流的合成矩形的指针。
对于不了解流的驱动程序,将返回相应 pad 的合成矩形。如果 pad 不存在,则返回 NULL。
-
v4l2_subdev_state_get_interval¶
v4l2_subdev_state_get_interval (state, pad, ...)
获取指向流帧间隔的指针
参数
state
子设备状态
pad
pad ID
...
流 ID(可选参数)
描述
此函数返回子设备状态中给定 pad + stream 的帧间隔指针。
对于不感知 stream 的驱动程序,将返回相应 pad 的帧间隔。如果 pad 不存在,则返回 NULL。
-
int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_format *format)¶
根据状态填充 format
参数
struct v4l2_subdev *sd
子设备
struct v4l2_subdev_state *state
子设备状态
struct v4l2_subdev_format *format
指向
struct v4l2_subdev_format
的指针
描述
根据 format 结构中的信息填充 format->format 字段。
如果子设备驱动程序在其 get_fmt 操作中不需要执行任何特殊操作,则支持活动状态的子设备驱动程序可以使用此函数来实现 v4l2_subdev_pad_ops.get_fmt。
成功时返回 0,否则返回错误值。
-
int v4l2_subdev_get_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *fi)¶
根据状态填充帧间隔
参数
struct v4l2_subdev *sd
子设备
struct v4l2_subdev_state *state
子设备状态
struct v4l2_subdev_frame_interval *fi
指向
struct v4l2_subdev_frame_interval
的指针
描述
根据 fi 结构中的信息填充 fi->interval 字段。
如果子设备驱动程序在其 get_frame_interval 操作中不需要执行任何特殊操作,则支持活动状态的子设备驱动程序可以使用此函数来实现 v4l2_subdev_pad_ops.get_frame_interval。
成功时返回 0,否则返回错误值。
-
int v4l2_subdev_set_routing(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, const struct v4l2_subdev_krouting *routing)¶
将给定的路由设置到子设备状态
参数
struct v4l2_subdev *sd
子设备
struct v4l2_subdev_state *state
子设备状态
const struct v4l2_subdev_krouting *routing
将复制到子设备状态的路由
描述
这将从状态中释放旧的路由表(如果有),为给定的路由分配足够的空间,并复制路由。
这可以在子设备驱动程序的 set_routing 操作中验证路由后使用。
-
for_each_active_route¶
for_each_active_route (routing, route)
迭代路由表的所有活动路由
参数
routing
路由表
路由
路由迭代器
-
int v4l2_subdev_set_routing_with_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, const struct v4l2_subdev_krouting *routing, const struct v4l2_mbus_framefmt *fmt)¶
将给定的路由和格式设置到子设备状态
参数
struct v4l2_subdev *sd
子设备
struct v4l2_subdev_state *state
子设备状态
const struct v4l2_subdev_krouting *routing
将复制到子设备状态的路由
const struct v4l2_mbus_framefmt *fmt
用于初始化所有流的格式
描述
这与 v4l2_subdev_set_routing 相同,但另外使用给定的格式初始化所有流。
-
int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing, u32 pad, u32 stream, u32 *other_pad, u32 *other_stream)¶
查找相反的 stream
参数
const struct v4l2_subdev_krouting *routing
用于查找相反侧的路由
u32 pad
pad ID
u32 stream
stream id
u32 *other_pad
用于返回相反 pad 的指针
u32 *other_stream
用于返回相反 stream 的指针
描述
此函数使用路由表查找与给定 pad + stream 相反的 pad + stream。
如果调用者不需要该值,则 other_pad 和/或 other_stream 可以为 NULL。
成功时返回 0,如果未找到匹配的路由,则返回 -EINVAL。
-
struct v4l2_mbus_framefmt *v4l2_subdev_state_get_opposite_stream_format(struct v4l2_subdev_state *state, u32 pad, u32 stream)¶
获取指向相反 stream 格式的指针
参数
struct v4l2_subdev_state *state
子设备状态
u32 pad
pad ID
u32 stream
stream id
描述
这将返回指向子设备状态中与给定 pad + stream 相反的 pad + stream 的 struct v4l2_mbus_framefmt
的指针。
如果状态不包含给定的 pad + stream,则返回 NULL。
-
u64 v4l2_subdev_state_xlate_streams(const struct v4l2_subdev_state *state, u32 pad0, u32 pad1, u64 *streams)¶
将 stream 从一个 pad 转换为另一个 pad
参数
const struct v4l2_subdev_state *state
子设备状态
u32 pad0
第一个 pad
u32 pad1
第二个 pad
u64 *streams
第一个 pad 上的 stream 位掩码
描述
子设备的接收端端口上的数据流会根据子设备状态路由表中的定义路由到发送端端口。路由的接收端和发送端的数据流编号不一定匹配。此函数使用 state 中的路由表,将 pad0 上的数据流编号(以位掩码 streams 表示)转换为 pad1 上对应的流编号。它返回 pad1 上的数据流掩码,并使用路由表中找到的数据流更新 streams。
pad0 和 pad1 必须分别为接收端和发送端端口,顺序不限。
返回值
pad1 上路由到 pad0 上 streams 的数据流的位掩码。
-
enum v4l2_subdev_routing_restriction¶
子设备内部路由限制
常量
V4L2_SUBDEV_ROUTING_NO_1_TO_N
一个输入流不能路由到多个输出流(流复制)
V4L2_SUBDEV_ROUTING_NO_N_TO_1
多个输入流不能路由到同一个输出流(流合并)
V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX
来自接收端端口的所有流必须路由到单个发送端端口
V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX
发送端端口上的所有流必须来自单个接收端端口
V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING
接收端端口不应包含多路复用的流
V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING
发送端端口不应包含多路复用的流
V4L2_SUBDEV_ROUTING_ONLY_1_TO_1
只允许非重叠的一对一数据流路由( V4L2_SUBDEV_ROUTING_NO_1_TO_N 和 V4L2_SUBDEV_ROUTING_NO_N_TO_1 的组合)
V4L2_SUBDEV_ROUTING_NO_STREAM_MIX
来自接收端端口的所有流必须路由到单个发送端端口,并且该发送端端口不得从任何其他接收端端口获取路由( V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX 和 V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX 的组合)
V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING
发送端或接收端都不允许有多路复用的流。
-
int v4l2_subdev_routing_validate(struct v4l2_subdev *sd, const struct v4l2_subdev_krouting *routing, enum v4l2_subdev_routing_restriction disallow)¶
验证路由是否符合驱动程序约束
参数
struct v4l2_subdev *sd
子设备
const struct v4l2_subdev_krouting *routing
要验证的路由
enum v4l2_subdev_routing_restriction disallow
路由限制
描述
此函数验证给定的路由是否符合 disallow 约束。
成功时返回 0,否则返回错误值。
-
int v4l2_subdev_enable_streams(struct v4l2_subdev *sd, u32 pad, u64 streams_mask)¶
启用端口上的数据流
参数
struct v4l2_subdev *sd
子设备
u32 pad
端口
u64 streams_mask
要启用的数据流的位掩码
描述
此函数启用子设备的发送端 pad 上的数据流。端口由其索引标识,而数据流由 streams_mask 位掩码标识。这允许一次在端口上启用多个数据流。
不允许启用已启用的数据流。如果 streams_mask 包含已启用的数据流,则此函数返回 -EALREADY,并且不执行任何操作。
每个数据流启用仅适用于实现 .enable_streams() 和 .disable_streams() 操作的子设备。对于其他子设备,此函数通过调用 .s_stream() 操作来实现尽力而为的兼容性,但仅限于具有单个发送端端口的子设备。
不感知数据流的驱动程序应将 streams_mask 设置为 BIT_ULL(0)。
返回值
0:成功
-EALREADY:streams_mask 中的一个数据流已启用
-EINVAL:端口索引无效,或者不对应于发送端端口
-EOPNOTSUPP:由于子设备有多个发送端端口,无法回退到旧版 .s_stream() 操作
-
int v4l2_subdev_disable_streams(struct v4l2_subdev *sd, u32 pad, u64 streams_mask)¶
禁用端口上的数据流
参数
struct v4l2_subdev *sd
子设备
u32 pad
端口
u64 streams_mask
要禁用的数据流的位掩码
描述
此函数禁用子设备的发送端 pad 上的数据流。端口由其索引标识,而数据流由 streams_mask 位掩码标识。这允许一次在端口上禁用多个数据流。
不允许禁用未启用的数据流。如果 streams_mask 包含已禁用的数据流,则此函数返回 -EALREADY,并且不执行任何操作。
每个数据流禁用仅适用于实现 .enable_streams() 和 .disable_streams() 操作的子设备。对于其他子设备,此函数通过调用 .s_stream() 操作来实现尽力而为的兼容性,但仅限于具有单个发送端端口的子设备。
不感知数据流的驱动程序应将 streams_mask 设置为 BIT_ULL(0)。
返回值
0:成功
-EALREADY:streams_mask 中的一个数据流未启用
-EINVAL:端口索引无效,或者不对应于发送端端口
-EOPNOTSUPP:由于子设备有多个发送端端口,无法回退到旧版 .s_stream() 操作
-
int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable)¶
使用 enable_streams 和 disable_streams 实现子设备 s_stream 操作的辅助函数
参数
struct v4l2_subdev *sd
子设备
int enable
启用或禁用数据流
描述
实现感知数据流的 v4l2_subdev_pad_ops.enable_streams
和 v4l2_subdev_pad_ops.disable_streams
操作的子设备驱动程序可以使用此辅助函数来实现旧版 v4l2_subdev_video_ops.s_stream
操作。
此辅助函数只能由具有单个发送端端口的子设备使用。
返回值
成功时返回 0,否则返回负错误代码。
-
void v4l2_subdev_lock_state(struct v4l2_subdev_state *state)¶
锁定子设备状态
-
void v4l2_subdev_unlock_state(struct v4l2_subdev_state *state)¶
解锁子设备状态
参数
struct v4l2_subdev_state *state
子设备状态
描述
解锁给定的子设备状态。
-
void v4l2_subdev_lock_states(struct v4l2_subdev_state *state1, struct v4l2_subdev_state *state2)¶
锁定两个子设备状态
参数
struct v4l2_subdev_state *state1
一个子设备状态
struct v4l2_subdev_state *state2
另一个子设备状态
描述
锁定两个子设备的状态。
使用后,必须使用 v4l2_subdev_unlock_states()
解锁状态。
这与在两个状态上都调用 v4l2_subdev_lock_state()
不同,这样如果状态共享同一个锁,则锁只会被获取一次(因此不会发生死锁)。调用者负责确保锁总是以相同的顺序获取。
-
void v4l2_subdev_unlock_states(struct v4l2_subdev_state *state1, struct v4l2_subdev_state *state2)¶
解锁两个子设备状态
参数
struct v4l2_subdev_state *state1
一个子设备状态
struct v4l2_subdev_state *state2
另一个子设备状态
描述
解锁两个子设备的状态。
这与在两个状态上都调用 v4l2_subdev_unlock_state()
不同,这样如果状态共享同一个锁,则锁只会被释放一次。
-
struct v4l2_subdev_state *v4l2_subdev_get_unlocked_active_state(struct v4l2_subdev *sd)¶
检查活动子设备状态是否已解锁并返回它
参数
struct v4l2_subdev *sd
子设备
描述
返回子设备的活动状态,如果子设备不支持活动状态则返回 NULL。如果状态不为 NULL,则调用 lockdep_assert_not_held(),如果状态被锁定则发出警告。
例如,当获取活动状态仅用于将其传递给其他函数,而不访问状态字段时,可以使用此函数。
-
struct v4l2_subdev_state *v4l2_subdev_get_locked_active_state(struct v4l2_subdev *sd)¶
检查活动子设备状态是否已锁定并返回它
参数
struct v4l2_subdev *sd
子设备
描述
返回子设备的活动状态,如果子设备不支持活动状态则返回 NULL。如果状态不为 NULL,则调用 lockdep_assert_held(),如果状态未锁定则发出警告。
当调用者知道活动状态已被锁定时,可以使用此函数。
-
struct v4l2_subdev_state *v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)¶
锁定并返回子设备的活动子设备状态
参数
struct v4l2_subdev *sd
子设备
描述
返回子设备的已锁定活动状态,如果子设备不支持活动状态则返回 NULL。
使用后,必须使用 v4l2_subdev_unlock_state()
解锁状态。
-
void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)¶
初始化子设备结构体
参数
struct v4l2_subdev *sd
指向要初始化的
struct v4l2_subdev
的指针const struct v4l2_subdev_ops *ops
指向
struct v4l2_subdev_ops
的指针。
-
v4l2_subdev_call¶
v4l2_subdev_call (sd, o, f, args...)
调用 v4l2_subdev 的一个操作。
参数
sd
指向
struct v4l2_subdev
的指针o
位于
struct v4l2_subdev_ops
中包含 f 的元素的名称。那里的每个元素都分组了一组回调函数。f
要调用的回调函数。回调函数根据
struct v4l2_subdev_ops
中每个元素进行分组定义。args...
f 的参数。
示例
err = v4l2_subdev_call(sd, video, s_std, norm);
-
v4l2_subdev_call_state_active¶
v4l2_subdev_call_state_active (sd, o, f, args...)
调用 v4l2_subdev 的一个操作,该操作将状态作为参数,并将子设备的活动状态传递给它。
参数
sd
指向
struct v4l2_subdev
的指针o
位于
struct v4l2_subdev_ops
中包含 f 的元素的名称。那里的每个元素都分组了一组回调函数。f
要调用的回调函数。回调函数根据
struct v4l2_subdev_ops
中每个元素进行分组定义。args...
f 的参数。
描述
这类似于 v4l2_subdev_call()
,只是此版本只能用于将子设备状态作为参数的操作。该宏将获取活动状态,在调用操作之前锁定它,并在调用后解锁它。
-
v4l2_subdev_call_state_try¶
v4l2_subdev_call_state_try (sd, o, f, args...)
调用 v4l2_subdev 的一个操作,该操作将状态作为参数,并将新分配的试用状态传递给子设备。
参数
sd
指向
struct v4l2_subdev
的指针o
位于
struct v4l2_subdev_ops
中包含 f 的元素的名称。那里的每个元素都分组了一组回调函数。f
要调用的回调函数。回调函数根据
struct v4l2_subdev_ops
中每个元素进行分组定义。args...
f 的参数。
描述
这类似于 v4l2_subdev_call_state_active()
,只是由于此版本会分配新状态,因此仅适用于 V4L2_SUBDEV_FORMAT_TRY 用例。
注意
只有旧的非 MC 驱动程序可能需要此宏。
-
v4l2_subdev_has_op¶
v4l2_subdev_has_op (sd, o, f)
检查子设备是否定义了某个操作。
参数
sd
指向
struct v4l2_subdev
的指针o
struct v4l2_subdev_ops
中回调函数的分组,f 是其中的一部分。f
要检查其是否存在的回调函数。
-
void v4l2_subdev_notify_event(struct v4l2_subdev *sd, const struct v4l2_event *ev)¶
为子设备传递事件通知
参数
struct v4l2_subdev *sd
要传递事件的子设备
const struct v4l2_event *ev
要传递的事件
描述
将把指定的事件传递给所有订阅了 v42l 子设备事件队列的用户空间事件侦听器以及使用 notify 回调的桥接驱动程序。notify 回调的通知类型将为 V4L2_DEVICE_NOTIFY_EVENT
。
-
bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd)¶
返回子设备是否正在流式传输
参数
struct v4l2_subdev *sd
子设备
描述
v4l2_subdev_is_streaming()
判断子设备当前是否正在流式传输。此处的“流式传输”是指是否已成功调用 .s_stream() 或 .enable_streams(),并且流式传输尚未被禁用。
如果子设备实现了 .enable_streams(),则必须在持有活动状态锁定的情况下调用此函数。