ChangeSet 1.1291, 2003/12/12 14:04:18-08:00, luca.risolia@studio.unibo.it

[PATCH] USB: W996[87]CF driver update


 CREDITS                           |    6 
 Documentation/Configure.help      |   15 
 Documentation/usb/w9968cf.txt     |  158 +++----
 MAINTAINERS                       |   10 
 drivers/usb/w9968cf.c             |  782 +++++++++++++++++++-------------------
 drivers/usb/w9968cf.h             |   66 +--
 drivers/usb/w9968cf_decoder.h     |    2 
 drivers/usb/w9968cf_externaldef.h |   13 
 8 files changed, 528 insertions(+), 524 deletions(-)


diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Fri Dec 12 15:05:19 2003
+++ b/CREDITS	Fri Dec 12 15:05:19 2003
@@ -2597,9 +2597,9 @@
 S: USA
 
 N: Luca Risolia
-E: luca_ing@libero.it
-D: V4L driver for W996[87]CF JPEG USB Dual Mode Camera Chip
-S: Via Libertà 41/a
+E: luca.risolia@studio.unibo.it
+D: V4L driver for W996[87]CF JPEG USB Dual Mode Camera Chips
+S: Via Liberta' 41-A
 S: Osio Sotto, 24046, Bergamo
 S: Italy
 
diff -Nru a/Documentation/Configure.help b/Documentation/Configure.help
--- a/Documentation/Configure.help	Fri Dec 12 15:05:19 2003
+++ b/Documentation/Configure.help	Fri Dec 12 15:05:19 2003
@@ -15361,19 +15361,18 @@
 
   This driver has an optional plugin, which is distributed as a
   separate module only (released under GPL). It contains code that 
-  allows you to use higher resolutions and framerates, and can't
-  be included into the official Linux kernel for performance 
-  purposes.
-  At the moment the driver needs a third-part module for the CMOS 
+  allows you to use higher resolutions and framerates, and cannot
+  be included in the official Linux kernel for performance purposes.
+  At the moment the driver needs a third-party module for the CMOS 
   sensors, which is available on internet: it is recommended to read
   <file:Documentation/usb/w9968cf.txt> for more informations and for
   a list of supported cameras.
 
   This driver uses the Video For Linux and the I2C APIs. 
-  You must say Y or M to both "Video For Linux" and 
-  "I2C Support" to use this driver.
-  Information on this API and pointers to "v4l" programs may be found
-  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+  You must say Y or M to both "Video For Linux" and "I2C Support" 
+  to use this driver. Information on this API and pointers to "v4l" 
+  programs may be found on the WWW at 
+  <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
diff -Nru a/Documentation/usb/w9968cf.txt b/Documentation/usb/w9968cf.txt
--- a/Documentation/usb/w9968cf.txt	Fri Dec 12 15:05:19 2003
+++ b/Documentation/usb/w9968cf.txt	Fri Dec 12 15:05:19 2003
@@ -1,6 +1,7 @@
 
-         W996[87]CF JPEG USB Dual Mode Camera Chip driver for Linux 2.4
-         ==============================================================
+                   W996[87]CF JPEG USB Dual Mode Camera Chip
+                        Linux 2.4 driver (basic version)
+                   =========================================
 
                                - Documentation -
 
@@ -11,7 +12,7 @@
 2. License
 3. Overview
 4. Supported devices
-5. Kernel configuration and third-part module compilation
+5. Module dependencies
 6. Module loading
 7. Module paramaters
 8. Credits
@@ -19,7 +20,7 @@
 
 1. Copyright
 ============
-Copyright (C) 2002 2003 by Luca Risolia <luca_ing@libero.it>
+Copyright (C) 2002 2003 by Luca Risolia <luca.risolia@studio.unibo.it>
 
 
 2. License
@@ -45,20 +46,23 @@
 Winbond W9967CF and Winbond W9968CF JPEG USB Dual Mode Camera Chips, when they
 are being commanded by USB.
 
-The driver relies on the Video4Linux, USB and I2C core modules of the Linux
-kernel, version 2.4.19 or greater, and is not compatible in any way with
-previous versions. It has been designed to run properly on SMP systems
-as well. At the moment, an additional module, "ovcamchip", is mandatory; it
-provides support for some OmniVision CMOS sensors connected to the W996[87]CF
-chips.
-
-The driver is split into two modules: the basic one, "w9968cf", is needed for
-the supported devices to work; the second one, "w9968cf-vpp", is an optional
-module, which provides some useful video post-processing functions like video
-decoding, up-scaling and colour conversions (these routines can't be included
-into official kernels). Once the driver is installed, every time an application
-tries to open a recognized device, "w9968cf" checks the presence of the
-"w9968cf-vpp" module and loads it automatically by default.
+The full-featured driver is divided into two modules: the basic one, "w9968cf",
+is needed for the supported devices to work; the second one, "w9968cf-vpp",
+is an optional module, which provides some useful video post-processing
+functions like video decoding, up-scaling and colour conversions. Once the
+driver is installed, every time an application tries to open a recognized
+device, "w9968cf" checks the presence of the "w9968cf-vpp" module and loads it
+automatically by default.
+
+Please keep in mind that official kernels do NOT include the second module for
+performance purposes. However it is always recommended to download and install
+the latest and complete release of the driver, replacing the existing one, if
+present: it will be still even possible not to load the "w9968cf-vpp" module at
+all, if you ever want to. Another important missing feature of the version in
+the official Linux 2.4 kernels is the writeable /proc filesystem interface.
+
+The latest and full-featured version of the W996[87]CF driver can be found at:
+http://go.lamarinapunto.com/
 
 Up to 32 cameras can be handled at the same time. They can be connected and
 disconnected from the host many times without turning off the computer, if
@@ -67,15 +71,17 @@
 To change the default settings for each camera, many paramaters can be passed
 through command line when the module is loaded into memory.
 
-It is recommended to install the latest and full featured version of the 
-W996[87]CF driver, which can be found at:
-http://go.lamarinapunto.com/
+The driver relies on the Video4Linux, USB and I2C core modules of the official
+Linux kernels, version 2.4.19 or greater, and is not compatible in any way with
+previous versions. It has been designed to run properly on SMP systems as well.
+At the moment, an additional module, "ovcamchip", is mandatory; it provides
+support for some OmniVision CMOS sensors connected to the W996[87]CF chips.
 
-The "ovcamchip" module is part of the OV511 driver, version 2.25, which can be
+The "ovcamchip" module is part of the OV511 driver, version 2.27, which can be
 downloaded from internet:
 http://alpha.dyndns.org/ov511/
-To know how to patch, compile and load it, read the "Kernel configuration"
-paragraph.
+To know how to compile it, read the documentation included in the OV511 
+package.
 
 
 4. Supported devices
@@ -94,22 +100,21 @@
 The list above does NOT imply that all those devices work with this driver: up
 until now only webcams that have a CMOS sensor supported by the "ovcamchip"
 module work. 
-For a list of supported CMOS sensors, please visit the module author homepage:
-http://alpha.dyndns.org/ov511/
+For a list of supported CMOS sensors, please visit the the author's homepage on
+this module: http://alpha.dyndns.org/ov511/
 
 Possible external microcontrollers of those webcams are not supported: this
-means that still images can't be downloaded from the device memory.
+means that still images cannot be downloaded from the device memory.
 
 Furthermore, it's worth to note that I was only able to run tests on my
 "Creative Labs Video Blaster WebCam Go". Donations of other models, for
 additional testing and full support, would be much appreciated.
 
 
-5. Kernel configuration and third-part module compilation
-=========================================================
-As noted above, kernel 2.4.19 is the minimum for this driver; for it to work
-properly, the driver needs kernel support for Video4Linux, USB and I2C, and a
-third-part module for the CMOS sensor.
+5. Module dependencies
+======================
+The driver needs kernel support for Video4Linux, USB and I2C, and a third-party
+module for the CMOS sensor.
 
 The following options of the kernel configuration file must be enabled and
 corresponding modules must be compiled:
@@ -128,7 +133,7 @@
 	#
 	CONFIG_USB=m
 
-In addition, depending on the hardware being used, just one of the modules
+In addition, depending on the hardware being used, only one of the modules
 below is necessary:
 
 	# USB Host Controller Drivers
@@ -138,6 +143,12 @@
 	CONFIG_USB_UHCI_ALT=m
 	CONFIG_USB_OHCI=m
 
+And finally:
+
+	# USB Multimedia devices
+	#
+	CONFIG_USB_W9968CF=m
+
 Also, make sure "Enforce bandwidth allocation" is NOT enabled.
 
 The /proc filesystem can be optionally built into the kernel:
@@ -150,39 +161,18 @@
 	#
 	CONFIG_VIDEO_PROC_FS=y
 
-	# USB Multimedia devices
-	#
-	CONFIG_USB_W9968CF=m
-
 The last module we need is "ovcamchip.o". To obtain it, you have to download
-the OV511 driver, version 2.25 - don't use other versions - which is available
-at http://alpha.dyndns.org/ov511/ . Then you have to download the latest 
-version of the full featured W996[87]CF driver, which contains a patch for the
-"ovcamchip" module; it is available at http://go.lamarinapunto.com .
-Once you have obtained the packages, decompress, patch and compile the 
-"ovcamchip" module. In other words:
-
-	[user@localhost home]$ tar xvzf w9968cf-x.x.tar.gz
-	[user@localhost home]$ tar xvjf ov511-2.25.tar.bz2
-	[user@localhost home]$ cd ov511-2.25
-	[user@localhost ov511-2.25]$ patch -p1 <                              \
-	                             /path/to/w9968cf-x.x/ov511-2.25.patch
-	[user@localhost ov511-2.25]$ make
-
-It's worth to note that the full featured version of the W996[87]CF driver
-can also be installed overwriting the one in the kernel; in this case, read the
-documentation included in the package.
-
-If everything went well, the W996[87]CF driver can be immediatly used (see next
-paragraph).
+the OV511, version 2.27 - don't use other versions - and compile it according
+to its documentation. 
+The package is available at http://alpha.dyndns.org/ov511/ .
 
 
 6. Module loading
 =================
 To use the driver, it is necessary to load the "w9968cf" module into memory
-after every other module required; they are named, in order: "videodev",
-"usbcore", then "ehci-hcd", "usb-uhci", "uhci", "usb-ohci" (just one), and also
-"i2c-core" and "ovcamchip".
+after every other module required: for the 2.4 series of the kernel, they are
+named, in order: "videodev", "usbcore", then "ehci-hcd", "usb-uhci", "uhci",
+"usb-ohci" (just one), and also "i2c-core" and "ovcamchip".
 
 Loading can be done this way, from root:
 
@@ -213,11 +203,10 @@
 
 7. Module paramaters
 ====================
-
 Module paramaters are listed below:
 -------------------------------------------------------------------------------
 Name:           vppmod_load
-Type:           int
+Type:           bool
 Syntax:         <0|1>
 Description:    Automatic 'w9968cf-vpp' module loading: 0 disabled, 1 enabled.
                 If enabled, every time an application attempts to open a
@@ -258,22 +247,22 @@
 Name:           max_buffers
 Type:           int array (min = 0, max = 32)
 Syntax:         <n[,...]>
-Description:    Only for advanced users.
+Description:    For advanced users.
                 Specify the maximum number of video frame buffers to allocate
                 for each device, from 2 to 32.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           double_buffer
-Type:           int array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]> 
 Description:    Hardware double buffering: 0 disabled, 1 enabled.
                 It should be enabled if you want smooth video output: if you
-                obtain out of sync. video, disable it at all, or try to
+                obtain out of sync. video, disable it, or try to
                 decrease the 'clockdiv' module paramater value.
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 Name:           clamping
-Type:           int array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]> 
 Description:    Video data clamping: 0 disabled, 1 enabled.
 Default:        0 for every device.
@@ -288,13 +277,13 @@
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           largeview
-Type:           int array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]> 
 Description:    Large view: 0 disabled, 1 enabled.
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 Name:           upscaling
-Type:           int array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]> 
 Description:    Software scaling (for non-compressed video only):
                 0 disabled, 1 enabled.
@@ -316,9 +305,8 @@
                 YUV420P/YUV420 in any resolutions where width and height are
                 multiples of 16.
 Default:        2 for every device.
-Note:           If 'w9968cf-vpp' is not loaded, this paramater is set to,
-                forcing decompression is not allowed; in this case this 
-                paramater is set to 2.
+Note:           If 'w9968cf-vpp' is not loaded, forcing decompression is not
+                allowed; in this case this paramater is set to 2.
 -------------------------------------------------------------------------------
 Name:           force_palette
 Type:           int array (min = 0, max = 32)
@@ -342,7 +330,7 @@
 Note:           If 'w9968cf-vpp' is not loaded, this paramater is set to 9.
 -------------------------------------------------------------------------------
 Name:           force_rgb
-Type:           int array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Read RGB video data instead of BGR:
                 1 = use RGB component ordering.
@@ -351,28 +339,28 @@
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           autobright
-Type:           long array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    CMOS sensor automatically changes brightness:
                 0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           autoexp
-Type:           long array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    CMOS sensor automatically changes exposure:
                 0 = no, 1 = yes
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 Name:           lightfreq
-Type:           long array (min = 0, max = 32)
+Type:           int array (min = 0, max = 32)
 Syntax:         <50|60[,...]>
 Description:    Light frequency in Hz:
                 50 for European and Asian lighting, 60 for American lighting.
 Default:        50 for every device.
 -------------------------------------------------------------------------------
 Name:           bandingfilter
-Type:           long array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]> 
 Description:    Banding filter to reduce effects of fluorescent 
                 lighting:
@@ -382,7 +370,7 @@
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           clockdiv
-Type:           long array (min = 0, max = 32)
+Type:           int array (min = 0, max = 32)
 Syntax:         <-1|n[,...]>
 Description:    Force pixel clock divisor to a specific value (for experts):
                 n may vary from 0 to 127.
@@ -391,21 +379,21 @@
 Default:        -1 for every device.
 -------------------------------------------------------------------------------
 Name:           backlight
-Type:           long array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Objects are lit from behind:
                 0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           mirror
-Type:           long array (min = 0, max = 32)
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Reverse image horizontally:
                 0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
-Name:           sensor_mono
-Type:           long array (min = 0, max = 32)
+Name:           monochrome
+Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]> 
 Description:    The CMOS sensor is monochrome:
                 0 = no, 1 = yes
@@ -446,7 +434,7 @@
 Type:           int
 Syntax:         <n> 
 Description:    Debugging information level, from 0 to 6:
-                0 = none (be cautious)
+                0 = none (use carefully)
                 1 = critical errors
                 2 = significant informations
                 3 = configuration or general messages
@@ -458,7 +446,7 @@
 Default:        2
 -------------------------------------------------------------------------------
 Name:           specific_debug
-Type:           int
+Type:           bool
 Syntax:         <0|1>
 Description:    Enable or disable specific debugging messages:
                 0 = print messages concerning every level <= 'debug' level.
@@ -479,8 +467,6 @@
 - memory management code has been copied from the bttv driver by Ralph Metzler,
   Marcus Metzler and Gerd Knorr;
 
-- the low-level I2C read function has been written by Frédéric Jouault, who
-  also gave me commented logs about sniffed USB traffic taken from another
-  driver for another system;
+- the low-level I2C read function has been written by Frederic Jouault;
 
-- the low-level I2C fast write function has been written by Piotr Czerczak;
+- the low-level I2C fast write function has been written by Piotr Czerczak.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Fri Dec 12 15:05:19 2003
+++ b/MAINTAINERS	Fri Dec 12 15:05:19 2003
@@ -2070,11 +2070,11 @@
 S:	Maintained
 
 USB W9968CF DRIVER
-P:      Luca Risolia
-M:      luca_ing@libero.it
-L:      linux-usb-devel@lists.sourceforge.net
-W:      http://go.lamarinapunto.com
-S:      Maintained
+P:	Luca Risolia
+M:	luca.risolia@studio.unibo.it
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://go.lamarinapunto.com
+S:	Maintained
 
 VFAT FILESYSTEM:
 P:	Gordon Chaffee
diff -Nru a/drivers/usb/w9968cf.c b/drivers/usb/w9968cf.c
--- a/drivers/usb/w9968cf.c	Fri Dec 12 15:05:19 2003
+++ b/drivers/usb/w9968cf.c	Fri Dec 12 15:05:19 2003
@@ -1,14 +1,14 @@
 /***************************************************************************
  * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip.       *
  *                                                                         *
- * Copyright (C) 2002 2003 by Luca Risolia <luca_ing@libero.it>            *
+ * Copyright (C) 2002 2003 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * - Memory management code from bttv driver by Ralph Metzler,             *
  *   Marcus Metzler and Gerd Knorr.                                        *
  * - I2C interface to kernel, high-level CMOS sensor control routines and  *
  *   some symbolic names from OV511 driver by Mark W. McClelland.          *
  * - Low-level I2C fast write function by Piotr Czerczak.                  *
- * - Low-level I2C read function by Frédéric Jouault.                      *
+ * - Low-level I2C read function by Frederic Jouault.                      *
  *                                                                         *
  * 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    *
@@ -46,17 +46,19 @@
 #include "w9968cf.h"
 #include "w9968cf_decoder.h"
 
-EXPORT_NO_SYMBOLS;
-
-
 
 /****************************************************************************
- * Modules paramaters                                                       *
+ * Module macros and paramaters                                             *
  ****************************************************************************/
 
+MODULE_AUTHOR(W9968CF_MODULE_AUTHOR" "W9968CF_AUTHOR_EMAIL);
+MODULE_DESCRIPTION(W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION);
+MODULE_LICENSE(W9968CF_MODULE_LICENSE);
+MODULE_SUPPORTED_DEVICE("Video");
+
 static u8 vppmod_load = W9968CF_VPPMOD_LOAD;
 static u8 simcams = W9968CF_SIMCAMS;
-static int video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /* -1=first free */
+static s8 video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /* -1=first free */
 static u16 packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_PACKET_SIZE};
 static u8 max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BUFFERS};
 static u8 double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] = 
@@ -74,10 +76,10 @@
 static u8 lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_LIGHTFREQ};
 static u8 bandingfilter[] = {[0 ... W9968CF_MAX_DEVICES-1]=
                              W9968CF_BANDINGFILTER};
-static int clockdiv[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLOCKDIV};
+static s8 clockdiv[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLOCKDIV};
 static u8 backlight[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BACKLIGHT};
 static u8 mirror[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_MIRROR};
-static u8 sensor_mono[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_SENSOR_MONO};
+static u8 monochrome[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_MONOCHROME};
 static u16 brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BRIGHTNESS};
 static u16 hue[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_HUE};
 static u16 colour[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_COLOUR};
@@ -88,36 +90,27 @@
 static u8 specific_debug = W9968CF_SPECIFIC_DEBUG;
 #endif
 
