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

📄 saa7146_video.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	{		DEB_EE(("VIDIOC_S_CTRL\n"));		err = set_control(fh,arg);		return err;	}	case VIDIOC_G_PARM:	{		struct v4l2_streamparm *parm = arg;		if( parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ) {			return -EINVAL;		}		memset(&parm->parm.capture,0,sizeof(struct v4l2_captureparm));		parm->parm.capture.readbuffers = 1;		// fixme: only for PAL!		parm->parm.capture.timeperframe.numerator = 1;		parm->parm.capture.timeperframe.denominator = 25;		return 0;	}	case VIDIOC_G_FMT:	{		struct v4l2_format *f = arg;		DEB_EE(("VIDIOC_G_FMT\n"));		return g_fmt(fh,f);	}	case VIDIOC_S_FMT:	{		struct v4l2_format *f = arg;		DEB_EE(("VIDIOC_S_FMT\n"));		return s_fmt(fh,f);	}	case VIDIOC_TRY_FMT:	{		struct v4l2_format *f = arg;		DEB_EE(("VIDIOC_TRY_FMT\n"));		return try_fmt(fh,f);	}	case VIDIOC_G_STD:	{		v4l2_std_id *id = arg;		DEB_EE(("VIDIOC_G_STD\n"));		*id = vv->standard->id;		return 0;	}	/* the saa7146 supfhrts (used in conjunction with the saa7111a for example)	   PAL / NTSC / SECAM. if your hardware does not (or does more)	   -- override this function in your extension */	case VIDIOC_ENUMSTD:	{		struct v4l2_standard *e = arg;		if (e->index < 0 )			return -EINVAL;		if( e->index < dev->ext_vv_data->num_stds ) {			DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);			return 0;		}		return -EINVAL;	}	case VIDIOC_S_STD:	{		v4l2_std_id *id = arg;		int found = 0;		int i, err;		DEB_EE(("VIDIOC_S_STD\n"));		if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {			DEB_D(("cannot change video standard while streaming capture is active\n"));			return -EBUSY;		}		if ((vv->video_status & STATUS_OVERLAY) != 0) {			vv->ov_suspend = vv->video_fh;			err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */			if (0 != err) {				DEB_D(("suspending video failed. aborting\n"));				return err;			}		}		down(&dev->lock);		for(i = 0; i < dev->ext_vv_data->num_stds; i++)			if (*id & dev->ext_vv_data->stds[i].id)				break;		if (i != dev->ext_vv_data->num_stds) {			vv->standard = &dev->ext_vv_data->stds[i];			if( NULL != dev->ext_vv_data->std_callback )				dev->ext_vv_data->std_callback(dev, vv->standard);			found = 1;		}		up(&dev->lock);		if (vv->ov_suspend != NULL) {			saa7146_start_preview(vv->ov_suspend);			vv->ov_suspend = NULL;		}		if( 0 == found ) {			DEB_EE(("VIDIOC_S_STD: standard not found.\n"));			return -EINVAL;		}		DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",vv->standard->name));		return 0;	}	case VIDIOC_OVERLAY:	{		int on = *(int *)arg;		int err = 0;		DEB_D(("VIDIOC_OVERLAY on:%d\n",on));		if (on != 0) {			err = saa7146_start_preview(fh);		} else {			err = saa7146_stop_preview(fh);		}		return err;	}	case VIDIOC_REQBUFS: {		struct v4l2_requestbuffers *req = arg;		DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));		return videobuf_reqbufs(q,req);	}	case VIDIOC_QUERYBUF: {		struct v4l2_buffer *buf = arg;		DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));		return videobuf_querybuf(q,buf);	}	case VIDIOC_QBUF: {		struct v4l2_buffer *buf = arg;		int ret = 0;		ret = videobuf_qbuf(q,buf);		DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));		return ret;	}	case VIDIOC_DQBUF: {		struct v4l2_buffer *buf = arg;		int ret = 0;		ret = videobuf_dqbuf(q,buf,file->f_flags & O_NONBLOCK);		DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));		return ret;	}	case VIDIOC_STREAMON: {		int *type = arg;		DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));		err = video_begin(fh);		if( 0 != err) {			return err;		}		err = videobuf_streamon(q);		return err;	}	case VIDIOC_STREAMOFF: {		int *type = arg;		DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));		/* ugly: we need to copy some checks from video_end(),		   because videobuf_streamoff() relies on the capture running.		   check and fix this */		if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {			DEB_S(("not capturing.\n"));			return 0;		}		if (vv->video_fh != fh) {			DEB_S(("capturing, but in another open.\n"));			return -EBUSY;		}		err = videobuf_streamoff(q);		if (0 != err) {			DEB_D(("warning: videobuf_streamoff() failed.\n"));			video_end(fh, file);		} else {			err = video_end(fh, file);		}		return err;	}	case VIDIOCGMBUF:	{		struct video_mbuf *mbuf = arg;		struct videobuf_queue *q;		int i;		/* fixme: number of capture buffers and sizes for v4l apps */		int gbuffers = 2;		int gbufsize = 768*576*4;		DEB_D(("VIDIOCGMBUF \n"));		q = &fh->video_q;		down(&q->lock);		err = videobuf_mmap_setup(q,gbuffers,gbufsize,					  V4L2_MEMORY_MMAP);		if (err < 0) {			up(&q->lock);			return err;		}		memset(mbuf,0,sizeof(*mbuf));		mbuf->frames = gbuffers;		mbuf->size   = gbuffers * gbufsize;		for (i = 0; i < gbuffers; i++)			mbuf->offsets[i] = i * gbufsize;		up(&q->lock);		return 0;	}	default:		return v4l_compat_translate_ioctl(inode,file,cmd,arg,						  saa7146_video_do_ioctl);	}	return 0;}/*********************************************************************************//* buffer handling functions                                                  */static int buffer_activate (struct saa7146_dev *dev,		     struct saa7146_buf *buf,		     struct saa7146_buf *next){	struct saa7146_vv *vv = dev->vv_data;	buf->vb.state = STATE_ACTIVE;	saa7146_set_capture(dev,buf,next);	mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT);	return 0;}static int buffer_prepare(struct videobuf_queue *q,			  struct videobuf_buffer *vb, enum v4l2_field field){	struct file *file = q->priv_data;	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	struct saa7146_buf *buf = (struct saa7146_buf *)vb;	int size,err = 0;	DEB_CAP(("vbuf:%p\n",vb));	/* sanity checks */	if (fh->video_fmt.width  < 48 ||	    fh->video_fmt.height < 32 ||	    fh->video_fmt.width  > vv->standard->h_max_out ||	    fh->video_fmt.height > vv->standard->v_max_out) {		DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));		return -EINVAL;	}	size = fh->video_fmt.sizeimage;	if (0 != buf->vb.baddr && buf->vb.bsize < size) {		DEB_D(("size mismatch.\n"));		return -EINVAL;	}	DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",		fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));	if (buf->vb.width  != fh->video_fmt.width  ||	    buf->vb.bytesperline != fh->video_fmt.bytesperline ||	    buf->vb.height != fh->video_fmt.height ||	    buf->vb.size   != size ||	    buf->vb.field  != field      ||	    buf->vb.field  != fh->video_fmt.field  ||	    buf->fmt       != &fh->video_fmt) {		saa7146_dma_free(dev,buf);	}	if (STATE_NEEDS_INIT == buf->vb.state) {		struct saa7146_format *sfmt;		buf->vb.bytesperline  = fh->video_fmt.bytesperline;		buf->vb.width  = fh->video_fmt.width;		buf->vb.height = fh->video_fmt.height;		buf->vb.size   = size;		buf->vb.field  = field;		buf->fmt       = &fh->video_fmt;		buf->vb.field  = fh->video_fmt.field;		sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);		if( 0 != IS_PLANAR(sfmt->trans)) {			saa7146_pgtable_free(dev->pci, &buf->pt[0]);			saa7146_pgtable_free(dev->pci, &buf->pt[1]);			saa7146_pgtable_free(dev->pci, &buf->pt[2]);			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);			saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);			saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);		} else {			saa7146_pgtable_free(dev->pci, &buf->pt[0]);			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);		}		err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb);		if (err)			goto oops;		err = saa7146_pgtable_build(dev,buf);		if (err)			goto oops;	}	buf->vb.state = STATE_PREPARED;	buf->activate = buffer_activate;	return 0; oops:	DEB_D(("error out.\n"));	saa7146_dma_free(dev,buf);	return err;}static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size){	struct file *file = q->priv_data;	struct saa7146_fh *fh = file->private_data;	if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)		*count = MAX_SAA7146_CAPTURE_BUFFERS;	*size = fh->video_fmt.sizeimage;	/* check if we exceed the "max_memory" parameter */	if( (*count * *size) > (max_memory*1048576) ) {		*count = (max_memory*1048576) / *size;	}	DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));	return 0;}static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb){	struct file *file = q->priv_data;	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	struct saa7146_buf *buf = (struct saa7146_buf *)vb;	DEB_CAP(("vbuf:%p\n",vb));	saa7146_buffer_queue(fh->dev,&vv->video_q,buf);}static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb){	struct file *file = q->priv_data;	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_buf *buf = (struct saa7146_buf *)vb;	DEB_CAP(("vbuf:%p\n",vb));	saa7146_dma_free(dev,buf);}static struct videobuf_queue_ops video_qops = {	.buf_setup    = buffer_setup,	.buf_prepare  = buffer_prepare,	.buf_queue    = buffer_queue,	.buf_release  = buffer_release,};/********************************************************************************//* file operations */static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv){	INIT_LIST_HEAD(&vv->video_q.queue);	init_timer(&vv->video_q.timeout);	vv->video_q.timeout.function = saa7146_buffer_timeout;	vv->video_q.timeout.data     = (unsigned long)(&vv->video_q);	vv->video_q.dev              = dev;	/* set some default values */	vv->standard = &dev->ext_vv_data->stds[0];	/* FIXME: what's this? */	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;	vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;}static int video_open(struct saa7146_dev *dev, struct file *file){	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;	struct saa7146_format *sfmt;	fh->video_fmt.width = 384;	fh->video_fmt.height = 288;	fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;	fh->video_fmt.bytesperline = 0;	fh->video_fmt.field = V4L2_FIELD_ANY;	sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);	fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;	videobuf_queue_init(&fh->video_q, &video_qops,			    dev->pci, &dev->slock,			    V4L2_BUF_TYPE_VIDEO_CAPTURE,			    V4L2_FIELD_INTERLACED,			    sizeof(struct saa7146_buf),			    file);	init_MUTEX(&fh->video_q.lock);	return 0;}static void video_close(struct saa7146_dev *dev, struct file *file){	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;	struct saa7146_vv *vv = dev->vv_data;	int err;	if (IS_CAPTURE_ACTIVE(fh) != 0) {		err = video_end(fh, file);	} else if (IS_OVERLAY_ACTIVE(fh) != 0) {		err = saa7146_stop_preview(fh);	}	/* hmm, why is this function declared void? */	/* return err */}static void video_irq_done(struct saa7146_dev *dev, unsigned long st){	struct saa7146_vv *vv = dev->vv_data;	struct saa7146_dmaqueue *q = &vv->video_q;	spin_lock(&dev->slock);	DEB_CAP(("called.\n"));	/* only finish the buffer if we have one... */	if( NULL != q->curr ) {		saa7146_buffer_finish(dev,q,STATE_DONE);	}	saa7146_buffer_next(dev,q,0);	spin_unlock(&dev->slock);}static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos){	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	ssize_t ret = 0;	DEB_EE(("called.\n"));	if ((vv->video_status & STATUS_CAPTURE) != 0) {		/* fixme: should we allow read() captures while streaming capture? */		if (vv->video_fh == fh) {			DEB_S(("already capturing.\n"));			return -EBUSY;		}		DEB_S(("already capturing in another open.\n"));		return -EBUSY;	}	ret = video_begin(fh);	if( 0 != ret) {		goto out;	}	ret = videobuf_read_one(&fh->video_q , data, count, ppos,				file->f_flags & O_NONBLOCK);	if (ret != 0) {		video_end(fh, file);	} else {		ret = video_end(fh, file);	}out:	/* restart overlay if it was active before */	if (vv->ov_suspend != NULL) {		saa7146_start_preview(vv->ov_suspend);		vv->ov_suspend = NULL;	}	return ret;}struct saa7146_use_ops saa7146_video_uops = {	.init = video_init,	.open = video_open,	.release = video_close,	.irq_done = video_irq_done,	.read = video_read,};

⌨️ 快捷键说明

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