diff -Naur linux-2.4.0-test9-pre6-orig/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- linux-2.4.0-test9-pre6-orig/Documentation/usb/ov511.txt Sun Sep 24 01:19:27 2000 +++ linux/Documentation/usb/ov511.txt Sun Sep 24 01:20:34 2000 @@ -6,11 +6,10 @@ Homepage: http://alpha.dyndns.org/ov511 NEW IN THIS VERSION: - o Stability improvements - o Support for hue control - o 160x120 mostly working - o OV6620 color problems fixed - o More WebCam 3 detection improvements + o Experimental control file interface (disabled by default) + o Debug messages now are off by default + o Snapshot mode now works with mmap() + o Other trivial fixes INTRODUCTION: @@ -205,13 +204,12 @@ when your system is under heavy load. WORKING FEATURES: - o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, 320x240, and - 160x120 + o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, and 320x240 o RGB24, YUV420, YUV422, YUYV, and YUV422P color o Monochrome o Setting/getting of saturation, contrast, brightness, and hue (only some of them work the OV7620 and OV7620AE) - o proc status reporting + o /proc status reporting EXPERIMENTAL FEATURES: o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and @@ -219,6 +217,7 @@ o Snapshot mode (only works with some read() based apps; see below for more) o OV6620 sensor support o GBR422 parsing + o 160x120 TODO: o Fix the noise / grainy image problem. @@ -227,18 +226,16 @@ so we can't really work on that yet. Please kindly inform OmniVision that you would like them to release their specifications to the Linux community. o YUV422 - o Get snapshot mode working with mmap(). o Fix fixFrameRGBoffset(). It is not stable yet with streaming video. - o Get autoadjust disable working o V4L2 support (Probably not until it goes into the kernel) - o Creative WebCam III has problems initializing its sensor. This should be - fixed now, but if you still have problems let me know. o Get rid of the memory management functions (put them in videodev.c??) o Setting of contrast and brightness not working with 7620/7620AE o Driver/camera state save/restore for when USB supports suspend/resume o Unstable on SMP systems o OV7620/OV6620 experience frame corruption with moving objects o OV6620 is too dark + o 176x144 support + o Driver sometimes hangs upon close() with OHCI HOW TO CONTACT ME: diff -Naur linux-2.4.0-test9-pre6-orig/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- linux-2.4.0-test9-pre6-orig/drivers/usb/ov511.c Sun Sep 24 01:19:51 2000 +++ linux/drivers/usb/ov511.c Sun Sep 24 01:20:23 2000 @@ -30,7 +30,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static const char version[] = "1.25"; +static const char version[] = "1.26"; #define __NO_VERSION__ @@ -52,6 +52,7 @@ #include "ov511.h" #undef OV511_GBR422 /* Experimental -- sets the 7610 to GBR422 */ +#undef OV511_CONTROL_API /* Experimental -- IOCTL control API hack */ #define OV511_I2C_RETRIES 3 @@ -74,7 +75,7 @@ * 5=highly repetitive mesgs * NOTE: This should be changed to 0, 1, or 2 for production kernels */ -static int debug = 3; +static int debug = 0; /* Fix vertical misalignment of red and blue at 640x480 */ static int fix_rgb_offset = 0; @@ -357,6 +358,7 @@ ov511->bridge == BRG_OV511PLUS ? "OV511+" : "unknown"); out += sprintf (out, "sensor : %s\n", + ov511->sensor == SEN_OV6620 ? "OV6620" : ov511->sensor == SEN_OV7610 ? "OV7610" : ov511->sensor == SEN_OV7620 ? "OV7620" : ov511->sensor == SEN_OV7620AE ? "OV7620AE" : @@ -448,7 +450,6 @@ } #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ - /********************************************************************** * * Camera interface @@ -700,7 +701,7 @@ { int rc; - PDEBUG(3, "Reset: type=0x%X", reset_type); + PDEBUG(4, "Reset: type=0x%X", reset_type); rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type); rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0); @@ -829,14 +830,21 @@ } else if ((ov511->sensor == SEN_OV7620) || (ov511->sensor == SEN_OV7620AE)) { #if 0 - cur_con = ov511_i2c_read(dev, OV7610_REG_CNT); - cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT); - // DEBUG_CODE - PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT), - ov511_i2c_read(dev, OV7610_REG_BRT)); + int cur_sat, new_sat, tmp; - if (ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0) + cur_sat = ov511_i2c_read(dev, OV7610_REG_BLUE); + + tmp = (p->hue >> 8) - cur_sat; + new_sat = (tmp < 0) ? (-tmp) | 0x80 : tmp; + + PDEBUG(1, "cur=%d target=%d diff=%d", cur_sat, p->hue >> 8, tmp); + + if (ov511_i2c_write(dev, OV7610_REG_BLUE, new_sat) < 0) return -EIO; + + // DEBUG_CODE + PDEBUG(1, "hue=%d", ov511_i2c_read(dev, OV7610_REG_BLUE)); + #endif } @@ -1662,6 +1670,11 @@ /* Frame start */ PDEBUG(4, "Frame start, framenum = %d", ov511->curframe); +#if 0 + /* Make sure no previous data carries over; necessary + * for compression experimentation */ + memset(frame->data, 0, MAX_DATA_SIZE); +#endif output_offset = 0; /* Check to see if it's a snapshot frame */ @@ -2481,6 +2494,13 @@ goto redo; } case FRAME_DONE: + if (ov511->snap_enabled && !ov511->frame[frame].snapshot) { + int ret; + if ((ret = ov511_new_frame(ov511, frame)) < 0) + return ret; + goto redo; + } + ov511->frame[frame].grabstate = FRAME_UNUSED; /* Reset the hardware snapshot button */ @@ -2689,6 +2709,110 @@ initialize: ov511_init_done, }; +#ifdef OV511_CONTROL_API +/********************************************************************** + * + * Control File Interface + * + * NOTE: This API is definitely subject to change at this time. + * + * Q: Why are you using a device file instead of a proc file? + * A: 1. /proc is for status reporting and not general I/O. + * 2. The proc interface used here won't allow IOCTL. + * + * Q: Why are you using IOCTL instead of read/write? + * A: Passing data in ASCII is a pain (look at cpia's proc support) + * + * Q: Why don't you use the normal video device's IOCTL function? + * A: This would either require that the device be opened multiple + * times, or that every video app implement ov511-control. + * + * I admit this is a shitty hack. I should at elast add a new device + * type to V4L. Hopefully 2.5/V4L2 will obviate the need for this. - MM + * + **********************************************************************/ + +static int ov511_control_open(struct video_device *dev, int flags) +{ + struct usb_ov511 *ov511 = (struct usb_ov511 *)dev; + int err = 0; + + MOD_INC_USE_COUNT; + PDEBUG(4, ""); + down(&ov511->lock); + + err = -EBUSY; + if (ov511->user) + goto out; + + ov511->control_user++; + +out: + up(&ov511->lock); + + if (err) + MOD_DEC_USE_COUNT; + + return err; +} + +static void ov511_control_close(struct video_device *dev) +{ + struct usb_ov511 *ov511 = (struct usb_ov511 *)dev; + + PDEBUG(4, ""); + + down(&ov511->lock); + + ov511->control_user--; + + up(&ov511->lock); + + /* This is definitely broken (as well as the other close()) */ + if (!ov511->dev) { + video_unregister_device(&ov511->vdev); + kfree(ov511); + ov511 = NULL; + } + + MOD_DEC_USE_COUNT; +} + +static int ov511_control_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) +{ + struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev; + + PDEBUG(4, "IOCtl: 0x%X", cmd); + + if (!ov511->dev) + return -EIO; + + switch (cmd) { + /* The purpose of this is to let the control app make sure that it is + * talking to an ov511 (using the name string). All V4L apps that use + * extended IOCTLs should do that! */ + case VIDIOCGCAP: + { + int err; + err = ov511_ioctl(vdev, cmd, arg); + } + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static struct video_device ov511_control_template = { + name: "OV511 USB Camera (control)", + type: VID_TYPE_CAPTURE, + hardware: VID_HARDWARE_OV511, + open: ov511_control_open, + close: ov511_control_close, + ioctl: ov511_control_ioctl, +}; +#endif + /**************************************************************************** * * OV511/OV7610 configuration @@ -3057,11 +3181,22 @@ init_waitqueue_head(&ov511->wq); - if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) == -1) { + if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) < 0) { err("video_register_device failed"); return -EBUSY; } +#ifdef OV511_CONTROL_API + /* Create control device. Not a VTX; this is just an awful hack */ + memcpy(&ov511->cdev, &ov511_control_template, + sizeof(ov511_control_template)); + if (video_register_device(&ov511->cdev, VFL_TYPE_VTX) < 0) { + err("video_register_device failed for control device"); + video_unregister_device(&ov511->vdev); + return -EBUSY; + } +#endif + if (ov511_write_regvals(dev, aRegvalsInit)) goto error; if (ov511_write_regvals(dev, aRegvalsNorm511)) goto error; @@ -3131,6 +3266,9 @@ error: video_unregister_device(&ov511->vdev); +#ifdef OV511_CONTROL_API + video_unregister_device(&ov511->cdev); +#endif usb_driver_release_interface(&ov511_driver, &dev->actconfig->interface[ov511->iface]); @@ -3277,6 +3415,13 @@ video_unregister_device(&ov511->vdev); else PDEBUG(3, "Device open...deferring video_unregister_device"); + +#ifdef OV511_CONTROL_API + if (!ov511->control_user) + video_unregister_device(&ov511->cdev); + else + PDEBUG(3, "Control device open...deferring video_unregister_device"); +#endif for (n = 0; n < OV511_NUMFRAMES; n++) ov511->frame[n].grabstate = FRAME_ERROR; diff -Naur linux-2.4.0-test9-pre6-orig/drivers/usb/ov511.h linux/drivers/usb/ov511.h --- linux-2.4.0-test9-pre6-orig/drivers/usb/ov511.h Sun Sep 24 01:19:51 2000 +++ linux/drivers/usb/ov511.h Sun Sep 24 01:20:27 2000 @@ -281,6 +281,7 @@ struct usb_ov511 { struct video_device vdev; + struct video_device cdev; /* Control device */ /* Device structure */ struct usb_device *dev; @@ -301,6 +302,7 @@ struct semaphore lock; int user; /* user count for exclusive use */ + int control_user; /* user count for control device */ int streaming; /* Are we streaming Isochronous? */ int grabbing; /* Are we grabbing? */ @@ -339,7 +341,7 @@ struct proc_dir_entry *proc_entry; /* /proc/ov511/videoX */ /* Framebuffer/sbuf management */ - int buf_state; + int buf_state; /* Already 'atomic' by use of buf_lock */ struct semaphore buf_lock; struct timer_list buf_timer; };