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

📄 em28xx-video.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
static int vidioc_cropcap(struct file *file, void *priv,					struct v4l2_cropcap *cc){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	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;}static int vidioc_streamon(struct file *file, void *priv,					enum v4l2_buf_type type){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	if (unlikely(res_get(fh) < 0))		return -EBUSY;	return (videobuf_streamon(&fh->vb_vidq));}static int vidioc_streamoff(struct file *file, void *priv,					enum v4l2_buf_type type){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	if (type != fh->type)		return -EINVAL;	videobuf_streamoff(&fh->vb_vidq);	res_free(fh);	return 0;}static int vidioc_querycap(struct file *file, void  *priv,					struct v4l2_capability *cap){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	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 =#if 0			V4L2_CAP_VBI_CAPTURE |#endif			V4L2_CAP_SLICED_VBI_CAPTURE |			V4L2_CAP_VIDEO_CAPTURE |			V4L2_CAP_AUDIO |			V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;	if (dev->tuner_type != TUNER_ABSENT)		cap->capabilities |= V4L2_CAP_TUNER;	return 0;}static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,					struct v4l2_fmtdesc *fmtd){	if (fmtd->index != 0)		return -EINVAL;	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;}/* Sliced VBI ioctls */static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,					struct v4l2_format *f){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	mutex_lock(&dev->lock);	f->fmt.sliced.service_set = 0;	em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);	if (f->fmt.sliced.service_set == 0)		rc = -EINVAL;	mutex_unlock(&dev->lock);	return rc;}static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,			struct v4l2_format *f){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	mutex_lock(&dev->lock);	em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);	mutex_unlock(&dev->lock);	if (f->fmt.sliced.service_set == 0)		return -EINVAL;	return 0;}#if 0/* RAW VBI ioctls */static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,					struct v4l2_format *f){	format->fmt.vbi.sampling_rate = 6750000 * 4;	format->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;	format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;	format->fmt.vbi.offset = 64 * 4;	format->fmt.vbi.start[0] = norm->vbi_v_start_0;	format->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 + 1;	format->fmt.vbi.start[1] = norm->vbi_v_start_1;	format->fmt.vbi.count[1] = format->fmt.vbi.count[0];	format->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */	return 0;}static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,			struct v4l2_format *f){	format->type = V4L2_BUF_TYPE_VBI_CAPTURE;	format->fmt.vbi.sampling_rate = HZ;	format->fmt.vbi.samples_per_line = 2048;	format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;	format->fmt.vbi.offset = 244;	format->fmt.vbi.flags = 0;	format->fmt.vbi.start[0] = 0;	format->fmt.vbi.start[1] = 0;	return 0;}#endifstatic int vidioc_reqbufs(struct file *file, void *priv,			  struct v4l2_requestbuffers *rb){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	return (videobuf_reqbufs(&fh->vb_vidq, rb));}static int vidioc_querybuf(struct file *file, void *priv,			   struct v4l2_buffer *b){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	return (videobuf_querybuf(&fh->vb_vidq, b));}static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	return (videobuf_qbuf(&fh->vb_vidq, b));}static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	return (videobuf_dqbuf(&fh->vb_vidq, b,				file->f_flags & O_NONBLOCK));}#ifdef CONFIG_VIDEO_V4L1_COMPATstatic int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf){	struct em28xx_fh  *fh = priv;	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);}#endif/* ----------------------------------------------------------- *//* RADIO ESPECIFIC IOCTLS                                      *//* ----------------------------------------------------------- */static int radio_querycap(struct file *file, void  *priv,			  struct v4l2_capability *cap){	struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;	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_TUNER;	return 0;}static int radio_g_tuner(struct file *file, void *priv,			 struct v4l2_tuner *t){	struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;	if (unlikely(t->index > 0))		return -EINVAL;	strcpy(t->name, "Radio");	t->type = V4L2_TUNER_RADIO;	em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);	return 0;}static int radio_enum_input(struct file *file, void *priv,			    struct v4l2_input *i){	if (i->index != 0)		return -EINVAL;	strcpy(i->name, "Radio");	i->type = V4L2_INPUT_TYPE_TUNER;	return 0;}static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a){	if (unlikely(a->index))		return -EINVAL;	strcpy(a->name, "Radio");	return 0;}static int radio_s_tuner(struct file *file, void *priv,			 struct v4l2_tuner *t){	struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;	if (0 != t->index)		return -EINVAL;	em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);	return 0;}static int radio_s_audio(struct file *file, void *fh,			 struct v4l2_audio *a){	return 0;}static int radio_s_input(struct file *file, void *fh, unsigned int i){	return 0;}static int radio_queryctrl(struct file *file, void *priv,			   struct v4l2_queryctrl *qc){	int i;	if (qc->id <  V4L2_CID_BASE ||		qc->id >= V4L2_CID_LASTP1)		return -EINVAL;	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;		}	}	return -EINVAL;}/* * em28xx_v4l2_open() * inits the device and starts isoc transfer */static int em28xx_v4l2_open(struct inode *inode, struct file *filp){	int minor = iminor(inode);	int errCode = 0, radio = 0;	struct em28xx *h, *dev = NULL;	struct em28xx_fh *fh;	enum v4l2_buf_type fh_type = 0;	lock_kernel();	list_for_each_entry(h, &em28xx_devlist, devlist) {		if (h->vdev->minor == minor) {			dev  = h;			fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		}		if (h->vbi_dev->minor == minor) {			dev  = h;			fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;		}		if (h->radio_dev &&		    h->radio_dev->minor == minor) {			radio = 1;			dev   = h;		}	}	if (NULL == dev) {		unlock_kernel();		return -ENODEV;	}	em28xx_videodbg("open minor=%d type=%s users=%d\n",				minor, v4l2_type_names[fh_type], dev->users);#if 0	errCode = em28xx_set_mode(dev, EM28XX_ANALOG_MODE);	if (errCode < 0) {		em28xx_errdev("Device locked on digital mode. Can't open analog\n");		return -EBUSY;	}#endif	fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);	if (!fh) {		em28xx_errdev("em28xx-video.c: Out of memory?!\n");		unlock_kernel();		return -ENOMEM;	}	mutex_lock(&dev->lock);	fh->dev = dev;	fh->radio = radio;	fh->type = fh_type;	filp->private_data = fh;	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {		dev->width = norm_maxw(dev);		dev->height = norm_maxh(dev);		dev->hscale = 0;		dev->vscale = 0;		em28xx_set_mode(dev, EM28XX_ANALOG_MODE);		em28xx_set_alternate(dev);		em28xx_resolution_set(dev);		/* Needed, since GPIO might have disabled power of		   some i2c device		 */		em28xx_config_i2c(dev);#if 0		/* device needs to be initialized before isoc transfer */		video_mux(dev, 0);#endif	}	if (fh->radio) {		em28xx_videodbg("video_open: setting radio device\n");#if 0		em28xx_start_radio(dev);#endif		em28xx_i2c_call_clients(dev, AUDC_SET_RADIO, NULL);	}	dev->users++;	videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,			NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,			sizeof(struct em28xx_buffer), fh);	mutex_unlock(&dev->lock);	unlock_kernel();	return errCode;}/* * em28xx_realease_resources() * unregisters the v4l2,i2c and usb devices * called when the device gets disconected or at module unload*/static void em28xx_release_resources(struct em28xx *dev){	/*FIXME: I2C IR should be disconnected */	em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n",				dev->vdev->num, dev->vbi_dev->num);	list_del(&dev->devlist);	if (dev->sbutton_input_dev)		em28xx_deregister_snapshot_button(dev);	if (dev->radio_dev) {		if (-1 != dev->radio_dev->minor)			video_unregister_device(dev->radio_dev);		else			video_device_release(dev->radio_dev);		dev->radio_dev = NULL;	}	if (dev->vbi_dev) {		if (-1 != dev->vbi_dev->minor)			video_unregister_device(dev->vbi_dev);		else			video_device_release(dev->vbi_dev);		dev->vbi_dev = NULL;	}	if (dev->vdev) {		if (-1 != dev->vdev->minor)			video_unregister_device(dev->vdev);		else			video_device_release(dev->vdev);		dev->vdev = NULL;	}	em28xx_i2c_unregister(dev);	usb_put_dev(dev->udev);	/* Mark device as unused */	em28xx_devused &= ~(1<<dev->devno);}/* * em28xx_v4l2_close() * stops streaming and deallocates all resources allocated by the v4l2 * calls and ioctls */static int em28xx_v4l2_close(struct inode *inode, struct file *filp){	struct em28xx_fh *fh  = filp->private_data;	struct em28xx    *dev = fh->dev;	int              errCode;	em28xx_videodbg("users=%d\n", dev->users);	if (res_check(fh))		res_free(fh);	mutex_lock(&dev->lock);	if (dev->users == 1) {		videobuf_stop(&fh->vb_vidq);		videobuf_mmap_free(&fh->vb_vidq);		/* the device is already disconnect,		   free the remaining resources */		if (dev->state & DEV_DISCONNECTED) {			em28xx_release_resources(dev);			mutex_unlock(&dev->lock);			kfree(dev);			return 0;		}		/* do this before setting alternate! */		em28xx_uninit_isoc(dev);		em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);		/* set alternate 0 */		dev->alt = 0;		em28xx_videodbg("setting alternate 0\n");		errCode = usb_set_interface(dev->udev, 0, 0);		if (errCode < 0) {			em28xx_errdev("cannot change alternate number to "					"0 (error=%i)\n", errCode);		}	}	kfree(fh);	dev->users--;	wake_up_interruptible_nr(&dev->open, 1);	mutex_unlock(&dev->lock);	return 0;}/* * em28xx_v4l2_read() * will allocate buffers when called for the first time */static ssize_tem28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,		 loff_t *pos){	struct em28xx_fh *fh = filp->private_data;	struct em28xx *dev = fh->dev;	int rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	/* FIXME: read() is not prepared to allow changing the video	   resolution while streaming. Seems a bug at em28xx_set_fmt	 */	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {		if (unlikely(res_get(fh)))			return -EBUSY;		return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,					filp->f_flags & O_NONBLOCK);	}	return 0;}/* * em28xx_v4l2_poll() * will allocate buffers when called for the first time */static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait){	struct em28xx_fh *fh = filp->private_data;	struct em28xx *dev = fh->dev;	int rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	if (unlikely(res_get(fh) < 0))		return POLLERR;	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)		return POLLERR;	return videobuf_poll_stream(filp, &fh->vb_vidq, wait);}/* * em28xx_v4l2_mmap() */static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma){	struct em28xx_fh *fh    = filp->private_data;	struct em28xx	 *dev   = fh->dev;	int		 rc;	if (unlikely(res_get(fh) < 0))		return -EBUSY;	rc = check_dev(dev);	if (rc < 0)		return rc;

⌨️ 快捷键说明

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