2.4. 视频设备的内部表示

/dev 目录中的实际设备节点是使用 video_device 结构体 (v4l2-dev.h) 创建的。此结构体可以动态分配或嵌入到更大的结构体中。

要动态分配它,请使用 video_device_alloc()

struct video_device *vdev = video_device_alloc();

if (vdev == NULL)
        return -ENOMEM;

vdev->release = video_device_release;

如果将其嵌入到更大的结构体中,则必须将 release() 回调设置为您自己的函数

struct video_device *vdev = &my_vdev->vdev;

vdev->release = my_vdev_release;

必须设置 release() 回调,并且当视频设备的最后一个用户退出时会调用它。

默认的 video_device_release() 回调目前只是调用 kfree 来释放已分配的内存。

还有一个 video_device_release_empty() 函数,它不执行任何操作(为空),如果该结构体是嵌入式的,并且在释放时无需执行任何操作,则应使用该函数。

您还应该设置 video_device 的以下字段

  • video_device->v4l2_dev:必须设置为 v4l2_device 父设备。

  • video_device->name:设置为具有描述性且唯一的内容。

  • video_device->vfl_dir:对于捕获设备,请将其设置为 VFL_DIR_RXVFL_DIR_RX 的值为 0,因此通常已经是默认值),对于输出设备,请设置为 VFL_DIR_TX,对于 mem2mem(编解码器)设备,请设置为 VFL_DIR_M2M

  • video_device->fops:设置为 v4l2_file_operations 结构体。

  • video_device->ioctl_ops:如果您使用 v4l2_ioctl_ops 来简化 ioctl 维护(强烈建议使用此方法,并且将来可能会强制使用!),则将其设置为您的 v4l2_ioctl_ops 结构体。video_device->vfl_type 和 video_device->vfl_dir 字段用于禁用不匹配类型/dir 组合的操作。例如,VBI 操作对非 VBI 节点禁用,输出操作对捕获设备禁用。这使得为 vbi 和视频节点提供一个 v4l2_ioctl_ops 结构体成为可能。

  • video_device->lock:如果您想在驱动程序中执行所有锁定,则将其保留为 NULL。否则,您可以提供指向 mutex_lock 结构体的指针,并且在调用 video_device->unlocked_ioctl 文件操作之前,核心会获取此锁并在之后释放。有关更多详细信息,请参见下一节。

  • video_device->queue:指向与此设备节点关联的 struct vb2_queue 的指针。如果 queue 不是 NULL,并且 queue->lock 不是 NULL,则 queue->lock 用于排队 ioctl(VIDIOC_REQBUFSCREATE_BUFSQBUFDQBUFQUERYBUFPREPARE_BUFSTREAMONSTREAMOFF),而不是上面的锁。这样,vb2 排队框架不必等待其他 ioctl。此队列指针还被 vb2 辅助函数用于检查排队所有权(即,是否允许调用它的文件句柄执行该操作)。

  • video_device->prio:跟踪优先级。用于实现 VIDIOC_G_PRIORITYVIDIOC_S_PRIORITY。如果将其保留为 NULL,则它将使用 struct v4l2_prio_state 中的 v4l2_device。如果您想为每个(组)设备节点拥有单独的优先级状态,则可以将其指向您自己的 v4l2_prio_state 结构体。

  • video_device->dev_parent:仅当 v4l2_device 注册时使用 NULL 作为父 device 结构体时才设置此项。这种情况仅发生在单个硬件设备具有多个 PCI 设备,它们都共享相同的 v4l2_device 核心时。

    cx88 驱动程序是这种情况的一个示例:一个核心 v4l2_device 结构体,但它被原始视频 PCI 设备 (cx8800) 和 MPEG PCI 设备 (cx8802) 使用。由于 v4l2_device 不能同时与两个 PCI 设备关联,因此在没有父设备的情况下进行设置。但是,当初始化 struct video_device 时,您确实知道要使用哪个父 PCI 设备,因此您可以将 dev_device 设置为正确的 PCI 设备。

如果您使用 v4l2_ioctl_ops,则应将 video_device->unlocked_ioctl 设置为 video_ioctl2() 在您的 v4l2_file_operations 结构体中。

