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_subdevvideo_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_SINKMEDIA_PAD_FL_SOURCE 中的一个且只有一个。

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_entityuse_count 字段由媒体驱动程序拥有,实体驱动程序不得触摸该字段。对该字段的访问必须受到 media_devicegraph_mutex 锁的保护。

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_entitypipe 字段将在上次嵌套的停止调用时重置为 NULL

如果链接的任一端是流式传输实体,则默认情况下链接配置将失败并显示 -EBUSY。可以在流式传输时修改的链接必须使用 MEDIA_LNK_FL_DYNAMIC 标志进行标记。

如果在流式传输实体上需要禁止其他操作(例如更改实体配置参数),则驱动程序可以显式检查媒体实体 stream_count 字段,以确定实体是否正在流式传输。此操作必须在 media_device graph_mutex 持有的情况下完成。

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_allocreq_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_sourcedisable_source 处理程序所需的信息设置 source_priv。调用者应持有 graph_mutex 以访问和调用 enable_sourcedisable_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() 宏格式化修订版。

注意

  1. 成功注册后,将创建一个名为 media[0-9]+ 的字符设备。设备主编号和次编号是动态的。型号名称作为 sysfs 属性导出。

  2. 注销尚未注册的媒体设备是安全的。

返回

成功时返回零,否则返回负错误代码。

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)

注销媒体设备元素

参数

struct media_device *mdev

指向 struct media_device 的指针

描述

在未注册(但已初始化)的媒体设备上调用此函数是安全的。

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.padmedia_entity.num_pads 置零。

实体具有描述实体功能和状态的标志

MEDIA_ENT_FL_DEFAULT

指示给定类型的默认实体。这可以用于报告默认音频和视频设备或默认摄像头传感器。

注意

驱动程序应在调用此函数之前设置实体功能。请注意,驱动程序不应使用值 MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWNMEDIA_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 参数。

void media_set_bus_info(char *bus_info, size_t bus_info_size, struct device *dev)

设置 bus_info 字段

参数

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

要注销的设备节点

描述

这将注销传递的设备。将来的打开调用将遇到错误。

应在 media_devnode_unregister_prepare() 之后调用

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。

参数

struct media_devnode *devnode

指向 media_devnode 结构的指针。

注意

如果 mdev 为 NULL,它也会返回 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_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_enum1ent_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)

从包含在 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_sinksig_type 条件的 pad 索引。

成功时,返回 pad 编号。如果未找到 pad 或媒体实体为 NULL 指针,则返回 -EINVAL。

在两个实体之间创建链接。

参数

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()

在两个实体之间创建链接。

参数

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,则 sourcesink 都可以为 NULL。在这种情况下,它将在所有与 source_function 匹配的实体和所有与 sink_function 匹配的实体之间创建一个交叉开关。如果 false,如果 sourcesink 都为 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()

删除与实体关联的所有链接

参数

struct media_entity *entity

指向 media_entity 的指针

描述

注意

当实体通过 media_device_register_entity() 取消注册时,会自动调用此函数。

配置媒体链接,无需锁定

参数

struct media_link *link

正在配置的链接

u32 flags

链接配置标志

描述

链接设置的大部分由通过链接连接的两个实体处理。此函数通知两个实体链接配置更改。

如果链接是不可变的,或者当前配置和新配置相同,则立即返回。

用户应持有 link->source->parent->mutex。否则,应使用 media_entity_setup_link()

在运行时更改链接标志属性

参数

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() 上描述的相同,用于接口到实体链接。

查找两个 pad 之间的链接

参数

struct media_pad *source

源 pad

struct media_pad *sink

接收端 pad

返回

返回指向两个实体之间链接的指针。如果不存在此类链接,则返回 NULL

struct media_pad *media_pad_remote_pad_first(const struct media_pad *pad)

查找链接远端处的第一个 pad

参数

const struct media_pad *pad

链接本地端的 pad

描述

通过迭代源于或终止于该 pad 的所有链接来搜索连接到给定 pad 的远程 pad,直到找到启用的链接。

