2.2.4 Video device‘s internal representation

在/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_RX(VFL_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和video节点提供一个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、STREAMON和STREAMOFF)进行排队,而不是使用上面的锁。这样,vb2排队框架不必等待其他ioctl。该队列指针也由vb2辅助函数用于检查排队所有权(即调用它的文件句柄是否允许执行该操作)。
• `video_device->prio`:跟踪优先级。用于实现VIDIOC_G_PRIORITY和VIDIOC_S_PRIORITY。如果保留为NULL,则将使用v4l2_device中的struct v4l2_prio_state。如果要针对每个(组)设备节点使用单独的优先级状态,则可以将其指向自己的struct v4l2_prio_state。
• `video_device->dev_parent`:仅在v4l2_device以NULL作为父设备结构进行注册时设置此字段。这只发生在一个硬件设备具有多个PCI设备,所有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_disable_ioctl(vdev,cmd)。如果基于外部因素(例如正在使用的卡)需要关闭v4l2_ioctl_ops中的某些功能,而无需创建新的结构,则通常会需要这样做。v4l2_file_operations结构是file_operations的子集。主要区别是省略了inode参数,因为从未使用过。如果需要与媒体框架集成,则必须通过调用media_entity_pads_init()初始化video_device结构中嵌入的media_entity结构(entity字段)。

struct media_pad *pad = &my_vdev->pad;
int err;
err = media_entity_pads_init(&vdev->entity, 1, pad);

pads数组必须先前已初始化。无需手动设置struct media_entity类型和名称字段。在打开/关闭视频设备时,将自动获取/释放对实体的引用。
2.2.4.1 ioctls and locking
V4L核心提供可选的锁定服务。主要服务是video_device结构中的锁字段,它是指向mutex的指针。如果设置了此指针,则unlocked_ioctl将使用它来串行化所有ioctls。如果您使用videobuf2框架,则可以设置第二个锁:video_device->queue->lock。如果设置了该锁,则将使用该锁来代替video_device->lock以串行化所有排队ioctls(请参见上一节以获取这些ioctls的完整列表)。使用不同的锁来处理排队ioctls的优点是,对于某些驱动程序(特别是USB驱动程序),某些命令(例如设置控件)可能需要很长时间,因此您希望为缓冲区排队ioctls使用单独的锁。这样,您的VIDIOC_DQBUF不会停顿(即把buffer相关的操作和其他操作用不同的lock控制),因为驱动程序正在忙于更改摄像头的曝光等。当然,您始终可以通过将两个锁指针保留为空来自己完成所有锁定。如果您使用旧的videobuf框架,则必须将video_device->lock传递给videobuf队列初始化函数:如果videobuf需要等待帧到达,则它将临时解锁该锁,并在之后重新锁定该锁。如果您的驱动程序也在代码中等待,则应该执行相同的操作,以允许其他进程在第一个进程等待某些内容时访问设备节点。
对于videobuf2,您需要实现wait_prepare()和wait_finish()回调以解锁/锁定(如果适用)。如果使用queue->lock指针,则可以使用辅助函数vb2_ops_wait_prepare()和vb2_ops_wait_finish()。在执行热插拔断开连接的实现之前,还应从video_device获取锁,然后调用v4l2_device_disconnect。如果您还使用video_device->queue->lock,则必须先锁定video_device->queue->lock,然后锁定video_device->lock。这样,您就可以确保在调用v4l2_device_disconnect()时没有ioctl正在运行。
videobuf2是什么:
videobuf2是Linux内核中提供的一种视频缓存管理框架,它使得视频采集或播放驱动程序的实现更加简单和可靠。它可以处理多个视频帧的非连续内存分配,支持内存映射和用户空间I / O,可以实现零拷贝,在极大程度上优化了多媒体子系统的性能。并且,它还支持超时、延迟、丢弃和错误恢复等特性,使驱动程序更加健壮。
2.2.4.2 Video device registration
接下来,您需要使用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字段,则视频设备实体将自动与媒体设备注册。注册的设备取决于type参数。以下是不同的设备类型:
- VFL_TYPE_VBI:这个类型适用于垂直切线编码器(VBI)设备,比如电视卡。
- VFL_TYPE_RADIO:这个类型适用于收音机设备,比如FM收音机卡。
- VFL_TYPE_SDR:这个类型适用于软件定义无线电设备,比如RTL-SDR。
......

