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

📄 pwc-if.c

📁 Linux support for Philips USB webcams halted Latest version: pwc-9.0.2.tar.gz (including documents
💻 C
📖 第 1 页 / 共 5 页
字号:
			type_id = 740; /* CCD sensor */			break;		case 0x08b5:			Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");			name = "Logitech QuickCam Orbit";			type_id = 740; /* CCD sensor */			features |= FEATURE_MOTOR_PANTILT;			break;		case 0x08b6:		case 0x08b7:		case 0x08b8:			Info("Logitech QuickCam detected (reserved ID).\n");			name = "Logitech QuickCam (res.)";			type_id = 730; /* Assuming CMOS */			break;        	default:			return -ENODEV;        		break;        	}        }	else if (vendor_id == 0x055d) {		/* I don't know the difference between the C10 and the C30;		   I suppose the difference is the sensor, but both cameras		   work equally well with a type_id of 675		 */		switch(product_id) {		case 0x9000:			Info("Samsung MPC-C10 USB webcam detected.\n");			name = "Samsung MPC-C10";			type_id = 675;			break;		case 0x9001:			Info("Samsung MPC-C30 USB webcam detected.\n");			name = "Samsung MPC-C30";			type_id = 675;			break;		default:			return -ENODEV;			break;		}	}	else if (vendor_id == 0x041e) {		switch(product_id) {		case 0x400c:			Info("Creative Labs Webcam 5 detected.\n");			name = "Creative Labs Webcam 5";			type_id = 730;			break;		case 0x4011:			Info("Creative Labs Webcam Pro Ex detected.\n");			name = "Creative Labs Webcam Pro Ex";			type_id = 740;			break;		default:			return -ENODEV;			break;		}	}	else if (vendor_id == 0x04cc) {		switch(product_id) {		case 0x8116:			Info("Sotec Afina Eye USB webcam detected.\n");			name = "Sotec Afina Eye";			type_id = 730;			break;		default:			return -ENODEV;			break;		}	}	else if (vendor_id == 0x06be) {		switch(product_id) {		case 0x8116:			/* This is essentially the same cam as the Sotec Afina Eye */			Info("AME Co. Afina Eye USB webcam detected.\n");			name = "AME Co. Afina Eye";			type_id = 750;			break;		default:			return -ENODEV;			break;		}		}	else if (vendor_id == 0x0d81) {		switch(product_id) {		case 0x1900:			Info("Visionite VCS-UC300 USB webcam detected.\n");			name = "Visionite VCS-UC300";			type_id = 740; /* CCD sensor */			break;		case 0x1910:			Info("Visionite VCS-UM100 USB webcam detected.\n");			name = "Visionite VCS-UM100";			type_id = 730; /* CMOS sensor */			break;		default:			return -ENODEV;			break;		}	}	else 		return -ENODEV; /* Not any of the know types; but the list keeps growing. */	memset(serial_number, 0, 30);	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);	Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);	if (udev->descriptor.bNumConfigurations > 1)		Info("Warning: more than 1 configuration available.\n");	/* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */	pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);	if (pdev == NULL) {		Err("Oops, could not allocate memory for pwc_device.\n");		return -ENOMEM;	}	memset(pdev, 0, sizeof(struct pwc_device));	pdev->type = type_id;	pdev->vsize = default_size;	pdev->vframes = default_fps;	strcpy(pdev->serial, serial_number);	pdev->features = features;	if (vendor_id == 0x046D && product_id == 0x08B5)	{		/* Logitech QuickCam Orbit	           The ranges have been determined experimentally; they may differ from cam to cam.	           Also, the exact ranges left-right and up-down are different for my cam	          */		pdev->angle_range.pan_min  = -7000;		pdev->angle_range.pan_max  =  7000;		pdev->angle_range.tilt_min = -3000;		pdev->angle_range.tilt_max =  2500;	}	init_MUTEX(&pdev->modlock);	pdev->ptrlock = SPIN_LOCK_UNLOCKED;	pdev->udev = udev;	init_waitqueue_head(&pdev->frameq);	pdev->vcompression = pwc_preferred_compression;	/* Allocate video_device structure */	pdev->vdev = video_device_alloc();	if (pdev->vdev == 0)	{		Err("Err, cannot allocate video_device struture. Failing probe.");		kfree(pdev);		return -ENOMEM;	}	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));	strcpy(pdev->vdev->name, name);	pdev->vdev->owner = THIS_MODULE;	video_set_drvdata(pdev->vdev, pdev);	pdev->release = udev->descriptor.bcdDevice;	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);	/* Now search device_hint[] table for a match, so we can hint a node number. */	for (hint = 0; hint < MAX_DEV_HINTS; hint++) {		if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&		     (device_hint[hint].pdev == NULL)) {			/* so far, so good... try serial number */			if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {			    	/* match! */			    	video_nr = device_hint[hint].device_node;			    	Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);			    	break;			}		}	}	pdev->vdev->release = video_device_release;	i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);	if (i < 0) {		Err("Failed to register as video device (%d).\n", i);		video_device_release(pdev->vdev); /* Drip... drip... drip... */		kfree(pdev); /* Oops, no memory leaks please */		return -EIO;	}	else {		Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);	}	/* occupy slot */	if (hint < MAX_DEV_HINTS) 		device_hint[hint].pdev = pdev;	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);	usb_set_intfdata (intf, pdev);	return 0;}/* The user janked out the cable... */static void usb_pwc_disconnect(struct usb_interface *intf){	struct pwc_device *pdev;	int hint;	lock_kernel();	pdev = usb_get_intfdata (intf);	usb_set_intfdata (intf, NULL);	if (pdev == NULL) {		Err("pwc_disconnect() Called without private pointer.\n");		goto disconnect_out;	}	if (pdev->udev == NULL) {		Err("pwc_disconnect() already called for %p\n", pdev);		goto disconnect_out;	}	if (pdev->udev != interface_to_usbdev(intf)) {		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");		goto disconnect_out;	}#ifdef PWC_MAGIC		if (pdev->magic != PWC_MAGIC) {		Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");		goto disconnect_out;	}#endif		/* We got unplugged; this is signalled by an EPIPE error code */	if (pdev->vopen) {		Info("Disconnected while webcam is in use!\n");		pdev->error_status = EPIPE;	}	/* Alert waiting processes */	wake_up_interruptible(&pdev->frameq);	/* Wait until device is closed */	while (pdev->vopen)		schedule();	/* Device is now closed, so we can safely unregister it */	Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");	video_unregister_device(pdev->vdev);	/* Free memory (don't set pdev to 0 just yet) */	kfree(pdev);disconnect_out:	/* search device_hint[] table if we occupy a slot, by any chance */	for (hint = 0; hint < MAX_DEV_HINTS; hint++)		if (device_hint[hint].pdev == pdev)			device_hint[hint].pdev = NULL;	unlock_kernel();}/* *grunt* We have to do atoi ourselves :-( */static int pwc_atoi(const char *s){	int k = 0;	k = 0;	while (*s != '\0' && *s >= '0' && *s <= '9') {		k = 10 * k + (*s - '0');		s++;	}	return k;}/*  * Initialization code & module stuff  */static char *size = NULL;static int fps = 0;static int fbufs = 0;static int mbufs = 0;static int trace = -1;static int compression = -1;static int leds[2] = { -1, -1 };static char *dev_hint[MAX_DEV_HINTS] = { };MODULE_PARM(size, "s");MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");MODULE_PARM(fps, "i");MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");MODULE_PARM(fbufs, "i");MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");MODULE_PARM(mbufs, "i");MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");MODULE_PARM(trace, "i");MODULE_PARM_DESC(trace, "For debugging purposes");MODULE_PARM(power_save, "i");MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");MODULE_PARM(compression, "i");MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");MODULE_PARM(leds, "2i");MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");MODULE_PARM(dev_hint, "0-20s");MODULE_PARM_DESC(dev_hint, "Device node hints");MODULE_DESCRIPTION("Philips & OEM USB webcam driver");MODULE_AUTHOR("Nemosoft Unv. <webcam@smcc.demon.nl>");MODULE_LICENSE("GPL");static int __init usb_pwc_init(void){	int i, sz;	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };	Info("Philips webcam module version " PWC_VERSION " loaded.\n");	Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");	Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");	Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");	if (fps) {		if (fps < 4 || fps > 30) {			Err("Framerate out of bounds (4-30).\n");			return -EINVAL;		}		default_fps = fps;		Info("Default framerate set to %d.\n", default_fps);	}	if (size) {		/* string; try matching with array */		for (sz = 0; sz < PSZ_MAX; sz++) {			if (!strcmp(sizenames[sz], size)) { /* Found! */				default_size = sz;				break;			}		}		if (sz == PSZ_MAX) {			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");			return -EINVAL;		}		Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);	}	if (mbufs) {		if (mbufs < 1 || mbufs > MAX_IMAGES) {			Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);			return -EINVAL;		}		default_mbufs = mbufs;		Info("Number of image buffers set to %d.\n", default_mbufs);	}	if (fbufs) {		if (fbufs < 2 || fbufs > MAX_FRAMES) {			Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);			return -EINVAL;		}		default_fbufs = fbufs;		Info("Number of frame buffers set to %d.\n", default_fbufs);	}	if (trace >= 0) {		Info("Trace options: 0x%04x\n", trace);		pwc_trace = trace;	}	if (compression >= 0) {		if (compression > 3) {			Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");			return -EINVAL;		}		pwc_preferred_compression = compression;		Info("Preferred compression set to %d.\n", pwc_preferred_compression);	}	if (power_save)		Info("Enabling power save on open/close.\n");	if (leds[0] >= 0)		led_on = leds[0];	if (leds[1] >= 0)		led_off = leds[1];	/* Big device node whoopla. Basicly, it allows you to assign a	   device node (/dev/videoX) to a camera, based on its type	   & serial number. The format is [type[.serialnumber]:]node.	   Any camera that isn't matched by these rules gets the next	   available free device node.	 */	for (i = 0; i < MAX_DEV_HINTS; i++) {		char *s, *colon, *dot;		/* This loop also initializes the array */		device_hint[i].pdev = NULL;		s = dev_hint[i];		if (s != NULL && *s != '\0') {			device_hint[i].type = -1; /* wildcard */			strcpy(device_hint[i].serial_number, "*");			/* parse string: chop at ':' & '/' */			colon = dot = s;			while (*colon != '\0' && *colon != ':')				colon++;			while (*dot != '\0' && *dot != '.')				dot++;			/* Few sanity checks */			if (*dot != '\0' && dot > colon) {				Err("Malformed camera hint: the colon must be after the dot.\n");				return -EINVAL;			}			if (*colon == '\0') {				/* No colon */				if (*dot != '\0') {					Err("Malformed camera hint: no colon + device node given.\n");					return -EINVAL;				}				else {					/* No type or serial number specified, just a number. */					device_hint[i].device_node = pwc_atoi(s);				}			}			else {				/* There's a colon, so we have at least a type and a device node */				device_hint[i].type = pwc_atoi(s);				device_hint[i].device_node = pwc_atoi(colon + 1);				if (*dot != '\0') {					/* There's a serial number as well */					int k;										dot++;					k = 0;					while (*dot != ':' && k < 29) {						device_hint[i].serial_number[k++] = *dot;						dot++;					}					device_hint[i].serial_number[k] = '\0';				}			}#if PWC_DEBUG					Debug("device_hint[%d]:\n", i);			Debug("  type    : %d\n", device_hint[i].type);			Debug("  serial# : %s\n", device_hint[i].serial_number);			Debug("  node    : %d\n", device_hint[i].device_node);#endif					}		else			device_hint[i].type = 0; /* not filled */	} /* ..for MAX_DEV_HINTS

⌨️ 快捷键说明

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