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

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

上层:

fbmem.c:
    ①file_operations
            open/read/write
    ②register_chardev
    ③入口/出口

硬件相关:

    ①分配fb_info
    ②设置fb_info
    ③注册
    ④硬件相关

如何编写分层驱动程序?

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

V4L2框架

APP:open/read/write

核心层
v4l2_dev.c

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

硬件相关
uvc_driver.c

v4l2_device_register
video_device_alloc
video_register_device
①分配video_device
②
③注册video_device

虚拟视频驱动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;

分析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来获得、设置"某些属性"

怎么写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来设置获得亮度等信息。

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

属性:
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

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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值