-MODULE_AUTHOR("Luca Risolia <luca_ing@libero.it>");
-
-MODULE_DESCRIPTION("Video4Linux driver for "
-                   "W996[87]CF JPEG USB Dual Mode Camera Chip");
-
-MODULE_SUPPORTED_DEVICE("Video");
-
-MODULE_LICENSE("GPL");
-
-MODULE_PARM(vppmod_load, "i");
+MODULE_PARM(vppmod_load, "b");
 MODULE_PARM(simcams, "i");
 MODULE_PARM(video_nr, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
 MODULE_PARM(packet_size, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
 MODULE_PARM(max_buffers, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
-MODULE_PARM(double_buffer, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
-MODULE_PARM(clamping, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(double_buffer, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
+MODULE_PARM(clamping, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
 MODULE_PARM(filter_type, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
-MODULE_PARM(largeview, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(largeview, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
 MODULE_PARM(decompression, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
-MODULE_PARM(upscaling, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(upscaling, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
 MODULE_PARM(force_palette, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
 MODULE_PARM(force_rgb, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
-MODULE_PARM(autobright, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
-MODULE_PARM(autoexp, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
-MODULE_PARM(lightfreq, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
-MODULE_PARM(bandingfilter, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
-MODULE_PARM(clockdiv, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
-MODULE_PARM(backlight, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
-MODULE_PARM(mirror, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
-MODULE_PARM(sensor_mono, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(autobright, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
+MODULE_PARM(autoexp, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
+MODULE_PARM(lightfreq, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(bandingfilter, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
+MODULE_PARM(clockdiv, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(backlight, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
+MODULE_PARM(mirror, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
+MODULE_PARM(monochrome, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "b");
 MODULE_PARM(brightness, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
 MODULE_PARM(hue, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
 MODULE_PARM(colour, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
@@ -125,7 +118,7 @@
 MODULE_PARM(whiteness, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
 #ifdef W9968CF_DEBUG
 MODULE_PARM(debug, "i");
-MODULE_PARM(specific_debug, "i");
+MODULE_PARM(specific_debug, "b");
 #endif
 
 MODULE_PARM_DESC(vppmod_load, 
@@ -163,7 +156,7 @@
                  "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")."
                  "\n");
 MODULE_PARM_DESC(max_buffers,
-                 "\n<n[,...]> Only for advanced users."
+                 "\n<n[,...]> For advanced users."
                  "\nSpecify the maximum number of video frame buffers"
                  "\nto allocate for each device, from 2 to "
                  __MODULE_STRING(W9968CF_MAX_BUFFERS)
@@ -206,7 +199,8 @@
                  "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING)
                  " for every device."
                  "\nIf 'w9968cf-vpp' is not loaded, this paramater is"
-                 " set to 0.");
+                 " set to 0."
+                 "\n");
 MODULE_PARM_DESC(decompression,
                  "\n<0|1|2[,...]> Software video decompression:"
                  "\n- 0 disables decompression (doesn't allow formats needing"
@@ -221,7 +215,8 @@
                  "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION)
                  " for every device."
                  "\nIf 'w9968cf-vpp' is not loaded, forcing decompression is "
-                 "\nnot allowed; in this case this paramater is set to 2.");
+                 "\nnot allowed; in this case this paramater is set to 2."
+                 "\n");
 MODULE_PARM_DESC(force_palette,
                  "\n<0"
                  "|" __MODULE_STRING(VIDEO_PALETTE_UYVY)
@@ -255,7 +250,8 @@
                  "\nInitial palette is "
                  __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"."
                  "\nIf 'w9968cf-vpp' is not loaded, this paramater is"
-                 " set to 9 (UYVY).");
+                 " set to 9 (UYVY)."
+                 "\n");
 MODULE_PARM_DESC(force_rgb, 
                  "\n<0|1[,...]> Read RGB video data instead of BGR:"
                  "\n 1 = use RGB component ordering."
@@ -314,10 +310,11 @@
                  "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR)
                  " for every device."
                  "\n");
-MODULE_PARM_DESC(sensor_mono,
-                 "\n<0|1[,...]> The OV CMOS sensor is monochrome:"
+MODULE_PARM_DESC(monochrome,
+                 "\n<0|1[,...]> Use OV CMOS sensor as monochrome sensor:"
                  "\n 0 = no, 1 = yes"
-                 "\nDefault value is "__MODULE_STRING(W9968CF_SENSOR_MONO)
+                 "\nNot all the sensors support monochrome color."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME)
                  " for every device."
                  "\n");
 MODULE_PARM_DESC(brightness, 
@@ -349,7 +346,7 @@
 #ifdef W9968CF_DEBUG
 MODULE_PARM_DESC(debug,
                  "\n<n> Debugging information level, from 0 to 6:"
-                 "\n0 = none (be cautious)"
+                 "\n0 = none (use carefully)"
                  "\n1 = critical errors"
                  "\n2 = significant informations"
                  "\n3 = configuration or general messages"
@@ -383,29 +380,23 @@
 static int w9968cf_release(struct inode*, struct file*);
 static ssize_t w9968cf_read(struct file*, char*, size_t, loff_t*);
 static int w9968cf_mmap(struct file*, struct vm_area_struct*);
-static int w9968cf_ioctl(struct inode*, struct file*,
-                         unsigned int, unsigned long);
-static int w9968cf_do_ioctl(struct w9968cf_device*, unsigned int, void*);
+static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long);
+static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int, void*);
 
-/* /proc interface */
 #if defined(CONFIG_VIDEO_PROC_FS)
+/* /proc interface */
 static void w9968cf_proc_create(void);
 static void w9968cf_proc_destroy(void);
 static void w9968cf_proc_create_dev(struct w9968cf_device*);
 static void w9968cf_proc_destroy_dev(struct w9968cf_device*);
 static int w9968cf_proc_read_global(char*, char**, off_t, int, int*, void*);
 static int w9968cf_proc_read_dev(char*, char**, off_t, int, int*, void*);
-#else
-static inline void w9968cf_proc_create(void) {}
-static inline void w9968cf_proc_destroy(void) {}
-static inline void w9968cf_proc_create_dev(struct w9968cf_device* cam) {}
-static inline void w9968cf_proc_destroy_dev(struct w9968cf_device* cam) {}
 #endif
 
 /* USB-specific */
-static void w9968cf_urb_complete(struct urb *urb);
 static int w9968cf_start_transfer(struct w9968cf_device*);
 static int w9968cf_stop_transfer(struct w9968cf_device*);
+static void w9968cf_urb_complete(struct urb *urb);
 static int w9968cf_write_reg(struct w9968cf_device*, u16 value, u16 index);
 static int w9968cf_read_reg(struct w9968cf_device*, u16 index);
 static int w9968cf_write_fsb(struct w9968cf_device*, u16* data);
@@ -413,7 +404,6 @@
 static int w9968cf_read_sb(struct w9968cf_device*);
 static int w9968cf_upload_quantizationtables(struct w9968cf_device*);
 
-
 /* Low-level I2C (SMBus) I/O */
 static int w9968cf_smbus_start(struct w9968cf_device*);
 static int w9968cf_smbus_stop(struct w9968cf_device*);
@@ -421,6 +411,7 @@
 static int w9968cf_smbus_read_byte(struct w9968cf_device*, u8* v);
 static int w9968cf_smbus_write_ack(struct w9968cf_device*);
 static int w9968cf_smbus_read_ack(struct w9968cf_device*);
+static int w9968cf_smbus_refresh_bus(struct w9968cf_device*);
 static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam,
                                       u16 address, u8* value);
 static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address, 
@@ -457,12 +448,11 @@
 static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val);
 static inline int w9968cf_sensor_cmd(struct w9968cf_device*, 
                                      unsigned int cmd, void *arg);
-static void w9968cf_sensor_configure(struct w9968cf_device*);
-static int w9968cf_sensor_change_settings(struct w9968cf_device*);
-static int w9968cf_sensor_get_picture(struct w9968cf_device*, 
-                                      struct video_picture*);
-static int w9968cf_sensor_set_picture(struct w9968cf_device*, 
-                                      struct video_picture pict);
+static int w9968cf_sensor_init(struct w9968cf_device*);
+static int w9968cf_sensor_update_settings(struct w9968cf_device*);
+static int w9968cf_sensor_get_picture(struct w9968cf_device*);
+static int w9968cf_sensor_update_picture(struct w9968cf_device*, 
+                                         struct video_picture pict);
 
 /* Other helper functions */
 static void w9968cf_configure_camera(struct w9968cf_device*,struct usb_device*,
@@ -608,8 +598,6 @@
  * Memory management functions                                              *
  ****************************************************************************/
 
-/* Shameless copy from bttv-driver.c */
-
 /* 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)
@@ -660,7 +648,6 @@
 	}
 	vfree(mem);
 }
-/* End of shameless copy */
 
 
 /*--------------------------------------------------------------------------
@@ -834,7 +821,7 @@
 	list_for_each(ptr, list) {
 		cam = list_entry(ptr, struct w9968cf_device, v4llist);
 		out += sprintf(out,"/dev/video%d       : %s\n", 
-		               cam->v4ldev.minor, symbolic(camlist, cam->id));
+		               cam->v4ldev->minor, symbolic(camlist, cam->id));
 	}
 
 	up(&w9968cf_devlist_sem);
@@ -865,21 +852,18 @@
 	int len;
 	char* out = page;
 
-	static struct video_picture pict; /* it has to be static */
-	static int rc = 0;
-
 	if (down_interruptible(&cam->procfs_sem))
 		return -ERESTARTSYS;
 
 	if (offset == 0)
-		rc = w9968cf_sensor_get_picture(cam, &pict);
+		w9968cf_sensor_get_picture(cam);
 
 	out += sprintf(out,"camera_model      : %s\n",
 	               symbolic(camlist, cam->id));
 	out += sprintf(out,"sensor_model      : %s\n",
 	               symbolic(senlist, cam->sensor));
 	out += sprintf(out,"sensor_monochrome : %s\n",
-	               YES_NO(cam->sensor_mono));
+	               YES_NO(cam->monochrome));
 	if (cam->users)
 		out += sprintf(out,"user_program      : %s\n",cam->command);
 	out += sprintf(out,"packet_size_bytes : %d\n", 
@@ -920,13 +904,11 @@
 	out += sprintf(out,"banding_filter    : %s\n",YES_NO(cam->bandfilt));
 	out += sprintf(out,"back_light        : %s\n",YES_NO(cam->backlight));
 	out += sprintf(out,"mirror            : %s\n",YES_NO(cam->mirror));
-	if (!rc) {
-		out += sprintf(out,"brightness        : %d\n",pict.brightness);
-		out += sprintf(out,"colour            : %d\n",pict.colour);
-		out += sprintf(out,"contrast          : %d\n",pict.contrast);
-		out += sprintf(out,"hue               : %d\n",pict.hue);
-		out += sprintf(out,"whiteness         : %d\n",pict.whiteness);
-	}
+	out += sprintf(out,"brightness        : %d\n",cam->picture.brightness);
+	out += sprintf(out,"colour            : %d\n",cam->picture.colour);
+	out += sprintf(out,"contrast          : %d\n",cam->picture.contrast);
+	out += sprintf(out,"hue               : %d\n",cam->picture.hue);
+	out += sprintf(out,"whiteness         : %d\n",cam->picture.whiteness);
 	out += sprintf(out,"hs_polarity       : %d\n",cam->hs_polarity);
 	out += sprintf(out,"vs_polarity       : %d\n",cam->vs_polarity);
 #ifdef W9968CF_DEBUG
@@ -954,34 +936,40 @@
 
 static void w9968cf_proc_create_dev(struct w9968cf_device* cam)
 {
-	char name[5];
+	char name[6];
 
 	if (!w9968cf_proc_entry)
 		return;
 
 	/* Create per-device readable entry */
-	sprintf(name, "dev%d", cam->v4ldev.minor);
-	cam->proc_dev = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, 
+	sprintf(name, "dev%d", cam->v4ldev->minor);
+	cam->proc_dev = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR,
 	                                       w9968cf_proc_entry,
 	                                       w9968cf_proc_read_dev,
 	                                       (void*)cam);
 	if (!cam->proc_dev)
 		return;
 	cam->proc_dev->owner = THIS_MODULE;
+
+	DBG(2, "Per-device entry /proc/video/w9968cf/dev%d created.",
+	    cam->v4ldev->minor)
 }
 
 
 static void w9968cf_proc_destroy_dev(struct w9968cf_device* cam)
 {
-	char name[5];
+	char name[6];
 
 	if (!cam->proc_dev)
 		return;
 
-	sprintf(name, "dev%d", cam->v4ldev.minor);
+	sprintf(name, "dev%d", cam->v4ldev->minor);
 
 	/* Destroy per-device entry */
 	remove_proc_entry(name, w9968cf_proc_entry);
+
+	DBG(2, "Per-device entry /proc/video/w9968cf/dev%d removed.",
+	    cam->v4ldev->minor)
 }
 
 
@@ -1010,7 +998,7 @@
 	else
 		DBG(2, "Unable to create /proc/video/w9968cf/global")
 
-	DBG(5, "/proc entries successfully created.")
+	DBG(2, "Main entry /proc/video/w9968cf/global created.")
 }
 
 
@@ -1024,7 +1012,7 @@
 
 	remove_proc_entry("w9968cf", video_proc_entry);
 
-	DBG(5, "/proc entries removed.")
+	DBG(2, "Main entry /proc/video/w9968cf/global removed.")
 }
 
 #endif /* CONFIG_VIDEO_PROC_FS */
@@ -1184,14 +1172,12 @@
 	for (i = 0; i < W9968CF_URBS; i++) {
 		urb = usb_alloc_urb(W9968CF_ISO_PACKETS);
 		cam->urb[i] = urb;
-
 		if (!urb) {
 			for (j = 0; j < i; j++)
 				usb_free_urb(cam->urb[j]);
 			DBG(1, "Couldn't allocate the URB structures.")
 			return -ENOMEM;
 		}
-
 		urb->dev = udev;
 		urb->context = (void*)cam;
 		urb->pipe = usb_rcvisocpipe(udev, 1);
@@ -1214,7 +1200,7 @@
 
 	t_size = (w*h*d)/16;
 
-	err = w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset  everything */
+	err = w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */
 	err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */
 
 	/* Transfer size */
@@ -1287,11 +1273,12 @@
 	spin_unlock_irqrestore(&cam->urb_lock, lock_flags);
 
 	for (i = W9968CF_URBS-1; i >= 0; i--)
-		if (cam->urb[i])
+		if (cam->urb[i]) {
 			if (!usb_unlink_urb(cam->urb[i])) {
 				usb_free_urb(cam->urb[i]);
 				cam->urb[i] = NULL;
 			}
+		}
 
 	if (cam->disconnected)
 		goto exit;
@@ -1347,8 +1334,7 @@
 
 	res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 1,
 	                      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-	                      0, index, (void*)buff,
-	                      2, W9968CF_USB_CTRL_TIMEOUT);
+	                      0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT);
 
 	if (res < 0)
 		DBG(4, "Failed to read a register "
@@ -1360,7 +1346,7 @@
 
 
 /*--------------------------------------------------------------------------
-  Write data to the fast serial bus registers.
+  Write 64-bit data to the fast serial bus registers.
   Return 0 on success, -1 otherwise.
   --------------------------------------------------------------------------*/
 static int w9968cf_write_fsb(struct w9968cf_device* cam, u16* data)
@@ -1373,8 +1359,7 @@
 
 	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
 	                      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-	                      value, 0x06, (void*)data, 6,
-	                      W9968CF_USB_CTRL_TIMEOUT);
+	                      value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT);
 
 	if (res < 0)
 		DBG(4, "Failed to write the FSB registers "
@@ -1536,6 +1521,22 @@
 }
 
 
+/* This is seems to refresh the communication through the serial bus */
+static int w9968cf_smbus_refresh_bus(struct w9968cf_device* cam)
+{
+	int err = 0, j;
+
+	for (j = 1; j <= 10; j++) {
+		err = w9968cf_write_reg(cam, 0x0020, 0x01);
+		err += w9968cf_write_reg(cam, 0x0000, 0x01);
+		if (err)
+			break;
+	}
+
+	return err;
+}
+
+
 /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
 static int 
 w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, 
@@ -1544,8 +1545,10 @@
 	u16* data = cam->data_buffer;
 	int err = 0;
 
-	 /* Enable SBUS outputs */
-	err += w9968cf_write_reg(cam, 0x0020, 0x01);
+	err += w9968cf_smbus_refresh_bus(cam);
+
+	/* Enable SBUS outputs */
+	err += w9968cf_write_sb(cam, 0x0020);
 
 	data[0] = 0x082f | ((address & 0x80) ? 0x1500 : 0x0);
 	data[0] |= (address & 0x40) ? 0x4000 : 0x0;
@@ -1589,7 +1592,7 @@
 	err += w9968cf_write_fsb(cam, data);
 
 	/* Disable SBUS outputs */
-	err += w9968cf_write_reg(cam, 0x0000, 0x01);
+	err += w9968cf_write_sb(cam, 0x0000);
 
 	if (!err)
 		DBG(5, "I2C write byte data done, addr.0x%04X, subaddr.0x%02X "
@@ -1626,7 +1629,7 @@
 	err += w9968cf_smbus_read_byte(cam, value);
 	err += w9968cf_smbus_write_ack(cam);
 	err += w9968cf_smbus_stop(cam);
- 
+
 	/* Serial data disable */
 	err += w9968cf_write_sb(cam, 0x0000);
 
@@ -1695,8 +1698,8 @@
                        int size, union i2c_smbus_data *data)
 {
 	struct w9968cf_device* cam = adapter->data;
-	u8 i, j;
-	int rc = 0, err = 0; 
+	u8 i;
+	int err = 0; 
 
 	switch (addr) {
 		case OV6xx0_SID:
@@ -1712,31 +1715,26 @@
 		addr <<= 1;
 
 		if (read_write == I2C_SMBUS_WRITE)
- 			rc = w9968cf_i2c_adap_write_byte(cam, addr, command);
+ 			err = w9968cf_i2c_adap_write_byte(cam, addr, command);
 		else if (read_write == I2C_SMBUS_READ) 
-			rc = w9968cf_i2c_adap_read_byte(cam,addr, &data->byte);
+			err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte);
 
 	} else if (size == I2C_SMBUS_BYTE_DATA) {
 		addr <<= 1;
 
 		if (read_write == I2C_SMBUS_WRITE)
- 			rc = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr,
+ 			err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr,
 			                                  command, data->byte);
 		else if (read_write == I2C_SMBUS_READ) {
 			for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) {
-				rc = w9968cf_i2c_adap_read_byte_data(cam, addr, 
+				err = w9968cf_i2c_adap_read_byte_data(cam,addr,
 				                         command, &data->byte);
-				if (rc < 0) {
-					/* Work around: this seems to wake up  
-					   the EEPROM from the stall state */
-					for (j = 0; j <= 10; j++) {
-					   err += w9968cf_write_sb(cam,0x0020);
-					   err += w9968cf_write_sb(cam,0x0000);
-					   if (err)
-					   	break;
+				if (err) {
+					if (w9968cf_smbus_refresh_bus(cam)) {
+						err = -EIO;
+						break;
 					}
-				}
-				else
+				} else
 					break;
 			}
 
@@ -1748,11 +1746,7 @@
 		return -EINVAL;
 	}
 
-	/* This works around a bug in the I2C core */
-	if (rc > 0)
-		rc = 0;
-
-	return rc;
+	return err;
 }
 
 
@@ -1768,41 +1762,22 @@
 {
 	struct w9968cf_device* cam = client->adapter->data;
 	const char* clientname = client->name;
-	int id = client->driver->id;
+	int id = client->driver->id, err = 0;
 
 	if (id == I2C_DRIVERID_OVCAMCHIP) {
-		int rc = 0;
-
 		cam->sensor_client = client;
-
-		rc = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE, 
-		                        &cam->sensor_mono);
-		if (rc < 0) {
-			DBG(1, "CMOS sensor initialization failed (rc=%d)",rc);
-			cam->sensor_client = NULL;
-			return rc;
-		}
-
-		if (w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE, 
-		                       &cam->sensor) < 0)
-			rc = -EIO;
-		else if (client->addr==OV7xx0_SID || client->addr==OV6xx0_SID)
-			w9968cf_sensor_configure(cam);
-		else
-			rc = -EINVAL;
-
-		if (rc < 0) {
+		err = w9968cf_sensor_init(cam);
+		if (err) {
 			cam->sensor_client = NULL;
-			cam->sensor = CC_UNKNOWN;
-			return rc;
+			return err;
 		}
-	} else	{
-		DBG(4, "Rejected client [%s] with [%s]", 
+	} else {
+		DBG(4, "Rejected client [%s] with driver [%s]", 
 		    clientname, client->driver->name)
-		return -1;
+		return -EINVAL;
 	}
 
-	DBG(2, "I2C attach client [%s] with [%s]",
+	DBG(5, "I2C attach client [%s] with driver [%s]",
 	    clientname, client->driver->name)
 
 	return 0;
@@ -1818,7 +1793,7 @@
 		cam->sensor_client = NULL;
 	}
 
-	DBG(2, "I2C detach [%s]", clientname)
+	DBG(5, "I2C detach client [%s]", clientname)
 
 	return 0;
 }
@@ -1846,7 +1821,7 @@
 
 static int w9968cf_i2c_init(struct w9968cf_device* cam)
 {
-	int rc = 0;
+	int err = 0;
 
 	static struct i2c_algorithm algo = {
 		.name =          "W996[87]CF algorithm",
@@ -1869,15 +1844,15 @@
 	strcpy(cam->i2c_adapter.name, "w9968cf");
 	cam->i2c_adapter.data = cam;
 
-	DBG(6, "Registering I2C bus with kernel...")
+	DBG(6, "Registering I2C adapter with kernel...")
 
-	rc = i2c_add_adapter(&cam->i2c_adapter);
-	if (rc)
-		DBG(5, "Failed to register the I2C bus.")
+	err = i2c_add_adapter(&cam->i2c_adapter);
+	if (err)
+		DBG(1, "Failed to register the I2C adapter.")
 	else
-		DBG(5, "I2C bus registered.")
+		DBG(5, "I2C adapter registered.")
 
-	return rc;
+	return err;
 }
 
 
@@ -1917,7 +1892,7 @@
   --------------------------------------------------------------------------*/
 static int w9968cf_init_chip(struct w9968cf_device* cam)
 {
-	int err = 0, rc = 0;
+	int err = 0;
 
 	err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */
 	err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* power on */
@@ -1952,22 +1927,11 @@
 	err += w9968cf_set_window(cam, cam->window);
 
 	if (err)
-		goto error;
-
-	rc = w9968cf_sensor_change_settings(cam);
-	if (rc)
-		goto error;
-
-	DBG(5, "Chip successfully initialized.");
-	
-	return 0;
-
-error:
-	DBG(1, "Chip initialization failed.")
-	if (err)
-		return err;
+		DBG(1, "Chip initialization failed.")
 	else
-		return rc;
+		DBG(5, "Chip successfully initialized.")
+
+	return err;
 }
 
 
@@ -1979,7 +1943,7 @@
 w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict)
 {
 	u16 fmt, hw_depth, hw_palette, reg_v = 0x0000;
-	int err = 0, rc = 0;
+	int err = 0;
 
 	/* Make sure we are using a valid depth */
 	pict.depth = w9968cf_valid_depth(pict.palette);
@@ -2040,12 +2004,10 @@
 	else if (cam->filter_type == 2)
 		reg_v |= 0x000c;
 
-	err = w9968cf_write_reg(cam, reg_v, 0x16);
-	if (err)
+	if ((err = w9968cf_write_reg(cam, reg_v, 0x16)))
 		goto error;
 
-	rc = w9968cf_sensor_set_picture(cam, pict);
-	if (rc)
+	if ((err = w9968cf_sensor_update_picture(cam, pict)))
 		goto error;
 
 	/* If all went well, update the device data structure */
@@ -2064,10 +2026,7 @@
 
 error:
 	DBG(1, "Failed to change picture settings.")
-	if (err)
-		return err;
-	else 
-		return rc;
+	return err;
 }
 
 
@@ -2082,7 +2041,7 @@
 	u16 x, y, w, h, scx, scy, cw, ch, ax, ay;
 	unsigned long fw, fh;
 	struct ovcamchip_window s_win;
-	int err=0, rc=0;
+	int err = 0;
 
 	/* Work around to avoid FP arithmetics */
 	#define __SC(x) ((x) << 10)
@@ -2126,8 +2085,8 @@
 		ch = h;
 	}
 
-	/* Setup the sensor window */
-	s_win.format = SENSOR_FORMAT;
+	/* Setup the window of the sensor */
+	s_win.format = VIDEO_PALETTE_UYVY;
 	s_win.width = cam->maxwidth;
 	s_win.height = cam->maxheight;
 	s_win.quarter = 0; /* full progressive video */
@@ -2156,7 +2115,7 @@
 				s_win.clockdiv = W9968CF_DEF_CLOCKDIVISOR;
 		}
 
-	/* We have to scale win.x and win.y offsets */	
+	/* We have to scale win.x and win.y offsets */
 	if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE))
 	     || (cam->vpp_flag & VPP_UPSCALE) ) {
 		ax = __SC(win.x)/fw;
@@ -2187,7 +2146,7 @@
 	y = ay + s_win.y;
 
 	/* Go ! */
-	if ((rc = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_MODE, &s_win)))
+	if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_MODE, &s_win)))
 		goto error;
 
 	err += w9968cf_write_reg(cam, scx + x, 0x10);
@@ -2232,10 +2191,7 @@
 
 error:
 	DBG(1, "Failed to change the capture area size.")
-	if (err)
-		return err;
-	else
-		return rc;
+	return err;
 }
 
 
@@ -2450,173 +2406,192 @@
 w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val)
 {
 	struct ovcamchip_control ctl;
-	int rc;
+	int err;
 
 	ctl.id = cid;
 	ctl.value = val;
 
-	rc = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_CTRL, &ctl);
+	err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_CTRL, &ctl);
 
-	return rc;
+	return err;
 }
 
+
 static int 
-w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int *val)
+w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val)
 {
 	struct ovcamchip_control ctl;
-	int rc;
+	int err;
 
 	ctl.id = cid;
 
-	rc = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_G_CTRL, &ctl);
-	if (rc >= 0)
+	err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_G_CTRL, &ctl);
+	if (!err)
 		*val = ctl.value;
 
-	return rc;
+	return err;
 }
 
 
 static inline int
-w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void *arg)
+w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg)
 {
 	struct i2c_client* c = cam->sensor_client;
+	int rc = 0;
 
-	DBG(6, "Executing CMOS sensor command...")
-
-	if (c && c->driver->command)
-		return c->driver->command(cam->sensor_client, cmd, arg);
-	else
+	if (c->driver->command) {
+		rc = c->driver->command(cam->sensor_client, cmd, arg);
+		/* The I2C driver returns -EPERM on non-supported controls */
+		return (rc < 0 && rc != -EPERM) ? rc : 0;
+	} else
 		return -ENODEV;
 }
 
 
 /*--------------------------------------------------------------------------
-  Change some settings of the CMOS sensor.
-  Returns: 0 for success, a negative number otherwise.
+  Update some settings of the CMOS sensor.
+  Returns: 0 on success, a negative number otherwise.
   --------------------------------------------------------------------------*/
-static int w9968cf_sensor_change_settings(struct w9968cf_device* cam)
+static int w9968cf_sensor_update_settings(struct w9968cf_device* cam)
 {
-	int rc;
+	int err = 0;
 
 	/* Auto brightness */
-	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT, 
-	                                cam->auto_brt);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT, 
+	                                 cam->auto_brt);
+	if (err)
+		return err;
 
 	/* Auto exposure */
-	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP, 
-	                                cam->auto_exp);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP, 
+	                                 cam->auto_exp);
+	if (err)
+		return err;
 
 	/* Banding filter */
-	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT, 
-	                                cam->bandfilt);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT, 
+	                                 cam->bandfilt);
+	if (err)
+		return err;
 
 	/* Light frequency */
-	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_FREQ,
-	                                cam->lightfreq);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_FREQ,
+	                                 cam->lightfreq);
+	if (err)
+		return err;
 
 	/* Back light */
