GoboLinux Downloads Documentation Community Recipes Screenshots

GoboLinux Recipe & Package Search Tool

71 versions of Linux.

ProgramAgeSizeByWWWSummary
Linux 4.13.2-r1 761  88794 Luca...
The Linux Kernel.
Linux 4.9.16-r3 932  100651 Luca...
The Linux Kernel.
Linux 4.9.4-r5 988  99374 Luca...
The Linux Kernel.
Linux 4.8.2-r2 1054  89394 Luca...
The Linux Kernel.
Linux 4.7.4-r1 1124  82767 Luca...
The Linux Kernel.
Linux 4.7.0-r4 1179  82585 Luca...
The Linux Kernel.
Linux 3.13.3-r1 2059  252629 Luca...
The Linux Kernel.
Linux 3.12.6-r1 2119  238949 Luca...
The Linux Kernel.
Linux 3.9.4-r2 2314  70048 Luca...
The Linux Kernel.
Linux 3.7.1-r2 2487  67579 Luca...
The Linux Kernel.
Linux 3.5.0-r1 2638  124391 Luca...
The Linux Kernel.
Linux 3.4.4-r1 2638  124348 Luca...
The Linux Kernel.
Linux 3.3.6-r1 2638  124410 Luca...
The Linux Kernel.
Linux 3.2.12-r2 2766  124345 Luca...
The Linux Kernel.
Linux 3.2.7-r1 2796  123550 Mich...
The Linux Kernel.
Linux 3.1.1-r1 2901  122907 Mich...
The Linux Kernel.
Linux 3.0.4-r4 2962  122754 Luca...
The Linux Kernel.
Linux 2.6.36.3-r1 3185  116087 Diog...
The Linux Kernel.
Linux 2.6.32.3-r1 3563  117990 Luca...
The Linux Kernel.
Linux 2.6.32-r1 3604  117751 Luca...
The Linux Kernel.
Linux 2.6.31.6-r3 3609  126499 Luca...
The Linux Kernel.
Linux 2.6.30.5-r1 3688  166102 Jona...
The Linux Kernel.
Linux 2.6.29.1-r1 3831  117500 Luca...
The Linux Kernel.
Linux 2.6.28.7-r1 3887  115518 Giam...
The Linux Kernel.
Linux 2.6.28.1-r1 3887  115487 Giam...
The Linux Kernel.
Linux 2.6.28-r1 3887  116681 Mich...
The Linux Kernel.
Linux 2.6.27.8-r1 3887  134160 Giam...
The Linux Kernel.
Linux 2.6.27.4-r3 3887  149529 Luca...
The Linux Kernel.
Linux 2.6.25.17-r1 3887  172834 Giam...
The Linux Kernel.
Linux 2.6.25.16-r1 3887  166500 Giam...
The Linux Kernel.
Linux 2.6.25.10-r2 3887  165320 Giam...
The Linux Kernel.
Linux 2.6.25.7-r1 3887  157294 Giam...
The Linux Kernel.
Linux 2.6.25.4-r1 3887  133017 Hopp...
The Linux Kernel.
Linux 2.6.25-r1 3887  133216 Luca...
The Linux Kernel.
Linux 2.6.24.4-r5 3887  150733
The Linux Kernel.
Linux 2.6.24.3-r5 3887  150221 Luca...
The Linux Kernel.
Linux 2.6.24.2-r3 3887  146488 Giam...
The Linux Kernel.
Linux 2.6.24.1-r1 3887  146454 Giam...
The Linux Kernel.
Linux 2.6.24-r1 3887  146428 Luca...
The Linux Kernel.
Linux 2.6.23.8-r4 3887  155842 Luca...
The Linux Kernel.
Linux 2.6.22.7-r4 3887  114727 Luca...
The Linux Kernel.
Linux 2.6.22.1-r1 3887  121391 Luca...
The Linux Kernel.
Linux 2.6.21.1-r3 3887  118854 Luca...
The Linux Kernel.
Linux 2.6.20.7-r1 3887  117945 Luca...
The Linux Kernel.
Linux 2.6.20.4-r3 3887  151150 Luca...
The Linux Kernel.
Linux 2.6.20-r1 3887  106429 Luca...
The Linux Kernel.
Linux 2.6.18.3-r2 3887  111124 Luca...
The Linux Kernel.
Linux 2.6.17.11-r1 3887  164053 Luca...
The Linux Kernel.
Linux 2.6.17.3-r1 3887  165067 Luca...
The Linux Kernel.
Linux 2.6.16.20-r1 3887  133625 Luca...
The Linux Kernel.
Linux 2.6.16.14-r1 3887  168270 Luca...
The Linux Kernel.
Linux 2.6.15.5-r1 3887  224686 Jona...
The Linux Kernel.
view entry at GitHub | download recipe.bz2 file
01-gobohide.patch
02-squashfs2.2.patch
03-squashfs-gobohide.patch
04-devfs.patch
05-bootsplash-3.1.6.patch
06-bootsplash-generic_fbdev.patch
07-unionfs_kmod.patch
08-acpi.patch
09-linux-2.6.15_pwc-10.0.11.patch
Recipe
Resources/Dependencies
Resources/Description
Resources/NewDependencies
i686/Recipe
i686/dot-config
ppc/Recipe
ppc/dot-config
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/Kconfig linux-2.6.15/drivers/usb/media/Kconfig
--- /tmp/linux-2.6.15.orig/drivers/usb/media/Kconfig	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/Kconfig	2006-01-08 01:24:23.000000000 +0100
@@ -197,9 +197,6 @@
 	  and never will be, but the 665 and 720/20 are supported by other 
 	  drivers.
 
-	  See <file:Documentation/usb/philips.txt> for more information and
-	  installation instructions.
-
 	  The built-in microphone is enabled by selecting USB Audio support.
 
 	  This driver uses the Video For Linux API. You must say Y or M to
@@ -210,4 +207,10 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called pwc.
 
+config PWC_DEBUG
+	bool "Enable full debugging output in pwc module."
+	depends on USB_PWC
+	---help---
+	  This option will enable debug tracing output for the pwc driver.  
+
 
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/Makefile linux-2.6.15/drivers/usb/media/pwc/Makefile
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/Makefile	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/Makefile	2006-01-08 01:24:23.000000000 +0100
@@ -1,20 +1,67 @@
+#
+# Makefile for the Linux Philips USB Webcam driver
+#
+# NOTE: This make file can serve as both an external Makefile (launched
+#       directly by the user), or as the sub-dir Makefile used by the kernel
+#       build system.
+
+# If CONFIG_USB_PWC isn't set, we'll assume the user want to build this driver has \
a module
+
+ifndef CONFIG_USB_PWC
+CONFIG_USB_PWC=m
+# Comment the next line, if you don't want debug message and a smaller binary
+CONFIG_PWC_DEBUG=y
+endif
+
 ifneq ($(KERNELRELEASE),)
 
-pwc-objs	:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o
+pwc-objs	:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
+pwc-objs	+= pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
 
 obj-$(CONFIG_USB_PWC) += pwc.o
 
+EXTRA_CFLAGS=-Wall -DXAWTV_HAS_BEEN_FIXED=1
+
+ifeq ($(CONFIG_PWC_DEBUG),y)
+EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1
 else
+EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0
+endif
 
-KDIR := /lib/modules/$(shell uname -r)/build
+else
+KVER  := $(shell uname -r)
+KLINK := $(shell test -e /lib/modules/${KVER}/source/ && echo source || echo build)
+KSRC  := /lib/modules/$(KVER)/$(KLINK)
+KMISC := /lib/modules/$(KVER)/kernel/drivers/usb/media
 PWD := $(shell pwd)
+EXTRA_CFLAGS=-Wall
+
+# Fix some problem with suse < 9.2 and suse >= 9.2
+is_suse := $(shell test -e /etc/SuSE-release && echo 1 || echo 0)
+ifeq ($(is_suse),1)
+  suse_version := $(shell grep VERSION /etc/SuSE-release | cut -f 3 -d " "| tr -d \
.)
+  is_suse_92_or_greater := $(shell test $(suse_version) -ge 92 && echo 1)
+  ifeq ($(is_suse_92_or_greater),1)
+    KSRC := /lib/modules/$(KVER)/build
+  endif
+endif
+
+
 
 default:
-	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+	$(MAKE) -C $(KSRC) SUBDIRS=$(PWD) modules
+
+install: default
+	install -d $(KMISC)
+	install -m 644 -c pwc.ko $(KMISC)
+	-/sbin/depmod -a
+
+uninstall:
+	-rm -rf $(KMISC)/pwc.ko
 
 endif
 
 clean:
-	rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c 
+	rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c
 	rm -rf .tmp_versions
 
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/philips.txt linux-2.6.15/drivers/usb/media/pwc/philips.txt
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/philips.txt	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/philips.txt	1970-01-01 01:00:00.000000000 \
+0100
@@ -1,236 +0,0 @@
-This file contains some additional information for the Philips and OEM webcams.
-E-mail: webcam@smcc.demon.nl                        Last updated: 2004-01-19
-Site: http://www.smcc.demon.nl/webcam/
-
-As of this moment, the following cameras are supported:
- * Philips PCA645
- * Philips PCA646
- * Philips PCVC675
- * Philips PCVC680
- * Philips PCVC690
- * Philips PCVC720/40
- * Philips PCVC730
- * Philips PCVC740
- * Philips PCVC750
- * Askey VC010
- * Creative Labs Webcam 5
- * Creative Labs Webcam Pro Ex
- * Logitech QuickCam 3000 Pro
- * Logitech QuickCam 4000 Pro
- * Logitech QuickCam Notebook Pro
- * Logitech QuickCam Zoom
- * Logitech QuickCam Orbit
- * Logitech QuickCam Sphere
- * Samsung MPC-C10
- * Samsung MPC-C30
- * Sotec Afina Eye
- * AME CU-001
- * Visionite VCS-UM100
- * Visionite VCS-UC300
-
-The main webpage for the Philips driver is at the address above. It contains
-a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
-contains decompression routines that allow you to use higher image sizes and
-framerates; in addition the webcam uses less bandwidth on the USB bus (handy
-if you want to run more than 1 camera simultaneously). These routines fall
-under a NDA, and may therefor not be distributed as source; however, its use
-is completely optional.
-
-You can build this code either into your kernel, or as a module. I recommend
-the latter, since it makes troubleshooting a lot easier. The built-in
-microphone is supported through the USB Audio class.
-
-When you load the module you can set some default settings for the
-camera; some programs depend on a particular image-size or -format and
-don't know how to set it properly in the driver. The options are:
-
-size
-   Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
-   'vga', for an image size of resp. 128x96, 160x120, 176x144,
-   320x240, 352x288 and 640x480 (of course, only for those cameras that 
-   support these resolutions).
-
-fps
-   Specifies the desired framerate. Is an integer in the range of 4-30.
-
-fbufs
-   This paramter specifies the number of internal buffers to use for storing 
-   frames from the cam. This will help if the process that reads images from 
-   the cam is a bit slow or momentarely busy. However, on slow machines it 
-   only introduces lag, so choose carefully. The default is 3, which is 
-   reasonable. You can set it between 2 and 5.
-
-mbufs
-   This is an integer between 1 and 10. It will tell the module the number of
-   buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
-   The default is 2, which is adequate for most applications (double
-   buffering).
-      
-   Should you experience a lot of 'Dumping frame...' messages during
-   grabbing with a tool that uses mmap(), you might want to increase if. 
-   However, it doesn't really buffer images, it just gives you a bit more
-   slack when your program is behind. But you need a multi-threaded or
-   forked program to really take advantage of these buffers.
-
-   The absolute maximum is 10, but don't set it too high!  Every buffer takes
-   up 460 KB of RAM, so unless you have a lot of memory setting this to
-   something more than 4 is an absolute waste.  This memory is only
-   allocated during open(), so nothing is wasted when the camera is not in
-   use.
-
-power_save
-   When power_save is enabled (set to 1), the module will try to shut down
-   the cam on close() and re-activate on open(). This will save power and
-   turn off the LED. Not all cameras support this though (the 645 and 646
-   don't have power saving at all), and some models don't work either (they
-   will shut down, but never wake up). Consider this experimental. By
-   default this option is disabled.
-
-compression (only useful with the plugin)
-   With this option you can control the compression factor that the camera
-   uses to squeeze the image through the USB bus. You can set the 
-   parameter between 0 and 3:
-     0 = prefer uncompressed images; if the requested mode is not available
-         in an uncompressed format, the driver will silently switch to low
-         compression.
-     1 = low compression.
-     2 = medium compression.
-     3 = high compression.
-      
-   High compression takes less bandwidth of course, but it could also
-   introduce some unwanted artefacts. The default is 2, medium compression.
-   See the FAQ on the website for an overview of which modes require
-   compression.
-
-   The compression parameter does not apply to the 645 and 646 cameras
-   and OEM models derived from those (only a few). Most cams honour this
-   parameter.
-
-leds
-   This settings takes 2 integers, that define the on/off time for the LED
-   (in milliseconds). One of the interesting things that you can do with
-   this is let the LED blink while the camera is in use. This:
-
-     leds=500,500
-      
-   will blink the LED once every second. But with:
-
-     leds=0,0
-
-   the LED never goes on, making it suitable for silent surveillance.
-
-   By default the camera's LED is on solid while in use, and turned off
-   when the camera is not used anymore.
-
-   This parameter works only with the ToUCam range of cameras (720, 730, 740,
-   750) and OEMs. For other cameras this command is silently ignored, and 
-   the LED cannot be controlled.
-
-   Finally: this parameters does not take effect UNTIL the first time you
-   open the camera device. Until then, the LED remains on.
-
-dev_hint
-   A long standing problem with USB devices is their dynamic nature: you
-   never know what device a camera gets assigned; it depends on module load
-   order, the hub configuration, the order in which devices are plugged in,
-   and the phase of the moon (i.e. it can be random). With this option you
-   can give the driver a hint as to what video device node (/dev/videoX) it
-   should use with a specific camera. This is also handy if you have two
-   cameras of the same model.
-
-   A camera is specified by its type (the number from the camera model,
-   like PCA645, PCVC750VC, etc) and optionally the serial number (visible
-   in /proc/bus/usb/devices). A hint consists of a string with the following
-   format:
-
-      [type[.serialnumber]:]node
-      
-   The square brackets mean that both the type and the serialnumber are
-   optional, but a serialnumber cannot be specified without a type (which
-   would be rather pointless). The serialnumber is separated from the type
-   by a '.'; the node number by a ':'.
-   
-   This somewhat cryptic syntax is best explained by a few examples:
-
-     dev_hint=3,5              The first detected cam gets assigned
-                               /dev/video3, the second /dev/video5. Any
-                               other cameras will get the first free 
-                               available slot (see below).
-
-     dev_hint=645:1,680:2      The PCA645 camera will get /dev/video1,
-                               and a PCVC680 /dev/video2.
-                               
-     dev_hint=645.0123:3,645.4567:0	The PCA645 camera with serialnumber 
-                                        0123 goes to /dev/video3, the same
-                                        camera model with the 4567 serial
-                                        gets /dev/video0.
-
-     dev_hint=750:1,4,5,6       The PCVC750 camera will get /dev/video1, the 
-                                next 3 Philips cams will use /dev/video4 
-                                through /dev/video6.
-
-   Some points worth knowing:
-   - Serialnumbers are case sensitive and must be written full, including 
-     leading zeroes (it's treated as a string).
-   - If a device node is already occupied, registration will fail and 
-     the webcam is not available.
-   - You can have up to 64 video devices; be sure to make enough device
-     nodes in /dev if you want to spread the numbers (this does not apply
-     to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA).
-   - If a camera does not match any dev_hint, it will simply get assigned
-     the first available device node, just as it used to be.
-
-trace
-   In order to better detect problems, it is now possible to turn on a
-   'trace' of some of the calls the module makes; it logs all items in your
-   kernel log at debug level.
-
-   The trace variable is a bitmask; each bit represents a certain feature.
-   If you want to trace something, look up the bit value(s) in the table 
-   below, add the values together and supply that to the trace variable.
-
-   Value  Value   Description					   Default
-   (dec)  (hex)
-       1    0x1   Module initialization; this will log messages       On
-                  while loading and unloading the module
-
-       2    0x2   probe() and disconnect() traces                     On
-
-       4    0x4   Trace open() and close() calls                      Off
-
-       8    0x8   read(), mmap() and associated ioctl() calls         Off
-
-      16   0x10   Memory allocation of buffers, etc.                  Off
-
-      32   0x20   Showing underflow, overflow and Dumping frame       On
-                  messages
-
-      64   0x40   Show viewport and image sizes                       Off
-
-     128   0x80   PWCX debugging                                      Off
-
-   For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
-   so you would supply trace=12 during insmod or modprobe. If
-   you want to turn the initialization and probing tracing off, set trace=0.
-   The default value for trace is 35 (0x23).
-
-
-
-Example:
-     
-     # modprobe pwc size=cif fps=15 power_save=1
-
-The fbufs, mbufs and trace parameters are global and apply to all connected
-cameras. Each camera has its own set of buffers.
-
-size and fps only specify defaults when you open() the device; this is to
-accommodate some tools that don't set the size. You can change these
-settings after open() with the Video4Linux ioctl() calls. The default of
-defaults is QCIF size at 10 fps.
-
-The compression parameter is semiglobal; it sets the initial compression
-preference for all camera's, but this parameter can be set per camera with
-the VIDIOCPWCSCQUAL ioctl() call.
-
-All parameters are optional.
-
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-ctrl.c linux-2.6.15/drivers/usb/media/pwc/pwc-ctrl.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-ctrl.c	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-ctrl.c	2006-01-08 01:25:14.000000000 +0100
@@ -2,7 +2,7 @@
    Functions that send various control messages to the webcam, including
    video modes.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -48,6 +48,8 @@
 #include "pwc-uncompress.h"
 #include "pwc-kiara.h"
 #include "pwc-timon.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 /* Request types: video */
 #define SET_LUM_CTL			0x01
@@ -95,11 +97,15 @@
 #define READ_RED_GAIN_FORMATTER			0x0700
 #define READ_BLUE_GAIN_FORMATTER		0x0800
 #define SENSOR_TYPE_FORMATTER1			0x0C00
+#define GET_STATUS_3000				0x3000
 #define READ_RAW_Y_MEAN_FORMATTER		0x3100
 #define SET_POWER_SAVE_MODE_FORMATTER		0x3200
 #define MIRROR_IMAGE_FORMATTER			0x3300
 #define LED_FORMATTER				0x3400
+#define LOWLIGHT				0x3500
+#define GET_STATUS_3600				0x3600
 #define SENSOR_TYPE_FORMATTER2			0x3700
+#define GET_STATUS_4100				0x4100	/* Get */
 
 /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
 #define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
@@ -109,7 +115,7 @@
 #define PT_RESET_CONTROL_FORMATTER		0x02
 #define PT_STATUS_FORMATTER			0x03
 
-static char *size2name[PSZ_MAX] =
+static const char *size2name[PSZ_MAX] =
 {
 	"subQCIF",
 	"QSIF",
@@ -139,6 +145,7 @@
 #include "pwc-nala.h"
 };
 
+static void pwc_set_image_buffer_size(struct pwc_device *pdev);
 
 /****************************************************************************/
 
@@ -160,31 +167,7 @@
 		&buf, buflen, 500)
 
 
-#if PWC_DEBUG
-void pwc_hexdump(void *p, int len)
-{
-	int i;
-	unsigned char *s;
-	char buf[100], *d;
-
-	s = (unsigned char *)p;
-	d = buf;
-	*d = '\0';
-	Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
-	for (i = 0; i < len; i++) {
-		d += sprintf(d, "%02X ", *s++);
-		if ((i & 0xF) == 0xF) {
-			Debug("%s\n", buf);
-			d = buf;
-			*d = '\0';
-		}
-	}
-	if ((i & 0xF) != 0)
-		Debug("%s\n", buf);
-}
-#endif
-
-static inline int send_video_command(struct usb_device *udev, int index, void *buf, \
int buflen)
+static int send_video_command(struct usb_device *udev, int index, void *buf, int \
buflen)
 {
 	return usb_control_msg(udev,
 		usb_sndctrlpipe(udev, 0),
@@ -197,7 +180,7 @@
 
 
 
-static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
 {
 	unsigned char buf[3];
 	int ret, fps;
@@ -230,34 +213,19 @@
 	if (pEntry->alternate == 0)
 		return -EINVAL;
 
-	if (pEntry->compressed)
-		return -ENOENT; /* Not supported. */
-
 	memcpy(buf, pEntry->mode, 3);	
 	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
 	if (ret < 0) {
-		Debug("Failed to send video command... %d\n", ret);
-		return ret;
+	      PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
+	      return ret;
 	}
-	if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
-	 {
-	   switch(pdev->type) {
-	     case 645:
-	     case 646:
-/*	       pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); \
*/
-	       break;
-
-	     case 675:
-	     case 680:
-	     case 690:
-	     case 720:
-	     case 730:
-	     case 740:
-	     case 750:
-/*	       pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); \
*/
-	       break;
-	   }
+	if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW) {
+	      if (DEVICE_USE_CODEC1(pdev->type)) 
+		    pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+	      else
+		    pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
 	}
+
  
 	pdev->cmd_len = 3;
 	memcpy(pdev->cmd_buf, buf, 3);
@@ -284,7 +252,7 @@
 }
 
 
-static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, \
int compression, int snapshot)
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int \
compression, int snapshot)
 {
 	unsigned char buf[13];
 	const struct Timon_table_entry *pChoose;
@@ -316,8 +284,8 @@
 	if (ret < 0)
 		return ret;
 
-/* 	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-	   pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
+	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+	   pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
 
 	pdev->cmd_len = 13;
 	memcpy(pdev->cmd_buf, buf, 13);
@@ -337,7 +305,7 @@
 }
 
 
-static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, \
int compression, int snapshot)
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int \
compression, int snapshot)
 {
 	const struct Kiara_table_entry *pChoose = NULL;
 	int fps, ret;
@@ -351,21 +319,14 @@
 	fps = (frames / 5) - 1;
 
 	/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
-	if (size == PSZ_VGA && frames == 5 && snapshot)
+	if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW)
 	{
 		/* Only available in case the raw palette is selected or 
 		   we have the decompressor available. This mode is 
 		   only available in compressed form 
 		*/
-		if (pdev->vpalette == VIDEO_PALETTE_RAW)
-		{
-	                Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
-			pChoose = &RawEntry;
-		}
-		else
-		{
-			Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n");
-		}
+		PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
+		pChoose = &RawEntry;
 	}
 	else
 	{
@@ -383,7 +344,7 @@
 	if (pChoose == NULL || pChoose->alternate == 0)
 		return -ENOENT; /* Not supported. */
 
-	Debug("Using alternate setting %d.\n", pChoose->alternate);
+	PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
 	
 	/* usb_control_msg won't take staticly allocated arrays as argument?? */
 	memcpy(buf, pChoose->mode, 12);
@@ -395,8 +356,8 @@
 	if (ret < 0)
 		return ret;
 
-/*	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-	  pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
+	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+	  pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
 
 	pdev->cmd_len = 12;
 	memcpy(pdev->cmd_buf, buf, 12);
@@ -411,11 +372,55 @@
 		pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
 	else
 		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+	PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n",
+	    pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength);
 	return 0;
 }
 
 
 
+/**
+   @pdev: device structure
+   @width: viewport width
+   @height: viewport height
+   @frame: framerate, in fps
+   @compression: preferred compression ratio
+   @snapshot: snapshot mode or streaming
+ */
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, \
int compression, int snapshot)
+{
+        int ret, size;
+
+        PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, \
frames, pdev->vpalette);
+	size = pwc_decode_size(pdev, width, height);
+	if (size < 0) {
+		PWC_DEBUG_MODULE("Could not find suitable size.\n");
+		return -ERANGE;
+	}
+	PWC_TRACE("decode_size = %d.\n", size);
+
+	if (DEVICE_USE_CODEC1(pdev->type)) {
+		ret = set_video_mode_Nala(pdev, size, frames);
+		
+	} else if (DEVICE_USE_CODEC3(pdev->type)) {
+		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
+
+	} else {
+		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+	}
+	if (ret < 0) {
+		PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], \
frames, ret);
+		return ret;
+	}
+	pdev->view.x = width;
+	pdev->view.y = height;
+	pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
+	pwc_set_image_buffer_size(pdev);
+	PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, \
pwc_image_sizes[size].x, pwc_image_sizes[size].y);
+	return 0;
+}
+
+
 static void pwc_set_image_buffer_size(struct pwc_device *pdev)
 {
 	int i, factor = 0, filler = 0;
@@ -446,71 +451,14 @@
 	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
 
 	/* Fill buffers with gray or black */
-	for (i = 0; i < MAX_IMAGES; i++) {
-		if (pdev->image_ptr[i] != NULL)
-			memset(pdev->image_ptr[i], filler, pdev->view.size);
+	for (i = 0; i < pwc_mbufs; i++) {
+		if (pdev->images[i].bufmem != NULL)
+			memset(pdev->images[i].bufmem, filler, pdev->view.size);
 	}
 }
 
 
 
-/**
-   @pdev: device structure
-   @width: viewport width
-   @height: viewport height
-   @frame: framerate, in fps
-   @compression: preferred compression ratio
-   @snapshot: snapshot mode or streaming
- */
-int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, \
int compression, int snapshot)
-{
-        int ret, size;
-
-        Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, \
frames, pdev->vpalette);
-	size = pwc_decode_size(pdev, width, height);
-	if (size < 0) {
-		Debug("Could not find suitable size.\n");
-		return -ERANGE;
-	}
-	Debug("decode_size = %d.\n", size);
-
-        ret = -EINVAL;
-	switch(pdev->type) {
-	case 645:
-	case 646:
-		ret = set_video_mode_Nala(pdev, size, frames);
-		break;
-
-	case 675:
-	case 680:
-	case 690:
-		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
-		break;
-	
-	case 720:
-	case 730:
-	case 740:
-	case 750:
-		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
-		break;
-	}
-	if (ret < 0) {
-		if (ret == -ENOENT)
-			Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", \
size2name[size], frames);
-		else {
-			Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], \
frames, ret);
-		}
-		return ret;
-	}
-	pdev->view.x = width;
-	pdev->view.y = height;
-	pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
-	pwc_set_image_buffer_size(pdev);
-	Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, \
pwc_image_sizes[size].x, pwc_image_sizes[size].y);
-	return 0;
-}
-
-
 /* BRIGHTNESS */
 
 int pwc_get_brightness(struct pwc_device *pdev)
