Subject: [PATCH 5 of 8] USB pwc driver update
From: Greg KH <[email-masked]>
To: [email-masked]
Cc: [email-masked]

Hi,

Here's a patch against 2.5.2-pre7 that updates the USB pwc video driver
to the latest version.  The patch was written by Nemosoft.

thanks,

greg k-h

diff -Nru a/drivers/usb/pwc-ctrl.c b/drivers/usb/pwc-ctrl.c
--- a/drivers/usb/pwc-ctrl.c	Thu Jan  3 16:45:34 2002
+++ b/drivers/usb/pwc-ctrl.c	Thu Jan  3 16:45:34 2002
@@ -1008,6 +1008,8 @@
 
 	if (pdev->type < 730)
 		return 0;
+	on_value /= 100;
+	off_value /= 100;
 	if (on_value < 0)
 		on_value = 0;
 	if (on_value > 0xff)
@@ -1048,8 +1050,8 @@
 
 	if (ret < 0)
 		return ret;
-	*on_value = buf[0];
-	*off_value = buf[1];
+	*on_value = buf[0] * 100;
+	*off_value = buf[1] * 100;
 	return 0;
 }
 
@@ -1175,6 +1177,8 @@
 			wb.read_red = pwc_read_red_gain(pdev);
 			wb.read_blue = pwc_read_blue_gain(pdev);
 		}
+		if (copy_to_user(arg, &wb, sizeof(wb)))
+			return -EFAULT;
 		break;
 	}
 
diff -Nru a/drivers/usb/pwc-if.c b/drivers/usb/pwc-if.c
--- a/drivers/usb/pwc-if.c	Thu Jan  3 16:45:34 2002
+++ b/drivers/usb/pwc-if.c	Thu Jan  3 16:45:34 2002
@@ -39,7 +39,10 @@
 
 /* Contributors:
    - Alvarado: adding whitebalance code
-   - Alistar Moire: QuickCam 3000 Pro testing
+   - Alistar Moire: QuickCam 3000 Pro device/product ID
+   - Tony Hoyle: Creative Labs Webcam 5 device/product ID
+   - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
+   - Jk Fang: SOTEC device/product ID
 */
 
 #include <linux/errno.h>
@@ -76,6 +79,8 @@
 	{ USB_DEVICE(0x046D, 0x08b0) },
 	{ USB_DEVICE(0x055D, 0x9000) },
 	{ USB_DEVICE(0x055D, 0x9001) },
+	{ USB_DEVICE(0x041E, 0x400C) },
+	{ USB_DEVICE(0x04CC, 0x8116) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, pwc_device_table);
@@ -887,6 +892,7 @@
 	/* Stop camera, but only if we are sure the camera is still there */
 	if (!pdev->unplugged)
 		usb_set_interface(pdev->udev, 0, 0);
+	/* Unlinking ISOC buffers one by one */
 	for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
 		pdev->sbuf[i].urb->next = NULL;
 		usb_unlink_urb(pdev->sbuf[i].urb);
@@ -1493,6 +1499,12 @@
 			 */
 			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);
@@ -1710,7 +1722,29 @@
 			break;
 		}
 	}
-	else return NULL; /* Not Philips, Askey, Logitech or Samsung, for sure. */
+	else if (vendor_id == 0x041e) {
+		switch(product_id) {
+		case 0x400c:
+			Info("Creative Labs Webcam 5 detected.\n");
+			type_id = 730;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+	}
+	else if (vendor_id == 0x04cc) { 
+		switch(product_id) {
+		case 0x8116:
+			Info("SOTEC CMS-001 USB webcam detected.\n");
+			type_id = 730;
+			break;  
+		default:
+			return NULL;
+			break;
+		}
+	}
+	else return NULL; /* Not Philips, Askey, Logitech, Samsung, Creative or SOTEC, for sure. */
 
 	memset(serial_number, 0, 30);
 	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
@@ -1780,16 +1814,6 @@
 	if (hint < MAX_DEV_HINTS) 
 		device_hint[hint].pdev = pdev;
 
-#if 0
-	/* Shut down camera now (some people like the LED off) */
-	if (power_save) {
-		Trace(TRACE_PROBE, "Powering down camera");
-		i = pwc_camera_power(pdev, 0);
-		if (i < 0)
-			Info("Failed to power-down the camera (%d)\n", i);
-	}
-#endif
-
 	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
 	return pdev;
 }
@@ -1799,6 +1823,7 @@
 {
 	struct pwc_device *pdev;
 	int hint;
+	DECLARE_WAITQUEUE(wait, current);
 
 	lock_kernel();
 	free_mem_leak();
@@ -1833,13 +1858,19 @@
 			 */
 			wake_up(&pdev->frameq);
 			
-			/* Wait until we get a 'go' from _close(). This
-			   had a gigantic race condition, since we kfree()
+			/* Wait until we get a 'go' from _close(). This used
+			   to have a gigantic race condition, since we kfree()
 			   stuff here, but we have to wait until close() 
-			   is finished. */
+			   is finished. 
+			 */
 			   
 			Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
-			sleep_on(&pdev->remove_ok);
+			add_wait_queue(&pdev->remove_ok, &wait);
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			/* ... wait ... */
+			schedule();
+			remove_wait_queue(&pdev->remove_ok, &wait);
+			set_current_state(TASK_RUNNING);
 			Trace(TRACE_PROBE, "Done sleeping.\n");
 			set_mem_leak(pdev->vdev);
 			pdev->vdev = NULL;
@@ -1920,7 +1951,7 @@
 	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
 
 	Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
-	Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro and the Samsung MPC-C10 and MPC-C30.\n");
+	Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30, the Creative WebCam 5 and the SOTEC CMS-001.\n");
 
 	if (fps) {
 		if (fps < 5 || fps > 30) {
diff -Nru a/drivers/usb/pwc-ioctl.h b/drivers/usb/pwc-ioctl.h
--- a/drivers/usb/pwc-ioctl.h	Thu Jan  3 16:45:35 2002
+++ b/drivers/usb/pwc-ioctl.h	Thu Jan  3 16:45:35 2002
@@ -79,8 +79,8 @@
 /* Used with VIDIOCPWC[SG]LED */
 struct pwc_leds
 {
-	int led_on;			/* Led on-time; range = 0..255 */
-	int led_off;			/*  */
+	int led_on;			/* Led on-time; range = 0..25000 */
+	int led_off;			/* Led off-time; range = 0..25000  */
 };

diff -Nru a/drivers/usb/pwc.h b/drivers/usb/pwc.h
--- a/drivers/usb/pwc.h	Thu Jan  3 16:45:35 2002
+++ b/drivers/usb/pwc.h	Thu Jan  3 16:45:35 2002
@@ -60,8 +60,8 @@
 
 /* Version block */
 #define PWC_MAJOR	8
-#define PWC_MINOR	4
-#define PWC_VERSION 	"8.4"
+#define PWC_MINOR	5
+#define PWC_VERSION 	"8.5"
 #define PWC_NAME 	"pwc"
 
 /* Turn certain features on/off */