⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vivi.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 3 页
字号:
		unsigned int index;		index = f->index;		type  = f->type;		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			ret=-EINVAL;			break;		}		switch (type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:			if (index > 0){				ret=-EINVAL;				break;			}			memset(f,0,sizeof(*f));			f->index = index;			f->type  = type;			strlcpy(f->description,format.name,sizeof(f->description));			f->pixelformat = format.fourcc;			break;		default:			ret=-EINVAL;		}		break;	}	case VIDIOC_G_FMT:	{		struct v4l2_format *f = (struct v4l2_format *)arg;		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			ret=-EINVAL;			break;		}		memset(&f->fmt.pix,0,sizeof(f->fmt.pix));		f->fmt.pix.width        = fh->width;		f->fmt.pix.height       = fh->height;		f->fmt.pix.field        = fh->vb_vidq.field;		f->fmt.pix.pixelformat  = fh->fmt->fourcc;		f->fmt.pix.bytesperline =			(f->fmt.pix.width * fh->fmt->depth) >> 3;		f->fmt.pix.sizeimage =			f->fmt.pix.height * f->fmt.pix.bytesperline;		break;	}	case VIDIOC_S_FMT:	{		struct v4l2_format *f = arg;		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			dprintk(1,"Only capture supported.\n");			ret=-EINVAL;			break;		}		ret = vivi_try_fmt(dev,fh,f);		if (ret < 0)			break;		fh->fmt           = &format;		fh->width         = f->fmt.pix.width;		fh->height        = f->fmt.pix.height;		fh->vb_vidq.field = f->fmt.pix.field;		fh->type          = f->type;		break;	}	case VIDIOC_TRY_FMT:	{		struct v4l2_format *f = arg;		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			ret=-EINVAL;			break;		}		ret=vivi_try_fmt(dev,fh,f);		break;	}	case VIDIOC_REQBUFS:		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			ret=-EINVAL;			break;		}		ret=videobuf_reqbufs(&fh->vb_vidq, arg);		break;	case VIDIOC_QUERYBUF:		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			ret=-EINVAL;			break;		}		ret=videobuf_querybuf(&fh->vb_vidq, arg);		break;	case VIDIOC_QBUF:		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			ret=-EINVAL;			break;		}		ret=videobuf_qbuf(&fh->vb_vidq, arg);		break;	case VIDIOC_DQBUF:		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			ret=-EINVAL;			break;		}		ret=videobuf_dqbuf(&fh->vb_vidq, arg,					file->f_flags & O_NONBLOCK);		break;#ifdef HAVE_V4L1	/* --- streaming capture ------------------------------------- */	case VIDIOCGMBUF:	{		struct video_mbuf *mbuf = arg;		struct videobuf_queue *q=&fh->vb_vidq;		struct v4l2_requestbuffers req;		unsigned int i;		memset(&req,0,sizeof(req));		req.type   = q->type;		req.count  = 8;		req.memory = V4L2_MEMORY_MMAP;		ret = videobuf_reqbufs(q,&req);		if (ret < 0)			break;		memset(mbuf,0,sizeof(*mbuf));		mbuf->frames = req.count;		mbuf->size   = 0;		for (i = 0; i < mbuf->frames; i++) {			mbuf->offsets[i]  = q->bufs[i]->boff;			mbuf->size       += q->bufs[i]->bsize;		}		break;	}#endif	case VIDIOC_STREAMON:	{		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		if (!res_get(dev,fh))			return -EBUSY;		ret=videobuf_streamon(&fh->vb_vidq);		break;	}	case VIDIOC_STREAMOFF:	{		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {			ret=-EINVAL;			break;		}		ret = videobuf_streamoff(&fh->vb_vidq);		if (ret < 0)			break;		res_free(dev,fh);		break;	}	/* ---------- tv norms ---------- */	case VIDIOC_ENUMSTD:	{		struct v4l2_standard *e = arg;		if (e->index>0) {			ret=-EINVAL;			break;		}		ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M");		/* Allows vivi to use different fps from video std */		e->frameperiod.numerator = WAKE_NUMERATOR;		e->frameperiod.denominator = WAKE_DENOMINATOR;		break;	}	case VIDIOC_G_STD:	{		v4l2_std_id *id = arg;		*id = V4L2_STD_NTSC_M;		break;	}	case VIDIOC_S_STD:	{		break;	}	/* ------ input switching ---------- */	case VIDIOC_ENUMINPUT:	{ /* only one input in this sample driver */		struct v4l2_input *inp = arg;		if (inp->index != 0) {			ret=-EINVAL;			break;		}		memset(inp, 0, sizeof(*inp));		inp->index = 0;		inp->type = V4L2_INPUT_TYPE_CAMERA;		inp->std = V4L2_STD_NTSC_M;		strcpy(inp->name,"Camera");		break;	}	case VIDIOC_G_INPUT:	{		unsigned int *i = arg;		*i = 0;		break;	}	case VIDIOC_S_INPUT:	{		unsigned int *i = arg;		if (*i > 0)			ret=-EINVAL;		break;	}	/* --- controls ---------------------------------------------- */	case VIDIOC_QUERYCTRL:	{		struct v4l2_queryctrl *qc = arg;		int i;		for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)			if (qc->id && qc->id == vivi_qctrl[i].id) {				memcpy(qc, &(vivi_qctrl[i]),					sizeof(*qc));				break;			}		ret=-EINVAL;		break;	}	case VIDIOC_G_CTRL:	{		struct v4l2_control *ctrl = arg;		int i;		for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)			if (ctrl->id == vivi_qctrl[i].id) {				ctrl->value=qctl_regs[i];				break;			}		ret=-EINVAL;		break;	}	case VIDIOC_S_CTRL:	{		struct v4l2_control *ctrl = arg;		int i;		for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)			if (ctrl->id == vivi_qctrl[i].id) {				if (ctrl->value <					vivi_qctrl[i].minimum					|| ctrl->value >					vivi_qctrl[i].maximum) {						ret=-ERANGE;						break;					}				qctl_regs[i]=ctrl->value;				break;			}		ret=-EINVAL;		break;	}	default:		ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl);	}	if (debug) {		if (ret<0) {			v4l_print_ioctl("vivi(err)", cmd);			dprintk(1,"errcode=%d\n",ret);		} else if (_IOC_DIR(cmd) & _IOC_READ)			v4l_printk_ioctl_arg("vivi(r)",cmd, arg);	}	return ret;}static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl);}/* ------------------------------------------------------------------	File operations for the device   ------------------------------------------------------------------*/#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8)static int vivi_open(struct inode *inode, struct file *file){	int minor = iminor(inode);	struct vivi_dev *h,*dev = NULL;	struct vivi_fh *fh;	struct list_head *list;	enum v4l2_buf_type type = 0;	int i;	printk(KERN_DEBUG "vivi: open called (minor=%d)\n",minor);	list_for_each(list,&vivi_devlist) {		h = list_entry(list, struct vivi_dev, vivi_devlist);		if (h->video_dev.minor == minor) {			dev  = h;			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		}	}	if (NULL == dev)		return -ENODEV;#if 0 /* Avoids an oops at read() - seems to be semaphore related */	if (dev->users) {		printk(KERN_INFO "this driver can be opened only once (users=%d)\n",dev->users);		return -EBUSY;	}#endif	/* If more than one user, mutex should be added */	dev->users++;	dprintk(1,"open minor=%d type=%s users=%d\n",				minor,v4l2_type_names[type],dev->users);	/* allocate + initialize per filehandle data */	fh = kzalloc(sizeof(*fh),GFP_KERNEL);	if (NULL == fh) {		dev->users--;		return -ENOMEM;	}	file->private_data = fh;	fh->dev      = dev;	fh->type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;	fh->fmt      = &format;	fh->width    = 640;	fh->height   = 480;	/* Put all controls at a sane state */	for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)		qctl_regs[i] =vivi_qctrl[i].default_value;	dprintk(1,"Open: fh=0x%08lx, dev=0x%08lx, dev->vidq=0x%08lx\n",		(unsigned long)fh,(unsigned long)dev,(unsigned long)&dev->vidq);	dprintk(1,"Open: list_empty queued=%d\n",list_empty(&dev->vidq.queued));	dprintk(1,"Open: list_empty active=%d\n",list_empty(&dev->vidq.active));	/* Resets frame counters */	dev->h=0;	dev->m=0;	dev->s=0;	dev->us=0;	dev->jiffies=jiffies;	sprintf(dev->timestr,"%02d:%02d:%02d:%03d",			dev->h,dev->m,dev->s,(dev->us+500)/1000);	videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops,			NULL, NULL,			fh->type,			V4L2_FIELD_INTERLACED,			sizeof(struct vivi_buffer),fh);	return 0;}static ssize_tvivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos){	struct vivi_fh *fh = file->private_data;	if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {		if (res_locked(fh->dev))			return -EBUSY;		return videobuf_read_one(&fh->vb_vidq, data, count, ppos,					file->f_flags & O_NONBLOCK);	}	return 0;}static unsigned intvivi_poll(struct file *file, struct poll_table_struct *wait){	struct vivi_fh *fh = file->private_data;	struct vivi_buffer *buf;	dprintk(1,"%s\n",__FUNCTION__);	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)		return POLLERR;	if (res_get(fh->dev,fh)) {		dprintk(1,"poll: mmap interface\n");		/* streaming capture */		if (list_empty(&fh->vb_vidq.stream))			return POLLERR;		buf = list_entry(fh->vb_vidq.stream.next,struct vivi_buffer,vb.stream);	} else {		dprintk(1,"poll: read() interface\n");		/* read() capture */		buf = (struct vivi_buffer*)fh->vb_vidq.read_buf;		if (NULL == buf)			return POLLERR;	}	poll_wait(file, &buf->vb.done, wait);	if (buf->vb.state == STATE_DONE ||	    buf->vb.state == STATE_ERROR)		return POLLIN|POLLRDNORM;	return 0;}static int vivi_release(struct inode *inode, struct file *file){	struct vivi_fh  *fh     = file->private_data;	struct vivi_dev *dev    = fh->dev;	struct vivi_dmaqueue *vidq = &dev->vidq;	int minor = iminor(inode);	vivi_stop_thread(vidq);	videobuf_mmap_free(&fh->vb_vidq);	kfree (fh);	dev->users--;	printk(KERN_DEBUG "vivi: close called (minor=%d, users=%d)\n",minor,dev->users);	return 0;}static intvivi_mmap(struct file *file, struct vm_area_struct * vma){	struct vivi_fh *fh = file->private_data;	int ret;	dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma);	ret=videobuf_mmap_mapper(&fh->vb_vidq, vma);	dprintk (1,"vma start=0x%08lx, size=%ld, ret=%d\n",		(unsigned long)vma->vm_start,		(unsigned long)vma->vm_end-(unsigned long)vma->vm_start,		ret);	return ret;}static struct file_operations vivi_fops = {	.owner		= THIS_MODULE,	.open           = vivi_open,	.release        = vivi_release,	.read           = vivi_read,	.poll		= vivi_poll,	.ioctl          = vivi_ioctl,	.mmap		= vivi_mmap,	.llseek         = no_llseek,};static struct video_device vivi = {	.name		= "VTM Virtual Video Capture Board",	.type		= VID_TYPE_CAPTURE,	.hardware	= 0,	.fops           = &vivi_fops,	.minor		= -1,//	.release	= video_device_release,};/* ------------------------------------------------------------------	Initialization and module stuff   ------------------------------------------------------------------*/static int __init vivi_init(void){	int ret;	struct vivi_dev *dev;	dev = kzalloc(sizeof(*dev),GFP_KERNEL);	if (NULL == dev)		return -ENOMEM;	list_add_tail(&dev->vivi_devlist,&vivi_devlist);	/* init video dma queues */	INIT_LIST_HEAD(&dev->vidq.active);	INIT_LIST_HEAD(&dev->vidq.queued);	/* initialize locks */	init_MUTEX(&dev->lock);	dev->vidq.timeout.function = vivi_vid_timeout;	dev->vidq.timeout.data     = (unsigned long)dev;	init_timer(&dev->vidq.timeout);	ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr);	printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret);	return ret;}static void __exit vivi_exit(void){	struct vivi_dev *h;	struct list_head *list;	list_for_each(list,&vivi_devlist) {		h = list_entry(list, struct vivi_dev, vivi_devlist);		kfree (h);	}	video_unregister_device(&vivi);}module_init(vivi_init);module_exit(vivi_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -