V4L/DVB (12438): Read buffer overflow
[safe/jmp/linux-2.6] / drivers / media / video / usbvideo / vicam.c
index 40d053e..45fce39 100644 (file)
@@ -41,7 +41,9 @@
 #include <linux/videodev.h>
 #include <linux/usb.h>
 #include <linux/vmalloc.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
@@ -190,7 +192,7 @@ initialize_camera(struct vicam_camera *cam)
 {
        int err;
        const struct ihex_binrec *rec;
-       const struct firmware *fw;
+       const struct firmware *uninitialized_var(fw);
 
        err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev);
        if (err) {
@@ -228,12 +230,12 @@ set_camera_power(struct vicam_camera *cam, int state)
        return 0;
 }
 
-static int
-vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg)
+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;
-       int retval = 0;
+       long retval = 0;
 
        if (!cam)
                return -ENODEV;
@@ -469,11 +471,10 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign
 }
 
 static int
-vicam_open(struct inode *inode, struct file *file)
+vicam_open(struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct vicam_camera *cam =
-           (struct vicam_camera *) dev->priv;
+       struct vicam_camera *cam = video_drvdata(file);
+
        DBG("open\n");
 
        if (!cam) {
@@ -487,20 +488,24 @@ vicam_open(struct inode *inode, struct file *file)
         * rely on this fact forever.
         */
 
+       lock_kernel();
        if (cam->open_count > 0) {
                printk(KERN_INFO
                       "vicam_open called on already opened camera");
+               unlock_kernel();
                return -EBUSY;
        }
 
        cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
        if (!cam->raw_image) {
+               unlock_kernel();
                return -ENOMEM;
        }
 
        cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
        if (!cam->framebuf) {
                kfree(cam->raw_image);
+               unlock_kernel();
                return -ENOMEM;
        }
 
@@ -508,6 +513,7 @@ vicam_open(struct inode *inode, struct file *file)
        if (!cam->cntrlbuf) {
                kfree(cam->raw_image);
                rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+               unlock_kernel();
                return -ENOMEM;
        }
 
@@ -525,12 +531,13 @@ vicam_open(struct inode *inode, struct file *file)
        cam->open_count++;
 
        file->private_data = cam;
+       unlock_kernel();
 
        return 0;
 }
 
 static int
-vicam_close(struct inode *inode, struct file *file)
+vicam_close(struct file *file)
 {
        struct vicam_camera *cam = file->private_data;
        int open_count;
@@ -777,25 +784,20 @@ vicam_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static const struct file_operations vicam_fops = {
+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,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static struct video_device vicam_template = {
-       .owner          = THIS_MODULE,
        .name           = "ViCam-based USB Camera",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &vicam_fops,
        .minor          = -1,
+       .release        = video_device_release_empty,
 };
 
 /* table of devices that work with this driver */
@@ -839,8 +841,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
               interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
        endpoint = &interface->endpoint[0].desc;
 
-       if ((endpoint->bEndpointAddress & 0x80) &&
-           ((endpoint->bmAttributes & 3) == 0x02)) {
+       if (usb_endpoint_is_bulk_in(endpoint)) {
                /* we found a bulk in endpoint */
                bulkEndpoint = endpoint->bEndpointAddress;
        } else {
@@ -860,20 +861,20 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
 
        mutex_init(&cam->cam_lock);
 
-       memcpy(&cam->vdev, &vicam_template,
-              sizeof (vicam_template));
-       cam->vdev.priv = cam;   // sort of a reverse mapping for those functions that get vdev only
+       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) == -1) {
+       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 video device %d\n",cam->vdev.minor);
+       printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",
+                       cam->vdev.num);
 
        usb_set_intfdata (intf, cam);