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

📄 pwc-if.c

📁 webcam device driver
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (iso_error < 20)				PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);		}	}handler_end:	if (awake)		wake_up_interruptible(&pdev->frameq);	urb->dev = pdev->udev;	i = usb_submit_urb(urb, GFP_ATOMIC);	if (i != 0)		PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);}int pwc_isoc_init(struct pwc_device *pdev){	struct usb_device *udev;	struct urb *urb;	int i, j, ret;	struct usb_interface *intf;	struct usb_host_interface *idesc = NULL;	if (pdev == NULL)		return -EFAULT;	if (pdev->iso_init)		return 0;	pdev->vsync = 0;	udev = pdev->udev;	/* Get the current alternate interface, adjust packet size */	if (!udev->actconfig)		return -EFAULT;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)	idesc = &udev->actconfig->interface[0]->altsetting[pdev->valternate];#else	intf = usb_ifnum_to_if(udev, 0);	if (intf)		idesc = usb_altnum_to_altsetting(intf, pdev->valternate);#endif			if (!idesc)		return -EFAULT;	/* Search video endpoint */	pdev->vmax_packet_size = -1;	for (i = 0; i < idesc->desc.bNumEndpoints; i++) {		if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)			pdev->vmax_packet_size = idesc->endpoint[i].desc.wMaxPacketSize;#else			pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);#endif			break;		}	}		if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {		PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");		return -ENFILE; /* Odd error, that should be noticeable */	}	/* Set alternate interface */	ret = 0;	PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);	ret = usb_set_interface(pdev->udev, 0, pdev->valternate);	if (ret < 0)		return ret;	for (i = 0; i < MAX_ISO_BUFS; i++) {		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);		if (urb == NULL) {			PWC_ERROR("Failed to allocate urb %d\n", i);			ret = -ENOMEM;			break;		}		pdev->sbuf[i].urb = urb;		PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);	}	if (ret) {		/* De-allocate in reverse order */		while (i >= 0) {			if (pdev->sbuf[i].urb != NULL)				usb_free_urb(pdev->sbuf[i].urb);			pdev->sbuf[i].urb = NULL;			i--;		}		return ret;	}	/* init URB structure */		for (i = 0; i < MAX_ISO_BUFS; i++) {		urb = pdev->sbuf[i].urb;		urb->interval = 1; // devik		urb->dev = udev;	        urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);		urb->transfer_flags = URB_ISO_ASAP;	        urb->transfer_buffer = pdev->sbuf[i].data;	        urb->transfer_buffer_length = ISO_BUFFER_SIZE;	        urb->complete = pwc_isoc_handler;	        urb->context = pdev;		urb->start_frame = 0;		urb->number_of_packets = ISO_FRAMES_PER_DESC;		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;			urb->iso_frame_desc[j].length = pdev->vmax_packet_size;		}	}	/* link */	for (i = 0; i < MAX_ISO_BUFS; i++) {		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);		if (ret)			PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);		else			PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);	}	/* All is done... */	pdev->iso_init = 1;	PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");	return 0;}void pwc_isoc_cleanup(struct pwc_device *pdev){	int i;	PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");	if (pdev == NULL)		return;	if (pdev->iso_init == 0)		return;	/* Unlinking ISOC buffers one by one */	for (i = 0; i < MAX_ISO_BUFS; i++) {		struct urb *urb;		urb = pdev->sbuf[i].urb;		if (urb != 0) {			if (pdev->iso_init) {				PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);				usb_kill_urb(urb);			}			PWC_DEBUG_MEMORY("Freeing URB\n");			usb_free_urb(urb);			pdev->sbuf[i].urb = NULL;		}	}	/* Stop camera, but only if we are sure the camera is still there (unplug	   is signalled by EPIPE) 	 */	if (pdev->error_status && pdev->error_status != EPIPE) {		PWC_DEBUG_OPEN("Setting alternate interface 0.\n");		usb_set_interface(pdev->udev, 0, 0);	}	pdev->iso_init = 0;	PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");}int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot){	int ret, start;	/* Stop isoc stuff */	pwc_isoc_cleanup(pdev);	/* Reset parameters */	pwc_reset_buffers(pdev);	/* Try to set video mode... */	start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);	if (ret) { 	        PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n");		/* That failed... restore old mode (we know that worked) */		start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);		if (start) {		        PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n");		}	}	if (start == 0)	{		if (pwc_isoc_init(pdev) < 0)		{			PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n");			ret = -EAGAIN; /* let's try again, who knows if it works a second time */		}	}	pdev->drop_frames++; /* try to avoid garbage during switch */	return ret; /* Return original error code */}/********* * sysfs *********/static struct pwc_device *cd_to_pwc(struct class_device *cd){	struct video_device *vdev = to_video_device(cd);	return video_get_drvdata(vdev);}static ssize_t show_pan_tilt(struct class_device *class_dev, char *buf){	struct pwc_device *pdev = cd_to_pwc(class_dev);	return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);}static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf,			 size_t count){	struct pwc_device *pdev = cd_to_pwc(class_dev);	int pan, tilt;	int ret = -EINVAL;	if (strncmp(buf, "reset", 5) == 0)		ret = pwc_mpt_reset(pdev, 0x3);	else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)		ret = pwc_mpt_set_angle(pdev, pan, tilt);	if (ret < 0)		return ret;	return strlen(buf);}static CLASS_DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,			 store_pan_tilt);static ssize_t show_snapshot_button_status(struct class_device *class_dev, char *buf){	struct pwc_device *pdev = cd_to_pwc(class_dev);	int status = pdev->snapshot_button_status;	pdev->snapshot_button_status = 0;	return sprintf(buf, "%d\n", status);}static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,			 NULL);static void pwc_create_sysfs_files(struct video_device *vdev){	struct pwc_device *pdev = video_get_drvdata(vdev);	if (pdev->features & FEATURE_MOTOR_PANTILT)		video_device_create_file(vdev, &class_device_attr_pan_tilt);	video_device_create_file(vdev, &class_device_attr_button);}static void pwc_remove_sysfs_files(struct video_device *vdev){	struct pwc_device *pdev = video_get_drvdata(vdev);	if (pdev->features & FEATURE_MOTOR_PANTILT)		video_device_remove_file(vdev, &class_device_attr_pan_tilt);	video_device_remove_file(vdev, &class_device_attr_button);}#if CONFIG_PWC_DEBUGstatic const char *pwc_sensor_type_to_string(unsigned int sensor_type){	switch(sensor_type) {		case 0x00:			return "Hyundai CMOS sensor";		case 0x20:		      	return "Sony CCD sensor + TDA8787";		case 0x2E:		      	return "Sony CCD sensor + Exas 98L59";		case 0x2F:		      	return "Sony CCD sensor + ADI 9804";		case 0x30:		      	return "Sharp CCD sensor + TDA8787";		case 0x3E:		      	return "Sharp CCD sensor + Exas 98L59";		case 0x3F:		      	return "Sharp CCD sensor + ADI 9804";		case 0x40:		      	return "UPA 1021 sensor";		case 0x100:		       	return "VGA sensor";		case 0x101:		       	return "PAL MR sensor";		default:		    	return "unknown type of sensor";	}}#endif/***************************************************************************//* Video4Linux functions */static int pwc_video_open(struct inode *inode, struct file *file){	int i, ret;	struct video_device *vdev = video_devdata(file);	struct pwc_device *pdev;	PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);		pdev = (struct pwc_device *)vdev->priv;	if (pdev == NULL)		BUG();	if (pdev->vopen) {		PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");		return -EBUSY;	}		down(&pdev->modlock);	if (!pdev->usb_init) {		PWC_DEBUG_OPEN("Doing first time initialization.\n");		pdev->usb_init = 1;		/* Query sensor type */		ret = pwc_get_cmos_sensor(pdev, &i);		if (ret >= 0)		{			PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",				       	pdev->vdev->name, 					pwc_sensor_type_to_string(i), i);		}	}	/* Turn on camera */	if (power_save) {		i = pwc_camera_power(pdev, 1);		if (i < 0)			PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i);	}	/* Set LED on/off time */	if (pwc_set_leds(pdev, led_on, led_off) < 0)		PWC_DEBUG_OPEN("Failed to set LED on/off time.\n");		pwc_construct(pdev); /* set min/max sizes correct */	/* So far, so good. Allocate memory. */	i = pwc_allocate_buffers(pdev);	if (i < 0) {		PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");		pwc_free_buffers(pdev);		up(&pdev->modlock);		return i;	}		/* Reset buffers & parameters */	pwc_reset_buffers(pdev);	for (i = 0; i < pwc_mbufs; i++)		pdev->image_used[i] = 0;	pdev->vframe_count = 0;	pdev->vframes_dumped = 0;	pdev->vframes_error = 0;	pdev->visoc_errors = 0;	pdev->error_status = 0;	pwc_construct(pdev); /* set min/max sizes correct */	/* Set some defaults */	pdev->vsnapshot = 0;	/* Start iso pipe for video; first try the last used video size	   (or the default one); if that fails try QCIF/10 or QSIF/10;	   it that fails too, give up.	 */	i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);	if (i)	{		unsigned int default_resolution;		PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n");		if (pdev->type>= 730)			default_resolution = PSZ_QSIF;		else			default_resolution = PSZ_QCIF;		i = pwc_set_video_mode(pdev,			       	       pwc_image_sizes[default_resolution].x,				       pwc_image_sizes[default_resolution].y,				       10,				       pdev->vcompression,				       0);	}	if (i) {		PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");		pwc_free_buffers(pdev);		up(&pdev->modlock);		return i;	}		i = pwc_isoc_init(pdev);	if (i) {		PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i);		pwc_isoc_cleanup(pdev);		pwc_free_buffers(pdev);		up(&pdev->modlock);		return i;	}	/* Initialize the webcam to sane value */	pwc_set_brightness(pdev, 0x7fff);	pwc_set_agc(pdev, 1, 0);	pdev->vopen++;	file->private_data = vdev;	up(&pdev->modlock);	PWC_DEBUG_OPEN("<< video_open() returns 0.\n");	return 0;}/* Note that all cleanup is done in the reverse order as in _open */static int pwc_video_close(struct inode *inode, struct file *file){	struct video_device *vdev = file->private_data;	struct pwc_device *pdev;	int i;

⌨️ 快捷键说明

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