linux camera V4L2框架(一)

1.V4L2 驱动中的核心结构体

v4l2_device;一个v4l2的总设备。

v4l2_sbudev:来描述camera等sensor设备,一般是指挂接在总线(i2c)上的摄像头

video_device:实际和处理器采集口相关的配置,一般该设备会完成注册以/dev/video0,video1的字符设备注册的形式暴露给应用层。

 

video_device的重要性在于它具备承上启下的作用,驱动实现的ioctl内容,刚好则是为用户的控制提供了内核的实现。当然内核ioctl向下又是能控制相关的vfe和sensor,如下

static struct video_device vfe_template = {
  .name       = "vfe",
  .fops       = &vfe_fops, //用户open的相关内容
  .ioctl_ops  = &vfe_ioctl_ops,//用户ioctl对应的相关内容                                                                               .release    = video_device_release,
};

 

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,   //最终会调用v4l2_ioctl_ops这个实际处理器的相关处理逻辑                                              //  //.unlocked_ioctl = 
  .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,//video buffer缓存申请
  .vidioc_querybuf          = vidioc_querybuf,//查询buffer属性,完成对用户v4l2的设置,为mmap做准备
  .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          = vidioc_streamon,//启动视频采集
  .vidioc_streamoff         = vidioc_streamoff,
  .vidioc_queryctrl         = vidioc_queryctrl,
  .vidioc_g_ctrl            = vidioc_g_ctrl,
  .vidioc_s_ctrl            = vidioc_s_ctrl,
  .vidioc_g_parm            = vidioc_g_parm,
  .vidioc_s_parm            = vidioc_s_parm,
#ifdef CONFIG_VIDEO_V4L1_COMPAT
  .vidiocgmbuf              = vidiocgmbuf,
#endif
};

video_device除了实现对基本的视频端口的硬件初始化,还完成对相关的视频采集缓存区的维护,通过queue来维护采集逻辑,通过中断来触发处理。

 

2.视频采集的最底层部分当然是外设camera

不同的camera有不同的驱动,但是他都凌驾在i2c的控制器上。故实现camera的驱动,通常都是实现i2c_driver和i2c_client的相关内容。这里相关的i2c_adapter(和处理器自己的i2c总线特性相关,比如A31有4路i2c,故有4个 adapter)。

比如camera ov5640的驱动架构很简单,但是为了和专门的视频采集挂接在一起,他作为i2c_client的同时也是v4l2_sbudev子设备。

static const struct v4l2_subdev_ops sensor_ops = {
	.core = &sensor_core_ops,
	.video = &sensor_video_ops,
};

这个结构体是作为v4l2子设备的op,会通过video device的ioctl来调用实现。

在video的驱动中,可以看到如下API:

v4l2_i2c_new_subdev_b oard():生成一个新的i2c的v4l2子设备,内部核心:是建立一个i2c_board_info(表明板级上的一个i2c client),并将其完成设备的注册,这会调用对应的camera驱动的probe函数。这里会调用函数:

v4l2_i2c_subdev_init(sd, client, &sensor_ops);//subdevice建立,与i2c client建立联系。

从上面的这个API的实现,建立了subdev和client的关系后,video这边就可以通过用户传入的ioctl命令来对subdev进行控制如:

v4l2_subdev_call内部会调用i2c_client的驱动处理即上文中的sensor_ops中的core和video过程。

 

到此为止,video device,subdev, sensor之间的关系基本理通,调用的顺序合理而且紧密,如下图所示。

linux camera V4L2框架(一)_第1张图片

                                              图1:  linux内核视频采集驱动架构

你可能感兴趣的:(linux camera V4L2框架(一))