5. 媒体控制器设备¶
5.1. 媒体控制器¶
媒体控制器用户空间 API 在 媒体控制器 uAPI 书籍中进行了文档化。本文档侧重于媒体框架的内核端实现。
5.1.1. 抽象媒体设备模型¶
发现设备内部拓扑并在运行时对其进行配置是媒体框架的目标之一。为了实现这一目标,硬件设备被建模为称为实体并通过垫连接的构建块的定向图。
实体是基本的媒体硬件构建块。它可以对应于各种逻辑块,例如物理硬件设备(例如 CMOS 传感器)、逻辑硬件设备(片上系统图像处理管道中的构建块)、DMA 通道或物理连接器。
垫是连接端点,实体可以通过该端点与其他实体进行交互。由实体产生的数据(不限于视频)从实体的输出流向一个或多个实体输入。垫不应与芯片边界处的物理引脚混淆。
链接是两个垫之间的点对点定向连接,无论是在同一实体上还是在不同实体上。数据从源垫流向接收垫。
5.1.2. 媒体设备¶
媒体设备由 struct media_device
实例表示,该实例在 include/media/media-device.h
中定义。结构的分配由媒体设备驱动程序处理,通常通过将 media_device
实例嵌入到更大的驱动程序特定结构中。
驱动程序通过调用 media_device_init()
来初始化媒体设备实例。在初始化媒体设备实例后,通过宏 media_device_register()
调用 __media_device_register()
来注册,并通过调用 media_device_unregister()
来注销。初始化的媒体设备最终必须通过调用 media_device_cleanup()
来清理。
请注意,不允许注销先前未注册的媒体设备实例,或清理先前未初始化的媒体设备实例。
5.1.3. 实体¶
实体由 struct media_entity
实例表示,该实例在 include/media/media-entity.h
中定义。该结构通常嵌入到更高级别的结构中,例如 v4l2_subdev
或 video_device
实例,尽管驱动程序可以直接分配实体。
驱动程序通过调用 media_entity_pads_init()
来初始化实体垫。
驱动程序通过调用 media_device_register_entity()
来注册实体到媒体设备,并通过调用 media_device_unregister_entity()
来注销。
5.1.4. 接口¶
接口由 struct media_interface
实例表示,该实例在 include/media/media-entity.h
中定义。目前,仅定义了一种类型的接口:设备节点。此类接口由 struct media_intf_devnode
表示。
驱动程序通过调用 media_devnode_create()
来初始化和创建设备节点接口,并通过调用 media_devnode_remove()
来删除它们。
5.1.5. 垫¶
垫由 struct media_pad
实例表示,该实例在 include/media/media-entity.h
中定义。每个实体将其垫存储在由实体驱动程序管理的垫数组中。驱动程序通常将该数组嵌入到驱动程序特定的结构中。
垫由其实体及其在垫数组中的从 0 开始的索引标识。
这两个信息都存储在 struct media_pad
中,这使得 struct media_pad
指针成为存储和传递链接引用的规范方式。
垫具有描述垫功能和状态的标志。
MEDIA_PAD_FL_SINK
指示垫支持接收数据。MEDIA_PAD_FL_SOURCE
指示垫支持源数据。
注意
对于每个垫,必须设置 MEDIA_PAD_FL_SINK
或 MEDIA_PAD_FL_SOURCE
中的一个且只有一个。
5.1.6. 链接¶
链接由 struct media_link
实例表示,该实例在 include/media/media-entity.h
中定义。有两种类型的链接
1. 垫到垫链接:
通过其 PAD 将两个实体关联起来。每个实体都有一个列表,该列表指向源自或针对其任何垫的所有链接。因此,给定的链接存储两次,一次在源实体中,一次在目标实体中。
驱动程序通过调用 media_create_pad_link()
来创建垫到垫链接,并通过 media_entity_remove_links()
删除。
2. 接口到实体链接:
将一个接口与一个链接关联起来。
驱动程序通过调用 media_create_intf_link()
来创建接口到实体链接,并通过 media_remove_intf_links()
删除。
注意
只有在两个端点都已创建后才能创建链接。
链接具有描述链接功能和状态的标志。有效值在 media_create_pad_link()
和 media_create_intf_link()
中进行了描述。
5.1.7. 图遍历¶
媒体框架提供 API 来遍历媒体图,定位连接的实体和链接。
要迭代属于媒体设备的所有实体,驱动程序可以使用媒体设备 for_each_entity 宏,该宏在 include/media/media-device.h
中定义。
struct media_entity *entity;
media_device_for_each_entity(entity, mdev) {
// entity will point to each entity in turn
...
}
辅助函数可用于查找两个给定垫之间的链接,或通过启用的链接连接到另一个垫的垫(media_entity_find_link()
、media_pad_remote_pad_first()
、media_entity_remote_source_pad_unique()
和 media_pad_remote_pad_unique()
)。
5.1.8. 使用计数和电源处理¶
由于驱动程序在电源管理需求方面的差异很大,媒体控制器不实现电源管理。但是,struct media_entity
包含一个 use_count
字段,媒体驱动程序可以使用该字段来跟踪每个实体的用户数量,以满足电源管理需求。
media_entity
。use_count
字段由媒体驱动程序拥有,实体驱动程序不得触摸该字段。对该字段的访问必须受到 media_device
。graph_mutex
锁的保护。
5.1.9. 链接设置¶
可以通过调用 media_entity_setup_link()
在运行时修改链接属性。
5.1.10. 管道和媒体流¶
媒体流是源自一个或多个源设备(例如传感器)的像素或元数据流,并通过媒体实体垫流向最终接收器。该流可以在路线上通过设备进行修改(例如,缩放或像素格式转换),或者可以拆分为多个分支,或者可以合并多个分支。
媒体管道是一组相互依赖的媒体流。这种相互依赖可能是由硬件引起的(例如,如果已启用第一个流,则无法更改第二个流的配置),或者由于软件设计而由驱动程序引起。最常见的媒体管道由一个不分支的单个流组成。
在开始流式传输时,驱动程序必须通知管道中的所有实体,以防止在流式传输期间通过调用 media_pipeline_start()
来修改链接状态。
该函数会将管道的所有垫标记为流式传输。
pipe 参数指向的 struct media_pipeline
实例将存储在管道的每个垫中。驱动程序应将 struct media_pipeline
嵌入到更高级别的管道结构中,然后可以通过 struct media_pad
pipe 字段访问管道。
可以嵌套调用 media_pipeline_start()
。对于该函数的所有嵌套调用,管道指针必须相同。
media_pipeline_start()
可能会返回错误。在这种情况下,它将清理它自己所做的任何更改。
在停止流式传输时,驱动程序必须使用 media_pipeline_stop()
通知实体。
如果已多次调用 media_pipeline_start()
,则需要相同数量的 media_pipeline_stop()
调用来停止流式传输。media_entity
。pipe
字段将在上次嵌套的停止调用时重置为 NULL
。
如果链接的任一端是流式传输实体,则默认情况下链接配置将失败并显示 -EBUSY
。可以在流式传输时修改的链接必须使用 MEDIA_LNK_FL_DYNAMIC
标志进行标记。
如果在流式传输实体上需要禁止其他操作(例如更改实体配置参数),则驱动程序可以显式检查媒体实体 stream_count 字段,以确定实体是否正在流式传输。此操作必须在 media_device graph_mutex 持有的情况下完成。
5.1.11. 链接验证¶
链接验证由 media_pipeline_start()
对管道中具有接收垫的任何实体执行。 media_entity
。link_validate()
回调用于此目的。在 link_validate()
回调中,实体驱动程序应检查连接实体的源垫的属性与其自身的接收垫是否匹配。匹配的实际含义取决于实体的类型(以及最终硬件的属性)。
子系统应通过提供特定于子系统的辅助函数来促进链接验证,以方便访问通常需要的信息,并最终提供一种使用驱动程序特定回调的方式。
5.1.12. 管道遍历¶
一旦使用 media_pipeline_start()
构建了管道,驱动程序可以使用 :c:macro:´media_pipeline_for_each_entity` 和 :c:macro:´media_pipeline_for_each_pad` 宏迭代管道中的实体或垫。迭代垫很简单
media_pipeline_pad_iter iter;
struct media_pad *pad;
media_pipeline_for_each_pad(pipe, &iter, pad) {
/* 'pad' will point to each pad in turn */
...
}
要迭代实体,迭代器需要作为附加步骤进行初始化和清理
media_pipeline_entity_iter iter;
struct media_entity *entity;
int ret;
ret = media_pipeline_entity_iter_init(pipe, &iter);
if (ret)
...;
media_pipeline_for_each_entity(pipe, &iter, entity) {
/* 'entity' will point to each entity in turn */
...
}
media_pipeline_entity_iter_cleanup(&iter);
5.1.13. 媒体控制器设备分配器 API¶
当媒体设备属于多个驱动程序时,共享媒体设备将使用共享 struct device
作为查找的键进行分配。
共享媒体设备应保持注册状态,直到最后一个驱动程序注销它。此外,当所有引用都释放时,应释放媒体设备。每个驱动程序在探测期间(在分配媒体设备时)都会获得对媒体设备的引用。如果媒体设备已经分配,则分配 API 会增加 refcount 并返回现有的媒体设备。驱动程序在其断开连接例程中调用 media_device_delete()
时,会将引用放回。
从 kref put 处理程序注销和清理媒体设备,以确保媒体设备在最后一个驱动程序注销媒体设备之前保持注册状态。
驱动程序使用
驱动程序应使用适当的媒体核心例程来管理共享媒体设备的生命周期,处理两种状态:1. 分配 -> 注册 -> 删除 2. 获取对已注册设备的引用 -> 删除
调用 media_device_delete()
例程以确保正确处理共享媒体设备删除。
驱动程序探测: 调用 media_device_usb_allocate()
以分配或获取引用调用 media_device_register()
,如果媒体 devnode 未注册
驱动程序断开连接: 调用 media_device_delete()
以释放 media_device。释放由 kref put 处理程序处理。
5.1.14. API 定义¶
-
struct media_entity_notify¶
媒体实体通知
定义:
struct media_entity_notify {
struct list_head list;
void *notify_data;
void (*notify)(struct media_entity *entity, void *notify_data);
};
成员
列表
列表头
notify_data
调用回调的输入数据
通知
回调函数指针
描述
驱动程序可以注册一个回调,以便在新实体注册到媒体设备时采取操作。此处理程序旨在创建现有实体之间的链接,而不应创建实体并注册它们。
-
struct media_device_ops¶
媒体设备操作
定义:
struct media_device_ops {
int (*link_notify)(struct media_link *link, u32 flags, unsigned int notification);
struct media_request *(*req_alloc)(struct media_device *mdev);
void (*req_free)(struct media_request *req);
int (*req_validate)(struct media_request *req);
void (*req_queue)(struct media_request *req);
};
成员
link_notify
链接状态更改通知回调。使用 graph_mutex 持有状态调用此回调。
req_alloc
分配请求。如果需要分配大于
struct media_request
的结构,请设置此项。 req_alloc 和 req_free 必须同时设置或同时设置为 NULL。req_free
释放请求。如果也设置了 req_alloc,请设置此项,否则保留为 NULL。
req_validate
验证请求,但不要立即排队。调用此操作时会持有 req_queue_mutex 锁。
req_queue
对已验证的请求进行排队,不能失败。如果排队此请求时出现问题,则应在驱动程序内部将其标记为这样,并且任何相关的缓冲区最终都必须以 VB2_BUF_STATE_ERROR 状态返回到 vb2。调用此操作时会持有 req_queue_mutex 锁。重要的是在所有其他对象类型排队之后,最后对 vb2 缓冲区对象进行排队:对缓冲区进行排队会启动请求处理,因此与请求(以及缓冲区)相关的所有其他对象都必须可供驱动程序使用。并且一旦缓冲区排队,驱动程序就可以在 req_queue 退出之前完成或删除请求中的对象。
-
struct media_device¶
媒体设备
定义:
struct media_device {
struct device *dev;
struct media_devnode *devnode;
char model[32];
char driver_name[32];
char serial[40];
char bus_info[32];
u32 hw_revision;
u64 topology_version;
u32 id;
struct ida entity_internal_idx;
int entity_internal_idx_max;
struct list_head entities;
struct list_head interfaces;
struct list_head pads;
struct list_head links;
struct list_head entity_notify;
struct mutex graph_mutex;
struct media_graph pm_count_walk;
void *source_priv;
int (*enable_source)(struct media_entity *entity, struct media_pipeline *pipe);
void (*disable_source)(struct media_entity *entity);
const struct media_device_ops *ops;
struct mutex req_queue_mutex;
atomic_t request_id;
};
成员
dev
父设备
devnode
媒体设备节点
型号
设备型号名称
driver_name
可选设备驱动程序名称。如果未设置,则对
MEDIA_IOC_DEVICE_INFO
的调用将返回dev->driver->name
。例如,这是 USB 驱动程序所需要的,否则它们都将显示为驱动程序名称为“usb”。序列号
设备序列号(可选)
bus_info
唯一且稳定的设备位置标识符
hw_revision
硬件设备修订版本
topology_version
用于存储图拓扑版本的单调计数器。每次拓扑更改时都应递增。
id
在上次注册的图对象上使用的唯一 ID
entity_internal_idx
图遍历算法使用的唯一内部实体 ID
entity_internal_idx_max
分配的内部实体索引
实体
已注册实体的列表
接口
已注册接口的列表
垫
已注册垫的列表
链接
已注册链接的列表
entity_notify
已注册 entity_notify 回调的列表
graph_mutex
保护对
struct media_device
数据的访问pm_count_walk
用于电源状态步行的图步行。使用 graph_mutex 序列化访问。
source_priv
用于启用/禁用源处理程序的驱动程序私有数据
启用源
启用源处理程序函数指针
禁用源
禁用源处理程序函数指针
ops
操作处理程序回调
req_queue_mutex
相对于停止或启动流式传输的其他操作,序列化 MEDIA_REQUEST_IOC_QUEUE ioctl。
request_id
用于生成唯一请求 ID
描述
此结构表示抽象的高级媒体设备。它允许轻松访问实体并提供基本的媒体设备级别支持。可以直接分配该结构或将其嵌入到更大的结构中。
父 dev 是物理设备。必须在注册媒体设备之前设置它。
model 是通过 sysfs 导出的描述性模型名称。它不必是唯一的。
enable_source 是一个处理程序,用于查找接收实体的源实体,并在源实体空闲时激活它们之间的链接。驱动程序应在访问源之前调用此处理程序。
disable_source 是一个处理程序,用于查找接收实体的源实体并停用它们之间的链接。驱动程序应调用此处理程序以释放源。
用例:查找连接到解码器实体的调谐器实体,并检查它是否可用,并从 enable_source 激活它们之间的链接,并从 disable_source 停用。
注意
预计网桥驱动程序在 media_device
注册时或网桥驱动程序在探测期间找到 media_device 时实现并设置处理程序。网桥驱动程序使用运行 enable_source 和 disable_source 处理程序所需的信息设置 source_priv。调用者应持有 graph_mutex 以访问和调用 enable_source 和 disable_source 处理程序。
-
void media_device_init(struct media_device *mdev)¶
初始化媒体设备元素
参数
struct media_device *mdev
指向 struct
media_device
的指针
描述
此函数在注册之前初始化媒体设备。媒体设备初始化和注册分为两个函数,以避免竞争条件,并在媒体图完成之前使媒体设备可供用户空间使用。
因此,驱动程序需要首先初始化媒体设备,注册媒体设备中的任何实体,创建 pad 到 pad 的链接,然后最后通过调用 media_device_register()
作为最后一步来注册媒体设备。
调用者负责在注册之前初始化媒体设备。必须设置以下字段
dev 必须指向父设备
model 必须填充设备型号名称
如果 bus_info 字段以“0”开头,则 bus_info 字段由 media_device_init()
为 PCI 和平台设备设置。
-
void media_device_cleanup(struct media_device *mdev)¶
清理媒体设备元素
参数
struct media_device *mdev
指向 struct
media_device
的指针
描述
此函数将销毁在 media_device_init()
中初始化的 graph_mutex。
-
int __media_device_register(struct media_device *mdev, struct module *owner)¶
注册一个媒体设备元素
参数
struct media_device *mdev
指向 struct
media_device
的指针struct module *owner
应填充
THIS_MODULE
描述
用户应该调用 media_device_register()
宏。
调用者负责在注册之前初始化 media_device
结构。必须设置 media_device
的以下字段
media_device.model
必须用设备的型号名称填充,并作为以 NUL 结尾的 UTF-8 字符串。设备/型号修订版不得存储在此字段中。
以下字段是可选的
media_device.serial
是一个唯一的序列号,存储为以 NUL 结尾的 ASCII 字符串。该字段足够大,可以以文本形式存储 GUID。如果硬件未提供唯一的序列号,则必须将此字段留空。
media_device.bus_info
表示设备在系统中的位置,作为以 NUL 结尾的 ASCII 字符串。对于 PCI/PCIe 设备,media_device.bus_info
必须设置为“PCI:”(或“PCIe:”),后跟 pci_name() 的值。对于 USB 设备,必须使用usb_make_path()
函数。应用程序使用此字段来区分未提供序列号的其他相同设备。
media_device.hw_revision
是驱动程序特定格式的硬件设备修订版。如果可能,应使用 KERNEL_VERSION() 宏格式化修订版。
注意
成功注册后,将创建一个名为 media[0-9]+ 的字符设备。设备主编号和次编号是动态的。型号名称作为 sysfs 属性导出。
注销尚未注册的媒体设备是不安全的。
返回
成功时返回零,否则返回负错误代码。
-
media_device_register¶
media_device_register (mdev)
注册一个媒体设备元素
参数
mdev
指向 struct
media_device
的指针
描述
此宏调用 __media_device_register()
,将 THIS_MODULE
作为 __media_device_register()
的第二个参数(owner)传递。
-
void media_device_unregister(struct media_device *mdev)¶
注销媒体设备元素
-
int media_device_register_entity(struct media_device *mdev, struct media_entity *entity)¶
在先前注册的媒体设备中注册媒体实体。
参数
struct media_device *mdev
指向 struct
media_device
的指针struct media_entity *entity
指向要注册的
media_entity
结构的指针
描述
实体由唯一的正整数 ID 标识。媒体控制器框架将自动生成此类 ID。ID 不保证是连续的,并且 ID 号可能会在新内核版本上更改。因此,驱动程序和用户空间都不应硬编码 ID 号来引用实体,而应在需要时使用框架来查找 ID。
应在调用 media_device_register_entity()
之前初始化 media_entity 名称、类型和标志字段。嵌入在更高级别标准结构中的实体可以通过更高级别的框架设置其中的一些字段。
如果设备有 pad,则应在此函数之前调用 media_entity_pads_init()
。否则,应在调用此函数之前将 media_entity.pad
和 media_entity.num_pads
置零。
实体具有描述实体功能和状态的标志
MEDIA_ENT_FL_DEFAULT
指示给定类型的默认实体。这可以用于报告默认音频和视频设备或默认摄像头传感器。
注意
驱动程序应在调用此函数之前设置实体功能。请注意,驱动程序不应使用值 MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN
和 MEDIA_ENT_F_UNKNOWN
。
-
void media_device_unregister_entity(struct media_entity *entity)¶
注销媒体实体。
参数
struct media_entity *entity
指向要注销的
media_entity
结构的指针
描述
当调用此函数时,将自动从 media_device 注销与实体关联的所有链接和所有 PAD。
注销实体不会更改其他实体的 ID,并且先前使用的 ID 将永远不会重用于新注册的实体。
注销媒体设备时,将自动注销其所有实体。然后不需要手动实体注销。
注意
如果需要,媒体实体实例本身必须由驱动程序显式释放。
-
void media_device_register_entity_notify(struct media_device *mdev, struct media_entity_notify *nptr)¶
注册媒体 entity_notify 回调
参数
struct media_device *mdev
媒体设备
struct media_entity_notify *nptr
媒体 entity_notify
描述
注意
注册新实体时,将调用所有注册的 media_entity_notify 回调。
-
void media_device_unregister_entity_notify(struct media_device *mdev, struct media_entity_notify *nptr)¶
注销媒体实体通知回调
参数
struct media_device *mdev
媒体设备
struct media_entity_notify *nptr
媒体 entity_notify
-
void media_device_pci_init(struct media_device *mdev, struct pci_dev *pci_dev, const char *name)¶
从 PCI 设备创建并初始化
media_device
结构。
参数
struct media_device *mdev
指向 struct
media_device
的指针struct pci_dev *pci_dev
指向 pci_dev 结构的指针
const char *name
媒体设备名称。如果
NULL
,则例程将使用 pci 设备的默认名称,由 pci_name() 宏给出。
-
void __media_device_usb_init(struct media_device *mdev, struct usb_device *udev, const char *board_name, const char *driver_name)¶
从 PCI 设备创建并初始化
media_device
结构。
参数
struct media_device *mdev
指向 struct
media_device
的指针struct usb_device *udev
指向
struct usb_device
的指针const char *board_name
媒体设备名称。如果
NULL
,则例程将使用 USB 产品名称(如果可用)。const char *driver_name
驱动程序的名称。如果
NULL
,则例程将使用udev->dev->driver->name
给出的名称,这通常是错误的做法。
描述
注意
最好调用 media_device_usb_init()
,因为此类宏会用 KBUILD_MODNAME
填充 driver_name。
-
media_device_usb_init¶
media_device_usb_init (mdev, udev, name)
从 PCI 设备创建并初始化
media_device
结构。
参数
mdev
指向 struct
media_device
的指针udev
指向
struct usb_device
的指针name
媒体设备名称。如果
NULL
,则例程将使用 USB 产品名称(如果可用)。
描述
此宏调用 media_device_usb_init()
,传递用 KBUILD_MODNAME
填充的 media_device_usb_init()
driver_name 参数。
参数
char *bus_info
在其中写入总线信息(字符数组)的变量
size_t bus_info_size
bus_info 的长度
struct device *dev
相关的
struct device
描述
基于 dev
设置总线信息。当前,这是为 PCI 和平台设备完成的。需要 dev 为非 NULL 才能执行此操作。
此函数不应从驱动程序调用。
-
struct media_file_operations¶
媒体设备文件操作
定义:
struct media_file_operations {
struct module *owner;
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
__poll_t (*poll) (struct file *, struct poll_table_struct *);
long (*ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*open) (struct file *);
int (*release) (struct file *);
};
成员
owner
应填充
THIS_MODULE
read
指向实现 read() 系统调用的函数的指针
write
指向实现 write() 系统调用的函数的指针
poll
指向实现 poll() 系统调用的函数的指针
ioctl
指向实现 ioctl() 系统调用的函数的指针
compat_ioctl
指向将处理在用 64 位编译的内核上对 ioctl() 系统调用的 32 位用户空间调用的函数的指针。
open
指向实现 open() 系统调用的函数的指针
release
指向将释放由 open 函数分配的资源的函数的指针。
-
struct media_devnode¶
媒体设备节点
定义:
struct media_devnode {
struct media_device *media_dev;
const struct media_file_operations *fops;
struct device dev;
struct cdev cdev;
struct device *parent;
int minor;
unsigned long flags;
void (*release)(struct media_devnode *devnode);
};
成员
media_dev
指向 struct
media_device
的指针fops
指向具有媒体设备操作的
media_file_operations
结构的指针dev
指向包含媒体控制器设备的
device
结构的指针cdev
struct cdev 指针字符设备
parent
父设备
minor
设备节点次编号
flags
标志,
MEDIA_FLAG_*
常量的组合release
在 media-device.c 的
media_devnode_release()
例程结束时调用的释放回调。
描述
此结构表示与媒体相关的设备节点。
parent 是物理设备。必须由核心驱动程序或设备驱动程序在注册节点之前设置。
-
int media_devnode_register(struct media_device *mdev, struct media_devnode *devnode, struct module *owner)¶
注册媒体设备节点
参数
struct media_device *mdev
我们要注册设备节点的
struct media_device
struct media_devnode *devnode
我们要注册的媒体设备节点结构
struct module *owner
应填充
THIS_MODULE
描述
注册代码分配次编号,并将新设备节点注册到内核。如果找不到空闲的次编号,或者设备节点的注册失败,则返回错误。
成功时返回零。
请注意,如果 media_devnode_register 调用失败,则不会调用 media_devnode 结构的 release() 回调,因此调用者负责释放任何数据。
-
void media_devnode_unregister_prepare(struct media_devnode *devnode)¶
清除媒体设备节点注册位
参数
struct media_devnode *devnode
要准备注销的设备节点
描述
这将清除传递的设备注册位。将来的打开调用将遇到错误。应在 media_devnode_unregister()
之前调用,以避免与注销和设备文件打开调用发生竞争。
如果设备节点从未注册或已注销,则可以安全地调用此函数。
-
void media_devnode_unregister(struct media_devnode *devnode)¶
注销媒体设备节点
参数
struct media_devnode *devnode
要注销的设备节点
描述
这将注销传递的设备。将来的打开调用将遇到错误。
-
struct media_devnode *media_devnode_data(struct file *filp)¶
返回指向
media_devnode
的指针
参数
struct file *filp
指向
file
结构的指针
-
int media_devnode_is_registered(struct media_devnode *devnode)¶
如果
media_devnode
已注册,则返回 true;否则返回 false。
-
enum media_gobj_type¶
图对象的类型
常量
MEDIA_GRAPH_ENTITY
标识媒体实体
MEDIA_GRAPH_PAD
标识媒体 pad
MEDIA_GRAPH_LINK
标识媒体链接
MEDIA_GRAPH_INTF_DEVNODE
通过设备节点标识媒体内核 API 接口
-
struct media_gobj¶
定义一个图对象。
定义:
struct media_gobj {
struct media_device *mdev;
u32 id;
struct list_head list;
};
成员
mdev
指向拥有该对象的
media_device
结构的指针id
非零对象 ID 标识符。ID 在 media_device 内部应该是唯一的,因为它由
MEDIA_BITS_PER_TYPE
组成,用于存储类型,再加上MEDIA_BITS_PER_ID
,用于存储 ID列表
存储在每种类型的 mdev 对象列表中的列表条目
描述
媒体图上的所有对象都应嵌入此结构
-
struct media_entity_enum¶
媒体实体的枚举。
定义:
struct media_entity_enum {
unsigned long *bmap;
int idx_max;
};
成员
bmap
位图,其中每个位代表
struct media_entity
->internal_idx 处的一个实体。idx_max
bmap 中的位数
-
struct media_graph¶
媒体图遍历状态
定义:
struct media_graph {
struct {
struct media_entity *entity;
struct list_head *link;
} stack[MEDIA_ENTITY_ENUM_MAX_DEPTH];
struct media_entity_enum ent_enum;
int top;
};
成员
stack
图遍历堆栈;堆栈包含有关要步行的媒体实体的路径以及通过其到达的链接的信息。
stack.entity
指向图中的
struct media_entity
的指针。stack.link
指向
struct list_head
的指针。ent_enum
已访问的实体
top
堆栈顶部
-
struct media_pipeline¶
媒体管道相关信息
定义:
struct media_pipeline {
bool allocated;
struct media_device *mdev;
struct list_head pads;
int start_count;
};
成员
allocated
媒体管道由框架分配和释放
mdev
管道所属的媒体设备
垫
media_pipeline_pad 列表
start_count
媒体管道启动 - 停止计数
-
struct media_pipeline_pad¶
媒体管道的一部分的 pad
定义:
struct media_pipeline_pad {
struct list_head list;
struct media_pipeline *pipe;
struct media_pad *pad;
};
成员
列表
媒体 pad pads 列表中的条目
pipe
pad 所属的 media_pipeline
pad
媒体 pad
描述
此结构将 pad 与媒体管道相关联。media_pipeline_pad 的实例由 media_pipeline_start()
在构建管道时创建,并存储在 media_pad.pads
列表中。media_pipeline_stop()
从列表中删除条目并删除它们。
-
struct media_pipeline_pad_iter¶
media_pipeline_for_each_pad 的迭代器
定义:
struct media_pipeline_pad_iter {
struct list_head *cursor;
};
成员
cursor
当前元素
-
struct media_pipeline_entity_iter¶
media_pipeline_for_each_entity 的迭代器
定义:
struct media_pipeline_entity_iter {
struct media_entity_enum ent_enum;
struct list_head *cursor;
};
成员
ent_enum
实体枚举跟踪器
cursor
当前元素
-
struct media_link¶
媒体图的一部分的链接对象。
定义:
struct media_link {
struct media_gobj graph_obj;
struct list_head list;
union {
struct media_gobj *gobj0;
struct media_pad *source;
struct media_interface *intf;
};
union {
struct media_gobj *gobj1;
struct media_pad *sink;
struct media_entity *entity;
};
struct media_link *reverse;
unsigned long flags;
bool is_backlink;
};
成员
graph_obj
嵌入式结构,包含媒体对象公共数据
列表
与拥有链接的实体或接口关联的链接列表。
{unnamed_union}
anonymous
gobj0
联合的一部分。用于获取链接的第一个 graph_object 的指针。
source
联合的一部分。仅当第一个对象 (gobj0) 是 pad 时使用。在这种情况下,它表示源 pad。
intf
联合的一部分。仅当第一个对象 (gobj0) 是接口时使用。
{unnamed_union}
anonymous
gobj1
联合的一部分。用于获取链接的第二个 graph_object 的指针。
sink
联合体的一部分。仅当第二个对象 (gobj1) 是 pad 时使用。在这种情况下,它表示 sink pad。
实体
联合体的一部分。仅当第二个对象 (gobj1) 是实体时使用。
reverse
指向 pad 到 pad 链接的反向链接的指针。
flags
链接标志,如 uapi/media.h (MEDIA_LNK_FL_*) 中所定义
is_backlink
指示链接是否为反向链接。
-
enum media_pad_signal_type¶
媒体 pad 中的信号类型
常量
PAD_SIGNAL_DEFAULT
默认信号。当所有输入或所有输出都由 pad 编号唯一标识时,使用此信号。
PAD_SIGNAL_ANALOG
pad 包含模拟信号。它可以是射频、中频、基带信号或子载波。调谐器输入、IF-PLL 解调器、复合和 S-video 信号应使用它。
PAD_SIGNAL_DV
包含数字视频信号,可以是来自模拟电视视频源的采样比特流。在这种情况下,它通常包含 VBI 数据。
PAD_SIGNAL_AUDIO
包含来自音频子载波的中频模拟信号或音频比特流。中频信号由调谐器提供,并由音频 AM/FM 解码器使用。比特流音频由音频解码器提供。
-
struct media_pad¶
媒体 pad 图对象。
定义:
struct media_pad {
struct media_gobj graph_obj;
struct media_entity *entity;
u16 index;
u16 num_links;
enum media_pad_signal_type sig_type;
unsigned long flags;
struct media_pipeline *pipe;
};
成员
graph_obj
嵌入式结构,包含媒体对象公共数据
实体
此 pad 所属的实体
index
实体 pads 数组中的 Pad 索引,从 0 到 n 编号
num_links
连接到此 pad 的链接数
sig_type
媒体 pad 中的信号类型
flags
Pad 标志,如 include/uapi/linux/media.h 中所定义(查找
MEDIA_PAD_FL_*
)pipe
此 pad 所属的 Pipeline。使用
media_entity_pipeline()
访问此字段。
-
struct media_entity_operations¶
媒体实体操作
定义:
struct media_entity_operations {
int (*get_fwnode_pad)(struct media_entity *entity, struct fwnode_endpoint *endpoint);
int (*link_setup)(struct media_entity *entity,const struct media_pad *local, const struct media_pad *remote, u32 flags);
int (*link_validate)(struct media_link *link);
bool (*has_pad_interdep)(struct media_entity *entity, unsigned int pad0, unsigned int pad1);
};
成员
get_fwnode_pad
基于 fwnode 端点返回 pad 编号,如果出错,则返回负值。此操作可用于将 fwnode 映射到媒体 pad 编号。可选。
link_setup
通知实体链接更改。该操作可能会返回错误,在这种情况下,链接设置将被取消。可选。
link_validate
返回从实体角度来看链接是否有效。
media_pipeline_start()
函数通过调用此操作来验证所有链接。可选。has_pad_interdep
返回实体的两个 pad 是否相互依赖。如果两个 pad 相互依赖,则它们是同一管道的一部分,启用其中一个 pad 意味着另一个 pad 将变为“锁定”状态,并且不允许配置更改。保证 pad0 和 pad1 不会同时是 sink 或 source。永远不要直接调用 .has_pad_interdep() 操作,始终使用 media_entity_has_pad_interdep()。可选:如果未实现该操作,则所有 pad 将被视为相互依赖。
描述
注意
这些回调函数在持有 struct media_device.graph_mutex
互斥锁的情况下被调用。
-
enum media_entity_type¶
媒体实体类型
常量
MEDIA_ENTITY_TYPE_BASE
实体未嵌入在另一个子系统结构中。
MEDIA_ENTITY_TYPE_VIDEO_DEVICE
实体嵌入在
struct video_device
实例中。MEDIA_ENTITY_TYPE_V4L2_SUBDEV
实体嵌入在
struct v4l2_subdev
实例中。
描述
媒体实体对象通常不直接实例化,而是媒体实体结构由其他子系统特定的结构继承(通过嵌入)。媒体实体类型标识实现媒体实体实例的子类结构的类型。
这允许媒体实体的运行时类型识别和安全地转换为正确的对象类型。例如,嵌入在 v4l2_subdev 结构实例中的媒体实体结构实例将具有类型 MEDIA_ENTITY_TYPE_V4L2_SUBDEV
,并且可以使用 container_of() 宏安全地转换为 v4l2_subdev
结构。
-
struct media_entity¶
媒体实体图对象。
定义:
struct media_entity {
struct media_gobj graph_obj;
const char *name;
enum media_entity_type obj_type;
u32 function;
unsigned long flags;
u16 num_pads;
u16 num_links;
u16 num_backlinks;
int internal_idx;
struct media_pad *pads;
struct list_head links;
const struct media_entity_operations *ops;
int use_count;
union {
struct {
u32 major;
u32 minor;
} dev;
} info;
};
成员
graph_obj
包含媒体对象公共数据的嵌入式结构。
name
实体名称。
obj_type
实现 media_entity 的对象的类型。
function
实体主要功能,如 include/uapi/linux/media.h 中所定义(查找
MEDIA_ENT_F_*
)flags
实体标志,如 include/uapi/linux/media.h 中所定义(查找
MEDIA_ENT_FL_*
)num_pads
sink 和 source pad 的数量。
num_links
链接总数,包括前向和反向,已启用和已禁用。
num_backlinks
反向链接数
internal_idx
唯一的内部实体特定编号。如果实体被注销或再次注册,则编号将被重用。
垫
Pads 数组,其大小由 num_pads 定义。
链接
数据链接列表。
ops
实体操作。
use_count
实体的使用计数。
info
包含 devnode 信息的联合体。仅为了向后兼容而保留。
info.dev
包含设备主设备号和次设备号信息。
info.dev.major
设备节点主设备号(如果设备是 devnode)。
info.dev.minor
设备节点次设备号(如果设备是 devnode)。
描述
注意
use_count 引用计数绝不能为负数,但故意使用有符号整数:一个简单的 WARN_ON(<0)
检查可用于检测使其变为负数的引用计数错误。
-
media_entity_for_each_pad¶
media_entity_for_each_pad (entity, iter)
迭代实体中的所有 pad
参数
实体
pad 所属的实体
iter
迭代器 pad
描述
迭代媒体实体中的所有 pad。
-
struct media_interface¶
媒体接口图对象。
定义:
struct media_interface {
struct media_gobj graph_obj;
struct list_head links;
u32 type;
u32 flags;
};
成员
graph_obj
嵌入式图对象
链接
指向图实体的链接列表
type
接口类型,如 include/uapi/linux/media.h 中所定义(查找
MEDIA_INTF_T_*
)flags
接口标志,如 include/uapi/linux/media.h 中所定义(查找
MEDIA_INTF_FL_*
)
描述
注意
目前,没有为 media_interface
定义任何标志。
-
struct media_intf_devnode¶
通过设备节点的媒体接口。
定义:
struct media_intf_devnode {
struct media_interface intf;
u32 major;
u32 minor;
};
成员
intf
嵌入式接口对象
major
设备节点的主设备号
minor
设备节点的次设备号
-
u32 media_entity_id(struct media_entity *entity)¶
返回媒体实体图对象 ID
参数
struct media_entity *entity
指向
media_entity
的指针
-
enum media_gobj_type media_type(struct media_gobj *gobj)¶
返回媒体对象类型
参数
struct media_gobj *gobj
指向 struct
media_gobj
图对象的指针
-
u32 media_id(struct media_gobj *gobj)¶
返回媒体对象 ID
参数
struct media_gobj *gobj
指向 struct
media_gobj
图对象的指针
-
u32 media_gobj_gen_id(enum media_gobj_type type, u64 local_id)¶
在对象 ID 上封装类型和 ID
参数
enum media_gobj_type type
对象类型,如 enum
media_gobj_type
中所定义。u64 local_id
下一个 ID,来自 struct
media_device.id
。
-
bool is_media_entity_v4l2_video_device(struct media_entity *entity)¶
检查实体是否为 video_device
参数
struct media_entity *entity
指向实体的指针
返回
如果实体是 video_device 对象的实例,并且可以使用 container_of() 宏安全地转换为 struct video_device
,则为 true
,否则为 false
。
-
bool is_media_entity_v4l2_subdev(struct media_entity *entity)¶
检查实体是否为 v4l2_subdev
参数
struct media_entity *entity
指向实体的指针
返回
如果实体是 v4l2_subdev
对象的实例,并且可以使用 container_of() 宏安全地转换为 struct v4l2_subdev
,则为 true
,否则为 false
。
-
int media_entity_enum_init(struct media_entity_enum *ent_enum, struct media_device *mdev)¶
初始化实体枚举
参数
struct media_entity_enum *ent_enum
要初始化的实体枚举
struct media_device *mdev
相关的媒体设备
返回
成功时为零,否则为负错误代码。
-
void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)¶
释放实体枚举的资源
参数
struct media_entity_enum *ent_enum
要释放的实体枚举
-
void media_entity_enum_zero(struct media_entity_enum *ent_enum)¶
清除整个枚举
参数
struct media_entity_enum *ent_enum
要清除的实体枚举
-
void media_entity_enum_set(struct media_entity_enum *ent_enum, struct media_entity *entity)¶
在枚举中标记单个实体
参数
struct media_entity_enum *ent_enum
实体枚举
struct media_entity *entity
要标记的实体
-
void media_entity_enum_clear(struct media_entity_enum *ent_enum, struct media_entity *entity)¶
在枚举中取消标记单个实体
参数
struct media_entity_enum *ent_enum
实体枚举
struct media_entity *entity
要取消标记的实体
-
bool media_entity_enum_test(struct media_entity_enum *ent_enum, struct media_entity *entity)¶
测试实体是否被标记
参数
struct media_entity_enum *ent_enum
实体枚举
struct media_entity *entity
要测试的实体
描述
如果实体被标记,则返回 true
。
-
bool media_entity_enum_test_and_set(struct media_entity_enum *ent_enum, struct media_entity *entity)¶
测试实体是否被标记,并标记它
参数
struct media_entity_enum *ent_enum
实体枚举
struct media_entity *entity
要测试的实体
描述
如果实体被标记,则返回 true
,并在执行此操作之前标记它。
-
bool media_entity_enum_empty(struct media_entity_enum *ent_enum)¶
测试整个枚举是否为空
参数
struct media_entity_enum *ent_enum
实体枚举
返回
如果实体为空,则返回 true
。
-
bool media_entity_enum_intersects(struct media_entity_enum *ent_enum1, struct media_entity_enum *ent_enum2)¶
测试两个枚举是否相交
参数
struct media_entity_enum *ent_enum1
第一个实体枚举
struct media_entity_enum *ent_enum2
第二个实体枚举
返回
如果实体枚举 ent_enum1 和 ent_enum2 相交,则返回 true
,否则返回 false
。
-
gobj_to_entity¶
gobj_to_entity (gobj)
从包含在 gobj 中的
media_entity
返回 struct 指针。
参数
gobj
指向 struct
media_gobj
图对象的指针
-
gobj_to_pad¶
gobj_to_pad (gobj)
从包含在 gobj 中的
media_pad
返回 struct 指针。
参数
gobj
指向 struct
media_gobj
图对象的指针
-
gobj_to_link¶
gobj_to_link (gobj)
从包含在 gobj 中的
media_link
返回 struct 指针。
参数
gobj
指向 struct
media_gobj
图对象的指针
-
gobj_to_intf¶
gobj_to_intf (gobj)
从包含在 gobj 中的
media_interface
返回 struct 指针。
参数
gobj
指向 struct
media_gobj
图对象的指针
-
intf_to_devnode¶
intf_to_devnode (intf)
从包含在 intf 中的
struct media_intf_devnode
返回 struct 指针。
参数
intf
指向 struct
media_intf_devnode
的指针
-
void media_gobj_create(struct media_device *mdev, enum media_gobj_type type, struct media_gobj *gobj)¶
初始化图对象
参数
struct media_device *mdev
指向包含该对象的
media_device
的指针enum media_gobj_type type
对象的类型
struct media_gobj *gobj
指向 struct
media_gobj
图对象的指针
描述
此例程初始化媒体图对象内的嵌入式 struct media_gobj
。如果使用 media_*_create
函数调用,则会自动调用它。但是,如果对象(实体、链接、pad、接口)嵌入在其他某个对象上,则应在媒体控制器注册对象之前调用此函数。
-
void media_gobj_destroy(struct media_gobj *gobj)¶
停止在媒体设备上使用图对象
参数
struct media_gobj *gobj
指向 struct
media_gobj
图对象的指针
描述
所有例程(如 media_device_unregister()
)都应该调用此函数来移除/销毁媒体图对象。
-
int media_entity_pads_init(struct media_entity *entity, u16 num_pads, struct media_pad *pads)¶
初始化实体 pad
参数
struct media_entity *entity
pad 所属的实体
u16 num_pads
sink 和 source pad 的总数
struct media_pad *pads
num_pads pad 的数组。
描述
pad 数组由实体驱动程序管理,并传递给 media_entity_pads_init()
,其指针将存储在 media_entity
结构中。
如果不需要 pad,驱动程序可以直接使用 0 填充 media_entity->num_pads
,使用 NULL
填充 media_entity->pads
,或者调用此函数来执行相同的操作。
由于 pad 的数量是预先知道的,因此 pad 数组不是动态分配的,而是由实体驱动程序管理的。大多数驱动程序会将 pad 数组嵌入到特定于驱动程序的结构中,从而避免动态分配。
驱动程序必须在调用 media_entity_pads_init()
之前设置 pads 数组中每个 pad 的方向。该函数将初始化其他 pad 字段。
-
void media_entity_cleanup(struct media_entity *entity)¶
释放与实体关联的资源
参数
struct media_entity *entity
pad 所属的实体
描述
此函数必须在注销实体后的清理阶段调用(目前,它不执行任何操作)。
对已清零但尚未通过 media_entity_pad_init() 初始化的 media_entity 调用 media_entity_cleanup()
是有效的,并且是一个空操作。
-
int media_get_pad_index(struct media_entity *entity, u32 pad_type, enum media_pad_signal_type sig_type)¶
从实体检索 pad 索引
参数
struct media_entity *entity
pad 所属的实体
u32 pad_type
pad 的类型,即 MEDIA_PAD_FL_* pad 类型之一
enum media_pad_signal_type sig_type
要搜索的 pad 的信号类型
描述
此辅助函数在实体内找到第一个满足 is_sink 和 sig_type 条件的 pad 索引。
成功时,返回 pad 编号。如果未找到 pad 或媒体实体为 NULL 指针,则返回 -EINVAL。
-
int media_create_pad_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags)¶
在两个实体之间创建链接。
参数
struct media_entity *source
指向源 pad 的
media_entity
的指针。u16 source_pad
pad 数组中源 pad 的编号
struct media_entity *sink
指向接收端 pad 的
media_entity
的指针。u16 sink_pad
pad 在 pads 数组中的编号。
u32 flags
链接标志,定义在 include/uapi/linux/media.h 中 (查找
MEDIA_LNK_FL_*
)
描述
flags 的有效值
MEDIA_LNK_FL_ENABLED
表示链接已启用,可用于传输媒体数据。当两个或多个链接指向同一个接收端 pad 时,一次只能启用其中一个链接。
MEDIA_LNK_FL_IMMUTABLE
表示链接的启用状态无法在运行时修改。如果设置了
MEDIA_LNK_FL_IMMUTABLE
,则还必须设置MEDIA_LNK_FL_ENABLED
,因为不可变的链接始终处于启用状态。
注意
在调用此函数之前,应事先为两端调用 media_entity_pads_init()
和 media_device_register_entity()
。
-
int media_create_pad_links(const struct media_device *mdev, const u32 source_function, struct media_entity *source, const u16 source_pad, const u32 sink_function, struct media_entity *sink, const u16 sink_pad, u32 flags, const bool allow_both_undefined)¶
在两个实体之间创建链接。
参数
const struct media_device *mdev
指向包含该对象的 media_device 的指针
const u32 source_function
源实体的功能。仅当 source 为 NULL 时使用。
struct media_entity *source
指向源 pad 的
media_entity
的指针。如果为 NULL,它将使用所有与 sink_function 匹配的实体。const u16 source_pad
pad 数组中源 pad 的编号
const u32 sink_function
接收端实体的功能。仅当 sink 为 NULL 时使用。
struct media_entity *sink
指向接收端 pad 的
media_entity
的指针。如果为 NULL,它将使用所有与 sink_function 匹配的实体。const u16 sink_pad
pad 在 pads 数组中的编号。
u32 flags
链接标志,定义在 include/uapi/linux/media.h 中。
const bool allow_both_undefined
如果
true
,则 source 和 sink 都可以为 NULL。在这种情况下,它将在所有与 source_function 匹配的实体和所有与 sink_function 匹配的实体之间创建一个交叉开关。如果false
,如果 source 和 sink 都为 NULL,它将返回 0 并且不创建任何链接。
描述
flags 的有效值
MEDIA_LNK_FL_ENABLED
标志表示链接已启用,可以用于传输媒体数据。如果创建了多个链接并且此标志作为参数传递,则只有第一个创建的链接才具有此标志。
MEDIA_LNK_FL_IMMUTABLE
标志表示链接的启用状态无法在运行时修改。如果设置了
MEDIA_LNK_FL_IMMUTABLE
,则还必须设置MEDIA_LNK_FL_ENABLED
,因为不可变的链接始终处于启用状态。
某些设备通常具有多个相同类型的源和/或接收端实体,这些实体应链接在一起。虽然 media_create_pad_link()
逐个创建链接,但此函数旨在允许 1:n、n:1 甚至交叉开关 (n:n) 链接。
注意
在调用此函数之前,应事先为要链接的实体调用 media_entity_pads_init()
和 media_device_register_entity()
。
-
void media_entity_remove_links(struct media_entity *entity)¶
删除与实体关联的所有链接
参数
struct media_entity *entity
指向
media_entity
的指针
描述
注意
当实体通过 media_device_register_entity()
取消注册时,会自动调用此函数。
-
int __media_entity_setup_link(struct media_link *link, u32 flags)¶
配置媒体链接,无需锁定
参数
struct media_link *link
正在配置的链接
u32 flags
链接配置标志
描述
链接设置的大部分由通过链接连接的两个实体处理。此函数通知两个实体链接配置更改。
如果链接是不可变的,或者当前配置和新配置相同,则立即返回。
用户应持有 link->source->parent->mutex。否则,应使用 media_entity_setup_link()
。
-
int media_entity_setup_link(struct media_link *link, u32 flags)¶
在运行时更改链接标志属性
参数
struct media_link *link
指向
media_link
的指针u32 flags
请求的新链接标志
描述
唯一可配置的属性是 MEDIA_LNK_FL_ENABLED
链接标志,用于启用/禁用链接。标有 MEDIA_LNK_FL_IMMUTABLE
链接标志的链接无法启用或禁用。
启用或禁用链接时,媒体框架会按顺序为链接的源和接收端的两个实体调用 link_setup 操作。如果第二个 link_setup 调用失败,则会在第一个实体上进行另一个 link_setup 调用,以恢复原始链接标志。
通过将 media_device.link_notify
指针设置为回调函数,可以通知媒体设备驱动程序链接设置操作。如果提供,则将在启用之前和禁用链接之后调用通知回调。
如果任何实体的链接是非不可变的,则实体驱动程序必须实现 link_setup 操作。该操作必须配置硬件或存储配置信息以供以后应用。
链接配置不得对其他链接产生任何副作用。如果在接收端 pad 启用的链接阻止在同一 pad 启用另一个链接,则 link_setup 操作必须返回 -EBUSY
,并且不能隐式禁用第一个启用的链接。
注意
链接的标志的有效值与 media_create_pad_link()
上描述的相同,用于 pad 到 pad 链接,或者与 media_create_intf_link()
上描述的相同,用于接口到实体链接。
-
struct media_link *media_entity_find_link(struct media_pad *source, struct media_pad *sink)¶
查找两个 pad 之间的链接
参数
struct media_pad *source
源 pad
struct media_pad *sink
接收端 pad
返回
返回指向两个实体之间链接的指针。如果不存在此类链接,则返回 NULL
。
参数
const struct media_pad *pad
链接本地端的 pad
描述
通过迭代源于或终止于该 pad 的所有链接来搜索连接到给定 pad 的远程 pad,直到找到启用的链接。
返回
返回指向第一个找到的启用链接的远程端 pad 的指针,如果未找到任何启用链接,则返回 NULL
。
参数
const struct media_pad *pad
pad
描述
搜索并通过启用链接返回连接到 pad 的远程 pad。如果找到多个(或没有)远程 pad,则返回错误。
唯一性约束使此辅助函数适用于一次在给定 pad 上支持单个活动源的实体。
-ENOTUNIQ - 启用了多个链接
-ENOLINK - 未找到连接的 pad
返回
指向远程 pad 的指针,如果发生错误,则指向以下错误指针之一
-
struct media_pad *media_entity_remote_pad_unique(const struct media_entity *entity, unsigned int type)¶
查找连接到实体的远程 pad
参数
const struct media_entity *entity
实体
unsigned int type
要查找的 pad 类型 (MEDIA_PAD_FL_SINK 或 MEDIA_PAD_FL_SOURCE)
描述
搜索并通过启用链接返回连接到 entity 的 type 的远程 pad。如果多个(或没有)远程 pad 符合这些条件,则返回错误。
唯一性约束使此辅助函数适用于一次支持单个活动源或接收端的实体。
-ENOTUNIQ - 启用了多个链接
-ENOLINK - 未找到连接的 pad
返回
指向远程 pad 的指针,如果发生错误,则指向以下错误指针之一
-
struct media_pad *media_entity_remote_source_pad_unique(const struct media_entity *entity)¶
查找连接到实体的远程源 pad
参数
const struct media_entity *entity
实体
描述
搜索并通过启用链接返回连接到 entity 的远程源 pad。如果多个(或没有)远程 pad 符合这些条件,则返回错误。
唯一性约束使此辅助函数适用于一次支持单个活动源的实体。
-ENOTUNIQ - 启用了多个链接
-ENOLINK - 未找到连接的 pad
返回
指向远程 pad 的指针,如果发生错误,则指向以下错误指针之一
参数
const struct media_pad *pad
pad
返回
如果 pad 是使用 media_pipeline_start()
函数启动的管道的一部分,则为 True,否则为 false。
-
bool media_entity_is_streaming(const struct media_entity *entity)¶
测试实体是否是流式传输管道的一部分
参数
const struct media_entity *entity
实体
返回
如果实体是使用 media_pipeline_start()
函数启动的管道的一部分,则为 True,否则为 false。
-
struct media_pipeline *media_entity_pipeline(struct media_entity *entity)¶
获取实体所属的媒体管道
参数
struct media_entity *entity
实体
描述
已弃用:请改用 media_pad_pipeline()
。
此函数返回在使用 media_pipeline_start()
构建管道时与实体关联的媒体管道。指针在调用 media_pipeline_stop()
之前仍然有效。
通常,实体可以是多个管道的一部分,当携带多个流时(在不同的 pad 上或在使用多路复用流的同一 pad 上)。此函数仅用于不支持多个管道的实体。
返回
实体所属的 media_pipeline,如果实体不属于任何管道,则为 NULL。
-
struct media_pipeline *media_pad_pipeline(struct media_pad *pad)¶
获取 pad 所属的媒体管道
参数
struct media_pad *pad
pad
描述
此函数返回在使用 media_pipeline_start()
构建管道时与 pad 关联的媒体管道。指针在调用 media_pipeline_stop()
之前仍然有效。
返回
pad 所属的 media_pipeline,如果 pad 不属于任何管道,则为 NULL。
-
int media_entity_get_fwnode_pad(struct media_entity *entity, const struct fwnode_handle *fwnode, unsigned long direction_flags)¶
从 fwnode 获取 pad 编号
参数
struct media_entity *entity
实体
const struct fwnode_handle *fwnode
指向应用于查找 pad 的 fwnode_handle 的指针
unsigned long direction_flags
pad 的预期方向,定义在 include/uapi/linux/media.h 中 (查找
MEDIA_PAD_FL_*
)
描述
此函数可用于从 fwnode 解析媒体 pad 编号。这对于使用更复杂的媒体 pad 映射的设备非常有用。
如果实体未实现 get_fwnode_pad() 操作,则此函数会在实体中搜索与 direction_flags 匹配的第一个 pad。
返回
成功时返回 pad 编号,或返回负错误代码。
-
int media_graph_walk_init(struct media_graph *graph, struct media_device *mdev)¶
分配图形遍历使用的资源。
参数
struct media_graph *graph
将用于遍历图形的媒体图形结构
struct media_device *mdev
指向包含该对象的
media_device
的指针
描述
此函数已弃用,请改用 media_pipeline_for_each_pad()
。
调用者需要在图形遍历期间持有 media_device graph_mutex,直到释放图形状态。
成功时返回零,否则返回负错误代码。
-
void media_graph_walk_cleanup(struct media_graph *graph)¶
释放图形遍历使用的资源。
-
void media_graph_walk_start(struct media_graph *graph, struct media_entity *entity)¶
从给定实体开始遍历媒体图形
参数
struct media_graph *graph
将用于遍历图形的媒体图形结构
struct media_entity *entity
起始实体
描述
此函数已弃用,请改用 media_pipeline_for_each_pad()
。
在使用此函数之前,必须使用 media_graph_walk_init()
分配用于遍历图形的资源。此函数初始化图形遍历结构,以遍历从给定实体开始的实体图形。遍历结构不得在图形遍历期间由调用者修改。在图形遍历之后,必须使用 media_graph_walk_cleanup()
释放资源。
-
struct media_entity *media_graph_walk_next(struct media_graph *graph)¶
获取图形中的下一个实体
参数
struct media_graph *graph
媒体图形结构
描述
此函数已弃用,请改用 media_pipeline_for_each_pad()
。
执行给定媒体实体图形的深度优先遍历。
图形结构必须先前已通过调用 media_graph_walk_start()
初始化。
返回
返回图形中的下一个实体,如果已遍历整个图形,则返回 NULL
。
-
int media_pipeline_start(struct media_pad *origin, struct media_pipeline *pipe)¶
将管道标记为流式传输
参数
struct media_pad *origin
起始 pad
struct media_pipeline *pipe
要分配给管道中所有 pad 的媒体管道。
描述
将通过启用链接(直接或间接)连接到 pad origin 的所有 pad 标记为流式传输。给定的管道对象分配给管道中的每个 pad,并存储在 media_pad 管道字段中。
可以嵌套对此函数的调用,在这种情况下,需要相同数量的 media_pipeline_stop()
调用来停止流式传输。对于所有嵌套的 media_pipeline_start()
调用,管道指针必须相同。
-
int __media_pipeline_start(struct media_pad *origin, struct media_pipeline *pipe)¶
将管道标记为流式传输
参数
struct media_pad *origin
起始 pad
struct media_pipeline *pipe
要分配给管道中所有 pad 的媒体管道。
描述
.. note:: 这是 media_pipeline_start()
的非锁定版本
参数
struct media_pad *pad
起始 pad
描述
将通过启用的链接(直接或间接)连接到给定 pad 的所有 pad 标记为非流式传输。media_pad pipe 字段重置为 NULL
。
如果多次调用 media_pipeline_start()
,则需要相同次数的函数调用才能将流水线标记为非流式传输。
-
media_pipeline_for_each_pad¶
media_pipeline_for_each_pad (pipe, iter, pad)
迭代媒体流水线中的所有 pad
参数
pipe
流水线
iter
pad
迭代器 pad
描述
迭代媒体流水线中的所有 pad。这仅在流水线已使用 media_pipeline_start()
构建并在使用 media_pipeline_stop()
销毁之前有效。
-
int media_pipeline_entity_iter_init(struct media_pipeline *pipe, struct media_pipeline_entity_iter *iter)¶
初始化流水线实体迭代器
参数
struct media_pipeline *pipe
流水线
struct media_pipeline_entity_iter *iter
迭代器
描述
必须调用此函数以初始化迭代器,然后才能在 media_pipeline_for_each_entity()
循环中使用它。迭代器必须在循环后(包括从循环中断的代码路径)通过调用 media_pipeline_entity_iter_cleanup 来销毁。
相同的迭代器可以在多个连续循环中使用,而无需销毁和重新初始化。
返回
成功时为 0,否则为负错误代码。
-
void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter)¶
销毁流水线实体迭代器
参数
struct media_pipeline_entity_iter *iter
迭代器
描述
必须调用此函数以销毁使用 media_pipeline_entity_iter_init()
初始化的迭代器。
-
media_pipeline_for_each_entity¶
media_pipeline_for_each_entity (pipe, iter, entity)
迭代媒体流水线中的所有实体
参数
pipe
流水线
iter
实体
迭代器实体
描述
迭代媒体流水线中的所有实体。这仅在流水线已使用 media_pipeline_start()
构建并在使用 media_pipeline_stop()
销毁之前有效。迭代器必须在使用迭代之前使用 media_pipeline_entity_iter_init()
初始化,并在之后使用 media_pipeline_entity_iter_cleanup()
销毁(包括从循环中断的代码路径)。
参数
struct media_pad *pad
起始 pad
描述
media_pipeline_alloc_start()
类似于 media_pipeline_start()
,但该函数不是在给定流水线上工作,而是在 pad 已经是流水线的一部分时使用现有流水线,或者分配一个新的流水线。
对 media_pipeline_alloc_start()
的调用必须与 media_pipeline_stop()
匹配。
-
struct media_intf_devnode *media_devnode_create(struct media_device *mdev, u32 type, u32 flags, u32 major, u32 minor)¶
创建并初始化设备节点接口
参数
struct media_device *mdev
指向 struct
media_device
的指针u32 type
接口类型,如 include/uapi/linux/media.h 中给出的(搜索
MEDIA_INTF_T_*
宏)。u32 flags
接口标志,如 include/uapi/linux/media.h 中定义的(搜索
MEDIA_INTF_FL_*
)u32 major
设备节点主编号。
u32 minor
设备节点次编号。
返回
- 如果成功,则返回指向新分配的
描述
注意
目前,没有为 media_interface
定义任何标志。
-
void media_devnode_remove(struct media_intf_devnode *devnode)¶
移除设备节点接口
-
struct media_link *media_create_intf_link(struct media_entity *entity, struct media_interface *intf, u32 flags)¶
创建实体和接口之间的链接
参数
struct media_entity *entity
指向
media_entity
的指针struct media_interface *intf
指向
media_interface
的指针u32 flags
链接标志,定义在 include/uapi/linux/media.h 中 (查找
MEDIA_LNK_FL_*
)
描述
flags 的有效值
MEDIA_LNK_FL_ENABLED
表示接口已连接到实体硬件。这是接口的默认值。如果硬件由于使用当前正在控制硬件的其他接口而繁忙,则可以禁用接口。
一个典型的例子是混合电视设备,该设备在给定的时间只能处理一种类型的流。因此,当数字电视正在流式传输时,V4L2 接口将不会启用,因为此类设备也无法流式传输模拟电视或广播。
注意
在调用此函数之前,应该为接口调用 media_devnode_create()
,并且应该为将成为链接一部分的接口调用 media_device_register_entity()
。
-
void __media_remove_intf_link(struct media_link *link)¶
删除单个接口链接
-
void media_remove_intf_link(struct media_link *link)¶
删除单个接口链接
-
void __media_remove_intf_links(struct media_interface *intf)¶
移除与接口关联的所有链接
-
void media_remove_intf_links(struct media_interface *intf)¶
移除与接口关联的所有链接
参数
struct media_interface *intf
指向
media_interface
的指针
描述
注意
通过
media_device_register_entity()
取消注册实体以及通过media_devnode_remove()
取消注册实体时,会自动调用此函数。首选使用此方法,而不是
__media_remove_intf_links()
。
-
media_entity_call¶
media_entity_call (entity, operation, args...)
在实体上调用
struct media_entity_operations
操作
参数
实体
将在其中调用 operation 的实体
操作
操作类型。应为结构
media_entity_operations
的成员名称。args...
可变参数
描述
此辅助函数将检查 operation 是否不为 NULL
。在这种情况下,它将发出对 operation(entity, args) 的调用。
-
struct media_link *media_create_ancillary_link(struct media_entity *primary, struct media_entity *ancillary)¶
在
media_entity
的两个实例之间创建辅助链接
参数
struct media_entity *primary
指向主要
media_entity
的指针struct media_entity *ancillary
指向辅助
media_entity
的指针
描述
在两个实体之间创建辅助链接,表明它们表示形成单个逻辑单元的两个连接的硬件。一个典型的例子是连接到其支持的传感器的相机镜头控制器。
该函数为新链接设置 MEDIA_LNK_FL_ENABLED 和 MEDIA_LNK_FL_IMMUTABLE。
-
struct media_link *__media_entity_next_link(struct media_entity *entity, struct media_link *link, unsigned long link_type)¶
遍历
media_entity
的链接
参数
struct media_entity *entity
指向
media_entity
的指针struct media_link *link
指向
media_link
的指针以保存迭代值unsigned long link_type
MEDIA_LNK_FL_LINK_TYPE 标志之一
描述
返回与特定链接类型匹配的实体的下一个链接。这允许遍历实体的链接,同时保证所有返回的链接都是给定类型。
-
for_each_media_entity_data_link¶
for_each_media_entity_data_link (entity, link)
遍历实体的数据链接
-
enum media_request_state¶
媒体请求状态
常量
MEDIA_REQUEST_STATE_IDLE
空闲
MEDIA_REQUEST_STATE_VALIDATING
正在验证请求,不允许状态更改
MEDIA_REQUEST_STATE_QUEUED
已排队
MEDIA_REQUEST_STATE_COMPLETE
已完成,请求已完成
MEDIA_REQUEST_STATE_CLEANING
正在清理,请求正在重新初始化
MEDIA_REQUEST_STATE_UPDATING
正在更新请求,即正在添加、修改或移除请求对象
NR_OF_MEDIA_REQUEST_STATE
媒体请求状态的数量,在内部用于完整性检查
-
struct media_request¶
媒体设备请求
定义:
struct media_request {
struct media_device *mdev;
struct kref kref;
char debug_str[TASK_COMM_LEN + 11];
enum media_request_state state;
unsigned int updating_count;
unsigned int access_count;
struct list_head objects;
unsigned int num_incomplete_objects;
wait_queue_head_t poll_wait;
spinlock_t lock;
};
成员
mdev
此请求所属的媒体设备
kref
引用计数
debug_str
调试消息的前缀(进程名称:fd)
state
请求的状态
updating_count
计算正在进行的请求更新的数量
access_count
计算正在进行的请求访问的数量
objects
struct media_request_object 请求对象的列表
num_incomplete_objects
请求中未完成对象的数量
poll_wait
poll 的等待队列
lock
序列化对此结构的访问
-
int media_request_lock_for_access(struct media_request *req)¶
锁定请求以访问其对象
参数
struct media_request *req
媒体请求
描述
在访问已完成的请求之前使用。在访问期间必须持有对请求的引用。这通常通过文件句柄自动进行。完成后使用 media_request_unlock_for_access。
-
void media_request_unlock_for_access(struct media_request *req)¶
解锁先前为访问而锁定的请求
参数
struct media_request *req
媒体请求
描述
解锁先前使用 media_request_lock_for_access 锁定的请求。
-
int media_request_lock_for_update(struct media_request *req)¶
锁定请求以更新其对象
参数
struct media_request *req
媒体请求
描述
在更新请求之前使用,即在其中添加、修改或移除请求对象。在更新期间必须持有对请求的引用。这通常通过文件句柄自动进行。完成后使用 media_request_unlock_for_update。
-
void media_request_unlock_for_update(struct media_request *req)¶
解锁先前为更新而锁定的请求
参数
struct media_request *req
媒体请求
描述
解锁先前使用 media_request_lock_for_update 锁定的请求。
-
void media_request_get(struct media_request *req)¶
获取媒体请求
参数
struct media_request *req
媒体请求
描述
获取媒体请求。
-
void media_request_put(struct media_request *req)¶
放置媒体请求
参数
struct media_request *req
媒体请求
描述
放置媒体请求。当引用计数达到 0 时,将释放媒体请求。
-
struct media_request *media_request_get_by_fd(struct media_device *mdev, int request_fd)¶
按 fd 获取媒体请求
参数
struct media_device *mdev
此请求所属的媒体设备
int request_fd
请求的文件描述符
描述
获取由媒体设备拥有的 request_fd 表示的请求。
如果此驱动程序不支持请求,则返回 -EBADR 错误指针。如果未找到请求,则返回 -EINVAL。如果找到请求,则返回指向请求的指针:调用者在使用完请求后必须调用 media_request_put。
-
int media_request_alloc(struct media_device *mdev, int *alloc_fd)¶
分配媒体请求
参数
struct media_device *mdev
此请求所属的媒体设备
int *alloc_fd
将请求的文件描述符存储在此 int 中
描述
分配媒体请求并将 fd 放入 alloc_fd 中。
-
struct media_request_object_ops¶
媒体请求对象操作
定义:
struct media_request_object_ops {
int (*prepare)(struct media_request_object *object);
void (*unprepare)(struct media_request_object *object);
void (*queue)(struct media_request_object *object);
void (*unbind)(struct media_request_object *object);
void (*release)(struct media_request_object *object);
};
成员
prepare
验证并准备请求对象,可选。
unprepare
取消准备请求对象,可选。
queue
将请求对象排队,可选。
unbind
取消绑定请求对象,可选。
release
Release
-
struct media_request_object¶
属于媒体请求的不透明对象
定义:
struct media_request_object {
const struct media_request_object_ops *ops;
void *priv;
struct media_request *req;
struct list_head list;
struct kref kref;
bool completed;
};
成员
ops
对象的运算
priv
对象的私有指针
req
此对象所属的请求(可以为 NULL)
列表
struct media_request 的对象列表条目
kref
对象的引用计数,在释放 req->lock 之前获取
completed
如果为 true,则此对象已完成。
描述
与请求相关的对象。此结构始终嵌入在另一个包含此请求对象的实际数据的结构中。
-
void media_request_object_get(struct media_request_object *obj)¶
获取媒体请求对象
参数
struct media_request_object *obj
对象
描述
获取媒体请求对象。
-
void media_request_object_put(struct media_request_object *obj)¶
放置媒体请求对象
参数
struct media_request_object *obj
对象
描述
放置媒体请求对象。一旦所有引用都消失,对象的内存就会被释放。
-
struct media_request_object *media_request_object_find(struct media_request *req, const struct media_request_object_ops *ops, void *priv)¶
在请求中查找对象
参数
struct media_request *req
媒体请求
const struct media_request_object_ops *ops
查找具有此 ops 值的对象
void *priv
查找具有此私有值的对象
描述
ops 和 priv 都必须为非 NULL。
返回对象指针;如果未找到,则返回 NULL。调用者必须在使用完对象后调用 media_request_object_put()
。
由于此函数需要遍历对象列表,因此它会获取 req->lock 自旋锁以确保安全。
-
void media_request_object_init(struct media_request_object *obj)¶
初始化媒体请求对象
参数
struct media_request_object *obj
对象
描述
初始化媒体请求对象。一旦对象没有引用,将使用 ops 的 release 回调释放该对象(此函数将引用初始化为 1)。
-
int media_request_object_bind(struct media_request *req, const struct media_request_object_ops *ops, void *priv, bool is_buffer, struct media_request_object *obj)¶
将媒体请求对象绑定到请求
参数
struct media_request *req
媒体请求
const struct media_request_object_ops *ops
此对象的对象操作
void *priv
与此对象关联的驱动程序特定的priv指针
bool is_buffer
如果对象是缓冲区对象,则设置为true。
struct media_request_object *obj
对象
描述
将此对象绑定到请求,并设置对象的操作和priv值,以便以后可以使用 media_request_object_find()
找到它。
每个绑定的对象都必须在某个时间点被内核解绑定或完成,否则请求将永远不会完成。当请求被释放时,所有已完成的对象将由请求核心代码解绑定。
缓冲区对象将被添加到请求的对象列表的末尾,非缓冲区对象将被添加到列表的前面。这确保了所有缓冲区对象都在列表的末尾,并且它们所依赖的所有非缓冲区对象都首先被处理。
-
void media_request_object_unbind(struct media_request_object *obj)¶
解绑定媒体请求对象
参数
struct media_request_object *obj
对象
描述
从请求中解绑定媒体请求对象。
-
void media_request_object_complete(struct media_request_object *obj)¶
将媒体请求对象标记为已完成
参数
struct media_request_object *obj
对象
描述
将媒体请求对象标记为已完成。只有绑定的对象才能完成。
-
struct media_device *media_device_usb_allocate(struct usb_device *udev, const char *module_name, struct module *owner)¶
分配并返回结构体
media
设备
参数
struct usb_device *udev
结构体
usb_device
指针const char *module_name
应该用
KBUILD_MODNAME
填充struct module *owner
驱动程序的结构体模块指针
THIS_MODULE
。对于内置驱动程序,THIS_MODULE
为 null。即使THIS_MODULE
为 null,它也是安全的。
描述
当多个驱动程序共享 usb_device 和媒体设备时,应调用此接口来分配媒体设备。此接口分配 media_device
结构并调用 media_device_usb_init()
来初始化它。
-
void media_device_delete(struct media_device *mdev, const char *module_name, struct module *owner)¶
释放媒体设备。调用
kref_put()
。
参数
struct media_device *mdev
结构体
media_device
指针const char *module_name
应该用
KBUILD_MODNAME
填充struct module *owner
驱动程序的结构体模块指针
THIS_MODULE
。对于内置驱动程序,THIS_MODULE
为 null。即使THIS_MODULE
为 null,它也是安全的。
描述
应该调用此接口来放置 Media Device Instance kref。