在某些情况下,您希望告诉核心您在 v4l2_ioctl_ops 中指定的函数应被忽略。您可以通过在调用 video_register_device() 之前调用此函数来标记此类 ioctl

如果根据外部因素(例如,正在使用的卡)您想关闭 v4l2_ioctl_ops 中的某些功能,而无需创建新的结构体,则通常需要这样做。

v4l2_file_operations 结构体是 file_operations 的子集。主要区别在于 inode 参数被省略,因为它从未使用过。

如果需要与媒体框架集成,则必须通过调用 media_entity_pads_init() 初始化嵌入在 video_device 结构体(实体字段)中的 media_entity 结构体

struct media_pad *pad = &my_vdev->pad;
int err;

err = media_entity_pads_init(&vdev->entity, 1, pad);

之前必须已初始化 pads 数组。无需手动设置 struct media_entity 类型和名称字段。

当视频设备打开/关闭时,将自动获取/释放对该实体的引用。

2.4.1. ioctls 和锁定

V4L 核心提供可选的锁定服务。主要服务是 struct video_device 中的 lock 字段,它是指向互斥量的指针。如果您设置此指针,则 unlocked_ioctl 将使用它来序列化所有 ioctl。

如果您正在使用 videobuf2 框架,则可以设置第二个锁:video_device->queue->lock。如果设置,则此锁将用于代替 video_device->lock 来序列化所有排队 ioctl(有关这些 ioctl 的完整列表,请参见上一节)。

为排队 ioctl 使用不同锁的优点是,对于某些驱动程序(尤其是 USB 驱动程序),某些命令(例如设置控件)可能需要很长时间,因此您想为缓冲区排队 ioctl 使用单独的锁。这样,您的 VIDIOC_DQBUF 不会因为驱动程序忙于更改例如网络摄像头的曝光而停顿。

当然,您始终可以通过将两个锁指针都保留为 NULL 来自己完成所有锁定。

对于 videobuf2,如果适用,您将需要实现 wait_prepare()wait_finish() 回调来解锁/锁定。如果您使用 queue->lock 指针,则可以使用辅助函数 vb2_ops_wait_prepare()vb2_ops_wait_finish()

热插拔断开的实现也应在调用 v4l2_device_disconnect 之前从 video_device 获取锁。如果您还使用 video_device->queue->lock,则必须首先锁定 video_device->queue->lock,然后锁定 video_device->lock。这样,您可以确保在调用 v4l2_device_disconnect() 时没有 ioctl 正在运行。

2.4.2. 视频设备注册

接下来,使用 video_register_device() 注册视频设备。这将为您创建字符设备。

err = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (err) {
        video_device_release(vdev); /* or kfree(my_vdev); */
        return err;
}

如果 v4l2_device 父设备具有非 NULL mdev 字段,则视频设备实体将自动在媒体设备中注册。

注册哪个设备取决于类型参数。存在以下类型

vfl_devnode_type

设备名称

用法

VFL_TYPE_VIDEO

/dev/videoX

用于视频输入/输出设备

VFL_TYPE_VBI

/dev/vbiX

用于垂直消隐数据(即隐藏字幕、图文电视)

VFL_TYPE_RADIO

/dev/radioX

用于无线电调谐器

VFL_TYPE_SUBDEV

/dev/v4l-subdevX

用于 V4L2 子设备

VFL_TYPE_SDR

/dev/swradioX

用于软件定义无线电 (SDR) 调谐器

VFL_TYPE_TOUCH

/dev/v4l-touchX

用于触摸传感器

最后一个参数使您可以一定程度地控制使用的设备节点编号(即 videoX 中的 X)。通常,您会传递 -1 以便 v4l2 框架选择第一个可用编号。但有时用户想要选择特定的节点编号。驱动程序通常允许用户通过驱动程序模块选项选择特定的设备节点编号。然后将该编号传递给此函数,并且 video_register_device 将尝试选择该设备节点编号。如果该编号已被使用,则将选择下一个可用的设备节点编号,并且它会向内核日志发送警告。

