v4l2-core中v4l2-dev注册玩耍

近日游玩看了v4l2-core相关的v4l2-dev.c,uvc_v4l2.c有些想法,特写下.
#ifndef _V4L2_DEVICE_H
#define _V4L2_DEVICE_H

struct v4l2_file_operations
{
	struct module*owner;
	size_t (*read)(struct file*,char __user*,size_t ,loff_t*);
	size_t (*write)(struct file*,char __user*,size_t ,loff_t*);
	unsigned int (*poll)(struct file*,struct poll_table_struct*);
	long (*unlocked_ioctl)(struct file*,unsigned int,unsigned long);
	int (*mmap)(struct file*,struct vm_area_struct*);
	int (*open)(struct file*);
	int (*release)(struct file*);
};

struct v4l2_ioctl_ops
{
	int (*videoc_reqbufs)(struct file*file,void*fh,struct v4l2_requestbuffers*b);
	int (*videoc_querybuf)(struct file*file,void*fh,struct v4l2_buffer*b);
	int (*videoc_qbuf)(struct file*file,void*fh,struct v4l2_buffer*b);
	int (*vidioc_dqbuf)(struct file*file,void*fh,struct v4l2_buffer*b);


	int (*vidioc_streamon)(struct file*file,void*fh,enum v4l2_buf_type i);
	int (*vidioc_streamoff)(struct file*file,void*fh,enum v4l2_buf_type i);

	int (*vidioc_subcribe_event)(struct v4l2_fh*fh,const struct v4l2_event_subscription*sub);
	int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh,const struct v4l2_event_subscription *sub);
	
};

struct video_device
{
	struct cdev*cdev;
    const struct v4l2_file_operations*fops;
	struct device dev;// v4l device 
	char name[32];
	int minor;
	int num;
	unsigned long flags;
	int index;
	spinlock_t fh_lock;
	void (*release)(struct video_device*vdev);
	const struct v4l2_ioctl_ops*ioctl_ops;
};

struct uvc_device
{
	struct video_device vdev;
};

#define VFL_TYPE_GRABBER 0 


extern int video_register_device(struct video_device*vdev,int type,int nr);
extern void video_unregister_device(struct video_device*vdev);
#endif 
#include "common.h"

static struct uvc_device*uvc_device = NULL;

#define VIDEO_MAJOR 81 
#define VIDEO_NUM_DEVICES 256
#define VIDEO_NAME        "video4linux"

#define to_video_device(cd) container_of(cd,struct video_device,dev)


static struct video_device*video_device[VIDEO_NUM_DEVICES];
static dev_t dev = MKDEV(VIDEO_MAJOR, 0);

struct video_device*video_devdata(struct file*file)
{
   return video_device[iminor(file_inode(file))];
}
	

static struct class video_class = {
	.name = VIDEO_NAME,
	//.dev_groups = video_device_groups,
};

static ssize_t v4l2_read(struct file*filp,char __user*buf,size_t sz,
loff_t*off)
{
   int ret = -ENODEV;
   struct video_device*vdev = video_devdata(filp);
   if(!vdev->fops->read)
   {
	   printk("v4l2_read\n");
	   return -EINVAL;
   }
   printk("v4l2_read 36\n");
   ret = vdev->fops->read(filp,buf,sz,off);
   return ret;
}

static ssize_t v4l2_write(struct file*filp,const char __user*buf,
       size_t sz,loff_t*off)
{
	struct video_device*vdev = video_devdata(filp);
	int ret = -ENODEV;
	
	if(!vdev->fops->write)
	return -EINVAL;
    
	printk("v4l2_write 50\n");
	ret = vdev->fops->write(filp,buf,sz,off);
	return ret;
}

static unsigned v4l2_poll(struct file *file, poll_table *wait)
{
	struct video_device*vdev = video_devdata(file);
	unsigned int res = POLLERR | POLLHUP;
	if(!vdev->fops->poll)
	return DEFAULT_POLLMASK;

    res = vdev->fops->poll(file,wait);
	return res;
}

static long v4l2_ioctl(struct file*filp,unsigned int cmd,unsigned long arg)
{
	struct video_device *vdev = video_devdata(filp);
	int ret = -ENODEV;
	
	if(vdev->fops->unlocked_ioctl)
	{
		ret = vdev->fops->unlocked_ioctl(filp,cmd,arg);
	}
	else 
	{
		ret = -ENOTTY;
	}
    return ret;
}

static int v4l2_open(struct inode*inode,struct file*filp)
{
	struct video_device*vdev;
	int ret = 0;
	vdev = video_devdata(filp);
	printk("v4l2_open 87\n");
    if(vdev->fops->open)
	{
	   ret = vdev->fops->open(filp);
	}
	else 
	{
	   ret = -ENODEV;
	}
    return ret;
}

static int v4l2_mmap(struct file*filp,struct vm_area_struct*vm)
{
	struct video_device*vdev = video_devdata(filp);
	int ret = -ENODEV;
	
	if(!vdev->fops->mmap)
	return -ENODEV;
    ret = vdev->fops->mmap(filp,vm);
	return ret;
}

