V4L/DVB (5163): Add checks for CAP_SYS_ADMIN to VIDIOC_DBG_G_REGISTER
[pandora-kernel.git] / drivers / media / video / usbvision / usbvision-video.c
index 864446c..6a61ebc 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <linux/version.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
@@ -204,7 +203,7 @@ MODULE_ALIAS(DRIVER_ALIAS);
 
 static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd)
 {
-       struct video_device *vdev = to_video_device(cd);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        return video_get_drvdata(vdev);
 }
 
@@ -214,81 +213,85 @@ static ssize_t show_version(struct class_device *cd, char *buf)
 }
 static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
 
-static ssize_t show_model(struct class_device *class_dev, char *buf)
+static ssize_t show_model(struct class_device *cd, char *buf)
 {
-       struct video_device *vdev = to_video_device(class_dev);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString);
 }
 static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
 
-static ssize_t show_hue(struct class_device *class_dev, char *buf)
+static ssize_t show_hue(struct class_device *cd, char *buf)
 {
-       struct video_device *vdev = to_video_device(class_dev);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        struct v4l2_control ctrl;
        ctrl.id = V4L2_CID_HUE;
        ctrl.value = 0;
-       call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+       if(usbvision->user)
+               call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
        return sprintf(buf, "%d\n", ctrl.value >> 8);
 }
 static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
 
-static ssize_t show_contrast(struct class_device *class_dev, char *buf)
+static ssize_t show_contrast(struct class_device *cd, char *buf)
 {
-       struct video_device *vdev = to_video_device(class_dev);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        struct v4l2_control ctrl;
        ctrl.id = V4L2_CID_CONTRAST;
        ctrl.value = 0;
-       call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+       if(usbvision->user)
+               call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
        return sprintf(buf, "%d\n", ctrl.value >> 8);
 }
 static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
 
-static ssize_t show_brightness(struct class_device *class_dev, char *buf)
+static ssize_t show_brightness(struct class_device *cd, char *buf)
 {
-       struct video_device *vdev = to_video_device(class_dev);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        struct v4l2_control ctrl;
        ctrl.id = V4L2_CID_BRIGHTNESS;
        ctrl.value = 0;
-       call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+       if(usbvision->user)
+               call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
        return sprintf(buf, "%d\n", ctrl.value >> 8);
 }
 static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
 
-static ssize_t show_saturation(struct class_device *class_dev, char *buf)
+static ssize_t show_saturation(struct class_device *cd, char *buf)
 {
-       struct video_device *vdev = to_video_device(class_dev);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        struct v4l2_control ctrl;
        ctrl.id = V4L2_CID_SATURATION;
        ctrl.value = 0;
-       call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+       if(usbvision->user)
+               call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
        return sprintf(buf, "%d\n", ctrl.value >> 8);
 }
 static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
 
-static ssize_t show_streaming(struct class_device *class_dev, char *buf)
+static ssize_t show_streaming(struct class_device *cd, char *buf)
 {
-       struct video_device *vdev = to_video_device(class_dev);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0));
 }
 static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
 
-static ssize_t show_compression(struct class_device *class_dev, char *buf)
+static ssize_t show_compression(struct class_device *cd, char *buf)
 {
-       struct video_device *vdev = to_video_device(class_dev);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS));
 }
 static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL);
 
-static ssize_t show_device_bridge(struct class_device *class_dev, char *buf)
+static ssize_t show_device_bridge(struct class_device *cd, char *buf)
 {
-       struct video_device *vdev = to_video_device(class_dev);
+       struct video_device *vdev = container_of(cd, struct video_device, class_dev);
        struct usb_usbvision *usbvision = video_get_drvdata(vdev);
        return sprintf(buf, "%d\n", usbvision->bridgeType);
 }