@@ -521,7 +469,7 @@
 	ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);	
 	if (ret < 0)
 		return ret;
-	return buf << 9;
+	return buf;
 }
 
 int pwc_set_brightness(struct pwc_device *pdev, int value)
@@ -546,7 +494,7 @@
 	ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	return buf << 10;
+	return buf;
 }
 
 int pwc_set_contrast(struct pwc_device *pdev, int value)
@@ -571,7 +519,7 @@
 	ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	return buf << 11;
+	return buf;
 }
 
 int pwc_set_gamma(struct pwc_device *pdev, int value)
@@ -589,37 +537,47 @@
 
 /* SATURATION */
 
-int pwc_get_saturation(struct pwc_device *pdev)
+/* return a value between [-100 , 100] */
+int pwc_get_saturation(struct pwc_device *pdev, int *value)
 {
 	char buf;
-	int ret;
+	int ret, saturation_register;
 
 	if (pdev->type < 675)
-		return -1;
-	ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 \
: SATURATION_MODE_FORMATTER1, 1);
+		return -EINVAL;
+	if (pdev->type < 730)
+		saturation_register = SATURATION_MODE_FORMATTER2;
+	else
+		saturation_register = SATURATION_MODE_FORMATTER1;
+	ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1);
 	if (ret < 0)
 		return ret;
-	return 32768 + buf * 327;
+	*value = (signed)buf;
+	return 0;
 }
 
+/* @param value saturation color between [-100 , 100] */
 int pwc_set_saturation(struct pwc_device *pdev, int value)
 {
 	char buf;
+	int saturation_register;
 
 	if (pdev->type < 675)
 		return -EINVAL;
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	/* saturation ranges from -100 to +100 */
-	buf = (value - 32768) / 327;
-	return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 \
: SATURATION_MODE_FORMATTER1, 1);
+	if (value < -100)
+		value = -100;
+	if (value > 100)
+		value = 100;
+	if (pdev->type < 730)
+		saturation_register = SATURATION_MODE_FORMATTER2;
+	else
+		saturation_register = SATURATION_MODE_FORMATTER1;
+	return SendControlMsg(SET_CHROM_CTL, saturation_register, 1);
 }
 
 /* AGC */
 
-static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
+int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
 {
 	char buf;
 	int ret;
@@ -644,7 +602,7 @@
 	return 0;
 }
 
-static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
+int pwc_get_agc(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -674,7 +632,7 @@
 	return 0;
 }
 
-static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
+int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
 {
 	char buf[2];
 	int speed, ret;
@@ -692,23 +650,16 @@
 			value = 0;
 		if (value > 0xffff)
 			value = 0xffff;
-		switch(pdev->type) {
-		case 675:
-		case 680:
-		case 690:
+
+		if (DEVICE_USE_CODEC2(pdev->type)) {
 			/* speed ranges from 0x0 to 0x290 (656) */
 			speed = (value / 100);
 			buf[1] = speed >> 8;
 			buf[0] = speed & 0xff;
-			break;
-		case 720:
-		case 730:
-		case 740:
-		case 750:
+		} else if (DEVICE_USE_CODEC3(pdev->type)) {
 			/* speed seems to range from 0x0 to 0xff */
 			buf[1] = 0;
 			buf[0] = value >> 8;
-			break;
 		}
 
 		ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
@@ -716,6 +667,25 @@
 	return ret;
 }	
 
+/* This function is not exported to v4l1, so output values between 0 -> 256 */
+int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf[2];
+	int ret;
+	
+	ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2);
+	if (ret < 0)
+		return ret;
+	*value = buf[0] + (buf[1] << 8);
+	if (DEVICE_USE_CODEC2(pdev->type)) {
+		/* speed ranges from 0x0 to 0x290 (656) */
+		*value *= 256/656;
+	} else if (DEVICE_USE_CODEC3(pdev->type)) {
+		/* speed seems to range from 0x0 to 0xff */
+	}
+	return 0;
+}
+
 
 /* POWER */
 
@@ -737,19 +707,19 @@
 
 /* private calls */
 
-static inline int pwc_restore_user(struct pwc_device *pdev)
+int pwc_restore_user(struct pwc_device *pdev)
 {
 	char buf; /* dummy */
 	return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0);
 }
 
-static inline int pwc_save_user(struct pwc_device *pdev)
+int pwc_save_user(struct pwc_device *pdev)
 {
 	char buf; /* dummy */
 	return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0);
 }
 
-static inline int pwc_restore_factory(struct pwc_device *pdev)
+int pwc_restore_factory(struct pwc_device *pdev)
 {
 	char buf; /* dummy */
 	return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0);
@@ -767,7 +737,7 @@
   * 03: manual
   * 04: auto
   */ 
-static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
+int pwc_set_awb(struct pwc_device *pdev, int mode)
 {
 	char buf;
 	int ret;
@@ -787,7 +757,7 @@
 	return 0;
 }
 
-static inline int pwc_get_awb(struct pwc_device *pdev)
+int pwc_get_awb(struct pwc_device *pdev)
 {
 	unsigned char buf;
 	int ret;
@@ -799,7 +769,7 @@
 	return buf;
 }
 
-static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
+int pwc_set_red_gain(struct pwc_device *pdev, int value)
 {
         unsigned char buf;
 
@@ -812,7 +782,7 @@
 	return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
 }
 
-static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
+int pwc_get_red_gain(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -825,7 +795,7 @@
 }
 
 
-static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
+int pwc_set_blue_gain(struct pwc_device *pdev, int value)
 {
 	unsigned char buf;
 
@@ -838,7 +808,7 @@
 	return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
 }
 
-static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
+int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -855,7 +825,7 @@
    internal red/blue gains, which may be different from the manual 
    gains set or read above.
  */   
-static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
+static int pwc_read_red_gain(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -867,7 +837,7 @@
 	return 0;
 }
 
-static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
+static int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -880,7 +850,7 @@
 }
 
 
-static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
+static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
 {
 	unsigned char buf;
 	
@@ -889,7 +859,7 @@
 	return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
 }
 
-static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
+static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -902,7 +872,7 @@
 }
 
 
-static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
+static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
 {
 	unsigned char buf;
 	
@@ -911,7 +881,7 @@
 	return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
 }
 
-static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
+static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -947,7 +917,7 @@
 	return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
 }
 
-static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
+int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
 {
 	unsigned char buf[2];
 	int ret;
@@ -966,7 +936,7 @@
 	return 0;
 }
 
-static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
+int pwc_set_contour(struct pwc_device *pdev, int contour)
 {
 	unsigned char buf;
 	int ret;
@@ -991,7 +961,7 @@
 	return 0;
 }
 
-static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
+int pwc_get_contour(struct pwc_device *pdev, int *contour)
 {
 	unsigned char buf;
 	int ret;
@@ -1013,7 +983,7 @@
 }
 
 
-static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
+int pwc_set_backlight(struct pwc_device *pdev, int backlight)
 {
 	unsigned char buf;
 	
@@ -1024,7 +994,7 @@
 	return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
 }
 
-static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
+int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
 {
 	int ret;
 	unsigned char buf;
@@ -1032,12 +1002,35 @@
 	ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	*backlight = buf;
+	*backlight = !!buf;
 	return 0;
 }
 
+int pwc_set_colour_mode(struct pwc_device *pdev, int colour)
+{
+	unsigned char buf;
+	
+	if (colour)
+		buf = 0xff;
+	else
+		buf = 0x0;
+	return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
+}
 
-static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
+int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
+{
+	int ret;
+	unsigned char buf;
+	
+	ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*colour = !!buf;
+	return 0;
+}
+
+
+int pwc_set_flicker(struct pwc_device *pdev, int flicker)
 {
 	unsigned char buf;
 	
@@ -1048,7 +1041,7 @@
 	return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
 }
 
-static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
+int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
 {
 	int ret;
 	unsigned char buf;
@@ -1056,12 +1049,11 @@
 	ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	*flicker = buf;
+	*flicker = !!buf;
 	return 0;
 }
 
-
-static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
+int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
 {
 	unsigned char buf;
 
@@ -1073,7 +1065,7 @@
 	return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
 }
 
-static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
+int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
 {
 	int ret;
 	unsigned char buf;
@@ -1085,7 +1077,7 @@
 	return 0;
 }
 
-static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
 {
 	unsigned char buf;
 	
@@ -1093,7 +1085,18 @@
 	return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
 }
 
-static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+{
+	int ret;
+	ret = _pwc_mpt_reset(pdev, flags);
+	if (ret >= 0) {
+		pdev->pan_angle = 0;
+		pdev->tilt_angle = 0;
+	}
+	return ret;
+}
+
+static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
 {
 	unsigned char buf[4];
 	
@@ -1111,7 +1114,35 @@
 	return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
 }
 
-static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status \
*status)
+int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+{
+	int ret;
+
+	/* check absolute ranges */
+	if (pan  < pdev->angle_range.pan_min  ||
+	    pan  > pdev->angle_range.pan_max  ||
+	    tilt < pdev->angle_range.tilt_min ||
+	    tilt > pdev->angle_range.tilt_max)
+		return -ERANGE;
+
+	/* go to relative range, check again */
+	pan  -= pdev->pan_angle;
+	tilt -= pdev->tilt_angle;
+	/* angles are specified in degrees * 100, thus the limit = 36000 */
+	if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)
+		return -ERANGE;
+
+	ret = _pwc_mpt_set_angle(pdev, pan, tilt);
+	if (ret >= 0) {
+		pdev->pan_angle  += pan;
+		pdev->tilt_angle += tilt;
+	}
+	if (ret == -EPIPE) /* stall -> out of range */
+		ret = -ERANGE;				
+	return ret;
+}
+
+static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
 {
 	int ret;
 	unsigned char buf[5];
@@ -1468,11 +1499,6 @@
 
  			ARG_IN(flags)
 			ret = pwc_mpt_reset(pdev, ARGR(flags));
- 			if (ret >= 0)
- 			{
- 				pdev->pan_angle = 0;
- 				pdev->tilt_angle = 0;
- 			}
  		}
  		else
  		{
@@ -1519,35 +1545,8 @@
  				new_pan  = pdev->pan_angle  + ARGR(angles).pan;
  				new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
 			}
-			/* check absolute ranges */
-			if (new_pan  < pdev->angle_range.pan_min  ||
-			    new_pan  > pdev->angle_range.pan_max  ||
-			    new_tilt < pdev->angle_range.tilt_min ||
-			    new_tilt > pdev->angle_range.tilt_max)
-			{
-				ret = -ERANGE;
-			}
-			else
-			{
-				/* go to relative range, check again */
-				new_pan  -= pdev->pan_angle;
-				new_tilt -= pdev->tilt_angle;
-				/* angles are specified in degrees * 100, thus the limit = 36000 */
-				if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000)
-					ret = -ERANGE;
-			}
-			if (ret == 0) /* no errors so far */
-			{
-				ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
-				if (ret >= 0)
-				{
-					pdev->pan_angle  += new_pan;
-					pdev->tilt_angle += new_tilt;
-				}
-				if (ret == -EPIPE) /* stall -> out of range */
-					ret = -ERANGE;				
-			}
- 		}
+			ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
+		}
  		else
  		{
  			ret = -ENXIO;
@@ -1625,4 +1624,4 @@
 }
 
 
