• V4L2框架


    摄像头驱动属于字符驱动。

    应用程序:open/read/write
    驱动程序:drv_open/drv_read/drv_write

    怎么去写驱动:

    ①构造file_operations:
            .open=drv_open
            .read=drv_read
            ...
    ②告诉内核:register_chardev(主设备号,次设备号, file_operations,name);
    //注册字符驱动程序就是把file_operations发到内核中的某个chardev数组中,根据主设备号和次设备号确定放入数组中的位置。
    
        1.分配cdev结构体
        2.设置cdev结构体,设置时,cdev结构体中的某一项=file_operations
        3.cdev_add
    
    ③谁来调用register_chardev,一般是入口函数来调用。
    ④有注册驱动就有对应的卸载驱动,一般利用出口函数进行卸载。在出口函数中调用unregistered_chardev
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    对于复杂的字符驱动:
    分层

    上层:

    fbmem.c:
        ①file_operations
                open/read/write
        ②register_chardev
        ③入口/出口
    
    • 1
    • 2
    • 3
    • 4
    • 5

    硬件相关:

        ①分配fb_info
        ②设置fb_info
        ③注册
        ④硬件相关
    
    • 1
    • 2
    • 3
    • 4

    如何编写分层驱动程序?

    ①分配某结构体(LCD驱动是fb_info结构体)
    ②设置
    ③注册
    ④硬件相关操作
    
    • 1
    • 2
    • 3
    • 4

    V4L2框架

    APP:open/read/write

    核心层
    v4l2_dev.c

    ①file_operations
    ②注册
    cdev_alloc:分配fop结构体
    cdev_ops=v4l2_fops,其中包含open/read/write
    cdev_add
    
    • 1
    • 2
    • 3
    • 4
    • 5

    硬件相关
    uvc_driver.c

    v4l2_device_register
    video_device_alloc
    video_register_device
    ①分配video_device
    ②
    ③注册video_device
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    虚拟视频驱动vivi.c分析:
    1.分配video_device
    2.设置
    3.注册:video_register_device

    vivi_init
        vivi_create_instance
            v4l2_device_register   // 不是主要, 只是用于初始化一些东西,比如自旋锁、引用计数
            video_device_alloc
            // 设置
              1. vfd:
                .fops           = &vivi_fops,
                .ioctl_ops     = &vivi_ioctl_ops,
                .release    = video_device_release,
              2.
                vfd->v4l2_dev = &dev->v4l2_dev;
              3. 设置"ctrl属性"(用于APP的ioctl):
                    v4l2_ctrl_handler_init(hdl, 11);
                    dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
                            V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
                    dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
                            V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
                    dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
                            V4L2_CID_CONTRAST, 0, 255, 1, 16);                        
            video_register_device(video_device, type:VFL_TYPE_GRABBER, nr)//根据类型创建不同的名字,对于不同的类型次设备号也是不一样的
                __video_register_device
                    vdev->cdev = cdev_alloc();
                    vdev->cdev->ops = &v4l2_fops;
                    cdev_add
                    
                    video_device[vdev->minor] = vdev;//根据次设备号将vdev放入数组
    
                    if (vdev->ctrl_handler == NULL)
                        vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    分析vivi.c的open,read,write,ioctl过程

    1. open
    app:     open("/dev/video0",....)
    ---------------------------------------------------
    drv:     v4l2_fops.v4l2_open
                vdev = video_devdata(filp);  // 根据次设备号从数组中得到video_device
                ret = vdev->fops->open(filp);
                            vivi_ioctl_ops.open
                                v4l2_fh_open
    
    2. read
    app:    read ....
    ---------------------------------------------------
    drv:    v4l2_fops.v4l2_read
                struct video_device *vdev = video_devdata(filp);
                ret = vdev->fops->read(filp, buf, sz, off);
    
    3. ioctl
    app:   ioctl
    ----------------------------------------------------
    drv:   v4l2_fops.unlocked_ioctl
                v4l2_ioctl
                    struct video_device *vdev = video_devdata(filp);
                    ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
                                video_ioctl2
                                    video_usercopy(file, cmd, arg, __video_do_ioctl);
                                        __video_do_ioctl
                                            struct video_device *vfd = video_devdata(file);
                                            根据APP传入的cmd来获得、设置"某些属性"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    怎么写V4L2的驱动?

       ①分配/设置/注册 v4l2_device:v4l2_device_register得到v4l2_device(辅助作用,提供自旋锁和计数量)。
        ②分配videv_device:video_device_alloc
        ③设置vfd(videv_device):a.vfd->v4l2_dev指向v4l2_device.
                                                 b.vfd:
                                                            .fops=...中的open/read/write 被上层的v4l2_fops调用
                                                            .ioctl_ops=
                                                  c.APP可以通过ioctl来设置获得亮度等信息。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    驱动程序里,谁来接收/存储/设置到硬件/提供这些信息

    属性:
    v4l2_ctrl

    管理:

     v4l2_ctrl_handler
    ①v4l2_ctrl_handler_init(初始化)
    ②创建以下v4l2_ctrl,放入v4l2_ctrl_handler链表
       v4l2_ctrl_new_std
       v4l2_ctrl_new_custom
    ③跟vdev关联
       v4l2_dev.ctrl_handler = hal
       video_dev->v4l2_dev= v4l2_dev
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    本文章源于百问网韦东山嵌入式

  • 相关阅读:
    C语言扫雷游戏完整实现(上)
    【测试开发】用例篇 · 熟悉黑盒测试用例设计方法(2)· 正交表 · 场景设计 · 常见案例练习
    如何创建 robots.txt 文件?
    什么时候不要采用微服务架构
    Java进阶(垃圾回收GC)——理论篇:JVM内存模型 & 垃圾回收定位清除算法 & JVM中的垃圾回收器
    Learning Tone Curves for Local Image Enhancement
    武汉凯迪正大—线圈匝间耐压测试仪
    【AGC】如何快速部署Serverless抽奖模板
    制作手机IOS苹果ipa应用的重签名工具
    centos7部署Nginx和RabbitMQ
  • 原文地址:https://blog.csdn.net/qq_44823010/article/details/126947936