@@ -297,31 +300,71 @@ static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL);
 static void usbvision_create_sysfs(struct video_device *vdev)
 {
        int res;
-       if (vdev) {
-               res=video_device_create_file(vdev, &class_device_attr_version);
-               res=video_device_create_file(vdev, &class_device_attr_model);
-               res=video_device_create_file(vdev, &class_device_attr_hue);
-               res=video_device_create_file(vdev, &class_device_attr_contrast);
-               res=video_device_create_file(vdev, &class_device_attr_brightness);
-               res=video_device_create_file(vdev, &class_device_attr_saturation);
-               res=video_device_create_file(vdev, &class_device_attr_streaming);
-               res=video_device_create_file(vdev, &class_device_attr_compression);
-               res=video_device_create_file(vdev, &class_device_attr_bridge);
-       }
+       if (!vdev)
+               return;
+       do {
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_version);
+               if (res<0)
+                       break;
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_model);
+               if (res<0)
+                       break;
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_hue);
+               if (res<0)
+                       break;
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_contrast);
+               if (res<0)
+                       break;
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_brightness);
+               if (res<0)
+                       break;
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_saturation);
+               if (res<0)
+                       break;
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_streaming);
+               if (res<0)
+                       break;
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_compression);
+               if (res<0)
+                       break;
+               res=class_device_create_file(&vdev->class_dev,
+                                            &class_device_attr_bridge);
+               if (res>=0)
+                       return;
+       } while (0);
+
+       err("%s error: %d\n", __FUNCTION__, res);
 }
 
 static void usbvision_remove_sysfs(struct video_device *vdev)
 {
        if (vdev) {
-               video_device_remove_file(vdev, &class_device_attr_version);
-               video_device_remove_file(vdev, &class_device_attr_model);
-               video_device_remove_file(vdev, &class_device_attr_hue);
-               video_device_remove_file(vdev, &class_device_attr_contrast);
-               video_device_remove_file(vdev, &class_device_attr_brightness);
-               video_device_remove_file(vdev, &class_device_attr_saturation);
-               video_device_remove_file(vdev, &class_device_attr_streaming);
-               video_device_remove_file(vdev, &class_device_attr_compression);
-               video_device_remove_file(vdev, &class_device_attr_bridge);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_version);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_model);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_hue);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_contrast);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_brightness);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_saturation);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_streaming);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_compression);
+               class_device_remove_file(&vdev->class_dev,
+                                        &class_device_attr_bridge);
        }
 }
 
@@ -353,20 +396,15 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
                if(!errCode) {
                        /* Allocate memory for the scratch ring buffer */
                        errCode = usbvision_scratch_alloc(usbvision);
-                       if(!errCode) {
-                               /* Allocate memory for the USB S buffers */
-                               errCode = usbvision_sbuf_alloc(usbvision);
-                               if ((!errCode) && (usbvision->isocMode==ISOC_MODE_COMPRESS)) {
-                                       /* Allocate intermediate decompression buffers only if needed */
-                                       errCode = usbvision_decompress_alloc(usbvision);
-                               }
+                       if ((!errCode) && (isocMode==ISOC_MODE_COMPRESS)) {
+                               /* Allocate intermediate decompression buffers only if needed */
+                               errCode = usbvision_decompress_alloc(usbvision);
                        }
                }
                if (errCode) {
                        /* Deallocate all buffers if trouble */
                        usbvision_frames_free(usbvision);
                        usbvision_scratch_free(usbvision);
-                       usbvision_sbuf_free(usbvision);
                        usbvision_decompress_free(usbvision);
                }
        }
@@ -437,9 +475,8 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
        usbvision_stop_isoc(usbvision);
 
        usbvision_decompress_free(usbvision);
-       usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
+       usbvision_frames_free(usbvision);
        usbvision_scratch_free(usbvision);
-       usbvision_sbuf_free(usbvision);
 
        usbvision->user--;
 
@@ -452,7 +489,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
        up(&usbvision->lock);
 
        if (usbvision->remove_pending) {
-               info("%s: Final disconnect", __FUNCTION__);
+               printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
                usbvision_release(usbvision);
        }
 
@@ -482,27 +519,8 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
                /* ioctls to allow direct acces to the NT100x registers */
-               case VIDIOC_INT_G_REGISTER:
-               {
-                       struct v4l2_register *reg = arg;
-                       int errCode;
-
-                       if (reg->i2c_id != 0)
-                               return -EINVAL;
-                       /* NT100x has a 8-bit register space */
-                       errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
-                       if (errCode < 0) {
-                               err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode);
-                       }
-                       else {
-                               reg->val=(unsigned char)errCode;
-                               PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X",
-                                                       (unsigned int)reg->reg, reg->val);
-                               errCode = 0; // No error
-                       }
-                       return errCode;
-               }
-               case VIDIOC_INT_S_REGISTER:
+               case VIDIOC_DBG_G_REGISTER:
+               case VIDIOC_DBG_S_REGISTER:
                {
                        struct v4l2_register *reg = arg;
                        int errCode;
@@ -511,15 +529,22 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                                return -EINVAL;
                        if (!capable(CAP_SYS_ADMIN))
                                return -EPERM;
-                       errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
+                       /* NT100x has a 8-bit register space */
+                       if (cmd == VIDIOC_DBG_G_REGISTER)
+                               errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
+                       else
+                               errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
                        if (errCode < 0) {
-                               err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode);
-                       }
-                       else {
-                               PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X",
-                                                       (unsigned int)reg->reg, reg->val);
-                               errCode = 0;
+                               err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__,
+                                   cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode);
+                               return errCode;
                        }
+                       if (cmd == VIDIOC_DBG_S_REGISTER)
+                               reg->val = (u8)errCode;
+
+                       PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X",
+                              cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S',
+                              (unsigned int)reg->reg, reg->val);
                        return 0;
                }
 #endif
@@ -1034,7 +1059,7 @@ static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file,
 }
 
 