-
+/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-dec1.c linux-2.6.15/drivers/usb/media/pwc/pwc-dec1.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-dec1.c	1970-01-01 01:00:00.000000000 \
+0100
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-dec1.c	2006-01-08 01:25:14.000000000 +0100
@@ -0,0 +1,50 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 1
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+
+#include "pwc-dec1.h"
+
+
+void pwc_dec1_init(int type, int release, void *buffer, void *table)
+{
+
+}
+
+void pwc_dec1_exit(void)
+{
+
+
+
+}
+
+int pwc_dec1_alloc(struct pwc_device *pwc)
+{
+	pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
+	if (pwc->decompress_data == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-dec1.h linux-2.6.15/drivers/usb/media/pwc/pwc-dec1.h
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-dec1.h	1970-01-01 01:00:00.000000000 \
+0100
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-dec1.h	2006-01-08 01:25:14.000000000 +0100
@@ -0,0 +1,43 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+
+#ifndef PWC_DEC1_H
+#define PWC_DEC1_H
+
+#include "pwc.h"
+
+struct pwc_dec1_private
+{
+	int version;
+
+};
+
+int  pwc_dec1_alloc(struct pwc_device *pwc);
+void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
+void pwc_dec1_exit(void);
+
+#endif
+
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-dec23.c linux-2.6.15/drivers/usb/media/pwc/pwc-dec23.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-dec23.c	1970-01-01 01:00:00.000000000 \
+0100
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-dec23.c	2006-01-08 01:25:14.000000000 \
+0100
@@ -0,0 +1,627 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 2 et 3
+   (C) 2004-2006  Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include "pwc-timon.h"
+#include "pwc-kiara.h"
+#include "pwc-dec23.h"
+#include "pwc-ioctl.h"
+
+#include <linux/string.h>
+
+static void fill_table_a000(unsigned int *p)
+{
+	static unsigned int initial_values[12] = {
+		0xFFAD9B00, 0xFFDDEE00, 0x00221200, 0x00526500,
+		0xFFC21E00, 0x003DE200, 0xFF924B80, 0xFFD2A300,
+		0x002D5D00, 0x006DB480, 0xFFED3E00, 0x0012C200
+	};
+	static unsigned int values_derivated[12] = {
+		0x0000A4CA, 0x00004424, 0xFFFFBBDC, 0xFFFF5B36,
+		0x00007BC4, 0xFFFF843C, 0x0000DB69, 0x00005ABA,
+		0xFFFFA546, 0xFFFF2497, 0x00002584, 0xFFFFDA7C
+	};
+	unsigned int temp_values[12];
+	int i, j;
+
+	memcpy(temp_values, initial_values, sizeof(initial_values));
+	for (i = 0; i < 256; i++) {
+		for (j = 0; j < 12; j++) {
+			*p++ = temp_values[j];
+			temp_values[j] += values_derivated[j];
+		}
+	}
+}
+
+static void fill_table_d000(unsigned char *p)
+{
+	int bit, byte;
+
+	for (bit = 0; bit < 8; bit++) {
+		unsigned char bitpower = 1 << bit;
+		unsigned char mask = bitpower - 1;
+		for (byte = 0; byte < 256; byte++) {
+			if (byte & bitpower)
+				*p++ = -(byte & mask);
+			else
+				*p++ = (byte & mask);
+		}
+	}
+}
+
+/*
+ *
+ * Kiara: 0 <= ver <= 7
+ * Timon: 0 <= ver <= 15
+ *
+ */
+static void fill_table_color(unsigned int version, const unsigned int *romtable,
+		      unsigned char *p0004, unsigned char *p8004)
+{
+	const unsigned int *table;
+	unsigned char *p0, *p8;
+	int i, j, k;
+	int dl, bit, pw;
+
+	romtable += version * 256;
+
+	for (i = 0; i < 2; i++) {
+		table = romtable + i * 128;
+
+		for (dl = 0; dl < 16; dl++) {
+			p0 = p0004 + (i << 14) + (dl << 10);
+			p8 = p8004 + (i << 12) + (dl << 8);
+
+			for (j = 0; j < 8; j++, table++, p0 += 128) {
+				for (k = 0; k < 16; k++) {
+					if (k == 0)
+						bit = 1;
+					else if (k >= 1 && k < 3)
+						bit = (table[0] >> 15) & 7;
+					else if (k >= 3 && k < 6)
+						bit = (table[0] >> 12) & 7;
+					else if (k >= 6 && k < 10)
+						bit = (table[0] >> 9) & 7;
+					else if (k >= 10 && k < 13)
+						bit = (table[0] >> 6) & 7;
+					else if (k >= 13 && k < 15)
+						bit = (table[0] >> 3) & 7;
+					else
+						bit = (table[0]) & 7;
+					if (k == 0)
+						*(unsigned char *)p8++ = 8;
+					else
+						*(unsigned char *)p8++ =
+						    j - bit;
+					*(unsigned char *)p8++ = bit;
+
+					pw = 1 << bit;
+					p0[k + 0x00] = (1 * pw) + 0x80;
+					p0[k + 0x10] = (2 * pw) + 0x80;
+					p0[k + 0x20] = (3 * pw) + 0x80;
+					p0[k + 0x30] = (4 * pw) + 0x80;
+					p0[k + 0x40] = (-pw) + 0x80;
+					p0[k + 0x50] = (2 * -pw) + 0x80;
+					p0[k + 0x60] = (3 * -pw) + 0x80;
+					p0[k + 0x70] = (4 * -pw) + 0x80;
+				}	/* end of for (k=0; k<16; k++, p8++) */
+			}	/* end of for (j=0; j<8; j++ , table++) */
+		}		/* end of for (dl=0; dl<16; dl++) */
+	}			/* end of for (i=0; i<2; i++) */
+}
+
+/*
+ * precision = (pdev->xx + pdev->yy)
+ *
+ */
+static void fill_table_dc00_d800(unsigned int *pdc00, unsigned int *pd800)
+{
+  int i = 0;
+  unsigned int offset1 = 0x4000;
+  unsigned int offset2 = 0x0000;
+
+  while (i<256) {
+       unsigned int msb = offset1 >> 15;
+  
+       if (msb > 255)
+         msb = 0;
+  
+       *pdc00++ = msb << 15;
+       *pd800++ = offset2;
+  
+       i++;
+       offset1 += 0x7BC4;
+       offset2 += 0x7BC4;
+  }
+}
+
+/*
+ * struct {
+ *   unsigned char op;	    // operation to execute
+ *   unsigned char bits;    // bits use to perform operation
+ *   unsigned char offset1; // offset to add to access in the table_0004 % 16
+ *   unsigned char offset2; // offset to add to access in the table_0004
+ * }
+ *
+ */
+static unsigned int table_ops[64*4] = {
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x10,
+	0x00, 0x06, 0x01, 0x30,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x01, 0x20,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x50,
+	0x00, 0x05, 0x02, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x03, 0x00,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x10,
+	0x00, 0x06, 0x02, 0x10,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x01, 0x60,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x50,
+	0x00, 0x05, 0x02, 0x40,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x03, 0x40,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x10,
+	0x00, 0x06, 0x01, 0x70,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x01, 0x20,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x50,
+	0x00, 0x05, 0x02, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x03, 0x00,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x10,
+	0x00, 0x06, 0x02, 0x50,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x01, 0x60,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x50,
+	0x00, 0x05, 0x02, 0x40,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x03, 0x40,
+	0x01, 0x00, 0x00, 0x00
+};
+
+/*
+ * TODO: multiply by 4 all values
+ *
+ */
+static unsigned int MulIdx[256] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+	0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+	4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
+	6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,
+	4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,
+	1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,
+	0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,
+	0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,
+	1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,
+	7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,
+	4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,
+	7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,
+	1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,
+	1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,
+	10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10
+};
+
+void pwc_dec23_init(int type, int release, unsigned char *mode, void *data)
+{
+	int flags;
+	struct pwc_dec23_private *pdev = data;
+	release = release;
+
+	if (DEVICE_USE_CODEC3(type)) {
+		flags = mode[2] & 0x18;	/* our: flags = 8, mode[2]==e8 */
+		if (flags == 8)
+			pdev->zz = 7;
+		else if (flags == 0x10)
+			pdev->zz = 8;
+		else
+			pdev->zz = 6;
+		flags = mode[2] >> 5;	/* our: 7 */
+
+		fill_table_color(flags, (unsigned int *)KiaraRomTable,
+				 pdev->table_0004, pdev->table_8004);
+	} else {
+		flags = mode[2] & 6;
+		if (flags == 2)
+			pdev->zz = 7;
+		else if (flags == 4)
+			pdev->zz = 8;
+		else
+			pdev->zz = 6;
+		flags = mode[2] >> 3;
+
+		fill_table_color(flags, (unsigned int *)TimonRomTable,
+				 pdev->table_0004, pdev->table_8004);
+	}
+
+	/* * * * ** */
+	pdev->xx = 8 - pdev->zz;
+	pdev->yy = 15 - pdev->xx;
+	pdev->zzmask = 0xFF >> pdev->xx;
+
+	fill_table_dc00_d800(pdev->table_dc00, pdev->table_d800);
+	fill_table_a000(pdev->table_a004);
+	fill_table_d000(pdev->table_d004);
+}
+
+/*
+ * To manage the stream, we keep in a 32 bits variables,
+ * the next bits in the stream. fill_reservoir() add to
+ * the reservoir at least wanted nbits.
+ *
+ */
+#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
+   while (nbits_in_reservoir<nbits_wanted) \
+    { \
+      reservoir |= (*(stream)++) << nbits_in_reservoir; \
+      nbits_in_reservoir+=8; \
+    } \
+}  while(0);
+
+#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
\
+   fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted); \
+   result = (reservoir) & ((1U<<nbits_wanted)-1); \
+   reservoir >>= nbits_wanted; \
+   nbits_in_reservoir -= nbits_wanted; \
+}  while(0);
+
+static void DecompressBand23(const struct pwc_dec23_private *pdev,
+			     const unsigned char *rawyuv,
+			     unsigned char *planar_y,
+			     unsigned char *planar_u,
+			     unsigned char *planar_v,
+			     unsigned int image_x,		/* aka number of pixels wanted ??? */
+			     unsigned int pixels_per_line,	/* aka number of pixels per line */
+			     int flags)
+{
+	unsigned int reservoir, nbits_in_reservoir;
+	int first_4_bits;
+	unsigned int bytes_per_channel;
+	int line_size;		/* size of the line (4Y+U+V) */
+	int passes;
+	const unsigned char *ptable0004, *ptable8004;
+
+	int even_line;
+	unsigned int temp_colors[16];
+	int nblocks;
+
+	const unsigned char *stream;
+	unsigned char *dest_y, *dest_u = NULL, *dest_v = NULL;
+	unsigned int offset_to_plane_u, offset_to_plane_v;
+
+	int i;
+
+	reservoir = 0;
+	nbits_in_reservoir = 0;
+	stream = rawyuv + 1;	/* The first byte of the stream is skipped */
+	even_line = 1;
+
+	get_nbits(reservoir, nbits_in_reservoir, stream, 4, first_4_bits);
+
+	line_size = pixels_per_line * 3;
+
+	for (passes = 0; passes < 2; passes++) {
+		if (passes == 0) {
+			bytes_per_channel = pixels_per_line;
+			dest_y = planar_y;
+			nblocks = image_x / 4;
+		} else {
+			/* Format planar: All Y, then all U, then all V */
+			bytes_per_channel = pixels_per_line / 2;
+			dest_u = planar_u;
+			dest_v = planar_v;
+			dest_y = dest_u;
+			nblocks = image_x / 8;
+		}
+
+		offset_to_plane_u = bytes_per_channel * 2;
+		offset_to_plane_v = bytes_per_channel * 3;
+
+		while (nblocks-- > 0) {
+			unsigned int gray_index;
+
+			fill_nbits(reservoir, nbits_in_reservoir, stream, 16);
+			gray_index = reservoir & pdev->zzmask;
+			reservoir >>= pdev->zz;
+			nbits_in_reservoir -= pdev->zz;
+
+			fill_nbits(reservoir, nbits_in_reservoir, stream, 2);
+
+			if ((reservoir & 3) == 0) {
+				reservoir >>= 2;
+				nbits_in_reservoir -= 2;
+				for (i = 0; i < 16; i++)
+					temp_colors[i] =
+					    pdev->table_dc00[gray_index];
+
+			} else {
+				unsigned int channel_v, offset1;
+
+				/* swap bit 0 and 2 of offset_OR */
+				channel_v =
+				    ((reservoir & 1) << 2) | (reservoir & 2) |
+				    ((reservoir & 4) >> 2);
+				reservoir >>= 3;
+				nbits_in_reservoir -= 3;
+
+				for (i = 0; i < 16; i++)
+					temp_colors[i] =
+					    pdev->table_d800[gray_index];
+
+				ptable0004 =
+				    pdev->table_0004 + (passes * 16384) +
+				    (first_4_bits * 1024) + (channel_v * 128);
+				ptable8004 =
+				    pdev->table_8004 + (passes * 4096) +
+				    (first_4_bits * 256) + (channel_v * 32);
+
+				offset1 = 0;
+				while (1) {
+					unsigned int index_in_table_ops, op,
+					    rows = 0;
+					fill_nbits(reservoir,
+						   nbits_in_reservoir, stream,
+						   16);
+
+					/* mode is 0,1 or 2 */
+					index_in_table_ops = (reservoir & 0x3F);
+					op = table_ops[index_in_table_ops * 4];
+					if (op == 2) {
+						reservoir >>= 2;
+						nbits_in_reservoir -= 2;
+						break;	/* exit the while(1) */
+					}
+					if (op == 0) {
+						unsigned int shift;
+
+						offset1 =
+						    (offset1 +
+						     table_ops
+						     [index_in_table_ops * 4 +
+						      2]) & 0x0F;
+						shift =
+						    table_ops[index_in_table_ops
+							      * 4 + 1];
+						reservoir >>= shift;
+						nbits_in_reservoir -= shift;
+						rows =
+						    ptable0004[offset1 +
+							       table_ops
+							       [index_in_table_ops
+								* 4 + 3]];
+					}
+					if (op == 1) {
+						/* 10bits [ xxxx xxxx yyyy 000 ]
+						 * yyy => offset in the table8004
+						 * xxx => offset in the tabled004
+						 */
+						unsigned int mask, shift;
+						unsigned int col1, row1,
+						    total_bits;
+
+						offset1 =
+						    (offset1 +
+						     ((reservoir >> 3) & 0x0F) +
+						     1) & 0x0F;
+
+						col1 = (reservoir >> 7) & 0xFF;
+						row1 = ptable8004[offset1 * 2];
+
+						/* Bit mask table */
+						mask =
+						    pdev->
+						    table_d004[(row1 << 8) +
+							       col1];
+						shift =
+						    ptable8004[offset1 * 2 + 1];
+						rows =
+						    ((mask << shift) +
+						     0x80) & 0xFF;
+
+						total_bits = row1 + 8;
+						reservoir >>= total_bits;
+						nbits_in_reservoir -=
+						    total_bits;
+					}
+					{
+						const unsigned int *table_a004 =
+						    pdev->table_a004 +
+						    rows * 12;
+						unsigned int *poffset = MulIdx + offset1 * 16;	/* 64/4 (int) */
+						for (i = 0; i < 16; i++) {
+							temp_colors[i] +=
+							    table_a004
+							    [*poffset];
+							poffset++;
+						}
+					}
+				}
+			}
+#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
+
+			if (passes == 0) {
+				const int *c = temp_colors;
+				unsigned char *d;
+
+				d = dest_y;
+				for (i = 0; i < 4; i++, c++)
+					*d++ = CLAMP((*c) >> pdev->yy);
+
+				d = dest_y + bytes_per_channel;
+				for (i = 0; i < 4; i++, c++)
+					*d++ = CLAMP((*c) >> pdev->yy);
+
+				d = dest_y + offset_to_plane_u;
+				for (i = 0; i < 4; i++, c++)
+					*d++ = CLAMP((*c) >> pdev->yy);
+
+				d = dest_y + offset_to_plane_v;
+				for (i = 0; i < 4; i++, c++)
+					*d++ = CLAMP((*c) >> pdev->yy);
+
+				dest_y += 4;
+			} else if (passes == 1) {
+				int *c1 = temp_colors;
+				int *c2 = temp_colors + 4;
+				unsigned char *d;
+
+				d = dest_y;
+				for (i = 0; i < 4; i++, c1++, c2++) {
+					*d++ = CLAMP((*c1) >> pdev->yy);
+					*d++ = CLAMP((*c2) >> pdev->yy);
+				}
+				c1 = temp_colors + 12;
+				//c2 = temp_colors+8;
+				d = dest_y + bytes_per_channel;
+				for (i = 0; i < 4; i++, c1++, c2++) {
+					*d++ = CLAMP((*c1) >> pdev->yy);
+					*d++ = CLAMP((*c2) >> pdev->yy);
+				}
+
+				if (even_line) {	/* Each line, swap u/v */
+					even_line = 0;
+					dest_y = dest_v;
+					dest_u += 8;
+				} else {
+					even_line = 1;
+					dest_y = dest_u;
+					dest_v += 8;
+				}
+			}
+
+		}		/* end of while (nblocks-->0) */
+
+	}			/* end of for (passes=0;passes<2;passes++) */
+
+}
+
+/**
+ *
+ * image: size of the image wanted
+ * view : size of the image returned by the camera
+ * offset: (x,y) to displayer image in the view
+ *
+ * src: raw data
+ * dst: image output
+ * flags: PWCX_FLAG_PLANAR
+ * pdev: private buffer
+ * bandlength:
+ *
+ */
+void pwc_dec23_decompress(const struct pwc_coord *image,
+			  const struct pwc_coord *view,
+			  const struct pwc_coord *offset,
+			  const void *src,
+			  void *dst,
+			  int flags, const void *data, int bandlength)
+{
+	const struct pwc_dec23_private *pdev = data;
+	unsigned char *pout, *pout_planar_y = NULL, *pout_planar_u =
+	    NULL, *pout_planar_v = NULL;
+	int i, n, stride, pixel_size;
+
+	if (flags & PWCX_FLAG_BAYER) {
+		pout = dst + (view->x * offset->y) + offset->x;
+		pixel_size = view->x * 4;
+	} else {
+		n = view->x * view->y;
+
+		/* offset in Y plane */
+		stride = view->x * offset->y;
+		pout_planar_y = dst + stride + offset->x;
+
+		/* offsets in U/V planes */
+		stride = (view->x * offset->y) / 4 + offset->x / 2;
+		pout_planar_u = dst + n + +stride;
+		pout_planar_v = dst + n + n / 4 + stride;
+
+		pixel_size = view->x * 4;
+	}
+
+	for (i = 0; i < image->y; i += 4) {
+		if (flags & PWCX_FLAG_BAYER) {
+			//TODO:
+			//DecompressBandBayer(pdev,src,pout,image.x,view->x,flags);
+			src += bandlength;
+			pout += pixel_size;
+		} else {
+			DecompressBand23(pdev, src, pout_planar_y,
+					 pout_planar_u, pout_planar_v, image->x,
+					 view->x, flags);
+			src += bandlength;
+			pout_planar_y += pixel_size;
+			pout_planar_u += view->x;
+			pout_planar_v += view->x;
+		}
+	}
+}
+
+void pwc_dec23_exit(void)
+{
+	/* Do nothing */
+
+}
+
+int  pwc_dec23_alloc(struct pwc_device *pwc)
+{
+	pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+	if (pwc->decompress_data == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-dec23.h linux-2.6.15/drivers/usb/media/pwc/pwc-dec23.h
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-dec23.h	1970-01-01 01:00:00.000000000 \
+0100
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-dec23.h	2006-01-08 01:25:14.000000000 \
+0100
@@ -0,0 +1,62 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef PWC_DEC23_H
+#define PWC_DEC23_H
+
+#include "pwc.h"
+
+struct pwc_dec23_private
+{
+  unsigned char xx,yy,zz,zzmask;
+
+  unsigned char table_0004[2*0x4000];
+  unsigned char table_8004[2*0x1000];
+  unsigned int  table_a004[256*12];
+
+  unsigned char table_d004[8*256];
+  unsigned int  table_d800[256];
+  unsigned int  table_dc00[256];
+};
+
+
+int  pwc_dec23_alloc(struct pwc_device *pwc);
+void pwc_dec23_init(int type, int release, unsigned char *buffer, void *private_data);
+void pwc_dec23_exit(void);
+void pwc_dec23_decompress(const struct pwc_coord *image,
+                            const struct pwc_coord *view,
+			    const struct pwc_coord *offset,
+			    const void *src,
+			    void *dst,
+			    int flags,
+			    const void *data,
+			    int bandlength);
+
+
+
+#endif
+
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
+
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-if.c linux-2.6.15/drivers/usb/media/pwc/pwc-if.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-if.c	2006-01-08 01:22:23.000000000 \
+0100
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-if.c	2006-01-08 01:25:14.000000000 +0100
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    USB and Video4Linux interface part.
    (C) 1999-2004 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -64,17 +64,20 @@
 #include <linux/vmalloc.h>
 #include <linux/version.h>
 #include <asm/io.h>
+#include <linux/moduleparam.h>
 
 #include "pwc.h"
 #include "pwc-ioctl.h"
 #include "pwc-kiara.h"
 #include "pwc-timon.h"
+#include "pwc-dec23.h"
+#include "pwc-dec1.h"
 #include "pwc-uncompress.h"
 
 /* Function prototypes and driver templates */
 
 /* hotplug device table support */
-static struct usb_device_id pwc_device_table [] = {
+static const struct usb_device_id pwc_device_table [] = {
 	{ USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
 	{ USB_DEVICE(0x0471, 0x0303) },
 	{ USB_DEVICE(0x0471, 0x0304) },
@@ -82,7 +85,7 @@
 	{ USB_DEVICE(0x0471, 0x0308) },
 	{ USB_DEVICE(0x0471, 0x030C) },
 	{ USB_DEVICE(0x0471, 0x0310) },
-	{ USB_DEVICE(0x0471, 0x0311) },
+	{ USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
 	{ USB_DEVICE(0x0471, 0x0312) },
 	{ USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
 	{ USB_DEVICE(0x069A, 0x0001) }, /* Askey */
@@ -111,7 +114,6 @@
 static void usb_pwc_disconnect(struct usb_interface *intf);
 
 static struct usb_driver pwc_driver = {
-	.owner =		THIS_MODULE,
 	.name =			"Philips webcam",	/* name */
 	.id_table =		pwc_device_table,
 	.probe =		usb_pwc_probe,		/* probe() */
@@ -124,11 +126,13 @@
 static int default_size = PSZ_QCIF;
 static int default_fps = 10;
 static int default_fbufs = 3;   /* Default number of frame buffers */
-static int default_mbufs = 2;	/* Default number of mmap() buffers */
-       int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
+       int pwc_mbufs = 2;	/* Default number of mmap() buffers */
+#if CONFIG_PWC_DEBUG
+       int pwc_trace = PWC_DEBUG_LEVEL;
+#endif
 static int power_save = 0;
 static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use \
*/
-static int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+       int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
 static struct {
 	int type;
 	char serial_number[30];
@@ -140,7 +144,7 @@
 
 static int pwc_video_open(struct inode *inode, struct file *file);
 static int pwc_video_close(struct inode *inode, struct file *file);
-static ssize_t pwc_video_read(struct file *file, char __user * buf,
+static ssize_t pwc_video_read(struct file *file, char __user *buf,
 			  size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
 static int  pwc_video_ioctl(struct inode *inode, struct file *file,
@@ -204,7 +208,8 @@
 /* Here we want the physical address of the memory.
  * This is used when initializing the contents of the area.
  */
-static inline unsigned long kvirt_to_pa(unsigned long adr) 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+static unsigned long kvirt_to_pa(unsigned long adr) 
 {
         unsigned long kva, ret;
 
@@ -213,43 +218,44 @@
 	ret = __pa(kva);
         return ret;
 }
+#endif
 
-static void * rvmalloc(unsigned long size)
+static void * pwc_rvmalloc(unsigned long size)
 {
 	void * mem;
 	unsigned long adr;
 
 	size=PAGE_ALIGN(size);
         mem=vmalloc_32(size);
-	if (mem) 
-	{
-		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	        adr=(unsigned long) mem;
-		while (size > 0) 
-                {
-			SetPageReserved(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr=(unsigned long) mem;
+	while (size > 0) 
+	 {
+	   SetPageReserved(vmalloc_to_page((void *)adr));
+	   adr  += PAGE_SIZE;
+	   size -= PAGE_SIZE;
+	 }
 	return mem;
 }
 
-static void rvfree(void * mem, unsigned long size)
+static void pwc_rvfree(void * mem, unsigned long size)
 {
         unsigned long adr;
 
-	if (mem) 
-	{
-	        adr=(unsigned long) mem;
-		while ((long) size > 0) 
-                {
-			ClearPageReserved(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
+	if (!mem) 
+	  	return;
+
+	adr=(unsigned long) mem;
+	while ((long) size > 0) 
+	 {
+	   ClearPageReserved(vmalloc_to_page((void *)adr));
+	   adr  += PAGE_SIZE;
+	   size -= PAGE_SIZE;
+	 }
+	vfree(mem);
 }
 
 
@@ -257,29 +263,23 @@
 
 static int pwc_allocate_buffers(struct pwc_device *pdev)
 {
-	int i;
+	int i, err;
 	void *kbuf;
 
-	Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
+	PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
 
 	if (pdev == NULL)
 		return -ENXIO;
 		
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("allocate_buffers(): magic failed.\n");
-		return -ENXIO;
-	}
-#endif	
-	/* Allocate Isochronous pipe buffers */
+	/* Allocate Isochronuous pipe buffers */
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		if (pdev->sbuf[i].data == NULL) {
 			kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
 			if (kbuf == NULL) {
-				Err("Failed to allocate iso buffer %d.\n", i);
+				PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
 				return -ENOMEM;
 			}
-			Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf);
+			PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
 			pdev->sbuf[i].data = kbuf;
 			memset(kbuf, 0, ISO_BUFFER_SIZE);
 		}
@@ -289,68 +289,59 @@
 	if (pdev->fbuf == NULL) {
 		kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
 		if (kbuf == NULL) {
-			Err("Failed to allocate frame buffer structure.\n");
+			PWC_ERROR("Failed to allocate frame buffer structure.\n");
 			return -ENOMEM;
 		}
-		Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf);
+		PWC_DEBUG_MEMORY("Allocated frame buffer structure at %p.\n", kbuf);
 		pdev->fbuf = kbuf;
 		memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
 	}
+
 	/* create frame buffers, and make circular ring */
 	for (i = 0; i < default_fbufs; i++) {
 		if (pdev->fbuf[i].data == NULL) {
 			kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
 			if (kbuf == NULL) {
-				Err("Failed to allocate frame buffer %d.\n", i);
+				PWC_ERROR("Failed to allocate frame buffer %d.\n", i);
 				return -ENOMEM;
 			}
-			Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf);
+			PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf);
 			pdev->fbuf[i].data = kbuf;
 			memset(kbuf, 128, PWC_FRAME_SIZE);
 		}
 	}
 	
 	/* Allocate decompressor table space */
-	kbuf = NULL;
-	switch (pdev->type)
-	 {
-	  case 675:
-	  case 680:
-	  case 690:
-	  case 720:
-	  case 730:
-	  case 740:
-	  case 750:
-#if 0	  
-	    Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private));
-	    kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);	/* Timon & Kiara \
*/
-	    break;
-	  case 645:
-	  case 646:
-	    /* TODO & FIXME */
-	    kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
-	    break;
-#endif	 
-	;
-	 }
-	pdev->decompress_data = kbuf;
-	
+	if (DEVICE_USE_CODEC1(pdev->type))
+		err = pwc_dec1_alloc(pdev);
+	else
+		err = pwc_dec23_alloc(pdev);
+
+	if (err) {
+	   PWC_ERROR("Failed to allocate decompress table.\n");
+	   return -ENOMEM;
+	}
+
 	/* Allocate image buffer; double buffer for mmap() */
-	kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
+	kbuf = pwc_rvmalloc(pwc_mbufs * PAGE_ALIGN(pdev->len_per_image));
 	if (kbuf == NULL) {
-		Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image);
+		PWC_ERROR("Failed to allocate image buffer(s). needed (%ld)\n",
+				pwc_mbufs * PAGE_ALIGN(pdev->len_per_image));
 		return -ENOMEM;
 	}
-	Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
+	PWC_DEBUG_MEMORY("Allocated image buffer at %p.\n", kbuf);
 	pdev->image_data = kbuf;
-	for (i = 0; i < default_mbufs; i++)
-		pdev->image_ptr[i] = kbuf + i * pdev->len_per_image;
-	for (; i < MAX_IMAGES; i++)
-		pdev->image_ptr[i] = NULL;
+	for (i = 0; i < pwc_mbufs; i++) {
+		pdev->images[i].bufmem = kbuf + i * PAGE_ALIGN(pdev->len_per_image);
+		pdev->images[i].vma_use_count = 0;
+	}
+	for (; i < MAX_IMAGES; i++) {
+		pdev->images[i].bufmem = NULL;
+	}
 
 	kbuf = NULL;
 	  
-	Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
+	PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n");
 	return 0;
 }
 
@@ -358,21 +349,14 @@
 {
 	int i;
 
-	Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
+	PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev);
 
 	if (pdev == NULL)
 		return;
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("free_buffers(): magic failed.\n");
-		return;
-	}
-#endif	
-
 	/* Release Iso-pipe buffers */
 	for (i = 0; i < MAX_ISO_BUFS; i++)
 		if (pdev->sbuf[i].data != NULL) {
-			Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
+			PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
 			kfree(pdev->sbuf[i].data);
 			pdev->sbuf[i].data = NULL;
 		}
@@ -381,7 +365,7 @@
 	if (pdev->fbuf != NULL) {
 		for (i = 0; i < default_fbufs; i++) {
 			if (pdev->fbuf[i].data != NULL) {
-				Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
+				PWC_DEBUG_MEMORY("Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
 				vfree(pdev->fbuf[i].data);
 				pdev->fbuf[i].data = NULL;
 			}
@@ -392,20 +376,19 @@
 
 	/* Intermediate decompression buffer & tables */
 	if (pdev->decompress_data != NULL) {
-		Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data);
+		PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data);
 		kfree(pdev->decompress_data);
 		pdev->decompress_data = NULL;
 	}
-	pdev->decompressor = NULL;
 
 	/* Release image buffers */
 	if (pdev->image_data != NULL) {
-		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
-		rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
+		PWC_DEBUG_MEMORY("Freeing image buffer at %p.\n", pdev->image_data);
+		pwc_rvfree(pdev->image_data, pwc_mbufs * PAGE_ALIGN(pdev->len_per_image));
 	}
 	pdev->image_data = NULL;
 	
-	Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
+	PWC_DEBUG_MEMORY("Leaving free_buffers().\n");
 }
 
 /* The frame & image buffer mess. 
@@ -465,7 +448,7 @@
 /**
   \brief Find next frame buffer to fill. Take from empty or full list, whichever \
comes first.
  */
-static inline int pwc_next_fill_frame(struct pwc_device *pdev)
+static int pwc_next_fill_frame(struct pwc_device *pdev)
 {
 	int ret;
 	unsigned long flags;
@@ -490,23 +473,17 @@
 	}
 	else {
 		/* Hmm. Take it from the full list */
-#if PWC_DEBUG
 		/* sanity check */
 		if (pdev->full_frames == NULL) {
-			Err("Neither empty or full frames available!\n");
+			PWC_ERROR("Neither empty or full frames available!\n");
 			spin_unlock_irqrestore(&pdev->ptrlock, flags);
 			return -EINVAL;
 		}
-#endif
 		pdev->fill_frame = pdev->full_frames;
 		pdev->full_frames = pdev->full_frames->next;
 		ret = 1;
 	}
 	pdev->fill_frame->next = NULL;
-#if PWC_DEBUG
-	Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
-	pdev->fill_frame->sequence = pdev->sequence++;
-#endif
 	spin_unlock_irqrestore(&pdev->ptrlock, flags);
 	return ret;
 }
@@ -547,7 +524,7 @@
 /**
   \brief Do all the handling for getting one frame: get pointer, decompress, advance \
pointers.
  */
-static int pwc_handle_frame(struct pwc_device *pdev)
+int pwc_handle_frame(struct pwc_device *pdev)
 {
 	int ret = 0;
 	unsigned long flags;
@@ -557,11 +534,11 @@
 	   we can release the lock after this without problems */
 	if (pdev->read_frame != NULL) {
 		/* This can't theoretically happen */
-		Err("Huh? Read frame still in use?\n");
+		PWC_ERROR("Huh? Read frame still in use?\n");
 	}
 	else {
 		if (pdev->full_frames == NULL) {
-			Err("Woops. No frames ready.\n");
+			PWC_ERROR("Woops. No frames ready.\n");
 		}
 		else {
 			pdev->read_frame = pdev->full_frames;
@@ -570,9 +547,6 @@
 		}
 
 		if (pdev->read_frame != NULL) {
-#if PWC_DEBUG
-			Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
-#endif
 			/* Decompression is a lenghty process, so it's outside of the lock.
 			   This gives the isoc_handler the opportunity to fill more frames
 			   in the mean time.
@@ -600,12 +574,99 @@
 /**
   \brief Advance pointers of image buffer (after each user request)
 */
-static inline void pwc_next_image(struct pwc_device *pdev)
+void pwc_next_image(struct pwc_device *pdev)
 {
 	pdev->image_used[pdev->fill_image] = 0;
-	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
+	pdev->fill_image = (pdev->fill_image + 1) % pwc_mbufs;
 }
 
+static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf \
*fbuf)
+{
+	int awake = 0;
+
+	/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus 
+	   frames on the USB wire after an exposure change. This conditition is 
+	   however detected  in the cam and a bit is set in the header.
+	   */
+	if (pdev->type == 730) {
+		unsigned char *ptr = (unsigned char *)fbuf->data;
+
+		if (ptr[1] == 1 && ptr[0] & 0x10) {
+			PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
+			pdev->drop_frames += 2;
+			pdev->vframes_error++;
+		}
+		if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+			if (ptr[0] & 0x01) {
+				pdev->snapshot_button_status = 1;
+				PWC_TRACE("Snapshot button pressed.\n");
+			}
+			else {
+				PWC_TRACE("Snapshot button released.\n");
+			}
+		}
+		if ((ptr[0] ^ pdev->vmirror) & 0x02) {
+			if (ptr[0] & 0x02)
+				PWC_TRACE("Image is mirrored.\n");
+			else
+				PWC_TRACE("Image is normal.\n");
+		}
+		pdev->vmirror = ptr[0] & 0x03;
+		/* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
+		   after a short frame; this condition is filtered out specifically. A 4 byte
+		   frame doesn't make sense anyway.
+		   So we get either this sequence: 
+		   drop_bit set -> 4 byte frame -> short frame -> good frame
+		   Or this one:
+		   drop_bit set -> short frame -> good frame
+		   So we drop either 3 or 2 frames in all!
+		   */
+		if (fbuf->filled == 4)
+			pdev->drop_frames++;
+	}
+	else if (pdev->type == 740) {
+		unsigned char *ptr = (unsigned char *)fbuf->data;
+		if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+			if (ptr[0] & 0x01) {
+				pdev->snapshot_button_status = 1;
+				PWC_TRACE("Snapshot button pressed.\n");
+			}
+			else
+				PWC_TRACE("Snapshot button released.\n");
+		}
+	}
+
+	/* In case we were instructed to drop the frame, do so silently.
+	   The buffer pointers are not updated either (but the counters are reset below).
+	   */
+	if (pdev->drop_frames > 0)
+		pdev->drop_frames--;
+	else {
+		/* Check for underflow first */
+		if (fbuf->filled < pdev->frame_total_size) {
+			PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
+				       " discarded.\n", fbuf->filled);
+			pdev->vframes_error++;
+		}
+		else {
+			/* Send only once per EOF */
+			awake = 1; /* delay wake_ups */
+
+			/* Find our next frame to fill. This will always succeed, since we
+			 * nick a frame from either empty or full list, but if we had to
+			 * take it from the full list, it means a frame got dropped.
+			 */
+			if (pwc_next_fill_frame(pdev)) {
+				pdev->vframes_dumped++;
+				if (pdev->vframe_count > FRAME_LOWMARK)
+					PWC_DEBUG_FLOW("Dumping frame %d%s.\n", pdev->vframe_count,
+							pdev->vframes_dumped>=20?  " (last message)":"");
+			}
+		}
+	} /* !drop_frames */
+	pdev->vframe_count++;
+	return awake;
+}
 
 /* This gets called for the Isochronous pipe (video). This is done in
  * interrupt time, so it has to be fast, not crash, and not stall. Neat.
@@ -621,17 +682,12 @@
 	awake = 0;
 	pdev = (struct pwc_device *)urb->context;
 	if (pdev == NULL) {
-		Err("isoc_handler() called with NULL device?!\n");
-		return;
-	}
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("isoc_handler() called with bad magic!\n");
+		PWC_ERROR("isoc_handler() called with NULL device?!\n");
 		return;
 	}
-#endif
+
 	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
-		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", \
urb, urb->status == -ENOENT ? "" : "a");
+		PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT \
? "" : "a");
 		return;
 	}
 	if (urb->status != -EINPROGRESS && urb->status != 0) {
@@ -646,13 +702,13 @@
 			case -EILSEQ:		errmsg = "CRC/Timeout (could be anything)"; break;
 			case -ETIMEDOUT:	errmsg = "NAK (device does not respond)"; break;
 		}
-		Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, \
errmsg);
+		PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, \
errmsg);
 		/* Give up after a number of contiguous errors on the USB bus. 
 		   Appearantly something is wrong so we simulate an unplug event.
 		 */
 		if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
 		{
-			Info("Too many ISOC errors, bailing out.\n");
+			PWC_INFO("Too many ISOC errors, bailing out.\n");
 			pdev->error_status = EIO;
 			awake = 1;
 			wake_up_interruptible(&pdev->frameq);
@@ -662,7 +718,7 @@
 
 	fbuf = pdev->fill_frame;
 	if (fbuf == NULL) {
-		Err("pwc_isoc_handler without valid fill frame.\n");
+		PWC_ERROR("pwc_isoc_handler without valid fill frame.\n");
 		awake = 1;
 		goto handler_end;
 	}
@@ -689,7 +745,7 @@
 
 					/* ...copy data to frame buffer, if possible */
 					if (flen + fbuf->filled > pdev->frame_total_size) {
-						Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", \
flen, pdev->frame_total_size);
+						PWC_DEBUG_FLOW("Frame buffer overflow (flen = %d, frame_total_size = %d).\n", \
flen, pdev->frame_total_size);
 						pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
 						pdev->vframes_error++;
 					}
@@ -705,96 +761,28 @@
 				/* Shorter packet... We probably have the end of an image-frame; 
 				   wake up read() process and let select()/poll() do something.
 				   Decompression is done in user time over there.
-				 */
+				   */
 				if (pdev->vsync == 2) {
-					/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus 
-					   frames on the USB wire after an exposure change. This conditition is 
-					   however detected  in the cam and a bit is set in the header.
-					 */
-					if (pdev->type == 730) {
-						unsigned char *ptr = (unsigned char *)fbuf->data;
-						
-						if (ptr[1] == 1 && ptr[0] & 0x10) {
-#if PWC_DEBUG
-							Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
-#endif
-							pdev->drop_frames += 2;
-							pdev->vframes_error++;
-						}
-						if ((ptr[0] ^ pdev->vmirror) & 0x01) {
-							if (ptr[0] & 0x01)
-								Info("Snapshot button pressed.\n");
-							else
-								Info("Snapshot button released.\n");
-						}
-						if ((ptr[0] ^ pdev->vmirror) & 0x02) {
-							if (ptr[0] & 0x02)
-								Info("Image is mirrored.\n");
-							else
-								Info("Image is normal.\n");
-						}
-						pdev->vmirror = ptr[0] & 0x03;
-						/* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
-						   after a short frame; this condition is filtered out specifically. A 4 byte
-						   frame doesn't make sense anyway.
-						   So we get either this sequence: 
-						   	drop_bit set -> 4 byte frame -> short frame -> good frame
-						   Or this one:
-						   	drop_bit set -> short frame -> good frame
-						   So we drop either 3 or 2 frames in all!
-						 */
-						if (fbuf->filled == 4)
-							pdev->drop_frames++;
+					if (pwc_rcv_short_packet(pdev, fbuf)) {
+						awake = 1;
+						fbuf = pdev->fill_frame;
 					}
-
-					/* In case we were instructed to drop the frame, do so silently.
-					   The buffer pointers are not updated either (but the counters are reset below).
-					 */
-					if (pdev->drop_frames > 0)
-						pdev->drop_frames--;
-					else {
-						/* Check for underflow first */
-						if (fbuf->filled < pdev->frame_total_size) {
-							Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
-							pdev->vframes_error++;
-						}
-						else {
-							/* Send only once per EOF */
-							awake = 1; /* delay wake_ups */
-
-							/* Find our next frame to fill. This will always succeed, since we
-							 * nick a frame from either empty or full list, but if we had to
-							 * take it from the full list, it means a frame got dropped.
-							 */
-							if (pwc_next_fill_frame(pdev)) {
-								pdev->vframes_dumped++;
-								if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
-									if (pdev->vframes_dumped < 20)
-										Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count);
-									if (pdev->vframes_dumped == 20)
-										Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count);
-								}
-							}
-							fbuf = pdev->fill_frame;
-						}
-					} /* !drop_frames */
-					pdev->vframe_count++;
 				}
 				fbuf->filled = 0;
 				fillptr = fbuf->data;
 				pdev->vsync = 1;
-			} /* .. flen < last_packet_size */
+			}
+
 			pdev->vlast_packet_size = flen;
 		} /* ..status == 0 */
-#if PWC_DEBUG
-		/* This is normally not interesting to the user, unless you are really debugging \
something */
 		else {
+			/* This is normally not interesting to the user, unless
+			 * you are really debugging something */
 			static int iso_error = 0;
 			iso_error++;
 			if (iso_error < 20)
-				Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+				PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
 		}
-#endif
 	}
 
 handler_end:
@@ -804,7 +792,7 @@
 	urb->dev = pdev->udev;
 	i = usb_submit_urb(urb, GFP_ATOMIC);
 	if (i != 0)
-		Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
+		PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
 }
 
 
