ChangeSet 1.893.2.27, 2003/01/06 11:07:07-08:00, [EMAIL PROTECTED]
[PATCH] USB ov511: Convert to new V4L 1 interface
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.
diff -Nru a/drivers/usb/ov511.c b/drivers/usb/ov511.c
--- a/drivers/usb/ov511.c Mon Jan 6 11:29:19 2003
+++ b/drivers/usb/ov511.c Mon Jan 6 11:29:19 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 sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel