Here's a patch to switch ov511 over to the new V4L 1 interface introduced in 2.4.19. Rather than storing the function pointers for open(), ioctl(), etc in struct video_device, I just hand the V4L layer a struct file_operations.

The advantages of this are:

- The driver more closely resembles its 2.5 counterpart.

- Multiple simultaneous opens will eventually be possible.

- The old interfaces required calling video_unregister_device() from close() if the device was unplugged while open, causing a deadlock in the V4L layer. Now we just call video_unregister_device() unconditionally from disconnect(). (Credit goes to Duncan Haldane for tracking that bug down)

This is just a backport of the changes made to the driver in ~2.5.10; nothing new here. I've been using this version of the code under 2.4 for months and it works well.

Please apply to 2.4-latest.

Happy New Year!

- Mark
===================================================================

 ov511.c |  127 ++++++++++++++++++++++------------------------------------------
 1 files changed, 44 insertions, 83 deletions


# This is a BitKeeper generated patch for the following project:
# Project Name: greg k-h's linux 2.4 USB kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.869   -> 1.870  
#        drivers/usb/ov511.c    1.23    -> 1.24   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/01/02      [EMAIL PROTECTED] 1.870
# [PATCH] ov511: Convert to new V4L 1 interface
# 
# Rather than storing the function pointers for open(), ioctl(), etc in
# struct video_device, just hand the V4L layer a struct file_operations.
# 
# The advantages of this are:
# 
# - The driver more closely resembles its 2.5 counterpart.
# 
# - Multiple simultaneous opens will eventually be possible.
# 
# - The old interfaces required calling video_unregister_device() from
#   close() if the device was unplugged while open, causing a deadlock
#   in the V4L layer. Now we just call video_unregister_device()
#   unconditionally from disconnect(). (Credit goes to Duncan Haldane for
#   tracking that bug down)
# 
# This is just a backport of the changes made to the driver in
# ~2.5.10; nothing new here. I've been using this version of the code
# under 2.4 for months and it works well.
# --------------------------------------------
#
diff -Nru a/drivers/usb/ov511.c b/drivers/usb/ov511.c
--- a/drivers/usb/ov511.c       Thu Jan  2 01:47:18 2003
+++ b/drivers/usb/ov511.c       Thu Jan  2 01:47:18 2003
@@ -1,7 +1,7 @@
 /*
  * OmniVision OV511 Camera-to-USB Bridge Driver
  *
- * Copyright (c) 1999-2002 Mark W. McClelland
+ * Copyright (c) 1999-2003 Mark W. McClelland
  * Original decompression code Copyright 1998-2000 OmniVision Technologies
  * Many improvements by Bret Wallach <[EMAIL PROTECTED]>
  * Color fixes by by Orion Sky Lawlor <[EMAIL PROTECTED]> (2/26/2000)
@@ -4529,8 +4529,9 @@
  ***************************************************************************/
 
 static int
-ov51x_v4l1_open(struct video_device *vdev, int flags)
+ov51x_v4l1_open(struct inode *inode, struct file *file)
 {
+       struct video_device *vdev = video_devdata(file);
        struct usb_ov511 *ov = vdev->priv;
        int err, i;
 
@@ -4574,6 +4575,7 @@
        }
 
        ov->user++;
+       file->private_data = vdev;
 
        if (ov->led_policy == LED_AUTO)
                ov51x_led_control(ov, 1);
@@ -4583,9 +4585,10 @@
        return err;
 }
 
-static void
-ov51x_v4l1_close(struct video_device *vdev)
+static int
+ov51x_v4l1_close(struct inode *inode, struct file *file)
 {
+       struct video_device *vdev = file->private_data;
        struct usb_ov511 *ov = vdev->priv;
 
        PDEBUG(4, "ov511_close");
@@ -4614,19 +4617,22 @@
                up(&ov->cbuf_lock);
 
                ov51x_dealloc(ov, 1);
-               video_unregister_device(&ov->vdev);
                kfree(ov);
                ov = NULL;
        }
 
-       return;
+       file->private_data = NULL;
+       return 0;
 }
 
 /* Do not call this function directly! */
 static int
-ov51x_v4l1_ioctl_internal(struct usb_ov511 *ov, unsigned int cmd,
-                         void *arg)
+ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
+                         unsigned int cmd, void *arg)
 {
+       struct video_device *vdev = file->private_data;
+       struct usb_ov511 *ov = vdev->priv;
+
        PDEBUG(5, "IOCtl: 0x%X", cmd);
 
        if (!ov->dev)
@@ -5066,80 +5072,29 @@
        return 0;
 }
 
-/* This is implemented as video_generic_ioctl() in the new V4L's videodev.c */
 static int