-	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BACKLIGHT,
-	                                cam->backlight);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BACKLIGHT,
+	                                 cam->backlight);
+	if (err)
+		return err;
 
 	/* Mirror */
-	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_MIRROR,
-	                                cam->mirror);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_MIRROR,
+	                                 cam->mirror);
+	if (err)
+		return err;
 
 	return 0;
 }
 
 
 /*--------------------------------------------------------------------------
-  Get some current picture settings from the CMOS sensor.
-  Returns: 0 for success, a negative number otherwise.
+  Get some current picture settings from the CMOS sensor and update the
+  internal 'picture' structure of the camera.
+  Returns: 0 on success, a negative number otherwise.
   --------------------------------------------------------------------------*/
-static int
-w9968cf_sensor_get_picture(struct w9968cf_device* cam, 
-                           struct video_picture* pict)
+static int w9968cf_sensor_get_picture(struct w9968cf_device* cam)
 {
-	int rc, v;
+	int err, v;
 
-	/* Don't return error if a setting is unsupported, or rest of settings
-	   will not be performed */
+	err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_CONT, &v);
+	if (err)
+		return err;
+	cam->picture.contrast = v;
 
-	rc = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_CONT, &v);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
-	pict->contrast = v;
-
-	rc = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_BRIGHT, &v);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
-	pict->brightness = v;
-
-	rc = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_SAT, &v);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
-	pict->colour = v;
-
-	rc = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_HUE, &v);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
-	pict->hue = v;
+	err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_BRIGHT, &v);
+	if (err)
+		return err;
+	cam->picture.brightness = v;
 