返回

返回指向第一个找到的启用链接的远程端 pad 的指针,如果未找到任何启用链接,则返回 NULL

struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad)

查找连接到 pad 的远程 pad

参数

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)

描述

搜索并通过启用链接返回连接到 entitytype 的远程 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 的指针,如果发生错误,则指向以下错误指针之一

bool media_pad_is_streaming(const struct media_pad *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)

释放图形遍历使用的资源。

参数

struct media_graph *graph

将用于遍历图形的媒体图形结构

描述

此函数已弃用,请改用 media_pipeline_for_each_pad()

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() 的非锁定版本

void media_pipeline_stop(struct media_pad *pad)

将流水线标记为非流式传输

参数

struct media_pad *pad

起始 pad

描述

将通过启用的链接(直接或间接)连接到给定 pad 的所有 pad 标记为非流式传输。media_pad pipe 字段重置为 NULL

如果多次调用 media_pipeline_start(),则需要相同次数的函数调用才能将流水线标记为非流式传输。

void __media_pipeline_stop(struct media_pad *pad)

将流水线标记为非流式传输

参数

struct media_pad *pad

起始 pad

描述

注意

这是 media_pipeline_stop() 的非锁定版本

media_pipeline_for_each_pad

media_pipeline_for_each_pad (pipe, iter, pad)

迭代媒体流水线中的所有 pad

参数

pipe

流水线

iter

迭代器 (struct media_pipeline_pad_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

迭代器 (struct media_pipeline_entity_iter)

实体

迭代器实体

描述

迭代媒体流水线中的所有实体。这仅在流水线已使用 media_pipeline_start() 构建并在使用 media_pipeline_stop() 销毁之前有效。迭代器必须在使用迭代之前使用 media_pipeline_entity_iter_init() 初始化,并在之后使用 media_pipeline_entity_iter_cleanup() 销毁(包括从循环中断的代码路径)。

int media_pipeline_alloc_start(struct media_pad *pad)

将管道标记为流式传输

参数

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_intf_devnode 指针。

描述

注意

目前,没有为 media_interface 定义任何标志。

void media_devnode_remove(struct media_intf_devnode *devnode)

移除设备节点接口

参数

struct media_intf_devnode *devnode

指向要释放的 media_intf_devnode 的指针。

描述

移除设备节点接口时,所有指向它的链接都会自动移除。

创建实体和接口之间的链接

参数

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()

删除单个接口链接

参数

struct media_link *link

指向 media_link 的指针。

描述

注意

这是 media_remove_intf_link() 的未锁定版本

删除单个接口链接

参数

struct media_link *link

指向 media_link 的指针。

描述

注意

首选使用此方法,而不是 __media_remove_intf_link()

移除与接口关联的所有链接

参数

struct media_interface *intf

指向 media_interface 的指针

描述

注意

这是 media_remove_intf_links() 的未锁定版本。

移除与接口关联的所有链接

参数

struct media_interface *intf

指向 media_interface 的指针

描述

注意

  1. 通过 media_device_register_entity() 取消注册实体以及通过 media_devnode_remove() 取消注册实体时,会自动调用此函数。

  2. 首选使用此方法,而不是 __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) 的调用。

media_entity 的两个实例之间创建辅助链接

参数

struct media_entity *primary

指向主要 media_entity 的指针

struct media_entity *ancillary

指向辅助 media_entity 的指针

描述

在两个实体之间创建辅助链接,表明它们表示形成单个逻辑单元的两个连接的硬件。一个典型的例子是连接到其支持的传感器的相机镜头控制器。

该函数为新链接设置 MEDIA_LNK_FL_ENABLED 和 MEDIA_LNK_FL_IMMUTABLE。

遍历 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 (entity, link)

遍历实体的数据链接

参数

实体

指向 media_entity 的指针

链接

指向 media_link 的指针以保存迭代值

描述

遍历 media_entity 的数据链接

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

查找具有此私有值的对象

描述

opspriv 都必须为非 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。