v4l2,camera笔记

本文探讨了V4L2(Video for Linux 2)如何作为通用框架调用具体的camera驱动,通过分析代码揭示V4L2如何在应用程序与驱动之间建立连接,特别关注open操作流程及driver的初始化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     开始学习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);
//初始化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,
};



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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值