static int v4l2_release(struct inode*inode,struct file*filp)
{
    struct video_device*vdev = video_devdata(filp);
    int ret = 0;
	if(vdev->fops->release)
	   ret = vdev->fops->release(filp);
    return 0;
}
static const struct file_operations v4l2_fops = 
{
   .owner = THIS_MODULE,
   .read  = v4l2_read,
   .write = v4l2_write,
   .open  = v4l2_open,
   .mmap  = v4l2_mmap,
   .unlocked_ioctl = v4l2_ioctl,
   .release = v4l2_release,
   .poll  = v4l2_poll,   
};

static int uvc_v4l2_open(struct file*file)
{
	struct video_device*vdev = video_devdata(file);
	printk("uvc_v4l2_open 133\n");
    return 0;
}

static int uvc_v4l2_release(struct file*file)
{
	struct video_device *vdev = video_devdata(file);
	printk("uvc_v4l2_release 140\n");
	return 0;
}

static int uvc_v4l2_mmap(struct file*file,struct vm_area_struct*vm)
{
	struct video_device *vdev = video_devdata(file);
	printk("uvc_v4l2_mmap 147\n");
	return 0;
}


static unsigned uvc_v4l2_poll(struct file *file, poll_table *wait)
{
	struct video_device*vdev = video_devdata(file);
	
	printk("uvc_v4l2_poll  155\n");
	return 0;
}

const struct v4l2_file_operations uvc_v4l2_fops = 
{
	.owner = THIS_MODULE,
	.open  = uvc_v4l2_open,
	.release = uvc_v4l2_release,
	//.unlocked_ioctl = video_ioctl2,
	.mmap  = uvc_v4l2_mmap,
	.poll = uvc_v4l2_poll,
};

static void v4l2_device_release(struct device*d)
{
	struct video_device*vdev = to_video_device(d);
	video_device[vdev->minor] = NULL;
	printk("vdev->minor is %d\n",vdev->minor);
	cdev_del(vdev->cdev);
	vdev->cdev = NULL;
}

int video_register_device(struct video_device*vdev,int type,int nr)
{
	int ret; 
	int minor_offset = 0;
	int minr_cnt = 64;
	const char*name_base;
	
	vdev->minor  = -1;
	name_base = "video";
	vdev->cdev = NULL;
	vdev->minor = nr -1;
	vdev->num = nr-1;
	video_device[vdev->minor] = vdev;
	vdev->cdev = cdev_alloc();
	if (vdev->cdev == NULL) {
		ret = -ENOMEM;
	    return ret;
	}
	vdev->cdev->ops = &v4l2_fops;
	ret = cdev_add(vdev->cdev,MKDEV(VIDEO_MAJOR,vdev->minor),1);
	if (ret < 0)
	{
		printk("%s: cdev_add failed\n", __func__);
		kfree(vdev->cdev);
		vdev->cdev = NULL;
        return ret;
	}
	
	vdev->dev.class = &video_class;
	vdev->dev.devt = MKDEV(VIDEO_MAJOR,vdev->minor);
	printk("vdev->num is %d\n",vdev->num);
	dev_set_name(&vdev->dev,"%s%d",name_base,vdev->num);
	ret = device_register(&vdev->dev);
	vdev->dev.release = v4l2_device_release;
	return 0;
}

void video_unregister_device(struct video_device*vdev)
{
	printk("video_unregister_device 77\n");
	device_unregister(&vdev->dev);
	class_unregister(&video_class);
    unregister_chrdev_region(dev,VIDEO_NUM_DEVICES);	
}

static int videodev_init(void)
{
   int ret;
   	printk("register_chrdev_region Linux video capture interface: v2.00\n");
	ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME);
	if (ret < 0) {
		printk("videodev: unable to get major %d\n",VIDEO_MAJOR);
		return ret;
	}
	
	ret = class_register(&video_class);
	if (ret < 0) {
		unregister_chrdev_region(dev, VIDEO_NUM_DEVICES);
		printk("video_dev: class_register failed\n");
		return -EIO;
	}
   return 0;
}
static int __init globalmem_platform_init(void)
{
	uvc_device = kzalloc(sizeof(*uvc_device),GFP_KERNEL);
	if(uvc_device == NULL)
	{
		return -ENOMEM;
	}

	videodev_init();
	
	uvc_device->vdev.fops = &uvc_v4l2_fops;
	uvc_device->vdev.ioctl_ops = NULL;
	video_register_device(&uvc_device->vdev,VFL_TYPE_GRABBER,1);
	
	return 0;  
}

static void __exit globalmem_platform_exit(void)
{ 
	video_unregister_device(&uvc_device->vdev);
	kfree(uvc_device);
	return ;	
}

module_init(globalmem_platform_init);
module_exit(globalmem_platform_exit);
MODULE_LICENSE("GPL");

在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天6点半起床10点半睡觉和今天早晚运动

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值