• 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

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

  • 相关阅读:
    webpack5基础--03_开发模式介绍
    windows10上使用Visual Studio对树莓派进行交叉编译示例
    携创教育:学位证和毕业证有什么区别?自考怎么申请学位证?
    论文:Few-shot Named Entity Recognition with Self-describing Networks
    智慧城市项目建设介绍
    docker搭建Elasticsearch、Kibana、Logstash 同步mysql数据到ES
    C++用条件变量实现线程安全的queue容器
    数据结构学习:链表
    Kafka:安装与简单使用
    linux下应用开发之按键信号结束线程
  • 原文地址:https://blog.csdn.net/qq_44823010/article/details/126947936