Forgot to attach the patch; sorry about that. Here it is...

Mark McClelland wrote:
> 
> This is against 2.3.99-pre9-2 + my 1.14 patch.
> 
> SUMMARY:
> o 384x288 and 448x336 modes
> o better /proc/video support
> 
> CHANGES:
> - changed to use /proc/video entry created by videodev.c
> - 384x288 and 448x336 modes added
> - ov511_move_data() rewritten
> - Added debug messages for IOCTLs
> - Miscellaneous changes in ov511_ioctl()
> - Documentation/Configure.help: CONFIG_VIDEO_PROC_FS help added
> - CREDITS: updated
> - drivers/char/Config.in: CONFIG_VIDEO_PROC_FS option added
> - drivers/char/videodev.c: procfs support added
> - Documentation/ov511.txt: updated

-- 
Mark McClelland
[EMAIL PROTECTED]
diff -Naur linux-2.3.99-pre9-2-orig/CREDITS linux/CREDITS
--- linux-2.3.99-pre9-2-orig/CREDITS    Sat May 20 11:58:30 2000
+++ linux/CREDITS       Sat May 20 11:02:25 2000
@@ -1617,7 +1617,7 @@
 E: [EMAIL PROTECTED]
 E: [EMAIL PROTECTED]
 W: http://helllabs.org/~claudio
-D: OV511 driver hacks
+D: V4L, OV511 driver hacks
 S: Conectiva S.A.
 S: R. Tocantins 89
 S: 80050-430  Curitiba PR
diff -Naur linux-2.3.99-pre9-2-orig/Documentation/Configure.help 
linux/Documentation/Configure.help
--- linux-2.3.99-pre9-2-orig/Documentation/Configure.help       Thu May 18 09:03:03 
2000
+++ linux/Documentation/Configure.help  Sat May 20 11:02:26 2000
@@ -14832,6 +14832,14 @@
   whenever you want). If you want to compile it as a module, say M
   here and read Documentation/modules.txt.
 
+Video For Linux /proc file system information
+CONFIG_VIDEO_PROC_FS
+  If you say Y here, you are able to access video device information
+  in /proc/video.
+
+  To use this option, you have to check, that the "/proc file system
+  support" (CONFIG_PROC_FS) is enabled too.
+
 AIMSlab RadioTrack (aka RadioReveal) support
 CONFIG_RADIO_RTRACK
   Choose Y here if you have one of these FM radio cards, and then fill
diff -Naur linux-2.3.99-pre9-2-orig/Documentation/usb/ov511.txt 
linux/Documentation/usb/ov511.txt
--- linux-2.3.99-pre9-2-orig/Documentation/usb/ov511.txt        Sat May 20 11:58:30 
2000
+++ linux/Documentation/usb/ov511.txt   Sat May 20 11:48:04 2000
@@ -6,8 +6,8 @@
 Homepage: http://alpha.dyndns.org/ov511
 
 NEW IN THIS VERSION:
- o 352x288 mode
- o force_rgb parameter for apps that expect RGB instead of BGR
+ o 384x288 and 448x336 modes
+ o better /proc/video support
 
 INTRODUCTION:
 
@@ -179,7 +179,7 @@
         your colors look VERY wrong, you may want to change this.
 
 WORKING FEATURES:
- o Color streaming/capture at 640x480, 352x288, and 320x240
+ o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, and 320x240
  o YUV420 color
  o Monochrome
  o Setting/getting of saturation, contrast and brightness (no hue yet; only
diff -Naur linux-2.3.99-pre9-2-orig/drivers/char/Config.in linux/drivers/char/Config.in
--- linux-2.3.99-pre9-2-orig/drivers/char/Config.in     Wed May 10 16:56:41 2000
+++ linux/drivers/char/Config.in        Sat May 20 11:02:26 2000
@@ -153,6 +153,7 @@
 
 tristate 'Video For Linux' CONFIG_VIDEO_DEV
 if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
+   bool '  V4L information in proc filesystem' CONFIG_VIDEO_PROC_FS Y
    dep_tristate '  I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT 
$CONFIG_I2C
    comment 'Radio Adapters'
    dep_tristate '  ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV
diff -Naur linux-2.3.99-pre9-2-orig/drivers/char/videodev.c 
linux/drivers/char/videodev.c
--- linux-2.3.99-pre9-2-orig/drivers/char/videodev.c    Thu Apr 13 07:54:32 2000
+++ linux/drivers/char/videodev.c       Sat May 20 11:02:26 2000
@@ -11,7 +11,8 @@
  *
  * Author:     Alan Cox, <[EMAIL PROTECTED]>
  *
- * Fixes:
+ * Fixes:      20000516  Claudio Matsuoka <[EMAIL PROTECTED]>
+ *             - Added procfs support
  */
 
 #include <linux/config.h>
@@ -40,6 +41,27 @@
  
 static struct video_device *video_device[VIDEO_NUM_DEVICES];
 
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+#include <linux/proc_fs.h>
+
+struct videodev_proc_data {
+       struct list_head proc_list;
+       char name[16];
+       struct video_device *vdev;
+       struct proc_dir_entry *proc_entry;
+       struct video_capability vcap;
+};
+
+static struct proc_dir_entry *video_dev_proc_entry = NULL;
+struct proc_dir_entry *video_proc_entry = NULL;
+EXPORT_SYMBOL(video_proc_entry);
+LIST_HEAD(videodev_proc_list);
+
+#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
+
+
 #ifdef CONFIG_VIDEO_BT848
 extern int init_bttv_cards(struct video_init *);
 extern int i2c_tuner_init(struct video_init *);
@@ -217,6 +239,152 @@
        return -EINVAL;
 }
 
+/*
+ *     /proc support
+ */
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+/* Hmm... i'd like to see video_capability information here, but
+ * how can I access it (without changing the other drivers? -claudio
+ */
+static int videodev_proc_read(char *page, char **start, off_t off,
+                              int count, int *eof, void *data)
+{
+       char *out = page;
+       struct video_device *vfd = data;
+       struct videodev_proc_data *d;
+       struct list_head *tmp;
+       int len;
+       char c = ' ';
+
+       list_for_each (tmp, &videodev_proc_list) {
+               d = list_entry(tmp, struct videodev_proc_data, proc_list);
+               if (vfd == d->vdev)
+                       break;
+       }
+
+       /* Sanity check */
+       if (tmp == &videodev_proc_list)
+               goto skip;
+               
+#define PRINT_VID_TYPE(x) do { if (vfd->type & x) \
+       out += sprintf (out, "%c%s", c, #x); c='|';} while (0)
+
+       out += sprintf (out, "name            : %s\n", vfd->name);
+       out += sprintf (out, "type            :");
+               PRINT_VID_TYPE(VID_TYPE_CAPTURE);
+               PRINT_VID_TYPE(VID_TYPE_TUNER);
+               PRINT_VID_TYPE(VID_TYPE_TELETEXT);
+               PRINT_VID_TYPE(VID_TYPE_OVERLAY);
+               PRINT_VID_TYPE(VID_TYPE_CHROMAKEY);
+               PRINT_VID_TYPE(VID_TYPE_CLIPPING);
+               PRINT_VID_TYPE(VID_TYPE_FRAMERAM);
+               PRINT_VID_TYPE(VID_TYPE_SCALES);
+               PRINT_VID_TYPE(VID_TYPE_MONOCHROME);
+               PRINT_VID_TYPE(VID_TYPE_SUBCAPTURE);
+               PRINT_VID_TYPE(VID_TYPE_MPEG_DECODER);
+               PRINT_VID_TYPE(VID_TYPE_MPEG_ENCODER);
+               PRINT_VID_TYPE(VID_TYPE_MJPEG_DECODER);
+               PRINT_VID_TYPE(VID_TYPE_MJPEG_ENCODER);
+       out += sprintf (out, "\n");
+       out += sprintf (out, "hardware        : 0x%x\n", vfd->hardware);
+#if 0
+       out += sprintf (out, "channels        : %d\n", d->vcap.channels);
+       out += sprintf (out, "audios          : %d\n", d->vcap.audios);
+       out += sprintf (out, "maxwidth        : %d\n", d->vcap.maxwidth);
+       out += sprintf (out, "maxheight       : %d\n", d->vcap.maxheight);
+       out += sprintf (out, "minwidth        : %d\n", d->vcap.minwidth);
+       out += sprintf (out, "minheight       : %d\n", d->vcap.minheight);
+#endif
+
+skip:
+       len = out - page;
+       len -= off;
+       if (len < count) {
+               *eof = 1;
+               if (len <= 0)
+                       return 0;
+       } else
+               len = count;
+
+       *start = page + off;
+
+       return len;
+}
+
+static void videodev_proc_create(void)
+{
+       video_proc_entry = create_proc_entry("video", S_IFDIR, &proc_root);
+
+       if (video_proc_entry == NULL) {
+               printk("video_dev: unable to initialise /proc/video\n");
+               return;
+       }
+
+       video_proc_entry->owner = THIS_MODULE;
+       video_dev_proc_entry = create_proc_entry("dev", S_IFDIR, video_proc_entry);
+
+       if (video_dev_proc_entry == NULL) {
+               printk("video_dev: unable to initialise /proc/video/dev\n");
+               return;
+       }
+
+       video_dev_proc_entry->owner = THIS_MODULE;
+}
+
+static void videodev_proc_destroy(void)
+{
+       if (video_dev_proc_entry != NULL)
+               remove_proc_entry("dev", video_proc_entry);
+
+       if (video_proc_entry != NULL)
+               remove_proc_entry("video", &proc_root);
+}
+
+static void videodev_proc_create_dev (struct video_device *vfd, char *name)
+{
+       struct videodev_proc_data *d;
+       struct proc_dir_entry *p;
+
+       if (video_dev_proc_entry == NULL)
+               return;
+
+       d = kmalloc (sizeof (struct videodev_proc_data), GFP_KERNEL);
+       if (!d)
+               return;
+
+       p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry);
+       p->data = vfd;
+       p->read_proc = videodev_proc_read;
+
+       d->proc_entry = p;
+       d->vdev = vfd;
+       strcpy (d->name, name);
+
+       /* How can I get capability information ? */
+
+       list_add (&d->proc_list, &videodev_proc_list);
+}
+
+static void videodev_proc_destroy_dev (struct video_device *vfd)
+{
+       struct list_head *tmp;
+       struct videodev_proc_data *d;
+
+       list_for_each (tmp, &videodev_proc_list) {
+               d = list_entry(tmp, struct videodev_proc_data, proc_list);
+               if (vfd == d->vdev) {
+                       remove_proc_entry(d->name, video_dev_proc_entry);
+                       list_del (&d->proc_list);
+                       kfree (d);
+                       break;
+               }
+       }
+}
+
+#endif /* CONFIG_VIDEO_PROC_FS */
+
 extern struct file_operations video_fops;
 
 /**
@@ -308,6 +476,13 @@
                                            VIDEO_MAJOR, vfd->minor,
                                            S_IFCHR | S_IRUSR | S_IWUSR, 0, 0,
                                            &video_fops, NULL);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+                       sprintf (name, "%s%d", name_base, i - base);
+                       videodev_proc_create_dev (vfd, name);
+#endif
+                       
+
                        return 0;
                }
        }
@@ -326,6 +501,11 @@
 {
        if(video_device[vfd->minor]!=vfd)
                panic("vfd: bad unregister");
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+       videodev_proc_destroy_dev (vfd);
+#endif
+
        devfs_unregister (vfd->devfs_handle);
        video_device[vfd->minor]=NULL;
        MOD_DEC_USE_COUNT;
@@ -363,6 +543,10 @@
         *      Init kernel installed video drivers
         */
                
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+       videodev_proc_create ();
+#endif
+       
        while(vfli->init!=NULL)
        {
                vfli->init(vfli);
@@ -379,6 +563,10 @@
 
 void cleanup_module(void)
 {
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+       videodev_proc_destroy ();
+#endif
+       
        devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture");
 }
 
diff -Naur linux-2.3.99-pre9-2-orig/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- linux-2.3.99-pre9-2-orig/drivers/usb/ov511.c        Sat May 20 11:58:30 2000
+++ linux/drivers/usb/ov511.c   Sat May 20 11:47:38 2000
@@ -30,7 +30,7 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-static const char version[] = "1.14";
+static const char version[] = "1.15";
 
 #define __NO_VERSION__
 
@@ -263,9 +263,10 @@
  * Based on the CPiA driver version 0.7.4 -claudio
  **********************************************************************/
 
-#ifdef CONFIG_PROC_FS
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
 static struct proc_dir_entry *ov511_proc_entry = NULL;
-static struct proc_dir_entry *video_proc_entry = NULL;
+extern struct proc_dir_entry *video_proc_entry;
 
 #define YES_NO(x) ((x) ? "yes" : "no")
 
@@ -343,6 +344,7 @@
                len = count;
 
        *start = page + off;
+
        return len;
 }
 
