]> git.pld-linux.org Git - packages/kernel.git/commitdiff
Konica USB support
authorcieciwa <cieciwa@pld-linux.org>
Wed, 2 Oct 2002 06:47:04 +0000 (06:47 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    linux-2.4.19-pre8-konicawc.patch -> 1.1

linux-2.4.19-pre8-konicawc.patch [new file with mode: 0644]

diff --git a/linux-2.4.19-pre8-konicawc.patch b/linux-2.4.19-pre8-konicawc.patch
new file mode 100644 (file)
index 0000000..ed9cb32
--- /dev/null
@@ -0,0 +1,1441 @@
+diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/Documentation/Configure.help linux-2.4.19-pre8-konicawc/Documentation/Configure.help
+--- linux-2.4.19-pre8/Documentation/Configure.help     Sat May 11 01:02:03 2002
++++ linux-2.4.19-pre8-konicawc/Documentation/Configure.help    Sat May 11 01:19:34 2002
+@@ -13685,6 +13685,21 @@
+   The module will be called vicam.o. If you want to compile it as a
+   module, say M here and read <file:Documentation/modules.txt>.
++Konica based Webcam
++CONFIG_USB_KONICAWC
++  Say Y here if you want support for webcams based on a Konica
++  chipset. This is known to work with the Intel YC76 webcam.
++
++  This driver uses the Video For Linux API.  You must enable
++  (Y or M in config) Video For Linux (under Character Devices)
++  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).
++  The module will be called konicawc.o. If you want to compile it as
++  a module, say M here and read <file:Documentation/modules.txt>.
+ Pegasus/Pegasus II based USB-Ethernet device support
+ CONFIG_USB_PEGASUS
+diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/Config.in linux-2.4.19-pre8-konicawc/drivers/usb/Config.in
+--- linux-2.4.19-pre8/drivers/usb/Config.in    Sat May 11 01:02:11 2002
++++ linux-2.4.19-pre8-konicawc/drivers/usb/Config.in   Sat May 11 01:18:02 2002
+@@ -80,6 +80,7 @@
+       dep_tristate '  USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
+       dep_tristate '  D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
+       dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
++      dep_tristate '  USB Konica Webcam support' CONFIG_USB_KONICAWC $CONFIG_USB $CONFIG_VIDEO_DEV
+    fi
+    comment 'USB Network adaptors'
+diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/Makefile linux-2.4.19-pre8-konicawc/drivers/usb/Makefile
+--- linux-2.4.19-pre8/drivers/usb/Makefile     Sat May 11 01:02:11 2002
++++ linux-2.4.19-pre8-konicawc/drivers/usb/Makefile    Sat May 11 01:36:40 2002
+@@ -10,7 +10,7 @@
+ # Objects that export symbols.
+-export-objs           := hcd.o usb.o ov511.o pwc-uncompress.o
++export-objs           := hcd.o usb.o ov511.o pwc-uncompress.o usbvideo.o
+ # Multipart objects.
+@@ -71,6 +71,7 @@
+ obj-$(CONFIG_USB_AUDIO)               += audio.o
+ obj-$(CONFIG_USB_EMI26)               += emi26.o
+ obj-$(CONFIG_USB_IBMCAM)      += ibmcam.o usbvideo.o ultracam.o
++obj-$(CONFIG_USB_KONICAWC)    += konicawc.o usbvideo.o
+ obj-$(CONFIG_USB_PWC)         += pwc.o
+ obj-$(CONFIG_USB_DC2XX)               += dc2xx.o
+ obj-$(CONFIG_USB_MDC800)      += mdc800.o
+diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/ibmcam.c linux-2.4.19-pre8-konicawc/drivers/usb/ibmcam.c
+--- linux-2.4.19-pre8/drivers/usb/ibmcam.c     Sat May 11 01:02:11 2002
++++ linux-2.4.19-pre8-konicawc/drivers/usb/ibmcam.c    Sat May 11 01:34:30 2002
+@@ -3899,6 +3899,17 @@
+       return uvd;
+ }
++
++static struct usb_device_id id_table[] = {
++      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },        /* Model 1 */
++      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },        /* Model 2 */
++      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },        /* Model 3 */
++      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },        /* Model 4 */
++      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },      /* Model 2 */
++      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },      /* Model 4 */
++      { }  /* Terminating entry */
++};
++
+ /*
+  * ibmcam_init()
+  *
+@@ -3926,7 +3937,8 @@
+               sizeof(ibmcam_t),
+               "ibmcam",
+               &cbTbl,
+-              THIS_MODULE);
++              THIS_MODULE,
++              id_table);
+ }
+ static void __exit ibmcam_cleanup(void)
+@@ -3934,15 +3946,6 @@
+       usbvideo_Deregister(&cams);
+ }
+-static __devinitdata struct usb_device_id id_table[] = {
+-      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },        /* Model 1 */
+-      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },        /* Model 2 */
+-      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },        /* Model 3 */
+-      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },        /* Model 4 */
+-      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },      /* Model 2 */
+-      { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },      /* Model 4 */
+-      { }  /* Terminating entry */
+-};
+ MODULE_DEVICE_TABLE(usb, id_table);
+ module_init(ibmcam_init);
+diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/konicawc.c linux-2.4.19-pre8-konicawc/drivers/usb/konicawc.c
+--- linux-2.4.19-pre8/drivers/usb/konicawc.c   Thu Jan  1 01:00:00 1970
++++ linux-2.4.19-pre8-konicawc/drivers/usb/konicawc.c  Sat May 11 03:18:42 2002
+@@ -0,0 +1,936 @@
++/*
++ * konicawc.c - konica webcam driver
++ *
++ * Author: Simon Evans <spse@secret.org.uk>
++ *
++ * Copyright (C) 2002 Simon Evans
++ *
++ * Licence: GPL
++ *
++ * Driver for USB webcams based on Konica chipset. This
++ * chipset is used in Intel YC76 camera.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++//#define DEBUG
++
++#include "usbvideo.h"
++
++#define MAX_BRIGHTNESS        108
++#define MAX_CONTRAST  108
++#define MAX_SATURATION        108
++#define MAX_SHARPNESS 108
++#define MAX_WHITEBAL  372
++#define MAX_SPEED     6
++
++
++#define MAX_CAMERAS   1
++
++#define DRIVER_VERSION        "v1.3"
++#define DRIVER_DESC   "Konica Webcam driver"
++
++enum ctrl_req {
++      SetWhitebal     = 0x01,
++      SetBrightness   = 0x02,
++        SetSharpness  = 0x03,
++      SetContrast     = 0x04,
++      SetSaturation   = 0x05,
++};
++
++
++enum frame_sizes {
++      SIZE_160X120    = 0,
++      SIZE_160X136    = 1,
++      SIZE_176X144    = 2,
++      SIZE_320X240    = 3,
++      
++};
++
++#define MAX_FRAME_SIZE        SIZE_320X240
++
++static usbvideo_t *cams;
++
++/* Some default values for inital camera settings,
++   can be set by modprobe */
++
++static int debug;
++static enum frame_sizes size; 
++static int speed = 6;         /* Speed (fps) 0 (slowest) to 6 (fastest) */
++static int brightness =       MAX_BRIGHTNESS/2;
++static int contrast = MAX_CONTRAST/2;
++static int saturation =       MAX_SATURATION/2;
++static int sharpness =        MAX_SHARPNESS/2;
++static int whitebal = 3*(MAX_WHITEBAL/4);
++
++static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
++
++/* These FPS speeds are from the windows config box. They are
++ * indexed on size (0-2) and speed (0-6). Divide by 3 to get the
++ * real fps.
++ */
++
++static int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
++                             { 24, 40, 48, 60, 72, 80, 100 },
++                             { 18, 30, 36, 45, 54, 60, 75  },
++                             { 6,  10, 12, 15, 18, 21, 25  } };
++
++struct cam_size {
++      u16     width;
++      u16     height;
++      u8      cmd;
++};
++
++static struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
++                                        { 160, 136, 0xa },
++                                        { 176, 144, 0x4 },
++                                        { 320, 240, 0x5 } };
++
++struct konicawc {
++      u8 brightness;          /* camera uses 0 - 9, x11 for real value */
++      u8 contrast;            /* as above */
++      u8 saturation;          /* as above */
++      u8 sharpness;           /* as above */
++      u8 white_bal;           /* 0 - 33, x11 for real value */
++      u8 speed;               /* Stored as 0 - 6, used as index in spd_to_* (above) */
++      u8 size;                /* Frame Size */
++      int height;
++      int width;
++      struct urb *sts_urb[USBVIDEO_NUMSBUF];
++      u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC];
++      struct urb *last_data_urb;
++      int lastframe;
++      int cur_frame_size;     /* number of bytes in current frame size */
++      int maxline;            /* number of lines per frame */
++      int yplanesz;           /* Number of bytes in the Y plane */
++      unsigned int skip_frame:2;
++      unsigned int buttonsts:1;
++};
++
++
++#define konicawc_set_misc(uvd, req, value, index)             konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0)
++#define konicawc_get_misc(uvd, req, value, index, buf, sz)    konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz)
++#define konicawc_set_value(uvd, value, index)                 konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0)
++
++
++static int konicawc_ctrl_msg(uvd_t *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
++{
++        int retval = usb_control_msg(uvd->dev,
++              dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),
++                  request, 0x40 | dir, value, index, buf, len, HZ);
++        return retval < 0 ? retval : 0;
++}
++
++
++static void konicawc_set_camera_size(uvd_t *uvd)
++{
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++
++      konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08);
++      cam->width = camera_sizes[cam->size].width;
++      cam->height = camera_sizes[cam->size].height;
++      cam->yplanesz = cam->height * cam->width;
++      cam->cur_frame_size = (cam->yplanesz * 3) / 2;
++      cam->maxline = cam->yplanesz / 256;
++      uvd->videosize = VIDEOSIZE(cam->width, cam->height);
++}
++
++
++static int konicawc_setup_on_open(uvd_t *uvd)
++{
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++
++      konicawc_set_misc(uvd, 0x2, 0, 0x0b);
++      dbg("setting brightness to %d (%d)", cam->brightness,
++          cam->brightness * 11);
++      konicawc_set_value(uvd, cam->brightness, SetBrightness);
++      dbg("setting white balance to %d (%d)", cam->white_bal,
++          cam->white_bal * 11);
++      konicawc_set_value(uvd, cam->white_bal, SetWhitebal);
++      dbg("setting contrast to %d (%d)", cam->contrast,
++          cam->contrast * 11);
++      konicawc_set_value(uvd, cam->contrast, SetContrast);
++      dbg("setting saturation to %d (%d)", cam->saturation,
++          cam->saturation * 11);
++      konicawc_set_value(uvd, cam->saturation, SetSaturation);
++      dbg("setting sharpness to %d (%d)", cam->sharpness,
++          cam->sharpness * 11);
++      konicawc_set_value(uvd, cam->sharpness, SetSharpness);
++      konicawc_set_camera_size(uvd);
++      konicawc_set_misc(uvd, 0x2, 1, 0x0b);
++      cam->lastframe = -1;
++      cam->skip_frame = 2;
++      cam->buttonsts = 0;
++      return 0;
++}
++
++
++static void konicawc_adjust_picture(uvd_t *uvd)
++{
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++
++      konicawc_set_misc(uvd, 0x2, 0, 0x0b);
++      dbg("new brightness: %d", uvd->vpic.brightness);
++      uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness;
++      if(cam->brightness != uvd->vpic.brightness / 11) {
++         cam->brightness = uvd->vpic.brightness / 11;
++         dbg("setting brightness to %d (%d)", cam->brightness,
++             cam->brightness * 11);
++         konicawc_set_value(uvd, cam->brightness, SetBrightness);
++      }
++
++      dbg("new contrast: %d", uvd->vpic.contrast);
++      uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast;
++      if(cam->contrast != uvd->vpic.contrast / 11) {
++              cam->contrast = uvd->vpic.contrast / 11;
++              dbg("setting contrast to %d (%d)", cam->contrast,
++                  cam->contrast * 11);
++              konicawc_set_value(uvd, cam->contrast, SetContrast);
++      }
++      konicawc_set_misc(uvd, 0x2, 1, 0x0b);
++}
++
++
++static int konicawc_compress_iso(uvd_t *uvd, struct urb *dataurb, struct urb *stsurb)
++{
++      char *cdata;
++      int i, totlen = 0;
++      unsigned char *status = stsurb->transfer_buffer;
++      int keep = 0, discard = 0, bad = 0;
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++
++      for (i = 0; i < dataurb->number_of_packets; i++) {
++              int button = cam->buttonsts;
++              unsigned char sts;
++              int n = dataurb->iso_frame_desc[i].actual_length;
++              int st = dataurb->iso_frame_desc[i].status;
++              cdata = dataurb->transfer_buffer +
++                      dataurb->iso_frame_desc[i].offset;
++
++              /* Detect and ignore errored packets */
++              if (st < 0) {
++                      if (debug >= 1)
++                              err("Data error: packet=%d. len=%d. status=%d.",
++                                  i, n, st);
++                      uvd->stats.iso_err_count++;
++                      continue;
++              }
++
++              /* Detect and ignore empty packets */
++              if (n <= 0) {
++                      uvd->stats.iso_skip_count++;
++                      continue;
++              }
++
++              /* See what the status data said about the packet */
++              sts = *(status+stsurb->iso_frame_desc[i].offset);
++
++              /* sts: 0x80-0xff: frame start with frame number (ie 0-7f)
++               * otherwise:
++               * bit 0 0: keep packet
++               *       1: drop packet (padding data)
++               *
++               * bit 4 0 button not clicked
++               *       1 button clicked
++               * button is used to `take a picture' (in software)
++               */
++
++              if(sts < 0x80) {
++                      button = sts & 0x40;
++                      sts &= ~0x40;
++              }
++              
++              /* work out the button status, but dont do
++                 anything with it for now */
++
++              if(button != cam->buttonsts) {
++                      dbg("button: %sclicked", button ? "" : "un");
++                      cam->buttonsts = button;
++              }
++
++              if(sts == 0x01) { /* drop frame */
++                      discard++;
++                      continue;
++              }
++              
++              if((sts > 0x01) && (sts < 0x80)) {
++                      info("unknown status %2.2x", sts);
++                      bad++;
++                      continue;
++              }
++
++              keep++;
++              if(sts & 0x80) { /* frame start */
++                      unsigned char marker[] = { 0, 0xff, 0, 0x00 };
++
++                      if(cam->skip_frame == 2) {
++                              cam->skip_frame--;
++                              continue;
++                      }
++                              
++                      /* Do we have enough space for this frame? */
++#if 0
++                      dbg("RingQueue: need %d have %d", cam->cur_frame_size + 4, RingQueue_GetFreeSpace(&uvd->dp));
++                      if(RingQueue_GetFreeSpace(&uvd->dp) < cam->cur_frame_size + 4) {
++                              info("Dropping frame");
++                              cam->skip_frame = 1;
++                              continue;
++                      } else {
++                              cam->skip_frame = 0;
++                      }
++#endif
++                      cam->skip_frame = 0;
++
++                      if(debug > 1)
++                              dbg("Adding Marker packet = %d, frame = %2.2x",
++                                  i, *(status+i));
++                      marker[3] = sts & 0x7F;
++                      if(RingQueue_GetFreeSpace(&uvd->dp) < (4+n)) {
++                              err("RingQueue Full! (cant add header) - Dropping frame");
++                              cam->skip_frame = 1;
++                      } else {
++                              RingQueue_Enqueue(&uvd->dp, marker, 4);
++                      }
++                              
++                      totlen += 4;
++              }
++              if(cam->skip_frame)
++                      continue;
++
++              totlen += n;    /* Little local accounting */
++              if(debug > 5)
++                      dbg("Adding packet %d, bytes = %d", i, n);
++              if(RingQueue_GetFreeSpace(&uvd->dp) < n) {
++                      err("RingQueue Full! (want %d got %d) - Dropping frame", n,
++                          RingQueue_GetFreeSpace(&uvd->dp));
++                      cam->skip_frame = 1;
++              } else {
++                      RingQueue_Enqueue(&uvd->dp, cdata, n);
++              }
++      }
++      if(debug > 8) {
++              dbg("finished: keep = %d discard = %d bad = %d added %d bytes",
++                  keep, discard, bad, totlen);
++      }
++      return totlen;
++}
++
++
++static void konicawc_isoc_irq(struct urb *urb)
++{
++      int i, len = 0;
++      uvd_t *uvd = urb->context;
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++
++      /* We don't want to do anything if we are about to be removed! */
++      if (!CAMERA_IS_OPERATIONAL(uvd))
++              return;
++
++      if(urb->status) {
++              if(urb->status == -EOVERFLOW) {
++                      dbg("isoc_irq: got babble");
++              } else if(urb->status == -ENOENT || urb->status == -EINPROGRESS) {
++                      dbg("isoc_irq: URB unlinked");
++              } else {
++                      dbg("isoc_irq: status %d", urb->status);
++              }
++              return;
++      }
++
++      if (urb->actual_length > 32) {
++              cam->last_data_urb = urb;
++              return;
++      }
++
++      if (!uvd->streaming) {
++              if (debug >= 1)
++                      info("Not streaming, but interrupt!");
++              return;
++      }
++
++      uvd->stats.urb_count++;
++      if (urb->actual_length <= 0)
++              goto urb_done_with;
++
++      /* Copy the data received into ring queue */
++      if(cam->last_data_urb) {
++              len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);
++              for (i = 0; i < FRAMES_PER_DESC; i++) {
++                      cam->last_data_urb->iso_frame_desc[i].status = 0;
++                      cam->last_data_urb->iso_frame_desc[i].actual_length = 0;
++              }
++              cam->last_data_urb = NULL;
++      }
++      uvd->stats.urb_length = len;
++      uvd->stats.data_count += len;
++
++      if(RingQueue_GetLength(&uvd->dp) >= 384)
++              RingQueue_WakeUpInterruptible(&uvd->dp);
++
++urb_done_with:
++
++      for (i = 0; i < FRAMES_PER_DESC; i++) {
++              urb->iso_frame_desc[i].status = 0;
++              urb->iso_frame_desc[i].actual_length = 0;
++      }
++      return;
++}
++
++
++static int konicawc_start_data(uvd_t *uvd)
++{
++      struct usb_device *dev = uvd->dev;
++      int i, errFlag;
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++      int pktsz;
++      struct usb_interface_descriptor *interface;
++
++      interface = &dev->actconfig->interface[uvd->iface].altsetting[spd_to_iface[cam->speed]];
++      pktsz = interface->endpoint[1].wMaxPacketSize;
++      dbg("pktsz = %d", pktsz);
++      if (!CAMERA_IS_OPERATIONAL(uvd)) {
++              err("Camera is not operational");
++              return -EFAULT;
++      }
++      uvd->curframe = -1;
++
++      /* Alternate interface 1 is is the biggest frame size */
++      i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
++      if (i < 0) {
++              err("usb_set_interface error");
++              uvd->last_error = i;
++              return -EBUSY;
++      }
++
++      /* We double buffer the Iso lists */
++      for (i=0; i < USBVIDEO_NUMSBUF; i++) {
++              int j, k;
++              struct urb *urb = uvd->sbuf[i].urb;
++              urb->dev = dev;
++              urb->context = uvd;
++              urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
++              urb->transfer_flags = USB_ISO_ASAP;
++              urb->transfer_buffer = uvd->sbuf[i].data;
++              urb->complete = konicawc_isoc_irq;
++              urb->number_of_packets = FRAMES_PER_DESC;
++              urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
++              for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
++                      urb->iso_frame_desc[j].offset = k;
++                      urb->iso_frame_desc[j].length = pktsz;
++              }
++
++              urb = cam->sts_urb[i];
++              urb->dev = dev;
++              urb->context = uvd;
++              urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);
++              urb->transfer_flags = USB_ISO_ASAP;
++              urb->transfer_buffer = cam->sts_buf[i];
++              urb->complete = konicawc_isoc_irq;
++              urb->number_of_packets = FRAMES_PER_DESC;
++              urb->transfer_buffer_length = FRAMES_PER_DESC;
++              for (j=0; j < FRAMES_PER_DESC; j++) {
++                      urb->iso_frame_desc[j].offset = j;
++                      urb->iso_frame_desc[j].length = 1;
++              }
++      }
++
++      cam->last_data_urb = NULL;
++      
++      /* Link URBs into a ring so that they invoke each other infinitely */
++      for (i=0; i < USBVIDEO_NUMSBUF; i++) {
++              if ((i+1) < USBVIDEO_NUMSBUF) {
++                      cam->sts_urb[i]->next = uvd->sbuf[i].urb;
++                      uvd->sbuf[i].urb->next = cam->sts_urb[i+1];
++              } else {
++                      cam->sts_urb[i]->next = uvd->sbuf[i].urb;
++                      uvd->sbuf[i].urb->next = cam->sts_urb[0];
++              }
++      }
++
++      /* Submit all URBs */
++      for (i=0; i < USBVIDEO_NUMSBUF; i++) {
++              errFlag = usb_submit_urb(uvd->sbuf[i].urb);
++              if (errFlag)
++                      err ("usb_submit_isoc(%d) ret %d", i, errFlag);
++
++              errFlag = usb_submit_urb(cam->sts_urb[i]);
++              if (errFlag)
++                      err("usb_submit_isoc(%d) ret %d", i, errFlag);
++      }
++
++      uvd->streaming = 1;
++      if (debug > 1)
++              dbg("streaming=1 video_endp=$%02x", uvd->video_endp);
++      return 0;
++}
++
++
++static void konicawc_stop_data(uvd_t *uvd)
++{
++      int i, j;
++      struct konicawc *cam;
++
++      if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
++              return;
++
++      cam = (struct konicawc *)uvd->user_data;
++      cam->last_data_urb = NULL;
++
++      /* Unschedule all of the iso td's */
++      for (i=0; i < USBVIDEO_NUMSBUF; i++) {
++              j = usb_unlink_urb(uvd->sbuf[i].urb);
++              if (j < 0)
++                      err("usb_unlink_urb() error %d.", j);
++
++              j = usb_unlink_urb(cam->sts_urb[i]);
++              if (j < 0)
++                      err("usb_unlink_urb() error %d.", j);
++      }
++
++      uvd->streaming = 0;
++
++      if (!uvd->remove_pending) {
++              /* Set packet size to 0 */
++              j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
++              if (j < 0) {
++                      err("usb_set_interface() error %d.", j);
++                      uvd->last_error = j;
++              }
++      }
++}
++
++
++static void konicawc_process_isoc(uvd_t *uvd, usbvideo_frame_t *frame)
++{     
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++      int maxline = cam->maxline;
++      int yplanesz = cam->yplanesz;
++
++      assert(frame != NULL);
++
++      if(debug > 5)
++              dbg("maxline = %d yplanesz = %d", maxline, yplanesz);
++      
++      if(debug > 3)
++              dbg("Frame state = %d", frame->scanstate);
++
++      if(frame->scanstate == ScanState_Scanning) {
++              int drop = 0;
++              int curframe;
++              int fdrops = 0;
++              if(debug > 3)
++                      dbg("Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp));
++              while(RingQueue_GetLength(&uvd->dp) >= 4) {
++                      if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
++                          (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
++                          (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
++                          (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) {
++                              curframe = RING_QUEUE_PEEK(&uvd->dp, 3);
++                              if(cam->lastframe != -1) {
++                                      fdrops = (0x80 + curframe - cam->lastframe) & 0x7F;
++                                      fdrops--;
++                                      if(fdrops) {
++                                              info("Dropped %d frames (%d -> %d)", fdrops,
++                                                   cam->lastframe, curframe);
++                                      }
++                              }
++                              cam->lastframe = curframe;
++                              frame->curline = 0;
++                              frame->scanstate = ScanState_Lines;
++                              RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
++                              break;
++                      }
++                      RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
++                      drop++;
++              }
++              if(drop)
++                      dbg("dropped %d bytes looking for new frame", drop);
++      }
++
++      if(frame->scanstate == ScanState_Scanning)
++              return;
++              
++      /* Try to move data from queue into frame buffer
++       * We get data in blocks of 384 bytes made up of:
++       * 256 Y, 64 U, 64 V.
++       * This needs to be written out as a Y plane, a U plane and a V plane.
++       */
++              
++      while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) {
++              /* Y */
++              RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256);
++              /* U */
++              RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64);
++              /* V */
++              RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64);
++              frame->seqRead_Length += 384;
++              frame->curline++;
++      }
++      /* See if we filled the frame */
++      if (frame->curline == maxline) {
++              if(debug > 5)
++                      dbg("got whole frame");
++
++              frame->frameState = FrameState_Done_Hold;
++              frame->curline = 0;
++              uvd->curframe = -1;
++              uvd->stats.frame_num++;
++      }
++}
++
++
++static int konicawc_find_fps(int size, int fps)
++{
++      int i;
++
++      fps *= 3;
++      dbg("konica_find_fps: size = %d fps = %d", size, fps);
++      if(fps <= spd_to_fps[size][0])
++              return 0;
++
++      if(fps >= spd_to_fps[size][MAX_SPEED])
++              return MAX_SPEED;
++
++      for(i = 0; i < MAX_SPEED; i++) {
++              if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) {
++                      dbg("fps %d between %d and %d", fps, i, i+1);
++                      if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps))
++                              return i;
++                      else
++                              return i+1;
++              }
++      }
++      return MAX_SPEED+1;
++}
++
++
++static int konicawc_set_video_mode(uvd_t *uvd, int x, int y, int fps)
++{
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++      int newspeed = cam->speed;
++      int newsize;
++
++      if(x > 0 && y > 0) {
++              if(debug >= 2)
++                      dbg("trying to find size %d,%d", x, y);
++              for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
++                      if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y))
++                              break;
++              }
++      } else {
++              newsize = cam->size;
++      }
++
++      if(newsize > MAX_FRAME_SIZE) {
++              dbg("couldnt find size %d,%d", x, y);
++              return -EINVAL;
++      }
++
++      if(fps > 0) {
++              dbg("trying to set fps to %d", fps);
++              newspeed = konicawc_find_fps(newsize, fps);
++              dbg("find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]);
++      }
++
++      if(newspeed > MAX_SPEED)
++              return -EINVAL;
++
++      dbg("setting size to %d speed to %d", newsize, newspeed);
++      if((newsize == cam->size) && (newspeed == cam->speed)) {
++              dbg("Nothing to do");
++              return 0;
++      }
++      info("setting to  %dx%d @ %d fps", camera_sizes[newsize].width,
++           camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3);
++
++      konicawc_stop_data(uvd);
++      konicawc_set_misc(uvd, 0x2, 0, 0x0b);
++      uvd->ifaceAltActive = spd_to_iface[newspeed];
++      dbg("new interface = %d", uvd->ifaceAltActive);
++      cam->speed = newspeed;
++
++      if(cam->size != newsize) {
++              cam->size = newsize;
++              konicawc_set_camera_size(uvd);
++      }
++
++      /* Flush the input queue and clear any current frame in progress */
++
++      RingQueue_Flush(&uvd->dp);
++      cam->skip_frame = 2;
++      cam->lastframe = -1;
++      if(uvd->curframe != -1) {
++        uvd->frame[uvd->curframe].curline = 0;
++        uvd->frame[uvd->curframe].seqRead_Length = 0;
++        uvd->frame[uvd->curframe].seqRead_Index = 0;
++      }
++
++      konicawc_set_misc(uvd, 0x2, 1, 0x0b);
++      konicawc_start_data(uvd);
++      return 0;
++}
++
++
++static int konicawc_calculate_fps(uvd_t *uvd)
++{
++      struct konicawc *cam = uvd->user_data;
++      return spd_to_fps[cam->size][cam->speed]/3;
++}
++
++
++static void konicawc_configure_video(uvd_t *uvd)
++{
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++      u8 buf[2];
++
++      memset(&uvd->vpic, 0, sizeof(uvd->vpic));
++      memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
++
++      RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS);
++      RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST);
++      RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION);
++      RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS);
++      RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL);
++
++      cam->brightness = brightness / 11;
++      cam->contrast = contrast / 11;
++      cam->saturation = saturation / 11;
++      cam->sharpness = sharpness / 11;
++      cam->white_bal = whitebal / 11;
++
++      uvd->vpic.colour = 108;
++      uvd->vpic.hue = 108;
++      uvd->vpic.brightness = brightness;
++      uvd->vpic.contrast = contrast;
++      uvd->vpic.whiteness = whitebal;
++      uvd->vpic.depth = 6;
++      uvd->vpic.palette = VIDEO_PALETTE_YUV420P;
++
++      memset(&uvd->vcap, 0, sizeof(uvd->vcap));
++      strcpy(uvd->vcap.name, "Konica Webcam");
++      uvd->vcap.type = VID_TYPE_CAPTURE;
++      uvd->vcap.channels = 1;
++      uvd->vcap.audios = 0;
++      uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;
++      uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;
++      uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;
++      uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;
++
++      memset(&uvd->vchan, 0, sizeof(uvd->vchan));
++      uvd->vchan.flags = 0 ;
++      uvd->vchan.tuners = 0;
++      uvd->vchan.channel = 0;
++      uvd->vchan.type = VIDEO_TYPE_CAMERA;
++      strcpy(uvd->vchan.name, "Camera");
++
++      /* Talk to device */
++      dbg("device init");
++      if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
++              dbg("3,10 -> %2.2x %2.2x", buf[0], buf[1]);
++      if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
++              dbg("3,10 -> %2.2x %2.2x", buf[0], buf[1]);
++      if(konicawc_set_misc(uvd, 0x2, 0, 0xd))
++              dbg("2,0,d failed");
++      dbg("setting initial values");
++}
++
++
++static void *konicawc_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *devid)
++{
++      uvd_t *uvd = NULL;
++      int i, nas;
++      int actInterface=-1, inactInterface=-1, maxPS=0;
++      unsigned char video_ep = 0;
++      
++      if (debug >= 1)
++              dbg("konicawc_probe(%p,%u.)", dev, ifnum);
++
++      /* We don't handle multi-config cameras */
++      if (dev->descriptor.bNumConfigurations != 1)
++              return NULL;
++
++      info("Konica Webcam (rev. 0x%04x)", dev->descriptor.bcdDevice);
++      RESTRICT_TO_RANGE(speed, 0, MAX_SPEED);
++
++      /* Validate found interface: must have one ISO endpoint */
++      nas = dev->actconfig->interface[ifnum].num_altsetting;
++      if (nas != 8) {
++              err("Incorrect number of alternate settings (%d) for this camera!", nas);
++              return NULL;
++      }
++      /* Validate all alternate settings */
++      for (i=0; i < nas; i++) {
++              const struct usb_interface_descriptor *interface;
++              const struct usb_endpoint_descriptor *endpoint;
++
++              interface = &dev->actconfig->interface[ifnum].altsetting[i];
++              if (interface->bNumEndpoints != 2) {
++                      err("Interface %d. has %u. endpoints!",
++                          ifnum, (unsigned)(interface->bNumEndpoints));
++                      return NULL;
++              }
++              endpoint = &interface->endpoint[1];
++              dbg("found endpoint: addr: 0x%2.2x maxps = 0x%4.4x",
++                  endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
++              if (video_ep == 0)
++                      video_ep = endpoint->bEndpointAddress;
++              else if (video_ep != endpoint->bEndpointAddress) {
++                      err("Alternate settings have different endpoint addresses!");
++                      return NULL;
++              }
++              if ((endpoint->bmAttributes & 0x03) != 0x01) {
++                      err("Interface %d. has non-ISO endpoint!", ifnum);
++                      return NULL;
++              }
++              if ((endpoint->bEndpointAddress & 0x80) == 0) {
++                      err("Interface %d. has ISO OUT endpoint!", ifnum);
++                      return NULL;
++              }
++              if (endpoint->wMaxPacketSize == 0) {
++                      if (inactInterface < 0)
++                              inactInterface = i;
++                      else {
++                              err("More than one inactive alt. setting!");
++                              return NULL;
++                      }
++              } else {
++                      if (i == spd_to_iface[speed]) {
++                              /* This one is the requested one */
++                              actInterface = i;
++                      }
++              }
++              if(endpoint->wMaxPacketSize > maxPS)
++                      maxPS = endpoint->wMaxPacketSize;
++      }
++      if(actInterface == -1) {
++              err("Cant find required endpoint");
++              return NULL;
++      }
++
++      dbg("Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS);
++
++      /* Code below may sleep, need to lock module while we are here */
++      MOD_INC_USE_COUNT;
++      uvd = usbvideo_AllocateDevice(cams);
++      if (uvd != NULL) {
++              struct konicawc *cam = (struct konicawc *)(uvd->user_data);
++              /* Here uvd is a fully allocated uvd_t object */
++              for(i = 0; i < USBVIDEO_NUMSBUF; i++) {
++                      cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC);
++                      if(cam->sts_urb[i] == NULL) {
++                              while(i--) {
++                                      usb_free_urb(cam->sts_urb[i]);
++                              }
++                              err("cant allocate urbs");
++                              return NULL;
++                      }
++              }
++              cam->speed = speed;
++              RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);
++              cam->width = camera_sizes[size].width;
++              cam->height = camera_sizes[size].height;
++              cam->size = size;
++
++              uvd->flags = 0;
++              uvd->debug = debug;
++              uvd->dev = dev;
++              uvd->iface = ifnum;
++              uvd->ifaceAltInactive = inactInterface;
++              uvd->ifaceAltActive = actInterface;
++              uvd->video_endp = video_ep;
++              uvd->iso_packet_len = maxPS;
++              uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P;
++              uvd->defaultPalette = VIDEO_PALETTE_YUV420P;
++              uvd->canvas = VIDEOSIZE(320, 240);
++              uvd->videosize = VIDEOSIZE(cam->width, cam->height);
++
++              /* Initialize konicawc specific data */
++              konicawc_configure_video(uvd);
++
++              i = usbvideo_RegisterVideoDevice(uvd);
++              uvd->max_frame_size = (320 * 240 * 3)/2;
++              if (i != 0) {
++                      err("usbvideo_RegisterVideoDevice() failed.");
++                      uvd = NULL;
++              }
++      }
++      MOD_DEC_USE_COUNT;
++      return uvd;
++}
++
++
++static void konicawc_free_uvd(uvd_t *uvd)
++{
++      int i;
++      struct konicawc *cam = (struct konicawc *)uvd->user_data;
++
++      for (i=0; i < USBVIDEO_NUMSBUF; i++) {
++              usb_free_urb(cam->sts_urb[i]);
++              cam->sts_urb[i] = NULL;
++      }
++}
++
++
++static struct usb_device_id id_table[] = {
++      { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */
++      { }  /* Terminating entry */
++};
++
++
++static int __init konicawc_init(void)
++{
++      usbvideo_cb_t cbTbl;
++      info(DRIVER_DESC " " DRIVER_VERSION);
++      memset(&cbTbl, 0, sizeof(cbTbl));
++      cbTbl.probe = konicawc_probe;
++      cbTbl.setupOnOpen = konicawc_setup_on_open;
++      cbTbl.processData = konicawc_process_isoc;
++      cbTbl.getFPS = konicawc_calculate_fps;
++      cbTbl.setVideoMode = konicawc_set_video_mode;
++      cbTbl.startDataPump = konicawc_start_data;
++      cbTbl.stopDataPump = konicawc_stop_data;
++      cbTbl.adjustPicture = konicawc_adjust_picture;
++      cbTbl.userFree = konicawc_free_uvd;
++      return usbvideo_register(
++              &cams,
++              MAX_CAMERAS,
++              sizeof(struct konicawc),
++              "konicawc",
++              &cbTbl,
++              THIS_MODULE,
++              id_table);
++}
++
++
++static void __exit konicawc_cleanup(void)
++{
++      usbvideo_Deregister(&cams);
++}
++
++
++MODULE_DEVICE_TABLE(usb, id_table);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_PARM(speed, "i");
++MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)");
++MODULE_PARM(size, "i");
++MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240");
++MODULE_PARM(brightness, "i");
++MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");
++MODULE_PARM(contrast, "i");
++MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");
++MODULE_PARM(saturation, "i");
++MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");
++MODULE_PARM(sharpness, "i");
++MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");
++MODULE_PARM(whitebal, "i");
++MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");
++MODULE_PARM(debug, "i");
++MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
++module_init(konicawc_init);
++module_exit(konicawc_cleanup);
+diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/ultracam.c linux-2.4.19-pre8-konicawc/drivers/usb/ultracam.c
+--- linux-2.4.19-pre8/drivers/usb/ultracam.c   Wed Oct 17 22:34:06 2001
++++ linux-2.4.19-pre8-konicawc/drivers/usb/ultracam.c  Sat May 11 01:34:30 2002
+@@ -659,6 +659,12 @@
+       return uvd;
+ }
++
++static struct usb_device_id id_table[] = {
++      { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
++      { }  /* Terminating entry */
++};
++
+ /*
+  * ultracam_init()
+  *
+@@ -682,7 +688,8 @@
+               sizeof(ultracam_t),
+               "ultracam",
+               &cbTbl,
+-              THIS_MODULE);
++              THIS_MODULE,
++              id_table);
+ }
+ static void __exit ultracam_cleanup(void)
+@@ -690,16 +697,7 @@
+       usbvideo_Deregister(&cams);
+ }
+-#if defined(usb_device_id_ver)
+-
+-static __devinitdata struct usb_device_id id_table[] = {
+-      { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
+-      { }  /* Terminating entry */
+-};
+ MODULE_DEVICE_TABLE(usb, id_table);
+-
+-
+-#endif /* defined(usb_device_id_ver) */
+ MODULE_LICENSE("GPL");
+ module_init(ultracam_init);
+diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/usbvideo.c linux-2.4.19-pre8-konicawc/drivers/usb/usbvideo.c
+--- linux-2.4.19-pre8/drivers/usb/usbvideo.c   Thu Oct 11 07:42:46 2001
++++ linux-2.4.19-pre8-konicawc/drivers/usb/usbvideo.c  Sat May 11 03:11:30 2002
+@@ -159,9 +159,21 @@
+ void RingQueue_Allocate(RingQueue_t *rq, int rqLen)
+ {
++      /* Make sure the requested size is a power of 2 and
++         round up if necessary. This allows index wrapping
++         using masks rather than modulo */
++
++      int i = 1;
+       assert(rq != NULL);
+       assert(rqLen > 0);
++
++      while(rqLen >> i)
++              i++;
++      if(rqLen != 1 << (i-1))
++              rqLen = 1 << i;
++
+       rq->length = rqLen;
++      rq->ri = rq->wi = 0;
+       rq->queue = usbvideo_rvmalloc(rq->length);
+       assert(rq->queue != NULL);
+ }
+@@ -185,12 +197,33 @@
+ int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len)
+ {
+-      int i;
++      int rql, toread;
++
+       assert(rq != NULL);
+       assert(dst != NULL);
+-      for (i=0; i < len; i++) {
+-              dst[i] = rq->queue[rq->ri];
+-              RING_QUEUE_DEQUEUE_BYTES(rq,1);
++
++
++      rql = RingQueue_GetLength(rq);
++      if(!rql)
++              return 0;
++
++      /* Clip requested length to available data */
++      if(len > rql)
++              len = rql;
++
++      toread = len;
++      if(rq->ri > rq->wi) {
++              /* Read data from tail */
++              int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri;
++              memcpy(dst, rq->queue + rq->ri, read);
++              toread -= read;
++              dst += read;
++              rq->ri = (rq->ri + read) & (rq->length-1);
++      }
++      if(toread) {
++              /* Read data from head */
++              memcpy(dst, rq->queue + rq->ri, toread);
++              rq->ri = (rq->ri + toread) & (rq->length-1);
+       }
+       return len;
+ }
+@@ -216,7 +249,7 @@
+               if (m > q_avail)
+                       m = q_avail;
+-              memmove(rq->queue + rq->wi, cdata, m);
++              memcpy(rq->queue + rq->wi, cdata, m);
+               RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
+               cdata += m;
+               enqueued += m;
+@@ -225,22 +258,6 @@
+       return enqueued;
+ }
+-int RingQueue_GetLength(const RingQueue_t *rq)
+-{
+-      int ri, wi;
+-
+-      assert(rq != NULL);
+-
+-      ri = rq->ri;
+-      wi = rq->wi;
+-      if (ri == wi)
+-              return 0;
+-      else if (ri < wi)
+-              return wi - ri;
+-      else
+-              return wi + (rq->length - ri);
+-}
+-
+ void RingQueue_InterruptibleSleepOn(RingQueue_t *rq)
+ {
+       assert(rq != NULL);
+@@ -254,6 +271,14 @@
+               wake_up_interruptible(&rq->wqh);
+ }
++void RingQueue_Flush(RingQueue_t *rq)
++{
++      assert(rq != NULL);
++      rq->ri = 0;
++      rq->wi = 0;
++}
++
++
+ /*
+  * usbvideo_VideosizeToString()
+  *
+@@ -390,7 +415,7 @@
+               q_used = RingQueue_GetLength(&uvd->dp);
+               if ((uvd->dp.ri + q_used) >= uvd->dp.length) {
+                       u_hi = uvd->dp.length;
+-                      u_lo = (q_used + uvd->dp.ri) % uvd->dp.length;
++                      u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1);
+               } else {
+                       u_hi = (q_used + uvd->dp.ri);
+                       u_lo = -1;
+@@ -757,7 +782,8 @@
+       const int num_extra,
+       const char *driverName,
+       const usbvideo_cb_t *cbTbl,
+-      struct module *md )
++      struct module *md,
++      const struct usb_device_id *id_table)
+ {
+       static const char proc[] = "usbvideo_register";
+       usbvideo_t *cams;
+@@ -791,6 +817,10 @@
+               cams->cb.getFrame = usbvideo_GetFrame;
+       if (cams->cb.disconnect == NULL)
+               cams->cb.disconnect = usbvideo_Disconnect;
++      if (cams->cb.startDataPump == NULL)
++              cams->cb.startDataPump = usbvideo_StartDataPump;
++      if (cams->cb.stopDataPump == NULL)
++              cams->cb.stopDataPump = usbvideo_StopDataPump;
+ #if USES_PROC_FS
+       /*
+        * If both /proc fs callbacks are NULL then we assume that the driver
+@@ -843,6 +873,7 @@
+       cams->usbdrv.name = cams->drvName;
+       cams->usbdrv.probe = cams->cb.probe;
+       cams->usbdrv.disconnect = cams->cb.disconnect;
++      cams->usbdrv.id_table = id_table;
+ #if USES_PROC_FS
+       if (cams->uses_procfs) {
+@@ -963,7 +994,7 @@
+       uvd->remove_pending = 1; /* Now all ISO data will be ignored */
+       /* At this time we ask to cancel outstanding URBs */
+-      usbvideo_StopDataPump(uvd);
++      GET_CALLBACK(uvd, stopDataPump)(uvd);
+       for (i=0; i < USBVIDEO_NUMSBUF; i++)
+               usb_free_urb(uvd->sbuf[i].urb);
+@@ -1192,8 +1223,7 @@
+       if (!CAMERA_IS_OPERATIONAL(uvd))
+               return -EFAULT;
+-
+-      if (size > (((2 * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
++      if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
+               return -EINVAL;
+       pos = (unsigned long) uvd->fbuf;
+@@ -1254,7 +1284,7 @@
+               /* Allocate memory for the frame buffers */
+               uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
+               uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);
+-              RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */
++              RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
+               if ((uvd->fbuf == NULL) ||
+                   (!RingQueue_IsAllocated(&uvd->dp))) {
+                       err("%s: Failed to allocate fbuf or dp", proc);
+@@ -1299,7 +1329,7 @@
+       if (errCode == 0) {
+               /* Start data pump if we have valid endpoint */
+               if (uvd->video_endp != 0)
+-                      errCode = usbvideo_StartDataPump(uvd);
++                      errCode = GET_CALLBACK(uvd, startDataPump)(uvd);
+               if (errCode == 0) {
+                       if (VALID_CALLBACK(uvd, setupOnOpen)) {
+                               if (uvd->debug > 1)
+@@ -1350,7 +1380,7 @@
+               info("%s($%p)", proc, dev);
+       down(&uvd->lock);       
+-      usbvideo_StopDataPump(uvd);
++      GET_CALLBACK(uvd, stopDataPump)(uvd);
+       usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
+       uvd->fbuf = NULL;
+       RingQueue_Free(&uvd->dp);
+@@ -1458,8 +1488,8 @@
+                       vw.x = 0;
+                       vw.y = 0;
+-                      vw.width = VIDEOSIZE_X(uvd->canvas);
+-                      vw.height = VIDEOSIZE_Y(uvd->canvas);
++                      vw.width = VIDEOSIZE_X(uvd->videosize);
++                      vw.height = VIDEOSIZE_Y(uvd->videosize);
+                       vw.chromakey = 0;
+                       if (VALID_CALLBACK(uvd, getFPS))
+                               vw.flags = GET_CALLBACK(uvd, getFPS)(uvd);
+@@ -1529,8 +1559,8 @@
+                               }
+                               return -EINVAL;
+                       }
+-                      if ((vm.frame != 0) && (vm.frame != 1)) {
+-                              err("VIDIOCMCAPTURE: vm.frame=%d. !E [0,1]", vm.frame);
++                      if ((vm.frame < 0) && (vm.frame >= USBVIDEO_NUMFRAMES)) {
++                              err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm.frame, USBVIDEO_NUMFRAMES-1);
+                               return -EINVAL;
+                       }
+                       if (uvd->frame[vm.frame].frameState == FrameState_Grabbing) {
+@@ -1629,7 +1659,7 @@
+ {
+       static const char proc[] = "usbvideo_v4l_read";
+       uvd_t *uvd = (uvd_t *) dev;
+-      int frmx = -1;
++      int frmx = -1, i;
+       usbvideo_frame_t *frame;
+       if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL))
+@@ -1641,14 +1671,13 @@
+       down(&uvd->lock);       
+       /* See if a frame is completed, then use it. */
+-      if ((uvd->frame[0].frameState == FrameState_Done) ||
+-          (uvd->frame[0].frameState == FrameState_Done_Hold) ||
+-          (uvd->frame[0].frameState == FrameState_Error)) {
+-              frmx = 0;
+-      } else if ((uvd->frame[1].frameState >= FrameState_Done) ||
+-                 (uvd->frame[1].frameState == FrameState_Done_Hold) ||
+-                 (uvd->frame[1].frameState >= FrameState_Done)) {
+-              frmx = 1;
++      for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
++              if ((uvd->frame[i].frameState == FrameState_Done) ||
++                  (uvd->frame[i].frameState == FrameState_Done_Hold) ||
++                  (uvd->frame[i].frameState == FrameState_Error)) {
++                      frmx = i;
++                      break;
++              }
+       }
+       /* FIXME: If we don't start a frame here then who ever does? */
+@@ -1663,10 +1692,12 @@
+        * We will need to wait until it becomes cooked, of course.
+        */
+       if (frmx == -1) {
+-              if (uvd->frame[0].frameState == FrameState_Grabbing)
+-                      frmx = 0;
+-              else if (uvd->frame[1].frameState == FrameState_Grabbing)
+-                      frmx = 1;
++              for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
++                      if (uvd->frame[i].frameState == FrameState_Grabbing) {
++                              frmx = i;
++                              break;
++                      }
++              }
+       }
+       /*
+@@ -1764,7 +1795,7 @@
+               /* Mark it as available to be used again. */
+               uvd->frame[frmx].frameState = FrameState_Unused;
+-              if (usbvideo_NewFrame(uvd, frmx ? 0 : 1)) {
++              if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
+                       err("%s: usbvideo_NewFrame failed.", proc);
+               }
+       }
+@@ -2001,7 +2032,7 @@
+               uvd->settingsAdjusted = 1;
+       }
+-      n = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES;
++      n = (framenum + 1) % USBVIDEO_NUMFRAMES;
+       if (uvd->frame[n].frameState == FrameState_Ready)
+               framenum = n;
+@@ -2033,7 +2064,8 @@
+        */
+       if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) {
+               /* This copies previous frame into this one to mask losses */
+-              memmove(frame->data, uvd->frame[1-framenum].data, uvd->max_frame_size);
++              int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES;
++              memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size);
+       } else {
+               if (uvd->flags & FLAGS_CLEAN_FRAMES) {
+                       /* This provides a "clean" frame but slows things down */
+diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/usbvideo.h linux-2.4.19-pre8-konicawc/drivers/usb/usbvideo.h
+--- linux-2.4.19-pre8/drivers/usb/usbvideo.h   Thu Oct 11 07:42:46 2001
++++ linux-2.4.19-pre8-konicawc/drivers/usb/usbvideo.h  Sat May 11 01:58:58 2002
+@@ -113,9 +113,10 @@
+     mr = LIMIT_RGB(mm_r); \
+ }
+-#define       RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % (rq)->length
++#define       RING_QUEUE_SIZE         (128*1024)      /* Must be a power of 2 */
++#define       RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1)
+ #define       RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n)
+-#define       RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % (rq)->length])
++#define       RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)])
+ typedef struct {
+       unsigned char *queue;   /* Data from the Isoc data pump */
+@@ -269,6 +270,9 @@
+       int (*getFrame)(uvd_t *, int);
+       int (*procfs_read)(char *page,char **start,off_t off,int count,int *eof,void *data);
+       int (*procfs_write)(struct file *file,const char *buffer,unsigned long count,void *data);
++      int (*startDataPump)(uvd_t *uvd);
++      void (*stopDataPump)(uvd_t *uvd);
++      int (*setVideoMode)(uvd_t *, int, int, int);
+ } usbvideo_cb_t;
+ struct s_usbvideo_t {
+@@ -302,15 +306,20 @@
+ #define       VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \
+               ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL)
+-void RingQueue_Initialize(RingQueue_t *rq);
+-void RingQueue_Allocate(RingQueue_t *rq, int rqLen);
+-int  RingQueue_IsAllocated(const RingQueue_t *rq);
+-void RingQueue_Free(RingQueue_t *rq);
+ int  RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len);
+ int  RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n);
+-int  RingQueue_GetLength(const RingQueue_t *rq);
+-void RingQueue_InterruptibleSleepOn(RingQueue_t *rq);
+ void RingQueue_WakeUpInterruptible(RingQueue_t *rq);
++void RingQueue_Flush(RingQueue_t *rq);
++
++static inline int RingQueue_GetLength(const RingQueue_t *rq)
++{
++      return (rq->wi - rq->ri + rq->length) & (rq->length-1);
++}
++
++static inline int RingQueue_GetFreeSpace(const RingQueue_t *rq)
++{
++      return rq->length - RingQueue_GetLength(rq);
++}
+ void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame);
+ void usbvideo_DrawLine(
+@@ -339,7 +348,8 @@
+       const int num_extra,
+       const char *driverName,
+       const usbvideo_cb_t *cbTable,
+-      struct module *md);
++      struct module *md,
++      const struct usb_device_id *id_table);
+ uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams);
+ int usbvideo_RegisterVideoDevice(uvd_t *uvd);
+ void usbvideo_Deregister(usbvideo_t **uvt);
This page took 0.19806 seconds and 4 git commands to generate.