另一个用例是,如果驱动程序创建了许多设备。在这种情况下,将不同的视频设备放置在单独的范围内可能很有用。例如,视频捕获设备从 0 开始,视频输出设备从 16 开始。因此,您可以使用最后一个参数指定最小设备节点编号,并且 v4l2 框架将尝试选择等于或高于您传递的第一个可用编号。如果失败,它将只选择第一个可用编号。

由于在这种情况下,您不关心有关无法选择指定设备节点编号的警告,因此您可以调用函数 video_register_device_no_warn() 代替。

每当创建设备节点时,还会为您创建一些属性。如果您查看 /sys/class/video4linux,您会看到这些设备。进入例如 video0,您将看到 'name'、'dev_debug' 和 'index' 属性。'name' 属性是 video_device 结构体的 'name' 字段。'dev_debug' 属性可用于启用核心调试。有关此方面的更多详细信息,请参见下一节。

'index' 属性是设备节点的索引:对于每次调用 video_register_device(),索引仅增加 1。您注册的第一个视频设备节点始终以索引 0 开始。

用户可以设置利用 index 属性的 udev 规则来创建奇特的设备名称(例如,用于 MPEG 视频捕获设备节点的 'mpegX')。

成功注册设备后,您可以使用以下字段

如果注册失败,则需要调用 video_device_release() 以释放已分配的 video_device 结构体,或者释放您自己的结构体(如果 video_device 嵌入其中)。如果注册失败,则永远不会调用 vdev->release() 回调,也不应尝试在注册失败时取消注册设备。

2.4.3. 视频设备调试

/sys/class/video4linux/<devX>/ 中的每个视频、vbi、无线电或 swradio 设备创建的 'dev_debug' 属性允许您启用文件操作的日志记录。

它是一个位掩码,可以设置以下位

掩码

描述

0x01

记录 ioctl 名称和错误代码。仅当同时设置了位 0x08 时,才会记录 VIDIOC_(D)QBUF ioctl。

0x02

记录 ioctl 名称参数和错误代码。仅当同时设置了位 0x08 时,才会记录 VIDIOC_(D)QBUF ioctl。

0x04

记录文件操作 open、release、read、write、mmap 和 get_unmapped_area。仅当同时设置了位 0x08 时,才会记录读写操作。

0x08

记录读写文件操作以及 VIDIOC_QBUF 和 VIDIOC_DQBUF ioctl。

0x10

记录 poll 文件操作。

0x20

记录控制操作中的错误和消息。

2.4.4. 视频设备清理

当必须删除视频设备节点时(在卸载驱动程序期间或由于 USB 设备断开连接时),应使用以下命令取消注册它们

这将从 sysfs 中删除设备节点(导致 udev 将它们从 /dev 中删除)。

video_unregister_device() 返回后,无法执行任何新的打开操作。但是,对于 USB 设备,某些应用程序可能仍然打开了其中一个设备节点。因此,在取消注册后,所有文件操作(当然,除了 release 之外)也将返回错误。

当视频设备节点的最后一个用户退出时,将调用 vdev->release() 回调,您可以在此处执行最终清理。

如果已初始化,请不要忘记清理与视频设备关联的媒体实体

media_entity_cleanup (&vdev->entity);

这可以从 release 回调中完成。

2.4.5. 辅助函数

有一些有用的辅助函数

您可以使用以下命令在 video_device 结构体中设置/获取驱动程序私有数据

请注意,您可以安全地在调用 video_register_device() 之前调用 video_set_drvdata()

还有这个函数

返回属于文件结构体的 video_device。

video_devdata() 函数将 video_get_drvdata()video_devdata() 结合在一起

您可以使用以下命令从 video_device 结构体转到 v4l2_device 结构体

struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
  • 设备节点名称

可以使用以下命令检索 video_device 节点内核名称

该名称被用户空间工具(例如 udev)用作提示。在可能的情况下,应使用该函数,而不是访问 video_device::num 和 video_device::minor 字段。

2.4.6. video_device 函数和数据结构

enum vfl_devnode_type

V4L2 设备节点的类型

常量

VFL_TYPE_VIDEO

用于视频输入/输出设备

VFL_TYPE_VBI

用于垂直消隐数据(即隐藏字幕、图文电视)

VFL_TYPE_RADIO

用于无线电调谐器

VFL_TYPE_SUBDEV

