最近在移植 A40i的红外摄像头驱动,把所研究的记录下来。
step1: v4l2-dev.c 通过v4l2_ioctl 的 ret = vdev->fops->ioctl(filp, cmd, arg); 跳转到 step2
static const struct file_operations v4l2_fops = {
...
.unlocked_ioctl = v4l2_ioctl,
...
}
static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct video_device *vdev = video_devdata(filp);
...
if (vdev->fops->unlocked_ioctl) {
...
} else if (vdev->fops->ioctl) {
...
if (video_is_registered(vdev))
ret = vdev->fops->ioctl(filp, cmd, arg); // 此处跳转到 step2
}
}
step2: vfe.c 摄像头接口驱动(Camera Interface (CAMIF) driver)
struct v4l2_file_operations vfe_fops = {
.....
.ioctl = video_ioctl2, //重要,跳转到 step3
}
probe_work_handle() 函数通过__video_register_device 注册 vfe_template[] 定义的 struct video_device 设备,即是 上面 v4l2_ioctl()函数的 vdev->fops->ioctl(filp, cmd, arg);
static const struct v4l2_file_operations vfe_fops = {
.owner = THIS_MODULE,
.open = vfe_open,
.release = vfe_close,
.read = vfe_read,
.poll = vfe_poll,
.ioctl = video_ioctl2, //重要,跳转到 step3
//.unlocked_ioctl =
#ifdef CONFIG_COMPAT
.compat_ioctl32 = vfe_compat_ioctl32,
#endif
.mmap = vfe_mmap,
};
static const struct v4l2_ioctl_ops vfe_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
.vidioc_enum_framesizes = vidioc_enum_framesizes,
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_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_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_streamon