-ov51x_v4l1_generic_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
-{
-       char    sbuf[128];
-       void    *mbuf = NULL;
-       void    *parg = NULL;
-       int     err  = -EINVAL;
-
-       /*  Copy arguments into temp kernel buffer  */
-       switch (_IOC_DIR(cmd)) {
-       case _IOC_NONE:
-               parg = arg;
-               break;
-       case _IOC_READ: /* some v4l ioctls are marked wrong ... */
-       case _IOC_WRITE:
-       case (_IOC_WRITE | _IOC_READ):
-               if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
-                       parg = sbuf;
-               } else {
-                       /* too big to allocate from stack */
-                       mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
-                       if (NULL == mbuf)
-                               return -ENOMEM;
-                       parg = mbuf;
-               }
-
-               err = -EFAULT;
-               if (copy_from_user(parg, arg, _IOC_SIZE(cmd)))
-                       goto out;
-               break;
-       }
-
-       err = ov51x_v4l1_ioctl_internal(vdev->priv, cmd, parg);
-       if (err == -ENOIOCTLCMD)
-               err = -EINVAL;
-       if (err < 0)
-               goto out;
-
-       /*  Copy results into user buffer  */
-       switch (_IOC_DIR(cmd))
-       {
-       case _IOC_READ:
-       case (_IOC_WRITE | _IOC_READ):
-               if (copy_to_user(arg, parg, _IOC_SIZE(cmd)))
-                       err = -EFAULT;
-               break;
-       }
-
-out:
-       if (mbuf)
-               kfree(mbuf);
-       return err;
-}
-
-static int
-ov51x_v4l1_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+ov51x_v4l1_ioctl(struct inode *inode, struct file *file,
+                unsigned int cmd, unsigned long arg)
 {
+       struct video_device *vdev = file->private_data;
        struct usb_ov511 *ov = vdev->priv;
        int rc;
 
        if (down_interruptible(&ov->lock))
                return -EINTR;
 
-       rc = ov51x_v4l1_generic_ioctl(vdev, cmd, arg);
+       rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal);
 
        up(&ov->lock);
        return rc;
 }
 
-static inline long
-ov51x_v4l1_read(struct video_device *vdev, char *buf, unsigned long count,
-               int noblock)
+static int
+ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
 {
+       struct video_device *vdev = file->private_data;
+       int noblock = file->f_flags&O_NONBLOCK;
+       unsigned long count = cnt;
        struct usb_ov511 *ov = vdev->priv;
        int i, rc = 0, frmx = -1;
        struct ov511_frame *frame;
@@ -5289,9 +5244,11 @@
 }
 
 static int
-ov51x_v4l1_mmap(struct video_device *vdev, const char *adr, unsigned long size)
+ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       unsigned long start = (unsigned long)adr;
+       struct video_device *vdev = file->private_data;
+       unsigned long start = vma->vm_start;
+       unsigned long size  = vma->vm_end - vma->vm_start;
        struct usb_ov511 *ov = vdev->priv;
        unsigned long page, pos;
 
@@ -5327,16 +5284,22 @@
        return 0;
 }
 
+static struct file_operations ov511_fops = {
+       .owner =        THIS_MODULE,
+       .open =         ov51x_v4l1_open,
+       .release =      ov51x_v4l1_close,
+       .read =         ov51x_v4l1_read,
+       .mmap =         ov51x_v4l1_mmap,
+       .ioctl =        ov51x_v4l1_ioctl,
+       .llseek =       no_llseek,
+};
+
 static struct video_device vdev_template = {
-       owner:          THIS_MODULE,
-       name:           "OV511 USB Camera",
-       type:           VID_TYPE_CAPTURE,
-       hardware:       VID_HARDWARE_OV511,
-       open:           ov51x_v4l1_open,
-       close:          ov51x_v4l1_close,
-       read:           ov51x_v4l1_read,
-       ioctl:          ov51x_v4l1_ioctl,
-       mmap:           ov51x_v4l1_mmap,
+       .owner =        THIS_MODULE,
+       .name =         "OV511 USB Camera",
+       .type =         VID_TYPE_CAPTURE,
+       .hardware =     VID_HARDWARE_OV511,
+       .fops =         &ov511_fops,
 };
 
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
@@ -6621,10 +6584,8 @@
 
        PDEBUG(3, "");
 
-       /* We don't want people trying to open up the device */
-       if (!ov->user)
-               video_unregister_device(&ov->vdev);
-       else
+       video_unregister_device(&ov->vdev);
+       if (ov->user)
                PDEBUG(3, "Device open...deferring video_unregister_device");
 
        for (n = 0; n < OV511_NUMFRAMES; n++)

===================================================================


This BitKeeper patch contains the following changesets:
1.870
## Wrapped with gzip_uu ##


begin 664 bkpatch2385
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
K6-$+UQ!?ZHKO$ZBI=[6AZP]_&*,9B^:BS`Z]7L_N=+S8_`=63;#)FPX`````
`
end

Reply via email to