用于 V4L2 子设备

VFL_TYPE_SDR

用于软件定义无线电调谐器

VFL_TYPE_TOUCH

用于触摸传感器

VFL_TYPE_MAX

VFL 类型的数量,必须始终在枚举中排在最后

enum vfl_devnode_direction

标识 struct video_device 是否对应于接收器、发射器或内存到内存设备。

常量

VFL_DIR_RX

设备是接收器。

VFL_DIR_TX

设备是发射器。

VFL_DIR_M2M

设备是内存到内存设备。

注意

如果 enum vfl_devnode_typeVFL_TYPE_SUBDEV,则忽略。

enum v4l2_video_device_flags

struct video_device 使用的标志

常量

V4L2_FL_REGISTERED

指示 struct video_device 已注册。如果驱动程序想要阻止所有未来的设备访问,则可以清除此标志。它由 video_unregister_device 清除。

V4L2_FL_USES_V4L2_FH

指示 file->private_data 指向 struct v4l2_fh。当调用 v4l2_fh_init() 时,核心会设置此标志。所有新驱动程序都应使用它。

V4L2_FL_QUIRK_INVERTED_CROP

一些旧的 M2M 驱动程序不正确地使用了 g/s_crop/cropcap:crop 和 compose 互换了。如果设置了这个标志,那么选择目标将在 v4l2-ioctl.c 中的 g/s_crop/cropcap 函数中互换。这允许这些驱动程序正确地实现选择 API,但是旧的 crop API 仍然可以按预期工作,以保持向后兼容性。永远不要为新的驱动程序设置此标志。

V4L2_FL_SUBDEV_RO_DEVNODE

表示视频设备节点以只读模式注册。该标志仅适用于为子设备注册的设备节点,当子设备节点通过 v4l2_device_register_ro_subdev_nodes() 注册时由核心设置,并由子设备 ioctl 处理程序使用以限制对某些 ioctl 调用的访问。

struct v4l2_prio_state

存储优先级状态

定义:

struct v4l2_prio_state {
    atomic_t prios[4];
};

成员

prios

带有元素的数组,用于存储数组优先级

描述

注意

prios 数组的大小与枚举 v4l2_priority 定义的优先级类型数量匹配。

void v4l2_prio_init(struct v4l2_prio_state *global)

初始化一个 struct v4l2_prio_state

参数

struct v4l2_prio_state *global

指向 struct v4l2_prio_state 的指针

int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, enum v4l2_priority new)

更改 v4l2 文件句柄优先级

参数

struct v4l2_prio_state *global

指向设备节点的 struct v4l2_prio_state 的指针。

enum v4l2_priority *local

指向期望的优先级的指针,如枚举 v4l2_priority 定义的那样

enum v4l2_priority new

请求的优先级类型,如枚举 v4l2_priority 定义的那样。

描述

注意

此函数应仅由 V4L2 核心使用。

void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local)

为文件句柄打开实现优先级逻辑

参数

struct v4l2_prio_state *global

指向设备节点的 struct v4l2_prio_state 的指针。

enum v4l2_priority *local

指向期望的优先级的指针,如枚举 v4l2_priority 定义的那样

描述

注意

此函数应仅由 V4L2 核心使用。

void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local)

为文件句柄关闭实现优先级逻辑

参数

struct v4l2_prio_state *global

指向设备节点的 struct v4l2_prio_state 的指针。

enum v4l2_priority local

要释放的优先级,如枚举 v4l2_priority 定义的那样

描述

注意

此函数应仅由 V4L2 核心使用。

enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global)

返回最大优先级,如存储在 global 数组中的那样。

参数

struct v4l2_prio_state *global

指向设备节点的 struct v4l2_prio_state 的指针。

描述

注意

此函数应仅由 V4L2 核心使用。

int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local)

为文件句柄关闭实现优先级逻辑

参数

struct v4l2_prio_state *global

指向设备节点的 struct v4l2_prio_state 的指针。

enum v4l2_priority local

期望的优先级,如枚举 v4l2_priority local 定义的那样

描述

注意

此函数应仅由 V4L2 核心使用。

struct v4l2_file_operations

V4L2 设备使用的 fs 操作

定义:

struct v4l2_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 (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
#ifdef CONFIG_COMPAT;
    long (*compat_ioctl32) (struct file *, unsigned int, unsigned long);
#endif;
    unsigned long (*get_unmapped_area) (struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
    int (*mmap) (struct file *, struct vm_area_struct *);
    int (*open) (struct file *);
    int (*release) (struct file *);
};

成员

owner

指向 struct module 的指针

read

实现 read() 系统调用所需的操作

write

实现 write() 系统调用所需的操作

poll

实现 poll() 系统调用所需的操作

unlocked_ioctl

实现 ioctl() 系统调用所需的操作

compat_ioctl32

在内核使用 64 位指令,但用户空间使用 32 位的情况下实现 ioctl() 系统调用所需的操作。

get_unmapped_area

由 mmap() 系统调用调用,在 %!CONFIG_MMU 时使用

mmap

实现 mmap() 系统调用所需的操作

open

实现 open() 系统调用所需的操作

release

实现 release() 系统调用所需的操作

描述

注意

这些操作用于在 V4L2 驱动程序中实现 fs struct file_operations。V4L2 核心使用子系统所需的一些额外逻辑覆盖 fs ops。

struct video_device

用于创建和管理 V4L2 设备节点的结构。

定义:

struct video_device {
#if defined(CONFIG_MEDIA_CONTROLLER);
    struct media_entity entity;
    struct media_intf_devnode *intf_devnode;
    struct media_pipeline pipe;
#endif;
    const struct v4l2_file_operations *fops;
    u32 device_caps;
    struct device dev;
    struct cdev *cdev;
    struct v4l2_device *v4l2_dev;
    struct device *dev_parent;
    struct v4l2_ctrl_handler *ctrl_handler;
    struct vb2_queue *queue;
    struct v4l2_prio_state *prio;
    char name[64];
    enum vfl_devnode_type vfl_type;
    enum vfl_devnode_direction vfl_dir;
    int minor;
    u16 num;
    unsigned long flags;
    int index;
    spinlock_t fh_lock;
    struct list_head        fh_list;
    int dev_debug;
    v4l2_std_id tvnorms;
    void (*release)(struct video_device *vdev);
    const struct v4l2_ioctl_ops *ioctl_ops;
    unsigned long valid_ioctls[BITS_TO_LONGS(BASE_VIDIOC_PRIVATE)];
    struct mutex *lock;
};

成员

entity

struct media_entity

intf_devnode

指向 struct media_intf_devnode 的指针

pipe

struct media_pipeline

fops

指向视频设备的 struct v4l2_file_operations 的指针

device_caps

在 v4l2_capabilities 中使用的设备功能

dev

视频设备的 struct device

cdev

字符设备

v4l2_dev

指向 struct v4l2_device 父级的指针

dev_parent

指向 struct device 父级的指针

ctrl_handler

与此设备节点关联的控件处理程序。可以为 NULL。

queue

与此设备节点关联的 struct vb2_queue。可以为 NULL。

prio

指向带有设备优先级状态的 struct v4l2_prio_state 的指针。如果为 NULL,则将使用 v4l2_dev->prio。

name

视频设备名称

vfl_type

V4L 设备类型,如 enum vfl_devnode_type 定义的那样

vfl_dir

V4L 接收器、发射器或 m2m

minor

设备节点“次设备号”。如果注册失败,则设置为 -1

num

视频设备节点的编号

flags

视频设备标志。使用位操作来设置/清除/测试标志。包含一组 enum v4l2_video_device_flags

index

用于区分一个物理设备上的多个索引的属性

fh_lock

所有 v4l2_fhs 的锁

fh_list

struct v4l2_fh 列表

dev_debug

内部设备调试标志,不供驱动程序使用

tvnorms

支持的电视制式

release

视频设备 release() 回调

ioctl_ops

指向带有 ioctl 回调的 struct v4l2_ioctl_ops 的指针

valid_ioctls

包含此设备的有效 ioctl 的位图

lock

指向 struct mutex 序列化锁的指针

描述

注意

仅当无法从 v4l2_dev 推断出 dev_parent 时才设置。

media_entity_to_video_device

media_entity_to_video_device (__entity)

从嵌入的 struct media_entity 返回一个 struct video_device

参数

__entity

指向 struct media_entity 的指针

to_video_device

to_video_device (cd)

从嵌入的 struct device 返回一个 struct video_device

参数

cd

指向 struct device 的指针

int __video_register_device(struct video_device *vdev, enum vfl_devnode_type type, int nr, int warn_if_nr_in_use, struct module *owner)

注册 video4linux 设备

参数

struct video_device *vdev

要注册的 struct video_device

enum vfl_devnode_type type

要注册的设备类型,如 enum vfl_devnode_type 定义的那样

int nr

期望的设备节点编号:(0 == /dev/video0, 1 == /dev/video1, ..., -1 == 第一个空闲的)

int warn_if_nr_in_use

如果期望的设备节点编号已被使用,并且选择了另一个编号,则发出警告。

struct module *owner

拥有视频设备节点的模块

描述

注册代码根据请求的类型分配次设备号和设备节点编号,并将新的设备节点注册到内核。

此函数假定 struct video_device 在分配时被清零,并且不包含任何过时的数据。

如果找不到空闲的次设备号或设备节点编号,或者设备节点注册失败,则返回错误。

成功时返回 0。

注意

此函数旨在仅在 V4L2 核心中使用。驱动程序应使用 video_register_device()video_register_device_no_warn()

int video_register_device(struct video_device *vdev, enum vfl_devnode_type type, int nr)

注册 video4linux 设备

参数

struct video_device *vdev

要注册的 struct video_device

enum vfl_devnode_type type

要注册的设备类型,如 enum vfl_devnode_type 定义的那样

int nr

期望的设备节点编号:(0 == /dev/video0, 1 == /dev/video1, ..., -1 == 第一个空闲的)

描述

在内部,它调用 __video_register_device()。请参阅其文档以获取更多详细信息。

注意

如果 video_register_device 失败,则不会调用 struct video_device 结构的 release() 回调,因此调用者负责释放任何数据。通常,这意味着您应该在失败时调用 video_device_release()

int video_register_device_no_warn(struct video_device *vdev, enum vfl_devnode_type type, int nr)

注册 video4linux 设备

参数

struct video_device *vdev

要注册的 struct video_device

enum vfl_devnode_type type

要注册的设备类型,如 enum vfl_devnode_type 定义的那样

int nr

期望的设备节点编号:(0 == /dev/video0, 1 == /dev/video1, ..., -1 == 第一个空闲的)

描述

此函数与 video_register_device() 相同,只是如果期望的设备节点编号已被使用,则不会发出警告。

在内部,它调用 __video_register_device()。请参阅其文档以获取更多详细信息。

注意

如果 video_register_device 失败,则不会调用 struct video_device 结构的 release() 回调,因此调用者负责释放任何数据。通常,这意味着您应该在失败时调用 video_device_release()

void video_unregister_device(struct video_device *vdev)

注销视频设备。

参数

struct video_device *vdev

要注册的 struct video_device

描述

如果 vdev == NULL 或如果 video_is_registered() 返回 false,则不执行任何操作。

struct video_device *video_device_alloc(void)

用于分配 struct video_device 的辅助函数

参数

void

没有参数

描述

如果 -ENOMEM 则返回 NULL,如果成功,则返回 struct video_device

void video_device_release(struct video_device *vdev)

用于释放 struct video_device 的辅助函数

参数

struct video_device *vdev

指向 struct video_device 的指针

描述

也可以用于 video_device->release()。

void video_device_release_empty(struct video_device *vdev)

用于实现 video_device->release() 回调的辅助函数。

参数

struct video_device *vdev

指向 struct video_device 的指针

描述

此 release 函数不执行任何操作。

当 video_device 是一个静态全局结构时,应使用它。

注意

拥有静态 video_device 在最佳情况下也是一个可疑的构造。

void v4l2_disable_ioctl(struct video_device *vdev, unsigned int cmd)

标记给定的命令未实现。不应使用核心锁定

参数

struct video_device *vdev

指向 struct video_device 的指针

unsigned int cmd

ioctl 命令

描述

此函数允许驱动程序仅提供一个 v4l2_ioctl_ops 结构,但根据实际找到的特定卡禁用 ioctl。

注意

必须在 video_register_device 之前调用此函数。另请参阅 determine_valid_ioctls() 的注释。

void *video_get_drvdata(struct video_device *vdev)

struct video_device 获取私有数据。

参数

struct video_device *vdev

指向 struct video_device 的指针

描述

返回指向私有数据的指针

void video_set_drvdata(struct video_device *vdev, void *data)

struct video_device 设置私有数据。

参数

struct video_device *vdev

指向 struct video_device 的指针

void *data

私有数据指针

struct video_device *video_devdata(struct file *file)

struct file 获取 struct video_device

参数

struct file *file

指向 struct file 的指针

void *video_drvdata(struct file *file)

使用 struct filestruct video_device 获取私有数据。

参数

struct file *file

指向 struct file 的指针

描述

此函数结合了 video_get_drvdata()video_devdata(),因为这非常常用。

const char *video_device_node_name(struct video_device *vdev)

返回视频设备名称

参数

struct video_device *vdev

指向 struct video_device 的指针

描述

返回设备名称字符串

int video_is_registered(struct video_device *vdev)

如果 struct video_device 已注册,则返回 true。

参数

struct video_device *vdev

指向 struct video_device 的指针

struct dentry *v4l2_debugfs_root(void)

返回顶级“v4l2”debugfs 目录的 dentry

参数

void

没有参数

描述

如果此目录尚不存在,则将创建它。

int video_device_pipeline_start(struct video_device *vdev, struct media_pipeline *pipe)

将管道标记为流式传输

参数

struct video_device *vdev

启动视频设备

struct media_pipeline *pipe

要分配给管道中所有实体的媒体管道。

描述

将通过启用的链接(直接或间接)连接到给定视频设备的所有实体标记为流式传输。给定的管道对象分配给管道中的每个 pad,并存储在 media_pad pipe 字段中。

可以嵌套对此函数的调用,在这种情况下,需要相同数量的 video_device_pipeline_stop() 调用才能停止流式传输。对于 video_device_pipeline_start() 的所有嵌套调用,管道指针必须相同。

视频设备必须包含单个 pad。

这是 media_pipeline_start() 的一个便捷封装。

int __video_device_pipeline_start(struct video_device *vdev, struct media_pipeline *pipe)

将管道标记为流式传输

参数

struct video_device *vdev

启动视频设备

struct media_pipeline *pipe

要分配给管道中所有实体的媒体管道。

描述

..note:: 这是 video_device_pipeline_start() 的非锁定版本

视频设备必须包含单个 pad。

这是 __media_pipeline_start() 的一个便捷封装。

void video_device_pipeline_stop(struct video_device *vdev)

将管道标记为非流式传输

参数

struct video_device *vdev

启动视频设备

描述

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

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

视频设备必须包含单个 pad。

这是 media_pipeline_stop() 的一个便捷封装。

void __video_device_pipeline_stop(struct video_device *vdev)

将管道标记为非流式传输

参数

struct video_device *vdev

启动视频设备

描述

注意

这是 media_pipeline_stop() 的非锁定版本

视频设备必须包含单个 pad。

这是 __media_pipeline_stop() 的一个便捷封装。

int video_device_pipeline_alloc_start(struct video_device *vdev)

将管道标记为流式传输

参数

struct video_device *vdev

启动视频设备

描述

video_device_pipeline_alloc_start() 类似于 video_device_pipeline_start(),但该函数不是在给定的管道上工作,而是将在视频设备已经是管道的一部分时使用现有管道,或者分配一个新的管道。

video_device_pipeline_alloc_start() 的调用必须与 video_device_pipeline_stop() 匹配。

struct media_pipeline *video_device_pipeline(struct video_device *vdev)

获取视频设备所属的媒体管道

参数

struct video_device *vdev

视频设备

描述

此函数返回在通过 video_device_pipeline_start() 构造管道时与视频设备关联的媒体管道。指针在调用 video_device_pipeline_stop() 之前仍然有效。

视频设备必须包含单个 pad。

这是 media_entity_pipeline() 的一个便捷封装。

返回

视频设备所属的 media_pipeline,如果视频设备不属于任何管道,则返回 NULL。