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

📄 em28xx-video.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		struct v4l2_standard *e = arg;		unsigned int i;		i = e->index;		if (i >= TVNORMS)			return -EINVAL;		ret = v4l2_video_std_construct(e, tvnorms[e->index].id,						tvnorms[e->index].name);		e->index = i;		if (ret < 0)			return ret;		return 0;	}	case VIDIOC_G_STD:	{		v4l2_std_id *id = arg;		*id = dev->tvnorm->id;		return 0;	}	case VIDIOC_S_STD:	{		v4l2_std_id *id = arg;		unsigned int i;		for (i = 0; i < TVNORMS; i++)			if (*id == tvnorms[i].id)				break;		if (i == TVNORMS)			for (i = 0; i < TVNORMS; i++)				if (*id & tvnorms[i].id)					break;		if (i == TVNORMS)			return -EINVAL;		mutex_lock(&dev->lock);		dev->tvnorm = &tvnorms[i];		em28xx_set_norm(dev, dev->width, dev->height);		em28xx_i2c_call_clients(dev, VIDIOC_S_STD,					&dev->tvnorm->id);		mutex_unlock(&dev->lock);		return 0;	}	/* ------ input switching ---------- */	case VIDIOC_ENUMINPUT:	{		struct v4l2_input *i = arg;		unsigned int n;		static const char *iname[] = {			[EM28XX_VMUX_COMPOSITE1] = "Composite1",			[EM28XX_VMUX_COMPOSITE2] = "Composite2",			[EM28XX_VMUX_COMPOSITE3] = "Composite3",			[EM28XX_VMUX_COMPOSITE4] = "Composite4",			[EM28XX_VMUX_SVIDEO] = "S-Video",			[EM28XX_VMUX_TELEVISION] = "Television",			[EM28XX_VMUX_CABLE] = "Cable TV",			[EM28XX_VMUX_DVB] = "DVB",			[EM28XX_VMUX_DEBUG] = "for debug only",		};		n = i->index;		if (n >= MAX_EM28XX_INPUT)			return -EINVAL;		if (0 == INPUT(n)->type)			return -EINVAL;		memset(i, 0, sizeof(*i));		i->index = n;		i->type = V4L2_INPUT_TYPE_CAMERA;		strcpy(i->name, iname[INPUT(n)->type]);		if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||			(EM28XX_VMUX_CABLE == INPUT(n)->type))			i->type = V4L2_INPUT_TYPE_TUNER;		for (n = 0; n < ARRAY_SIZE(tvnorms); n++)			i->std |= tvnorms[n].id;		return 0;	}	case VIDIOC_G_INPUT:	{		int *i = arg;		*i = dev->ctl_input;		return 0;	}	case VIDIOC_S_INPUT:	{		int *index = arg;		if (*index >= MAX_EM28XX_INPUT)			return -EINVAL;		if (0 == INPUT(*index)->type)			return -EINVAL;		mutex_lock(&dev->lock);		video_mux(dev, *index);		mutex_unlock(&dev->lock);		return 0;	}	case VIDIOC_G_AUDIO:	{		struct v4l2_audio *a = arg;		unsigned int index = a->index;		if (a->index > 1)			return -EINVAL;		memset(a, 0, sizeof(*a));		index = dev->ctl_ainput;		if (index == 0) {			strcpy(a->name, "Television");		} else {			strcpy(a->name, "Line In");		}		a->capability = V4L2_AUDCAP_STEREO;		a->index = index;		return 0;	}	case VIDIOC_S_AUDIO:	{		struct v4l2_audio *a = arg;		if (a->index != dev->ctl_ainput)			return -EINVAL;		return 0;	}	/* --- controls ---------------------------------------------- */	case VIDIOC_QUERYCTRL:	{		struct v4l2_queryctrl *qc = arg;		int i, id=qc->id;		memset(qc,0,sizeof(*qc));		qc->id=id;		if (!dev->has_msp34xx) {			for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {				if (qc->id && qc->id == em28xx_qctrl[i].id) {					memcpy(qc, &(em28xx_qctrl[i]),					sizeof(*qc));					return 0;				}			}		}		em28xx_i2c_call_clients(dev,cmd,qc);		if (qc->type)			return 0;		else			return -EINVAL;	}	case VIDIOC_G_CTRL:	{		struct v4l2_control *ctrl = arg;		int retval=-EINVAL;		if (!dev->has_msp34xx)			retval=em28xx_get_ctrl(dev, ctrl);		if (retval==-EINVAL) {			em28xx_i2c_call_clients(dev,cmd,arg);			return 0;		} else return retval;	}	case VIDIOC_S_CTRL:	{		struct v4l2_control *ctrl = arg;		u8 i;		if (!dev->has_msp34xx){			for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {				if (ctrl->id == em28xx_qctrl[i].id) {					if (ctrl->value <					em28xx_qctrl[i].minimum					|| ctrl->value >					em28xx_qctrl[i].maximum)						return -ERANGE;					return em28xx_set_ctrl(dev, ctrl);				}			}		}		em28xx_i2c_call_clients(dev,cmd,arg);		return 0;	}	/* --- tuner ioctls ------------------------------------------ */	case VIDIOC_G_TUNER:	{		struct v4l2_tuner *t = arg;		if (0 != t->index)			return -EINVAL;		memset(t, 0, sizeof(*t));		strcpy(t->name, "Tuner");		mutex_lock(&dev->lock);		/* let clients fill in the remainder of this struct */		em28xx_i2c_call_clients(dev, cmd, t);		mutex_unlock(&dev->lock);		em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal,				t->afc);		return 0;	}	case VIDIOC_S_TUNER:	{		struct v4l2_tuner *t = arg;		if (0 != t->index)			return -EINVAL;		mutex_lock(&dev->lock);		/* let clients handle this */		em28xx_i2c_call_clients(dev, cmd, t);		mutex_unlock(&dev->lock);		return 0;	}	case VIDIOC_G_FREQUENCY:	{		struct v4l2_frequency *f = arg;		memset(f, 0, sizeof(*f));		f->type = V4L2_TUNER_ANALOG_TV;		f->frequency = dev->ctl_freq;		return 0;	}	case VIDIOC_S_FREQUENCY:	{		struct v4l2_frequency *f = arg;		if (0 != f->tuner)			return -EINVAL;		if (V4L2_TUNER_ANALOG_TV != f->type)			return -EINVAL;		mutex_lock(&dev->lock);		dev->ctl_freq = f->frequency;		em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f);		mutex_unlock(&dev->lock);		return 0;	}	case VIDIOC_CROPCAP:	{		struct v4l2_cropcap *cc = arg;		if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		cc->bounds.left = 0;		cc->bounds.top = 0;		cc->bounds.width = dev->width;		cc->bounds.height = dev->height;		cc->defrect = cc->bounds;		cc->pixelaspect.numerator = 54;	/* 4:3 FIXME: remove magic numbers */		cc->pixelaspect.denominator = 59;		return 0;	}	case VIDIOC_STREAMON:	{		int *type = arg;		if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE			|| dev->io != IO_MMAP)			return -EINVAL;		if (list_empty(&dev->inqueue))			return -EINVAL;		dev->stream = STREAM_ON;	/* FIXME: Start video capture here? */		em28xx_videodbg("VIDIOC_STREAMON: starting stream\n");		return 0;	}	case VIDIOC_STREAMOFF:	{		int *type = arg;		int ret;		if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE			|| dev->io != IO_MMAP)			return -EINVAL;		if (dev->stream == STREAM_ON) {			em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n");			if ((ret = em28xx_stream_interrupt(dev)))				return ret;		}		em28xx_empty_framequeues(dev);		return 0;	}	default:		return v4l_compat_translate_ioctl(inode, filp, cmd, arg,						  driver_ioctl);	}	return 0;}/* * em28xx_v4l2_do_ioctl() * This function is _not_ called directly, but from * em28xx_v4l2_ioctl. Userspace * copying is done already, arg is a kernel pointer. */static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp,				 unsigned int cmd, void *arg){	struct em28xx *dev = filp->private_data;	if (!dev)		return -ENODEV;	if (video_debug > 1)		v4l_print_ioctl(dev->name,cmd);	switch (cmd) {		/* --- capabilities ------------------------------------------ */	case VIDIOC_QUERYCAP:		{		struct v4l2_capability *cap = arg;		memset(cap, 0, sizeof(*cap));		strlcpy(cap->driver, "em28xx", sizeof(cap->driver));		strlcpy(cap->card, em28xx_boards[dev->model].name,			sizeof(cap->card));		strlcpy(cap->bus_info, dev->udev->dev.bus_id,			sizeof(cap->bus_info));		cap->version = EM28XX_VERSION_CODE;		cap->capabilities =				V4L2_CAP_SLICED_VBI_CAPTURE |				V4L2_CAP_VIDEO_CAPTURE |				V4L2_CAP_AUDIO |				V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;		if (dev->has_tuner)			cap->capabilities |= V4L2_CAP_TUNER;		return 0;	}	/* --- capture ioctls ---------------------------------------- */	case VIDIOC_ENUM_FMT:	{		struct v4l2_fmtdesc *fmtd = arg;		if (fmtd->index != 0)			return -EINVAL;		memset(fmtd, 0, sizeof(*fmtd));		fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		strcpy(fmtd->description, "Packed YUY2");		fmtd->pixelformat = V4L2_PIX_FMT_YUYV;		memset(fmtd->reserved, 0, sizeof(fmtd->reserved));		return 0;	}	case VIDIOC_G_FMT:		return em28xx_get_fmt(dev, (struct v4l2_format *) arg);	case VIDIOC_TRY_FMT:	case VIDIOC_S_FMT:		return em28xx_set_fmt(dev, cmd, (struct v4l2_format *)arg);	case VIDIOC_REQBUFS:	{		struct v4l2_requestbuffers *rb = arg;		u32 i;		int ret;		if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||			rb->memory != V4L2_MEMORY_MMAP)			return -EINVAL;		if (dev->io == IO_READ) {			em28xx_videodbg ("method is set to read;"				" close and open the device again to"				" choose the mmap I/O method\n");			return -EINVAL;		}		for (i = 0; i < dev->num_frames; i++)			if (dev->frame[i].vma_use_count) {				em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped\n");				return -EINVAL;			}		if (dev->stream == STREAM_ON) {			em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");			if ((ret = em28xx_stream_interrupt(dev)))				return ret;		}		em28xx_empty_framequeues(dev);		em28xx_release_buffers(dev);		if (rb->count)			rb->count =				em28xx_request_buffers(dev, rb->count);		dev->frame_current = NULL;		em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n",						rb->count);		dev->io = rb->count ? IO_MMAP : IO_NONE;		return 0;	}	case VIDIOC_QUERYBUF:	{		struct v4l2_buffer *b = arg;		if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||			b->index >= dev->num_frames || dev->io != IO_MMAP)			return -EINVAL;		memcpy(b, &dev->frame[b->index].buf, sizeof(*b));		if (dev->frame[b->index].vma_use_count) {			b->flags |= V4L2_BUF_FLAG_MAPPED;		}		if (dev->frame[b->index].state == F_DONE)			b->flags |= V4L2_BUF_FLAG_DONE;		else if (dev->frame[b->index].state != F_UNUSED)			b->flags |= V4L2_BUF_FLAG_QUEUED;		return 0;	}	case VIDIOC_QBUF:	{		struct v4l2_buffer *b = arg;		unsigned long lock_flags;		if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||			b->index >= dev->num_frames || dev->io != IO_MMAP) {			return -EINVAL;		}		if (dev->frame[b->index].state != F_UNUSED) {			return -EAGAIN;		}		dev->frame[b->index].state = F_QUEUED;		/* add frame to fifo */		spin_lock_irqsave(&dev->queue_lock, lock_flags);		list_add_tail(&dev->frame[b->index].frame,				&dev->inqueue);		spin_unlock_irqrestore(&dev->queue_lock, lock_flags);		return 0;	}	case VIDIOC_DQBUF:	{		struct v4l2_buffer *b = arg;		struct em28xx_frame_t *f;		unsigned long lock_flags;		int ret = 0;		if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE			|| dev->io != IO_MMAP)			return -EINVAL;		if (list_empty(&dev->outqueue)) {			if (dev->stream == STREAM_OFF)				return -EINVAL;			if (filp->f_flags & O_NONBLOCK)				return -EAGAIN;			ret = wait_event_interruptible				(dev->wait_frame,				(!list_empty(&dev->outqueue)) ||				(dev->state & DEV_DISCONNECTED));			if (ret)				return ret;			if (dev->state & DEV_DISCONNECTED)				return -ENODEV;		}		spin_lock_irqsave(&dev->queue_lock, lock_flags);

⌨️ 快捷键说明

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