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
表示焊盘支持发送数据。
注意
每个 pad 必须设置 MEDIA_PAD_FL_SINK
或 MEDIA_PAD_FL_SOURCE
中的一个且仅一个。
5.1.6. 链接¶
链接由 struct media_link
实例表示,该实例在 include/media/media-entity.h
中定义。链接有两种类型
1. pad 到 pad 的链接:
通过其 PAD 将两个实体关联起来。每个实体都有一个列表,指向源自或针对其任何 pad 的所有链接。因此,给定的链接会被存储两次,一次在源实体中,一次在目标实体中。
驱动程序通过调用:media_create_pad_link()
创建 pad 到 pad 的链接,并通过 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。
要遍历属于媒体设备的所有实体,驱动程序可以使用在 include/media/media-device.h
中定义的 media_device_for_each_entity 宏。
struct media_entity *entity;
media_device_for_each_entity(entity, mdev) {
// entity will point to each entity in turn
...
}
可以使用辅助函数来查找两个给定 pad 之间的链接,或者通过启用的链接连接到另一个 pad 的 pad(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. 管道和媒体流¶
媒体流是从一个或多个源设备(如传感器)发出,并通过媒体实体 pad 流向最终接收器的像素或元数据流。该流可以在路由上被设备修改(例如,缩放或像素格式转换),或者可以分成多个分支,或者可以合并多个分支。
媒体管道是一组相互依赖的媒体流。这种相互依赖关系可能是由硬件(例如,如果第一个流已启用,则无法更改第二个流的配置)或由驱动程序由于软件设计引起的。最常见的是,媒体管道由单个不分支的流组成。
在开始流式传输时,驱动程序必须通知管道中的所有实体,以防止在流式传输期间通过调用 media_pipeline_start()
修改链接状态。
该函数会将管道中所有作为流一部分的 pad 标记为流式传输。
由 pipe 参数指向的 struct media_pipeline
实例将存储在管道中的每个 pad 中。驱动程序应将 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
标志。
如果需要在流式传输实体上禁用其他操作(例如,更改实体配置参数),驱动程序可以显式检查 media_entity stream_count 字段以查找实体是否正在流式传输。此操作必须在持有 media_device graph_mutex 的情况下完成。
5.1.11. 链接验证¶
对于管道中具有接收器 pad 的任何实体,media_pipeline_start()
执行链接验证。为此目的使用 media_entity
.link_validate()
回调。在 link_validate()
回调中,实体驱动程序应检查连接实体的源 pad 的属性及其自身的接收器 pad 是否匹配。匹配的实际含义取决于实体的类型(最终取决于硬件的属性)。
子系统应通过提供子系统特定的辅助函数来促进链接验证,以便轻松访问常用信息,并最终提供使用特定于驱动程序的回调的方法。
5.1.12. 管道遍历¶
使用 media_pipeline_start()
构建管道后,驱动程序可以使用 :c:macro:`media_pipeline_for_each_entity` 和 :c:macro:`media_pipeline_for_each_pad` 宏遍历管道中的实体或 pad。遍历 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
作为查找的键进行分配。
共享媒体设备应保持注册状态,直到最后一个驱动程序取消注册它为止。此外,当所有引用都被释放时,应释放媒体设备。每个驱动程序在探测期间获取对媒体设备的引用,此时它会分配媒体设备。如果媒体设备已经分配,则 allocate API 会增加 refcount 并返回现有的媒体设备。驱动程序在调用 media_device_delete()
时,会在其断开连接例程中放回引用。
媒体设备从 kref put 处理程序中注销并清理,以确保媒体设备在最后一个驱动程序注销媒体设备之前保持注册状态。
驱动程序用法
驱动程序应使用适当的媒体核心例程来管理共享媒体设备的生命周期,处理以下两种状态:1. 分配 -> 注册 -> 删除 2. 获取已注册设备的引用 -> 删除
调用 media_device_delete()
例程以确保正确处理共享媒体设备的删除。
驱动程序探测: 调用 media_device_usb_allocate()
来分配或获取引用。如果媒体设备节点未注册,则调用 media_device_register()
。
驱动程序断开连接: 调用 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);
};
成员
list
链表头
notify_data
调用回调的输入数据
notify
回调函数指针
描述
当新实体在媒体设备上注册时,驱动程序可以注册一个回调来执行操作。此处理程序旨在创建现有实体之间的链接,而不应创建实体并注册它们。
-
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
媒体设备节点
model
设备型号名称
driver_name
可选的设备驱动程序名称。如果未设置,则对
MEDIA_IOC_DEVICE_INFO
的调用将返回dev->driver->name
。例如,USB 驱动程序需要此项,否则它们都将显示为驱动程序名称为“usb”。serial
设备序列号(可选)
bus_info
唯一且稳定的设备位置标识符
hw_revision
硬件设备修订版本
topology_version
用于存储图形拓扑版本的单调计数器。每次拓扑更改时都应递增。
id
上次注册的图形对象上使用的唯一 ID
entity_internal_idx
图形遍历算法使用的唯一内部实体 ID
entity_internal_idx_max
已分配的内部实体索引
entities
已注册实体列表
interfaces
已注册接口列表
pads
已注册焊盘列表
links
已注册链接列表
entity_notify
已注册的 entity_notify 回调列表
graph_mutex
保护对
struct media_device
数据的访问pm_count_walk
用于电源状态遍历的图形遍历。使用 graph_mutex 串行访问。
source_priv
用于启用/禁用源处理程序的驱动程序私有数据
enable_source
启用源处理程序函数指针
disable_source
禁用源处理程序函数指针
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
指向结构
media_device
的指针
描述
此函数在注册媒体设备之前初始化它。媒体设备初始化和注册分为两个函数,以避免竞争条件,并在媒体图完成之前使媒体设备可供用户空间使用。
因此,驱动程序需要先初始化媒体设备,在媒体设备中注册任何实体,创建焊盘到焊盘的链接,然后最后通过调用 media_device_register()
作为最后一步来注册媒体设备。
调用者负责在注册之前初始化媒体设备。必须设置以下字段
dev 必须指向父设备
model 必须填充设备型号名称
如果 bus_info 字段以“0”开头,则 media_device_init()
为 PCI 和平台设备设置 bus_info 字段。
-
void media_device_cleanup(struct media_device *mdev)¶
清理媒体设备元素
-
int __media_device_register(struct media_device *mdev, struct module *owner)¶
注册媒体设备元素
参数
struct media_device *mdev
指向结构
media_device
的指针struct module *owner
应填充
THIS_MODULE
描述
用户应改为调用 media_device_register()
宏。
调用者负责在注册前初始化 media_device
结构体。 media_device
的以下字段必须设置:
media_device.model
必须使用以 NULL 结尾的 UTF-8 字符串填充设备型号名称。设备/型号修订版本不得存储在此字段中。
以下字段是可选的:
media_device.serial
是一个唯一的序列号,存储为以 NULL 结尾的 ASCII 字符串。该字段足够大,可以存储文本形式的 GUID。如果硬件不提供唯一的序列号,则此字段必须留空。
media_device.bus_info
表示设备在系统中的位置,以 NULL 结尾的 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
指向结构
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
指向结构
media_device
的指针struct media_entity *entity
指向要注册的
media_entity
结构体的指针
描述
实体由唯一的正整数 ID 标识。媒体控制器框架将自动生成此类 ID。不能保证 ID 是连续的,并且 ID 号在较新的内核版本上可能会更改。因此,驱动程序和用户空间都不应硬编码 ID 号来引用实体,而应在需要时使用框架来查找 ID。
在调用 media_device_register_entity()
之前,应初始化 media_entity 的名称、类型和标志字段。嵌入到更高层标准结构中的实体可以由更高层框架设置其中的一些字段。
如果设备有焊盘,则应在此函数之前调用 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
结构体的指针
描述
当调用此函数时,与实体关联的所有链接和所有 PAD 都会自动从 media_device 中注销。
注销一个实体不会更改其他实体的 ID,并且先前使用的 ID 永远不会被重用于新注册的实体。
当注销媒体设备时,其所有实体都会自动注销。然后不需要手动注销实体。
注意
如果需要,驱动程序必须显式释放 media_entity 实例本身。
-
void media_device_register_entity_notify(struct media_device *mdev, struct media_entity_notify *nptr)¶
注册一个 media_entity_notify 回调
参数
struct media_device *mdev
媒体设备
struct media_entity_notify *nptr
media_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
media_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
指向结构
media_device
的指针struct pci_dev *pci_dev
指向 struct pci_dev 的指针
const char *name
媒体设备名称。如果
NULL
,该例程将使用 pci_name() 宏给出的 pci 设备的默认名称。
-
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
指向结构
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
指向结构
media_device
的指针udev
指向
struct usb_device
的指针name
媒体设备名称。如果为
NULL
,该例程将使用 USB 产品名称(如果可用)。
描述
此宏调用 media_device_usb_init()
,并将 media_device_usb_init()
的 driver_name 参数填充为 KBUILD_MODNAME
。
参数
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 位的内核上处理 32 位用户空间对 ioctl() 系统调用的函数的指针。
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
指向结构
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
要准备取消注册的设备节点
描述
这会清除传递的设备注册位。以后的 open 调用将会遇到错误。应在 media_devnode_unregister()
之前调用,以避免取消注册和设备文件 open 调用之间的竞争。
如果设备节点从未注册或已经取消注册,则可以安全地调用此函数。
-
void media_devnode_unregister(struct media_devnode *devnode)¶
取消注册媒体设备节点
参数
struct media_devnode *devnode
要取消注册的设备节点
描述
这将取消注册传递的设备。以后的 open 调用将会遇到错误。
-
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
标识一个媒体端口
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 组成list
存储在每个类型 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
管道所属的媒体设备
pads
media_pipeline_pad 的列表
start_count
媒体管道启动-停止计数
-
struct media_pipeline_pad¶
媒体管道的一部分端口
定义:
struct media_pipeline_pad {
struct list_head list;
struct media_pipeline *pipe;
struct media_pad *pad;
};
成员
list
媒体端口列表中的条目
pipe
端口所属的媒体管道
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
包含媒体对象公共数据的嵌入式结构体
list
与拥有该链接的实体或接口关联的链表。
{unnamed_union}
匿名
gobj0
联合体的一部分。用于获取链接的第一个图对象的指针。
source
联合体的一部分。仅当第一个对象 (gobj0) 是端口时使用。在这种情况下,它表示源端口。
intf
联合体的一部分。仅当第一个对象 (gobj0) 是接口时使用。
{unnamed_union}
匿名
gobj1
联合体的一部分。用于获取链接的第二个图对象的指针。
sink
联合体的一部分。仅当第二个对象 (gobj1) 是端口时使用。在这种情况下,它表示接收器端口。
entity
联合体的一部分。仅当第二个对象 (gobj1) 是实体时使用。
reverse
指向端口到端口链接的反向链接的指针。
flags
链接标志,如 uapi/media.h 中定义 (MEDIA_LNK_FL_*)
is_backlink
指示链接是否为反向链接。
-
enum media_pad_signal_type¶
媒体端口内的信号类型
常量
PAD_SIGNAL_DEFAULT
默认信号。当所有输入或所有输出都由端口号唯一标识时使用此信号。
PAD_SIGNAL_ANALOG
端口包含模拟信号。它可以是射频、中频、基带信号或子载波。调谐器输入、中频锁相环解调器、复合信号和 S-Video 信号应使用它。
PAD_SIGNAL_DV
包含数字视频信号,它可以是从模拟电视视频源采样的比特流。在这种情况下,它通常包含 VBI 数据。
PAD_SIGNAL_AUDIO
包含来自音频子载波的中频模拟信号或音频比特流。中频信号由调谐器提供,并由音频 AM/FM 解码器使用。比特流音频由音频解码器提供。
-
struct media_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
包含媒体对象公共数据的嵌入式结构体
entity
此端口所属的实体
index
实体端口数组中的端口索引,从 0 到 n 编号
num_links
连接到此端口的链接数
sig_type
媒体端口内的信号类型
flags
端口标志,如 include/uapi/linux/media.h 中定义(查找
MEDIA_PAD_FL_*
)pipe
此端口所属的管道。使用
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 端点返回端口号,如果出错则返回负值。此操作可用于将 fwnode 映射到媒体端口号。可选。
link_setup
通知实体链接更改。该操作可能会返回错误,在这种情况下,链接设置将被取消。可选。
link_validate
从实体角度返回链接是否有效。
media_pipeline_start()
函数通过调用此操作来验证所有链接。可选。has_pad_interdep
返回实体的两个端口是否相互依赖。如果两个端口相互依赖,则它们是同一管道的一部分,并且启用其中一个端口意味着另一个端口将变为“锁定”状态,并且不允许配置更改。保证 pad0 和 pad1 不会同时是接收器或源。永远不要直接调用 .has_pad_interdep() 操作,始终使用 media_entity_has_pad_interdep()。可选:如果未实现该操作,则所有端口都将被视为相互依赖。
描述
注意
这些回调函数在持有结构体 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
接收器和源焊盘的数量。
num_links
链接总数,包括前向和后向,启用和禁用。
num_backlinks
后向链接的数量
internal_idx
一个唯一的内部实体特定编号。如果实体注销或再次注册,则会重复使用这些编号。
pads
焊盘数组,其大小由 num_pads 定义。
links
数据链接列表。
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)
迭代实体中的所有焊盘
参数
entity
焊盘所属的实体
iter
迭代器焊盘
描述
迭代媒体实体中的所有焊盘。
-
struct media_interface¶
一个媒体接口图对象。
定义:
struct media_interface {
struct media_gobj graph_obj;
struct list_head links;
u32 type;
u32 flags;
};
成员
graph_obj
嵌入式图对象
links
指向图实体的链接列表
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
指向
media_gobj
图结构的指针
-
u32 media_id(struct media_gobj *gobj)¶
返回媒体对象 ID
参数
struct media_gobj *gobj
指向
media_gobj
图结构的指针
-
u32 media_gobj_gen_id(enum media_gobj_type type, u64 local_id)¶
在对象 ID 上封装类型和 ID
参数
enum media_gobj_type type
在枚举
media_gobj_type
中定义的对象类型。u64 local_id
来自结构体
media_device.id
的下一个 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() 宏安全地转换为结构体 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
结构体指针。
参数
gobj
指向
media_gobj
图结构的指针
-
gobj_to_pad¶
gobj_to_pad (gobj)
从其中包含的 gobj 返回
media_pad
结构体指针。
参数
gobj
指向
media_gobj
图结构的指针
-
gobj_to_link¶
gobj_to_link (gobj)
从其中包含的 gobj 返回
media_link
结构体指针。
参数
gobj
指向
media_gobj
图结构的指针
-
gobj_to_intf¶
gobj_to_intf (gobj)
从其中包含的 gobj 返回
media_interface
结构体指针。
参数
gobj
指向
media_gobj
图结构的指针
-
intf_to_devnode¶
intf_to_devnode (intf)
从其中包含的 intf 返回
struct media_intf_devnode
指针。
参数
intf
指向
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
指向
media_gobj
图结构的指针
描述
此例程初始化媒体图对象内部嵌入的 media_gobj
结构体。如果使用 media_*_create
函数调用,则会自动调用此例程。但是,如果该对象(实体、链接、pad、接口)嵌入在其他对象上,则应在媒体控制器上注册该对象之前调用此函数。
-
void media_gobj_destroy(struct media_gobj *gobj)¶
停止在媒体设备上使用图对象
参数
struct media_gobj *gobj
指向
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 的数组。
描述
pads 数组由实体驱动程序管理,并传递给 media_entity_pads_init()
,该函数的指针将存储在 media_entity
结构中。
如果不需要 pad,驱动程序可以直接将 media_entity->num_pads
填充为 0,将 media_entity->pads
填充为 NULL
,或者调用此函数来完成相同的操作。
由于 pad 的数量是预先知道的,因此 pads 数组不是动态分配的,而是由实体驱动程序管理的。大多数驱动程序会将 pads 数组嵌入到驱动程序特定的结构中,从而避免动态分配。
驱动程序必须在调用 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 或 media 实体是指向 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
pads 数组中源 pad 的编号
struct media_entity *sink
指向接收器 pad 的
media_entity
的指针。u16 sink_pad
pads 数组中接收器 pad 的编号。
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
pads 数组中源 pad 的编号
const u32 sink_function
接收器实体的功能。仅当 sink 为 NULL 时使用。
struct media_entity *sink
指向接收器 pad 的
media_entity
的指针。如果为 NULL,则将使用所有与 sink_function 匹配的实体。const u16 sink_pad
pads 数组中接收器 pad 的编号。
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)¶
查找连接到实体的远程源衬垫
参数
const struct media_entity *entity
实体
描述
搜索并通过启用的链接返回连接到 entity 的远程源衬垫。 如果多个(或没有)远程衬垫符合这些条件,则返回错误。
唯一性约束使此辅助函数适用于一次仅支持单个活动源的实体。
-ENOTUNIQ - 启用了多个链接
-ENOLINK - 未找到连接的 pad
返回值:
指向远程 pad 的指针,或者如果发生错误,则指向以下错误指针之一
参数
const struct media_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()
之前保持有效。
通常,当携带多个流(在不同的衬垫上,或使用复用流在同一衬垫上)时,实体可以是多个管道的一部分。 此函数仅用于不支持多个管道的实体。
返回值:
实体所属的 media_pipeline,如果实体不属于任何管道,则为 NULL。
-
struct media_pipeline *media_pad_pipeline(struct media_pad *pad)¶
获取衬垫所属的媒体管道
参数
struct media_pad *pad
pad
描述
当使用 media_pipeline_start()
构建管道时,此函数返回与衬垫关联的媒体管道。 该指针在调用 media_pipeline_stop()
之前保持有效。
返回值:
衬垫所属的 media_pipeline,如果衬垫不属于任何管道,则为 NULL。
-
int media_entity_get_fwnode_pad(struct media_entity *entity, const struct fwnode_handle *fwnode, unsigned long direction_flags)¶
从 fwnode 获取衬垫编号
参数
struct media_entity *entity
实体
const struct fwnode_handle *fwnode
指向应该用于查找衬垫的 fwnode_handle 的指针
unsigned long direction_flags
衬垫的预期方向,如 include/uapi/linux/media.h 中所定义(搜索
MEDIA_PAD_FL_*
)
描述
此函数可用于从 fwnode 解析媒体衬垫编号。 这对于使用更复杂的媒体衬垫映射的设备很有用。
如果实体未实现 get_fwnode_pad() 操作,则此函数将在实体中搜索第一个与 direction_flags 匹配的衬垫。
返回值:
成功时返回衬垫编号,否则返回负错误代码。
-
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 的 pipe 字段中。
可以嵌套调用此函数,在这种情况下,需要相同数量的 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。这仅在管道已通过 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
entity
迭代器实体
描述
迭代媒体管道中的所有实体。这仅在管道已通过 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
指向结构
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
操作
参数
entity
将在其上调用 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
轮询的等待队列
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
释放请求对象,必需。
-
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)
list
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
查找具有此 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
对象
描述
初始化一个媒体请求对象。一旦对象没有引用(此函数将引用初始化为 1),将使用 ops 的释放回调来释放该对象。
-
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
对象
描述
将此对象绑定到请求,并设置该对象的 ops 和 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
为空。即使THIS_MODULE
为空也是安全的。
描述
当多个驱动程序共享 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
为空。即使THIS_MODULE
为空也是安全的。
描述
应该调用此接口来释放媒体设备实例的 kref。