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

📄 tm6000-video.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
}static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i){	struct tm6000_fh  *fh=priv;	struct tm6000_core *dev    = fh->dev;	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	if (i != fh->type)		return -EINVAL;	videobuf_streamoff(&fh->vb_vidq);	res_free(dev,fh);	return (0);}static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *norm){	int rc=0;	struct tm6000_fh   *fh=priv;	struct tm6000_core *dev = fh->dev;	rc=tm6000_set_standard (dev, norm);#if 1	fh->width  = dev->width;	fh->height = dev->height;#endif	if (rc<0)		return rc;	tm6000_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm);	return 0;}static int vidioc_enum_input (struct file *file, void *priv,				struct v4l2_input *inp){	switch (inp->index) {	case TM6000_INPUT_TV:		inp->type = V4L2_INPUT_TYPE_TUNER;		strcpy(inp->name,"Television");		break;	case TM6000_INPUT_COMPOSITE:		inp->type = V4L2_INPUT_TYPE_CAMERA;		strcpy(inp->name,"Composite");		break;	case TM6000_INPUT_SVIDEO:		inp->type = V4L2_INPUT_TYPE_CAMERA;		strcpy(inp->name,"S-Video");		break;	default:		return -EINVAL;	}	inp->std = TM6000_STD;	return 0;}static int vidioc_g_input (struct file *file, void *priv, unsigned int *i){	struct tm6000_fh   *fh=priv;	struct tm6000_core *dev = fh->dev;	*i=dev->input;	return 0;}static int vidioc_s_input (struct file *file, void *priv, unsigned int i){	struct tm6000_fh   *fh=priv;	struct tm6000_core *dev = fh->dev;	int rc=0;	char buf[1];	switch (i) {	case TM6000_INPUT_TV:		dev->input=i;		*buf=0;		break;	case TM6000_INPUT_COMPOSITE:	case TM6000_INPUT_SVIDEO:		dev->input=i;		*buf=1;		break;	default:		return -EINVAL;	}	rc=tm6000_read_write_usb (dev, USB_DIR_OUT | USB_TYPE_VENDOR,			       REQ_03_SET_GET_MCU_PIN, 0x03, 1, buf, 1);	if (!rc) {		dev->input=i;		rc=vidioc_s_std (file, priv, &dev->vfd->current_norm);	}	return (rc);}	/* --- controls ---------------------------------------------- */static int vidioc_queryctrl (struct file *file, void *priv,				struct v4l2_queryctrl *qc){	int i;	for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)		if (qc->id && qc->id == tm6000_qctrl[i].id) {			memcpy(qc, &(tm6000_qctrl[i]),				sizeof(*qc));			return (0);		}	return -EINVAL;}static int vidioc_g_ctrl (struct file *file, void *priv,				struct v4l2_control *ctrl){	struct tm6000_fh  *fh=priv;	struct tm6000_core *dev    = fh->dev;	int  val;	/* FIXME: Probably, those won't work! Maybe we need shadow regs */	switch (ctrl->id) {	case V4L2_CID_CONTRAST:		val=tm6000_get_reg (dev, REQ_07_SET_GET_AVREG, 0x08, 0);		break;	case V4L2_CID_BRIGHTNESS:		val=tm6000_get_reg (dev, REQ_07_SET_GET_AVREG, 0x09, 0);		return 0;	case V4L2_CID_SATURATION:		val=tm6000_get_reg (dev, REQ_07_SET_GET_AVREG, 0x0a, 0);		return 0;	case V4L2_CID_HUE:		val=tm6000_get_reg (dev, REQ_07_SET_GET_AVREG, 0x0b, 0);		return 0;	default:		return -EINVAL;	}	if (val<0)		return val;	ctrl->value=val;	return 0;}static int vidioc_s_ctrl (struct file *file, void *priv,				struct v4l2_control *ctrl){	struct tm6000_fh   *fh  =priv;	struct tm6000_core *dev = fh->dev;	u8  val=ctrl->value;	switch (ctrl->id) {	case V4L2_CID_CONTRAST:  tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x08, val);		return 0;	case V4L2_CID_BRIGHTNESS:  tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x09, val);		return 0;	case V4L2_CID_SATURATION:  tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x0a, val);		return 0;	case V4L2_CID_HUE:  tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x0b, val);		return 0;	}	return -EINVAL;}static int vidioc_g_tuner (struct file *file, void *priv,				struct v4l2_tuner *t){	struct tm6000_fh   *fh  =priv;	struct tm6000_core *dev = fh->dev;	if (unlikely(UNSET == dev->tuner_type))		return -EINVAL;	if (0 != t->index)		return -EINVAL;	strcpy(t->name, "Television");	t->type       = V4L2_TUNER_ANALOG_TV;	t->capability = V4L2_TUNER_CAP_NORM;	t->rangehigh  = 0xffffffffUL;	t->rxsubchans = V4L2_TUNER_SUB_MONO;	return 0;}static int vidioc_s_tuner (struct file *file, void *priv,				struct v4l2_tuner *t){	struct tm6000_fh   *fh  =priv;	struct tm6000_core *dev = fh->dev;	if (UNSET == dev->tuner_type)		return -EINVAL;	if (0 != t->index)		return -EINVAL;	return 0;}static int vidioc_g_frequency (struct file *file, void *priv,				struct v4l2_frequency *f){	struct tm6000_fh   *fh  =priv;	struct tm6000_core *dev = fh->dev;	if (unlikely(UNSET == dev->tuner_type))		return -EINVAL;	f->type = V4L2_TUNER_ANALOG_TV;	f->frequency = dev->freq;	tm6000_i2c_call_clients(dev,VIDIOC_G_FREQUENCY,f);	return 0;}static int vidioc_s_frequency (struct file *file, void *priv,				struct v4l2_frequency *f){	struct tm6000_fh   *fh  =priv;	struct tm6000_core *dev = fh->dev;	if (unlikely(f->type != V4L2_TUNER_ANALOG_TV))		return -EINVAL;	if (unlikely(UNSET == dev->tuner_type))		return -EINVAL;	if (unlikely(f->tuner != 0))		return -EINVAL;//	mutex_lock(&dev->lock);	dev->freq = f->frequency;	tm6000_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f);//	mutex_unlock(&dev->lock);	return 0;}/* ------------------------------------------------------------------	File operations for the device   ------------------------------------------------------------------*/static int tm6000_open(struct inode *inode, struct file *file){	int minor = iminor(inode);	struct tm6000_core *h,*dev = NULL;	struct tm6000_fh *fh;	struct list_head *list;	enum v4l2_buf_type type = 0;	int i,rc;	printk(KERN_INFO "tm6000: open called (minor=%d)\n",minor);	dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called "						"(minor=%d)\n",minor);	list_for_each(list,&tm6000_corelist) {		h = list_entry(list, struct tm6000_core, tm6000_corelist);		if (h->vfd->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(dev, V4L2_DEBUG_OPEN, "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;	dev->fourcc  = format[0].fourcc;	fh->fmt      = format_by_fourcc(dev->fourcc);	tm6000_get_std_res (dev);	fh->width    = dev->width;	fh->height   = dev->height;	dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, "						"dev->vidq=0x%08lx\n",		(unsigned long)fh,(unsigned long)dev,(unsigned long)&dev->vidq);	dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "				"queued=%d\n",list_empty(&dev->vidq.queued));	dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "				"active=%d\n",list_empty(&dev->vidq.active));#if 0	/* Resets frame counters */	sprintf(dev->timestr,"%02d:%02d:%02d:%03d",			dev->h,dev->m,dev->s,(dev->us+500)/1000);#endif	/* initialize hardware on analog mode */	if (dev->mode!=TM6000_MODE_ANALOG) {		rc=tm6000_init_analog_mode (dev);		if (rc<0)			return rc;		/* Put all controls at a sane state */		for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)			qctl_regs[i] =tm6000_qctrl[i].default_value;		dev->mode=TM6000_MODE_ANALOG;	}	videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,			NULL, &dev->slock,			fh->type,			V4L2_FIELD_INTERLACED,			sizeof(struct tm6000_buffer),fh);	return 0;}static ssize_ttm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos){	struct tm6000_fh        *fh = file->private_data;	if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {		if (res_locked(fh->dev))			return -EBUSY;		return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,					file->f_flags & O_NONBLOCK);#if 0		return videobuf_read_one(&fh->vb_vidq, data, count, pos,					file->f_flags & O_NONBLOCK);#endif	}	return 0;}static unsigned inttm6000_poll(struct file *file, struct poll_table_struct *wait){	struct tm6000_fh        *fh = file->private_data;	struct tm6000_buffer    *buf;	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)		return POLLERR;	if (res_get(fh->dev,fh)) {		/* streaming capture */		if (list_empty(&fh->vb_vidq.stream))			return POLLERR;		buf = list_entry(fh->vb_vidq.stream.next,struct tm6000_buffer,vb.stream);	} else {		/* read() capture */#if 0		buf = (struct tm6000_buffer*)fh->vb_vidq.read_buf;		if (NULL == buf)			return POLLERR;#else		return videobuf_poll_stream(file, &fh->vb_vidq,					    wait);#endif	}	poll_wait(file, &buf->vb.done, wait);	if (buf->vb.state == VIDEOBUF_DONE ||	    buf->vb.state == VIDEOBUF_ERROR)		return POLLIN|POLLRDNORM;	return 0;}static int tm6000_release(struct inode *inode, struct file *file){	struct tm6000_fh         *fh = file->private_data;	struct tm6000_core      *dev = fh->dev;	int minor = iminor(inode);	dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (minor=%d, users=%d)\n",minor,dev->users);	dev->users--;	if (!dev->users) {		tm6000_uninit_isoc(dev);		videobuf_mmap_free(&fh->vb_vidq);	}	kfree (fh);	return 0;}static int tm6000_mmap(struct file *file, struct vm_area_struct * vma){	struct tm6000_fh        *fh = file->private_data;	int ret;	ret=videobuf_mmap_mapper(&fh->vb_vidq, vma);	return ret;}static struct file_operations tm6000_fops = {	.owner		= THIS_MODULE,	.open           = tm6000_open,	.release        = tm6000_release,	.ioctl          = video_ioctl2, /* V4L2 ioctl handler */	.read           = tm6000_read,	.poll		= tm6000_poll,	.mmap		= tm6000_mmap,	.llseek         = no_llseek,};static const struct v4l2_ioctl_ops video_ioctl_ops = {	.vidioc_querycap          = vidioc_querycap,	.vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,	.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,	.vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,	.vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,	.vidioc_s_std             = vidioc_s_std,	.vidioc_enum_input        = vidioc_enum_input,	.vidioc_g_input           = vidioc_g_input,	.vidioc_s_input           = vidioc_s_input,	.vidioc_queryctrl         = vidioc_queryctrl,	.vidioc_g_ctrl            = vidioc_g_ctrl,	.vidioc_s_ctrl            = vidioc_s_ctrl,	.vidioc_g_tuner           = vidioc_g_tuner,	.vidioc_s_tuner           = vidioc_s_tuner,	.vidioc_g_frequency       = vidioc_g_frequency,	.vidioc_s_frequency       = vidioc_s_frequency,	.vidioc_streamon          = vidioc_streamon,	.vidioc_streamoff         = vidioc_streamoff,	.vidioc_reqbufs           = vidioc_reqbufs,	.vidioc_querybuf          = vidioc_querybuf,	.vidioc_qbuf              = vidioc_qbuf,	.vidioc_dqbuf             = vidioc_dqbuf,#ifdef CONFIG_VIDEO_V4L1_COMPAT	.vidiocgmbuf              = vidiocgmbuf,#endif};static struct video_device tm6000_template = {	.name		= "tm6000",	.fops           = &tm6000_fops,	.ioctl_ops      = &video_ioctl_ops,	.minor		= -1,	.release	= video_device_release,	.tvnorms        = TM6000_STD,	.current_norm   = V4L2_STD_NTSC_M,};/* -----------------------------------------------------------------	Initialization and module stuff   ------------------------------------------------------------------*/int tm6000_v4l2_register(struct tm6000_core *dev){	int ret = -1;	struct video_device *vfd;	vfd = video_device_alloc();	if(!vfd) {		return -ENOMEM;	}	dev->vfd = vfd;	list_add_tail(&dev->tm6000_corelist,&tm6000_corelist);	/* init video dma queues */	INIT_LIST_HEAD(&dev->vidq.active);	INIT_LIST_HEAD(&dev->vidq.queued);	memcpy (dev->vfd, &tm6000_template, sizeof(*(dev->vfd)));	dev->vfd->debug=tm6000_debug;	ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr);	printk(KERN_INFO "Trident TVMaster TM5600/TM6000 USB2 board (Load status: %d)\n", ret);	return ret;}int tm6000_v4l2_unregister(struct tm6000_core *dev){	struct tm6000_core *h;	struct list_head *pos, *tmp;	video_unregister_device(dev->vfd);	list_for_each_safe(pos, tmp, &tm6000_corelist) {		h = list_entry(pos, struct tm6000_core, tm6000_corelist);		if (h == dev) {			list_del(pos);		}	}	return 0;}int tm6000_v4l2_exit(void){#if 0	struct tm6000_core *h;	struct list_head *list;	while (!list_empty(&tm6000_corelist)) {		list = tm6000_corelist.next;		list_del(list);		h = list_entry(list, struct tm6000_core, tm6000_corelist);		video_unregister_device(&h->vfd);		kfree (h);	}#endif	return 0;}module_param(video_nr, int, 0);MODULE_PARM_DESC(video_nr,"Allow changing video device number");module_param_named (debug, tm6000_debug, int, 0444);MODULE_PARM_DESC(debug,"activates debug info");module_param(vid_limit,int,0644);MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");

⌨️ 快捷键说明

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