@@ -357,12 +359,11 @@
        char name[7];
        struct proc_dir_entry *ent;
        
-       PDEBUG (4, "creating /proc/video/ov511/videoX entry");
        if (!ov511_proc_entry || !ov511)
                return;
 
        sprintf(name, "video%d", ov511->vdev.minor);
-       PDEBUG (4, "creating %s", name);
+       PDEBUG (4, "creating /proc/video/ov511/%s", name);
        
        ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry);
 
@@ -372,7 +373,6 @@
        ent->data = ov511;
        ent->read_proc = ov511_read_proc;
        ent->write_proc = ov511_write_proc;
-       ent->size = 3626;       /* FIXME */
        ov511->proc_entry = ent;
 }
 
@@ -391,22 +391,13 @@
 
 static void proc_ov511_create(void)
 {
-       struct proc_dir_entry *p = NULL;
-
        /* No current standard here. Alan prefers /proc/video/ as it keeps
         * /proc "less cluttered than /proc/randomcardifoundintheshed/"
         * -claudio
         */
-       PDEBUG (3, "creating /proc/video");
-       video_proc_entry = proc_mkdir("video", p);
-       if (!video_proc_entry) {
-               if (!p) {
-                       err("Unable to initialise /proc/video\n");
-                       return;
-               } else {        /* FIXME - this doesn't work */
-                       PDEBUG (3, "/proc/video already exists");
-                       video_proc_entry = p;
-               }
+       if (video_proc_entry == NULL) {
+               err("Unable to initialise /proc/video/ov511");
+               return;
        }
 
        ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry);
@@ -414,16 +405,19 @@
        if (ov511_proc_entry)
                ov511_proc_entry->owner = THIS_MODULE;
        else
-               err("Unable to initialise /proc/video/ov511\n");
+               err("Unable to initialise /proc/ov511");
 }
 
 static void proc_ov511_destroy(void)
 {
        PDEBUG (3, "removing /proc/video/ov511");
+
+       if (ov511_proc_entry == NULL)
+               return;
+
        remove_proc_entry("ov511", video_proc_entry);
-       remove_proc_entry("video", NULL);
 }
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
 
 
 /**********************************************************************
@@ -852,7 +846,7 @@
        return 0;
 }
 
-/* FIXME: add 176x144, 160x140 */
+/* FIXME: add 400x300, 176x144, 160x140 */
 static struct mode_list mlist[] = {
        { 640, 480, VIDEO_PALETTE_GREY, 0x4f, 0x3d, 0x00, 0x00,
          0x4f, 0x3d, 0x00, 0x00, 0x04, 0x03, 0x24, 0x04, 0x9e },
@@ -866,6 +860,14 @@
          0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e },
        { 352, 288, VIDEO_PALETTE_RGB24,0x2b, 0x25, 0x00, 0x00,
          0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e },
