v4l2,camera笔记

来源:互联网 发布:网络音乐 版权 政策 编辑:程序博客网 时间:2024/06/03 23:49
开始学习v4l2中camera的架构

    app调用v4l2框架,然后v4l2框架再调用具体的驱动

     如:在app:open----->v4l2:open------->driver:open

\

   v4l2提供的是一个通用的框架,然后驱动去实现具体的内容。

   问题:那么v4l2是怎么调用driver的呢?

           这个我们看看相关代码就很清楚了。

//drivers/media/video/v4l2-dev.c

[html] view plaincopyprint?
  1. static int v4l2_open(struct inode *inode, struct file *filp)  
  2. {  
  3.     printk("<6>\nsong:**************v4l2_open************\n");  
  4.     struct video_device *vdev;  
  5.     int ret = 0;  
  6.     /* Check if the video device is available */  
  7.     mutex_lock(&videodev_lock);  
  8.     //这里就是从我们的在驱动中注册的video_device->cdev得到video_device.  
  9.     vdev = video_devdata(filp);  
  10.    /* return ENODEV if the video device has been removed  
  11.        already or if it is not registered anymore. */  
  12.     if (vdev == NULL || !video_is_registered(vdev)) {  
  13.         mutex_unlock(&videodev_lock);  
  14.         return -ENODEV;  
  15.     }  
  16.     /* and increase the device refcount */  
  17.     video_get(vdev);  
  18.     mutex_unlock(&videodev_lock);  
  19.         //调用在驱动注册的open方法  
  20.     if (vdev->fops->open)  
  21.         ret = vdev->fops->open(filp);  
  22.   
  23.     /* decrease the refcount in case of an error */  
  24.     if (ret)  
  25.         video_put(vdev);  
  26.     return ret;  
  27. }  


  其它操作和open操作是一样的。

下面来看具体的驱动代码:

1.首先dcam_init()

在初始化的时候要注册一个platform driver:

platform_driver_register(&dcam_driver) 

然后进行相关初始化:create_instance(i)

相关代码:

[cpp] view plaincopyprint?
  1. int __init dcam_v4l2_init(void)  
  2. {  
  3.     int ret = 0, i;  
  4.       
  5.     if(platform_driver_register(&dcam_driver) != 0) {  
  6.         printk("platform device register Failed \n");  
  7.         return -1;  
  8.     }  
  9.        // 省略  
  10.           
  11.         ret = create_instance(i);      
  12.          
  13.   
  14.         // 省略  
  15.   
  16. return ret;}  
  17.   
  18. static struct platform_driver dcam_driver = {  
  19.     .probe    = dcam_probe,  
  20.     .remove   = dcam_remove,  
  21.     .driver   = {  
  22.         .owner = THIS_MODULE,  
  23.         .name = "XXXXX_dcam",  
  24.     },  
  25. };  
  26.   
  27. static int __init create_instance(int inst)  
  28. {  
  29.     struct dcam_dev *dev;  
  30.     struct video_device *vfd;  
  31.     int ret, i;  
  32.   
  33.     dev = kzalloc(sizeof(*dev), GFP_KERNEL);  
  34.     if (!dev)  
  35.         return -ENOMEM;  
  36.   
  37.     snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),  
  38.             "%s-%03d", DCAM_MODULE_NAME, inst);  
  39.     ret = v4l2_device_register(NULL, &dev->v4l2_dev);  
  40. //初始化v4l2_device  
  41.     if (ret)  
  42.         goto free_dev;  
  43.   
  44.     /* init video dma queues */  
  45.     INIT_LIST_HEAD(&dev->vidq.active);  
  46.     init_waitqueue_head(&dev->vidq.wq);  
  47.   
  48.     /* initialize locks */  
  49.     spin_lock_init(&dev->slock);  
  50.     mutex_init(&dev->mutex);  
  51.   
  52.     ret = -ENOMEM;  
  53. //为video_device分配内存  
  54.     vfd = video_device_alloc();  
  55.     if (!vfd)  
  56.         goto unreg_dev;  
  57. //为vfd赋值  
  58.     *vfd = dcam_template;  
  59.     vfd->debug = debug;  
  60. //注册video_device,主要作用是注册cdev,具体看实现,这个函数很重要  
  61.     ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);  
  62.     if (ret < 0)  
  63.         goto rel_vdev;  
  64.   
  65.     video_set_drvdata(vfd, dev);  
  66.   
  67.     /* Set all controls to their default value. */  
  68.     for (i = 0; i < ARRAY_SIZE(dcam_qctrl); i++)  
  69.         dev->qctl_regs[i] = dcam_qctrl[i].default_value;  
  70.   
  71.     /* Now that everything is fine, let's add it to device list */  
  72.     list_add_tail(&dev->dcam_devlist, &dcam_devlist);  
  73.   
  74.     snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",  
  75.             dcam_template.name, vfd->num);  
  76.   
  77.     if (video_nr >= 0)  
  78.         video_nr++;  
  79.   
  80.     dev->vfd = vfd;  
  81.     v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",  
  82.             vfd->num);  
  83.     return 0;  
  84.   
  85. rel_vdev:  
  86.     video_device_release(vfd);  
  87. unreg_dev:  
  88.     v4l2_device_unregister(&dev->v4l2_dev);  
  89. free_dev:  
  90.     kfree(dev);  
  91.     return ret;  
  92. }  
  93.   
  94. static struct video_device dcam_template = {  
  95.     .name        = "dcam",  
  96.     .fops           = &dcam_fops,  
  97.     .ioctl_ops     = &dcam_ioctl_ops,  
  98.     .minor        = -1,  
  99.     .release    = video_device_release,  
  100.   
  101.     .tvnorms              = V4L2_STD_525_60,  
  102.     .current_norm         = V4L2_STD_NTSC_M,  
  103. };  
  104.   
  105.   
  106. //现在分析probe函数  
  107. //主要作用是注册一个miscdevice  
  108. int dcam_probe(struct platform_device *pdev)  
  109. {  
  110.     int ret;  
  111.     printk(KERN_ALERT"dcam_probe called\n");  
  112.   
  113.     ret = misc_register(&dcam_v4l2_dev);//这个可以去查看相关的注册过程  
  114.     if (ret) {  
  115.         printk (KERN_ERR "cannot register miscdev on minor=%d (%d)\n",  
  116.                 DCAM_MINOR, ret);  
  117.         return ret;  
  118.     }  
  119.   
  120.     lock = (struct mutex *)kmalloc(sizeof(struct mutex), GFP_KERNEL);  
  121.     if (lock == NULL)  
  122.         return -1;  
  123.   
  124.     mutex_init(lock);      
  125.   
  126.     printk(KERN_ALERT "dcam_probe Success.\n");  
  127.   
  128.     return 0;  
  129. }  
  130. static struct miscdevice dcam_v4l2_dev = {  
  131.     .minor   = DCAM_MINOR,  
  132.     .name   = "sc8800g_dcam",  
  133.     .fops   = &dcam_fops,  
  134. };  
这样基本上一个设备就可以正常工作了。
0 0
原创粉丝点击