-static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
+static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
                      size_t count, loff_t *ppos)
 {
        struct video_device *dev = video_devdata(file);
@@ -1042,7 +1067,6 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
        int noblock = file->f_flags & O_NONBLOCK;
        unsigned long lock_flags;
 
-       int frmx = -1;
        int ret,i;
        struct usbvision_frame *frame;
 
@@ -1117,7 +1141,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
                frame->bytes_read = 0;
 
                /* Mark it as available to be used again. */
-               usbvision->frame[frmx].grabstate = FrameState_Unused;
+               frame->grabstate = FrameState_Unused;
 /*     } */
 
        return count;
@@ -1249,7 +1273,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
        up(&usbvision->lock);
 
        if (usbvision->remove_pending) {
-               info("%s: Final disconnect", __FUNCTION__);
+               printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
                usbvision_release(usbvision);
        }
 
@@ -1438,7 +1462,7 @@ static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
 //
 
 // Video template
-static struct file_operations usbvision_fops = {
+static const struct file_operations usbvision_fops = {
        .owner             = THIS_MODULE,
        .open           = usbvision_v4l2_open,
        .release        = usbvision_v4l2_close,
@@ -1459,7 +1483,7 @@ static struct video_device usbvision_video_template = {
 
 
 // Radio template
-static struct file_operations usbvision_radio_fops = {
+static const struct file_operations usbvision_radio_fops = {
        .owner             = THIS_MODULE,
        .open           = usbvision_radio_open,
        .release        = usbvision_radio_close,
@@ -1480,7 +1504,7 @@ static struct video_device usbvision_radio_template=
 
 
 // vbi template
-static struct file_operations usbvision_vbi_fops = {
+static const struct file_operations usbvision_vbi_fops = {
        .owner             = THIS_MODULE,
        .open           = usbvision_vbi_open,
        .release        = usbvision_vbi_close,
@@ -1575,7 +1599,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
        if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) {
                goto err_exit;
        }
-       info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f);
+       printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", usbvision->nr,usbvision->vdev->minor & 0x1f);
 
        // Radio Device:
        if (usbvision_device_data[usbvision->DevModel].Radio) {
@@ -1587,7 +1611,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
                if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) {
                        goto err_exit;
                }
-               info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f);
+               printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", usbvision->nr, usbvision->rdev->minor & 0x1f);
        }
        // vbi Device:
        if (usbvision_device_data[usbvision->DevModel].vbi) {
@@ -1598,7 +1622,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
                if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) {
                        goto err_exit;
                }
-               info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f);
+               printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", usbvision->nr,usbvision->vbi->minor & 0x1f);
        }
        // all done
        return 0;
@@ -1747,7 +1771,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
                        continue;
                }
 
-               info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString);
+               printk(KERN_INFO "%s: %s found\n", __FUNCTION__, usbvision_device_data[model].ModelString);
                break;
        }
 
@@ -1859,7 +1883,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
        up(&usbvision->lock);
 
        if (usbvision->user) {
-               info("%s: In use, disconnect pending", __FUNCTION__);
+               printk(KERN_INFO "%s: In use, disconnect pending\n", __FUNCTION__);
                wake_up_interruptible(&usbvision->wait_frame);
                wake_up_interruptible(&usbvision->wait_stream);
        }
@@ -1884,7 +1908,7 @@ static struct usb_driver usbvision_driver = {
  * This procedure preprocesses CustomDevice parameter if any
  *
  */
-void customdevice_process(void)
+static void customdevice_process(void)
 {
        usbvision_device_data[0]=usbvision_device_data[1];
        usbvision_table[0]=usbvision_table[1];
@@ -1939,22 +1963,22 @@ void customdevice_process(void)
                {
                        case 'P':
                                PDEBUG(DBG_PROBE, "VideoNorm=PAL");
-                               usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL;
+                               usbvision_device_data[0].VideoNorm=V4L2_STD_PAL;
                                break;
 
                        case 'S':
                                PDEBUG(DBG_PROBE, "VideoNorm=SECAM");
-                               usbvision_device_data[0].VideoNorm=VIDEO_MODE_SECAM;
+                               usbvision_device_data[0].VideoNorm=V4L2_STD_SECAM;
                                break;
 
                        case 'N':
                                PDEBUG(DBG_PROBE, "VideoNorm=NTSC");
-                               usbvision_device_data[0].VideoNorm=VIDEO_MODE_NTSC;
+                               usbvision_device_data[0].VideoNorm=V4L2_STD_NTSC;
                                break;
 
                        default:
                                PDEBUG(DBG_PROBE, "VideoNorm=PAL (by default)");
-                               usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL;
+                               usbvision_device_data[0].VideoNorm=V4L2_STD_PAL;
                                break;
                }
                goto2next(parse);
@@ -2025,7 +2049,7 @@ static int __init usbvision_init(void)
        errCode = usb_register(&usbvision_driver);
 
        if (errCode == 0) {
-               info(DRIVER_DESC " : " USBVISION_VERSION_STRING);
+               printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n");
                PDEBUG(DBG_PROBE, "success");
        }
        return errCode;