+       { 384, 288, VIDEO_PALETTE_GREY, 0x2f, 0x25, 0x00, 0x00,
+         0x2f, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e },
+       { 384, 288, VIDEO_PALETTE_RGB24,0x2f, 0x25, 0x00, 0x00,
+         0x2f, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e },
+       { 448, 336, VIDEO_PALETTE_GREY, 0x37, 0x29, 0x00, 0x00,
+         0x37, 0x29, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e },
+       { 448, 336, VIDEO_PALETTE_RGB24,0x37, 0x29, 0x00, 0x00,
+         0x37, 0x29, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e },
        { 0, 0 }
 };
 
@@ -1302,158 +1304,190 @@
        int i, totlen = 0;
        int aPackNum[10];
        struct ov511_frame *frame;
+       unsigned char *pData;
+       int iPix;
 
-       PDEBUG(4, "ov511_move_data");
+       PDEBUG (4, "Moving %d packets", urb->number_of_packets);
 
        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;
+
                urb->iso_frame_desc[i].actual_length = 0;
                urb->iso_frame_desc[i].status = 0;
+
                cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 
                aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1;
 
-               if (!n || ov511->curframe == -1) continue;
+               if (!n || ov511->curframe == -1)
+                       continue;
 
                if (st)
                        PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
 
                frame = &ov511->frame[ov511->curframe];
                
-               /* Can we find a frame end */
+               /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
+                * byte non-zero. The EOF packet has image width/height in the
+                * 10th and 11th packets. The 9th bit is given as follows:
+                *
+                * bit 7: EOF
+                *     6: compression enabled
+                *     5: 422/420/400 modes
+                *     4: 422/420/400 modes
+                *     3: 1
+                *     2: snapshot bottom on
+                *     1: snapshot frame
+                *     0: even/odd field
+                */
+
+               /* Check for SOF/EOF packet */
                if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 
-                    cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
-                   (cdata[8] & 8) && (cdata[8] & 0x80)) {
+                    cdata[4] | cdata[5] | cdata[6] | cdata[7]) ||
+                    (~cdata[8] & 0x08))
+                       goto check_middle;
+
+               /* Frame end */
+               if (cdata[8] & 0x80) {
+#if 0
+                       struct timeval *ts;
+
+                       ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE);
+                       do_gettimeofday (ts);
+#endif
+
+                       PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d",
+                               ov511->curframe, (int)(cdata[ov511->packet_size - 1]),
+                               (int)(cdata[9]), (int)(cdata[10]));
 
