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

📄 pwc-if.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		case VIDIOCSCHAN:		{				/* The spec says the argument is an integer, but			   the bttv driver uses a video_channel arg, which			   makes sense becasue it also has the norm flag.			 */			struct video_channel v;			if (copy_from_user(&v, arg, sizeof(v)))				return -EFAULT;			if (v.channel != 0)				return -EINVAL;			return 0;		}		/* Picture functions; contrast etc. */		case VIDIOCGPICT:		{			struct video_picture p;			int val;			p.colour = 0x8000;			p.hue = 0x8000;			val = pwc_get_brightness(pdev);			if (val >= 0)				p.brightness = val;			else				p.brightness = 0xffff;			val = pwc_get_contrast(pdev);			if (val >= 0)				p.contrast = val;			else				p.contrast = 0xffff;			/* Gamma, Whiteness, what's the difference? :) */			val = pwc_get_gamma(pdev);			if (val >= 0)				p.whiteness = val;			else				p.whiteness = 0xffff;			val = pwc_get_saturation(pdev);			if (val >= 0)				p.colour = val;			else				p.colour = 0xffff;			p.depth = 24;			p.palette = pdev->vpalette;			p.hue = 0xFFFF; /* N/A */			if (copy_to_user(arg, &p, sizeof(p)))				return -EFAULT;			break;		}				case VIDIOCSPICT:		{			struct video_picture p;			if (copy_from_user(&p, arg, sizeof(p)))				return -EFAULT;			/*			 *	FIXME:	Suppose we are mid read			        ANSWER: No problem: the firmware of the camera			                can handle brightness/contrast/etc			                changes at _any_ time, and the palette			                is used exactly once in the uncompress			                routine.			 */			pwc_set_brightness(pdev, p.brightness);			pwc_set_contrast(pdev, p.contrast);			pwc_set_gamma(pdev, p.whiteness);			pwc_set_saturation(pdev, p.colour);			if (p.palette && p.palette != pdev->vpalette) {				if (pwc_set_palette(pdev, p.palette) < 0)					return -EINVAL;			}			break;		}		/* Window/size parameters */				case VIDIOCGWIN:		{			struct video_window vw;						vw.x = 0;			vw.y = 0;			vw.width = pdev->view.x;			vw.height = pdev->view.y;			vw.chromakey = 0;			vw.flags = (pdev->vframes << PWC_FPS_SHIFT) | 			           (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);						if (copy_to_user(arg, &vw, sizeof(vw)))				return -EFAULT;						break;		}				case VIDIOCSWIN:		{			struct video_window vw;			int fps, snapshot, ret;					if (copy_from_user(&vw, arg, sizeof(vw)))				return -EFAULT;			fps = (vw.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;			snapshot = vw.flags & PWC_FPS_SNAPSHOT;			if (fps == 0)				fps = pdev->vframes;			if (pdev->view.x == vw.width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)				return 0;			ret = pwc_try_video_mode(pdev, vw.width, vw.height, fps, pdev->vcompression, snapshot);			if (ret)				return ret;			break;				}				/* We don't have overlay support (yet) */		case VIDIOCGFBUF:		{			struct video_buffer vb;						vb.base = NULL;			vb.height = 0;			vb.width = 0;			vb.depth = 0;			vb.bytesperline = 0;						if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))				return -EFAULT;			break;		}		/* mmap() functions */		case VIDIOCGMBUF:		{			/* Tell the user program how much memory is needed for a mmap() */			struct video_mbuf vm;			int i;			memset(&vm, 0, sizeof(vm));			vm.size = default_mbufs * pdev->len_per_image;			vm.frames = default_mbufs; /* double buffering should be enough for most applications */			for (i = 0; i < default_mbufs; i++)				vm.offsets[i] = i * pdev->len_per_image;			if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))				return -EFAULT;			break;		}		case VIDIOCMCAPTURE:		{			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */			struct video_mmap vm;			if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))				return -EFAULT;			Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm.width, vm.height, vm.frame, vm.format);			if (vm.frame < 0 || vm.frame >= default_mbufs)				return -EINVAL;			/* xawtv is nasty. It probes the available palettes			   by setting a very small image size and trying			   various palettes... The driver doesn't support			   such small images, so I'm working around it.			 */			if (vm.format && vm.format != pdev->vpalette)				if (pwc_set_palette(pdev, vm.format) < 0)					return -EINVAL;			 			if ((vm.width != pdev->view.x || vm.height != pdev->view.y) &&			    (vm.width >= pdev->view_min.x && vm.height >= pdev->view_min.y)) {				int ret;								Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");				ret = pwc_try_video_mode(pdev, vm.width, vm.height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);				if (ret)					return ret;			} /* ... size mismatch */			/* FIXME: should we lock here? */			if (pdev->image_used[vm.frame])				return -EBUSY;	/* buffer wasn't available. Bummer */			pdev->image_used[vm.frame] = 1;			/* Okay, we're done here. In the SYNC call we wait until a 			   frame comes available, then expand image into the given 			   buffer.			   In contrast to the CPiA cam the Philips cams deliver a 			   constant stream, almost like a grabber card. Also,			   we have separate buffers for the rawdata and the image,			   meaning we can nearly always expand into the requested buffer.			 */			Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");			break;		}		case VIDIOCSYNC:		{			/* The doc says: "Whenever a buffer is used it should			   call VIDIOCSYNC to free this frame up and continue."			   			   The only odd thing about this whole procedure is 			   that MCAPTURE flags the buffer as "in use", and			   SYNC immediately unmarks it, while it isn't 			   after SYNC that you know that the buffer actually			   got filled! So you better not start a CAPTURE in			   the same frame immediately (use double buffering). 			   This is not a problem for this cam, since it has 			   extra intermediate buffers, but a hardware 			   grabber card will then overwrite the buffer 			   you're working on.			 */			int mbuf, ret;			if (copy_from_user((void *)&mbuf, arg, sizeof(int)))				return -EFAULT;			Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", mbuf);			/* bounds check */			if (mbuf < 0 || mbuf >= default_mbufs)				return -EINVAL;			/* check if this buffer was requested anyway */			if (pdev->image_used[mbuf] == 0)				return -EINVAL;			/* Add ourselves to the frame wait-queue.			   			   FIXME: needs auditing for safety.			   QUSTION: In what respect? I think that using the			            frameq is safe now.			 */			add_wait_queue(&pdev->frameq, &wait);			while (pdev->full_frames == NULL) {				if (pdev->unplugged) {					remove_wait_queue(&pdev->frameq, &wait);					set_current_state(TASK_RUNNING);					return -ENODEV;				}				                	if (signal_pending(current)) {	                		remove_wait_queue(&pdev->frameq, &wait);		                	set_current_state(TASK_RUNNING);		                	return -ERESTARTSYS;	        	        }	                	schedule();		                set_current_state(TASK_INTERRUPTIBLE);			}			remove_wait_queue(&pdev->frameq, &wait);			set_current_state(TASK_RUNNING);							/* The frame is ready. Expand in the image buffer 			   requested by the user. I don't care if you 			   mmap() 5 buffers and request data in this order: 			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .			   Grabber hardware may not be so forgiving.			 */			Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");			pdev->fill_image = mbuf; /* tell in which buffer we want the image to be expanded */			/* Decompress, etc */			ret = pwc_handle_frame(pdev);			pdev->image_used[mbuf] = 0;			if (ret)				return -EFAULT;			break;		}				case VIDIOCGAUDIO:		{			struct video_audio v;						strcpy(v.name, "Microphone");			v.audio = -1; /* unknown audio minor */			v.flags = 0;			v.mode = VIDEO_SOUND_MONO;			v.volume = 0;			v.bass = 0;			v.treble = 0;			v.balance = 0x8000;			v.step = 1;						if (copy_to_user(arg, &v, sizeof(v)))				return -EFAULT;			break;			}				case VIDIOCSAUDIO:		{			struct video_audio v;						if (copy_from_user(&v, arg, sizeof(v)))				return -EFAULT;			/* Dummy: nothing can be set */			break;		}				case VIDIOCGUNIT:		{			struct video_unit vu;						vu.video = pdev->vdev->minor & 0x3F;			vu.audio = -1; /* not known yet */			vu.vbi = -1;			vu.radio = -1;			vu.teletext = -1;			if (copy_to_user(arg, &vu, sizeof(vu)))				return -EFAULT;			break;		}		default:			return pwc_ioctl(pdev, cmd, arg);	} /* ..switch */	return 0;}	static int pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size){	struct pwc_device *pdev;	unsigned long start = (unsigned long)adr;	unsigned long page, pos;		Trace(TRACE_MEMORY, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size);	pdev = vdev->priv;	/* FIXME - audit mmap during a read */			pos = (unsigned long)pdev->image_data;	while (size > 0) {		page = kvirt_to_pa(pos);		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))			return -EAGAIN;		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return 0;}/***************************************************************************//* USB functions *//* This function gets called when a new device is plugged in or the usb core * is loaded. */static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id){	struct pwc_device *pdev = NULL;	struct video_device *vdev;	int vendor_id, product_id, type_id;	int i, hint;	int video_nr = -1; /* default: use next available device */	char serial_number[30];	free_mem_leak();		/* Check if we can handle this device */	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", udev->descriptor.idVendor, udev->descriptor.idProduct, ifnum);	/* the interfaces are probed one by one. We are only interested in the	   video interface (0) now.	   Interface 1 is the Audio Control, and interface 2 Audio itself.	 */	if (ifnum > 0) 		return NULL;	vendor_id = udev->descriptor.idVendor;	product_id = udev->descriptor.idProduct;	if (vendor_id == 0x0471) {		switch (product_id) {		case 0x0302:			Info("Philips PCA645VC USB webcam detected.\n");			type_id = 645;			break;		case 0x0303:			Info("Philips PCA646VC USB webcam detected.\n");			type_id = 646;			break;		case 0x0304:			Info("Askey VC010 type 2 USB webcam detected.\n");			type_id = 646;			break;		case 0x0307:			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");			type_id = 675;			break;		case 0x0308:			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");			type_id = 680;			break;		case 0x030C:			Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");			type_id = 690;			break;		case 0x0310:			Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n");			type_id = 730;			break;		case 0x0311:			Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n");			type_id = 740;			break;		case 0x0312:			Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");			type_id = 750;			break;		default:			return NULL;

⌨️ 快捷键说明

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