-	pict->whiteness = W9968CF_WHITENESS; /* to do! */
+	err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_SAT, &v);
+	if (err)
+		return err;
+	cam->picture.colour = v;
+
+	err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_HUE, &v);
+	if (err)
+		return err;
+	cam->picture.hue = v;
 
 	DBG(5, "Got picture settings from the CMOS sensor.")
 
 	PDBGG("Brightness, contrast, hue, colour, whiteness are "
-	      "%d,%d,%d,%d,%d.", pict->brightness, pict->contrast,
-	      pict->hue, pict->colour, pict->whiteness)
+	      "%d,%d,%d,%d,%d.", cam->picture.brightness,cam->picture.contrast,
+	      cam->picture.hue, cam->picture.colour, cam->picture.whiteness)
 
 	return 0;
 }
 
 
 /*--------------------------------------------------------------------------
-  Change picture settings of the CMOS sensor.
-  Returns: 0 for success, a negative number otherwise.
+  Update picture settings of the CMOS sensor.
+  Returns: 0 on success, a negative number otherwise.
   --------------------------------------------------------------------------*/
 static int
-w9968cf_sensor_set_picture(struct w9968cf_device* cam, 
-                           struct video_picture pict)
+w9968cf_sensor_update_picture(struct w9968cf_device* cam, 
+                              struct video_picture pict)
 {
-	int rc;
-
-	rc = w9968cf_sensor_set_control(cam,OVCAMCHIP_CID_CONT, pict.contrast);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	int err = 0;
 
-	if (!cam->auto_brt) {
-		rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT, 
-	                                        pict.brightness);
-		if (SENSOR_FATAL_ERROR(rc))
-			return rc;
+	if ((!cam->sensor_initialized)
+	    || pict.contrast != cam->picture.contrast) {
+		err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_CONT,
+		                                 pict.contrast);
+		if (err)
+			goto fail;
+		DBG(4, "Contrast changed from %d to %d.",
+		    cam->picture.contrast, pict.contrast)
+		cam->picture.contrast = pict.contrast;
 	}
 
-	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT, pict.colour);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	if (((!cam->sensor_initialized) || 
+	    pict.brightness != cam->picture.brightness) && (!cam->auto_brt)) {
+		err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT, 
+		                                 pict.brightness);
+		if (err)
+			goto fail;
+		DBG(4, "Brightness changed from %d to %d.",
+		    cam->picture.brightness, pict.brightness)
+		cam->picture.brightness = pict.brightness;
+	}
 
-	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE, pict.hue);
-	if (SENSOR_FATAL_ERROR(rc))
-		return rc;
+	if ((!cam->sensor_initialized) || pict.colour != cam->picture.colour) {
+		err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT, 
+		                                 pict.colour);
+		if (err)
+			goto fail;
+		DBG(4, "Colour changed from %d to %d.",
+		    cam->picture.colour, pict.colour)
+		cam->picture.colour = pict.colour;
+	}
 
-	PDBGG("Brightness, contrast, hue, colour, whiteness are "
-	      "%d,%d,%d,%d,%d.", pict.brightness, pict.contrast,
-	      pict.hue, pict.colour, pict.whiteness)
+	if ((!cam->sensor_initialized) || pict.hue != cam->picture.hue) {
+		err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE, 
+		                                 pict.hue);
+		if (err)
+			goto fail;
+		DBG(4, "Hue changed from %d to %d.",
+		    cam->picture.hue, pict.hue)
+		cam->picture.hue = pict.hue;
+	}
 
 	return 0;
+
+fail:
+	DBG(4, "Failed to change sensor picture setting.")
+	return err;
 }
 
 
@@ -2626,12 +2601,22 @@
  ****************************************************************************/
 
 /*--------------------------------------------------------------------------
-  This function is called when the CMOS sensor is detected.
+  This function is called when a supported CMOS sensor is detected.
+  Return 0 if the initialization succeeds, a negative number otherwise.
   --------------------------------------------------------------------------*/
-static void w9968cf_sensor_configure(struct w9968cf_device* cam)
+static int w9968cf_sensor_init(struct w9968cf_device* cam)
 {
-	/* NOTE: Make sure width and height are a multiple of 16 */
+	int err = 0;
+
+	if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE, 
+	                              &cam->monochrome)))
+		goto error;
 
+	if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE, 
+	                              &cam->sensor)))
+		goto error;
+
+	/* NOTE: Make sure width and height are a multiple of 16 */
 	switch (cam->sensor_client->addr) {
 		case OV6xx0_SID:
 			cam->maxwidth = 352;
@@ -2645,6 +2630,10 @@
 			cam->minwidth = 64;
 			cam->minheight = 48;
 			break;
+		default:
+			DBG(1, "Not supported CMOS sensor detected for %s.",
+			    symbolic(camlist, cam->id))
+			return -EINVAL;
 	}
 
 	/* These values depend on the ones in the ovxxx0.c sources */
@@ -2663,7 +2652,24 @@
 			cam->hs_polarity = 0;
 	}
 