-                   struct timeval *ts;
-                   ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE);
-                   do_gettimeofday(ts);
-
-                   PDEBUG(4, "Frame End, curframe = %d, packnum=%d, hw=%d, vw=%d",
-                          ov511->curframe, (int)(cdata[ov511->packet_size - 1]),
-                          (int)(cdata[9]), (int)(cdata[10]));
+                       if (frame->scanstate == STATE_LINES) {
+                               int iFrameNext;
 
-                   if (frame->scanstate == STATE_LINES) {
-                       int iFrameNext;
                                if (fix_rgb_offset)
                                        fixFrameRGBoffset(frame);
                                frame->grabstate = FRAME_DONE;
-                       if (waitqueue_active(&frame->wq)) {
-                                       frame->grabstate = FRAME_DONE;
-                                       wake_up_interruptible(&frame->wq);
+
+                               if (waitqueue_active(&frame->wq)) {
+                                       frame->grabstate = FRAME_DONE;
+                                       wake_up_interruptible(&frame->wq);
                                }
-                               /* If next frame is ready or grabbing, point to it */
+
+                               /* If next frame is ready or grabbing,
+                                 * point to it */
                                iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;
-                               if (ov511->frame[iFrameNext].grabstate== FRAME_READY ||
-                                   ov511->frame[iFrameNext].grabstate== 
FRAME_GRABBING) {
-                                 ov511->curframe = iFrameNext;
-                                 ov511->frame[iFrameNext].scanstate = STATE_SCANNING;
+                               if (ov511->frame[iFrameNext].grabstate == FRAME_READY
+                                   || ov511->frame[iFrameNext].grabstate == 
+FRAME_GRABBING) {
+                                       ov511->curframe = iFrameNext;
+                                       ov511->frame[iFrameNext].scanstate = 
+STATE_SCANNING;
                                } else {
+                                       if (frame->grabstate == FRAME_DONE) {
+                                               PDEBUG(4, "Frame done! 
+congratulations");
+                                       } else {
+                                               PDEBUG(4, "Frame not ready? state = 
+%d",
+                                                       
+ov511->frame[iFrameNext].grabstate);
+                                       }
 
-                                 PDEBUG(4, "Frame not ready? state = %d",
-                                        ov511->frame[iFrameNext].grabstate);
-
-                                 ov511->curframe = -1;
+                                       ov511->curframe = -1;
                                }
-                   }
-               }
-
-               /* Can we find a frame start */
-               else if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 
-                         cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
-                        (cdata[8] & 8)) {
-
-                       PDEBUG(4, "ov511: Found Frame Start!, framenum = %d",
-                              ov511->curframe);
+                       }
+                       /* Image corruption caused by misplaced frame->segment = 0
+                        * fixed by [EMAIL PROTECTED]
+                        */
+               } else {
+                       /* Frame start */
+                       PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
 
                        /* Check to see if it's a snapshot frame */
                        /* FIXME?? Should the snapshot reset go here? Performance? */
                        if (cdata[8] & 0x02) {
                                frame->snapshot = 1;
-                               PDEBUG(3, "ov511_move_data: snapshot detected");
+                               PDEBUG(3, "snapshot detected");
                        }
 
                        frame->scanstate = STATE_LINES;
                        frame->segment = 0;
                }
 
+check_middle:
                /* Are we in a frame? */
-               if (frame->scanstate == STATE_LINES) {
-                       unsigned char * pData;
-                       int iPix;
-
-                       /* Deal with leftover from last segment, if any */
-                       if (frame->segment) {
-                         pData = ov511->scratch;
-                         iPix = - ov511->scratchlen;
-                         memmove(pData + ov511->scratchlen, cdata,
-                                 iPix+frame->segsize);
-                       } else {
-                         pData = &cdata[iPix = 9];
-                       }
+               if (frame->scanstate != STATE_LINES)
+                       continue;
 
-                       /* Parse the segments */
-                       while(iPix <= (ov511->packet_size - 1) - frame->segsize &&
-                             frame->segment < frame->width * frame->height / 256) {
-                         int iSegY;
-                         int iSegUV;
-                         int iY, jY, iUV, jUV;
-                         int iOutY, iOutUV;
-                         unsigned char * pOut;
-
-                         iSegY = iSegUV = frame->segment;
-                         pOut = frame->data;
-                         
-                         frame->segment++;
-                         iPix += frame->segsize;
-
-                         if (frame->sub_flag) {
-                           int iSeg1;
-                           iSeg1 = iSegY / (ov511->subw / 32);
-                           iSeg1 *= frame->width / 32;
-                           iSegY = iSeg1 + (iSegY % (ov511->subw / 32));
-                           if (iSegY >= frame->width * ov511->subh / 256)
-                             break;
-
-                           iSeg1 = iSegUV / (ov511->subw / 16);
-                           iSeg1 *= frame->width / 16;
-                           iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16));
-
-                           pOut += (ov511->subx +
-                                    ov511->suby * frame->width) * frame->depth;
-                         }
-
-                         iY     = iSegY / (frame->width / WDIV);
-                         jY     = iSegY - iY * (frame->width / WDIV);
-                         iOutY  = (iY*HDIV*frame->width + jY*WDIV) * frame->depth;
-                         iUV    = iSegUV / (frame->width / WDIV * 2);
-                         jUV    = iSegUV - iUV * (frame->width / WDIV * 2);
-                         iOutUV = (iUV*HDIV*2*frame->width + jUV*WDIV/2) * 
frame->depth;
-
-                         if (frame->format == VIDEO_PALETTE_GREY) {
-                           ov511_parse_data_grey(pData, pOut, iOutY, frame->width);
-                         } else if (frame->format == VIDEO_PALETTE_RGB24) {
-                           ov511_parse_data_rgb24(pData, pOut, iOutY, iOutUV, iY & 1,
-                                                  frame->width);
-                         }
-                         pData = &cdata[iPix];
-                       }
+               /* Deal with leftover from last segment, if any */
+               if (frame->segment) {
+                       pData = ov511->scratch;
+                       iPix = -ov511->scratchlen;
+                       memmove(pData + ov511->scratchlen, cdata,
+                               iPix+frame->segsize);
+               } else {
+                       pData = &cdata[iPix = 9];
+               }
+
+               /* Parse the segments */
+               while (iPix <= (ov511->packet_size - 1) - frame->segsize &&
+                   frame->segment < frame->width * frame->height / 256) {
+                       int iSegY, iSegUV;
+                       int iY, jY, iUV, jUV;
+                       int iOutY, iOutUV;
+                       unsigned char *pOut;
+
+                       iSegY = iSegUV = frame->segment;
+                       pOut = frame->data;
+                       frame->segment++;
+                       iPix += frame->segsize;
+
+                       /* Handle subwindow */
+                       if (frame->sub_flag) {
+                               int iSeg1;
+
+                               iSeg1 = iSegY / (ov511->subw / 32);
+                               iSeg1 *= frame->width / 32;
+                               iSegY = iSeg1 + (iSegY % (ov511->subw / 32));
+                               if (iSegY >= frame->width * ov511->subh / 256)
+                                       break;
+
+                               iSeg1 = iSegUV / (ov511->subw / 16);
+                               iSeg1 *= frame->width / 16;
+                               iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16));
 
