Chinaunix首页 | 论坛 | 博客
  • 博客访问: 346775
  • 博文数量: 108
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 65
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-16 11:38
文章分类
文章存档

2016年(2)

2015年(44)

2014年(62)

分类: 嵌入式

2015-10-13 21:20:17


点击(此处)折叠或打开

  1. 以vivi.c为例分析摄像头驱动程序思路:
  2. Virtual Video driver - This code emulates a real video device with v4l2 api

  3. 入口:static int __init vivi_init(void)
  4.           ret = vivi_create_instance(i) //创建设备
  5.                    struct vivi_dev *dev; //定义一个vivi_dev结构体
  6.       (a)定义 struct video_device *vfd //定义一个video_devce结构体
  7. struct vivi_dev {
  8.     struct list_head vivi_devlist;
  9.     struct v4l2_device      v4l2_dev;

  10.     spinlock_t slock;
  11.     struct mutex         mutex;

  12.     int users;

  13.     /* various device info */
  14.     struct video_device *vfd;

  15.     struct vivi_dmaqueue vidq;

  16.     /* Several counters */
  17.     int h, m, s, ms;
  18.     unsigned long jiffies;
  19.     char timestr[13];

  20.     int             mv_count;    /* Controls bars movement */

  21.     /* Input Number */
  22.     int             input;

  23.     /* Control 'registers' */
  24.     int              qctl_regs[ARRAY_SIZE(vivi_qctrl)];
  25. };
  26. 重要成员:
  27. /* various device info */
  28.     struct video_device *vfd; //套接一个video_devce结构体,里面设置设备信息
  29. struct video_device
  30. {
  31.     const struct v4l2_file_operations *fops;

  32.     /* sysfs */
  33.     struct device dev;        /* v4l device */
  34.     struct cdev *cdev;        /* character device */

  35.     /* Set either parent or v4l2_dev if your driver uses v4l2_device */
  36.     struct device *parent;        /* device parent */
  37.     struct v4l2_device *v4l2_dev;    /* v4l2_device parent */

  38.     /* device info */
  39.     char name[32];
  40.     int vfl_type;
  41.     /* 'minor' is set to -1 if the registration failed */
  42.     int minor;
  43.     u16 num;
  44.     /* use bitops to set/clear/test flags */
  45.     unsigned long flags;
  46.     /* attribute to differentiate multiple indices on one physical device */
  47.     int index;

  48.     int debug;            /* Activates debug level*/

  49.     /* Video standard vars */
  50.     v4l2_std_id tvnorms;        /* Supported tv norms */
  51.     v4l2_std_id current_norm;    /* Current tvnorm */

  52.     /* callbacks */
  53.     void (*release)(struct video_device *vdev);

  54.     
  55.     const struct v4l2_ioctl_ops *ioctl_ops;
  56. };
  57. 重要成员:
  58.     const struct v4l2_file_operations *fops; //定义设备操作函数
  59.     const struct v4l2_ioctl_ops *ioctl_ops; //定义ioctl 回调函数,用于应用程序获取底层信息比如获取、配置摄像头所支持的格式
  60.     
  61. vivi.c中对video_device设置的过程:
  62.       (b)分配    vfd = video_device_alloc(); //给前面定义的video_device结构体分配内存
  63.       (c)设置    *vfd = vivi_template; //把之前设置好的video_device结构体赋给vfd
  64. 注:
  65. static struct video_device vivi_template = {
  66.     .name        = "vivi",
  67.     .fops = &vivi_fops,
  68.     .ioctl_ops     = &vivi_ioctl_ops,
  69.     .minor        = -1,
  70.     .release    = video_device_release,
  71. 其中包括几个两个重要操作函数的设置:
  72. 1.
  73. static const struct v4l2_file_operations vivi_fops = {
  74.     .owner        = THIS_MODULE,
  75.     .open = vivi_open,
  76.     .release = vivi_close,
  77.     .read = vivi_read,
  78.     .poll        = vivi_poll,
  79.     .ioctl = video_ioctl2, /* V4L2 ioctl handler */
  80.     .mmap = vivi_mmap,
  81. };


  82. struct v4l2_file_operations {
  83.     struct module *owner;
  84.     ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
  85.     ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
  86.     unsigned int (*poll) (struct file *, struct poll_table_struct *);
  87.     long (*ioctl) (struct file *, unsigned int, unsigned long);
  88.     long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
  89.     unsigned long (*get_unmapped_area) (struct file *, unsigned long,
  90.                 unsigned long, unsigned long, unsigned long);
  91.     int (*mmap) (struct file *, struct vm_area_struct *);
  92.     int (*open) (struct file *);
  93.     int (*release) (struct file *);
  94. };
  95. 2.
  96. static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
  97.     /* 表示它是一个摄像头设备 */
  98.     .vidioc_querycap = vidioc_querycap,
  99.         
  100.     /* 用于选择输入源,在xawtv里面就是video source */    
  101.     //.vidioc_enum_input = vidioc_enum_input,    
  102.     //.vidioc_g_input = vidioc_g_input,
  103.     //.vidioc_s_input = vidioc_s_input,
  104.     
  105.     /* 用于列举、获得TV 制式,不是必须的*/
  106.     //.vidioc_s_std = vidioc_s_std,
  107.     /* video_device里面:
  108.      .tvnorms = V4L2_STD_525_60, //用于IDIOC_ENUMSTD
  109.      .current_norm = V4L2_STD_NTSC_M,// 用于VIDIOC_G_STD
  110.      */

  111.     /* 用于列举、获得、测试、设置摄像头所提供的格式 */
  112.     .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,//也可以去掉
  113.     .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
  114.     .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
  115.     .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,

  116.     /* 缓冲区操作: 申请/ 查询/ 放入队列/取出队列*/
  117.     .vidioc_reqbufs = vidioc_reqbufs,
  118.     .vidioc_querybuf = vidioc_querybuf,
  119.     .vidioc_qbuf = vidioc_qbuf,
  120.     .vidioc_dqbuf = vidioc_dqbuf,
  121.     
  122.     /* 查询/获得/设置属性 */
  123.     //.vidioc_queryctrl = vidioc_queryctrl,
  124.     //.vidioc_g_ctrl = vidioc_g_ctrl,
  125.     //.vidioc_s_ctrl = vidioc_s_ctrl,

  126.     /* 启动/停止摄像头 */
  127.     .vidioc_streamon = vidioc_streamon,
  128.     .vidioc_streamoff = vidioc_streamoff,
  129. };


  130. struct v4l2_ioctl_ops {
  131.     /* ioctl callbacks */

  132.     /* VIDIOC_QUERYCAP handler */
  133.     int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);

  134.     /* Priority handling */
  135.     int (*vidioc_g_priority) (struct file *file, void *fh,
  136.                  enum v4l2_priority *p);
  137.     int (*vidioc_s_priority) (struct file *file, void *fh,
  138.                  enum v4l2_priority p);

  139.     /* VIDIOC_ENUM_FMT handlers */
  140.     int (*vidioc_enum_fmt_vid_cap) (struct file *file, void *fh,
  141.                      struct v4l2_fmtdesc *f);
  142.     int (*vidioc_enum_fmt_vid_overlay) (struct file *file, void *fh,
  143.                      struct v4l2_fmtdesc *f);
  144.     int (*vidioc_enum_fmt_vid_out) (struct file *file, void *fh,
  145.                      struct v4l2_fmtdesc *f);
  146.     int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
  147.                      struct v4l2_fmtdesc *f);

  148.     /* VIDIOC_G_FMT handlers */
  149.     int (*vidioc_g_fmt_vid_cap) (struct file *file, void *fh,
  150.                     struct v4l2_format *f);
  151.     int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh,
  152.                     struct v4l2_format *f);
  153.     int (*vidioc_g_fmt_vid_out) (struct file *file, void *fh,
  154.                     struct v4l2_format *f);
  155.     int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh,
  156.                     struct v4l2_format *f);
  157.     int (*vidioc_g_fmt_vbi_cap) (struct file *file, void *fh,
  158.                     struct v4l2_format *f);
  159.     int (*vidioc_g_fmt_vbi_out) (struct file *file, void *fh,
  160.                     struct v4l2_format *f);
  161.     int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *fh,
  162.                     struct v4l2_format *f);
  163.     int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh,
  164.                     struct v4l2_format *f);
  165.     int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
  166.                     struct v4l2_format *f);

  167.     /* VIDIOC_S_FMT handlers */
  168.     int (*vidioc_s_fmt_vid_cap) (struct file *file, void *fh,
  169.                     struct v4l2_format *f);
  170.     int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh,
  171.                     struct v4l2_format *f);
  172.     int (*vidioc_s_fmt_vid_out) (struct file *file, void *fh,
  173.                     struct v4l2_format *f);
  174.     int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh,
  175.                     struct v4l2_format *f);
  176.     int (*vidioc_s_fmt_vbi_cap) (struct file *file, void *fh,
  177.                     struct v4l2_format *f);
  178.     int (*vidioc_s_fmt_vbi_out) (struct file *file, void *fh,
  179.                     struct v4l2_format *f);
  180.     int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *fh,
  181.                     struct v4l2_format *f);
  182.     int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh,
  183.                     struct v4l2_format *f);
  184.     int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
  185.                     struct v4l2_format *f);

  186.     /* VIDIOC_TRY_FMT handlers */
  187.     int (*vidioc_try_fmt_vid_cap) (struct file *file, void *fh,
  188.                      struct v4l2_format *f);
  189.     int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh,
  190.                      struct v4l2_format *f);
  191.     int (*vidioc_try_fmt_vid_out) (struct file *file, void *fh,
  192.                      struct v4l2_format *f);
  193.     int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh,
  194.                      struct v4l2_format *f);
  195.     int (*vidioc_try_fmt_vbi_cap) (struct file *file, void *fh,
  196.                      struct v4l2_format *f);
  197.     int (*vidioc_try_fmt_vbi_out) (struct file *file, void *fh,
  198.                      struct v4l2_format *f);
  199.     int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *fh,
  200.                      struct v4l2_format *f);
  201.     int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh,
  202.                      struct v4l2_format *f);
  203.     int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
  204.                      struct v4l2_format *f);

  205.     /* Buffer handlers */
  206.     int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
  207.     int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
  208.     int (*vidioc_qbuf) (struct file *file, void *fh, struct v4l2_buffer *b);
  209.     int (*vidioc_dqbuf) (struct file *file, void *fh, struct v4l2_buffer *b);


  210.     int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
  211. #ifdef CONFIG_VIDEO_V4L1_COMPAT
  212.             /* buffer type is struct vidio_mbuf * */
  213.     int (*vidiocgmbuf) (struct file *file, void *fh, struct video_mbuf *p);
  214. #endif
  215.     int (*vidioc_g_fbuf) (struct file *file, void *fh,
  216.                 struct v4l2_framebuffer *a);
  217.     int (*vidioc_s_fbuf) (struct file *file, void *fh,
  218.                 struct v4l2_framebuffer *a);

  219.         /* Stream on/off */
  220.     int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);
  221.     int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);

  222.         /* Standard handling
  223.             ENUMSTD is handled by videodev.c
  224.          */
  225.     int (*vidioc_g_std) (struct file *file, void *fh, v4l2_std_id *norm);
  226.     int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
  227.     int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);

  228.         /* Input handling */
  229.     int (*vidioc_enum_input)(struct file *file, void *fh,
  230.                  struct v4l2_input *inp);
  231.     int (*vidioc_g_input) (struct file *file, void *fh, unsigned int *i);
  232.     int (*vidioc_s_input) (struct file *file, void *fh, unsigned int i);

  233.         /* Output handling */
  234.     int (*vidioc_enum_output) (struct file *file, void *fh,
  235.                  struct v4l2_output *a);
  236.     int (*vidioc_g_output) (struct file *file, void *fh, unsigned int *i);
  237.     int (*vidioc_s_output) (struct file *file, void *fh, unsigned int i);

  238.         /* Control handling */
  239.     int (*vidioc_queryctrl) (struct file *file, void *fh,
  240.                     struct v4l2_queryctrl *a);
  241.     int (*vidioc_g_ctrl) (struct file *file, void *fh,
  242.                     struct v4l2_control *a);
  243.     int (*vidioc_s_ctrl) (struct file *file, void *fh,
  244.                     struct v4l2_control *a);
  245.     int (*vidioc_g_ext_ctrls) (struct file *file, void *fh,
  246.                     struct v4l2_ext_controls *a);
  247.     int (*vidioc_s_ext_ctrls) (struct file *file, void *fh,
  248.                     struct v4l2_ext_controls *a);
  249.     int (*vidioc_try_ext_ctrls) (struct file *file, void *fh,
  250.                     struct v4l2_ext_controls *a);
  251.     int (*vidioc_querymenu) (struct file *file, void *fh,
  252.                     struct v4l2_querymenu *a);

  253.     /* Audio ioctls */
  254.     int (*vidioc_enumaudio) (struct file *file, void *fh,
  255.                     struct v4l2_audio *a);
  256.     int (*vidioc_g_audio) (struct file *file, void *fh,
  257.                     struct v4l2_audio *a);
  258.     int (*vidioc_s_audio) (struct file *file, void *fh,
  259.                     struct v4l2_audio *a);

  260.     /* Audio out ioctls */
  261.     int (*vidioc_enumaudout) (struct file *file, void *fh,
  262.                     struct v4l2_audioout *a);
  263.     int (*vidioc_g_audout) (struct file *file, void *fh,
  264.                     struct v4l2_audioout *a);
  265.     int (*vidioc_s_audout) (struct file *file, void *fh,
  266.                     struct v4l2_audioout *a);
  267.     int (*vidioc_g_modulator) (struct file *file, void *fh,
  268.                     struct v4l2_modulator *a);
  269.     int (*vidioc_s_modulator) (struct file *file, void *fh,
  270.                     struct v4l2_modulator *a);
  271.     /* Crop ioctls */
  272.     int (*vidioc_cropcap) (struct file *file, void *fh,
  273.                     struct v4l2_cropcap *a);
  274.     int (*vidioc_g_crop) (struct file *file, void *fh,
  275.                     struct v4l2_crop *a);
  276.     int (*vidioc_s_crop) (struct file *file, void *fh,
  277.                     struct v4l2_crop *a);
  278.     /* Compression ioctls */
  279.     int (*vidioc_g_jpegcomp) (struct file *file, void *fh,
  280.                     struct v4l2_jpegcompression *a);
  281.     int (*vidioc_s_jpegcomp) (struct file *file, void *fh,
  282.                     struct v4l2_jpegcompression *a);
  283.     int (*vidioc_g_enc_index) (struct file *file, void *fh,
  284.                     struct v4l2_enc_idx *a);
  285.     int (*vidioc_encoder_cmd) (struct file *file, void *fh,
  286.                     struct v4l2_encoder_cmd *a);
  287.     int (*vidioc_try_encoder_cmd) (struct file *file, void *fh,
  288.                     struct v4l2_encoder_cmd *a);

  289.     /* Stream type-dependent parameter ioctls */
  290.     int (*vidioc_g_parm) (struct file *file, void *fh,
  291.                     struct v4l2_streamparm *a);
  292.     int (*vidioc_s_parm) (struct file *file, void *fh,
  293.                     struct v4l2_streamparm *a);

  294.     /* Tuner ioctls */
  295.     int (*vidioc_g_tuner) (struct file *file, void *fh,
  296.                     struct v4l2_tuner *a);
  297.     int (*vidioc_s_tuner) (struct file *file, void *fh,
  298.                     struct v4l2_tuner *a);
  299.     int (*vidioc_g_frequency) (struct file *file, void *fh,
  300.                     struct v4l2_frequency *a);
  301.     int (*vidioc_s_frequency) (struct file *file, void *fh,
  302.                     struct v4l2_frequency *a);

  303.     /* Sliced VBI cap */
  304.     int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh,
  305.                     struct v4l2_sliced_vbi_cap *a);

  306.     /* Log status ioctl */
  307.     int (*vidioc_log_status) (struct file *file, void *fh);

  308.     int (*vidioc_s_hw_freq_seek) (struct file *file, void *fh,
  309.                     struct v4l2_hw_freq_seek *a);

  310.     /* Debugging ioctls */
  311. #ifdef CONFIG_VIDEO_ADV_DEBUG
  312.     int (*vidioc_g_register) (struct file *file, void *fh,
  313.                     struct v4l2_dbg_register *reg);
  314.     int (*vidioc_s_register) (struct file *file, void *fh,
  315.                     struct v4l2_dbg_register *reg);
  316. #endif
  317.     int (*vidioc_g_chip_ident) (struct file *file, void *fh,
  318.                     struct v4l2_dbg_chip_ident *chip);

  319.     int (*vidioc_enum_framesizes) (struct file *file, void *fh,
  320.                      struct v4l2_frmsizeenum *fsize);

  321.     int (*vidioc_enum_frameintervals) (struct file *file, void *fh,
  322.                      struct v4l2_frmivalenum *fival);

  323.     /* For other private ioctls */
  324.     long (*vidioc_default)     (struct file *file, void *fh,
  325.                     int cmd, void *arg);
  326. };    
  327.     (d)注册     ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
  328.                  return video_register_device_index(vdev, type, nr, -1);
  329.                          /*注册三部曲*/
  330.                          vdev->cdev = cdev_alloc(); //第一步 分配字符设备内存
  331.                          vdev->cdev->ops = &v4l2_fops; //第二部 设置将设备节点的操作函数
  332.                          ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); //将字符设备注册进内核
  333. 以上是虚拟视频驱动vivi.c的分析,以下下是分析vivi.c的open,read,write,ioctl过程:
  334. 1. open
  335. app: open(/dev/video0)

  336. 2. read
  337. app: read(/dev/video0)

  338. 3. write
  339. app: write(/dev/video0)     
  340. 4. ioctl
  341. app: iotcl(/dev/video0)
  342.   
  343.   以上系统函数调用,在进入驱动程序里都对应上面注册的v4l2_fops结构体里面的对应函数:
  344.  static const struct file_operations v4l2_fops = {
  345.      .owner = THIS_MODULE,
  346.     .read = v4l2_read,
  347.     .write = v4l2_write,
  348.     .open = v4l2_open,
  349.     .get_unmapped_area = v4l2_get_unmapped_area,
  350.     .mmap = v4l2_mmap,
  351.     .ioctl = v4l2_ioctl,    


  352. static int v4l2_open(struct inode *inode, struct file *filp)
  353. {
  354.     struct video_device *vdev;
  355.     int ret = 0;

  356.     /* Check if the video device is available */
  357.     mutex_lock(&videodev_lock);
  358.     vdev = video_devdata(filp); // 根据次设备号从数组中得到video_device
  359.     /* return ENODEV if the video device has been removed
  360.      already or if it is not registered anymore. */
  361.     if (vdev == NULL || video_is_unregistered(vdev)) {
  362.         mutex_unlock(&videodev_lock);
  363.         return -ENODEV;
  364.     }
  365.     /* and increase the device refcount */
  366.     video_get(vdev);
  367.     mutex_unlock(&videodev_lock);
  368.     if (vdev->fops->open)
  369.         ret = vdev->fops->open(filp); //这里才显示庐山真面目,最终调用的是前面写的vivi_open函数

  370.     /* decrease the refcount in case of an error */
  371.     if (ret)
  372.         video_put(vdev);
  373.     return ret;    
  374. }
  375. 注:
  376. struct video_device *video_devdata(struct file *file)
  377. {
  378.     return video_device[iminor(file->f_path.dentry->d_inode)];
  379.     
  380. }
  381. 同理:app中的read函数最终会调用v4l2_read函数:
  382. static ssize_t v4l2_read(struct file *filp, char __user *buf,
  383.         size_t sz, loff_t *off)
  384. {
  385.     struct video_device *vdev = video_devdata(filp);

  386.     if (!vdev->fops->read)
  387.         return -EINVAL;
  388.     if (video_is_unregistered(vdev))
  389.         return -EIO;
  390.     return vdev->fops->read(filp, buf, sz, off); //最终会调用v4l2_fops操作结构体中的vivi_read函数
  391. }
  392. 注:由于采用总线设备驱动模型,一些驱动通用的函数,linux系统已经帮助实现v4l2_dev.c(例v4l2_fops),到具体open,read,write,ioctl时,即最终
  393. 的open,read,write,ioctl等函数还要写驱动的人实现。

  394. static ssize_t v4l2_write(struct file *filp, const char __user *buf,
  395.         size_t sz, loff_t *off)
  396. {
  397.     struct video_device *vdev = video_devdata(filp);

  398.     if (!vdev->fops->write)
  399.         return -EINVAL;
  400.     if (video_is_unregistered(vdev))
  401.         return -EIO;
  402.     return vdev->fops->write(filp, buf, sz, off);//最终会调用v4l2_fops操作结构体中的vivi_write函数
  403. }

  404. static int v4l2_ioctl(struct inode *inode, struct file *filp,
  405.         unsigned int cmd, unsigned long arg)
  406. {
  407.     struct video_device *vdev = video_devdata(filp);

  408.     if (!vdev->fops->ioctl)
  409.         return -ENOTTY;
  410.     /* Allow ioctl to continue even if the device was unregistered.
  411.      Things like dequeueing buffers might still be useful. */
  412.     return vdev->fops->ioctl(filp, cmd, arg); //最终会调用v4l2_fops操作结构体中的vivi_ioctl函数

阅读(1355) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~