v4l2_device
v4l2_device在v4l2框架中充当所有v4l2_subdev的父设备,管理着注册在其下的子设备。以下是v4l2_device结构体原型(去掉了无关的成员):
复制代码
struct v4l2_device {
structlist_head subdevs; //用链表管理注册的subdev
charname[V4L2_DEVICE_NAME_SIZE]; //device 名字
structkref ref; //引用计数
……
}
复制代码
可以看出v4l2_device的主要作用是管理注册在其下的子设备,方便系统查找引用到。
V4l2_device的注册和注销:
int v4l2_device_register(struct device*dev, struct v4l2_device *v4l2_dev)
static void v4l2_device_release(struct kref *ref)
V4l2_subdev
V4l2_subdev代表子设备,包含了子设备的相关属性和操作。先来看下结构体原型:
复制代码
struct v4l2_subdev {
struct v4l2_device *v4l2_dev; //指向父设备
//提供一些控制v4l2设备的接口
const struct v4l2_subdev_ops *ops;
//向V4L2框架提供的接口函数
const struct v4l2_subdev_internal_ops *internal_ops;
//subdev控制接口
struct v4l2_ctrl_handler *ctrl_handler;
/* name must be unique */
charname[V4L2_SUBDEV_NAME_SIZE];
/*subdev device node */
struct video_device *devnode;
};
复制代码
每个子设备驱动都需要实现一个v4l2_subdev结构体,v4l2_subdev可以内嵌到其它结构体中,也可以独立使用。结构体中包含了对子设备操作的成员v4l2_subdev_ops和v4l2_subdev_internal_ops。
v4l2_subdev_ops结构体原型如下:
复制代码
struct v4l2_subdev_ops {
//视频设备通用的操作:初始化、加载FW、上电和RESET等
const struct v4l2_subdev_core_ops *core; //tuner特有的操作
const struct v4l2_subdev_tuner_ops *tuner; //audio特有的操作
const struct v4l2_subdev_audio_ops *audio; //视频设备的特有操作:设置帧率、裁剪图像、开关视频流等
const struct v4l2_subdev_video_ops *video;
……
};
复制代码
视频设备通常需要实现core和video成员,这两个OPS中的操作都是可选的,但是对于视频流设备video->s_stream(开启或关闭流IO)必须要实现。
v4l2_subdev_internal_ops结构体原型如下:
复制代码
struct v4l2_subdev_internal_ops {
//当subdev注册时被调用,读取IC的ID来进行识别
int(*registered)(struct v4l2_subdev *sd);
void(*unregistered)(struct v4l2_subdev *sd);
//当设备节点被打开时调用,通常会给设备上电和设置视频捕捉FMT
int(*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
int(*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
};
复制代码
v4l2_subdev_internal_ops是向V4L2框架提供的接口,只能被V4L2框架层调用。在注册或打开子设备时,进行一些辅助性操作。
Subdev的注册和注销
当我们把v4l2_subdev需要实现的成员都已经实现,就可以调用以下函数把子设备注册到V4L2核心层:
int v4l2_device_register_subdev(struct v4l2_device*v4l2_dev, struct v4l2_subdev *sd)
当卸载子设备时,可以调用以下函数进行注销:
void v4l2_device_unregister_subdev(struct v4l2_subdev*sd)
video_device
video_device结构体用于在/dev目录下生成设备节点文件,把操作设备的接口暴露给用户空间。
复制代码
struct video_device
{
const struct v4l2_file_operations *fops; //V4L2设备操作集合
/*sysfs */
struct device dev; /* v4l device */
struct cdev *cdev; //字符设备
/* Seteither parent or v4l2_dev if your driver uses v4l2_device */
struct device *parent; /* deviceparent */
struct