-                       /* Save extra data for next time */
-                       if (frame->segment < frame->width * frame->height / 256) {
-                         ov511->scratchlen = (ov511->packet_size - 1) - iPix;
-                         if (ov511->scratchlen < frame->segsize) {
-                           memmove(ov511->scratch, pData, ov511->scratchlen);
-                         } else {
-                           ov511->scratchlen = 0;
-                         }
+                               pOut += (ov511->subx + ov511->suby * frame->width) *
+                                       (frame->depth >> 3);
                        }
+
+                       /* 
+                        * iY counts segment lines
+                        * jY counts segment columns
+                        * iOutY is the offset (in bytes) of the segment upper left 
+corner
+                        */
+                       iY = iSegY / (frame->width / WDIV);
+                       jY = iSegY - iY * (frame->width / WDIV);
+                       iOutY = (iY*HDIV*frame->width + jY*WDIV) * (frame->depth >> 3);
+                       iUV = iSegUV / (frame->width / WDIV * 2);
+                       jUV = iSegUV - iUV * (frame->width / WDIV * 2);
+                       iOutUV = (iUV*HDIV*2*frame->width + jUV*WDIV/2) * 
+(frame->depth >> 3);
+
+                       if (frame->format == VIDEO_PALETTE_GREY)
+                               ov511_parse_data_grey (pData, pOut, iOutY, 
+frame->width);
+                       else if (frame->format == VIDEO_PALETTE_RGB24)
+                               ov511_parse_data_rgb24 (pData, pOut, iOutY, iOutUV,
+                                       iY & 1, frame->width);
+
+                       pData = &cdata[iPix];
+               }
+
+               /* Save extra data for next time */
+               if (frame->segment < frame->width * frame->height / 256) {
+                       ov511->scratchlen = (ov511->packet_size - 1) - iPix;
+                       if (ov511->scratchlen < frame->segsize)
+                               memmove(ov511->scratch, pData,
+                                       ov511->scratchlen);
+                       else
+                               ov511->scratchlen = 0;
                }
        }
 
