v4l2,camera笔记

from:


http://blog.csdn.net/hanmengaidudu/article/details/26000977

开始学习v4l2中camera的架构

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

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

\

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

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

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

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

  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. }  
  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. }  
static int v4l2_open(struct inode *inode, struct file *filp)
{
    printk("<6>\nsong:**************v4l2_open************\n");
    struct video_device *vdev;
    int ret = 0;
    /* Check if the video device is available */
    mutex_lock(&videodev_lock);
    //这里就是从我们的在驱动中注册的video_device->cdev得到video_device.
    vdev = video_devdata(filp);
   /* return ENODEV if the video device has been removed
       already or if it is not registered anymore. */
    if (vdev == NULL || !video_is_registered(vdev)) {
        mutex_unlock(&videodev_lock);
        return -ENODEV;
    }
    /* and increase the device refcount */
    video_get(vdev);
    mutex_unlock(&videodev_lock);
        //调用在驱动注册的open方法
    if (vdev->fops->open)
        ret = vdev->fops->open(filp);

    /* decrease the refcount in case of an error */
    if (ret)
        video_put(vdev);
    return ret;
}



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

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

1.首先dcam_init()

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

platform_driver_register(&dcam_driver) 

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

相关代码:

  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. };  
  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. };  
int __init dcam_v4l2_init(void)
{
    int ret = 0, i;
    
    if(platform_driver_register(&dcam_driver) != 0) {
        printk("platform device register Failed \n");
        return -1;
    }
       // 省略
        
        ret = create_instance(i);    
       

        // 省略

return ret;}

static struct platform_driver dcam_driver = {
    .probe    = dcam_probe,
    .remove   = dcam_remove,
    .driver   = {
        .owner = THIS_MODULE,
        .name = "XXXXX_dcam",
    },
};

static int __init create_instance(int inst)
{
    struct dcam_dev *dev;
    struct video_device *vfd;
    int ret, i;

    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    if (!dev)
        return -ENOMEM;

    snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
            "%s-%03d", DCAM_MODULE_NAME, inst);
    ret = v4l2_device_register(NULL, &dev->v4l2_dev);
//初始化v4l2_device
    if (ret)
        goto free_dev;

    /* init video dma queues */
    INIT_LIST_HEAD(&dev->vidq.active);
    init_waitqueue_head(&dev->vidq.wq);

    /* initialize locks */
    spin_lock_init(&dev->slock);
    mutex_init(&dev->mutex);

    ret = -ENOMEM;
//为video_device分配内存
    vfd = video_device_alloc();
    if (!vfd)
        goto unreg_dev;
//为vfd赋值
    *vfd = dcam_template;
    vfd->debug = debug;
//注册video_device,主要作用是注册cdev,具体看实现,这个函数很重要
    ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
    if (ret < 0)
        goto rel_vdev;

    video_set_drvdata(vfd, dev);

    /* Set all controls to their default value. */
    for (i = 0; i < ARRAY_SIZE(dcam_qctrl); i++)
        dev->qctl_regs[i] = dcam_qctrl[i].default_value;

    /* Now that everything is fine, let's add it to device list */
    list_add_tail(&dev->dcam_devlist, &dcam_devlist);

    snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
            dcam_template.name, vfd->num);

    if (video_nr >= 0)
        video_nr++;

    dev->vfd = vfd;
    v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
            vfd->num);
    return 0;

rel_vdev:
    video_device_release(vfd);
unreg_dev:
    v4l2_device_unregister(&dev->v4l2_dev);
free_dev:
    kfree(dev);
    return ret;
}

static struct video_device dcam_template = {
    .name        = "dcam",
    .fops           = &dcam_fops,
    .ioctl_ops     = &dcam_ioctl_ops,
    .minor        = -1,
    .release    = video_device_release,

    .tvnorms              = V4L2_STD_525_60,
    .current_norm         = V4L2_STD_NTSC_M,
};


//现在分析probe函数
//主要作用是注册一个miscdevice
int dcam_probe(struct platform_device *pdev)
{
    int ret;
    printk(KERN_ALERT"dcam_probe called\n");

    ret = misc_register(&dcam_v4l2_dev);//这个可以去查看相关的注册过程
    if (ret) {
        printk (KERN_ERR "cannot register miscdev on minor=%d (%d)\n",
                DCAM_MINOR, ret);
        return ret;
    }

    lock = (struct mutex *)kmalloc(sizeof(struct mutex), GFP_KERNEL);
    if (lock == NULL)
        return -1;

    mutex_init(lock);    

    printk(KERN_ALERT "dcam_probe Success.\n");

    return 0;
}
static struct miscdevice dcam_v4l2_dev = {
    .minor   = DCAM_MINOR,
    .name   = "sc8800g_dcam",
    .fops   = &dcam_fops,
};


这样基本上一个设备就可以正常工作了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值