本文共 3721 字,大约阅读时间需要 12 分钟。
开始学习v4l2中camera的架构
app调用v4l2框架,然后v4l2框架再调用具体的驱动
如:在app:open----->v4l2:open------->driver:open
v4l2提供的是一个通用的框架,然后驱动去实现具体的内容。
问题:那么v4l2是怎么调用driver的呢?
这个我们看看相关代码就很清楚了。
//drivers/media/video/v4l2-dev.c
- 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)
相关代码:
- 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);
-
- if (ret)
- goto free_dev;
-
-
- INIT_LIST_HEAD(&dev->vidq.active);
- init_waitqueue_head(&dev->vidq.wq);
-
-
- spin_lock_init(&dev->slock);
- mutex_init(&dev->mutex);
-
- ret = -ENOMEM;
-
- vfd = video_device_alloc();
- if (!vfd)
- goto unreg_dev;
-
- *vfd = dcam_template;
- vfd->debug = debug;
-
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
- if (ret < 0)
- goto rel_vdev;
-
- video_set_drvdata(vfd, dev);
-
-
- for (i = 0; i < ARRAY_SIZE(dcam_qctrl); i++)
- dev->qctl_regs[i] = dcam_qctrl[i].default_value;
-
-
- 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,
- };
-
-
-
-
- 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,
- };
这样基本上一个设备就可以正常工作了。 转载地址:http://pvomi.baihongyu.com/