-	DBG(5, "CMOS sensor %s configured.", symbolic(senlist, cam->sensor))
+	if ((err = w9968cf_sensor_update_settings(cam)))
+		goto error;
+
+	if ((err = w9968cf_sensor_update_picture(cam, cam->picture)))
+		goto error;
+
+	cam->sensor_initialized = 1;
+
+	DBG(2, "%s CMOS sensor initialized.", symbolic(senlist, cam->sensor))
+	return 0;
+
+error:
+	cam->sensor_initialized = 0;
+	cam->sensor = CC_UNKNOWN;
+	DBG(1, "CMOS sensor initialization failed for %s (/dev/video%d). "
+	       "Try to detach and attach this device again.",
+	    symbolic(camlist, cam->id), cam->v4ldev->minor)
+	return err;
 }
 
 
@@ -2678,7 +2684,7 @@
                          enum w9968cf_model_id mod_id,
                          const unsigned short dev_nr)
 {
-#if defined(CONFIG_VIDEO_PROC_FS)
+#ifdef CONFIG_VIDEO_PROC_FS
 	init_MUTEX(&cam->procfs_sem);
 #endif
 	init_MUTEX(&cam->fileop_sem);
@@ -2691,13 +2697,7 @@
 	cam->usbdev = udev;
 	cam->id = mod_id;
 	cam->sensor = CC_UNKNOWN;
-
-	strcpy(cam->v4ldev.name, symbolic(camlist, mod_id));
-	cam->v4ldev.type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
-	cam->v4ldev.hardware = VID_HARDWARE_W9968CF;
-	cam->v4ldev.fops = &w9968cf_fops;
-	cam->v4ldev.priv = (void*)cam;
-	cam->v4ldev.minor = video_nr[dev_nr];
+	cam->sensor_initialized = 0;
 
 	/* Calculate the alternate setting number (from 1 to 16)
 	   according to the 'packet_size' module parameter */
@@ -2709,66 +2709,66 @@
 
 	cam->max_buffers = (max_buffers[dev_nr] < 2 || 
 	                    max_buffers[dev_nr] > W9968CF_MAX_BUFFERS)
-	                   ? W9968CF_BUFFERS : max_buffers[dev_nr];
+	                   ? W9968CF_BUFFERS : (u8)max_buffers[dev_nr];
 
 	cam->double_buffer = (double_buffer[dev_nr] == 0 || 
 	                      double_buffer[dev_nr] == 1)
-	                     ? double_buffer[dev_nr] : W9968CF_DOUBLE_BUFFER;
+	                     ? (u8)double_buffer[dev_nr]:W9968CF_DOUBLE_BUFFER;
 
 	cam->clamping = (clamping[dev_nr] == 0 || clamping[dev_nr] == 1)
-	                ? clamping[dev_nr] : W9968CF_CLAMPING;
+	                ? (u8)clamping[dev_nr] : W9968CF_CLAMPING;
 	
 	cam->filter_type = (filter_type[dev_nr] == 0 ||
 	                    filter_type[dev_nr] == 1 ||
 	                    filter_type[dev_nr] == 2)
-	                   ? filter_type[dev_nr] : W9968CF_FILTER_TYPE;
+	                   ? (u8)filter_type[dev_nr] : W9968CF_FILTER_TYPE;
 
 	cam->capture = 1;
 
 	cam->largeview = (largeview[dev_nr] == 0 || largeview[dev_nr] == 1)
-	                 ? largeview[dev_nr] : W9968CF_LARGEVIEW;
+	                 ? (u8)largeview[dev_nr] : W9968CF_LARGEVIEW;
 
 	cam->decompression = (decompression[dev_nr] == 0 || 
 	                      decompression[dev_nr] == 1 ||
 	                      decompression[dev_nr] == 2)
-	                     ? decompression[dev_nr] : W9968CF_DECOMPRESSION;
+	                     ? (u8)decompression[dev_nr]:W9968CF_DECOMPRESSION;
 
 	cam->upscaling = (upscaling[dev_nr] == 0 || 
 	                  upscaling[dev_nr] == 1)
-	                 ? upscaling[dev_nr] : W9968CF_UPSCALING;
+	                 ? (u8)upscaling[dev_nr] : W9968CF_UPSCALING;
 
 	cam->auto_brt = (autobright[dev_nr] == 0 || autobright[dev_nr] == 1)
-	                ? autobright[dev_nr] : W9968CF_AUTOBRIGHT;
+	                ? (u8)autobright[dev_nr] : W9968CF_AUTOBRIGHT;
 
 	cam->auto_exp = (autoexp[dev_nr] == 0 || autoexp[dev_nr] == 1)
-	                ? autoexp[dev_nr] : W9968CF_AUTOEXP;
+	                ? (u8)autoexp[dev_nr] : W9968CF_AUTOEXP;
 
 	cam->lightfreq = (lightfreq[dev_nr] == 50 || lightfreq[dev_nr] == 60)
-	                 ? lightfreq[dev_nr] : W9968CF_LIGHTFREQ;
+	                 ? (u8)lightfreq[dev_nr] : W9968CF_LIGHTFREQ;
 
 	cam->bandfilt = (bandingfilter[dev_nr] == 0 || 
 	                 bandingfilter[dev_nr] == 1)
-	                ? bandingfilter[dev_nr] : W9968CF_BANDINGFILTER;
+	                ? (u8)bandingfilter[dev_nr] : W9968CF_BANDINGFILTER;
 
 	cam->backlight = (backlight[dev_nr] == 0 || backlight[dev_nr] == 1)
-	                 ? backlight[dev_nr] : W9968CF_BACKLIGHT;
+	                 ? (u8)backlight[dev_nr] : W9968CF_BACKLIGHT;
 
 	cam->clockdiv = (clockdiv[dev_nr] == -1 || clockdiv[dev_nr] >= 0)
-	                ? clockdiv[dev_nr] : W9968CF_CLOCKDIV;
+	                ? (s8)clockdiv[dev_nr] : W9968CF_CLOCKDIV;
 
 	cam->mirror = (mirror[dev_nr] == 0 || mirror[dev_nr] == 1)
-	              ? mirror[dev_nr] : W9968CF_MIRROR;
+	              ? (u8)mirror[dev_nr] : W9968CF_MIRROR;
 
-	cam->sensor_mono = (sensor_mono[dev_nr]==0 || sensor_mono[dev_nr]==1)
-	                   ? sensor_mono[dev_nr] : W9968CF_SENSOR_MONO;
+	cam->monochrome = (monochrome[dev_nr] == 0 || monochrome[dev_nr] == 1)
+	                  ? monochrome[dev_nr] : W9968CF_MONOCHROME;
 
-	cam->picture.brightness = brightness[dev_nr];
-	cam->picture.hue = hue[dev_nr];
-	cam->picture.colour = colour[dev_nr];
-	cam->picture.contrast = contrast[dev_nr];
-	cam->picture.whiteness = whiteness[dev_nr];
-	if (w9968cf_valid_palette(force_palette[dev_nr])) {
-		cam->picture.palette = force_palette[dev_nr];
+	cam->picture.brightness = (u16)brightness[dev_nr];
+	cam->picture.hue = (u16)hue[dev_nr];
+	cam->picture.colour = (u16)colour[dev_nr];
+	cam->picture.contrast = (u16)contrast[dev_nr];
+	cam->picture.whiteness = (u16)whiteness[dev_nr];
+	if (w9968cf_valid_palette((u16)force_palette[dev_nr])) {
+		cam->picture.palette = (u16)force_palette[dev_nr];
 		cam->force_palette = 1;
 	} else {
 		cam->force_palette = 0;
@@ -2781,7 +2781,7 @@
 	}
 
 	cam->force_rgb = (force_rgb[dev_nr] == 0 || force_rgb[dev_nr] == 1)
-	                 ? force_rgb[dev_nr] : W9968CF_FORCE_RGB;
+	                 ? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB;
 
 	cam->window.x = 0;
 	cam->window.y = 0;
@@ -2886,7 +2886,7 @@
 	else
 		DBG(3, "- Clock divisor: %d", cam->clockdiv)
 
-	if (cam->sensor_mono)
+	if (cam->monochrome)
 		DBG(3, "- CMOS sensor used as monochrome.")
 	else
 		DBG(3, "- CMOS sensor not used as monochrome.")
@@ -2902,10 +2902,12 @@
 {
 	down(&w9968cf_devlist_sem);
 
-	DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev.minor)
+	DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor)
 
+#ifdef CONFIG_VIDEO_PROC_FS
 	w9968cf_proc_destroy_dev(cam);
-	video_unregister_device(&cam->v4ldev);
+#endif
+	video_unregister_device(cam->v4ldev);
 	list_del(&cam->v4llist);
 	i2c_del_adapter(&cam->i2c_adapter);
 	w9968cf_deallocate_memory(cam);
@@ -2925,24 +2927,25 @@
 
 static int w9968cf_open(struct inode* inode, struct file* filp)
 {
-	struct w9968cf_device* cam =
-	  (struct w9968cf_device*)video_devdata(filp)->priv;    
+	struct w9968cf_device* cam;
 	int err;
 
+	cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
+
 	down(&cam->dev_sem);
 
 	if (cam->sensor == CC_UNKNOWN) {
 		DBG(2, "No supported CMOS sensor has been detected by the "
 		       "'ovcamchip' module for the %s (/dev/video%d). Make "
 		       "sure it is loaded *before* the 'w9968cf' module.", 
-		    symbolic(camlist, cam->id),cam->v4ldev.minor)
+		    symbolic(camlist, cam->id), cam->v4ldev->minor)
 		up(&cam->dev_sem);
 		return -ENODEV;
 	}
 
 	if (cam->users) {
 		DBG(2, "%s (/dev/video%d) has been already occupied by '%s'.",
-		    symbolic(camlist, cam->id),cam->v4ldev.minor, cam->command)
+		    symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command)
 		if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) {
 			up(&cam->dev_sem);
 			return -EWOULDBLOCK;
@@ -2958,7 +2961,7 @@
 	}
 
 	DBG(5, "Opening the %s, /dev/video%d ...",
-	    symbolic(camlist, cam->id), cam->v4ldev.minor)
+	    symbolic(camlist, cam->id), cam->v4ldev->minor)
 
 	cam->streaming = 0;
 	cam->misconfigured = 0;
@@ -2975,7 +2978,7 @@
 	if ((err = w9968cf_start_transfer(cam)))
 		goto deallocate_memory;
 
-	filp->private_data = (void*)cam;
+	filp->private_data = cam;
 
 	cam->users++;
 	strcpy(cam->command, current->comm);