@@ -840,20 +828,25 @@
 
 	/* Search video endpoint */
 	pdev->vmax_packet_size = -1;
-	for (i = 0; i < idesc->desc.bNumEndpoints; i++)
+	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) \
{
-		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+		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;
-	Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate);
+	PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
 	ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
 	if (ret < 0)
 		return ret;
@@ -861,12 +854,12 @@
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
 		if (urb == NULL) {
-			Err("Failed to allocate urb %d\n", i);
+			PWC_ERROR("Failed to allocate urb %d\n", i);
 			ret = -ENOMEM;
 			break;
 		}
 		pdev->sbuf[i].urb = urb;
-		Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
+		PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
 	}
 	if (ret) {
 		/* De-allocate in reverse order */
@@ -903,14 +896,14 @@
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
 		if (ret)
-			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+			PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
 		else
-			Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb);
+			PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
 	}
 
 	/* All is done... */
 	pdev->iso_init = 1;
-	Trace(TRACE_OPEN, "<< pwc_isoc_init()\n");
+	PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
 	return 0;
 }
 
@@ -918,7 +911,7 @@
 {
 	int i;
 
-	Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n");
+	PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
 	if (pdev == NULL)
 		return;
 
@@ -929,10 +922,10 @@
 		urb = pdev->sbuf[i].urb;
 		if (urb != 0) {
 			if (pdev->iso_init) {
-				Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
+				PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
 				usb_kill_urb(urb);
 			}
-			Trace(TRACE_MEMORY, "Freeing URB\n");
+			PWC_DEBUG_MEMORY("Freeing URB\n");
 			usb_free_urb(urb);
 			pdev->sbuf[i].urb = NULL;
 		}
@@ -942,12 +935,12 @@
 	   is signalled by EPIPE) 
 	 */
 	if (pdev->error_status && pdev->error_status != EPIPE) {
-		Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
+		PWC_DEBUG_OPEN("Setting alternate interface 0.\n");
 		usb_set_interface(pdev->udev, 0, 0);
 	}
 
 	pdev->iso_init = 0;