-
-       PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d\n",
+       PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d",
               aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
               aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
 
@@ -1472,8 +1506,6 @@
        if (!ov511->streaming) {
                PDEBUG(2, "hmmm... not streaming, but got interrupt");
                return;
-       } else {
-               PDEBUG(5, "streaming. got interrupt");
        }
        
        sbuf = &ov511->sbuf[ov511->cursbuf];
@@ -1723,7 +1755,7 @@
 
 static int ov511_init_done(struct video_device *dev)
 {
-#ifdef CONFIG_PROC_FS
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
        create_proc_ov511_cam((struct usb_ov511 *)dev);
 #endif
 
@@ -1749,6 +1781,8 @@
        {
                struct video_capability b;
 
+               PDEBUG (4, "VIDIOCGCAP");
+
                strcpy(b.name, "OV511 USB Camera");
                b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
                b.channels = 1;
@@ -1798,6 +1832,8 @@
        {
                struct video_picture p;
 
+               PDEBUG (4, "VIDIOCGPICT");
+
                if (ov7610_get_picture(ov511, &p))
                        return -EIO;
                                                        
@@ -1809,18 +1845,33 @@
        case VIDIOCSPICT:
        {
                struct video_picture p;
+               int i;
+
+               PDEBUG (4, "VIDIOCSPICT");
 
                if (copy_from_user(&p, arg, sizeof(p)))
                        return -EFAULT;
-                       
+
                if (ov7610_set_picture(ov511, &p))
                        return -EIO;
 
+               /* FIXME: check validity */
+
+               PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette);
+               for (i = 0; i < OV511_NUMFRAMES; i++) {
+                       ov511->frame[i].depth = p.depth;
+                       ov511->frame[i].format = p.palette;
+                       ov511->frame[i].segsize = GET_SEGSIZE(p.palette);
+               }
+
                return 0;
        }
        case VIDIOCGCAPTURE:
        {
                int vf;
+
+               PDEBUG (4, "VIDIOCGCAPTURE");
+
                if (copy_from_user(&vf, arg, sizeof(vf)))
                        return -EFAULT;
                ov511->sub_flag = vf;
@@ -1836,16 +1887,25 @@
                        return -EINVAL;
                if (vc.decimation)
                        return -EINVAL;
+#if 0
                vc.x /= 4;
                vc.x *= 4;
                vc.y /= 2;
                vc.y *= 2;
                vc.width /= 32;
                vc.width *= 32;
-               if (vc.width == 0) vc.width = 32;
+#else
+               vc.x &= ~3L;
+               vc.y &= ~1L;
+               vc.y &= ~31L;
+#endif
+               if (vc.width == 0)
+                       vc.width = 32;
+
                vc.height /= 16;
                vc.height *= 16;
-               if (vc.height == 0) vc.height = 16;
+               if (vc.height == 0)
+                       vc.height = 16;
 
                ov511->subx = vc.x;
                ov511->suby = vc.y;
@@ -1857,9 +1917,15 @@
        case VIDIOCSWIN:
        {
                struct video_window vw;
+               int i, result;
 
                if (copy_from_user(&vw, arg, sizeof(vw)))
                        return -EFAULT;
+
+               PDEBUG (4, "VIDIOCSWIN: width=%d, height=%d",
+                       vw.width, vw.height);
+
+#if 0
                if (vw.flags)
                        return -EINVAL;
                if (vw.clipcount)
@@ -1868,8 +1934,22 @@
                        return -EINVAL;
                if (vw.width != DEFAULT_WIDTH)
                        return -EINVAL;
+#endif
 
-               ov511->compress = 0;
+               /* If we're collecting previous frame wait
+                  before changing modes */
+               interruptible_sleep_on(&ov511->wq);
+               if (signal_pending(current)) return -EINTR;
+
+               result = ov511_mode_init_regs(ov511, vw.width, vw.height,
+                       ov511->frame[0].format, ov511->sub_flag);
+               if (result < 0)
+                       return result;
+
+               for (i = 0; i < OV511_NUMFRAMES; i++) {
+                       ov511->frame[i].width = vw.width;
+                       ov511->frame[i].height = vw.height;
+               }
 
                return 0;
        }
@@ -1877,13 +1957,15 @@
        {
                struct video_window vw;
 
-               vw.x = 0;
+               vw.x = 0;               /* FIXME */
                vw.y = 0;
-               vw.width = DEFAULT_WIDTH;
-               vw.height = DEFAULT_HEIGHT;
+               vw.width = ov511->frame[0].width;
+               vw.height = ov511->frame[0].height;
                vw.chromakey = 0;
                vw.flags = 30;
 
+               PDEBUG (4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
+
                if (copy_to_user(arg, &vw, sizeof(vw)))
                        return -EFAULT;
 
@@ -1935,19 +2017,16 @@
                           before changing modes */
                        interruptible_sleep_on(&ov511->wq);
                        if (signal_pending(current)) return -EINTR;
-                       ov511_mode_init_regs(ov511,
-                                            vm.width, vm.height,
-                                            vm.format, ov511->sub_flag);
+                       ov511_mode_init_regs(ov511, vm.width, vm.height,
+                               vm.format, ov511->sub_flag);
                }
 
                ov511->frame[vm.frame].width = vm.width;
                ov511->frame[vm.frame].height = vm.height;
                ov511->frame[vm.frame].format = vm.format;
                ov511->frame[vm.frame].sub_flag = ov511->sub_flag;
-               ov511->frame[vm.frame].segsize =
-                 vm.format == VIDEO_PALETTE_RGB24 ? 384 : 256;
-               ov511->frame[vm.frame].depth =
-                 vm.format == VIDEO_PALETTE_RGB24 ? 3 : 1;
+               ov511->frame[vm.frame].segsize = GET_SEGSIZE(vm.format);
+               ov511->frame[vm.frame].depth = GET_DEPTH(vm.format);
 
                /* Mark it as ready */
                ov511->frame[vm.frame].grabstate = FRAME_READY;
@@ -1965,11 +2044,11 @@
                       ov511->frame[frame].grabstate);
 
                switch (ov511->frame[frame].grabstate) {
-                       case FRAME_UNUSED:
-                               return -EINVAL;
-                       case FRAME_READY:
-                       case FRAME_GRABBING:
-                       case FRAME_ERROR:
+               case FRAME_UNUSED:
+                       return -EINVAL;
+               case FRAME_READY:
+               case FRAME_GRABBING:
+               case FRAME_ERROR:
 redo:
                        if (!ov511->dev)
                                return -EIO;
@@ -1989,23 +2068,21 @@
                                if ((ret = ov511_new_frame(ov511, frame)) < 0)
                                        return ret;
                                goto redo;
-                       }                               
-                       case FRAME_DONE:
-                               ov511->frame[frame].grabstate = FRAME_UNUSED;
-                               break;
-               }
-
-               ov511->frame[frame].grabstate = FRAME_UNUSED;
-
-               /* Reset the hardware snapshot button */
-               /* FIXME - Is this the best place for this? */
-               if ((ov511->snap_enabled) &&
-                   (ov511->frame[frame].snapshot)) {
-                       ov511->frame[frame].snapshot = 0;
-                       ov511_reg_write(ov511->dev, 0x52, 0x01);
-                       ov511_reg_write(ov511->dev, 0x52, 0x03);
-                       ov511_reg_write(ov511->dev, 0x52, 0x01);
-               }
+                       }                       
+               case FRAME_DONE:
+                       ov511->frame[frame].grabstate = FRAME_UNUSED;
+
+                       /* Reset the hardware snapshot button */
+                       /* FIXME - Is this the best place for this? */
+                       if ((ov511->snap_enabled) &&
+                           (ov511->frame[frame].snapshot)) {
+                               ov511->frame[frame].snapshot = 0;
+                               ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 
+0x01);
+                               ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 
+0x03);
+                               ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 
+0x01);
+                       }
+                       break;
+               } /* end switch */
 
                return 0;
        }
@@ -2038,7 +2115,7 @@
                return -EINVAL;
        default:
                return -ENOIOCTLCMD;
-       }       /* End switch(cmd) */
+       } /* end switch */
 
        return 0;
 }
@@ -2610,7 +2687,7 @@
                ov511->sbuf[0].urb = NULL;
        }
 
-#ifdef CONFIG_PROC_FS
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
         destroy_proc_ov511_cam(ov511);
 #endif
 
@@ -2637,8 +2714,7 @@
 
 static int __init usb_ov511_init(void)
 {
-#ifdef CONFIG_PROC_FS
-       PDEBUG(3, "creating /proc/ov511");
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
         proc_ov511_create();
 #endif
 
@@ -2655,7 +2731,7 @@
        usb_deregister(&ov511_driver);
        info("ov511 driver deregistered");
 
-#ifdef CONFIG_PROC_FS
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
         proc_ov511_destroy();
 #endif 
 }

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to