@@ -2997,8 +3000,9 @@
 
 static int w9968cf_release(struct inode* inode, struct file* filp)
 {
-	struct w9968cf_device* cam = 
-	  (struct w9968cf_device*)video_devdata(filp)->priv;
+	struct w9968cf_device* cam;
+
+	cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
 
 	down(&cam->dev_sem); /* prevent disconnect() to be called */
 
@@ -3026,11 +3030,12 @@
 static ssize_t
 w9968cf_read(struct file* filp, char* buf, size_t count, loff_t* f_pos)
 {
-	struct w9968cf_device* cam =
-	  (struct w9968cf_device*)video_devdata(filp)->priv;
+	struct w9968cf_device* cam;
 	struct w9968cf_frame_t* fr;
 	int err = 0;
 
+	cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
+
 	if (filp->f_flags & O_NONBLOCK)
 		return -EWOULDBLOCK;
 
@@ -3094,9 +3099,8 @@
 
 static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma)
 {
-	struct w9968cf_device* cam =
-	  (struct w9968cf_device*)video_devdata(filp)->priv;
-
+	struct w9968cf_device* cam = (struct w9968cf_device*)
+	                             video_get_drvdata(video_devdata(filp));
 	unsigned long vsize = vma->vm_end - vma->vm_start,
 	              psize = cam->nbuffers * w9968cf_get_max_bufsize(cam),
 	              start = vma->vm_start,
@@ -3136,10 +3140,11 @@
 w9968cf_ioctl(struct inode* inode, struct file* filp,
               unsigned int cmd, unsigned long arg)
 {
-	struct w9968cf_device* cam =
-	  (struct w9968cf_device*)video_devdata(filp)->priv;
+	struct w9968cf_device* cam;
 	int err;
 
+	cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
+
 	if (down_interruptible(&cam->fileop_sem))
 		return -ERESTARTSYS;
 
@@ -3155,7 +3160,7 @@
 		return -EIO;
 	}
 
-	err = w9968cf_do_ioctl(cam, cmd, (void*)arg);
+	err = w9968cf_v4l_ioctl(inode, filp, cmd, (void* )arg);
 
 	up(&cam->fileop_sem);
 	return err;
@@ -3163,8 +3168,10 @@
 
 
 static int 
-w9968cf_do_ioctl(struct w9968cf_device* cam, unsigned cmd, void* arg)
+w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
+                  unsigned int cmd, void* arg)
 {
+	struct w9968cf_device* cam;
 	const char* v4l1_ioctls[] = {
 		"?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", 
 		"GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF",
@@ -3176,7 +3183,9 @@
 
 	#define V4L1_IOCTL(cmd) \
 	        ((_IOC_NR((cmd)) < sizeof(v4l1_ioctls)/sizeof(char*)) ? \
-	        v4l1_ioctls[_IOC_NR((cmd))] : "???")
+	        v4l1_ioctls[_IOC_NR((cmd))] : "?")
+
+	cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
 
 	switch (cmd) {
 
@@ -3190,7 +3199,7 @@
 			.minheight = cam->minheight,
 		};
 		sprintf(cap.name, "W996[87]CF USB Camera #%d", 
-		        cam->v4ldev.minor);
+		        cam->v4ldev->minor);
 		cap.maxwidth = (cam->upscaling && w9968cf_vppmod_present)
 		               ? W9968CF_MAX_WIDTH : cam->maxwidth;
 		cap.maxheight = (cam->upscaling && w9968cf_vppmod_present)
@@ -3241,15 +3250,10 @@
 
 	case VIDIOCGPICT: /* get image properties of the picture */
 	{
-		struct video_picture pict;
-
-		if (w9968cf_sensor_get_picture(cam, &pict))
+		if (w9968cf_sensor_get_picture(cam))
 			return -EIO;
 
-		pict.depth = cam->picture.depth;
-		pict.palette = cam->picture.palette;
-
-		if (copy_to_user(arg, &pict, sizeof(pict)))
+		if (copy_to_user(arg, &cam->picture, sizeof(cam->picture)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGPICT successfully called.")
@@ -3278,13 +3282,6 @@
 			return -EINVAL;
 		}
 
-		if (pict.depth != w9968cf_valid_depth(pict.palette)) {
-			DBG(4, "Depth %d bpp is not supported for %s palette. "
-			       "VIDIOCSPICT failed.", 
-			    pict.depth, symbolic(v4l1_plist, pict.palette))
-			return -EINVAL;
-		}
-
 		if (!cam->force_palette) {
 		   if (cam->decompression == 0) {
 		      if (w9968cf_need_decompression(pict.palette)) {
@@ -3303,9 +3300,15 @@
 		   }
 		}
 
-		if (pict.palette != cam->picture.palette ||
-		    pict.depth   != cam->picture.depth)
-		{
+		if (pict.depth != w9968cf_valid_depth(pict.palette)) {
+			DBG(4, "Requested depth %d bpp is not valid for %s "
+			       "palette: ignored and changed to %d bpp.", 
+			    pict.depth, symbolic(v4l1_plist, pict.palette),
+			    w9968cf_valid_depth(pict.palette))
+			pict.depth = w9968cf_valid_depth(pict.palette);
+		}
+
+		if (pict.palette != cam->picture.palette) {
 			if(*cam->requested_frame
 			   || cam->frame_current->queued) {
 				err = wait_event_interruptible
@@ -3328,15 +3331,9 @@
 			if (w9968cf_start_transfer(cam))
 				goto ioctl_fail;
 
-		} else if ( ((pict.brightness != cam->picture.brightness) &&
-		            (!cam->auto_brt)) ||
-		            pict.hue != cam->picture.hue ||
-		            pict.colour != cam->picture.colour ||
-		            pict.contrast != cam->picture.contrast ||
-		            pict.whiteness != cam->picture.whiteness ) {
-			if (w9968cf_sensor_set_picture(cam, pict))
-				return -EIO;
-		}
+		} else if (w9968cf_sensor_update_picture(cam, pict))
+			return -EIO;
+
 
 		DBG(5, "VIDIOCSPICT successfully called.")
 		return 0;
@@ -3368,7 +3365,6 @@
 		    win.y != cam->window.y ||
 		    win.width != cam->window.width ||
 		    win.height != cam->window.height) {
-
 			if(*cam->requested_frame
 			   || cam->frame_current->queued) {
 				err = wait_event_interruptible
@@ -3479,12 +3475,12 @@
 		   }
 		}
 
-		if (w9968cf_adjust_window_size(cam, (u16*)&mmap.width, 
-		                               (u16*)&mmap.height)) {
+		if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width, 
+		                                      (u16*)&mmap.height))) {
 			DBG(4, "Resolution not supported (%dx%d). "
 			       "VIDIOCMCAPTURE failed.",
 			    mmap.width, mmap.height)
-			return -EINVAL;
+			return err;
 		}
 
 		fr = &cam->frame[mmap.frame];
@@ -3599,7 +3595,7 @@
 	case VIDIOCGUNIT:/* report the unit numbers of the associated devices*/
 	{
 		struct video_unit unit = {
-			.video = cam->v4ldev.minor,
+			.video = cam->v4ldev->minor,
 			.vbi = VIDEO_NO_UNIT,
 			.radio = VIDEO_NO_UNIT,
 			.audio = VIDEO_NO_UNIT,
@@ -3767,14 +3763,6 @@
 		return NULL;
 	}
 
-	err = usb_set_configuration(udev, 1);
-	err += usb_set_interface(udev, 0, 0);
-
-	if (err) {
-		DBG(1, "Device configuration failed.")
-		return NULL;
-	}
-
 	cam = (struct w9968cf_device*)
 	          kmalloc(sizeof(struct w9968cf_device), GFP_KERNEL);
 
@@ -3806,10 +3794,24 @@
 	}
 	memset(cam->data_buffer, 0, 8);
 
-	/* Set some basic constants */
-	w9968cf_configure_camera(cam, udev, mod_id, dev_nr);
+	/* Register the V4L device */
+	cam->v4ldev = video_device_alloc();
+	if (!cam->v4ldev) {
+		DBG(1, "Could not allocate memory for a V4L structure.")
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	strcpy(cam->v4ldev->name, symbolic(camlist, mod_id));
+	cam->v4ldev->owner = THIS_MODULE;
+	cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
+	cam->v4ldev->hardware = VID_HARDWARE_W9968CF;
+	cam->v4ldev->fops = &w9968cf_fops;
+	cam->v4ldev->minor = video_nr[dev_nr];
+	cam->v4ldev->release = video_device_release;
+	video_set_drvdata(cam->v4ldev, cam);
 
-	err = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER,
+	err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
 	                            video_nr[dev_nr]);
 	if (err) {
 		DBG(1, "V4L device registration failed.")
@@ -3820,22 +3822,27 @@
 		goto fail;
 	}
 
-	DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev.minor)
+	DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->minor)
+
+	/* Set some basic constants */
+	w9968cf_configure_camera(cam, udev, mod_id, dev_nr);
 
 	/* Ok, add a new entry into the list of V4L registered devices */
 	down(&w9968cf_devlist_sem);
 	list_add(&cam->v4llist, &w9968cf_dev_list);
 	up(&w9968cf_devlist_sem);
-
 	dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0;
 
 	w9968cf_turn_on_led(cam);
 
 	w9968cf_i2c_init(cam);
 
+#ifdef CONFIG_VIDEO_PROC_FS
 	w9968cf_proc_create_dev(cam);
+#endif
 
 	up(&cam->dev_sem);
+
 	return (void*)cam;
 
 fail: /* Free unused memory */
@@ -3844,6 +3851,8 @@
 			kfree(cam->control_buffer);
 		if (cam->data_buffer)
 			kfree(cam->data_buffer);
+		if (cam->v4ldev)
+			video_device_release(cam->v4ldev);
 		up(&cam->dev_sem);
 		kfree(cam);
 	}
@@ -3851,7 +3860,8 @@
 }
 
 
-static void w9968cf_usb_disconnect(struct usb_device* udev, void* drv_context)
+static void
+w9968cf_usb_disconnect(struct usb_device* udev, void* drv_context)
 {
 	struct w9968cf_device* cam = (struct w9968cf_device*)drv_context;
 
@@ -3871,7 +3881,7 @@
 			DBG(2, "The device is open (/dev/video%d)! "
 			       "Process name: %s. Deregistration and memory "
 			       "deallocation are deferred on close.",
-			    cam->v4ldev.minor, cam->command)
+			    cam->v4ldev->minor, cam->command)
 
 			cam->misconfigured = 1;
 
@@ -3956,14 +3966,18 @@
 
 	init_MUTEX(&w9968cf_devlist_sem);
 
+#ifdef CONFIG_VIDEO_PROC_FS
 	w9968cf_proc_create();
+#endif
 
 	w9968cf_vppmod_detect();
 
 	if ((err = usb_register(&w9968cf_usb_driver))) {
 		if (w9968cf_vppmod_present)
 			w9968cf_vppmod_release();
+#ifdef CONFIG_VIDEO_PROC_FS
 		w9968cf_proc_destroy();
+#endif
 		return err;
 	}
 
@@ -3976,7 +3990,9 @@
 	/* w9968cf_usb_disconnect() will be called */
 	usb_deregister(&w9968cf_usb_driver);
 
+#ifdef CONFIG_VIDEO_PROC_FS
 	w9968cf_proc_destroy();	
+#endif
 
 	if (w9968cf_vppmod_present)
 		w9968cf_vppmod_release();
@@ -3987,3 +4003,5 @@
 
 module_init(w9968cf_module_init);
 module_exit(w9968cf_module_exit);
