1.概述
在V4L2子系统中,Video设备是一个字符设备,设备节点为/dev/videoX
,主设备号为81,次设备号范围为0-63。在用户空间,应用可以通过open/close/ioctl/mmap/read/write
系统调用操作Video设备。在内核空间中,Video设备的具体操作方法由驱动中的struct video_device
提供。驱动使用video_register_device
函数将struct video_device
注册到V4L2的核心层,然后V4L2的核心层在向上注册一个字符设备,该字符设备实现了虚拟文件系统要求的方法。这样应用就可以使用系统调用访问虚拟文件系统中Video设备提供的方法,然后进一步访问V4L2核心层提供的v4l2_fops
方法集合,最后通过struct video_device
结构体中的fops
和ioctl_ops
方法集合访问Video主设备。Video主设备通过v4l2_subdev_call
方法访问Video从设备,同时Video从设备可以通过notify
回掉方法通知主设备发生了事件。Camera Host控制器为Video主设备,Camear Sensor(摄像头)为Video从设备,一般为I2C设备。
2.数据结构介绍
Video设备使用struct video_device
结构体表示。设备的操作方法由fops
和ioctl_ops
函数指针集合指定,fops
是文件操作方法,实现常见的open、read、write
方法,ioctl_ops
实现应用层的ioctl
函数,功能较多。具体的设备类型由vfl_type
指定,可用VFL_TYPE_XXXX表示。Video设备是一个字符设备,由cdev
指向创建的字符设备结构体。使用video_device_alloc
函数动态分配video_device
结构体内存,使用video_device_release
释放分配的video_device
结构体内存,video_device
的release
函数可以初始化为video_device_release
,当设备注销时释放内存。使用video_register_device
注册该结构体,使用video_unregister_device
注销该结构体。
[include/media/v4l2-dev.h]
// video设备类型,由video_device的vfl_type成员指定
#define VFL_TYPE_GRABBER 0 // 图像采集设备,包括摄像头、调谐器等
#define VFL_TYPE_VBI 1 // 从视频消隐的时间段取得信息的设备
#define VFL_TYPE_RADIO 2 // 无线电设备,如收音机等
#define VFL_TYPE_SUBDEV 3 // v4l2从设备
#define VFL_TYPE_SDR 4 // Software Defined Radio
#define VFL_TYPE_MAX 5
// 传输方向,设备类型为VFL_TYPE_SUBDEV时忽略,由video_device的vfl_dir成员指定
#define VFL_DIR_RX 0 // 接收
#define VFL_DIR_TX 1 // 发送
#define VFL_DIR_M2M 2 // 内存到内存
// video_device注册状态掩码,若注册成功则video_device的flags的bit0为1,
// 注销时video_device的flags的bit0清零
#define V4L2_FL_REGISTERED (0)
// video_device的flags的bit1为1,则file->private_data指向struct v4l2_fh
#define V4L2_FL_USES_V4L2_FH (1)
struct video_device
{
#if defined(CONFIG_MEDIA_CONTROLLER) // 多媒体设备配置选项
struct media_entity entity; // 用于运行时数据流的管理
#endif
/* video设备操作函数集合,实现read、write等函数 */
const struct v4l2_file_operations *fops;
// video_device对应的设备结构体
struct device dev;
// 字符设备指针,注册时创建字符设备结构体
struct cdev *cdev;
struct v4l2_device *v4l2_dev; /* v4l2_device parent */
/* Only set parent if that can't be deduced from v4l2_dev */
struct device *dev_parent; /* device parent */
/* Control handler associated with this device node. May be NULL. */
struct v4l2_ctrl_handler *ctrl_handler;
/* vb2_queue associated with this device node. May be NULL. */
struct vb2_queue *queue;
/* Priority state. If NULL, then v4l2_dev->prio will be used. */
struct v4l2_prio_state *prio;
/* 设备名称 */
char name[32];
int vfl_type; /* 设备类型 */
int vfl_dir; /* 传输方向 */
int minor; // 次设备号,如果注册失败,将被设置为-1
u16 num; // 设备数量
// 标志位,可以使用set/clear/test操作
unsigned long flags;
// 物理设备的索引,用来区分不同的物理设备
int index;
/* V4L2 file handles */
spinlock_t fh_lock; /* Lock for all v4l2_fhs */
struct list_head fh_list; /* List of struct v4l2_fh */
/* Video standard vars */
v4l2_std_id tvnorms; /* Supported tv norms */
// 设备引用计数为