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

📄 stv680.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
			stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED;			stv680->scratch_use++;			if (stv680->scratch_use >= STV680_NUMSCRATCH)				stv680->scratch_use = 0;			if (errors > STV680_MAX_ERRORS) {				errors = 0;				PDEBUG (2, "STV(i): too many errors, restarting capture");				stv680_stop_stream (stv680);				stv680_start_stream (stv680);			}		}		/* else */	}			/* while */	return 0;}/********************************************************************* * Video4Linux *********************************************************************/static int stv_open (struct inode *inode, struct file *file){	struct video_device *dev = video_devdata(file);	struct usb_stv *stv680 = video_get_drvdata(dev);	int err = 0;	/* we are called with the BKL held */	stv680->user = 1;	err = stv_init (stv680);	/* main initialization routine for camera */	if (err >= 0) {		stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES);		if (!stv680->fbuf) {			PDEBUG (0, "STV(e): Could not rvmalloc frame bufer");			err = -ENOMEM;		}		file->private_data = dev;	}	if (err)		stv680->user = 0;	return err;}static int stv_close (struct inode *inode, struct file *file){	struct video_device *dev = file->private_data;	struct usb_stv *stv680 = video_get_drvdata(dev);	int i;	for (i = 0; i < STV680_NUMFRAMES; i++)		stv680->frame[i].grabstate = FRAME_UNUSED;	if (stv680->streaming)		stv680_stop_stream (stv680);	if ((i = stv_stop_video (stv680)) < 0)		PDEBUG (1, "STV(e): stop_video failed in stv_close");	rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES);	stv680->user = 0;	if (stv680->removed) {		kfree(stv680);		stv680 = NULL;		PDEBUG (0, "STV(i): device unregistered");	}	file->private_data = NULL;	return 0;}static int stv680_do_ioctl (struct inode *inode, struct file *file,			    unsigned int cmd, void *arg){	struct video_device *vdev = file->private_data;	struct usb_stv *stv680 = video_get_drvdata(vdev);	if (!stv680->udev)		return -EIO;	switch (cmd) {	case VIDIOCGCAP:{			struct video_capability *b = arg;			strcpy (b->name, stv680->camera_name);			b->type = VID_TYPE_CAPTURE;			b->channels = 1;			b->audios = 0;			b->maxwidth = stv680->maxwidth;			b->maxheight = stv680->maxheight;			b->minwidth = stv680->maxwidth / 2;			b->minheight = stv680->maxheight / 2;			return 0;		}	case VIDIOCGCHAN:{			struct video_channel *v = arg;			if (v->channel != 0)				return -EINVAL;			v->flags = 0;			v->tuners = 0;			v->type = VIDEO_TYPE_CAMERA;			strcpy (v->name, "STV Camera");			return 0;		}	case VIDIOCSCHAN:{			struct video_channel *v = arg;			if (v->channel != 0)				return -EINVAL;			return 0;		}	case VIDIOCGPICT:{			struct video_picture *p = arg;			stv680_get_pict (stv680, p);			return 0;		}	case VIDIOCSPICT:{			struct video_picture *p = arg;			if (stv680_set_pict (stv680, p))				return -EINVAL;			return 0;		}	case VIDIOCSWIN:{			struct video_window *vw = arg;			if (vw->flags)				return -EINVAL;			if (vw->clipcount)				return -EINVAL;			if (vw->width != stv680->vwidth) {				if (stv680_set_size (stv680, vw->width, vw->height)) {					PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN");					return -EINVAL;				}			}			return 0;		}	case VIDIOCGWIN:{			struct video_window *vw = arg;			vw->x = 0;	/* FIXME */			vw->y = 0;			vw->chromakey = 0;			vw->flags = 0;			vw->clipcount = 0;			vw->width = stv680->vwidth;			vw->height = stv680->vheight;			return 0;		}	case VIDIOCGMBUF:{			struct video_mbuf *vm = arg;			int i;			memset (vm, 0, sizeof (*vm));			vm->size = STV680_NUMFRAMES * stv680->maxframesize;			vm->frames = STV680_NUMFRAMES;			for (i = 0; i < STV680_NUMFRAMES; i++)				vm->offsets[i] = stv680->maxframesize * i;			return 0;		}	case VIDIOCMCAPTURE:{			struct video_mmap *vm = arg;			if (vm->format != STV_VIDEO_PALETTE) {				PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)",					vm->format, STV_VIDEO_PALETTE);				if ((vm->format == 3) && (swapRGB_on == 0))  {					PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is (auto) ON");					/* this may fix those apps (e.g., xawtv) that want BGR */					swapRGB = 1;				}				return -EINVAL;			}			if (vm->frame >= STV680_NUMFRAMES) {				PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES");				return -EINVAL;			}			if ((stv680->frame[vm->frame].grabstate == FRAME_ERROR)			    || (stv680->frame[vm->frame].grabstate == FRAME_GRABBING)) {				PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate (%i) error",					stv680->frame[vm->frame].grabstate);				return -EBUSY;			}			/* Is this according to the v4l spec??? */			if (stv680->vwidth != vm->width) {				if (stv680_set_size (stv680, vm->width, vm->height)) {					PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed");					return -EINVAL;				}			}			stv680->frame[vm->frame].grabstate = FRAME_READY;			if (!stv680->streaming)				stv680_start_stream (stv680);			return 0;		}	case VIDIOCSYNC:{			int *frame = arg;			int ret = 0;			if (*frame < 0 || *frame >= STV680_NUMFRAMES) {				PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC");				return -EINVAL;			}			ret = stv680_newframe (stv680, *frame);			stv680->frame[*frame].grabstate = FRAME_UNUSED;			return ret;		}	case VIDIOCGFBUF:{			struct video_buffer *vb = arg;			memset (vb, 0, sizeof (*vb));			return 0;		}	case VIDIOCKEY:		return 0;	case VIDIOCCAPTURE:		{			PDEBUG (2, "STV(e): VIDIOCCAPTURE failed");			return -EINVAL;		}	case VIDIOCSFBUF:	case VIDIOCGTUNER:	case VIDIOCSTUNER:	case VIDIOCGFREQ:	case VIDIOCSFREQ:	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:		return -EINVAL;	default:		return -ENOIOCTLCMD;	}			/* end switch */	return 0;}static int stv680_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, stv680_do_ioctl);}static int stv680_mmap (struct file *file, struct vm_area_struct *vma){	struct video_device *dev = file->private_data;	struct usb_stv *stv680 = video_get_drvdata(dev);	unsigned long start = vma->vm_start;	unsigned long size  = vma->vm_end-vma->vm_start;	unsigned long page, pos;	down (&stv680->lock);	if (stv680->udev == NULL) {		up (&stv680->lock);		return -EIO;	}	if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)		    & ~(PAGE_SIZE - 1))) {		up (&stv680->lock);		return -EINVAL;	}	pos = (unsigned long) stv680->fbuf;	while (size > 0) {		page = vmalloc_to_pfn((void *)pos);		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {			up (&stv680->lock);			return -EAGAIN;		}		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	up (&stv680->lock);	return 0;}static ssize_t stv680_read (struct file *file, char __user *buf,			size_t count, loff_t *ppos){	struct video_device *dev = file->private_data;	unsigned long int realcount = count;	int ret = 0;	struct usb_stv *stv680 = video_get_drvdata(dev);	unsigned long int i;	if (STV680_NUMFRAMES != 2) {		PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!");		return -1;	}	if (stv680->udev == NULL)		return -EIO;	if (realcount > (stv680->vwidth * stv680->vheight * 3))		realcount = stv680->vwidth * stv680->vheight * 3;	/* Shouldn't happen: */	if (stv680->frame[0].grabstate == FRAME_GRABBING) {		PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read");		return -EBUSY;	}	stv680->frame[0].grabstate = FRAME_READY;	stv680->frame[1].grabstate = FRAME_UNUSED;	stv680->curframe = 0;	if (!stv680->streaming)		stv680_start_stream (stv680);	if (!stv680->streaming) {		ret = stv680_newframe (stv680, 0);	/* ret should = 0 */	}	ret = stv680_newframe (stv680, 0);	if (!ret) {		if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) {			PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i);			return -EFAULT;		}	} else {		realcount = ret;	}	stv680->frame[0].grabstate = FRAME_UNUSED;	return realcount;}				/* stv680_read */static struct file_operations stv680_fops = {	.owner =	THIS_MODULE,	.open =		stv_open,	.release =     	stv_close,	.read =		stv680_read,	.mmap =		stv680_mmap,	.ioctl =        stv680_ioctl,	.llseek =       no_llseek,};static struct video_device stv680_template = {	.owner =	THIS_MODULE,	.name =		"STV0680 USB camera",	.type =		VID_TYPE_CAPTURE,	.hardware =	VID_HARDWARE_SE401,	.fops =         &stv680_fops,	.release =	video_device_release,	.minor = 	-1,};static int stv680_probe (struct usb_interface *intf, const struct usb_device_id *id){	struct usb_device *dev = interface_to_usbdev(intf);	struct usb_host_interface *interface;	struct usb_stv *stv680 = NULL;	char *camera_name = NULL;	int retval = 0;	/* We don't handle multi-config cameras */	if (dev->descriptor.bNumConfigurations != 1) {		PDEBUG (0, "STV(e): Number of Configurations != 1");		return -ENODEV;	}	interface = &intf->altsetting[0];	/* Is it a STV680? */	if ((le16_to_cpu(dev->descriptor.idVendor) == USB_PENCAM_VENDOR_ID) &&	    (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) {		camera_name = "STV0680";		PDEBUG (0, "STV(i): STV0680 camera found.");	} else if ((le16_to_cpu(dev->descriptor.idVendor) == USB_CREATIVEGOMINI_VENDOR_ID) &&		   (le16_to_cpu(dev->descriptor.idProduct) == USB_CREATIVEGOMINI_PRODUCT_ID)) {		camera_name = "Creative WebCam Go Mini";		PDEBUG (0, "STV(i): Creative WebCam Go Mini found.");	} else {		PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 or Creative WebCam Go Mini values.");		PDEBUG (0, "STV(e): Check that the STV0680 or Creative WebCam Go Mini camera is connected to the computer.");		retval = -ENODEV;		goto error;	}	/* We found one */	if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {		PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct.");		retval = -ENOMEM;		goto error;	}	memset (stv680, 0, sizeof (*stv680));	stv680->udev = dev;	stv680->camera_name = camera_name;	stv680->vdev = video_device_alloc();	if (!stv680->vdev) {		retval = -ENOMEM;		goto error;	}	memcpy(stv680->vdev, &stv680_template, sizeof(stv680_template));	stv680->vdev->dev = &intf->dev;	video_set_drvdata(stv680->vdev, stv680);	memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name));	init_waitqueue_head (&stv680->wq);	init_MUTEX (&stv680->lock);	wmb ();	if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {		PDEBUG (0, "STV(e): video_register_device failed");		retval = -EIO;		goto error_vdev;	}	PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor);	usb_set_intfdata (intf, stv680);	stv680_create_sysfs_files(stv680->vdev);	return 0;error_vdev:	video_device_release(stv680->vdev);error:	kfree(stv680);	return retval;}static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680){	int i;	stv680->udev = NULL;	stv680->frame[0].grabstate = FRAME_ERROR;	stv680->frame[1].grabstate = FRAME_ERROR;	stv680->streaming = 0;	wake_up_interruptible (&stv680->wq);	for (i = 0; i < STV680_NUMSBUF; i++)		if (stv680->urb[i]) {			usb_kill_urb (stv680->urb[i]);			usb_free_urb (stv680->urb[i]);			stv680->urb[i] = NULL;			kfree(stv680->sbuf[i].data);		}	for (i = 0; i < STV680_NUMSCRATCH; i++)		kfree(stv680->scratch[i].data);	PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);	/* Free the memory */	kfree(stv680);}static void stv680_disconnect (struct usb_interface *intf){	struct usb_stv *stv680 = usb_get_intfdata (intf);	usb_set_intfdata (intf, NULL);	if (stv680) {		/* We don't want people trying to open up the device */		if (stv680->vdev) {			stv680_remove_sysfs_files(stv680->vdev);			video_unregister_device(stv680->vdev);			stv680->vdev = NULL;		}		if (!stv680->user) {			usb_stv680_remove_disconnected (stv680);		} else {			stv680->removed = 1;		}	}}static struct usb_driver stv680_driver = {	.owner =	THIS_MODULE,	.name =		"stv680",	.probe =	stv680_probe,	.disconnect =	stv680_disconnect,	.id_table =	device_table};/******************************************************************** *  Module routines ********************************************************************/static int __init usb_stv680_init (void){	if (usb_register (&stv680_driver) < 0) {		PDEBUG (0, "STV(e): Could not setup STV0680 driver");		return -1;	}	PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION);	info(DRIVER_DESC " " DRIVER_VERSION);	return 0;}static void __exit usb_stv680_exit (void){	usb_deregister (&stv680_driver);	PDEBUG (0, "STV(i): driver deregistered");}module_init (usb_stv680_init);module_exit (usb_stv680_exit);

⌨️ 快捷键说明

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