最后一个参数可以让您在设备节点号(即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开始。
用户可以设置udev规则,利用索引属性来创建漂亮的设备名称(例如MPEG视频采集设备节点的“mpegX”)。
设备成功注册后,就可以使用以下字段:
• video_device->vfl_type:传递给video_register_device()的设备类型。
• video_device->minor:分配的设备次设备号。
• video_device->num:设备节点号(即videoX中的X)。
• video_device->index:设备索引号。
如果注册失败,则需要调用video_device_release()来释放分配的video_device结构体,或者释放您自己的结构体,如果video_device嵌入在其中。如果注册失败,vdev->release()回调将永远不会被调用,也不应尝试取消注册设备。
2.2.4.3 video device debugging
‘dev_debug’属性是为每个video、vbi、radio或swradio设备在/sys/class/video4linux/<devX>/中创建的,它允许您启用文件操作的日志记录。它是一个位掩码,可以设置以下位:

 2.2.4.4 Video device cleanup
当必须删除视频设备节点时,无论是在卸载驱动程序期间还是因为USB设备已断开连接,您都应该使用以下方法注销它们:video_unregister_device()(vdev);这将从sysfs中删除设备节点(导致udev将它们从/dev中删除)。在video_unregister_device()返回之后,无法再进行新的打开操作。但是,在USB设备的情况下,某些应用程序可能仍然会打开其中一个这些设备节点。因此,在取消注册后,除了释放之外,所有文件操作(当然还有)都将返回错误。
当视频设备节点的最后一个用户退出时,就会调用vdev->release()回调函数,您可以在其中进行最终清理。如果已经初始化,请不要忘记清理与视频设备关联的媒体实体:media_entity_cleanup(&vdev->entity); 这可以从释放回调中完成。
2.2.4.5 helper functions
有一些有用的辅助函数:
• 文件和video_device私有数据
您可以使用以下函数在video_device结构中设置/获取驱动程序私有数据:
video_get_drvdata(vdev);
video_set_drvdata(vdev);
请注意,在调用video_register_device()之前,您可以安全地调用video_set_drvdata()。
还有这个函数:
video_devdata(struct file *file);
返回与文件结构相关联的video_device。
video_devdata()函数将video_get_drvdata()与video_devdata()组合在一起:
video_drvdata(struct file *file);
您可以通过以下方式从video_device结构转换为v4l2_device结构:

struct v4l2_device *v4l2_dev = vdev->v4l2_dev;

• 设备节点名称
可以使用以下函数检索video_device节点内核名称:
video_device_node_name(vdev);
该名称用作用户空间工具(例如udev)的提示。应尽可能使用该函数,而不是访问video_device ::num和video_device ::minor字段。
2.2.4.6 video_device functions and data structures
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是接收器、发射器还是mem-to-mem设备。
常量
VFL_DIR_RX:设备是接收器。
VFL_DIR_TX:设备是发射器。
VFL_DIR_M2M:设备是mem到mem设备。
注意
如果枚举vfl_devnode_type为VFL_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)
返回全局数组中存储的最大优先级
参数
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中。
描述
返回值:若所请求的优先级比当前最高优先级更低,则返回-EBUSY;否则返回0。注意:此函数仅应由V4L2核心使用。
struct v4l2_file_operations
V4L2设备所使用的文件系统操作集合
定义

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 实现特殊情况下Kernel使用64位指令,但用户空间使用32位指令时所需的ioctl()操作。
get_unmapped_area 被mmap()系统调用调用,用于当%!CONFIG_MMU时。
mmap 实现mmap()系统调用所需的操作。
open 实现open()系统调用所需的操作。
release 实现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[32];
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:如果CONFIG_MEDIA_CONTROLLER已定义,则它是一个指向struct media_entity结构体的指针。
intf_devnode:如果CONFIG_MEDIA_CONTROLLER已定义,则它是一个指向struct media_intf_devnode结构体的指针。
pipe:如果CONFIG_MEDIA_CONTROLLER已定义,则它是一个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:与此设备节点关联的控制句柄。可能为空。
queue:与该设备节点相关联的struct vb2_queue。可能为空。
prio:指向struct v4l2_prio_state的指针,包含设备的优先级状态。如果为NULL,则使用v4l2_dev-> prio。
name:视频设备名称。
vfl_type:V4L设备类型,由enum vfl_devnode_type定义。
vfl_dir:V4L接收器、发射器或m2m。
minor:设备节点的“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:指向struct v4l2_ioctl_ops的指针,包含ioctl回调。
valid_ioctls:此设备的有效ioctls位图。
lock:指向struct mutex的指针,用于序列化锁定。
描述
注意:只有在无法从v4l2_dev中推断出dev_parent时才设置dev_parent。
media_entity_to_video_device(__entity)
函数从嵌入在其上的struct media_entity返回一个struct video_device。
参数:
__entity:指向struct media_entity的指针。
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设备。
参数:
vdev:要注册的struct video_device。
type:要注册的设备类型,由enum vfl_devnode_type定义。
nr:所需的设备节点号,其中0表示/dev/video0,1表示/dev/video1,依此类推;-1表示第一个可用的设备节点号。
warn_if_nr_in_use:如果所需的设备节点号已被使用且选择了另一个设备节点号,则提出警告。
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设备。
参数:
vdev:要注册的struct video_device。
type:要注册的设备类型,由enum vfl_devnode_type定义。
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)
函数与video_register_device()相同,除了如果所需的设备节点号已被使用,则不会发出警告。
在内部,它调用__video_register_device()。请参阅其文档以获取更多详细信息。
注意:如果video_register_device失败,则不会调用struct video_device结构的release()回调函数,因此调用方负责释放任何数据。通常,在失败时应调用video_device_release()。
void video_unregister_device(struct video_device *vdev)
函数用于注销video4linux设备。
参数:
vdev:要注销的struct video_device。
描述:
如果vdev == NULL或video_is_registered()返回false,则不执行任何操作。
struct video_device * video_device_alloc(void)
函数用于分配struct video_device。
参数:无参数。
描述:成功时返回struct video_device,如果-ENOMEM,则返回NULL。
void video_device_release(struct video_device *vdev)
函数用于释放struct video_device。
参数:指向struct video_device的指针vdev。
描述:也可用于video_device->release()。
void video_device_release_empty(struct video_device *vdev)
函数用于实现video_device->release()回调。
参数:指向struct video_device的指针vdev。
描述:此release函数不执行任何操作。它应该在video_device是静态全局结构时使用。
注意:拥有静态video_device只是最优解的可疑构造。
void v4l2_disable_ioctl(struct video_device *vdev, unsigned int cmd)
函数用于标记给定命令未实现。不应使用core锁定。
参数:
vdev:指向struct video_device的指针。
cmd:ioctl命令。
描述:
该函数允许驱动程序提供一个v4l2_ioctl_ops结构,但基于实际找到的特定卡禁用ioctls。
注意:这必须在video_register_device之前调用。另请参阅deter-mine_valid_ioctls()的注释。
void * video_get_drvdata(struct video_device *vdev)
函数用于从struct video_device获取私有数据。
参数:指向struct video_device的指针vdev。
描述:返回指向私有数据的指针。
void video_set_drvdata(struct video_device *vdev, void *data)
函数用于设置struct video_device的私有数据。
参数:
vdev:指向struct video_device的指针。
data:私有数据指针。
描述:设置结构体中的私有数据指针以便将数据与struct video_device关联。
struct video_device * video_devdata(struct file *file)
函数用于从struct file获取struct video_device。
参数:指向struct file的指针file。
描述:返回文件的struct video_device。
void * video_drvdata(struct file *file)
函数用于使用struct file从struct video_device中获取私有数据。
参数:指向struct file的指针file。
描述:此函数结合了video_get_drvdata()和video_devdata(),因为这两个函数经常一起使用。
const char * video_device_node_name(struct video_device *vdev)
函数用于返回视频设备的名称。
参数:指向struct video_device的指针vdev。
描述:返回视频设备名称字符串。
int video_is_registered(struct video_device *vdev)
函数用于检查struct video_device是否已注册。
参数:指向struct video_device的指针vdev。
描述:如果struct video_device已注册,则返回true;否则返回false。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值