+
+EXPORT_NO_SYMBOLS;
diff -Nru a/drivers/usb/w9968cf.h b/drivers/usb/w9968cf.h
--- a/drivers/usb/w9968cf.h	Fri Dec 12 15:05:19 2003
+++ b/drivers/usb/w9968cf.h	Fri Dec 12 15:05:19 2003
@@ -1,7 +1,7 @@
 /***************************************************************************
  * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip.       *
  *                                                                         *
- * Copyright (C) 2002 2003 by Luca Risolia <luca_ing@libero.it>            *
+ * Copyright (C) 2002 2003 by Luca Risolia <luca.risolia@studio.unibo.it>  *
  *                                                                         *
  * 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    *
@@ -24,11 +24,14 @@
 #include <linux/videodev.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
-#include <linux/proc_fs.h>
+#ifdef CONFIG_VIDEO_PROC_FS
+#	include <linux/proc_fs.h>
+#endif
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/wait.h>
 #include <linux/config.h>
+#include <linux/param.h>
 #include <asm/semaphore.h>
 #include <asm/types.h>
 
@@ -106,7 +109,7 @@
 #define W9968CF_LARGEVIEW      1 /* 0 disable, 1 enable */
 #define W9968CF_UPSCALING      0 /* 0 disable, 1 enable */
 
-#define W9968CF_SENSOR_MONO    0 /* 0 not monochrome, 1 monochrome sensor */
+#define W9968CF_MONOCHROME     0 /* 0 not monochrome, 1 monochrome sensor */
 #define W9968CF_BRIGHTNESS     31000 /* from 0 to 65535 */
 #define W9968CF_HUE            32768 /* from 0 to 65535 */
 #define W9968CF_COLOUR         32768 /* from 0 to 65535 */
@@ -130,9 +133,10 @@
 
 #define W9968CF_MODULE_NAME     "V4L driver for W996[87]CF JPEG USB " \
                                 "Dual Mode Camera Chip"
-#define W9968CF_MODULE_VERSION  "v1.22"
+#define W9968CF_MODULE_VERSION  "v1.24-basic"
 #define W9968CF_MODULE_AUTHOR   "(C) 2002 2003 Luca Risolia"
-#define W9968CF_AUTHOR_EMAIL    "<luca_ing@libero.it>"
+#define W9968CF_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
+#define W9968CF_MODULE_LICENSE  "GPL"
 
 static u8 w9968cf_vppmod_present; /* status flag: yes=1, no=0 */
 
@@ -172,6 +176,7 @@
 };
 
 struct w9968cf_frame_t {
+	#define W9968CF_HW_BUF_SIZE 640*480*2 /* buf.size of original frames */
 	void* buffer;
 	u32 length;
 	enum w9968cf_frame_status status;
@@ -195,8 +200,8 @@
 struct w9968cf_device {
 	enum w9968cf_model_id id;   /* private device identifier */
 
-	struct video_device v4ldev; /* V4L structure */
-	struct list_head v4llist;   /* entry of the list of V4L cameras */
+	struct video_device* v4ldev; /* -> V4L structure */
+	struct list_head v4llist;    /* entry of the list of V4L cameras */
 
 	struct usb_device* usbdev;           /* -> main USB structure */
 	struct urb* urb[W9968CF_URBS];       /* -> USB request block structs */
@@ -208,9 +213,9 @@
 	struct w9968cf_frame_t frame_tmp;  /* temporary frame */
 	struct w9968cf_frame_t* frame_current; /* -> frame being grabbed */
 	struct w9968cf_frame_t* requested_frame[W9968CF_MAX_BUFFERS];
-	void* vpp_buffer; /* -> helper buffer for post-processing routines */
+	void* vpp_buffer; /*-> helper buf.for video post-processing routines */
 
-	u8 max_buffers,   /* number of requested buffers */	   
+	u8 max_buffers,   /* number of requested buffers */
 	   force_palette, /* yes=1/no=0 */
 	   force_rgb,     /* read RGB instead of BGR, yes=1, no=0 */
 	   double_buffer, /* hardware double buffering yes=1/no=0 */
@@ -221,15 +226,17 @@
 	   decompression, /* 0=disabled, 1=forced, 2=allowed */
 	   upscaling;     /* software image scaling, 0=enabled, 1=disabled */
 
-	struct video_picture picture; /* current window settings */
-	struct video_window window;   /* current picture settings */
+	struct video_picture picture; /* current picture settings */
+	struct video_window window;   /* current window settings */
 
 	u16 hw_depth,    /* depth (used by the chip) */
 	    hw_palette,  /* palette (used by the chip) */
 	    hw_width,    /* width (used by the chip) */
 	    hw_height,   /* height (used by the chip) */
 	    hs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */
-	    vs_polarity; /* 0=negative sync pulse, 1=positive sync pulse */
+	    vs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */
+	    start_cropx, /* pixels from HS inactive edge to 1st cropped pixel*/
+	    start_cropy; /* pixels from VS incative edge to 1st cropped pixel*/
 
 	enum w9968cf_vpp_flag vpp_flag; /* post-processing routines in use */
 
@@ -240,16 +247,15 @@
 	   users,         /* flag: number of users holding the device */
 	   streaming;     /* flag: yes=1, no=0 */
 
-	int sensor; /* type of image CMOS sensor chip (CC_*) */
-
-	/* Determined by CMOS sensor type */
-	u16 maxwidth,
-	    maxheight,
-	    minwidth,
-	    minheight,
-	    start_cropx,
-	    start_cropy;
+	u8 sensor_initialized; /* flag: yes=1, no=0 */
 
+	/* Determined by CMOS sensor type: */
+	int sensor,       /* type of image sensor chip (CC_*) */
+	    monochrome;   /* CMOS sensor is (probably) monochrome */
+	u16 maxwidth,     /* maximum width supported by the CMOS sensor */
+	    maxheight,    /* maximum height supported by the CMOS sensor */
+	    minwidth,     /* minimum width supported by the CMOS sensor */
+	    minheight;    /* minimum height supported by the CMOS sensor */
 	u8  auto_brt,     /* auto brightness enabled flag */
 	    auto_exp,     /* auto exposure enabled flag */
 	    backlight,    /* backlight exposure algorithm flag */
@@ -257,21 +263,20 @@
 	    lightfreq,    /* power (lighting) frequency */
 	    bandfilt;     /* banding filter enabled flag */
 	s8  clockdiv;     /* clock divisor */
-	int sensor_mono;  /* CMOS sensor is (probably) monochrome */
 
 	/* I2C interface to kernel */
 	struct i2c_adapter i2c_adapter;
 	struct i2c_client* sensor_client;
 
-#if defined(CONFIG_VIDEO_PROC_FS)
+#ifdef CONFIG_VIDEO_PROC_FS
 	/* /proc entries, relative to /proc/video/w9968cf/ */
-	struct proc_dir_entry *proc_dev;   /* readable per-device entry */
+	struct proc_dir_entry *proc_dev;   /* rw per-device entry */
 #endif
 
 	/* Locks */
 	struct semaphore dev_sem,    /* for probe, disconnect,open and close */
 	                 fileop_sem; /* for read and ioctl */
-#if defined(CONFIG_VIDEO_PROC_FS)
+#ifdef CONFIG_VIDEO_PROC_FS
 	struct semaphore procfs_sem; /* for /proc read/write calls */
 #endif
 	spinlock_t urb_lock,   /* for submit_urb() and unlink_urb() */
@@ -280,14 +285,9 @@
 	wait_queue_head_t open, wait_queue;
 };
 
-#define W9968CF_HW_BUF_SIZE 640*480*2 /* buf. size for original video frames */
-
-#define SENSOR_FORMAT          VIDEO_PALETTE_UYVY
-#define SENSOR_FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)
-
 
 /****************************************************************************
- * Macros and other constants                                               *
+ * Macros for debugging                                                     *
  ****************************************************************************/
 
 #undef DBG
@@ -303,7 +303,7 @@
 	else if ((level) == 4) \
 		warn(fmt, ## args); \
 	else if ((level) >= 5) \
-		info("[%s,%d] " fmt, \
+		info("[%s:%d] " fmt, \
 		     __PRETTY_FUNCTION__, __LINE__ , ## args); \
 } \
 }
@@ -314,7 +314,7 @@
 
 #undef PDBG
 #undef PDBGG
-#define PDBG(fmt, args...) info("[%s, %d] "fmt, \
+#define PDBG(fmt, args...) info("[%s:%d] "fmt, \
 	                        __PRETTY_FUNCTION__, __LINE__ , ## args);
 #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
 
diff -Nru a/drivers/usb/w9968cf_decoder.h b/drivers/usb/w9968cf_decoder.h
--- a/drivers/usb/w9968cf_decoder.h	Fri Dec 12 15:05:19 2003
+++ b/drivers/usb/w9968cf_decoder.h	Fri Dec 12 15:05:19 2003
@@ -1,7 +1,7 @@
 /***************************************************************************
  * Video decoder for the W996[87]CF driver for Linux.                      *
  *                                                                         *
- * Copyright (C) 2003 by Luca Risolia <luca_ing@libero.it>                 *
+ * Copyright (C) 2003 by Luca Risolia <luca.risolia@studio.unibo.it>       *
  *                                                                         *
  * 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    *
diff -Nru a/drivers/usb/w9968cf_externaldef.h b/drivers/usb/w9968cf_externaldef.h
--- a/drivers/usb/w9968cf_externaldef.h	Fri Dec 12 15:05:19 2003
+++ b/drivers/usb/w9968cf_externaldef.h	Fri Dec 12 15:05:19 2003
@@ -1,8 +1,9 @@
 /***************************************************************************
- * Various definitions for compatibility with external modules.            *
+ * Various definitions for compatibility with OVCAMCHIP external module.   *
  * This file is part of the W996[87]CF driver for Linux.                   *
  *                                                                         *
- * Copyright (C) 2002 2003 by Luca Risolia <luca_ing@libero.it>            *
+ * The definitions have been taken from the OVCAMCHIP module written by    *
+ * Mark McClelland.                                                        *
  *                                                                         *
  * 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    *
@@ -27,10 +28,8 @@
 #include <asm/ioctl.h>
 #include <asm/types.h>
 
-/* The following values have been copied from the "ovcamchip" module. */
-
 #ifndef I2C_DRIVERID_OVCAMCHIP
-#	define I2C_DRIVERID_OVCAMCHIP	0xf00f
+#	define I2C_DRIVERID_OVCAMCHIP 0xf00f
 #endif
 
 /* Controls */
@@ -77,10 +76,10 @@
 	int width;
 	int height;
 	int format;
-	int quarter;		/* Scale width and height down 2x */
+	int quarter;  /* Scale width and height down 2x */
 
 	/* This stuff will be removed eventually */
-	int clockdiv;		/* Clock divisor setting */
+	int clockdiv; /* Clock divisor setting */
 };
 
 /* Commands. 
