+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/io.h>
-
-#include "usbvideo.h"
-
-#if defined(MAP_NR)
-#define        virt_to_page(v) MAP_NR(v)       /* Kernels 2.2.x */
-#endif
-
-static int video_nr = -1;
-module_param(video_nr, int, 0);
-
-/*
- * Local prototypes.
- */
-static void usbvideo_Disconnect(struct usb_interface *intf);
-static void usbvideo_CameraRelease(struct uvd *uvd);
-
-static long usbvideo_v4l_ioctl(struct file *file,
-                             unsigned int cmd, unsigned long arg);
-static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
-static int usbvideo_v4l_open(struct file *file);
-static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
-                            size_t count, loff_t *ppos);
-static int usbvideo_v4l_close(struct file *file);
-
-static int usbvideo_StartDataPump(struct uvd *uvd);
-static void usbvideo_StopDataPump(struct uvd *uvd);
-static int usbvideo_GetFrame(struct uvd *uvd, int frameNum);
-static int usbvideo_NewFrame(struct uvd *uvd, int framenum);
-static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
-                                               struct usbvideo_frame *frame);
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-static void *usbvideo_rvmalloc(unsigned long size)
-{
-       void *mem;
-       unsigned long adr;
-
-       size = PAGE_ALIGN(size);
-       mem = vmalloc_32(size);
-       if (!mem)
-               return NULL;
-
-       memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-       adr = (unsigned long) mem;
-       while (size > 0) {
-               SetPageReserved(vmalloc_to_page((void *)adr));
-               adr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       return mem;
-}
-
-static void usbvideo_rvfree(void *mem, unsigned long size)
-{
-       unsigned long adr;
-
-       if (!mem)
-               return;
-
-       adr = (unsigned long) mem;
-       while ((long) size > 0) {
-               ClearPageReserved(vmalloc_to_page((void *)adr));
-               adr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       vfree(mem);
-}
-
-static void RingQueue_Initialize(struct RingQueue *rq)
-{
-       assert(rq != NULL);
-       init_waitqueue_head(&rq->wqh);
-}
-
-static void RingQueue_Allocate(struct RingQueue *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);
-}
-
-static int RingQueue_IsAllocated(const struct RingQueue *rq)
-{
-       if (rq == NULL)
-               return 0;
-       return (rq->queue != NULL) && (rq->length > 0);
-}
-
-static void RingQueue_Free(struct RingQueue *rq)
-{
-       assert(rq != NULL);
-       if (RingQueue_IsAllocated(rq)) {
-               usbvideo_rvfree(rq->queue, rq->length);
-               rq->queue = NULL;
-               rq->length = 0;
-       }
-}
-
-int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len)
-{
-       int rql, toread;
-
-       assert(rq != NULL);
-       assert(dst != NULL);
-
-       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;
-}
-
-EXPORT_SYMBOL(RingQueue_Dequeue);
-
-int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n)
-{
-       int enqueued = 0;
-
-       assert(rq != NULL);
-       assert(cdata != NULL);
-       assert(rq->length > 0);
-       while (n > 0) {
-               int m, q_avail;
-
-               /* Calculate the largest chunk that fits the tail of the ring */
-               q_avail = rq->length - rq->wi;
-               if (q_avail <= 0) {
-                       rq->wi = 0;
-                       q_avail = rq->length;
-               }
-               m = n;
-               assert(q_avail > 0);
-               if (m > q_avail)
-                       m = q_avail;
-
-               memcpy(rq->queue + rq->wi, cdata, m);
-               RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
-               cdata += m;
-               enqueued += m;
-               n -= m;
-       }
-       return enqueued;
-}
-
-EXPORT_SYMBOL(RingQueue_Enqueue);
-
-static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq)
-{
-       assert(rq != NULL);
-       interruptible_sleep_on(&rq->wqh);
-}
-
-void RingQueue_WakeUpInterruptible(struct RingQueue *rq)
-{
-       assert(rq != NULL);
-       if (waitqueue_active(&rq->wqh))
-               wake_up_interruptible(&rq->wqh);
-}
-
-EXPORT_SYMBOL(RingQueue_WakeUpInterruptible);
-
-void RingQueue_Flush(struct RingQueue *rq)
-{
-       assert(rq != NULL);
-       rq->ri = 0;
-       rq->wi = 0;
-}
-
-EXPORT_SYMBOL(RingQueue_Flush);
-
-
-/*
- * usbvideo_VideosizeToString()
- *
- * This procedure converts given videosize value to readable string.
- *
- * History:
- * 07-Aug-2000 Created.
- * 19-Oct-2000 Reworked for usbvideo module.
- */
-static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs)
-{
-       char tmp[40];
-       int n;
-
-       n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs));
-       assert(n < sizeof(tmp));
-       if ((buf == NULL) || (bufLen < n))
-               err("usbvideo_VideosizeToString: buffer is too small.");
-       else
-               memmove(buf, tmp, n);
-}
-
-/*
- * usbvideo_OverlayChar()
- *
- * History:
- * 01-Feb-2000 Created.
- */
-static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame,
-                                int x, int y, int ch)
-{
-       static const unsigned short digits[16] = {
-               0xF6DE, /* 0 */
-               0x2492, /* 1 */
-               0xE7CE, /* 2 */
-               0xE79E, /* 3 */
-               0xB792, /* 4 */
-               0xF39E, /* 5 */
-               0xF3DE, /* 6 */
-               0xF492, /* 7 */
-               0xF7DE, /* 8 */
-               0xF79E, /* 9 */
-               0x77DA, /* a */
-               0xD75C, /* b */
-               0xF24E, /* c */
-               0xD6DC, /* d */
-               0xF34E, /* e */
-               0xF348  /* f */
-       };
-       unsigned short digit;
-       int ix, iy;
-       int value;
-
-       if ((uvd == NULL) || (frame == NULL))
-               return;
-
-       value = hex_to_bin(ch);
-       if (value < 0)
-               return;
-       digit = digits[value];
-
-       for (iy=0; iy < 5; iy++) {
-               for (ix=0; ix < 3; ix++) {
-                       if (digit & 0x8000) {
-                               if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) {
-/* TODO */                             RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF);
-                               }
-                       }
-                       digit = digit << 1;
-               }
-       }
-}
-
-/*
- * usbvideo_OverlayString()
- *
- * History:
- * 01-Feb-2000 Created.
- */
-static void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame,
-                                  int x, int y, const char *str)
-{
-       while (*str) {
-               usbvideo_OverlayChar(uvd, frame, x, y, *str);
-               str++;
-               x += 4; /* 3 pixels character + 1 space */
-       }
-}
-
-/*
- * usbvideo_OverlayStats()
- *
- * Overlays important debugging information.
- *
- * History:
- * 01-Feb-2000 Created.
- */
-static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame)
-{
-       const int y_diff = 8;
-       char tmp[16];
-       int x = 10, y=10;
-       long i, j, barLength;
-       const int qi_x1 = 60, qi_y1 = 10;
-       const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10;
-
-       /* Call the user callback, see if we may proceed after that */
-       if (VALID_CALLBACK(uvd, overlayHook)) {
-               if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0)
-                       return;
-       }
-
-       /*
-        * We draw a (mostly) hollow rectangle with qi_xxx coordinates.
-        * Left edge symbolizes the queue index 0; right edge symbolizes
-        * the full capacity of the queue.
-        */
-       barLength = qi_x2 - qi_x1 - 2;
-       if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) {
-/* TODO */     long u_lo, u_hi, q_used;
-               long m_ri, m_wi, m_lo, m_hi;
-
-               /*
-                * Determine fill zones (used areas of the queue):
-                * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length
-                *
-                * if u_lo < 0 then there is no first filler.
-                */
-
-               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-1);
-               } else {
-                       u_hi = (q_used + uvd->dp.ri);
-                       u_lo = -1;
-               }
-
-               /* Convert byte indices into screen units */
-               m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length);
-               m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length);
-               m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1;
-               m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length);
-
-               for (j=qi_y1; j < (qi_y1 + qi_h); j++) {
-                       for (i=qi_x1; i < qi_x2; i++) {
-                               /* Draw border lines */
-                               if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) ||
-                                   (i == qi_x1) || (i == (qi_x2 - 1))) {
-                                       RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF);
-                                       continue;
-                               }
-                               /* For all other points the Y coordinate does not matter */
-                               if ((i >= m_ri) && (i <= (m_ri + 3))) {
-                                       RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00);
-                               } else if ((i >= m_wi) && (i <= (m_wi + 3))) {
-                                       RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00);
-                               } else if ((i < m_lo) || ((i > m_ri) && (i < m_hi)))
-                                       RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF);
-                       }
-               }
-       }
-
-       sprintf(tmp, "%8lx", uvd->stats.frame_num);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8lx", uvd->stats.urb_count);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8lx", uvd->stats.urb_length);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8lx", uvd->stats.data_count);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8lx", uvd->stats.header_count);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8lx", uvd->stats.iso_skip_count);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8lx", uvd->stats.iso_err_count);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8x", uvd->vpic.colour);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8x", uvd->vpic.hue);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8x", uvd->vpic.brightness >> 8);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8x", uvd->vpic.contrast >> 12);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-
-       sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8);
-       usbvideo_OverlayString(uvd, frame, x, y, tmp);
-       y += y_diff;
-}
-
-/*
- * usbvideo_ReportStatistics()
- *
- * This procedure prints packet and transfer statistics.
- *
- * History:
- * 14-Jan-2000 Corrected default multiplier.
- */
-static void usbvideo_ReportStatistics(const struct uvd *uvd)
-{
-       if ((uvd != NULL) && (uvd->stats.urb_count > 0)) {
-               unsigned long allPackets, badPackets, goodPackets, percent;
-               allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES;
-               badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count;
-               goodPackets = allPackets - badPackets;
-               /* Calculate percentage wisely, remember integer limits */
-               assert(allPackets != 0);
-               if (goodPackets < (((unsigned long)-1)/100))
-                       percent = (100 * goodPackets) / allPackets;
-               else
-                       percent = goodPackets / (allPackets / 100);
-               dev_info(&uvd->dev->dev,
-                        "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n",
-                        allPackets, badPackets, percent);
-               if (uvd->iso_packet_len > 0) {
-                       unsigned long allBytes, xferBytes;
-                       char multiplier = ' ';
-                       allBytes = allPackets * uvd->iso_packet_len;
-                       xferBytes = uvd->stats.data_count;
-                       assert(allBytes != 0);
-                       if (xferBytes < (((unsigned long)-1)/100))
-                               percent = (100 * xferBytes) / allBytes;
-                       else
-                               percent = xferBytes / (allBytes / 100);
-                       /* Scale xferBytes for easy reading */
-                       if (xferBytes > 10*1024) {
-                               xferBytes /= 1024;
-                               multiplier = 'K';
-                               if (xferBytes > 10*1024) {
-                                       xferBytes /= 1024;
-                                       multiplier = 'M';
-                                       if (xferBytes > 10*1024) {
-                                               xferBytes /= 1024;
-                                               multiplier = 'G';
-                                               if (xferBytes > 10*1024) {
-                                                       xferBytes /= 1024;
-                                                       multiplier = 'T';
-                                               }
-                                       }
-                               }
-                       }
-                       dev_info(&uvd->dev->dev,
-                                "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n",
-                                xferBytes, multiplier, percent);
-               }
-       }
-}
-
-/*
- * usbvideo_TestPattern()
- *
- * Procedure forms a test pattern (yellow grid on blue background).
- *
- * Parameters:
- * fullframe: if TRUE then entire frame is filled, otherwise the procedure
- *           continues from the current scanline.
- * pmode      0: fill the frame with solid blue color (like on VCR or TV)
- *           1: Draw a colored grid
- *
- * History:
- * 01-Feb-2000 Created.
- */
-void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
-{
-       struct usbvideo_frame *frame;
-       int num_cell = 0;
-       int scan_length = 0;
-       static int num_pass;
-
-       if (uvd == NULL) {
-               err("%s: uvd == NULL", __func__);
-               return;
-       }
-       if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
-               err("%s: uvd->curframe=%d.", __func__, uvd->curframe);
-               return;
-       }
-
-       /* Grab the current frame */
-       frame = &uvd->frame[uvd->curframe];
-
-       /* Optionally start at the beginning */
-       if (fullframe) {
-               frame->curline = 0;
-               frame->seqRead_Length = 0;
-       }
-#if 0
-       {       /* For debugging purposes only */
-               char tmp[20];
-               usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request);
-               dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp);
-       }
-#endif
-       /* Form every scan line */
-       for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) {
-               int i;
-               unsigned char *f = frame->data +
-                       (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline);
-               for (i=0; i < VIDEOSIZE_X(frame->request); i++) {
-                       unsigned char cb=0x80;
-                       unsigned char cg = 0;
-                       unsigned char cr = 0;
-
-                       if (pmode == 1) {
-                               if (frame->curline % 32 == 0)
-                                       cb = 0, cg = cr = 0xFF;
-                               else if (i % 32 == 0) {
-                                       if (frame->curline % 32 == 1)
-                                               num_cell++;
-                                       cb = 0, cg = cr = 0xFF;
-                               } else {
-                                       cb = ((num_cell*7) + num_pass) & 0xFF;
-                                       cg = ((num_cell*5) + num_pass*2) & 0xFF;
-                                       cr = ((num_cell*3) + num_pass*3) & 0xFF;
-                               }
-                       } else {
-                               /* Just the blue screen */
-                       }
-
-                       *f++ = cb;
-                       *f++ = cg;
-                       *f++ = cr;
-                       scan_length += 3;
-               }
-       }
-
-       frame->frameState = FrameState_Done;
-       frame->seqRead_Length += scan_length;
-       ++num_pass;
-
-       /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */
-       usbvideo_OverlayStats(uvd, frame);
-}
-
-EXPORT_SYMBOL(usbvideo_TestPattern);
-
-
-#ifdef DEBUG
-/*
- * usbvideo_HexDump()
- *
- * A debugging tool. Prints hex dumps.
- *
- * History:
- * 29-Jul-2000 Added printing of offsets.
- */
-void usbvideo_HexDump(const unsigned char *data, int len)
-{
-       const int bytes_per_line = 32;
-       char tmp[128]; /* 32*3 + 5 */
-       int i, k;
-
-       for (i=k=0; len > 0; i++, len--) {
-               if (i > 0 && ((i % bytes_per_line) == 0)) {
-                       printk("%s\n", tmp);
-                       k=0;
-               }
-               if ((i % bytes_per_line) == 0)
-                       k += sprintf(&tmp[k], "%04x: ", i);
-               k += sprintf(&tmp[k], "%02x ", data[i]);
-       }
-       if (k > 0)
-               printk("%s\n", tmp);
-}
-
-EXPORT_SYMBOL(usbvideo_HexDump);
-
-#endif
-
-/* ******************************************************************** */
-
-/* XXX: this piece of crap really wants some error handling.. */
-static int usbvideo_ClientIncModCount(struct uvd *uvd)
-{
-       if (uvd == NULL) {
-               err("%s: uvd == NULL", __func__);
-               return -EINVAL;
-       }
-       if (uvd->handle == NULL) {
-               err("%s: uvd->handle == NULL", __func__);
-               return -EINVAL;
-       }
-       if (!try_module_get(uvd->handle->md_module)) {
-               err("%s: try_module_get() == 0", __func__);
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static void usbvideo_ClientDecModCount(struct uvd *uvd)
-{
-       if (uvd == NULL) {
-               err("%s: uvd == NULL", __func__);
-               return;
-       }
-       if (uvd->handle == NULL) {
-               err("%s: uvd->handle == NULL", __func__);
-               return;
-       }
-       if (uvd->handle->md_module == NULL) {
-               err("%s: uvd->handle->md_module == NULL", __func__);
-               return;
-       }
-       module_put(uvd->handle->md_module);
-}
-
-int usbvideo_register(
-       struct usbvideo **pCams,
-       const int num_cams,
-       const int num_extra,
-       const char *driverName,
-       const struct usbvideo_cb *cbTbl,
-       struct module *md,
-       const struct usb_device_id *id_table)
-{
-       struct usbvideo *cams;
-       int i, base_size, result;
-
-       /* Check parameters for sanity */
-       if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
-               err("%s: Illegal call", __func__);
-               return -EINVAL;
-       }
-
-       /* Check registration callback - must be set! */
-       if (cbTbl->probe == NULL) {
-               err("%s: probe() is required!", __func__);
-               return -EINVAL;
-       }
-
-       base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo);
-       cams = kzalloc(base_size, GFP_KERNEL);
-       if (cams == NULL) {
-               err("Failed to allocate %d. bytes for usbvideo struct", base_size);
-               return -ENOMEM;
-       }
-       dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
-           __func__, cams, base_size, num_cams);
-
-       /* Copy callbacks, apply defaults for those that are not set */
-       memmove(&cams->cb, cbTbl, sizeof(cams->cb));
-       if (cams->cb.getFrame == NULL)
-               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;
-
-       cams->num_cameras = num_cams;
-       cams->cam = (struct uvd *) &cams[1];
-       cams->md_module = md;
-       mutex_init(&cams->lock);        /* to 1 == available */
-
-       for (i = 0; i < num_cams; i++) {
-               struct uvd *up = &cams->cam[i];
-
-               up->handle = cams;
-
-               /* Allocate user_data separately because of kmalloc's limits */
-               if (num_extra > 0) {
-                       up->user_size = num_cams * num_extra;
-                       up->user_data = kmalloc(up->user_size, GFP_KERNEL);
-                       if (up->user_data == NULL) {
-                               err("%s: Failed to allocate user_data (%d. bytes)",
-                                   __func__, up->user_size);
-                               while (i) {
-                                       up = &cams->cam[--i];
-                                       kfree(up->user_data);
-                               }
-                               kfree(cams);
-                               return -ENOMEM;
-                       }
-                       dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
-                            __func__, i, up->user_data, up->user_size);
-               }
-       }
-
-       /*
-        * Register ourselves with USB stack.
-        */
-       strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown");
-       cams->usbdrv.name = cams->drvName;
-       cams->usbdrv.probe = cams->cb.probe;
-       cams->usbdrv.disconnect = cams->cb.disconnect;
-       cams->usbdrv.id_table = id_table;
-
-       /*
-        * Update global handle to usbvideo. This is very important
-        * because probe() can be called before usb_register() returns.
-        * If the handle is not yet updated then the probe() will fail.
-        */
-       *pCams = cams;
-       result = usb_register(&cams->usbdrv);
-       if (result) {
-               for (i = 0; i < num_cams; i++) {
-                       struct uvd *up = &cams->cam[i];
-                       kfree(up->user_data);
-               }
-               kfree(cams);
-       }
-
-       return result;
-}
-
-EXPORT_SYMBOL(usbvideo_register);
-
-/*
- * usbvideo_Deregister()
- *
- * Procedure frees all usbvideo and user data structures. Be warned that
- * if you had some dynamically allocated components in ->user field then
- * you should free them before calling here.
- */
-void usbvideo_Deregister(struct usbvideo **pCams)
-{
-       struct usbvideo *cams;
-       int i;
-
-       if (pCams == NULL) {
-               err("%s: pCams == NULL", __func__);
-               return;
-       }
-       cams = *pCams;
-       if (cams == NULL) {
-               err("%s: cams == NULL", __func__);
-               return;
-       }
-
-       dbg("%s: Deregistering %s driver.", __func__, cams->drvName);
-       usb_deregister(&cams->usbdrv);
-
-       dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras);
-       for (i=0; i < cams->num_cameras; i++) {
-               struct uvd *up = &cams->cam[i];
-               int warning = 0;
-
-               if (up->user_data != NULL) {
-                       if (up->user_size <= 0)
-                               ++warning;
-               } else {
-                       if (up->user_size > 0)
-                               ++warning;
-               }
-               if (warning) {
-                       err("%s: Warning: user_data=$%p user_size=%d.",
-                           __func__, up->user_data, up->user_size);
-               } else {
-                       dbg("%s: Freeing %d. $%p->user_data=$%p",
-                           __func__, i, up, up->user_data);
-                       kfree(up->user_data);
-               }
-       }
-       /* Whole array was allocated in one chunk */
-       dbg("%s: Freed %d uvd structures",
-           __func__, cams->num_cameras);
-       kfree(cams);
-       *pCams = NULL;
-}
-
-EXPORT_SYMBOL(usbvideo_Deregister);
-
-/*
- * usbvideo_Disconnect()
- *
- * This procedure stops all driver activity. Deallocation of
- * the interface-private structure (pointed by 'ptr') is done now
- * (if we don't have any open files) or later, when those files
- * are closed. After that driver should be removable.
- *
- * This code handles surprise removal. The uvd->user is a counter which
- * increments on open() and decrements on close(). If we see here that
- * this counter is not 0 then we have a client who still has us opened.
- * We set uvd->remove_pending flag as early as possible, and after that
- * all access to the camera will gracefully fail. These failures should
- * prompt client to (eventually) close the video device, and then - in
- * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter.
- *
- * History:
- * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone.
- * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close()
- * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
- * 19-Oct-2000 Moved to usbvideo module.
- */
-static void usbvideo_Disconnect(struct usb_interface *intf)
-{
-       struct uvd *uvd = usb_get_intfdata (intf);
-       int i;
-
-       if (uvd == NULL) {
-               err("%s($%p): Illegal call.", __func__, intf);
-               return;
-       }
-
-       usb_set_intfdata (intf, NULL);
-
-       usbvideo_ClientIncModCount(uvd);
-       if (uvd->debug > 0)
-               dev_info(&intf->dev, "%s(%p.)\n", __func__, intf);
-
-       mutex_lock(&uvd->lock);
-       uvd->remove_pending = 1; /* Now all ISO data will be ignored */
-
-       /* At this time we ask to cancel outstanding URBs */
-       GET_CALLBACK(uvd, stopDataPump)(uvd);
-
-       for (i=0; i < USBVIDEO_NUMSBUF; i++)
-               usb_free_urb(uvd->sbuf[i].urb);
-
-       usb_put_dev(uvd->dev);
-       uvd->dev = NULL;            /* USB device is no more */
-
-       video_unregister_device(&uvd->vdev);
-       if (uvd->debug > 0)
-               dev_info(&intf->dev, "%s: Video unregistered.\n", __func__);
-
-       if (uvd->user)
-               dev_info(&intf->dev, "%s: In use, disconnect pending.\n",
-                        __func__);
-       else
-               usbvideo_CameraRelease(uvd);
-       mutex_unlock(&uvd->lock);
-       dev_info(&intf->dev, "USB camera disconnected.\n");
-
-       usbvideo_ClientDecModCount(uvd);
-}
-
-/*
- * usbvideo_CameraRelease()
- *
- * This code does final release of uvd. This happens
- * after the device is disconnected -and- all clients
- * closed their files.
- *
- * History:
- * 27-Jan-2000 Created.
- */
-static void usbvideo_CameraRelease(struct uvd *uvd)
-{
-       if (uvd == NULL) {
-               err("%s: Illegal call", __func__);
-               return;
-       }
-
-       RingQueue_Free(&uvd->dp);
-       if (VALID_CALLBACK(uvd, userFree))
-               GET_CALLBACK(uvd, userFree)(uvd);
-       uvd->uvd_used = 0;      /* This is atomic, no need to take mutex */
-}
-
-/*
- * usbvideo_find_struct()
- *
- * This code searches the array of preallocated (static) structures
- * and returns index of the first one that isn't in use. Returns -1
- * if there are no free structures.
- *
- * History:
- * 27-Jan-2000 Created.
- */
-static int usbvideo_find_struct(struct usbvideo *cams)
-{
-       int u, rv = -1;
-
-       if (cams == NULL) {
-               err("No usbvideo handle?");
-               return -1;
-       }
-       mutex_lock(&cams->lock);
-       for (u = 0; u < cams->num_cameras; u++) {
-               struct uvd *uvd = &cams->cam[u];
-               if (!uvd->uvd_used) /* This one is free */
-               {
-                       uvd->uvd_used = 1;      /* In use now */
-                       mutex_init(&uvd->lock); /* to 1 == available */
-                       uvd->dev = NULL;
-                       rv = u;
-                       break;
-               }
-       }
-       mutex_unlock(&cams->lock);
-       return rv;
-}
-
-static const struct v4l2_file_operations usbvideo_fops = {
-       .owner =  THIS_MODULE,
-       .open =   usbvideo_v4l_open,
-       .release =usbvideo_v4l_close,
-       .read =   usbvideo_v4l_read,
-       .mmap =   usbvideo_v4l_mmap,
-       .ioctl =  usbvideo_v4l_ioctl,
-};
-static const struct video_device usbvideo_template = {
-       .fops =       &usbvideo_fops,
-};
-
-struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams)
-{
-       int i, devnum;
-       struct uvd *uvd = NULL;
-
-       if (cams == NULL) {
-               err("No usbvideo handle?");
-               return NULL;
-       }
-
-       devnum = usbvideo_find_struct(cams);
-       if (devnum == -1) {
-               err("IBM USB camera driver: Too many devices!");
-               return NULL;
-       }
-       uvd = &cams->cam[devnum];
-       dbg("Device entry #%d. at $%p", devnum, uvd);
-
-       /* Not relying upon caller we increase module counter ourselves */
-       usbvideo_ClientIncModCount(uvd);
-
-       mutex_lock(&uvd->lock);
-       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-               uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-               if (uvd->sbuf[i].urb == NULL) {
-                       err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC);
-                       uvd->uvd_used = 0;
-                       uvd = NULL;
-                       goto allocate_done;
-               }
-       }
-       uvd->user=0;
-       uvd->remove_pending = 0;
-       uvd->last_error = 0;
-       RingQueue_Initialize(&uvd->dp);
-
-       /* Initialize video device structure */
-       uvd->vdev = usbvideo_template;
-       sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName);
-       /*
-        * The client is free to overwrite those because we
-        * return control to the client's probe function right now.
-        */
-allocate_done:
-       mutex_unlock(&uvd->lock);
-       usbvideo_ClientDecModCount(uvd);
-       return uvd;
-}
-
-EXPORT_SYMBOL(usbvideo_AllocateDevice);
-
-int usbvideo_RegisterVideoDevice(struct uvd *uvd)
-{
-       char tmp1[20], tmp2[20];        /* Buffers for printing */
-
-       if (uvd == NULL) {
-               err("%s: Illegal call.", __func__);
-               return -EINVAL;
-       }
-       if (uvd->video_endp == 0) {
-               dev_info(&uvd->dev->dev,
-                        "%s: No video endpoint specified; data pump disabled.\n",
-                        __func__);
-       }
-       if (uvd->paletteBits == 0) {
-               err("%s: No palettes specified!", __func__);
-               return -EINVAL;
-       }
-       if (uvd->defaultPalette == 0) {
-               dev_info(&uvd->dev->dev, "%s: No default palette!\n",
-                        __func__);
-       }
-
-       uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
-               VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL;
-       usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize);
-       usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas);
-
-       if (uvd->debug > 0) {
-               dev_info(&uvd->dev->dev,
-                        "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n",
-                        __func__, uvd->iface, uvd->video_endp,
-                        uvd->paletteBits);
-       }
-       if (uvd->dev == NULL) {
-               err("%s: uvd->dev == NULL", __func__);
-               return -EINVAL;
-       }
-       uvd->vdev.parent = &uvd->dev->dev;
-       uvd->vdev.release = video_device_release_empty;
-       if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
-               err("%s: video_register_device failed", __func__);
-               return -EPIPE;
-       }
-       if (uvd->debug > 1) {
-               dev_info(&uvd->dev->dev,
-                        "%s: video_register_device() successful\n", __func__);
-       }
-
-       dev_info(&uvd->dev->dev, "%s on %s: canvas=%s videosize=%s\n",
-                (uvd->handle != NULL) ? uvd->handle->drvName : "???",
-                video_device_node_name(&uvd->vdev), tmp2, tmp1);
-
-       usb_get_dev(uvd->dev);
-       return 0;
-}
-
-EXPORT_SYMBOL(usbvideo_RegisterVideoDevice);
-
-/* ******************************************************************** */
-
-static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct uvd *uvd = file->private_data;
-       unsigned long start = vma->vm_start;
-       unsigned long size  = vma->vm_end-vma->vm_start;
-       unsigned long page, pos;
-
-       if (!CAMERA_IS_OPERATIONAL(uvd))
-               return -EFAULT;
-
-       if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
-               return -EINVAL;
-
-       pos = (unsigned long) uvd->fbuf;
-       while (size > 0) {
-               page = vmalloc_to_pfn((void *)pos);
-               if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-                       return -EAGAIN;
-
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               if (size > PAGE_SIZE)
-                       size -= PAGE_SIZE;
-               else
-                       size = 0;
-       }
-
-       return 0;
-}
-
-/*
- * usbvideo_v4l_open()
- *
- * This is part of Video 4 Linux API. The driver can be opened by one
- * client only (checks internal counter 'uvdser'). The procedure
- * then allocates buffers needed for video processing.
- *
- * History:
- * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the
- *             camera is also initialized here (once per connect), at
- *             expense of V4L client (it waits on open() call).
- * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
- * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
- */
-static int usbvideo_v4l_open(struct file *file)
-{
-       struct video_device *dev = video_devdata(file);
-       struct uvd *uvd = (struct uvd *) dev;
-       const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len;
-       int i, errCode = 0;
-
-       if (uvd->debug > 1)
-               dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev);
-
-       if (usbvideo_ClientIncModCount(uvd) < 0)
-               return -ENODEV;
-       mutex_lock(&uvd->lock);
-
-       if (uvd->user) {
-               err("%s: Someone tried to open an already opened device!", __func__);
-               errCode = -EBUSY;
-       } else {
-               /* Clear statistics */
-               memset(&uvd->stats, 0, sizeof(uvd->stats));
-
-               /* Clean pointers so we know if we allocated something */
-               for (i=0; i < USBVIDEO_NUMSBUF; i++)
-                       uvd->sbuf[i].data = NULL;
-
-               /* 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, RING_QUEUE_SIZE);
-               if ((uvd->fbuf == NULL) ||
-                   (!RingQueue_IsAllocated(&uvd->dp))) {
-                       err("%s: Failed to allocate fbuf or dp", __func__);
-                       errCode = -ENOMEM;
-               } else {
-                       /* Allocate all buffers */
-                       for (i=0; i < USBVIDEO_NUMFRAMES; i++) {
-                               uvd->frame[i].frameState = FrameState_Unused;
-                               uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size);
-                               /*
-                                * Set default sizes in case IOCTL (VIDIOCMCAPTURE)
-                                * is not used (using read() instead).
-                                */
-                               uvd->frame[i].canvas = uvd->canvas;
-                               uvd->frame[i].seqRead_Index = 0;
-                       }
-                       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-                               uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);
-                               if (uvd->sbuf[i].data == NULL) {
-                                       errCode = -ENOMEM;
-                                       break;
-                               }
-                       }
-               }
-               if (errCode != 0) {
-                       /* Have to free all that memory */
-                       if (uvd->fbuf != NULL) {
-                               usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
-                               uvd->fbuf = NULL;
-                       }
-                       RingQueue_Free(&uvd->dp);
-                       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-                               kfree(uvd->sbuf[i].data);
-                               uvd->sbuf[i].data = NULL;
-                       }
-               }
-       }
-
-       /* If so far no errors then we shall start the camera */
-       if (errCode == 0) {
-               /* Start data pump if we have valid endpoint */
-               if (uvd->video_endp != 0)
-                       errCode = GET_CALLBACK(uvd, startDataPump)(uvd);
-               if (errCode == 0) {
-                       if (VALID_CALLBACK(uvd, setupOnOpen)) {
-                               if (uvd->debug > 1)
-                                       dev_info(&uvd->dev->dev,
-                                                "%s: setupOnOpen callback\n",
-                                                __func__);
-                               errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
-                               if (errCode < 0) {
-                                       err("%s: setupOnOpen callback failed (%d.).",
-                                           __func__, errCode);
-                               } else if (uvd->debug > 1) {
-                                       dev_info(&uvd->dev->dev,
-                                                "%s: setupOnOpen callback successful\n",
-                                                __func__);
-                               }
-                       }
-                       if (errCode == 0) {
-                               uvd->settingsAdjusted = 0;
-                               if (uvd->debug > 1)
-                                       dev_info(&uvd->dev->dev,
-                                                "%s: Open succeeded.\n",
-                                                __func__);
-                               uvd->user++;
-                               file->private_data = uvd;
-                       }
-               }
-       }
-       mutex_unlock(&uvd->lock);
-       if (errCode != 0)
-               usbvideo_ClientDecModCount(uvd);
-       if (uvd->debug > 0)
-               dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__,
-                        errCode);
-       return errCode;
-}
-
-/*
- * usbvideo_v4l_close()
- *
- * This is part of Video 4 Linux API. The procedure
- * stops streaming and deallocates all buffers that were earlier
- * allocated in usbvideo_v4l_open().
- *
- * History:
- * 22-Jan-2000 Moved scratch buffer deallocation here.
- * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
- * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep.
- */
-static int usbvideo_v4l_close(struct file *file)
-{
-       struct video_device *dev = file->private_data;
-       struct uvd *uvd = (struct uvd *) dev;
-       int i;
-
-       if (uvd->debug > 1)
-               dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev);
-
-       mutex_lock(&uvd->lock);
-       GET_CALLBACK(uvd, stopDataPump)(uvd);
-       usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
-       uvd->fbuf = NULL;
-       RingQueue_Free(&uvd->dp);
-
-       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-               kfree(uvd->sbuf[i].data);
-               uvd->sbuf[i].data = NULL;
-       }
-
-#if USBVIDEO_REPORT_STATS
-       usbvideo_ReportStatistics(uvd);
-#endif
-
-       uvd->user--;
-       if (uvd->remove_pending) {
-               if (uvd->debug > 0)
-                       dev_info(&uvd->dev->dev, "%s: Final disconnect.\n",
-                                __func__);
-               usbvideo_CameraRelease(uvd);
-       }
-       mutex_unlock(&uvd->lock);
-       usbvideo_ClientDecModCount(uvd);
-
-       if (uvd->debug > 1)
-               dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__);
-       file->private_data = NULL;
-       return 0;
-}
-
-/*
- * usbvideo_v4l_ioctl()
- *
- * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
- *
- * History:
- * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings.
- */
-static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
-       struct uvd *uvd = file->private_data;
-
-       if (!CAMERA_IS_OPERATIONAL(uvd))
-               return -EIO;
-
-       switch (cmd) {
-               case VIDIOCGCAP:
-               {
-                       struct video_capability *b = arg;
-                       *b = uvd->vcap;
-                       return 0;
-               }
-               case VIDIOCGCHAN:
-               {
-                       struct video_channel *v = arg;
-                       *v = uvd->vchan;
-                       return 0;
-               }
-               case VIDIOCSCHAN:
-               {
-                       struct video_channel *v = arg;
-                       if (v->channel != 0)
-                               return -EINVAL;
-                       return 0;
-               }
-               case VIDIOCGPICT:
-               {
-                       struct video_picture *pic = arg;
-                       *pic = uvd->vpic;
-                       return 0;
-               }
-               case VIDIOCSPICT:
-               {
-                       struct video_picture *pic = arg;
-                       /*
-                        * Use temporary 'video_picture' structure to preserve our
-                        * own settings (such as color depth, palette) that we
-                        * aren't allowing everyone (V4L client) to change.
-                        */
-                       uvd->vpic.brightness = pic->brightness;
-                       uvd->vpic.hue = pic->hue;
-                       uvd->vpic.colour = pic->colour;
-                       uvd->vpic.contrast = pic->contrast;
-                       uvd->settingsAdjusted = 0;      /* Will force new settings */
-                       return 0;
-               }
-               case VIDIOCSWIN:
-               {
-                       struct video_window *vw = arg;
-
-                       if(VALID_CALLBACK(uvd, setVideoMode)) {
-                               return GET_CALLBACK(uvd, setVideoMode)(uvd, vw);
-                       }
-
-                       if (vw->flags)
-                               return -EINVAL;
-                       if (vw->clipcount)
-                               return -EINVAL;
-                       if (vw->width != VIDEOSIZE_X(uvd->canvas))
-                               return -EINVAL;
-                       if (vw->height != VIDEOSIZE_Y(uvd->canvas))
-                               return -EINVAL;
-
-                       return 0;
-               }
-               case VIDIOCGWIN:
-               {
-                       struct video_window *vw = arg;
-
-                       vw->x = 0;
-                       vw->y = 0;
-                       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);
-                       else
-                               vw->flags = 10; /* FIXME: do better! */
-                       return 0;
-               }
-               case VIDIOCGMBUF:
-               {
-                       struct video_mbuf *vm = arg;
-                       int i;
-
-                       memset(vm, 0, sizeof(*vm));
-                       vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES;
-                       vm->frames = USBVIDEO_NUMFRAMES;
-                       for(i = 0; i < USBVIDEO_NUMFRAMES; i++)
-                         vm->offsets[i] = i * uvd->max_frame_size;
-
-                       return 0;
-               }
-               case VIDIOCMCAPTURE:
-               {
-                       struct video_mmap *vm = arg;
-
-                       if (uvd->debug >= 1) {
-                               dev_info(&uvd->dev->dev,
-                                        "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n",
-                                        vm->frame, vm->width, vm->height, vm->format);
-                       }
-                       /*
-                        * Check if the requested size is supported. If the requestor
-                        * requests too big a frame then we may be tricked into accessing
-                        * outside of own preallocated frame buffer (in uvd->frame).
-                        * This will cause oops or a security hole. Theoretically, we
-                        * could only clamp the size down to acceptable bounds, but then
-                        * we'd need to figure out how to insert our smaller buffer into
-                        * larger caller's buffer... this is not an easy question. So we
-                        * here just flatly reject too large requests, assuming that the
-                        * caller will resubmit with smaller size. Callers should know
-                        * what size we support (returned by VIDIOCGCAP). However vidcat,
-                        * for one, does not care and allows to ask for any size.
-                        */
-                       if ((vm->width > VIDEOSIZE_X(uvd->canvas)) ||
-                           (vm->height > VIDEOSIZE_Y(uvd->canvas))) {
-                               if (uvd->debug > 0) {
-                                       dev_info(&uvd->dev->dev,
-                                                "VIDIOCMCAPTURE: Size=%dx%d "
-                                                "too large; allowed only up "
-                                                "to %ldx%ld\n", vm->width,
-                                                vm->height,
-                                                VIDEOSIZE_X(uvd->canvas),
-                                                VIDEOSIZE_Y(uvd->canvas));
-                               }
-                               return -EINVAL;
-                       }
-                       /* Check if the palette is supported */
-                       if (((1L << vm->format) & uvd->paletteBits) == 0) {
-                               if (uvd->debug > 0) {
-                                       dev_info(&uvd->dev->dev,
-                                                "VIDIOCMCAPTURE: format=%d. "
-                                                "not supported "
-                                                "(paletteBits=$%08lx)\n",
-                                                vm->format, uvd->paletteBits);
-                               }
-                               return -EINVAL;
-                       }
-                       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) {
-                               /* Not an error - can happen */
-                       }
-                       uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height);
-                       uvd->frame[vm->frame].palette = vm->format;
-
-                       /* Mark it as ready */
-                       uvd->frame[vm->frame].frameState = FrameState_Ready;
-
-                       return usbvideo_NewFrame(uvd, vm->frame);
-               }
-               case VIDIOCSYNC:
-               {
-                       int *frameNum = arg;
-                       int ret;
-
-                       if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES)
-                               return -EINVAL;
-
-                       if (uvd->debug >= 1)
-                               dev_info(&uvd->dev->dev,
-                                        "VIDIOCSYNC: syncing to frame %d.\n",
-                                        *frameNum);
-                       if (uvd->flags & FLAGS_NO_DECODING)
-                               ret = usbvideo_GetFrame(uvd, *frameNum);
-                       else if (VALID_CALLBACK(uvd, getFrame)) {
-                               ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum);
-                               if ((ret < 0) && (uvd->debug >= 1)) {
-                                       err("VIDIOCSYNC: getFrame() returned %d.", ret);
-                               }
-                       } else {
-                               err("VIDIOCSYNC: getFrame is not set");
-                               ret = -EFAULT;
-                       }
-
-                       /*
-                        * The frame is in FrameState_Done_Hold state. Release it
-                        * right now because its data is already mapped into
-                        * the user space and it's up to the application to
-                        * make use of it until it asks for another frame.
-                        */
-                       uvd->frame[*frameNum].frameState = FrameState_Unused;
-                       return ret;
-               }
-               case VIDIOCGFBUF:
-               {
-                       struct video_buffer *vb = arg;
-
-                       memset(vb, 0, sizeof(*vb));
-                       return 0;
-               }
-               case VIDIOCKEY:
-                       return 0;
-
-               case VIDIOCCAPTURE:
-                       return -EINVAL;
-
-               case VIDIOCSFBUF:
-
-               case VIDIOCGTUNER:
-               case VIDIOCSTUNER:
-
-               case VIDIOCGFREQ:
-               case VIDIOCSFREQ:
-
-               case VIDIOCGAUDIO:
-               case VIDIOCSAUDIO:
-                       return -EINVAL;
-
-               default:
-                       return -ENOIOCTLCMD;
-       }
-       return 0;
-}
-
-static long usbvideo_v4l_ioctl(struct file *file,
-                      unsigned int cmd, unsigned long arg)
-{
-       return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl);
-}
-
-/*
- * usbvideo_v4l_read()
- *
- * This is mostly boring stuff. We simply ask for a frame and when it
- * arrives copy all the video data from it into user space. There is
- * no obvious need to override this method.
- *
- * History:
- * 20-Oct-2000 Created.
- * 01-Nov-2000 Added mutex (uvd->lock).
- */
-static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
-                     size_t count, loff_t *ppos)
-{
-       struct uvd *uvd = file->private_data;
-       int noblock = file->f_flags & O_NONBLOCK;
-       int frmx = -1, i;
-       struct usbvideo_frame *frame;
-
-       if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL))
-               return -EFAULT;
-
-       if (uvd->debug >= 1)
-               dev_info(&uvd->dev->dev,
-                        "%s: %Zd. bytes, noblock=%d.\n",
-                        __func__, count, noblock);
-
-       mutex_lock(&uvd->lock);
-
-       /* See if a frame is completed, then use it. */
-       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? */
-       if (noblock && (frmx == -1)) {
-               count = -EAGAIN;
-               goto read_done;
-       }
-
-       /*
-        * If no FrameState_Done, look for a FrameState_Grabbing state.
-        * See if a frame is in process (grabbing), then use it.
-        * We will need to wait until it becomes cooked, of course.
-        */
-       if (frmx == -1) {
-               for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
-                       if (uvd->frame[i].frameState == FrameState_Grabbing) {
-                               frmx = i;
-                               break;
-                       }
-               }
-       }
-
-       /*
-        * If no frame is active, start one. We don't care which one
-        * it will be, so #0 is as good as any.
-        * In read access mode we don't have convenience of VIDIOCMCAPTURE
-        * to specify the requested palette (video format) on per-frame
-        * basis. This means that we have to return data in -some- format
-        * and just hope that the client knows what to do with it.
-        * The default format is configured in uvd->defaultPalette field
-        * as one of VIDEO_PALETTE_xxx values. We stuff it into the new
-        * frame and initiate the frame filling process.
-        */
-       if (frmx == -1) {
-               if (uvd->defaultPalette == 0) {
-                       err("%s: No default palette; don't know what to do!", __func__);
-                       count = -EFAULT;
-                       goto read_done;
-               }
-               frmx = 0;
-               /*
-                * We have no per-frame control over video size.
-                * Therefore we only can use whatever size was
-                * specified as default.
-                */
-               uvd->frame[frmx].request = uvd->videosize;
-               uvd->frame[frmx].palette = uvd->defaultPalette;
-               uvd->frame[frmx].frameState = FrameState_Ready;
-               usbvideo_NewFrame(uvd, frmx);
-               /* Now frame 0 is supposed to start filling... */
-       }
-
-       /*
-        * Get a pointer to the active frame. It is either previously
-        * completed frame or frame in progress but not completed yet.
-        */
-       frame = &uvd->frame[frmx];
-
-       /*
-        * Sit back & wait until the frame gets filled and postprocessed.
-        * If we fail to get the picture [in time] then return the error.
-        * In this call we specify that we want the frame to be waited for,
-        * postprocessed and switched into FrameState_Done_Hold state. This
-        * state is used to hold the frame as "fully completed" between
-        * subsequent partial reads of the same frame.
-        */
-       if (frame->frameState != FrameState_Done_Hold) {
-               long rv = -EFAULT;
-               if (uvd->flags & FLAGS_NO_DECODING)
-                       rv = usbvideo_GetFrame(uvd, frmx);
-               else if (VALID_CALLBACK(uvd, getFrame))
-                       rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx);
-               else
-                       err("getFrame is not set");
-               if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) {
-                       count = rv;
-                       goto read_done;
-               }
-       }
-
-       /*
-        * Copy bytes to user space. We allow for partial reads, which
-        * means that the user application can request read less than
-        * the full frame size. It is up to the application to issue
-        * subsequent calls until entire frame is read.
-        *
-        * First things first, make sure we don't copy more than we
-        * have - even if the application wants more. That would be
-        * a big security embarassment!
-        */
-       if ((count + frame->seqRead_Index) > frame->seqRead_Length)
-               count = frame->seqRead_Length - frame->seqRead_Index;
-
-       /*
-        * Copy requested amount of data to user space. We start
-        * copying from the position where we last left it, which
-        * will be zero for a new frame (not read before).
-        */
-       if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) {
-               count = -EFAULT;
-               goto read_done;
-       }
-
-       /* Update last read position */
-       frame->seqRead_Index += count;
-       if (uvd->debug >= 1) {
-               err("%s: {copy} count used=%Zd, new seqRead_Index=%ld",
-                       __func__, count, frame->seqRead_Index);
-       }
-
-       /* Finally check if the frame is done with and "release" it */
-       if (frame->seqRead_Index >= frame->seqRead_Length) {
-               /* All data has been read */
-               frame->seqRead_Index = 0;
-
-               /* Mark it as available to be used again. */
-               uvd->frame[frmx].frameState = FrameState_Unused;
-               if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
-                       err("%s: usbvideo_NewFrame failed.", __func__);
-               }
-       }
-read_done:
-       mutex_unlock(&uvd->lock);
-       return count;
-}
-
-/*
- * Make all of the blocks of data contiguous
- */
-static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb)
-{
-       char *cdata;
-       int i, totlen = 0;
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int n = urb->iso_frame_desc[i].actual_length;
-               int st = urb->iso_frame_desc[i].status;
-
-               cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-               /* Detect and ignore errored packets */
-               if (st < 0) {
-                       if (uvd->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;
-               }
-               totlen += n;    /* Little local accounting */
-               RingQueue_Enqueue(&uvd->dp, cdata, n);
-       }
-       return totlen;
-}
-
-static void usbvideo_IsocIrq(struct urb *urb)
-{
-       int i, ret, len;
-       struct uvd *uvd = urb->context;
-
-       /* We don't want to do anything if we are about to be removed! */
-       if (!CAMERA_IS_OPERATIONAL(uvd))
-               return;
-#if 0
-       if (urb->actual_length > 0) {
-               dev_info(&uvd->dev->dev,
-                        "urb=$%p status=%d. errcount=%d. length=%d.\n",
-                        urb, urb->status, urb->error_count,
-                        urb->actual_length);
-       } else {
-               static int c = 0;
-               if (c++ % 100 == 0)
-                       dev_info(&uvd->dev->dev, "No Isoc data\n");
-       }
-#endif
-
-       if (!uvd->streaming) {
-               if (uvd->debug >= 1)
-                       dev_info(&uvd->dev->dev,
-                                "Not streaming, but interrupt!\n");
-               return;
-       }
-
-       uvd->stats.urb_count++;
-       if (urb->actual_length <= 0)
-               goto urb_done_with;
-
-       /* Copy the data received into ring queue */
-       len = usbvideo_CompressIsochronous(uvd, urb);
-       uvd->stats.urb_length = len;
-       if (len <= 0)
-               goto urb_done_with;
-
-       /* Here we got some data */
-       uvd->stats.data_count += len;
-       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;
-       }
-       urb->status = 0;
-       urb->dev = uvd->dev;
-       ret = usb_submit_urb (urb, GFP_KERNEL);
-       if(ret)
-               err("usb_submit_urb error (%d)", ret);
-       return;
-}
-
-/*
- * usbvideo_StartDataPump()
- *
- * History:
- * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead
- *             of hardcoded values. Simplified by using for loop,
- *             allowed any number of URBs.
- */
-static int usbvideo_StartDataPump(struct uvd *uvd)
-{
-       struct usb_device *dev = uvd->dev;
-       int i, errFlag;
-
-       if (uvd->debug > 1)
-               dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
-
-       if (!CAMERA_IS_OPERATIONAL(uvd)) {
-               err("%s: Camera is not operational", __func__);
-               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("%s: usb_set_interface error", __func__);
-               uvd->last_error = i;
-               return -EBUSY;
-       }
-       if (VALID_CALLBACK(uvd, videoStart))
-               GET_CALLBACK(uvd, videoStart)(uvd);
-       else
-               err("%s: videoStart not set", __func__);
-
-       /* 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->interval = 1;
-               urb->transfer_flags = URB_ISO_ASAP;
-               urb->transfer_buffer = uvd->sbuf[i].data;
-               urb->complete = usbvideo_IsocIrq;
-               urb->number_of_packets = FRAMES_PER_DESC;
-               urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
-               for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length = uvd->iso_packet_len;
-               }
-       }
-
-       /* Submit all URBs */
-       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-               errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
-               if (errFlag)
-                       err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag);
-       }
-
-       uvd->streaming = 1;
-       if (uvd->debug > 1)
-               dev_info(&uvd->dev->dev,
-                        "%s: streaming=1 video_endp=$%02x\n", __func__,
-                        uvd->video_endp);
-       return 0;
-}
-
-/*
- * usbvideo_StopDataPump()
- *
- * This procedure stops streaming and deallocates URBs. Then it
- * activates zero-bandwidth alt. setting of the video interface.
- *
- * History:
- * 22-Jan-2000 Corrected order of actions to work after surprise removal.
- * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values.
- */
-static void usbvideo_StopDataPump(struct uvd *uvd)
-{
-       int i, j;
-
-       if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
-               return;
-
-       if (uvd->debug > 1)
-               dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
-
-       /* Unschedule all of the iso td's */
-       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-               usb_kill_urb(uvd->sbuf[i].urb);
-       }
-       if (uvd->debug > 1)
-               dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__);
-       uvd->streaming = 0;
-
-       if (!uvd->remove_pending) {
-               /* Invoke minidriver's magic to stop the camera */
-               if (VALID_CALLBACK(uvd, videoStop))
-                       GET_CALLBACK(uvd, videoStop)(uvd);
-               else
-                       err("%s: videoStop not set", __func__);
-
-               /* Set packet size to 0 */
-               j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
-               if (j < 0) {
-                       err("%s: usb_set_interface() error %d.", __func__, j);
-                       uvd->last_error = j;
-               }
-       }
-}
-
-/*
- * usbvideo_NewFrame()
- *
- * History:
- * 29-Mar-00 Added copying of previous frame into the current one.
- * 6-Aug-00  Added model 3 video sizes, removed redundant width, height.
- */
-static int usbvideo_NewFrame(struct uvd *uvd, int framenum)
-{
-       struct usbvideo_frame *frame;
-       int n;
-
-       if (uvd->debug > 1)
-               dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd,
-                        framenum);
-
-       /* If we're not grabbing a frame right now and the other frame is */
-       /*  ready to be grabbed into, then use it instead */
-       if (uvd->curframe != -1)
-               return 0;
-
-       /* If necessary we adjust picture settings between frames */
-       if (!uvd->settingsAdjusted) {
-               if (VALID_CALLBACK(uvd, adjustPicture))
-                       GET_CALLBACK(uvd, adjustPicture)(uvd);
-               uvd->settingsAdjusted = 1;
-       }
-
-       n = (framenum + 1) % USBVIDEO_NUMFRAMES;
-       if (uvd->frame[n].frameState == FrameState_Ready)
-               framenum = n;
-
-       frame = &uvd->frame[framenum];
-
-       frame->frameState = FrameState_Grabbing;
-       frame->scanstate = ScanState_Scanning;
-       frame->seqRead_Length = 0;      /* Accumulated in xxx_parse_data() */
-       frame->deinterlace = Deinterlace_None;
-       frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */
-       uvd->curframe = framenum;
-
-       /*
-        * Normally we would want to copy previous frame into the current one
-        * before we even start filling it with data; this allows us to stop
-        * filling at any moment; top portion of the frame will be new and
-        * bottom portion will stay as it was in previous frame. If we don't
-        * do that then missing chunks of video stream will result in flickering
-        * portions of old data whatever it was before.
-        *
-        * If we choose not to copy previous frame (to, for example, save few
-        * bus cycles - the frame can be pretty large!) then we have an option
-        * to clear the frame before using. If we experience losses in this
-        * mode then missing picture will be black (no flickering).
-        *
-        * Finally, if user chooses not to clean the current frame before
-        * filling it with data then the old data will be visible if we fail
-        * to refill entire frame with new data.
-        */
-       if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) {
-               /* This copies previous frame into this one to mask losses */
-               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 */
-                       memset(frame->data, 0, uvd->max_frame_size);
-               }
-       }
-       return 0;
-}
-
-/*
- * usbvideo_CollectRawData()
- *
- * This procedure can be used instead of 'processData' callback if you
- * only want to dump the raw data from the camera into the output
- * device (frame buffer). You can look at it with V4L client, but the
- * image will be unwatchable. The main purpose of this code and of the
- * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from
- * new, unknown cameras. This procedure will be automatically invoked
- * instead of the specified callback handler when uvd->flags has bit
- * FLAGS_NO_DECODING set. Therefore, any regular build of any driver
- * based on usbvideo can use this feature at any time.
- */
-static void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame)
-{
-       int n;
-
-       assert(uvd != NULL);
-       assert(frame != NULL);
-
-       /* Try to move data from queue into frame buffer */
-       n = RingQueue_GetLength(&uvd->dp);
-       if (n > 0) {
-               int m;
-               /* See how much space we have left */
-               m = uvd->max_frame_size - frame->seqRead_Length;
-               if (n > m)
-                       n = m;
-               /* Now move that much data into frame buffer */
-               RingQueue_Dequeue(
-                       &uvd->dp,
-                       frame->data + frame->seqRead_Length,
-                       m);
-               frame->seqRead_Length += m;
-       }
-       /* See if we filled the frame */
-       if (frame->seqRead_Length >= uvd->max_frame_size) {
-               frame->frameState = FrameState_Done;
-               uvd->curframe = -1;
-               uvd->stats.frame_num++;
-       }
-}
-
-static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
-{
-       struct usbvideo_frame *frame = &uvd->frame[frameNum];
-
-       if (uvd->debug >= 2)
-               dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd,
-                        frameNum);
-
-       switch (frame->frameState) {
-       case FrameState_Unused:
-               if (uvd->debug >= 2)
-                       dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n",
-                                __func__);
-               return -EINVAL;
-       case FrameState_Ready:
-       case FrameState_Grabbing:
-       case FrameState_Error:
-       {
-               int ntries, signalPending;
-       redo:
-               if (!CAMERA_IS_OPERATIONAL(uvd)) {
-                       if (uvd->debug >= 2)
-                               dev_info(&uvd->dev->dev,
-                                        "%s: Camera is not operational (1)\n",
-                                        __func__);
-                       return -EIO;
-               }
-               ntries = 0;
-               do {
-                       RingQueue_InterruptibleSleepOn(&uvd->dp);
-                       signalPending = signal_pending(current);
-                       if (!CAMERA_IS_OPERATIONAL(uvd)) {
-                               if (uvd->debug >= 2)
-                                       dev_info(&uvd->dev->dev,
-                                                "%s: Camera is not "
-                                                "operational (2)\n", __func__);
-                               return -EIO;
-                       }
-                       assert(uvd->fbuf != NULL);
-                       if (signalPending) {
-                               if (uvd->debug >= 2)
-                                       dev_info(&uvd->dev->dev,
-                                       "%s: Signal=$%08x\n", __func__,
-                                       signalPending);
-                               if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
-                                       usbvideo_TestPattern(uvd, 1, 0);
-                                       uvd->curframe = -1;
-                                       uvd->stats.frame_num++;
-                                       if (uvd->debug >= 2)
-                                               dev_info(&uvd->dev->dev,
-                                                        "%s: Forced test "
-                                                        "pattern screen\n",
-                                                        __func__);
-                                       return 0;
-                               } else {
-                                       /* Standard answer: Interrupted! */
-                                       if (uvd->debug >= 2)
-                                               dev_info(&uvd->dev->dev,
-                                                        "%s: Interrupted!\n",
-                                                        __func__);
-                                       return -EINTR;
-                               }
-                       } else {
-                               /* No signals - we just got new data in dp queue */
-                               if (uvd->flags & FLAGS_NO_DECODING)
-                                       usbvideo_CollectRawData(uvd, frame);
-                               else if (VALID_CALLBACK(uvd, processData))
-                                       GET_CALLBACK(uvd, processData)(uvd, frame);
-                               else
-                                       err("%s: processData not set", __func__);
-                       }
-               } while (frame->frameState == FrameState_Grabbing);
-               if (uvd->debug >= 2) {
-                       dev_info(&uvd->dev->dev,
-                                "%s: Grabbing done; state=%d. (%lu. bytes)\n",
-                                __func__, frame->frameState,
-                                frame->seqRead_Length);
-               }
-               if (frame->frameState == FrameState_Error) {
-                       int ret = usbvideo_NewFrame(uvd, frameNum);
-                       if (ret < 0) {
-                               err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret);
-                               return ret;
-                       }
-                       goto redo;
-               }
-               /* Note that we fall through to meet our destiny below */
-       }
-       case FrameState_Done:
-               /*
-                * Do all necessary postprocessing of data prepared in
-                * "interrupt" code and the collecting code above. The
-                * frame gets marked as FrameState_Done by queue parsing code.
-                * This status means that we collected enough data and
-                * most likely processed it as we went through. However
-                * the data may need postprocessing, such as deinterlacing
-                * or picture adjustments implemented in software (horror!)
-                *
-                * As soon as the frame becomes "final" it gets promoted to
-                * FrameState_Done_Hold status where it will remain until the
-                * caller consumed all the video data from the frame. Then
-                * the empty shell of ex-frame is thrown out for dogs to eat.
-                * But we, worried about pets, will recycle the frame!
-                */
-               uvd->stats.frame_num++;
-               if ((uvd->flags & FLAGS_NO_DECODING) == 0) {
-                       if (VALID_CALLBACK(uvd, postProcess))
-                               GET_CALLBACK(uvd, postProcess)(uvd, frame);
-                       if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST)
-                               usbvideo_SoftwareContrastAdjustment(uvd, frame);
-               }
-               frame->frameState = FrameState_Done_Hold;
-               if (uvd->debug >= 2)
-                       dev_info(&uvd->dev->dev,
-                                "%s: Entered FrameState_Done_Hold state.\n",
-                                __func__);
-               return 0;
-
-       case FrameState_Done_Hold:
-               /*
-                * We stay in this state indefinitely until someone external,
-                * like ioctl() or read() call finishes digesting the frame
-                * data. Then it will mark the frame as FrameState_Unused and
-                * it will be released back into the wild to roam freely.
-                */
-               if (uvd->debug >= 2)
-                       dev_info(&uvd->dev->dev,
-                                "%s: FrameState_Done_Hold state.\n",
-                                __func__);
-               return 0;
-       }
-
-       /* Catch-all for other cases. We shall not be here. */
-       err("%s: Invalid state %d.", __func__, frame->frameState);
-       frame->frameState = FrameState_Unused;
-       return 0;
-}
-
-/*
- * usbvideo_DeinterlaceFrame()
- *
- * This procedure deinterlaces the given frame. Some cameras produce
- * only half of scanlines - sometimes only even lines, sometimes only
- * odd lines. The deinterlacing method is stored in frame->deinterlace
- * variable.
- *
- * Here we scan the frame vertically and replace missing scanlines with
- * average between surrounding ones - before and after. If we have no
- * line above then we just copy next line. Similarly, if we need to
- * create a last line then preceding line is used.
- */
-void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame)
-{
-       if ((uvd == NULL) || (frame == NULL))
-               return;
-
-       if ((frame->deinterlace == Deinterlace_FillEvenLines) ||
-           (frame->deinterlace == Deinterlace_FillOddLines))
-       {
-               const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-               int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1;
-
-               for (; i < VIDEOSIZE_Y(frame->request); i += 2) {
-                       const unsigned char *fs1, *fs2;
-                       unsigned char *fd;
-                       int ip, in, j;  /* Previous and next lines */
-
-                       /*
-                        * Need to average lines before and after 'i'.
-                        * If we go out of bounds seeking those lines then
-                        * we point back to existing line.
-                        */
-                       ip = i - 1;     /* First, get rough numbers */
-                       in = i + 1;
-
-                       /* Now validate */
-                       if (ip < 0)
-                               ip = in;
-                       if (in >= VIDEOSIZE_Y(frame->request))
-                               in = ip;
-
-                       /* Sanity check */
-                       if ((ip < 0) || (in < 0) ||
-                           (ip >= VIDEOSIZE_Y(frame->request)) ||
-                           (in >= VIDEOSIZE_Y(frame->request)))
-                       {
-                               err("Error: ip=%d. in=%d. req.height=%ld.",
-                                   ip, in, VIDEOSIZE_Y(frame->request));
-                               break;
-                       }
-
-                       /* Now we need to average lines 'ip' and 'in' to produce line 'i' */
-                       fs1 = frame->data + (v4l_linesize * ip);
-                       fs2 = frame->data + (v4l_linesize * in);
-                       fd = frame->data + (v4l_linesize * i);
-
-                       /* Average lines around destination */
-                       for (j=0; j < v4l_linesize; j++) {
-                               fd[j] = (unsigned char)((((unsigned) fs1[j]) +
-                                                        ((unsigned)fs2[j])) >> 1);
-                       }
-               }
-       }
-
-       /* Optionally display statistics on the screen */
-       if (uvd->flags & FLAGS_OVERLAY_STATS)
-               usbvideo_OverlayStats(uvd, frame);
-}
-
-EXPORT_SYMBOL(usbvideo_DeinterlaceFrame);
-
-/*
- * usbvideo_SoftwareContrastAdjustment()
- *
- * This code adjusts the contrast of the frame, assuming RGB24 format.
- * As most software image processing, this job is CPU-intensive.
- * Get a camera that supports hardware adjustment!
- *
- * History:
- * 09-Feb-2001  Created.
- */
-static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
-                                               struct usbvideo_frame *frame)
-{
-       int i, j, v4l_linesize;
-       signed long adj;
-       const int ccm = 128; /* Color correction median - see below */
-
-       if ((uvd == NULL) || (frame == NULL)) {
-               err("%s: Illegal call.", __func__);
-               return;
-       }
-       adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
-       RESTRICT_TO_RANGE(adj, -ccm, ccm+1);
-       if (adj == 0) {
-               /* In rare case of no adjustment */
-               return;
-       }
-       v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-       for (i=0; i < VIDEOSIZE_Y(frame->request); i++) {
-               unsigned char *fd = frame->data + (v4l_linesize * i);
-               for (j=0; j < v4l_linesize; j++) {
-                       signed long v = (signed long) fd[j];
-                       /* Magnify up to 2 times, reduce down to zero */
-                       v = 128 + ((ccm + adj) * (v - 128)) / ccm;
-                       RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */
-                       fd[j] = (unsigned char) v;
-               }
-       }
-}
-
-MODULE_LICENSE("GPL");
 
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef usbvideo_h
-#define        usbvideo_h
-
-#include "videodev.h"
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-
-/* Most helpful debugging aid */
-#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
-
-#define USBVIDEO_REPORT_STATS  1       /* Set to 0 to block statistics on close */
-
-/* Bit flags (options) */
-#define FLAGS_RETRY_VIDIOCSYNC         (1 << 0)
-#define        FLAGS_MONOCHROME                (1 << 1)
-#define FLAGS_DISPLAY_HINTS            (1 << 2)
-#define FLAGS_OVERLAY_STATS            (1 << 3)
-#define FLAGS_FORCE_TESTPATTERN                (1 << 4)
-#define FLAGS_SEPARATE_FRAMES          (1 << 5)
-#define FLAGS_CLEAN_FRAMES             (1 << 6)
-#define        FLAGS_NO_DECODING               (1 << 7)
-
-/* Bit flags for frames (apply to the frame where they are specified) */
-#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST  (1 << 0)
-
-/* Camera capabilities (maximum) */
-#define CAMERA_URB_FRAMES       32
-#define CAMERA_MAX_ISO_PACKET   1023 /* 1022 actually sent by camera */
-#define FRAMES_PER_DESC                (CAMERA_URB_FRAMES)
-#define FRAME_SIZE_PER_DESC    (CAMERA_MAX_ISO_PACKET)
-
-/* This macro restricts an int variable to an inclusive range */
-#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
-
-#define V4L_BYTES_PER_PIXEL     3      /* Because we produce RGB24 */
-
-/*
- * Use this macro to construct constants for different video sizes.
- * We have to deal with different video sizes that have to be
- * configured in the device or compared against when we receive
- * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y
- * #defines and that's the end of story. However this solution
- * does not allow to convert between real pixel sizes and the
- * constant (integer) value that may be used to tag a frame or
- * whatever. The set of macros below constructs videosize constants
- * from the pixel size and allows to reconstruct the pixel size
- * from the combined value later.
- */
-#define        VIDEOSIZE(x,y)  (((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16))
-#define        VIDEOSIZE_X(vs) ((vs) & 0xFFFFL)
-#define        VIDEOSIZE_Y(vs) (((vs) >> 16) & 0xFFFFL)
-typedef unsigned long videosize_t;
-
-/*
- * This macro checks if the camera is still operational. The 'uvd'
- * pointer must be valid, uvd->dev must be valid, we are not
- * removing the device and the device has not erred on us.
- */
-#define CAMERA_IS_OPERATIONAL(uvd) (\
-       (uvd != NULL) && \
-       ((uvd)->dev != NULL) && \
-       ((uvd)->last_error == 0) && \
-       (!(uvd)->remove_pending))
-
-/*
- * We use macros to do YUV -> RGB conversion because this is
- * very important for speed and totally unimportant for size.
- *
- * YUV -> RGB Conversion
- * ---------------------
- *
- * B = 1.164*(Y-16)                + 2.018*(V-128)
- * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
- * R = 1.164*(Y-16) + 1.596*(U-128)
- *
- * If you fancy integer arithmetics (as you should), hear this:
- *
- * 65536*B = 76284*(Y-16)                + 132252*(V-128)
- * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
- * 65536*R = 76284*(Y-16) + 104595*(U-128)
- *
- * Make sure the output values are within [0..255] range.
- */
-#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
-#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
-    int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
-    mm_y = (my) - 16;  \
-    mm_u = (mu) - 128; \
-    mm_v = (mv) - 128; \
-    mm_yc= mm_y * 76284; \
-    mm_b = (mm_yc              + 132252*mm_v   ) >> 16; \
-    mm_g = (mm_yc -  53281*mm_u -  25625*mm_v  ) >> 16; \
-    mm_r = (mm_yc + 104595*mm_u                        ) >> 16; \
-    mb = LIMIT_RGB(mm_b); \
-    mg = LIMIT_RGB(mm_g); \
-    mr = LIMIT_RGB(mm_r); \
-}
-
-#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-1)])
-
-struct RingQueue {
-       unsigned char *queue;   /* Data from the Isoc data pump */
-       int length;             /* How many bytes allocated for the queue */
-       int wi;                 /* That's where we write */
-       int ri;                 /* Read from here until you hit write index */
-       wait_queue_head_t wqh;  /* Processes waiting */
-};
-
-enum ScanState {
-       ScanState_Scanning,     /* Scanning for header */
-       ScanState_Lines         /* Parsing lines */
-};
-
-/* Completion states of the data parser */
-enum ParseState {
-       scan_Continue,          /* Just parse next item */
-       scan_NextFrame,         /* Frame done, send it to V4L */
-       scan_Out,               /* Not enough data for frame */
-       scan_EndParse           /* End parsing */
-};
-
-enum FrameState {
-       FrameState_Unused,      /* Unused (no MCAPTURE) */
-       FrameState_Ready,       /* Ready to start grabbing */
-       FrameState_Grabbing,    /* In the process of being grabbed into */
-       FrameState_Done,        /* Finished grabbing, but not been synced yet */
-       FrameState_Done_Hold,   /* Are syncing or reading */
-       FrameState_Error,       /* Something bad happened while processing */
-};
-
-/*
- * Some frames may contain only even or odd lines. This type
- * specifies what type of deinterlacing is required.
- */
-enum Deinterlace {
-       Deinterlace_None=0,
-       Deinterlace_FillOddLines,
-       Deinterlace_FillEvenLines
-};
-
-#define USBVIDEO_NUMFRAMES     2       /* How many frames we work with */
-#define USBVIDEO_NUMSBUF       2       /* How many URBs linked in a ring */
-
-/* This structure represents one Isoc request - URB and buffer */
-struct usbvideo_sbuf {
-       char *data;
-       struct urb *urb;
-};
-
-struct usbvideo_frame {
-       char *data;             /* Frame buffer */
-       unsigned long header;   /* Significant bits from the header */
-
-       videosize_t canvas;     /* The canvas (max. image) allocated */
-       videosize_t request;    /* That's what the application asked for */
-       unsigned short palette; /* The desired format */
-
-       enum FrameState frameState;/* State of grabbing */
-       enum ScanState scanstate;       /* State of scanning */
-       enum Deinterlace deinterlace;
-       int flags;              /* USBVIDEO_FRAME_FLAG_xxx bit flags */
-
-       int curline;            /* Line of frame we're working on */
-
-       long seqRead_Length;    /* Raw data length of frame */
-       long seqRead_Index;     /* Amount of data that has been already read */
-
-       void *user;             /* Additional data that user may need */
-};
-
-/* Statistics that can be overlaid on screen */
-struct usbvideo_statistics {
-       unsigned long frame_num;        /* Sequential number of the frame */
-       unsigned long urb_count;        /* How many URBs we received so far */
-       unsigned long urb_length;       /* Length of last URB */
-       unsigned long data_count;       /* How many bytes we received */
-       unsigned long header_count;     /* How many frame headers we found */
-       unsigned long iso_skip_count;   /* How many empty ISO packets received */
-       unsigned long iso_err_count;    /* How many bad ISO packets received */
-};
-
-struct usbvideo;
-
-struct uvd {
-       struct video_device vdev;       /* Must be the first field! */
-       struct usb_device *dev;
-       struct usbvideo *handle;        /* Points back to the struct usbvideo */
-       void *user_data;                /* Camera-dependent data */
-       int user_size;                  /* Size of that camera-dependent data */
-       int debug;                      /* Debug level for usbvideo */
-       unsigned char iface;            /* Video interface number */
-       unsigned char video_endp;
-       unsigned char ifaceAltActive;
-       unsigned char ifaceAltInactive; /* Alt settings */
-       unsigned long flags;            /* FLAGS_USBVIDEO_xxx */
-       unsigned long paletteBits;      /* Which palettes we accept? */
-       unsigned short defaultPalette;  /* What palette to use for read() */
-       struct mutex lock;
-       int user;               /* user count for exclusive use */
-
-       videosize_t videosize;  /* Current setting */
-       videosize_t canvas;     /* This is the width,height of the V4L canvas */
-       int max_frame_size;     /* Bytes in one video frame */
-
-       int uvd_used;           /* Is this structure in use? */
-       int streaming;          /* Are we streaming Isochronous? */
-       int grabbing;           /* Are we grabbing? */
-       int settingsAdjusted;   /* Have we adjusted contrast etc.? */
-       int last_error;         /* What calamity struck us? */
-
-       char *fbuf;             /* Videodev buffer area */
-       int fbuf_size;          /* Videodev buffer size */
-
-       int curframe;
-       int iso_packet_len;     /* Videomode-dependent, saves bus bandwidth */
-
-       struct RingQueue dp;    /* Isoc data pump */
-       struct usbvideo_frame frame[USBVIDEO_NUMFRAMES];
-       struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF];
-
-       volatile int remove_pending;    /* If set then about to exit */
-
-       struct video_picture vpic, vpic_old;    /* Picture settings */
-       struct video_capability vcap;           /* Video capabilities */
-       struct video_channel vchan;     /* May be used for tuner support */
-       struct usbvideo_statistics stats;
-       char videoName[32];             /* Holds name like "video7" */
-};
-
-/*
- * usbvideo callbacks (virtual methods). They are set when usbvideo
- * services are registered. All of these default to NULL, except those
- * that default to usbvideo-provided methods.
- */
-struct usbvideo_cb {
-       int (*probe)(struct usb_interface *, const struct usb_device_id *);
-       void (*userFree)(struct uvd *);
-       void (*disconnect)(struct usb_interface *);
-       int (*setupOnOpen)(struct uvd *);
-       void (*videoStart)(struct uvd *);
-       void (*videoStop)(struct uvd *);
-       void (*processData)(struct uvd *, struct usbvideo_frame *);
-       void (*postProcess)(struct uvd *, struct usbvideo_frame *);
-       void (*adjustPicture)(struct uvd *);
-       int (*getFPS)(struct uvd *);
-       int (*overlayHook)(struct uvd *, struct usbvideo_frame *);
-       int (*getFrame)(struct uvd *, int);
-       int (*startDataPump)(struct uvd *uvd);
-       void (*stopDataPump)(struct uvd *uvd);
-       int (*setVideoMode)(struct uvd *uvd, struct video_window *vw);
-};
-
-struct usbvideo {
-       int num_cameras;                /* As allocated */
-       struct usb_driver usbdrv;       /* Interface to the USB stack */
-       char drvName[80];               /* Driver name */
-       struct mutex lock;              /* Mutex protecting camera structures */
-       struct usbvideo_cb cb;          /* Table of callbacks (virtual methods) */
-       struct video_device vdt;        /* Video device template */
-       struct uvd *cam;                        /* Array of camera structures */
-       struct module *md_module;       /* Minidriver module */
-};
-
-
-/*
- * This macro retrieves callback address from the struct uvd object.
- * No validity checks are done here, so be sure to check the
- * callback beforehand with VALID_CALLBACK.
- */
-#define        GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName)
-
-/*
- * This macro returns either callback pointer or NULL. This is safe
- * macro, meaning that most of components of data structures involved
- * may be NULL - this only results in NULL being returned. You may
- * wish to use this macro to make sure that the callback is callable.
- * However keep in mind that those checks take time.
- */
-#define        VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \
-               ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL)
-
-int  RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len);
-int  RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n);
-void RingQueue_WakeUpInterruptible(struct RingQueue *rq);
-void RingQueue_Flush(struct RingQueue *rq);
-
-static inline int RingQueue_GetLength(const struct RingQueue *rq)
-{
-       return (rq->wi - rq->ri + rq->length) & (rq->length-1);
-}
-
-static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq)
-{
-       return rq->length - RingQueue_GetLength(rq);
-}
-
-void usbvideo_DrawLine(
-       struct usbvideo_frame *frame,
-       int x1, int y1,
-       int x2, int y2,
-       unsigned char cr, unsigned char cg, unsigned char cb);
-void usbvideo_HexDump(const unsigned char *data, int len);
-void usbvideo_SayAndWait(const char *what);
-void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode);
-
-/* Memory allocation routines */
-unsigned long usbvideo_kvirt_to_pa(unsigned long adr);
-
-int usbvideo_register(
-       struct usbvideo **pCams,
-       const int num_cams,
-       const int num_extra,
-       const char *driverName,
-       const struct usbvideo_cb *cbTable,
-       struct module *md,
-       const struct usb_device_id *id_table);
-struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams);
-int usbvideo_RegisterVideoDevice(struct uvd *uvd);
-void usbvideo_Deregister(struct usbvideo **uvt);
-
-int usbvideo_v4l_initialize(struct video_device *dev);
-
-void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame);
-
-/*
- * This code performs bounds checking - use it when working with
- * new formats, or else you may get oopses all over the place.
- * If pixel falls out of bounds then it gets shoved back (as close
- * to place of offence as possible) and is painted bright red.
- *
- * There are two important concepts: frame width, height and
- * V4L canvas width, height. The former is the area requested by
- * the application -for this very frame-. The latter is the largest
- * possible frame that we can serve (we advertise that via V4L ioctl).
- * The frame data is expected to be formatted as lines of length
- * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines.
- */
-static inline void RGB24_PUTPIXEL(
-       struct usbvideo_frame *fr,
-       int ix, int iy,
-       unsigned char vr,
-       unsigned char vg,
-       unsigned char vb)
-{
-       register unsigned char *pf;
-       int limiter = 0, mx, my;
-       mx = ix;
-       my = iy;
-       if (mx < 0) {
-               mx=0;
-               limiter++;
-       } else if (mx >= VIDEOSIZE_X((fr)->request)) {
-               mx= VIDEOSIZE_X((fr)->request) - 1;
-               limiter++;
-       }
-       if (my < 0) {
-               my = 0;
-               limiter++;
-       } else if (my >= VIDEOSIZE_Y((fr)->request)) {
-               my = VIDEOSIZE_Y((fr)->request) - 1;
-               limiter++;
-       }
-       pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix));
-       if (limiter) {
-               *pf++ = 0;
-               *pf++ = 0;
-               *pf++ = 0xFF;
-       } else {
-               *pf++ = (vb);
-               *pf++ = (vg);
-               *pf++ = (vr);
-       }
-}
-
-#endif /* usbvideo_h */
 
