This patch is against Logitech Quickcam Web driver. It adds support for Linux 2.2.x and an option to disable automatic exposure control (module parameter "adaptive"). To apply, tar xvfz quickcam-web-driver.tar.gz cd quickcam patch -s -p1 < /path/quickcam-web-driver.patch2 Author: tuukkat@ee.oulu.fi diff -PruN quickcam/hdcs.c quickcam-tt/hdcs.c --- quickcam/hdcs.c Sun Dec 9 21:35:35 2001 +++ quickcam-tt/hdcs.c Wed Jul 10 16:16:31 2002 @@ -195,10 +195,11 @@ } /* set_shutter */ -static int hdcs_set_shutter(struct usb_device *dev, int sval, int xval) +static int hdcs_set_shutter(struct usb_device *dev, unsigned int val) { struct quickcam_i2c i2cbuff; - +unsigned int sval = qcclip(1,0xfd,val>>8); +unsigned int xval = 0x100; usb_quickcam_i2c_new(&i2cbuff); usb_quickcam_i2c_add(&i2cbuff,control, 0); diff -PruN quickcam/helper.h quickcam-tt/helper.h --- quickcam/helper.h Sun Nov 4 14:49:36 2001 +++ quickcam-tt/helper.h Wed Jul 10 11:26:25 2002 @@ -3,6 +3,7 @@ #define qcmax(a,b) ((a)>(b)?(a):(b)) #define qcmin(a,b) ((a)<(b)?(a):(b)) +#define qcclip(min,max,a) qcmax((min),qcmin((max),(a))) #define qcabs(a) ((a)>0?(a):-(a)) #define qcboundscheck(x,low,high) \ diff -PruN quickcam/makefile quickcam-tt/makefile --- quickcam/makefile Wed Jan 23 16:01:23 2002 +++ quickcam-tt/makefile Wed Jul 10 11:27:11 2002 @@ -16,7 +16,7 @@ mod_quickcam.o: quickcam.o hdcs.o pb0100.o yuv.o vv6410.o memory.o ld -r -o mod_quickcam.o quickcam.o hdcs.o pb0100.o yuv.o vv6410.o memory.o -quickcam.o: quickcam.c quickcam.h pb0100.h hdcs.h vv6410.h memory.h +quickcam.o: quickcam.c quickcam.h pb0100.h hdcs.h vv6410.h memory.h helper.h .c.o: $(CC) $(MODULE_CFLAGS) -c $< diff -PruN quickcam/pb0100.c quickcam-tt/pb0100.c --- quickcam/pb0100.c Sat Nov 24 23:19:22 2001 +++ quickcam-tt/pb0100.c Wed Jul 10 16:16:48 2002 @@ -151,7 +151,7 @@ return(-1); } -static int pb0100_set_shutter(struct usb_device * dev, int sval, int xval) +static int pb0100_set_shutter(struct usb_device * dev, unsigned int val) { return(0); } diff -PruN quickcam/quickcam.c quickcam-tt/quickcam.c --- quickcam/quickcam.c Wed Jan 23 17:05:41 2002 +++ quickcam-tt/quickcam.c Wed Jul 10 16:20:18 2002 @@ -72,6 +72,7 @@ MODULE_PARM(interpolation, "i"); MODULE_PARM(mode, "i"); MODULE_PARM(keepexposure, "i"); +MODULE_PARM(adaptive, "i"); MODULE_PARM(tobgr, "i"); MODULE_PARM(rgain, "i"); MODULE_PARM(bgain, "i"); @@ -84,6 +85,7 @@ MODULE_PARM_DESC(interpolation, "Sets the interpolation mode (0-1)"); MODULE_PARM_DESC(mode, "Sets the speed (0-1)"); MODULE_PARM_DESC(keepexposure, "Keep gain settings across one open to another (0-1)"); +MODULE_PARM_DESC(adaptive, "Automatic adaptive brightness control (0-1)"); MODULE_PARM_DESC(tobgr, "Automatic RGB -> BGR conversion"); MODULE_PARM_DESC(rgain, "Initial value of red gain (0-255)"); MODULE_PARM_DESC(bgain, "Initial value of blue gain (0-255)"); @@ -100,6 +102,7 @@ static int debug = DEBUGLEVEL; static int keepexposure = 0; +static int adaptive = 1; /* Enabled by default */ static int tobgr = 0; static int interpolation = 0; /* 1 = bilinear interpolation */ @@ -338,9 +341,9 @@ char buff[1]; buff[0] = val; return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x04, - 0x40, - reg, 0, + 0x04, /* Request */ + 0x40, /* RequestType */ + reg, 0, /* Value, Index */ buff, 1, HZ); } @@ -429,10 +432,9 @@ { struct usb_device *dev = quickcam->dev; int gr, gb, gg; - - gr=qcmin(255,qcmax(1,(quickcam->gain*quickcam->red)>>7)); - gb=qcmin(255,qcmax(1,(quickcam->gain*quickcam->blue)>>7)); - gg=qcmin(255,qcmax(1,(quickcam->gain*quickcam->green)>>7)); + gr=qcclip(1,255,(quickcam->gain*quickcam->red)>>7); + gb=qcclip(1,255,(quickcam->gain*quickcam->blue)>>7); + gg=qcclip(1,255,(quickcam->gain*quickcam->green)>>7); if (debug&DEBUGDATA) { printk("usb_quickcam_set_gains: gain %d, red %d, blue %d, green %d\n", @@ -461,19 +463,19 @@ quickcam->val = val; if (qcabs(val-brightness)>5) quickcam->gain-=(val-brightness)/5; - quickcam->gain=qcmin(255,qcmax(1,quickcam->gain)); + quickcam->gain=qcclip(1,255,quickcam->gain); /* It seems that the less gain you have the better ... You have less noise */ - if (quickcam->gain<=2 && quickcam->shutter_val>2) + if (quickcam->gain<=2 && quickcam->shutter_val>512) { quickcam->gain+=2; - quickcam->shutter_val-=2; + quickcam->shutter_val-=512; } /* Instead of amplifying the signal, open the shutter to get more light ! */ - if (quickcam->gain>=200 && quickcam->shutter_val<254) + if (quickcam->gain>=200 && quickcam->shutter_val<65024) { quickcam->gain-=2; - quickcam->shutter_val+=2; + quickcam->shutter_val+=512; } if (debug&DEBUGDATA) { @@ -481,7 +483,7 @@ printk("usb_quickcam_set_exposure: gain %d shutter %d\n",quickcam->gain,quickcam->shutter_val); } if (os!=quickcam->shutter_val) - quickcam->sensor_ctrl.set_shutter(dev,quickcam->shutter_val,0x100); + quickcam->sensor_ctrl.set_shutter(dev,quickcam->shutter_val); if (og!=quickcam->gain) return usb_quickcam_set_gains(quickcam); return 0; @@ -808,7 +810,7 @@ * the frame is done, the exposure should * be set here (We are the waked-up process) */ - if (yy>=XH || (yy>=XH/2 && mode)) { + if (adaptive && (yy>=XH || (yy>=XH/2 && mode))) { if (quickcam->sensor_ctrl.mode==2) mid_value = mid_value/(yy/2); else @@ -1205,14 +1207,14 @@ if(!keepexposure) { quickcam->gain =10; } - quickcam->blue =qcmin(255,qcmax(2,bgain)); - quickcam->red =qcmin(255,qcmax(2,rgain)); - quickcam->green=qcmin(255,qcmax(2,ggain)); + quickcam->blue =qcclip(2,255,bgain); + quickcam->red =qcclip(2,255,rgain); + quickcam->green=qcclip(2,255,ggain); if (usb_quickcam_set_gains(quickcam)<0) { printk("set_gains sensor failed\n"); return(-1); } - if (quickcam->sensor_ctrl.set_shutter(quickcam->dev,quickcam->shutter_val,0x100)<0) { + if (quickcam->sensor_ctrl.set_shutter(quickcam->dev,quickcam->shutter_val)<0) { printk("set_shutter sensor failed\n"); return(-1); } @@ -1622,7 +1624,7 @@ quickcam->vpic.brightness = quickcam->brightness; quickcam->vpic.colour = quickcam->green<<8; - quickcam->vpic.contrast = quickcam->shutter_val<<8; + quickcam->vpic.contrast = quickcam->shutter_val; quickcam->vpic.hue = (quickcam->red - quickcam->blue + 0xff)<<7; if (copy_to_user(arg, &quickcam->vpic, sizeof(quickcam->vpic))) retval = -EFAULT; @@ -1640,21 +1642,25 @@ else { if(p.brightness != quickcam->vpic.brightness) { quickcam->vpic.brightness = p.brightness; - quickcam->brightness = qcmin(0xfd00,qcmax(0x100,quickcam->vpic.brightness)); + quickcam->brightness = qcclip(0x100,0xfd00,quickcam->vpic.brightness); + if (!adaptive) { + quickcam->gain = quickcam->vpic.brightness >> 8; + usb_quickcam_set_gains(quickcam); + } } if(p.contrast != quickcam->vpic.contrast) { quickcam->vpic.contrast = p.contrast; - quickcam->shutter_val = qcmin(0xfd,qcmax(1,quickcam->vpic.contrast>>8)); - quickcam->sensor_ctrl.set_shutter(quickcam->dev,quickcam->shutter_val,0x100); + quickcam->shutter_val = quickcam->vpic.contrast; + quickcam->sensor_ctrl.set_shutter(quickcam->dev,quickcam->shutter_val); } if(p.colour != quickcam->vpic.colour) { quickcam->vpic.colour = p.colour; - quickcam->green = qcmin(0xfd,qcmax(1,quickcam->vpic.colour>>8)); + quickcam->green = qcclip(1,0xfd,quickcam->vpic.colour>>8); usb_quickcam_set_gains(quickcam); } if(p.hue != quickcam->vpic.hue) { quickcam->vpic.hue = p.hue; - quickcam->red = qcmin(0xfd,qcmax(1,quickcam->vpic.hue>>8)); + quickcam->red = qcclip(1,0xfd,quickcam->vpic.hue>>8); quickcam->blue = 0xff-quickcam->red; usb_quickcam_set_gains(quickcam); } @@ -2253,7 +2259,9 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,255) if (dev->descriptor.idVendor != 0x046d) return NULL; - if (dev->descriptor.idProduct != 0x0840 && dev->descriptor.idProduct != 0x0870) + if (dev->descriptor.idProduct != 0x0840 && + dev->descriptor.idProduct != 0x0850 && + dev->descriptor.idProduct != 0x0870) return NULL; /* Checking vendor/product should be enough, but what the hell */ diff -PruN quickcam/quickcam.h quickcam-tt/quickcam.h --- quickcam/quickcam.h Mon Dec 31 12:14:15 2001 +++ quickcam-tt/quickcam.h Wed Jul 10 16:17:12 2002 @@ -6,7 +6,7 @@ #include #define _QUICKCAM_ISOPIPE 0x81 -#define SHUTTER_VAL 0x80 +#define SHUTTER_VAL 0x8000 #define EXPO_VAL 0xa0 #define RGAIN_DEF 0x80 #define BGAIN_DEF 0x80 @@ -93,7 +93,7 @@ int (*init) (struct usb_device * dev, int mode, int *rgain, int *bgain, int *ggain, struct sensorctrl *sensor_ctrl); - int (*set_shutter) (struct usb_device * dev, int sval, int xval); + int (*set_shutter) (struct usb_device * dev, unsigned int val); int (*set_gains) (struct usb_device * dev, int rgain, int bgain, int ggain); int (*set_window) (struct usb_device * dev, int x, int y, int w, int h, struct sensorctrl *sensor_ctrl); diff -PruN quickcam/vv6410.c quickcam-tt/vv6410.c --- quickcam/vv6410.c Wed Jan 23 17:24:38 2002 +++ quickcam-tt/vv6410.c Wed Jul 10 16:25:39 2002 @@ -348,17 +348,25 @@ return(-1); } -static int vv6410_set_shutter(struct usb_device *dev, int sval, int xval) +static int vv6410_set_shutter(struct usb_device *dev, unsigned int val) { +static const unsigned int linelength = 415; /* For CIF */ struct quickcam_i2c i2cbuff; +unsigned int fine; +unsigned int coarse; + val = (val*val >> 14) + val/4; + fine = val % linelength; + coarse = val / linelength; + if (coarse>=512) coarse = 512; - printk("vv6410_set_shutter %d\n",sval); + printk("vv6410_set_shutter %d (%i,%i)\n",val,coarse,fine); - usb_quickcam_i2c_new(&i2cbuff); - sval = sval * 2; - usb_quickcam_i2c_add(&i2cbuff,0x23,sval&255); - usb_quickcam_i2c_add(&i2cbuff,0x22,sval>>8); - return(usb_quickcam_i2c_send(dev,&i2cbuff,VV6410_ADDR)); + usb_quickcam_i2c_new(&i2cbuff); + usb_quickcam_i2c_add(&i2cbuff,0x20,fine >> 8); + usb_quickcam_i2c_add(&i2cbuff,0x21,fine & 0xff); + usb_quickcam_i2c_add(&i2cbuff,0x22,coarse >> 8); + usb_quickcam_i2c_add(&i2cbuff,0x23,coarse & 0xff); + return usb_quickcam_i2c_send(dev,&i2cbuff,VV6410_ADDR); } static int vv6410_set_gains(struct usb_device *dev, int rgain, int bgain, int ggain)