-	Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n");
+	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)
@@ -961,18 +954,18 @@
 	/* Try to set video mode... */
 	start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, \
new_snapshot);
 	if (ret) { 
-	        Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
+	        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) {
-		        Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
+		        PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n");
 		}
 	}
 	if (start == 0)
 	{
 		if (pwc_isoc_init(pdev) < 0)
 		{
-			Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
+			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 */
 		}
 	}
@@ -980,17 +973,108 @@
 	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_DEBUG
+static 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;
+	int i, ret;
 	struct video_device *vdev = video_devdata(file);
 	struct pwc_device *pdev;
 
-	Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
+	PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
 	
 	pdev = (struct pwc_device *)vdev->priv;
 	if (pdev == NULL)
@@ -1000,34 +1084,16 @@
 	
 	down(&pdev->modlock);
 	if (!pdev->usb_init) {
-		Trace(TRACE_OPEN, "Doing first time initialization.\n");
+		PWC_DEBUG_OPEN("Doing first time initialization.\n");
 		pdev->usb_init = 1;
-		
-		if (pwc_trace & TRACE_OPEN)
+
+		/* Query sensor type */
+		ret = pwc_get_cmos_sensor(pdev, &i);
+		if (ret >= 0)
 		{
-			/* Query sensor type */
-			const char *sensor_type = NULL;
-			int ret;
-
-			ret = pwc_get_cmos_sensor(pdev, &i);
-			if (ret >= 0)
-			{
-				switch(i) {
-				case 0x00:  sensor_type = "Hyundai CMOS sensor"; break;
-				case 0x20:  sensor_type = "Sony CCD sensor + TDA8787"; break;
-				case 0x2E:  sensor_type = "Sony CCD sensor + Exas 98L59"; break;
-				case 0x2F:  sensor_type = "Sony CCD sensor + ADI 9804"; break;
-				case 0x30:  sensor_type = "Sharp CCD sensor + TDA8787"; break;
-				case 0x3E:  sensor_type = "Sharp CCD sensor + Exas 98L59"; break;
-				case 0x3F:  sensor_type = "Sharp CCD sensor + ADI 9804"; break;
-				case 0x40:  sensor_type = "UPA 1021 sensor"; break;
-				case 0x100: sensor_type = "VGA sensor"; break;
-				case 0x101: sensor_type = "PAL MR sensor"; break;
-				default:    sensor_type = "unknown type of sensor"; break;
-				}
-			}
-			if (sensor_type != NULL)
-				Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, \
i);
+			PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
+				       	pdev->vdev->name, 
+					pwc_sensor_type_to_string(i), i);
 		}
 	}
 
@@ -1035,34 +1101,31 @@
 	if (power_save) {
 		i = pwc_camera_power(pdev, 1);
 		if (i < 0)
-			Info("Failed to restore power to the camera! (%d)\n", i);
+			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)
-		Info("Failed to set LED on/off time.\n");
+		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) {
-		Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n");
+		PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
 		up(&pdev->modlock);
 		return i;
 	}
 	
 	/* Reset buffers & parameters */
 	pwc_reset_buffers(pdev);
-	for (i = 0; i < default_mbufs; i++)
+	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;
-#if PWC_DEBUG
-	pdev->sequence = 0;
-#endif
 	pwc_construct(pdev); /* set min/max sizes correct */
 
 	/* Set some defaults */
@@ -1074,29 +1137,41 @@
 	 */
 	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)	{
-		Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
-		if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
-			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, \
10, pdev->vcompression, 0);
+		unsigned int default_resolution;
+		PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n");
+		if (pdev->type>= 730)
+			default_resolution = PSZ_QSIF;
 		else
-			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, \
10, pdev->vcompression, 0);
+			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) {
-		Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
+		PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
 		up(&pdev->modlock);
 		return i;
 	}
 	
 	i = pwc_isoc_init(pdev);
 	if (i) {
-		Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+		PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i);
 		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);
-	Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
+	PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
 	return 0;
 }
 
@@ -1107,35 +1182,23 @@
 	struct pwc_device *pdev;
 	int i;
 
-	Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
+	PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
 	pdev = (struct pwc_device *)vdev->priv;
 	if (pdev->vopen == 0)
-		Info("video_close() called on closed device?\n");
+		PWC_DEBUG_MODULE("video_close() called on closed device?\n");
 
 	/* Dump statistics, but only if a reasonable amount of frames were
 	   processed (to prevent endless log-entries in case of snap-shot
 	   programs)
 	 */
 	if (pdev->vframe_count > 20)
-		Info("Closing video device: %d frames received, dumped %d frames, %d frames with \
errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+		PWC_DEBUG_MODULE("Closing video device: %d frames received, dumped %d frames, \
%d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
 
-	switch (pdev->type)
-	 {
-	  case 675:
-	  case 680:
-	  case 690:
-	  case 720:
-	  case 730:
-	  case 740:
-	  case 750:
-/*	    pwc_dec23_exit();	*//* Timon & Kiara */
-	    break;
-	  case 645:
-	  case 646:
-/*	    pwc_dec1_exit(); */
-	    break;
-	 }
+	if (DEVICE_USE_CODEC1(pdev->type))
+	    pwc_dec1_exit();
+	else
+	    pwc_dec23_exit();
 
 	pwc_isoc_cleanup(pdev);
 	pwc_free_buffers(pdev);
@@ -1144,15 +1207,15 @@
 	if (pdev->error_status != EPIPE) {
 		/* Turn LEDs off */
 		if (pwc_set_leds(pdev, 0, 0) < 0)
-			Info("Failed to set LED on/off time.\n");
+			PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
 		if (power_save) {
 			i = pwc_camera_power(pdev, 0);
 			if (i < 0)
-				Err("Failed to power down camera (%d)\n", i);
+				PWC_ERROR("Failed to power down camera (%d)\n", i);
 		}
 	}
 	pdev->vopen = 0;
-	Trace(TRACE_OPEN, "<< video_close()\n");
+	PWC_DEBUG_OPEN("<< video_close()\n");
 	return 0;
 }
 
@@ -1168,7 +1231,7 @@
                 device is tricky anyhow.
  */
 
-static ssize_t pwc_video_read(struct file *file, char __user * buf,
+static ssize_t pwc_video_read(struct file *file, char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	struct video_device *vdev = file->private_data;
@@ -1177,7 +1240,8 @@
 	DECLARE_WAITQUEUE(wait, current);
         int bytes_to_read;
 
-	Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count);
+	PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n",
+		       	vdev, buf, count);
 	if (vdev == NULL)
 		return -EFAULT;
 	pdev = vdev->priv;
@@ -1218,16 +1282,16 @@
 			return -EFAULT;
 	}
 
-	Trace(TRACE_READ, "Copying data to user space.\n");
+	PWC_DEBUG_READ("Copying data to user space.\n");
 	if (pdev->vpalette == VIDEO_PALETTE_RAW)
-		bytes_to_read = pdev->frame_size;
+		bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
 	else
  		bytes_to_read = pdev->view.size;
 
 	/* copy bytes to user space; we allow for partial reads */
 	if (count + pdev->image_read_pos > bytes_to_read)
 		count = bytes_to_read - pdev->image_read_pos;
-	if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, \
count))
+	if (copy_to_user(buf, pdev->images[pdev->fill_image].bufmem + pdev->image_read_pos, \
count))
 		return -EFAULT;
 	pdev->image_read_pos += count;
 	if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
@@ -1257,351 +1321,12 @@
 	return 0;
 }
 
-static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
-			      unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = vdev->priv;
-	if (pdev == NULL)
-		return -EFAULT;
-
-	switch (cmd) {
-		/* Query cabapilities */
-		case VIDIOCGCAP:
-		{
-			struct video_capability *caps = arg;
-
-			strcpy(caps->name, vdev->name);
-			caps->type = VID_TYPE_CAPTURE;
-			caps->channels = 1;
-			caps->audios = 1;
-			caps->minwidth  = pdev->view_min.x;
-			caps->minheight = pdev->view_min.y;
-			caps->maxwidth  = pdev->view_max.x;
-			caps->maxheight = pdev->view_max.y;
-			break;
-		}
-
-		/* Channel functions (simulate 1 channel) */
-		case VIDIOCGCHAN:
-		{
-			struct video_channel *v = arg;
-
-			if (v->channel != 0)
-				return -EINVAL;
-			v->flags = 0;
-			v->tuners = 0;
-			v->type = VIDEO_TYPE_CAMERA;
-			strcpy(v->name, "Webcam");
-			return 0;
-		}
-
-		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 = arg;
-			if (v->channel != 0)
-				return -EINVAL;
-			return 0;
-		}
-
-
-		/* Picture functions; contrast etc. */
-		case VIDIOCGPICT:
-		{
-			struct video_picture *p = arg;
-			int val;
-
-			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 */
-			break;
-		}
-
-		case VIDIOCSPICT:
-		{
-			struct video_picture *p = arg;
-			/*
-			 *	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) {
-				switch (p->palette) {
-					case VIDEO_PALETTE_YUV420P:
-					case VIDEO_PALETTE_RAW:
-						pdev->vpalette = p->palette;
-						return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, \
pdev->vcompression, pdev->vsnapshot);
-						break;
-					default:
-						return -EINVAL;
-						break;
-				}
-			}
-			break;
-		}
-
-		/* Window/size parameters */		
-		case VIDIOCGWIN:
-		{
-			struct video_window *vw = arg;
-			
-			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);
-			break;
-		}
-		
-		case VIDIOCSWIN:
-		{
-			struct video_window *vw = arg;
-			int fps, snapshot, ret;
-
-			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 = arg;
-
-			memset(vb,0,sizeof(*vb));
-			break;
-		}
-
-		/* mmap() functions */
-		case VIDIOCGMBUF:
-		{
-			/* Tell the user program how much memory is needed for a mmap() */
-			struct video_mbuf *vm = arg;
-			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;
-			break;
-		}
-
-		case VIDIOCMCAPTURE:
-		{
-			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) \
*/
-			struct video_mmap *vm = arg;
-
-			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)
-			{
-				switch (vm->format)
-				{
-					case VIDEO_PALETTE_YUV420P:
-					case VIDEO_PALETTE_RAW:
-						break;
-					default:
-						return -EINVAL;
-						break;
-				}
-			}
-
-			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 = arg;
-			int ret;
-
-			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.
-			   QUESTION: 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->error_status) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -pdev->error_status;
-				}
-			
-	                	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 = arg;
-			
-			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;
-			break;	
-		}
-		
-		case VIDIOCSAUDIO:
-		{
-			/* Dummy: nothing can be set */
-			break;
-		}
-		
-		case VIDIOCGUNIT:
-		{
-			struct video_unit *vu = arg;
-			
-			vu->video = pdev->vdev->minor & 0x3F;
-			vu->audio = -1; /* not known yet */
-			vu->vbi = -1;
-			vu->radio = -1;
-			vu->teletext = -1;
-			break;
-		}
-		default:
-			return pwc_ioctl(pdev, cmd, arg);
-	} /* ..switch */
-	return 0;
-}	
-
 static int pwc_video_ioctl(struct inode *inode, struct file *file,
 			   unsigned int cmd, unsigned long arg)
 {
 	return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
 }
 
-
 static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct video_device *vdev = file->private_data;
@@ -1609,18 +1334,32 @@
 	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end-vma->vm_start;
 	unsigned long page, pos;
+	int index;
 	
-	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
+	PWC_DEBUG_MEMORY("mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
 	pdev = vdev->priv;
-	
-	vma->vm_flags |= VM_IO;
+
+	/* Find the idx buffer for this mapping */
+	for (index = 0; index < pwc_mbufs; index++) {
+		if (((index*PAGE_ALIGN(pdev->len_per_image))>>PAGE_SHIFT) == vma->vm_pgoff)
+			break;
+	}
+	if (index == MAX_IMAGES)
+		return -EINVAL;
+
+	vma->vm_flags |= VM_IO;	/* from 2.6.9-acX */
 
 	pos = (unsigned long)pdev->image_data;
 	while (size > 0) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+		page = kvirt_to_pa(pos);
+		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+			return -EAGAIN;
+#else
 		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
 			return -EAGAIN;
-
+#endif
 		start += PAGE_SIZE;
 		pos += PAGE_SIZE;
 		if (size > PAGE_SIZE)
@@ -1628,7 +1367,6 @@
 		else
 			size = 0;
 	}
-
 	return 0;
 }
 
@@ -1649,10 +1387,17 @@
 	int video_nr = -1; /* default: use next available device */
 	char serial_number[30], *name;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+	vendor_id = udev->descriptor.idVendor;
+	product_id = udev->descriptor.idProduct;
+#else
+	vendor_id = le16_to_cpu(udev->descriptor.idVendor);
+	product_id = le16_to_cpu(udev->descriptor.idProduct);
+#endif
+
 	/* Check if we can handle this device */
-	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", 
-		le16_to_cpu(udev->descriptor.idVendor),
-		le16_to_cpu(udev->descriptor.idProduct),
+	PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n", 
+		vendor_id, product_id,
 		intf->altsetting->desc.bInterfaceNumber);
 
 	/* the interfaces are probed one by one. We are only interested in the
@@ -1662,58 +1407,55 @@
 	if (intf->altsetting->desc.bInterfaceNumber > 0)
 		return -ENODEV;
 
-	vendor_id = le16_to_cpu(udev->descriptor.idVendor);
-	product_id = le16_to_cpu(udev->descriptor.idProduct);
-
 	if (vendor_id == 0x0471) {
 		switch (product_id) {
 		case 0x0302:
-			Info("Philips PCA645VC USB webcam detected.\n");
+			PWC_INFO("Philips PCA645VC USB webcam detected.\n");
 			name = "Philips 645 webcam";
 			type_id = 645;
 			break;
 		case 0x0303:
-			Info("Philips PCA646VC USB webcam detected.\n");
+			PWC_INFO("Philips PCA646VC USB webcam detected.\n");
 			name = "Philips 646 webcam";
 			type_id = 646;
 			break;
 		case 0x0304:
-			Info("Askey VC010 type 2 USB webcam detected.\n");
+			PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
 			name = "Askey VC010 webcam";
 			type_id = 646;
 			break;
 		case 0x0307:
-			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
 			name = "Philips 675 webcam";
 			type_id = 675;
 			break;
 		case 0x0308:
-			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
 			name = "Philips 680 webcam";
 			type_id = 680;
 			break;
 		case 0x030C:
-			Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
 			name = "Philips 690 webcam";
 			type_id = 690;
 			break;
 		case 0x0310:
-			Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
 			name = "Philips 730 webcam";
 			type_id = 730;
 			break;
 		case 0x0311:
-			Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
 			name = "Philips 740 webcam";
 			type_id = 740;
 			break;
 		case 0x0312:
-			Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
 			name = "Philips 750 webcam";
 			type_id = 750;
 			break;
 		case 0x0313:
-			Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
 			name = "Philips 720K/40 webcam";
 			type_id = 720;
 			break;
@@ -1725,7 +1467,7 @@
 	else if (vendor_id == 0x069A) {
 		switch(product_id) {
 		case 0x0001:
-			Info("Askey VC010 type 1 USB webcam detected.\n");
+			PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
 			name = "Askey VC010 webcam";
 			type_id = 645;
 			break;
@@ -1737,32 +1479,33 @@
 	else if (vendor_id == 0x046d) {
 		switch(product_id) {
 		case 0x08b0:
-			Info("Logitech QuickCam Pro 3000 USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
 			name = "Logitech QuickCam Pro 3000";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x08b1:
-			Info("Logitech QuickCam Notebook Pro USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
 			name = "Logitech QuickCam Notebook Pro";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x08b2:
-			Info("Logitech QuickCam 4000 Pro USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
 			name = "Logitech QuickCam Pro 4000";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x08b3:
-			Info("Logitech QuickCam Zoom USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
 			name = "Logitech QuickCam Zoom";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x08B4:
-			Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
 			name = "Logitech QuickCam Zoom";
 			type_id = 740; /* CCD sensor */
+			power_save = 1;
 			break;
 		case 0x08b5:
-			Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
 			name = "Logitech QuickCam Orbit";
 			type_id = 740; /* CCD sensor */
 			features |= FEATURE_MOTOR_PANTILT;
@@ -1770,7 +1513,7 @@
 		case 0x08b6:
 		case 0x08b7:
 		case 0x08b8:
-			Info("Logitech QuickCam detected (reserved ID).\n");
+			PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
 			name = "Logitech QuickCam (res.)";
 			type_id = 730; /* Assuming CMOS */
 			break;
@@ -1786,12 +1529,12 @@
 		 */
 		switch(product_id) {
 		case 0x9000:
-			Info("Samsung MPC-C10 USB webcam detected.\n");
+			PWC_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");
+			PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
 			name = "Samsung MPC-C30";
 			type_id = 675;
 			break;
@@ -1803,12 +1546,12 @@
 	else if (vendor_id == 0x041e) {
 		switch(product_id) {
 		case 0x400c:
-			Info("Creative Labs Webcam 5 detected.\n");
+			PWC_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");
+			PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
 			name = "Creative Labs Webcam Pro Ex";
 			type_id = 740;
 			break;
@@ -1820,7 +1563,7 @@
 	else if (vendor_id == 0x04cc) {
 		switch(product_id) {
 		case 0x8116:
-			Info("Sotec Afina Eye USB webcam detected.\n");
+			PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
 			name = "Sotec Afina Eye";
 			type_id = 730;
 			break;
@@ -1833,7 +1576,7 @@
 		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");
+			PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
 			name = "AME Co. Afina Eye";
 			type_id = 750;
 			break;
@@ -1846,12 +1589,12 @@
 	else if (vendor_id == 0x0d81) {
 		switch(product_id) {
 		case 0x1900:
-			Info("Visionite VCS-UC300 USB webcam detected.\n");
+			PWC_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");
+			PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
 			name = "Visionite VCS-UM100";
 			type_id = 730; /* CMOS sensor */
 			break;
@@ -1865,15 +1608,15 @@
 
 	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);
+	PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
 
 	if (udev->descriptor.bNumConfigurations > 1)
-		Info("Warning: more than 1 configuration available.\n");
+		PWC_WARNING("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");
+		PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
 		return -ENOMEM;
 	}
 	memset(pdev, 0, sizeof(struct pwc_device));
@@ -1905,17 +1648,22 @@
 	pdev->vdev = video_device_alloc();
 	if (pdev->vdev == 0)
 	{
-		Err("Err, cannot allocate video_device struture. Failing probe.");
+		PWC_ERROR("Err, cannot allocate video_device struture. Failing probe.");
 		kfree(pdev);
 		return -ENOMEM;
 	}
 	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
+	pdev->vdev->dev = &(udev->dev);
 	strcpy(pdev->vdev->name, name);
 	pdev->vdev->owner = THIS_MODULE;
 	video_set_drvdata(pdev->vdev, pdev);
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+	pdev->release = udev->descriptor.bcdDevice;
+#else
 	pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
-	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+#endif
+	PWC_DEBUG_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++) {
@@ -1925,7 +1673,7 @@
 			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);
+			    	PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
 			    	break;
 			}
 		}
@@ -1934,21 +1682,27 @@
 	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);
+		PWC_ERROR("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);
+		PWC_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);
+	PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
 	usb_set_intfdata (intf, pdev);
+	pwc_create_sysfs_files(pdev->vdev);
+
+	/* Set the leds off */
+	pwc_set_leds(pdev, 0, 0);
+	pwc_camera_power(pdev, 0);
+
 	return 0;
 }
 