+++ /dev/null
-/*
- * USB ViCam WebCam driver
- * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
- *                    Christopher L Cheney (ccheney@cheney.cx),
- *                    Pavel Machek (pavel@ucw.cz),
- *                    John Tyner (jtyner@cs.ucr.edu),
- *                    Monroe Williams (monroe@pobox.com)
- *
- * Supports 3COM HomeConnect PC Digital WebCam
- * Supports Compro PS39U WebCam
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * This source code is based heavily on the CPiA webcam driver which was
- * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt
- *
- * Portions of this code were also copied from usbvideo.c
- *
- * Special thanks to the whole team at Sourceforge for help making
- * this driver become a reality.  Notably:
- * Andy Armstrong who reverse engineered the color encoding and
- * Pavel Machek and Chris Cheney who worked on reverse engineering the
- *    camera controls and wrote the first generation driver.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include "videodev.h"
-#include <linux/usb.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-#include <linux/ihex.h>
-#include "usbvideo.h"
-
-// #define VICAM_DEBUG
-
-#ifdef VICAM_DEBUG
-#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
-#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
-#else
-#define DBG(fmn,args...) do {} while(0)
-#endif
-
-#define DRIVER_AUTHOR           "Joe Burks, jburks@wavicle.org"
-#define DRIVER_DESC             "ViCam WebCam Driver"
-
-/* Define these values to match your device */
-#define USB_VICAM_VENDOR_ID    0x04c1
-#define USB_VICAM_PRODUCT_ID   0x009d
-#define USB_COMPRO_VENDOR_ID   0x0602
-#define USB_COMPRO_PRODUCT_ID  0x1001
-
-#define VICAM_BYTES_PER_PIXEL   3
-#define VICAM_MAX_READ_SIZE     (512*242+128)
-#define VICAM_MAX_FRAME_SIZE    (VICAM_BYTES_PER_PIXEL*320*240)
-#define VICAM_FRAMES            2
-
-#define VICAM_HEADER_SIZE       64
-
-/* rvmalloc / rvfree copied from usbvideo.c
- *
- * Not sure why these are not yet non-statics which I can reference through
- * usbvideo.h the same as it is in 2.4.20.  I bet this will get fixed sometime
- * in the future.
- *
-*/
-static void *rvmalloc(unsigned long size)
-{
-       void *mem;
-       unsigned long adr;
-
-       size = PAGE_ALIGN(size);
-       mem = vmalloc_32(size);
-       if (!mem)
-               return NULL;
-
-       memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-       adr = (unsigned long) mem;
-       while (size > 0) {
-               SetPageReserved(vmalloc_to_page((void *)adr));
-               adr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-       unsigned long adr;
-
-       if (!mem)
-               return;
-
-       adr = (unsigned long) mem;
-       while ((long) size > 0) {
-               ClearPageReserved(vmalloc_to_page((void *)adr));
-               adr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       vfree(mem);
-}
-
-struct vicam_camera {
-       u16 shutter_speed;      // capture shutter speed
-       u16 gain;               // capture gain
-
-       u8 *raw_image;          // raw data captured from the camera
-       u8 *framebuf;           // processed data in RGB24 format
-       u8 *cntrlbuf;           // area used to send control msgs
-
-       struct video_device vdev;       // v4l video device
-       struct usb_device *udev;        // usb device
-
-       /* guard against simultaneous accesses to the camera */
-       struct mutex cam_lock;
-
-       int is_initialized;
-       u8 open_count;
-       u8 bulkEndpoint;
-       int needsDummyRead;
-};
-
-static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
-static void vicam_disconnect(struct usb_interface *intf);
-static void read_frame(struct vicam_camera *cam, int framenum);
-static void vicam_decode_color(const u8 *, u8 *);
-
-static int __send_control_msg(struct vicam_camera *cam,
-                             u8 request,
-                             u16 value,
-                             u16 index,
-                             unsigned char *cp,
-                             u16 size)
-{
-       int status;
-
-       /* cp must be memory that has been allocated by kmalloc */
-
-       status = usb_control_msg(cam->udev,
-                                usb_sndctrlpipe(cam->udev, 0),
-                                request,
-                                USB_DIR_OUT | USB_TYPE_VENDOR |
-                                USB_RECIP_DEVICE, value, index,
-                                cp, size, 1000);
-
-       status = min(status, 0);
-
-       if (status < 0) {
-               printk(KERN_INFO "Failed sending control message, error %d.\n",
-                      status);
-       }
-
-       return status;
-}
-
-static int send_control_msg(struct vicam_camera *cam,
-                           u8 request,
-                           u16 value,
-                           u16 index,
-                           unsigned char *cp,
-                           u16 size)
-{
-       int status = -ENODEV;
-       mutex_lock(&cam->cam_lock);
-       if (cam->udev) {
-               status = __send_control_msg(cam, request, value,
-                                           index, cp, size);
-       }
-       mutex_unlock(&cam->cam_lock);
-       return status;
-}
-static int
-initialize_camera(struct vicam_camera *cam)
-{
-       int err;
-       const struct ihex_binrec *rec;
-       const struct firmware *uninitialized_var(fw);
-
-       err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev);
-       if (err) {
-               printk(KERN_ERR "Failed to load \"vicam/firmware.fw\": %d\n",
-                      err);
-               return err;
-       }
-
-       for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
-               memcpy(cam->cntrlbuf, rec->data, be16_to_cpu(rec->len));
-
-               err = send_control_msg(cam, 0xff, 0, 0,
-                                      cam->cntrlbuf, be16_to_cpu(rec->len));
-               if (err)
-                       break;
-       }
-
-       release_firmware(fw);
-
-       return err;
-}
-
-static int
-set_camera_power(struct vicam_camera *cam, int state)
-{
-       int status;
-
-       if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
-               return status;
-
-       if (state) {
-               send_control_msg(cam, 0x55, 1, 0, NULL, 0);
-       }
-
-       return 0;
-}
-
-static long
-vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
-{
-       void __user *user_arg = (void __user *)arg;
-       struct vicam_camera *cam = file->private_data;
-       long retval = 0;
-
-       if (!cam)
-               return -ENODEV;
-
-       switch (ioctlnr) {
-               /* query capabilities */
-       case VIDIOCGCAP:
-               {
-                       struct video_capability b;
-
-                       DBG("VIDIOCGCAP\n");
-                       memset(&b, 0, sizeof(b));
-                       strcpy(b.name, "ViCam-based Camera");
-                       b.type = VID_TYPE_CAPTURE;
-                       b.channels = 1;
-                       b.audios = 0;
-                       b.maxwidth = 320;       /* VIDEOSIZE_CIF */
-                       b.maxheight = 240;
-                       b.minwidth = 320;       /* VIDEOSIZE_48_48 */
-                       b.minheight = 240;
-
-                       if (copy_to_user(user_arg, &b, sizeof(b)))
-                               retval = -EFAULT;
-
-                       break;
-               }
-               /* get/set video source - we are a camera and nothing else */
-       case VIDIOCGCHAN:
-               {
-                       struct video_channel v;
-
-                       DBG("VIDIOCGCHAN\n");
-                       if (copy_from_user(&v, user_arg, sizeof(v))) {
-                               retval = -EFAULT;
-                               break;
-                       }
-                       if (v.channel != 0) {
-                               retval = -EINVAL;
-                               break;
-                       }
-
-                       v.channel = 0;
-                       strcpy(v.name, "Camera");
-                       v.tuners = 0;
-                       v.flags = 0;
-                       v.type = VIDEO_TYPE_CAMERA;
-                       v.norm = 0;
-
-                       if (copy_to_user(user_arg, &v, sizeof(v)))
-                               retval = -EFAULT;
-                       break;
-               }
-
-       case VIDIOCSCHAN:
-               {
-                       int v;
-
-                       if (copy_from_user(&v, user_arg, sizeof(v)))
-                               retval = -EFAULT;
-                       DBG("VIDIOCSCHAN %d\n", v);
-
-                       if (retval == 0 && v != 0)
-                               retval = -EINVAL;
-
-                       break;
-               }
-
-               /* image properties */
-       case VIDIOCGPICT:
-               {
-                       struct video_picture vp;
-                       DBG("VIDIOCGPICT\n");
-                       memset(&vp, 0, sizeof (struct video_picture));
-                       vp.brightness = cam->gain << 8;
-                       vp.depth = 24;
-                       vp.palette = VIDEO_PALETTE_RGB24;
-                       if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
-                               retval = -EFAULT;
-                       break;
-               }
-
-       case VIDIOCSPICT:
-               {
-                       struct video_picture vp;
-
-                       if (copy_from_user(&vp, user_arg, sizeof(vp))) {
-                               retval = -EFAULT;
-                               break;
-                       }
-
-                       DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
-                           vp.palette);
-
-                       cam->gain = vp.brightness >> 8;
-
-                       if (vp.depth != 24
-                           || vp.palette != VIDEO_PALETTE_RGB24)
-                               retval = -EINVAL;
-
-                       break;
-               }
-
-               /* get/set capture window */
-       case VIDIOCGWIN:
-               {
-                       struct video_window vw;
-                       vw.x = 0;
-                       vw.y = 0;
-                       vw.width = 320;
-                       vw.height = 240;
-                       vw.chromakey = 0;
-                       vw.flags = 0;
-                       vw.clips = NULL;
-                       vw.clipcount = 0;
-
-                       DBG("VIDIOCGWIN\n");
-
-                       if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
-                               retval = -EFAULT;
-
-                       // I'm not sure what the deal with a capture window is, it is very poorly described
-                       // in the doc.  So I won't support it now.
-                       break;
-               }
-
-       case VIDIOCSWIN:
-               {
-
-                       struct video_window vw;
-
-                       if (copy_from_user(&vw, user_arg, sizeof(vw))) {
-                               retval = -EFAULT;
-                               break;
-                       }
-
-                       DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
-
-                       if ( vw.width != 320 || vw.height != 240 )
-                               retval = -EFAULT;
-
-                       break;
-               }
-
-               /* mmap interface */
-       case VIDIOCGMBUF:
-               {
-                       struct video_mbuf vm;
-                       int i;
-
-                       DBG("VIDIOCGMBUF\n");
-                       memset(&vm, 0, sizeof (vm));
-                       vm.size =
-                           VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
-                       vm.frames = VICAM_FRAMES;
-                       for (i = 0; i < VICAM_FRAMES; i++)
-                               vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
-
-                       if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))
-                               retval = -EFAULT;
-
-                       break;
-               }
-
-       case VIDIOCMCAPTURE:
-               {
-                       struct video_mmap vm;
-                       // int video_size;
-
-                       if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
-                               retval = -EFAULT;
-                               break;
-                       }
-
-                       DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
-
-                       if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
-                               retval = -EINVAL;
-
-                       // in theory right here we'd start the image capturing
-                       // (fill in a bulk urb and submit it asynchronously)
-                       //
-                       // Instead we're going to do a total hack job for now and
-                       // retrieve the frame in VIDIOCSYNC
-
-                       break;
-               }
-
-       case VIDIOCSYNC:
-               {
-                       int frame;
-
-                       if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {
-                               retval = -EFAULT;
-                               break;
-                       }
-                       DBG("VIDIOCSYNC: %d\n", frame);
-
-                       read_frame(cam, frame);
-                       vicam_decode_color(cam->raw_image,
-                                          cam->framebuf +
-                                          frame * VICAM_MAX_FRAME_SIZE );
-
-                       break;
-               }
-
-               /* pointless to implement overlay with this camera */
-       case VIDIOCCAPTURE:
-       case VIDIOCGFBUF:
-       case VIDIOCSFBUF:
-       case VIDIOCKEY:
-               retval = -EINVAL;
-               break;
-
-               /* tuner interface - we have none */
-       case VIDIOCGTUNER:
-       case VIDIOCSTUNER:
-       case VIDIOCGFREQ:
-       case VIDIOCSFREQ:
-               retval = -EINVAL;
-               break;
-
-               /* audio interface - we have none */
-       case VIDIOCGAUDIO:
-       case VIDIOCSAUDIO:
-               retval = -EINVAL;
-               break;
-       default:
-               retval = -ENOIOCTLCMD;
-               break;
-       }
-
-       return retval;
-}
-
-static int
-vicam_open(struct file *file)
-{
-       struct vicam_camera *cam = video_drvdata(file);
-
-       DBG("open\n");
-
-       if (!cam) {
-               printk(KERN_ERR
-                      "vicam video_device improperly initialized");
-               return -EINVAL;
-       }
-
-       /* cam_lock/open_count protects us from simultaneous opens
-        * ... for now. we probably shouldn't rely on this fact forever.
-        */
-
-       mutex_lock(&cam->cam_lock);
-       if (cam->open_count > 0) {
-               printk(KERN_INFO
-                      "vicam_open called on already opened camera");
-               mutex_unlock(&cam->cam_lock);
-               return -EBUSY;
-       }
-
-       cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
-       if (!cam->raw_image) {
-               mutex_unlock(&cam->cam_lock);
-               return -ENOMEM;
-       }
-
-       cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
-       if (!cam->framebuf) {
-               kfree(cam->raw_image);
-               mutex_unlock(&cam->cam_lock);
-               return -ENOMEM;
-       }
-
-       cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!cam->cntrlbuf) {
-               kfree(cam->raw_image);
-               rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
-               mutex_unlock(&cam->cam_lock);
-               return -ENOMEM;
-       }
-
-       cam->needsDummyRead = 1;
-       cam->open_count++;
-
-       file->private_data = cam;
-       mutex_unlock(&cam->cam_lock);
-
-
-       // First upload firmware, then turn the camera on
-
-       if (!cam->is_initialized) {
-               initialize_camera(cam);
-
-               cam->is_initialized = 1;
-       }
-
-       set_camera_power(cam, 1);
-
-       return 0;
-}
-
-static int
-vicam_close(struct file *file)
-{
-       struct vicam_camera *cam = file->private_data;
-       int open_count;
-       struct usb_device *udev;
-
-       DBG("close\n");
-
-       /* it's not the end of the world if
-        * we fail to turn the camera off.
-        */
-
-       set_camera_power(cam, 0);
-
-       kfree(cam->raw_image);
-       rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
-       kfree(cam->cntrlbuf);
-
-       mutex_lock(&cam->cam_lock);
-
-       cam->open_count--;
-       open_count = cam->open_count;
-       udev = cam->udev;
-
-       mutex_unlock(&cam->cam_lock);
-
-       if (!open_count && !udev) {
-               kfree(cam);
-       }
-
-       return 0;
-}
-
-static void vicam_decode_color(const u8 *data, u8 *rgb)
-{
-       /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
-        * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
-        */
-
-       int i, prevY, nextY;
-
-       prevY = 512;
-       nextY = 512;
-
-       data += VICAM_HEADER_SIZE;
-
-       for( i = 0; i < 240; i++, data += 512 ) {
-               const int y = ( i * 242 ) / 240;
-
-               int j, prevX, nextX;
-               int Y, Cr, Cb;
-
-               if ( y == 242 - 1 ) {
-                       nextY = -512;
-               }
-
-               prevX = 1;
-               nextX = 1;
-
-               for ( j = 0; j < 320; j++, rgb += 3 ) {
-                       const int x = ( j * 512 ) / 320;
-                       const u8 * const src = &data[x];
-
-                       if ( x == 512 - 1 ) {
-                               nextX = -1;
-                       }
-
-                       Cr = ( src[prevX] - src[0] ) +
-                               ( src[nextX] - src[0] );
-                       Cr /= 2;
-
-                       Cb = ( src[prevY] - src[prevX + prevY] ) +
-                               ( src[prevY] - src[nextX + prevY] ) +
-                               ( src[nextY] - src[prevX + nextY] ) +
-                               ( src[nextY] - src[nextX + nextY] );
-                       Cb /= 4;
-
-                       Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
-
-                       if ( i & 1 ) {
-                               int Ct = Cr;
-                               Cr = Cb;
-                               Cb = Ct;
-                       }
-
-                       if ( ( x ^ i ) & 1 ) {
-                               Cr = -Cr;
-                               Cb = -Cb;
-                       }
-
-                       rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
-                                       500 ) / 900, 0, 255 );
-                       rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
-                                         ( 813 * Cr ) ) +
-                                         500 ) / 1000, 0, 255 );
-                       rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
-                                       500 ) / 1300, 0, 255 );
-
-                       prevX = -1;
-               }
-
-               prevY = -512;
-       }
-}
-
-static void
-read_frame(struct vicam_camera *cam, int framenum)
-{
-       unsigned char *request = cam->cntrlbuf;
-       int realShutter;
-       int n;
-       int actual_length;
-
-       if (cam->needsDummyRead) {
-               cam->needsDummyRead = 0;
-               read_frame(cam, framenum);
-       }
-
-       memset(request, 0, 16);
-       request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
-
-       request[1] = 0; // 512x242 capture
-
-       request[2] = 0x90;      // the function of these two bytes
-       request[3] = 0x07;      // is not yet understood
-
-       if (cam->shutter_speed > 60) {
-               // Short exposure
-               realShutter =
-                   ((-15631900 / cam->shutter_speed) + 260533) / 1000;
-               request[4] = realShutter & 0xFF;
-               request[5] = (realShutter >> 8) & 0xFF;
-               request[6] = 0x03;
-               request[7] = 0x01;
-       } else {
-               // Long exposure
-               realShutter = 15600 / cam->shutter_speed - 1;
-               request[4] = 0;
-               request[5] = 0;
-               request[6] = realShutter & 0xFF;
-               request[7] = realShutter >> 8;
-       }
-
-       // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
-       request[8] = 0;
-       // bytes 9-15 do not seem to affect exposure or image quality
-
-       mutex_lock(&cam->cam_lock);
-
-       if (!cam->udev) {
-               goto done;
-       }
-
-       n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
-
-       if (n < 0) {
-               printk(KERN_ERR
-                      " Problem sending frame capture control message");
-               goto done;
-       }
-
-       n = usb_bulk_msg(cam->udev,
-                        usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
-                        cam->raw_image,
-                        512 * 242 + 128, &actual_length, 10000);
-
-       if (n < 0) {
-               printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
-                      n);
-       }
-
- done:
-       mutex_unlock(&cam->cam_lock);
-}
-
-static ssize_t
-vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
-{
-       struct vicam_camera *cam = file->private_data;
-
-       DBG("read %d bytes.\n", (int) count);
-
-       if (*ppos >= VICAM_MAX_FRAME_SIZE) {
-               *ppos = 0;
-               return 0;
-       }
-
-       if (*ppos == 0) {
-               read_frame(cam, 0);
-               vicam_decode_color(cam->raw_image,
-                                  cam->framebuf +
-                                  0 * VICAM_MAX_FRAME_SIZE);
-       }
-
-       count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
-
-       if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
-               count = -EFAULT;
-       } else {
-               *ppos += count;
-       }
-
-       if (count == VICAM_MAX_FRAME_SIZE) {
-               *ppos = 0;
-       }
-
-       return count;
-}
-
-
-static int
-vicam_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       // TODO: allocate the raw frame buffer if necessary
-       unsigned long page, pos;
-       unsigned long start = vma->vm_start;
-       unsigned long size  = vma->vm_end-vma->vm_start;
-       struct vicam_camera *cam = file->private_data;
-
-       if (!cam)
-               return -ENODEV;
-
-       DBG("vicam_mmap: %ld\n", size);
-
-       /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
-        * to the size the application requested for mmap and it was screwing apps up.
-        if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
-        return -EINVAL;
-        */
-
-       pos = (unsigned long)cam->framebuf;
-       while (size > 0) {
-               page = vmalloc_to_pfn((void *)pos);
-               if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-                       return -EAGAIN;
-
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               if (size > PAGE_SIZE)
-                       size -= PAGE_SIZE;
-               else
-                       size = 0;
-       }
-
-       return 0;
-}
-
-static const struct v4l2_file_operations vicam_fops = {
-       .owner          = THIS_MODULE,
-       .open           = vicam_open,
-       .release        = vicam_close,
-       .read           = vicam_read,
-       .mmap           = vicam_mmap,
-       .ioctl          = vicam_ioctl,
-};
-
-static struct video_device vicam_template = {
-       .name           = "ViCam-based USB Camera",
-       .fops           = &vicam_fops,
-       .release        = video_device_release_empty,
-};
-
-/* table of devices that work with this driver */
-static struct usb_device_id vicam_table[] = {
-       {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
-       {USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)},
-       {}                      /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, vicam_table);
-
-static struct usb_driver vicam_driver = {
-       .name           = "vicam",
-       .probe          = vicam_probe,
-       .disconnect     = vicam_disconnect,
-       .id_table       = vicam_table
-};
-
-/**
- *     vicam_probe
- *     @intf: the interface
- *     @id: the device id
- *
- *     Called by the usb core when a new device is connected that it thinks
- *     this driver might be interested in.
- */
-static int
-vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
-{
-       struct usb_device *dev = interface_to_usbdev(intf);
-       int bulkEndpoint = 0;
-       const struct usb_host_interface *interface;
-       const struct usb_endpoint_descriptor *endpoint;
-       struct vicam_camera *cam;
-
-       printk(KERN_INFO "ViCam based webcam connected\n");
-
-       interface = intf->cur_altsetting;
-
-       DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
-              interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
-       endpoint = &interface->endpoint[0].desc;
-
-       if (usb_endpoint_is_bulk_in(endpoint)) {
-               /* we found a bulk in endpoint */
-               bulkEndpoint = endpoint->bEndpointAddress;
-       } else {
-               printk(KERN_ERR
-                      "No bulk in endpoint was found ?! (this is bad)\n");
-       }
-
-       if ((cam =
-            kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
-               printk(KERN_WARNING
-                      "could not allocate kernel memory for vicam_camera struct\n");
-               return -ENOMEM;
-       }
-
-
-       cam->shutter_speed = 15;
-
-       mutex_init(&cam->cam_lock);
-
-       memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template));
-       video_set_drvdata(&cam->vdev, cam);
-
-       cam->udev = dev;
-       cam->bulkEndpoint = bulkEndpoint;
-
-       if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) {
-               kfree(cam);
-               printk(KERN_WARNING "video_register_device failed\n");
-               return -EIO;
-       }
-
-       printk(KERN_INFO "ViCam webcam driver now controlling device %s\n",
-               video_device_node_name(&cam->vdev));
-
-       usb_set_intfdata (intf, cam);
-
-       return 0;
-}
-
-static void
-vicam_disconnect(struct usb_interface *intf)
-{
-       int open_count;
-       struct vicam_camera *cam = usb_get_intfdata (intf);
-       usb_set_intfdata (intf, NULL);
-
-       /* we must unregister the device before taking its
-        * cam_lock. This is because the video open call
-        * holds the same lock as video unregister. if we
-        * unregister inside of the cam_lock and open also
-        * uses the cam_lock, we get deadlock.
-        */
-
-       video_unregister_device(&cam->vdev);
-
-       /* stop the camera from being used */
-
-       mutex_lock(&cam->cam_lock);
-
-       /* mark the camera as gone */
-
-       cam->udev = NULL;
-
-       /* the only thing left to do is synchronize with
-        * our close/release function on who should release
-        * the camera memory. if there are any users using the
-        * camera, it's their job. if there are no users,
-        * it's ours.
-        */
-
-       open_count = cam->open_count;
-
-       mutex_unlock(&cam->cam_lock);
-
-       if (!open_count) {
-               kfree(cam);
-       }
-
-       printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
-}
-
-/*
- */
-static int __init
-usb_vicam_init(void)
-{
-       int retval;
-       DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
-       retval = usb_register(&vicam_driver);
-       if (retval)
-               printk(KERN_WARNING "usb_register failed!\n");
-       return retval;
-}
-
-static void __exit
-usb_vicam_exit(void)
-{
-       DBG(KERN_INFO
-              "ViCam-based WebCam driver shutdown\n");
-
-       usb_deregister(&vicam_driver);
-}
-
-module_init(usb_vicam_init);
-module_exit(usb_vicam_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("vicam/firmware.fw");