虚拟视频驱动vivi.c分析(linux-3.4.2版本)

时间:2021-03-05 23:34:09

参考韦东山老师视频:


虚拟视频驱动vivi.c分析(linux-3.4.2版本):

vivi_init
     vivi_create_instance(i);
{
struct vivi_dev *dev;
struct video_device *vfd;
struct v4l2_ctrl_handler *hdl;


        // 不是主要, 只是用于初始化一些东西,比如自旋锁、引用计数
v4l2_device_register(NULL, &dev->v4l2_dev);


        vfd = video_device_alloc();
*vfd = vivi_template;        //设置
   1. vfd:
            .fops           = &vivi_fops,
            .ioctl_ops = &vivi_ioctl_ops,
            .release = video_device_release,
vfd->v4l2_dev = &dev->v4l2_dev;


//设置"ctrl属性"(用于APP的ioctl):
hdl = &dev->ctrl_handler;
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(vfd, VFL_TYPE_GRABBER, video_nr);
__video_register_device(video_device vdev, type, nr, 1, vdev->fops->owner);
vdev->cdev = cdev_alloc();
vdev->cdev->ops = &v4l2_fops;
cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR:81, vdev->minor), 1);


device_register(&vdev->dev);

video_device[vdev->minor] = vdev;


if (vdev->ctrl_handler == NULL)    //设置ctrl_handler;
           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_fops.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 (v4l2-ioctl.c中)
                                video_usercopy(file, cmd, arg, __video_do_ioctl);
                                    __video_do_ioctl(*file,cmd, *arg);
                                        struct video_device *vfd = video_devdata(file);
                                        根据APP传入的cmd来获得、设置"某些属性"


v4l2_ctrl_handler的使用过程:
    __video_do_ioctl(*file,cmd, *arg);
        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);
          find_ref(hdl, id);// 根据ID在ctrl_handler里找到v4l2_ctrl,返回它的值