@@ -1962,27 +1716,21 @@
 	pdev = usb_get_intfdata (intf);
 	usb_set_intfdata (intf, NULL);
 	if (pdev == NULL) {
-		Err("pwc_disconnect() Called without private pointer.\n");
+		PWC_ERROR("pwc_disconnect() Called without private pointer.\n");
 		goto disconnect_out;
 	}
 	if (pdev->udev == NULL) {
-		Err("pwc_disconnect() already called for %p\n", pdev);
+		PWC_ERROR("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");
+		PWC_ERROR("pwc_disconnect() Woops: pointer mismatch udev/pdev.\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");
+		PWC_INFO("Disconnected while webcam is in use!\n");
 		pdev->error_status = EPIPE;
 	}
 
@@ -1992,7 +1740,8 @@
 	while (pdev->vopen)
 		schedule();
 	/* Device is now closed, so we can safely unregister it */
-	Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
+	PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
+	pwc_remove_sysfs_files(pdev->vdev);
 	video_unregister_device(pdev->vdev);
 
 	/* Free memory (don't set pdev to 0 just yet) */
@@ -2026,58 +1775,69 @@
  * Initialization code & module stuff 
  */
 
-static char size[10];
-static int fps = 0;
-static int fbufs = 0;
-static int mbufs = 0;
-static int trace = -1;
+static char *size;
+static int fps;
+static int fbufs;
+static int mbufs;
 static int compression = -1;
 static int leds[2] = { -1, -1 };
-static char *dev_hint[MAX_DEV_HINTS] = { };
+static int leds_nargs;
+static char *dev_hint[MAX_DEV_HINTS];
+static int dev_hint_nargs;
+
+module_param(size, charp, 0444);
+module_param(fps, int, 0444);
+module_param(fbufs, int, 0444);
+module_param(mbufs, int, 0444);
+#if CONFIG_PWC_DEBUG
+module_param_named(trace, pwc_trace, int, 0644);
+#endif
+module_param(power_save, int, 0444);
+module_param(compression, int, 0444);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+module_param_array(leds, int, leds_nargs, 0444);
+module_param_array(dev_hint, charp, dev_hint_nargs, 0444);
+#else
+module_param_array(leds, int, &leds_nargs, 0444);
+module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
+#endif
 
-module_param_string(size, size, sizeof(size), 0);
 MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, \
vga");
-module_param(fps, int, 0000);
 MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range \
5-30");
-module_param(fbufs, int, 0000);
 MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
-module_param(mbufs, int, 0000);
 MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
-module_param(trace, int, 0000);
 MODULE_PARM_DESC(trace, "For debugging purposes");
-module_param(power_save, bool, 0000);
 MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
-module_param(compression, int, 0000);
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) \
to 3 (high compression)");
-module_param_array(leds, int, NULL, 0000);
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-module_param_array(dev_hint, charp, NULL, 0000);
 MODULE_PARM_DESC(dev_hint, "Device node hints");
 
 MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
 MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("pwcx");
+MODULE_VERSION( PWC_VERSION );
 
 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");
+	PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
+	PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 \
& PCVC830/840.\n");
+	PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 \
and MPC-C30,\n");
+	PWC_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");
+			PWC_ERROR("Framerate out of bounds (4-30).\n");
 			return -EINVAL;
 		}
 		default_fps = fps;
-		Info("Default framerate set to %d.\n", default_fps);
+		PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
 	}
 
