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

📄 stv680.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				return -EFAULT;			}			if (v != 0)				return -EINVAL;			return 0;		}	case VIDIOCGPICT:{			struct video_picture p;			stv680_get_pict (stv680, &p);			if (copy_to_user (arg, &p, sizeof (p))) {				PDEBUG (2, "STV(e): VIDIOCGPICT failed");				return -EFAULT;			}			return 0;		}	case VIDIOCSPICT:{			struct video_picture p;			if (copy_from_user (&p, arg, sizeof (p))) {				PDEBUG (2, "STV(e): VIDIOCSPICT failed");				return -EFAULT;			}			copy_from_user (&p, arg, sizeof (p));			PDEBUG (2, "STV(i): palette set to %i in VIDIOSPICT", p.palette);			if (stv680_set_pict (stv680, &p))				return -EINVAL;			return 0;		}	case VIDIOCSWIN:{			struct video_window vw;			if (copy_from_user (&vw, arg, sizeof (vw)))				return -EFAULT;			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;			vw.x = 0;	/* FIXME */			vw.y = 0;			vw.chromakey = 0;			vw.flags = 0;			vw.clipcount = 0;			vw.width = stv680->vwidth;			vw.height = stv680->vheight;			if (copy_to_user (arg, &vw, sizeof (vw))) {				PDEBUG (2, "STV(e): VIDIOCGWIN failed");				return -EFAULT;			}			return 0;		}	case VIDIOCGMBUF:{			struct video_mbuf vm;			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;			if (copy_to_user ((void *) arg, (void *) &vm, sizeof (vm))) {				PDEBUG (2, "STV(e): VIDIOCGMBUF failed");				return -EFAULT;			}			return 0;		}	case VIDIOCMCAPTURE:{			struct video_mmap vm;			if (copy_from_user (&vm, arg, sizeof (vm))) {				PDEBUG (2, "STV(e): VIDIOCMCAPTURE failed");				return -EFAULT;			}			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, ret = 0;			if (copy_from_user ((void *) &frame, arg, sizeof (int))) {				PDEBUG (2, "STV(e): VIDIOCSYNC failed");				return -EFAULT;			}			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;			memset (&vb, 0, sizeof (vb));			vb.base = NULL;	/* frame buffer not supported, not used */			if (copy_to_user ((void *) arg, (void *) &vb, sizeof (vb))) {				PDEBUG (2, "STV(e): VIDIOCSYNC failed");				return -EFAULT;			}			return 0;		}	case VIDIOCKEY:		return 0;	case VIDIOCCAPTURE:		{			PDEBUG (2, "STV(e): VIDIOCCAPTURE failed");			return -EINVAL;		}	case VIDIOCSFBUF:		return -EINVAL;	case VIDIOCGTUNER:	case VIDIOCSTUNER:		return -EINVAL;	case VIDIOCGFREQ:	case VIDIOCSFREQ:		return -EINVAL;	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:		return -EINVAL;	default:		return -ENOIOCTLCMD;	}			/* end switch */	return 0;}static int stv680_mmap (struct video_device *dev, const char *adr, unsigned long size){	struct usb_stv *stv680 = (struct usb_stv *) dev;	unsigned long start = (unsigned long) adr;	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 = kvirt_to_pa (pos);		if (remap_page_range (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 long stv680_read (struct video_device *dev, char *buf, unsigned long count, int noblock){	unsigned long int realcount = count;	int ret = 0;	struct usb_stv *stv680 = (struct usb_stv *) 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 int stv_init_done (struct video_device *dev){#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	if (create_proc_stv680_cam ((struct usb_stv *) dev) < 0)		return -1;#endif	return 0;}static struct video_device stv680_template = {	owner:		THIS_MODULE,	name:		"STV0680 USB camera",	type:		VID_TYPE_CAPTURE,	hardware:	VID_HARDWARE_SE401,	open:		stv_open,	close:		stv_close,	read:		stv680_read,	write:		stv680_write,	ioctl:		stv680_ioctl,	mmap:		stv680_mmap,	initialize:	stv_init_done,};static void *__devinit stv680_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id){	struct usb_interface_descriptor *interface;	struct usb_stv *stv680;	char *camera_name = NULL;	/* We don't handle multi-config cameras */	if (dev->descriptor.bNumConfigurations != 1) {		PDEBUG (0, "STV(e): Number of Configurations != 1");		return NULL;	}	interface = &dev->actconfig->interface[ifnum].altsetting[0];	/* Is it a STV680? */	if ((dev->descriptor.idVendor == USB_PENCAM_VENDOR_ID) && (dev->descriptor.idProduct == USB_PENCAM_PRODUCT_ID)) {		camera_name = "STV0680";		PDEBUG (0, "STV(i): STV0680 camera found.");	} else {		PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values.");		PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer.");		return NULL;	}	/* We found one */	if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {		PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct.");		return NULL;	}	memset (stv680, 0, sizeof (*stv680));	stv680->udev = dev;	stv680->camera_name = camera_name;	memcpy (&stv680->vdev, &stv680_template, sizeof (stv680_template));	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) {		kfree (stv680);		PDEBUG (0, "STV(e): video_register_device failed");		return NULL;	}	PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev.minor);	return stv680;}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]) {			stv680->urb[i]->next = NULL;			usb_unlink_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++)		if (stv680->scratch[i].data) {			kfree (stv680->scratch[i].data);		}	PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	destroy_proc_stv680_cam (stv680);#endif	/* Free the memory */	kfree (stv680);}static void stv680_disconnect (struct usb_device *dev, void *ptr){	struct usb_stv *stv680 = (struct usb_stv *) ptr;	lock_kernel ();	/* We don't want people trying to open up the device */	if (!stv680->user) {		video_unregister_device (&stv680->vdev);		usb_stv680_remove_disconnected (stv680);	} else {		stv680->removed = 1;	}	unlock_kernel ();}static struct usb_driver stv680_driver = {	name:		"stv680",	probe:		stv680_probe,	disconnect:	stv680_disconnect,	id_table:	device_table};/******************************************************************** *  Module routines ********************************************************************/static int __init usb_stv680_init (void){#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	if (proc_stv680_create () < 0)		return -1;#endif	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");#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	proc_stv680_destroy ();#endif}module_init (usb_stv680_init);module_exit (usb_stv680_exit);

⌨️ 快捷键说明

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