v4l2 编程接口(二) ― driver(二)

2014-11-24 09:08:17 · 作者: · 浏览: 1
= vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_queryctrl = vidioc_queryctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
.vidioc_default = vidioc_default,
};
该结构各域的作用如上篇文章所述。video_device 通过 video_register_device 函数注册,函数原型如下:
[cpp]
/**
* video_register_device - 注册一个 v4l2 设备
* @vdev: video_device 结构
* @type: v4l2 设备的类型
* @nr: 从设备号(0 == /dev/video0, 1 == /dev/video1, -1 == first free)
*
* 注册代码将会根据注册设备的类型指派从设备号,如果没有合适的从设备号将会返回错误值.
*
* 通常有如下几种设备类型
*
* %VFL_TYPE_GRABBER - 视频采集设备
*
* %VFL_TYPE_VTX - 图文电视设备
*
* %VFL_TYPE_VBI - 场消隐区解码设备(undecoded)
*
* %VFL_TYPE_RADIO - 无线设备
*/
int video_register_device(struct video_device *vdev, int type, int nr)
{
return __video_register_device(vdev, type, nr, 1);
}
EXPORT_SYMBOL(video_register_device);
该函数注册流程较简单:首先会根据设备类型确定在 /dev 目录下的节点名称以及从设备号的偏移和值,然后为 cdev 申请内存空间并注册,将 vdev->cdev->ops 设置为内核提供的 v4l2_fops,最后将 vdev->dev 注册到 sysfs 中。
2、v4l2_subdev
许多驱动需要与子设备通信,这些设备做的任务比较常见的是音视频处理、编解码等, 网络摄像头比较常见的子设备是传感器和摄像头控制器。为了提供一个统一的接口给这些子设备,内核将涉及到子设备控制的那部分(如 vidioc_s_ctrl、vidioc_s_frequency 等)独立了出来,用 struct v4l2_subdev 来表示以方便用户实现 v4l2 驱动程序:
[cpp]
struct v4l2_subdev {
struct list_head list; /* 链接至 v4l2_device */
struct module *owner;
u32 flags;
struct v4l2_device *v4l2_dev; /* 指向 v4l2_device */
const struct v4l2_subdev_ops *ops; /* subdev 操作合集 */
/* name must be unique */
char name[V4L2_SUBDEV_NAME_SIZE];
/* can be used to group similar subdevs, value is driver-specific */
u32 grp_id;
/* 私有数据 */
void *priv;
};
其中 list 域作为链表节点链接至 v4l2_dev 指向的 v4l2_device 结构中,这个结构中最重要的成员就是 struct v4l2_subdev_ops *ops,该域包含了 v4l2 设备支持的所有操作,定义如下:
[cpp]
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core; /* 通用操作合集 */
const struct v4l2_subdev_tuner_ops *tuner; /* 调谐器操作合集 */
const struct v4l2_subdev_audio_ops *audio; /* 音频操作合集 */
const struct v4l2_subdev_video_ops *video; /* 视频操作合集 */
};
v4l2_subdev_core_ops 包含的操作合集是各种类型设备通用的:
[cpp]
struct v4l2_subdev_core_ops {
int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); /* 获取设备id */
int (*log_status)(struct v4l2_subdev *sd); /* 状态消息 */
int (*s_config)(struct v4l2_subdev *sd, int irq, void *platform_data); /* 设置配置信息 */
int (*init)(struct v4l2_subdev *sd, u32 val); /* 初始化设备 */
int (*load_fw)(struct v4l2_subdev *sd); /* 加载firmware */
int (*reset)(struct v4l2_subdev *sd, u32 val); /* 重置设备 */
int (*s_gpi