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_REQBUFS, CREATE_BUFS, QBUF, DQBUF, QUERYBUF, PREPARE_BUF, STREAMONSTREAMOFF),而不是上面的锁。这样,vb2 排队框架不必等待其他 ioctl。此队列指针还被 vb2 助手函数用于检查排队所有权(即,是否允许调用它的文件句柄执行该操作)。

  • video_device->prio: 跟踪优先级。用于实现 VIDIOC_G_PRIORITYVIDIOC_S_PRIORITY。如果保留为 NULL,则它将使用 v4l2_device 中的 struct v4l2_prio_state。如果要为每个(组)设备节点具有单独的优先级状态,则可以将其指向您自己的 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,那么您应该在您的 v4l2_file_operations 结构体中将 video_device->unlocked_ioctl 设置为 video_ioctl2()

在某些情况下,您希望告诉核心,您在 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 父设备的 mdev 字段不是 NULL,则视频设备实体将自动向媒体设备注册。

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

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. 视频设备调试

为每个视频、vbi、无线电或软件无线电设备创建的 ‘dev_debug’ 属性位于 /sys/class/video4linux/<devX>/ 中,它允许你启用文件操作的日志记录。

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

掩码

描述

0x01

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

0x02

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

0x04

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

0x08

记录 read 和 write 文件操作以及 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:裁剪和合成被交换。如果设置此标志,则 v4l2-ioctl.c 中的 g/s_crop/cropcap 函数中的选择目标将被交换。这允许这些驱动程序正确实现选择 API,但旧的裁剪 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 *);
};

成员

拥有者

指向 struct module 的指针

读取

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

写入

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

轮询

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

unlocked_ioctl

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

compat_ioctl32

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

get_unmapped_area

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

mmap

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

打开

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

释放

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

描述

注意

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

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;
};

成员

实体

struct media_entity

intf_devnode

指向 struct media_intf_devnode 的指针

管道

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。

队列

与此设备节点关联的 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() 回调

ioctl_ops

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

valid_ioctls

此设备的有效 ioctl 的位图

指向 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 的指针

描述

此释放函数不执行任何操作。

当 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。