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

📄 em28xx-video.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 4 页
字号:
				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;					}				}			}			if (dev->decoder == EM28XX_TVP5150) {				em28xx_i2c_call_clients(dev,cmd,qc);				if (qc->type)					return 0;				else					return -EINVAL;			}			for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) {				if (qc->id && qc->id == saa711x_qctrl[i].id) {					memcpy(qc, &(saa711x_qctrl[i]),					       sizeof(*qc));					return 0;				}			}			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) {				if (dev->decoder == EM28XX_TVP5150) {					em28xx_i2c_call_clients(dev,cmd,arg);					return 0;				}				return saa711x_get_ctrl(dev, ctrl);			} 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);					}				}			}			if (dev->decoder == EM28XX_TVP5150) {				em28xx_i2c_call_clients(dev,cmd,arg);				return 0;			} else 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);					}				}				for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) {					if (ctrl->id == saa711x_qctrl[i].id) {						if (ctrl->value <						saa711x_qctrl[i].minimum						|| ctrl->value >						saa711x_qctrl[i].maximum)							return -ERANGE;						return saa711x_set_ctrl(dev, ctrl);					}				}			}			return -EINVAL;		}		/* --- tuner ioctls ------------------------------------------ */	case VIDIOC_G_TUNER:		{			struct v4l2_tuner *t = arg;			int status = 0;			if (0 != t->index)				return -EINVAL;			memset(t, 0, sizeof(*t));			strcpy(t->name, "Tuner");			t->type = V4L2_TUNER_ANALOG_TV;			t->capability = V4L2_TUNER_CAP_NORM;			t->rangehigh = 0xffffffffUL;	/* FIXME: set correct range *//*		t->signal = 0xffff;*//*		em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/			/* No way to get signal strength? */			down(&dev->lock);			em28xx_i2c_call_clients(dev, DECODER_GET_STATUS,						&status);			up(&dev->lock);			t->signal =			    (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0;			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;			int status = 0;			if (0 != t->index)				return -EINVAL;			memset(t, 0, sizeof(*t));			strcpy(t->name, "Tuner");			t->type = V4L2_TUNER_ANALOG_TV;			t->capability = V4L2_TUNER_CAP_NORM;			t->rangehigh = 0xffffffffUL;	/* FIXME: set correct range *//*		t->signal = 0xffff; */			/* No way to get signal strength? */			down(&dev->lock);			em28xx_i2c_call_clients(dev, DECODER_GET_STATUS,						&status);			up(&dev->lock);			t->signal =			    (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0;			em28xx_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n",				 t->signal, t->afc);			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;			down(&dev->lock);			dev->ctl_freq = f->frequency;			em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f);			up(&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_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:		{			struct v4l2_format *format = arg;			em28xx_videodbg("VIDIOC_G_FMT: type=%s\n",				 format->type ==				 V4L2_BUF_TYPE_VIDEO_CAPTURE ?				 "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type ==				 V4L2_BUF_TYPE_VBI_CAPTURE ?				 "V4L2_BUF_TYPE_VBI_CAPTURE " :				 "not supported");			if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)				return -EINVAL;			format->fmt.pix.width = dev->width;			format->fmt.pix.height = dev->height;			format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;			format->fmt.pix.bytesperline = dev->bytesperline;			format->fmt.pix.sizeimage = dev->frame_size;			format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;			format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;	/* FIXME: TOP? NONE? BOTTOM? ALTENATE? */			em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width,				 dev->height);			return 0;		}	case VIDIOC_TRY_FMT:	case VIDIOC_S_FMT:		{			struct v4l2_format *format = arg;			u32 i;			int ret = 0;			int width = format->fmt.pix.width;			int height = format->fmt.pix.height;			unsigned int hscale, vscale;			unsigned int maxh, maxw;			maxw = norm_maxw(dev);			maxh = norm_maxh(dev);/*		int both_fields; */			em28xx_videodbg("%s: type=%s\n",				 cmd ==				 VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" :				 "VIDIOC_S_FMT",				 format->type ==				 V4L2_BUF_TYPE_VIDEO_CAPTURE ?				 "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type ==				 V4L2_BUF_TYPE_VBI_CAPTURE ?				 "V4L2_BUF_TYPE_VBI_CAPTURE " :				 "not supported");			if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)				return -EINVAL;			em28xx_videodbg("%s: requested %dx%d\n",				 cmd ==				 VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" :				 "VIDIOC_S_FMT", format->fmt.pix.width,				 format->fmt.pix.height);			/* FIXME: Move some code away from here */			/* width must even because of the YUYV format */			/* height must be even because of interlacing */			height &= 0xfffe;			width &= 0xfffe;			if (height < 32)				height = 32;			if (height > maxh)				height = maxh;			if (width < 48)				width = 48;			if (width > maxw)				width = maxw;			if(dev->is_em2800){				/* the em2800 can only scale down to 50% */				if(height % (maxh / 2))					height=maxh;				if(width % (maxw / 2))					width=maxw;				/* according to empiatech support */				/* the MaxPacketSize is to small to support */				/* framesizes larger than 640x480 @ 30 fps */				/* or 640x576 @ 25 fps. As this would cut */				/* of a part of the image we prefer */				/* 360x576 or 360x480 for now */				if(width == maxw && height == maxh)					width /= 2;			}			if ((hscale =			     (((unsigned long)maxw) << 12) / width - 4096L) >=			    0x4000)				hscale = 0x3fff;			width =			    (((unsigned long)maxw) << 12) / (hscale + 4096L);			if ((vscale =			     (((unsigned long)maxh) << 12) / height - 4096L) >=			    0x4000)				vscale = 0x3fff;			height =			    (((unsigned long)maxh) << 12) / (vscale + 4096L);			format->fmt.pix.width = width;			format->fmt.pix.height = height;			format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;			format->fmt.pix.bytesperline = width * 2;			format->fmt.pix.sizeimage = width * 2 * height;			format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;			format->fmt.pix.field = V4L2_FIELD_INTERLACED;			em28xx_videodbg("%s: returned %dx%d (%d, %d)\n",				 cmd ==				 VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" :				 "VIDIOC_S_FMT", format->fmt.pix.width,				 format->fmt.pix.height, hscale, vscale);			if (cmd == VIDIOC_TRY_FMT)				return 0;			for (i = 0; i < dev->num_frames; i++)				if (dev->frame[i].vma_use_count) {					em28xx_videodbg("VIDIOC_S_FMT failed. "						"Unmap the buffers first.\n");					return -EINVAL;				}			/* stop io in case it is already in progress */			if (dev->stream == STREAM_ON) {				em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n");				if ((ret = em28xx_stream_interrupt(dev)))					return ret;			}			em28xx_release_buffers(dev);			dev->io = IO_NONE;			/* set new image size */			dev->width = width;			dev->height = height;			dev->frame_size = dev->width * dev->height * 2;			dev->field_size = dev->frame_size >> 1;	/*both_fileds ? dev->frame_size>>1 : dev->frame_size; */			dev->bytesperline = dev->width * 2;			dev->hscale = hscale;			dev->vscale = vscale;/*			dev->both_fileds = both_fileds; */			em28xx_uninit_isoc(dev);			em28xx_set_alternate(dev);			em28xx_capture_start(dev, 1);			em28xx_resolution_set(dev);			em28xx_init_isoc(dev);			return 0;		}		/* --- streaming capture ------------------------------------- */	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);

⌨️ 快捷键说明

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