]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/zr364xx.c
V4L/DVB (9074): gspca: sonixj webcam 0c45:60fe added.
[linux-2.6-omap-h63xx.git] / drivers / media / video / zr364xx.c
index d8f847edf017571c8c6ca0053487b0cb2d9cbd73..93991cb9ca713b9ae1b5e96a544f1c4ce22a61e5 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/proc_fs.h>
 #include <linux/highmem.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 
 /* Version Information */
@@ -62,8 +63,8 @@
 
 
 /* Module parameters */
-static int debug = 0;
-static int mode = 0;
+static int debug;
+static int mode;
 
 
 /* Module parameters interface */
@@ -94,6 +95,7 @@ static struct usb_device_id device_table[] = {
        {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
        {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
        {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
+       {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
        {}                      /* Terminating entry */
 };
 
@@ -114,6 +116,7 @@ struct zr364xx_camera {
        int height;
        int method;
        struct mutex lock;
+       int users;
 };
 
 
@@ -389,7 +392,7 @@ static int read_frame(struct zr364xx_camera *cam, int framenum)
 }
 
 
-static ssize_t zr364xx_read(struct file *file, char *buf, size_t cnt,
+static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt,
                            loff_t * ppos)
 {
        unsigned long count = cnt;
@@ -520,7 +523,7 @@ static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv,
        return 0;
 }
 
-static int zr364xx_vidioc_enum_fmt_cap(struct file *file,
+static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
                                       void *priv, struct v4l2_fmtdesc *f)
 {
        if (f->index > 0)
@@ -536,7 +539,7 @@ static int zr364xx_vidioc_enum_fmt_cap(struct file *file,
        return 0;
 }
 
-static int zr364xx_vidioc_try_fmt_cap(struct file *file, void *priv,
+static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                                      struct v4l2_format *f)
 {
        struct video_device *vdev = video_devdata(file);
@@ -563,7 +566,7 @@ static int zr364xx_vidioc_try_fmt_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int zr364xx_vidioc_g_fmt_cap(struct file *file, void *priv,
+static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
                                    struct v4l2_format *f)
 {
        struct video_device *vdev = video_devdata(file);
@@ -588,7 +591,7 @@ static int zr364xx_vidioc_g_fmt_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int zr364xx_vidioc_s_fmt_cap(struct file *file, void *priv,
+static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
                                    struct v4l2_format *f)
 {
        struct video_device *vdev = video_devdata(file);
@@ -639,21 +642,22 @@ static int zr364xx_open(struct inode *inode, struct file *file)
 
        DBG("zr364xx_open");
 
-       cam->skip = 2;
+       mutex_lock(&cam->lock);
 
-       err = video_exclusive_open(inode, file);
-       if (err < 0)
-               return err;
+       if (cam->users) {
+               err = -EBUSY;
+               goto out;
+       }
 
        if (!cam->framebuf) {
                cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES);
                if (!cam->framebuf) {
                        info("vmalloc_32 failed!");
-                       return -ENOMEM;
+                       err = -ENOMEM;
+                       goto out;
                }
        }
 
-       mutex_lock(&cam->lock);
        for (i = 0; init[cam->method][i].size != -1; i++) {
                err =
                    send_control_msg(udev, 1, init[cam->method][i].value,
@@ -661,20 +665,23 @@ static int zr364xx_open(struct inode *inode, struct file *file)
                                     init[cam->method][i].size);
                if (err < 0) {
                        info("error during open sequence: %d", i);
-                       mutex_unlock(&cam->lock);
-                       return err;
+                       goto out;
                }
        }
 
+       cam->skip = 2;
+       cam->users++;
        file->private_data = vdev;
 
        /* Added some delay here, since opening/closing the camera quickly,
         * like Ekiga does during its startup, can crash the webcam
         */
        mdelay(100);
+       err = 0;
 
+out:
        mutex_unlock(&cam->lock);
-       return 0;
+       return err;
 }
 
 
@@ -695,6 +702,10 @@ static int zr364xx_release(struct inode *inode, struct file *file)
        udev = cam->udev;
 
        mutex_lock(&cam->lock);
+
+       cam->users--;
+       file->private_data = NULL;
+
        for (i = 0; i < 2; i++) {
                err =
                    send_control_msg(udev, 1, init[cam->method][i].value,
@@ -702,21 +713,19 @@ static int zr364xx_release(struct inode *inode, struct file *file)
                                     init[cam->method][i].size);
                if (err < 0) {
                        info("error during release sequence");
-                       mutex_unlock(&cam->lock);
-                       return err;
+                       goto out;
                }
        }
 
-       file->private_data = NULL;
-       video_exclusive_release(inode, file);
-
        /* Added some delay here, since opening/closing the camera quickly,
         * like Ekiga does during its startup, can crash the webcam
         */
        mdelay(100);
+       err = 0;
 
+out:
        mutex_unlock(&cam->lock);
-       return 0;
+       return err;
 }
 
 
@@ -760,19 +769,12 @@ static const struct file_operations zr364xx_fops = {
        .llseek = no_llseek,
 };
 
-static struct video_device zr364xx_template = {
-       .owner = THIS_MODULE,
-       .name = DRIVER_DESC,
-       .type = VID_TYPE_CAPTURE,
-       .fops = &zr364xx_fops,
-       .release = video_device_release,
-       .minor = -1,
-
+static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
        .vidioc_querycap        = zr364xx_vidioc_querycap,
-       .vidioc_enum_fmt_cap    = zr364xx_vidioc_enum_fmt_cap,
-       .vidioc_try_fmt_cap     = zr364xx_vidioc_try_fmt_cap,
-       .vidioc_s_fmt_cap       = zr364xx_vidioc_s_fmt_cap,
-       .vidioc_g_fmt_cap       = zr364xx_vidioc_g_fmt_cap,
+       .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = zr364xx_vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = zr364xx_vidioc_g_fmt_vid_cap,
        .vidioc_enum_input      = zr364xx_vidioc_enum_input,
        .vidioc_g_input         = zr364xx_vidioc_g_input,
        .vidioc_s_input         = zr364xx_vidioc_s_input,
@@ -783,6 +785,14 @@ static struct video_device zr364xx_template = {
        .vidioc_s_ctrl          = zr364xx_vidioc_s_ctrl,
 };
 
+static struct video_device zr364xx_template = {
+       .name = DRIVER_DESC,
+       .fops = &zr364xx_fops,
+       .ioctl_ops = &zr364xx_ioctl_ops,
+       .release = video_device_release,
+       .minor = -1,
+};
+
 
 
 /*******************/