(视频)vivi驱动层代码分析

回顾第二期驱动视频:字符  块  网卡
 app层:open   read    write
____________________________________________


驱动:drv_open drv_read  drv_write

____________________________________________
怎样写驱动:1、构造file_operation:
.open = drv_open
.read = drv_read
   2、告诉内核: register_chrdev(主, file_operation,name)
   3、入口函数
   4、出口函数


第二种方式
   1、分配 cdev 
   2、设置:cdev
   

对于复杂的字符设备驱动程序,引入分层概念,如LCD分层:
分层     fbmem.c  1 file_operation
        2 regiser_chrdev
        3 入口/出口函数(内核已经提供)
———————————————————————————————————
    硬件相关: 1、分配fb_info
      2、设置fb_infor
      3、注册

      4、硬件相关的操作


怎么写分层驱动:
      1、分配某个结构体(不同的设备不同,如lcd为fb_info)
      2、设置
      3、注册
      4、硬件相关操作

vivi.c中的头文件包含:
vivi.c包含头文件v4l2-device.h和v4l2-ioctl.h,其中v4l2-device.h中包含了v4l2-subdev.h,v4l2-subdev.h中又包含了

v4l2-common.h,v4l2-common.h中包含了v4l2-dev.h。vivi.h


在v4l2-dev.h中定义了结构体video_device和v4l2_file_operations;

在v4l2-ioctl.h中定义了结构体v4l2_ioctl_ops;
在v4l2-device.h中定义了结构体v4l2_device;
struct v4l2_capability/v4l2_cropcap/v4l2_crop在/include/linux/videodev2.h定义


结构体包含关系
struct video_device
->vivi_fops (v4l2_file_operations)
->vivi_ioctl_ops (v4l2_ioctl_ops)


构思V4L2框架:


APP            open  write  read  
———————————————————————————————————
核心层          v4l2_dev.c                 1、file_operation   -》》   vdev->cdev = cdev_alloc()
      vdev->cdev->ops = &v4l2_fops (函数)
      cdev_add 
  2、注册                     

———————————————————————————————————
硬件相关             |--- uvc_register_device  不重要   1、分配 video_device
uvc_driver.c |--- video_dev_alloc   2、设置
|--- video_register_device 重要   3、注册:video_register_device


video_register_device最后调用__video_register_device (核心层的)
———————————————————————————————————
/drivers/media/video
虚拟视频驱动分析:
1、分配video_device
2、设置
3、注册:video_register_device  
*************************************************************************************************
vivi_dev *dev //这个设备定义了vivi_dev摄像头驱动的结构体
程序的思路:(1)最重要的是vivi_dev这个抽象出来的设备,即*dev。它其实定义了一个vivi虚拟摄像头设备,其中有相机的照片大  小、v4l2_ctrl结构体、video_device设备等结构体成员。在vivi_init()函数中完成了height width/v4l2_ctrl的 赋值,对于video_device,定义了vfd这个变量,将vivi_template{ .fops = ;. ioctl = ;...}赋值给了vfd。


 (2)video_register_device()函数中完成了对vfd这个video_device这个结构体的赋值,其中主要是对vfd->cdev的赋值
                vdev->cdev = cdev_alloc();
               vdev->cdev->ops = &v4l2_fops;
                 vdev->cdev->owner = owner;
其中:stuct file_operation v4l2_fops = 
{ .owner = ; 
 .read = v4l2_read;

另外一个成员vfd->dev这个成员进行了注册device_register(&vdev->dev);   video_device结构体中包含了cdev和 device dev两个成员变量。


 (3)最后将dev->vfd = vfd; 完成对vivi_dev的赋值。
总结:vivi_dev包含了video_device重要成员,video_device中包含了cdev/dev/*ioctl_ops/*fops(v4l2_file_operateion)成员,
      而cdev中又包含了ops/owner等成员。
     /video_device只是一个vivi_dev摄像头设备的一个重要部分而已。
*************************************************************************************************
/drivers/media/video/vivi.c
vivi_init 
vivi_create_instance          /drivers/media/video/vivi.c
v4l2_device_register  //不是主要的 ,只是用于初始化一些东西,比如自旋锁
video_device_alloc
kzalloc(sizeof(struct video_device),GFP_KERNEL);

//设置
 *vfd = vivi_template;                   //将vivi_tmpplate结构体完全赋值给*vfd(video_device)
     1.vfd:

  .fops = &vivi_fops,

.ioctl_ops    = &vivi_ioctl_ops,
.release      = video_device_release,

     2.
vfd->v4l2_dev = &dev->v4l2_dev;   
***将vivi_device中v4l2_device赋给vfd即video_device的v4l2****

     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);  
            vfd.v4l2_file_operation
             video_register_device(video_device,type:VFL_TYPE_GRABBER,nr)
                         __video_register_device
                                             vdev->cdev = cdev_alloc();
                                              vdev->cdev->ops = &v4l2_fops;
                                              cdev_add 
              dev->vfd = vfd ;    ****将vfd即video_device结构体赋给vivi_dev中的video_device******


                video_device[vdev->minor] = vdev

分析vivi.c的open,read,write,ioctl过程:
1. open
app:       open("/dev/**",);
_____________________________________________
drv:     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_ctrl_handler的使用过程:
    __video_do_ioctl
        struct video_device *vfd = video_devdata(file);


    case VIDIOC_QUERYCTRL:
    {
    struct v4l2_queryctrl *p = arg;
    
    if (vfh && vfh->ctrl_handler)
    ret = v4l2_queryctrl(vfh->ctrl_handler, p);
    else if (vfd->ctrl_handler)  // 在哪设置?在video_register_device
    ret = v4l2_queryctrl(vfd->ctrl_handler, p);
               // 根据ID在ctrl_handler里找到v4l2_ctrl,返回它的值
         
怎样写V4L2驱动:   
1、分配/设置/注册 V4L2_device 、v4l2_device_register,v4l2_device(辅助作用,提供自旋锁)
2、分配:video_device ,video_device_alloc    |
3、设置:a.vfd->v4l2_dev  指向第一步v4l2_device ---------------
                 b.vfd           .fops
                                    .ioctl                    
   app可以通过ioctl来控制
   驱动程序里,谁来接收、存储、提供这些信息。
     属性:v4l2_ctrl结构体
     管理:v4l2_ctrl_handler     (1、用v4l2_ctrl_handler_init初始化)
                                      (2、v4l2_ctrl_new_std/v4l2_ctrl_new_custom来创建v4l2_ctrl,放入链表)
                                          (3、跟vdev关联:v4l2_dev.handler = hd1)
                  (                               video_dev->v4l2_dev =v4l2_dev )
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值