-	if (size[0]) {
+	if (size) {
 		/* string; try matching with array */
 		for (sz = 0; sz < PSZ_MAX; sz++) {
 			if (!strcmp(sizenames[sz], size)) { /* Found! */
@@ -2086,41 +1846,42 @@
 			}
 		}
 		if (sz == PSZ_MAX) {
-			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
+			PWC_ERROR("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);
+		PWC_DEBUG_MODULE("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);
+			PWC_ERROR("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);
+		pwc_mbufs = mbufs;
+		PWC_DEBUG_MODULE("Number of image buffers set to %d.\n", pwc_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);
+			PWC_ERROR("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);
+		PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs);
 	}
-	if (trace >= 0) {
-		Info("Trace options: 0x%04x\n", trace);
-		pwc_trace = trace;
+#if CONFIG_PWC_DEBUG
+	if (pwc_trace >= 0) {
+		PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
 	}
+#endif
 	if (compression >= 0) {
 		if (compression > 3) {
-			Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 \
(high).\n");
+			PWC_ERROR("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);
+		PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
 	}
 	if (power_save)
-		Info("Enabling power save on open/close.\n");
+		PWC_DEBUG_MODULE("Enabling power save on open/close.\n");
 	if (leds[0] >= 0)
 		led_on = leds[0];
 	if (leds[1] >= 0)
@@ -2151,14 +1912,14 @@
 				dot++;
 			/* Few sanity checks */
 			if (*dot != '\0' && dot > colon) {
-				Err("Malformed camera hint: the colon must be after the dot.\n");
+				PWC_ERROR("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");
+					PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
 					return -EINVAL;
 				}
 				else {
@@ -2183,28 +1944,27 @@
 					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			
+			PWC_TRACE("device_hint[%d]:\n", i);
+			PWC_TRACE("  type    : %d\n", device_hint[i].type);
+			PWC_TRACE("  serial# : %s\n", device_hint[i].serial_number);
+			PWC_TRACE("  node    : %d\n", device_hint[i].device_node);
 		}
 		else
 			device_hint[i].type = 0; /* not filled */
 	} /* ..for MAX_DEV_HINTS */
 
- 	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+ 	PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
 	return usb_register(&pwc_driver);
 }
 
 static void __exit usb_pwc_exit(void)
 {
-	Trace(TRACE_MODULE, "Deregistering driver.\n");
+	PWC_DEBUG_MODULE("Deregistering driver.\n");
 	usb_deregister(&pwc_driver);
-	Info("Philips webcam module removed.\n");
+	PWC_INFO("Philips webcam module removed.\n");
 }
 
 module_init(usb_pwc_init);
 module_exit(usb_pwc_exit);
 
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-ioctl.h linux-2.6.15/drivers/usb/media/pwc/pwc-ioctl.h
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-ioctl.h	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-ioctl.h	2006-01-08 01:25:14.000000000 \
+0100
@@ -2,7 +2,7 @@
 #define PWC_IOCTL_H
 
 /* (C) 2001-2004 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -25,7 +25,7 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-/* This is pwc-ioctl.h belonging to PWC 8.12.1
+/* This is pwc-ioctl.h belonging to PWC 10.0.10
    It contains structures and defines to communicate from user space
    directly to the driver.
  */
@@ -37,6 +37,7 @@
    2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
    2003/12/13  Nemosft Unv. Some modifications to make interfacing to
                PWCX easier
+   2006/01/01  Luc Saillard Add raw format definition
  */
 
 /* These are private ioctl() commands, specific for the Philips webcams.
@@ -51,6 +52,7 @@
              ... 	the function
  */
 
+#include <linux/types.h>
 
  /* Enumeration of image sizes */
 #define PSZ_SQCIF	0x00
@@ -65,6 +67,8 @@
 /* The frame rate is encoded in the video_window.flags parameter using
    the upper 16 bits, since some flags are defined nowadays. The following
    defines provide a mask and shift to filter out this value.
+   This value can also be passing using the private flag when using v4l2 and
+   VIDIOC_S_FMT ioctl.
 
    In 'Snapshot' mode the camera freezes its automatic exposure and colour
    balance controls.
@@ -73,6 +77,8 @@
 #define PWC_FPS_MASK		0x00FF0000
 #define PWC_FPS_FRMASK		0x003F0000
 #define PWC_FPS_SNAPSHOT	0x00400000
+#define PWC_QLT_MASK		0x03000000
+#define PWC_QLT_SHIFT		24
 
 
 /* structure for transferring x & y coordinates */
@@ -289,4 +295,28 @@
 };
 #define VIDIOCPWCGVIDTABLE	_IOR('v', 216, struct pwc_table_init_buffer)
 
+/*
+ * This is private command used when communicating with v4l2.
+ * In the future all private ioctl will be remove/replace to 
+ * use interface offer by v4l2.
+ */
+
+#define V4L2_CID_PRIVATE_SAVE_USER       (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_RESTORE_USER    (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_COLOUR_MODE     (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AUTOCONTOUR     (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_PRIVATE_CONTOUR         (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_PRIVATE_BACKLIGHT       (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_PRIVATE_FLICKERLESS     (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
+
+struct pwc_raw_frame {
+   __le16 type;		/* type of the webcam */
+   __le16 vbandlength;	/* Size of 4lines compressed (used by the decompressor) */
+   __u8   cmd[4];	/* the four byte of the command (in case of nala version, only \
the first 3 bytes is filled) */
+   __u8   rawframe[0];	/* frame_size = H/4*vbandlength */
+} __attribute__ ((packed));
+
+
 #endif
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-kiara.c linux-2.6.15/drivers/usb/media/pwc/pwc-kiara.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-kiara.c	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-kiara.c	2006-01-08 01:25:14.000000000 \
+0100
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -316,3 +316,576 @@
    },
 };
 
+
+/*
+ * Rom table for kiara chips
+ *
+ * 32 roms tables (one for each resolution ?)
+ *  2 tables per roms (one for each passes) (Y, and U&V)
+ * 128 bytes per passes
+ */
+
+const unsigned int KiaraRomTable [8][2][16][8] =  
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009292,0x00009493,0x000124db},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009292,
+    0x00009492,0x00009493,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000126dc,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
+
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-kiara.h linux-2.6.15/drivers/usb/media/pwc/pwc-kiara.h
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-kiara.h	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-kiara.h	2006-01-08 01:25:14.000000000 \
+0100
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-misc.c linux-2.6.15/drivers/usb/media/pwc/pwc-misc.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-misc.c	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-misc.c	2006-01-08 01:25:14.000000000 +0100
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam 
    Various miscellaneous functions and tables.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -28,14 +28,14 @@
 
 #include "pwc.h"
 
-struct pwc_coord pwc_image_sizes[PSZ_MAX] =
+const struct pwc_coord pwc_image_sizes[PSZ_MAX] =
 {
-	{ 128,  96, 0 },
-	{ 160, 120, 0 },
-	{ 176, 144, 0 },
-	{ 320, 240, 0 },
-	{ 352, 288, 0 },
-	{ 640, 480, 0 },
+	{ 128,  96, 0 }, /* sqcif */
+	{ 160, 120, 0 }, /* qsif */
+	{ 176, 144, 0 }, /* qcif */
+	{ 320, 240, 0 }, /* sif */
+	{ 352, 288, 0 }, /* cif */
+	{ 640, 480, 0 }, /* vga */
 };
 
 /* x,y -> PSZ_ */
@@ -52,7 +52,7 @@
 	{
 		if (width > pdev->abs_max.x || height > pdev->abs_max.y)
 		{
-			Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
+			PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
                 	return -1;
                 }
 	}
@@ -60,7 +60,7 @@
 	{
 		if (width > pdev->view_max.x || height > pdev->view_max.y)
 		{
-			Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n");
+			PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n");
 			return -1;
 		}
 	}
@@ -81,9 +81,8 @@
 /* initialize variables depending on type and decompressor*/
 void pwc_construct(struct pwc_device *pdev)
 {
-	switch(pdev->type) {
-	case 645:
-	case 646:
+  	if (DEVICE_USE_CODEC1(pdev->type)) {
+
 		pdev->view_min.x = 128;
 		pdev->view_min.y =  96;
 		pdev->view_max.x = 352;
@@ -95,10 +94,23 @@
 		pdev->vendpoint = 4;
 		pdev->frame_header_size = 0;
 		pdev->frame_trailer_size = 0;
-		break;
-	case 675:
-	case 680:
-	case 690:
+
+	} else if (DEVICE_USE_CODEC3(pdev->type)) {
+
+	   	pdev->view_min.x = 160;
+		pdev->view_min.y = 120;
+		pdev->view_max.x = 640;
+		pdev->view_max.y = 480;
+		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+                pdev->abs_max.x = 640;
+                pdev->abs_max.y = 480;
+		pdev->vcinterface = 3;
+		pdev->vendpoint = 5;
+		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+
+	} else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
+
 		pdev->view_min.x = 128;
 		pdev->view_min.y =  96;
 		/* Anthill bug #38: PWC always reports max size, even without PWCX */
@@ -111,25 +123,7 @@
 		pdev->vendpoint = 4;
 		pdev->frame_header_size = 0;
 		pdev->frame_trailer_size = 0;
-		break;
-	case 720:
-	case 730:
-	case 740:
-	case 750:
-		pdev->view_min.x = 160;
-		pdev->view_min.y = 120;
-		pdev->view_max.x = 640;
-		pdev->view_max.y = 480;
-		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
-                pdev->abs_max.x = 640;
-                pdev->abs_max.y = 480;
-		pdev->vcinterface = 3;
-		pdev->vendpoint = 5;
-		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
-		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
-		break;
 	}
-	Debug("type = %d\n",pdev->type);
 	pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
 	pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
 	pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-timon.c linux-2.6.15/drivers/usb/media/pwc/pwc-timon.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-timon.c	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-timon.c	2006-01-08 01:25:14.000000000 \
+0100
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -314,3 +314,1133 @@
    },
 };
 
+/*
+ * 16 versions:
+ *   2 tables  (one for Y, and one for U&V)
+ *   16 levels of details per tables
+ *   8 blocs
+ */
+
+const unsigned int TimonRomTable [16][2][16][8] =  
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000001,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000001,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000049,0x00000249,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009292,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x000124db,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001b724,0x0001b925,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 8 */
+  { /* version 8, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 8, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 9 */
+  { /* version 9, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 9, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 10 */
+  { /* version 10, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 10, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x00009493,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 11 */
+  { /* version 11, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 11, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 12 */
+  { /* version 12, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 12, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 13 */
+  { /* version 13, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 13, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 14 */
+  { /* version 14, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 14, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 15 */
+  { /* version 15, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 15, passes 1 */
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000124db,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-timon.h linux-2.6.15/drivers/usb/media/pwc/pwc-timon.h
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-timon.h	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-timon.h	2006-01-08 01:25:14.000000000 \
+0100
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -42,7 +42,7 @@
 #ifndef PWC_TIMON_H
 #define PWC_TIMON_H
 
-#include "pwc-ioctl.h"
+#include "pwc-ioctl.h" /* for PSZ_MAX */
 
 struct Timon_table_entry
 {
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-uncompress.c linux-2.6.15/drivers/usb/media/pwc/pwc-uncompress.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-uncompress.c	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-uncompress.c	2006-01-08 01:25:14.000000000 \
+0100
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    Decompression frontend.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -22,6 +22,8 @@
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+   vim: set ts=8:  
 */
 
 #include <asm/current.h>
@@ -29,6 +31,8 @@
 
 #include "pwc.h"
 #include "pwc-uncompress.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 int pwc_decompress(struct pwc_device *pdev)
 {
@@ -40,17 +44,11 @@
 
 	if (pdev == NULL)
 		return -EFAULT;
-#if defined(__KERNEL__) && defined(PWC_MAGIC)
-	if (pdev->magic != PWC_MAGIC) {
-		Err("pwc_decompress(): magic failed.\n");
-		return -EFAULT;
-	}
-#endif
 
 	fbuf = pdev->read_frame;
 	if (fbuf == NULL)
 		return -EFAULT;
-	image = pdev->image_ptr[pdev->fill_image];
+	image = pdev->images[pdev->fill_image].bufmem;
 	if (!image)
 		return -EFAULT;
 
@@ -59,88 +57,87 @@
 	/* Raw format; that's easy... */
 	if (pdev->vpalette == VIDEO_PALETTE_RAW)
 	{
-		memcpy(image, yuv, pdev->frame_size);
+		struct pwc_raw_frame *raw_frame = image;
+		raw_frame->type = cpu_to_le16(pdev->type);
+		raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength);
+			/* cmd_buf is always 4 bytes, but sometimes, only the
+			 * first 3 bytes is filled (Nala case). We can
+			 * determine this using the type of the webcam */
+		memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
+		memcpy(raw_frame+1, yuv, pdev->frame_size);
 		return 0;
 	}
 
 	if (pdev->vbandlength == 0) {
-		/* Uncompressed mode. We copy the data into the output buffer,
-		   using the viewport size (which may be larger than the image
-		   size). Unfortunately we have to do a bit of byte stuffing
-		   to get the desired output format/size.
+		/* Uncompressed mode.
+		 * We copy the data into the output buffer, using the viewport
+		 * size (which may be larger than the image size).
+		 * Unfortunately we have to do a bit of byte stuffing to get
+		 * the desired output format/size.
+		 *
+		 * We do some byte shuffling here to go from the
+		 * native format to YUV420P.
 		 */
-			/*
-			 * We do some byte shuffling here to go from the
-			 * native format to YUV420P.
-			 */
-			src = (u16 *)yuv;
-			n = pdev->view.x * pdev->view.y;
-
-			/* offset in Y plane */
-			stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
-			dsty = (u16 *)(image + stride);
-
-			/* offsets in U/V planes */
-			stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
-			dstu = (u16 *)(image + n +         stride);
-			dstv = (u16 *)(image + n + n / 4 + stride);
-
-			/* increment after each line */
-			stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
-
-			for (line = 0; line < pdev->image.y; line++) {
-				for (col = 0; col < pdev->image.x; col += 4) {
-					*dsty++ = *src++;
-					*dsty++ = *src++;
-					if (line & 1)
-						*dstv++ = *src++;
-					else
-						*dstu++ = *src++;
-				}
-				dsty += stride;
+		src = (u16 *)yuv;
+		n = pdev->view.x * pdev->view.y;
+
+		/* offset in Y plane */
+		stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
+		dsty = (u16 *)(image + stride);
+
+		/* offsets in U/V planes */
+		stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
+		dstu = (u16 *)(image + n +         stride);
+		dstv = (u16 *)(image + n + n / 4 + stride);
+
+		/* increment after each line */
+		stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
+
+		for (line = 0; line < pdev->image.y; line++) {
+			for (col = 0; col < pdev->image.x; col += 4) {
+				*dsty++ = *src++;
+				*dsty++ = *src++;
 				if (line & 1)
-					dstv += (stride >> 1);
+					*dstv++ = *src++;
 				else
-					dstu += (stride >> 1);
+					*dstu++ = *src++;
 			}
+			dsty += stride;
+			if (line & 1)
+				dstv += (stride >> 1);
+			else
+				dstu += (stride >> 1);
+		}
+
+		return 0;
 	}
-	else {
-		/* Compressed; the decompressor routines will write the data
-		   in planar format immediately.
-		 */
-		int flags;
-                
-                flags = PWCX_FLAG_PLANAR;
-                if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
-		 {
-		   printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
-		   flags |= PWCX_FLAG_BAYER;
-		   return -ENXIO; /* No such device or address: missing decompressor */
-		 }
-
-#if 0
-		switch (pdev->type)
-		 {
-		  case 675:
-		  case 680:
-		  case 690:
-		  case 720:
-		  case 730:
-		  case 740:
-		  case 750:
-		    pwc_dec23_decompress(&pdev->image, &pdev->view,
-				&pdev->offset, yuv, image, flags,
+
+	/*
+	 * Compressed;
+	 * the decompressor routines will write the data in planar format
+	 * immediately.
+	 */
+	if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) {
+		PWC_ERROR("Mode Bayer is not supported for now\n");
+		/* flags |= PWCX_FLAG_BAYER; */
+		return -ENXIO; /* No such device or address: missing decompressor */
+	}
+
+	if (DEVICE_USE_CODEC1(pdev->type)) {
+
+		/* TODO & FIXME */
+		PWC_ERROR("This chipset is not supported for now\n");
+		return -ENXIO; /* No such device or address: missing decompressor */
+
+	} else {
+		pwc_dec23_decompress(&pdev->image, &pdev->view, &pdev->offset,
+				yuv, image,
+				PWCX_FLAG_PLANAR,
 				pdev->decompress_data, pdev->vbandlength);
-		    break;
-		  case 645:
-		  case 646:
-		    /* TODO & FIXME */
-		    return -ENXIO; /* Missing decompressor */
-		    break;
-		 }
-#endif
+
 	}
 	return 0;
 }
 
 
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-uncompress.h linux-2.6.15/drivers/usb/media/pwc/pwc-uncompress.h
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-uncompress.h	2005-10-28 02:02:08.000000000 \
+0200
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-uncompress.h	2006-01-08 01:25:14.000000000 \
+0100
@@ -1,5 +1,5 @@
 /* (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-v4l.c linux-2.6.15/drivers/usb/media/pwc/pwc-v4l.c
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc-v4l.c	1970-01-01 01:00:00.000000000 \
+0100
+++ linux-2.6.15/drivers/usb/media/pwc/pwc-v4l.c	2006-01-08 01:25:14.000000000 +0100
@@ -0,0 +1,1214 @@
+/* Linux driver for Philips webcam
+   USB and Video4Linux interface part.
+   (C) 1999-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+#include "pwc-ioctl.h"
+
+static struct v4l2_queryctrl pwc_controls[] = {
+        {
+	    .id      = V4L2_CID_BRIGHTNESS,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Brightness",
+	    .minimum = 0,
+	    .maximum = 128,
+	    .step    = 1,
+	    .default_value = 64,
+	},
+        {
+	    .id      = V4L2_CID_CONTRAST,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Contrast",
+	    .minimum = 0,
+	    .maximum = 64,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+        {
+	    .id      = V4L2_CID_SATURATION,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Saturation",
+	    .minimum = -100,
+	    .maximum = 100,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+        {
+	    .id      = V4L2_CID_GAMMA,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Gamma",
+	    .minimum = 0,
+	    .maximum = 32,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+        {
+	    .id      = V4L2_CID_RED_BALANCE,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Red Gain",
+	    .minimum = 0,
+	    .maximum = 256,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+        {
+	    .id      = V4L2_CID_BLUE_BALANCE,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Blue Gain",
+	    .minimum = 0,
+	    .maximum = 256,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+        {
+	    .id      = V4L2_CID_AUTO_WHITE_BALANCE,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Auto White Balance",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_EXPOSURE,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Shutter Speed (Exposure)",
+	    .minimum = 0,
+	    .maximum = 256,
+	    .step    = 1,
+	    .default_value = 200,
+	},
+	{
+	    .id      = V4L2_CID_AUTOGAIN,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Auto Gain Enabled",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 1,
+	},
+	{
+	    .id      = V4L2_CID_GAIN,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Gain Level",
+	    .minimum = 0,
+	    .maximum = 256,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+#if XAWTV_HAS_BEEN_FIXED
+        {
+	    .id      = V4L2_CID_PRIVATE_SAVE_USER,
+	    .type    = V4L2_CTRL_TYPE_BUTTON,
+	    .name    = "Save User Settings",
+	    .minimum = 0,
+	    .maximum = 0,
+	    .step    = 0,
+	    .default_value = 0,
+	},
+        {
+	    .id      = V4L2_CID_PRIVATE_RESTORE_USER,
+	    .type    = V4L2_CTRL_TYPE_BUTTON,
+	    .name    = "Restore User Settings",
+	    .minimum = 0,
+	    .maximum = 0,
+	    .step    = 0,
+	    .default_value = 0,
+	},
+        {
+	    .id      = V4L2_CID_PRIVATE_RESTORE_FACTORY,
+	    .type    = V4L2_CTRL_TYPE_BUTTON,
+	    .name    = "Restore Factory Settings",
+	    .minimum = 0,
+	    .maximum = 0,
+	    .step    = 0,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_COLOUR_MODE,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Colour mode",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_AUTOCONTOUR,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Auto contour",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_CONTOUR,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Contour",
+	    .minimum = 0,
+	    .maximum = 63,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_BACKLIGHT,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Backlight compensation",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	  .id      = V4L2_CID_PRIVATE_FLICKERLESS,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Flickerless",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_NOISE_REDUCTION,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Noise reduction",
+	    .minimum = 0,
+	    .maximum = 3,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+#endif
+};
+
+#if CONFIG_PWC_DEBUG
+static const char *v4l1_ioctls[] = {
+        "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
+        "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
+        "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
+        "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
+        "SMICROCODE", "GVBIFMT", "SVBIFMT" };
+#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
+#endif
+
+static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format \
*f)
+{
+	memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+	f->fmt.pix.width        = pdev->image.x;
+	f->fmt.pix.height       = pdev->image.y;
+	f->fmt.pix.field        = V4L2_FIELD_NONE;
+	if (pdev->vpalette == VIDEO_PALETTE_YUV420P) {
+		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_YUV420;
+		f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
+		f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+	} else {
+		/* vbandlength contains 4 lines ...  */
+		f->fmt.pix.bytesperline = pdev->vbandlength/4;
+		f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame);
+		if (DEVICE_USE_CODEC1(pdev->type))
+			f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC1;
+		else
+			f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC2;
+	}
+	PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
+			"width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", \

+			f->fmt.pix.width,
+			f->fmt.pix.height,
+			f->fmt.pix.bytesperline,
+			f->fmt.pix.sizeimage,
+			(f->fmt.pix.pixelformat)&255,
+			(f->fmt.pix.pixelformat>>8)&255,
+			(f->fmt.pix.pixelformat>>16)&255,
+			(f->fmt.pix.pixelformat>>24)&255);
+}
+
+/* ioctl(VIDIOC_TRY_FMT) */
+static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+		return -EINVAL;
+	}
+
+	switch (f->fmt.pix.pixelformat) {
+		case V4L2_PIX_FMT_YUV420:
+			break;
+		case V4L2_PIX_FMT_PWC1:
+			if (DEVICE_USE_CODEC23(pdev->type)) {
+				PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
+				return -EINVAL;
+			}
+			break;
+		case V4L2_PIX_FMT_PWC2:
+			if (DEVICE_USE_CODEC1(pdev->type)) {
+				PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
+				return -EINVAL;
+			}
+			break;
+		default:
+			PWC_DEBUG_IOCTL("Unsupported pixel format\n");
+			return -EINVAL;
+
+	}
+
+	if (f->fmt.pix.width > pdev->view_max.x)
+		f->fmt.pix.width = pdev->view_max.x;
+	else if (f->fmt.pix.width < pdev->view_min.x)
+		f->fmt.pix.width = pdev->view_min.x;
+
+	if (f->fmt.pix.height > pdev->view_max.y)
+		f->fmt.pix.height = pdev->view_max.y;
+	else if (f->fmt.pix.height < pdev->view_min.y)
+		f->fmt.pix.height = pdev->view_min.y;
+
+	return 0;
+}
+
+/* ioctl(VIDIOC_SET_FMT) */
+static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+	int ret, fps, snapshot, compression, pixelformat;
+
+	ret = pwc_vidioc_try_fmt(pdev, f);
+	if (ret<0)
+		return ret;
+
+	pixelformat = f->fmt.pix.pixelformat;
+	compression = pdev->vcompression;
+	snapshot = 0;
+	fps = pdev->vframes;
+	if (f->fmt.pix.priv) {
+		compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT;
+		snapshot = f->fmt.pix.priv & PWC_FPS_SNAPSHOT;
+		fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+		if (fps == 0)
+			fps = pdev->vframes;
+	}
+
+	PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
+			"compression=%d snapshot=%d format=%c%c%c%c\n",
+			f->fmt.pix.width, f->fmt.pix.height, fps,
+			compression, snapshot,
+			(pixelformat)&255,
+			(pixelformat>>8)&255,
+			(pixelformat>>16)&255,
+			(pixelformat>>24)&255);
+
+	ret = pwc_try_video_mode(pdev,
+				 f->fmt.pix.width,
+				 f->fmt.pix.height,
+				 fps,
+				 compression,
+				 snapshot);
+
+	PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret);
+
+	if (ret)
+		return ret;
+
+	if (pixelformat == V4L2_PIX_FMT_YUV420)
+		pdev->vpalette = VIDEO_PALETTE_YUV420P;
+	else
+		pdev->vpalette = VIDEO_PALETTE_RAW;
+
+	pwc_vidioc_fill_fmt(pdev, f);
+
+	return 0;
+
+}
+
+int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+	 	       unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct pwc_device *pdev;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+
+	switch (_IOC_TYPE(cmd)) {
+		case 'v':
+			PWC_DEBUG_IOCTL("ioctl 0x%x (v4l1, VIDIOC%s)\n", cmd,
+					(_IOC_NR(cmd) < V4L1_IOCTLS) ?  v4l1_ioctls[_IOC_NR(cmd)] : "???");
+			break;
+		case 'V':
+			PWC_DEBUG_IOCTL("ioctl 0x%x (v4l2, %s)\n", cmd,
+					v4l2_ioctl_names[_IOC_NR(cmd)]);
+			break;
+		default:
+			PWC_DEBUG_IOCTL("ioctl 0x%x (unknown)\n", cmd);
+	}
+
+
+	switch (cmd) {
+		/* Query cabapilities */
+		case VIDIOCGCAP:
+		{
+			struct video_capability *caps = arg;
+
+			strcpy(caps->name, vdev->name);
+			caps->type = VID_TYPE_CAPTURE;
+			caps->channels = 1;
+			caps->audios = 1;
+			caps->minwidth  = pdev->view_min.x;
+			caps->minheight = pdev->view_min.y;
+			caps->maxwidth  = pdev->view_max.x;
+			caps->maxheight = pdev->view_max.y;
+			break;
+		}
+
+		/* Channel functions (simulate 1 channel) */
+		case VIDIOCGCHAN:
+		{
+			struct video_channel *v = arg;
+
+			if (v->channel != 0)
+				return -EINVAL;
+			v->flags = 0;
+			v->tuners = 0;
+			v->type = VIDEO_TYPE_CAMERA;
+			strcpy(v->name, "Webcam");
+			return 0;
+		}
+
+		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 = arg;
+			if (v->channel != 0)
+				return -EINVAL;
+			return 0;
+		}
+
+
+		/* Picture functions; contrast etc. */
+		case VIDIOCGPICT:
+		{
+			struct video_picture *p = arg;
+			int val;
+
+			val = pwc_get_brightness(pdev);
+			if (val >= 0)
+				p->brightness = (val<<9);
+			else
+				p->brightness = 0xffff;
+			val = pwc_get_contrast(pdev);
+			if (val >= 0)
+				p->contrast = (val<<10);
+			else
+				p->contrast = 0xffff;
+			/* Gamma, Whiteness, what's the difference? :) */
+			val = pwc_get_gamma(pdev);
+			if (val >= 0)
+				p->whiteness = (val<<11);
+			else
+				p->whiteness = 0xffff;
+			if (pwc_get_saturation(pdev, &val)<0)
+				p->colour = 0xffff;
+			else
+				p->colour = 32768 + val * 327;
+			p->depth = 24;
+			p->palette = pdev->vpalette;
+			p->hue = 0xFFFF; /* N/A */
+			break;
+		}
+
+		case VIDIOCSPICT:
+		{
+			struct video_picture *p = arg;
+			/*
+			 *	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-32768)/327);
+			if (p->palette && p->palette != pdev->vpalette) {
+				switch (p->palette) {
+					case VIDEO_PALETTE_YUV420P:
+					case VIDEO_PALETTE_RAW:
+						pdev->vpalette = p->palette;
+						return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, \
pdev->vcompression, pdev->vsnapshot);
+						break;
+					default:
+						return -EINVAL;
+						break;
+				}
+			}
+			break;
+		}
+
+		/* Window/size parameters */		
+		case VIDIOCGWIN:
+		{
+			struct video_window *vw = arg;
+			
+			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);
+			break;
+		}
+		
+		case VIDIOCSWIN:
+		{
+			struct video_window *vw = arg;
+			int fps, snapshot, ret;
+
+			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 = arg;
+
+			memset(vb,0,sizeof(*vb));
+			break;
+		}
+
+		/* mmap() functions */
+		case VIDIOCGMBUF:
+		{
+			/* Tell the user program how much memory is needed for a mmap() */
+			struct video_mbuf *vm = arg;
+			int i;
+
+			memset(vm, 0, sizeof(*vm));
+			vm->size = pwc_mbufs * PAGE_ALIGN(pdev->len_per_image);
+			vm->frames = pwc_mbufs; /* double buffering should be enough for most applications \
*/
+			for (i = 0; i < pwc_mbufs; i++)
+				vm->offsets[i] = i * PAGE_ALIGN(pdev->len_per_image);
+			break;
+		}
+
+		case VIDIOCMCAPTURE:
+		{
+			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) \
*/
+			struct video_mmap *vm = arg;
+
+			PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, \
vm->frame, vm->format);
+			if (vm->frame < 0 || vm->frame >= pwc_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)
+			{
+				switch (vm->format)
+				{
+					case VIDEO_PALETTE_YUV420P:
+					case VIDEO_PALETTE_RAW:
+						break;
+					default:
+						return -EINVAL;
+						break;
+				}
+			}
+
+			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;
+
+				PWC_DEBUG_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.
+			 */
+			PWC_DEBUG_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 = arg;
+			int ret;
+
+			PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf);
+
+			/* bounds check */
+			if (*mbuf < 0 || *mbuf >= pwc_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.
+			   QUESTION: In what respect? I think that using the
+			             frameq is safe now.
+			 */
+			add_wait_queue(&pdev->frameq, &wait);
+			while (pdev->full_frames == NULL) {
+				/* Check for unplugged/etc. here */
+				if (pdev->error_status) {
+					remove_wait_queue(&pdev->frameq, &wait);
+					set_current_state(TASK_RUNNING);
+					return -pdev->error_status;
+				}
+			
+	                	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.
+			 */
+			PWC_DEBUG_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 = arg;
+			
+			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;
+			break;	
+		}
+		
+		case VIDIOCSAUDIO:
+		{
+			/* Dummy: nothing can be set */
+			break;
+		}
+		
+		case VIDIOCGUNIT:
+		{
+			struct video_unit *vu = arg;
+			
+			vu->video = pdev->vdev->minor & 0x3F;
+			vu->audio = -1; /* not known yet */
+			vu->vbi = -1;
+			vu->radio = -1;
+			vu->teletext = -1;
+			break;
+		}
+
+	    	/* V4L2 Layer */
+	    	case VIDIOC_QUERYCAP:
+	    	{
+		    struct v4l2_capability *cap = arg;
+
+		    PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application"\
+				       "try to use the v4l2 layer\n");
+		    strcpy(cap->driver,PWC_NAME);
+		    strlcpy(cap->card, vdev->name, sizeof(cap->card));
+		    usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info));
+		    cap->version = PWC_VERSION_CODE;
+		    cap->capabilities =
+			V4L2_CAP_VIDEO_CAPTURE	|
+			V4L2_CAP_STREAMING	|
+			V4L2_CAP_READWRITE;
+		    return 0;
+		}
+
+	    	case VIDIOC_ENUMINPUT:
+	    	{
+		    struct v4l2_input *i = arg;
+
+		    if ( i->index )	/* Only one INPUT is supported */
+			  return -EINVAL;
+
+		    memset(i, 0, sizeof(struct v4l2_input));
+		    strcpy(i->name, "usb");
+		    return 0;
+		}
+
+	    	case VIDIOC_G_INPUT:
+		{
+		    int *i = arg;
+		    *i = 0;	/* Only one INPUT is supported */
+		    return 0;
+		}
+	    	case VIDIOC_S_INPUT:
+	    	{
+			int *i = arg;
+
+			if ( *i ) {	/* Only one INPUT is supported */
+				PWC_DEBUG_IOCTL("Only one input source is"\
+					" supported with this webcam.\n");
+				return -EINVAL;
+			}
+			return 0;
+		}
+
+		/* TODO: */
+	    	case VIDIOC_QUERYCTRL:
+		{
+			struct v4l2_queryctrl *c = arg;
+			int i;
+		
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id);
+			for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) {
+				if (pwc_controls[i].id == c->id) {
+					PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
+					memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl));
+					return 0;
+				}
+			}
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n");
+
+			return -EINVAL;
+		}
+		case VIDIOC_G_CTRL:
+		{
+			struct v4l2_control *c = arg;
+			int ret;
+
+			switch (c->id)
+			{
+				case V4L2_CID_BRIGHTNESS:
+					c->value = pwc_get_brightness(pdev);
+					if (c->value<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_CONTRAST:
+					c->value = pwc_get_contrast(pdev);
+					if (c->value<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_SATURATION:
+					ret = pwc_get_saturation(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_GAMMA:
+					c->value = pwc_get_gamma(pdev);
+					if (c->value<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_RED_BALANCE:
+					ret = pwc_get_red_gain(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					c->value >>= 8;
+					return 0;
+				case V4L2_CID_BLUE_BALANCE:
+					ret = pwc_get_blue_gain(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					c->value >>= 8;
+					return 0;
+				case V4L2_CID_AUTO_WHITE_BALANCE:
+					ret = pwc_get_awb(pdev);
+					if (ret<0)
+						return -EINVAL;
+					c->value = (ret == PWC_WB_MANUAL)?0:1;
+					return 0;
+				case V4L2_CID_GAIN:
+					ret = pwc_get_agc(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					c->value >>= 8;
+					return 0;
+				case V4L2_CID_AUTOGAIN:
+					ret = pwc_get_agc(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					c->value = (c->value < 0)?1:0;
+					return 0;
+				case V4L2_CID_EXPOSURE:
+					ret = pwc_get_shutter_speed(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+			        case V4L2_CID_PRIVATE_COLOUR_MODE:
+					ret = pwc_get_colour_mode(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					return 0;
+			        case V4L2_CID_PRIVATE_AUTOCONTOUR:
+					ret = pwc_get_contour(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					c->value=(c->value == -1?1:0);
+					return 0;
+				case V4L2_CID_PRIVATE_CONTOUR:
+					ret = pwc_get_contour(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					c->value >>= 10;
+					return 0;
+				case V4L2_CID_PRIVATE_BACKLIGHT:
+					ret = pwc_get_backlight(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_FLICKERLESS:
+					ret = pwc_get_flicker(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					c->value=(c->value?1:0);
+					return 0;
+				case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+					ret = pwc_get_dynamic_noise(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					return 0;
+
+				case V4L2_CID_PRIVATE_SAVE_USER:
+				case V4L2_CID_PRIVATE_RESTORE_USER:
+				case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+					return -EINVAL;
+			}
+			return -EINVAL;
+		}
+		case VIDIOC_S_CTRL:
+		{
+			struct v4l2_control *c = arg;
+			int ret;
+
+			switch (c->id)
+			{
+				case V4L2_CID_BRIGHTNESS:
+					c->value <<= 9;
+					ret = pwc_set_brightness(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_CONTRAST:
+					c->value <<= 10;
+					ret = pwc_set_contrast(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+			        case V4L2_CID_SATURATION:
+					ret = pwc_set_saturation(pdev, c->value);
+					if (ret<0)
+					  return -EINVAL;
+					return 0;
+				case V4L2_CID_GAMMA:
+					c->value <<= 11;
+					ret = pwc_set_gamma(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_RED_BALANCE:
+					c->value <<= 8;
+					ret = pwc_set_red_gain(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_BLUE_BALANCE:
+					c->value <<= 8;
+					ret = pwc_set_blue_gain(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_AUTO_WHITE_BALANCE:
+					c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO;
+					ret = pwc_set_awb(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_EXPOSURE:
+					c->value <<= 8;
+					ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_AUTOGAIN:
+					/* autogain off means nothing without a gain */
+					if (c->value == 0)
+						return 0;
+					ret = pwc_set_agc(pdev, c->value, 0);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_GAIN:
+					c->value <<= 8;
+					ret = pwc_set_agc(pdev, 0, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_SAVE_USER:
+					if (pwc_save_user(pdev))
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_RESTORE_USER:
+					if (pwc_restore_user(pdev))
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+					if (pwc_restore_factory(pdev))
+						return -EINVAL;
+					return 0;
+			        case V4L2_CID_PRIVATE_COLOUR_MODE:
+				        ret = pwc_set_colour_mode(pdev, c->value);
+					if (ret < 0)
+					  return -EINVAL;
+					return 0;
+			        case V4L2_CID_PRIVATE_AUTOCONTOUR:
+				  c->value=(c->value == 1)?-1:0;
+				  ret = pwc_set_contour(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				  return 0;
+			        case V4L2_CID_PRIVATE_CONTOUR:
+				  c->value <<= 10;
+				  ret = pwc_set_contour(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				  return 0;
+			        case V4L2_CID_PRIVATE_BACKLIGHT:
+				  ret = pwc_set_backlight(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				  return 0;
+			        case V4L2_CID_PRIVATE_FLICKERLESS:
+				  ret = pwc_set_flicker(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+			        case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+				  ret = pwc_set_dynamic_noise(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				  return 0;
+
+			}
+			return -EINVAL;
+		}
+
+		case VIDIOC_ENUM_FMT:
+		{
+		    	struct v4l2_fmtdesc *f = arg;
+			int index; 
+
+			if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			      return -EINVAL;
+
+		    	/* We only support two format: the raw format, and YUV */
+			index = f->index;
+			memset(f,0,sizeof(struct v4l2_fmtdesc));
+			f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			f->index = index;
+			switch(index)
+			{
+				case 0:
+					/* RAW format */
+			    		f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2;
+					f->flags = V4L2_FMT_FLAG_COMPRESSED;
+			    		strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description));
+					break;
+				case 1:
+			    		f->pixelformat = V4L2_PIX_FMT_YUV420;
+			    		strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description));
+					break;
+			    	default:
+			      		return -EINVAL;
+			}
+			return 0;
+		}
+
+	    	case VIDIOC_G_FMT:
+		{
+		    	struct v4l2_format *f = arg;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y);
+			if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			      return -EINVAL;
+
+			pwc_vidioc_fill_fmt(pdev, f);
+
+			return 0;
+		}
+
+		case VIDIOC_TRY_FMT:
+			return pwc_vidioc_try_fmt(pdev, arg);
+
+	    	case VIDIOC_S_FMT:
+			return pwc_vidioc_set_fmt(pdev, arg);
+
+		case VIDIOC_G_STD:
+		{
+			v4l2_std_id *std = arg;
+			*std = V4L2_STD_UNKNOWN;
+			return 0;
+		}
+
+		case VIDIOC_S_STD:
+		{
+			v4l2_std_id *std = arg;
+			if (*std != V4L2_STD_UNKNOWN)
+				return -EINVAL;
+			return 0;
+		}
+
+		case VIDIOC_ENUMSTD:
+		{
+			struct v4l2_standard *std = arg;
+			if (std->index != 0)
+				return -EINVAL;
+			std->id = V4L2_STD_UNKNOWN;
+			strncpy(std->name, "webcam", sizeof(std->name));
+			return 0;
+		}
+
+		case VIDIOC_REQBUFS:
+		{
+			struct v4l2_requestbuffers *rb = arg;
+			int nbuffers;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count);
+			if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+				return -EINVAL;
+			if (rb->memory != V4L2_MEMORY_MMAP)
+				return -EINVAL;
+
+			nbuffers = rb->count;
+			if (nbuffers < 2)
+				nbuffers = 2;
+			else if (nbuffers > pwc_mbufs)
+				nbuffers = pwc_mbufs;
+			/* Force to use our # of buffers */
+			rb->count = pwc_mbufs;
+			return 0;
+		}
+
+		case VIDIOC_QUERYBUF:
+		{
+			struct v4l2_buffer *buf = arg;
+			int index;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index);
+			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+				return -EINVAL;
+			if (buf->memory != V4L2_MEMORY_MMAP)
+				return -EINVAL;
+			index = buf->index;
+			if (index < 0 || index >= pwc_mbufs)
+				return -EINVAL;
+
+			memset(buf, 0, sizeof(struct v4l2_buffer));
+			buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			buf->index = index;
+			buf->m.offset = index * PAGE_ALIGN(pdev->len_per_image);
+			if (pdev->vpalette == VIDEO_PALETTE_RAW)
+				buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+			else
+				buf->bytesused = pdev->view.size;
+			buf->field = V4L2_FIELD_NONE;
+			buf->memory = V4L2_MEMORY_MMAP;
+			//buf->flags = V4L2_BUF_FLAG_MAPPED;
+			buf->length = pdev->len_per_image;
+
+			PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index);
+			PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset);
+			PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused);
+
+			return 0;
+		}
+
+		case VIDIOC_QBUF:
+		{
+			struct v4l2_buffer *buf = arg;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index);
+			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+				return -EINVAL;
+			if (buf->memory != V4L2_MEMORY_MMAP)
+				return -EINVAL;
+			if (buf->index < 0 || buf->index >= pwc_mbufs)
+				return -EINVAL;
+
+			buf->flags |= V4L2_BUF_FLAG_QUEUED;
+			buf->flags &= ~V4L2_BUF_FLAG_DONE;
+
+			return 0;
+		}
+
+		case VIDIOC_DQBUF:
+		{
+			struct v4l2_buffer *buf = arg;
+			int ret;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
+
+			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+				return -EINVAL;
+
+			/* Add ourselves to the frame wait-queue.
+			
+			   FIXME: needs auditing for safety.
+			   QUESTION: 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->error_status) {
+					remove_wait_queue(&pdev->frameq, &wait);
+					set_current_state(TASK_RUNNING);
+					return -pdev->error_status;
+				}
+			
+	                	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);
+				
+			PWC_DEBUG_READ("VIDIOC_DQBUF: frame ready.\n");
+			/* Decompress data in pdev->images[pdev->fill_image] */
+			ret = pwc_handle_frame(pdev);
+			if (ret)
+				return -EFAULT;
+			PWC_DEBUG_READ("VIDIOC_DQBUF: after pwc_handle_frame\n");
+
+			buf->index = pdev->fill_image;
+			if (pdev->vpalette == VIDEO_PALETTE_RAW)
+				buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+			else
+				buf->bytesused = pdev->view.size;
+			buf->flags = V4L2_BUF_FLAG_MAPPED;
+			buf->field = V4L2_FIELD_NONE;
+			do_gettimeofday(&buf->timestamp);
+			buf->sequence = 0;
+			buf->memory = V4L2_MEMORY_MMAP;
+			buf->m.offset = pdev->fill_image * PAGE_ALIGN(pdev->len_per_image);
+			buf->length = buf->bytesused;
+			PWC_DEBUG_READ("VIDIOC_DQBUF: buf->index=%d\n",buf->index);
+			PWC_DEBUG_READ("VIDIOC_DQBUF: buf->length=%d\n",buf->length);
+			PWC_DEBUG_READ("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset);
+			PWC_DEBUG_READ("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused);
+
+
+			pwc_next_image(pdev);
+			PWC_DEBUG_READ("VIDIOC_DQBUF: leaving\n");
+			return 0;
+
+		}
+
+		case VIDIOC_STREAMON:
+	       	{
+			return 0;
+		}
+
+		case VIDIOC_STREAMOFF:
+	       	{
+			return 0;
+		}
+	
+		default:
+			return pwc_ioctl(pdev, cmd, arg);
+	} /* ..switch */
+	return 0;
+}	
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff -Naur /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc.h linux-2.6.15/drivers/usb/media/pwc/pwc.h
--- /tmp/linux-2.6.15.orig/drivers/usb/media/pwc/pwc.h	2006-01-08 01:22:23.000000000 \
+0100
+++ linux-2.6.15/drivers/usb/media/pwc/pwc.h	2006-01-08 01:25:14.000000000 +0100
@@ -1,5 +1,5 @@
 /* (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -30,50 +30,86 @@
 #include <linux/usb.h>
 #include <linux/spinlock.h>
 #include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/wait.h>
 #include <linux/smp_lock.h>
+#include <linux/version.h>
 #include <asm/semaphore.h>
 #include <asm/errno.h>
 
 #include "pwc-uncompress.h"
 #include "pwc-ioctl.h"
 
-/* Defines and structures for the Philips webcam */
-/* Used for checking memory corruption/pointer validation */
-#define PWC_MAGIC 0x89DC10ABUL
-#undef PWC_MAGIC
-
 /* Turn some debugging options on/off */
-#define PWC_DEBUG 0
+#ifndef CONFIG_PWC_DEBUG
+#define CONFIG_PWC_DEBUG 1
+#endif
+
+/* Version block */
+#define PWC_MAJOR	10
+#define PWC_MINOR	0
+#define PWC_EXTRAMINOR	11
+#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
+#define PWC_VERSION 	"10.0.11-unofficial"
+#define PWC_NAME 	"pwc"
+#define PFX		PWC_NAME ": "
+
 
 /* Trace certain actions in the driver */
-#define TRACE_MODULE	0x0001
-#define TRACE_PROBE	0x0002
-#define TRACE_OPEN	0x0004
-#define TRACE_READ	0x0008
-#define TRACE_MEMORY	0x0010
-#define TRACE_FLOW	0x0020
-#define TRACE_SIZE	0x0040
-#define TRACE_PWCX	0x0080
-#define TRACE_SEQUENCE	0x1000
-
-#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
-#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
-#define Info(A...)  printk(KERN_INFO  PWC_NAME " " A)
-#define Err(A...)   printk(KERN_ERR   PWC_NAME " " A)
+#define PWC_DEBUG_LEVEL_MODULE	(1<<0)
+#define PWC_DEBUG_LEVEL_PROBE	(1<<1)
+#define PWC_DEBUG_LEVEL_OPEN	(1<<2)
+#define PWC_DEBUG_LEVEL_READ	(1<<3)
+#define PWC_DEBUG_LEVEL_MEMORY	(1<<4)
+#define PWC_DEBUG_LEVEL_FLOW	(1<<5)
+#define PWC_DEBUG_LEVEL_SIZE	(1<<6)
+#define PWC_DEBUG_LEVEL_IOCTL	(1<<7)
+#define PWC_DEBUG_LEVEL_SEQ	(1<<8)
+#define PWC_DEBUG_LEVEL_TRACE	(1<<8)
+
+#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args)
+#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args)
+#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args)
+#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args)
+#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args)
+#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args)
+#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args)
+#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args)
+#define PWC_DEBUG_SEQ(fmt, args...) PWC_DEBUG(SEQ, fmt, ##args)
+#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+
+#if CONFIG_PWC_DEBUG
+
+#define PWC_DEBUG_LEVEL	(PWC_DEBUG_LEVEL_MODULE)
+
+#define PWC_DEBUG(level, fmt, args...) do {\
+	  if ((PWC_DEBUG_LEVEL_ ##level) & PWC_DEBUG_LEVEL) \
+	     printk(KERN_DEBUG PFX fmt, ##args); \
+	  } while(0)
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+#else /* if ! CONFIG_PWC_DEBUG */
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) do { } while(0)
+#define PWC_DEBUG(level, fmt, args...) do { } while(0)
 
+#endif
 
 /* Defines for ToUCam cameras */
 #define TOUCAM_HEADER_SIZE		8
 #define TOUCAM_TRAILER_SIZE		4
 
 #define FEATURE_MOTOR_PANTILT		0x0001
-
-/* Version block */
-#define PWC_MAJOR	9
-#define PWC_MINOR	0
-#define PWC_VERSION 	"9.0.2-unofficial"
-#define PWC_NAME 	"pwc"
+#define FEATURE_CODEC1			0x0002
+#define FEATURE_CODEC2			0x0004
 
 /* Turn certain features on/off */
 #define PWC_INT_PIPE 0
@@ -95,6 +131,18 @@
 /* Absolute maximum number of buffers available for mmap() */
 #define MAX_IMAGES 		10
 
+/* Some macros to quickly find the type of a webcam */ 
+#define DEVICE_USE_CODEC1(x) ((x)<675)
+#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700)
+#define DEVICE_USE_CODEC3(x) ((x)>=700)
+#define DEVICE_USE_CODEC23(x) ((x)>=675)
+
+
+#ifndef V4L2_PIX_FMT_PWC1
+#define V4L2_PIX_FMT_PWC1	v4l2_fourcc('P','W','C','1')
+#define V4L2_PIX_FMT_PWC2	v4l2_fourcc('P','W','C','2')
+#endif
+
 /* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
 struct pwc_iso_buf
 {
@@ -110,17 +158,19 @@
    void *data;
    volatile int filled;		/* number of bytes filled */
    struct pwc_frame_buf *next;	/* list */
-#if PWC_DEBUG
-   int sequence;		/* Sequence number */
-#endif
+};
+
+/* additionnal informations used when dealing image between kernel and userland \
*/
+struct pwc_imgbuf
+{
+	void *bufmem;		/* addr of this buffer in kernel space */
+	int   vma_use_count;	/* count the number of time this memory is mapped */
 };
 
 struct pwc_device
 {
    struct video_device *vdev;
-#ifdef PWC_MAGIC
-   int magic;
-#endif
+
    /* Pointer to our usb_device */
    struct usb_device *udev;
    
@@ -177,12 +227,8 @@
    int frame_size;
    int frame_total_size; /* including header & trailer */
    int drop_frames;
-#if PWC_DEBUG
-   int sequence;			/* Debugging aid */
-#endif
 
    /* 3: decompression */
-   struct pwc_decompressor *decompressor;	/* function block with decompression routines \
*/
    void *decompress_data;		/* private data for decompression engine */
 
    /* 4: image */
@@ -198,7 +244,7 @@
    struct pwc_coord offset;		/* offset within the viewport */
 
    void *image_data;			/* total buffer, which is subdivided into ... */
-   void *image_ptr[MAX_IMAGES];		/* ...several images... */
+   struct pwc_imgbuf images[MAX_IMAGES];/* ...several images... */
    int fill_image;			/* ...which are rotated. */
    int len_per_image;			/* length per image */
    int image_read_pos;			/* In case we read data in pieces, keep track of were we \
are in the imagebuffer */
@@ -211,6 +257,7 @@
    struct pwc_mpt_range angle_range;
    int pan_angle;			/* in degrees * 100 */
    int tilt_angle;			/* absolute angle; 0,0 is home position */
+   int snapshot_button_status;		/* set to 1 when the user push the button, reset \
to 0 when this value is read */
 
    /*** Misc. data ***/
    wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
@@ -219,20 +266,23 @@
 #endif
 };
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* Global variable */
+/* Global variables */
 extern int pwc_trace;
+extern int pwc_preferred_compression;
+extern int pwc_mbufs;
 
 /** functions in pwc-if.c */
 int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, \
int new_compression, int new_snapshot);
+int pwc_handle_frame(struct pwc_device *pdev);
+void pwc_next_image(struct pwc_device *pdev);
 
 /** Functions in pwc-misc.c */
 /* sizes in pixels */
-extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
+extern const struct pwc_coord pwc_image_sizes[PSZ_MAX];
 
 int pwc_decode_size(struct pwc_device *pdev, int width, int height);
 void pwc_construct(struct pwc_device *pdev);
@@ -240,6 +290,9 @@
 /** Functions in pwc-ctrl.c */
 /* Request a certain video mode. Returns < 0 if not possible */
 extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int \
frames, int compression, int snapshot);
+/* Calculate the number of bytes per image (not frame) */
+extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
+extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
 
 /* Various controls; should be obvious. Value 0..65535, or < 0 on error */
 extern int pwc_get_brightness(struct pwc_device *pdev);
@@ -248,10 +301,37 @@
 extern int pwc_set_contrast(struct pwc_device *pdev, int value);
 extern int pwc_get_gamma(struct pwc_device *pdev);
 extern int pwc_set_gamma(struct pwc_device *pdev, int value);
-extern int pwc_get_saturation(struct pwc_device *pdev);
+extern int pwc_get_saturation(struct pwc_device *pdev, int *value);
 extern int pwc_set_saturation(struct pwc_device *pdev, int value);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
+extern int pwc_restore_user(struct pwc_device *pdev);
+extern int pwc_save_user(struct pwc_device *pdev);
+extern int pwc_restore_factory(struct pwc_device *pdev);
+
+/* exported for use by v4l2 controls */
+extern int pwc_get_red_gain(struct pwc_device *pdev, int *value);
+extern int pwc_set_red_gain(struct pwc_device *pdev, int value);
+extern int pwc_get_blue_gain(struct pwc_device *pdev, int *value);
+extern int pwc_set_blue_gain(struct pwc_device *pdev, int value);
+extern int pwc_get_awb(struct pwc_device *pdev);
+extern int pwc_set_awb(struct pwc_device *pdev, int mode);
+extern int pwc_set_agc(struct pwc_device *pdev, int mode, int value);
+extern int pwc_get_agc(struct pwc_device *pdev, int *value);
+extern int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value);
+extern int pwc_get_shutter_speed(struct pwc_device *pdev, int *value);
+
+extern int pwc_set_colour_mode(struct pwc_device *pdev, int colour);
+extern int pwc_get_colour_mode(struct pwc_device *pdev, int *colour);
+extern int pwc_set_contour(struct pwc_device *pdev, int contour);
+extern int pwc_get_contour(struct pwc_device *pdev, int *contour);
+extern int pwc_set_backlight(struct pwc_device *pdev, int backlight);
+extern int pwc_get_backlight(struct pwc_device *pdev, int *backlight);
+extern int pwc_set_flicker(struct pwc_device *pdev, int flicker);
+extern int pwc_get_flicker(struct pwc_device *pdev, int *flicker);
+extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise);
+extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise);
 
 /* Power down or up the camera; not supported by all models */
 extern int pwc_camera_power(struct pwc_device *pdev, int power);
@@ -259,6 +339,9 @@
 /* Private ioctl()s; see pwc-ioctl.h */
 extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
 
+/** Functions in pwc-v4l.c */
+extern int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+			      unsigned int cmd, void *arg);
 
 /** pwc-uncompress.c */
 /* Expand frame to image, possibly including decompression. Uses read_frame and \
fill_image */
@@ -270,3 +353,4 @@
 
 
 #endif
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
Linux 2.6.15.2-r1 3887  177165 Carl...
The Linux Kernel.
Linux 2.6.15.1-r1 3887  149219 Jona...
The Linux Kernel.
Linux 2.6.15-r1 3887  149214 Luca...
The Linux Kernel.
Linux 2.6.14.4-r1 3887  150166 Jona...
The Linux Kernel.
Linux 2.6.14.3-r1 3887  150060 Jona...
The Linux Kernel.
Linux 2.6.14.2-r1 3887  149791 Carl...
The Linux Kernel.
Linux 2.6.13.4-r1 3887  149559 Luca...
The Linux Kernel.
Linux 2.6.13.2-r1 3887  56611 Jona...
The Linux Kernel.
Linux 2.6.13.1-r1 3887  56378 Luca...
The Linux Kernel.
Linux 2.6.12.2-r1 3887  50355 Luca...
The Linux Kernel.
Linux 2.6.11.9-r1 3887  98969 Luca...
The Linux Kernel.
Linux 2.6.11.8-r1 3887  109424 Jona...
The Linux Kernel.
Linux 2.6.11-r1 3887  99032 Luca...
The Linux Kernel.
Linux 2.6.10-r1 3887  65969 Luca...
The Linux Kernel.
Linux 2.6.9-r1 3887  278461 Luca...
The Linux Kernel.
Linux 2.6.8.1-r1 3887  35576 Luca...
The Linux Kernel.
Linux 2.6.7-r1 3887  22610 Luca...
The Linux Kernel.
Linux 2.6.6-r1 3887  21958 Luca...
The Linux Kernel.
Linux 2.4.26-r1 3887  22359 Luca...
The Linux Kernel.