[media] pwc: convert to video_ioctl2
Hans Verkuil [Sat, 22 Jan 2011 09:34:55 +0000 (06:34 -0300)]
Tested with a Logitech QuickCam Pro 4000.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h

index 4aa70fa..780af5f 100644 (file)
@@ -151,8 +151,6 @@ static int pwc_video_close(struct file *file);
 static ssize_t pwc_video_read(struct file *file, char __user *buf,
                          size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
-static long  pwc_video_ioctl(struct file *file,
-                           unsigned int ioctlnr, unsigned long arg);
 static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
 
 static const struct v4l2_file_operations pwc_fops = {
@@ -162,7 +160,7 @@ static const struct v4l2_file_operations pwc_fops = {
        .read =         pwc_video_read,
        .poll =         pwc_video_poll,
        .mmap =         pwc_video_mmap,
-       .unlocked_ioctl = pwc_video_ioctl,
+       .unlocked_ioctl = video_ioctl2,
 };
 static struct video_device pwc_template = {
        .name =         "Philips Webcam",       /* Filled in later */
@@ -1378,23 +1376,6 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
        return 0;
 }
 
-static long pwc_video_ioctl(struct file *file,
-                          unsigned int cmd, unsigned long arg)
-{
-       struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev;
-       long r = -ENODEV;
-
-       if (!vdev)
-               goto out;
-       pdev = video_get_drvdata(vdev);
-
-       if (!pdev->unplugged)
-               r = video_usercopy(file, cmd, arg, pwc_video_do_ioctl);
-out:
-       return r;
-}
-
 static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct video_device *vdev = file->private_data;
@@ -1744,6 +1725,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
        pdev->vdev->parent = &intf->dev;
        pdev->vdev->lock = &pdev->modlock;
+       pdev->vdev->ioctl_ops = &pwc_ioctl_ops;
        strcpy(pdev->vdev->name, name);
        video_set_drvdata(pdev->vdev, pdev);
 
index 8a7e52c..68a5313 100644 (file)
@@ -341,606 +341,554 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
 
 }
 
-long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
 {
        struct video_device *vdev = video_devdata(file);
-       struct pwc_device *pdev;
-       DECLARE_WAITQUEUE(wait, current);
-
-       if (vdev == NULL)
-               return -EFAULT;
-       pdev = video_get_drvdata(vdev);
-       if (pdev == NULL)
-               return -EFAULT;
+       struct pwc_device *pdev = video_drvdata(file);
+
+       strcpy(cap->driver, PWC_NAME);
+       strlcpy(cap->card, vdev->name, sizeof(cap->card));
+       usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
+       cap->version = PWC_VERSION_CODE;
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE  |
+               V4L2_CAP_STREAMING      |
+               V4L2_CAP_READWRITE;
+       return 0;
+}
 
-#ifdef CONFIG_USB_PWC_DEBUG
-       if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) {
-               v4l_printk_ioctl(cmd);
-               printk("\n");
-       }
-#endif
-
-
-       switch (cmd) {
-               /* V4L2 Layer */
-               case VIDIOC_QUERYCAP:
-               {
-                   struct v4l2_capability *cap = arg;
-
-                   PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\
-                                      "try to use the v4l2 layer\n");
-                   strcpy(cap->driver,PWC_NAME);
-                   strlcpy(cap->card, vdev->name, sizeof(cap->card));
-                   usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info));
-                   cap->version = PWC_VERSION_CODE;
-                   cap->capabilities =
-                       V4L2_CAP_VIDEO_CAPTURE  |
-                       V4L2_CAP_STREAMING      |
-                       V4L2_CAP_READWRITE;
-                   return 0;
-               }
+static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+       if (i->index)   /* Only one INPUT is supported */
+               return -EINVAL;
 
-               case VIDIOC_ENUMINPUT:
-               {
-                   struct v4l2_input *i = arg;
+       strcpy(i->name, "usb");
+       return 0;
+}
 
-                   if ( i->index )     /* Only one INPUT is supported */
-                         return -EINVAL;
+static int pwc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
 
-                   memset(i, 0, sizeof(struct v4l2_input));
-                   strcpy(i->name, "usb");
-                   return 0;
-               }
+static int pwc_s_input(struct file *file, void *fh, unsigned int i)
+{
+       return i ? -EINVAL : 0;
+}
 
-               case VIDIOC_G_INPUT:
-               {
-                   int *i = arg;
-                   *i = 0;     /* Only one INPUT is supported */
-                   return 0;
-               }
-               case VIDIOC_S_INPUT:
-               {
-                       int *i = arg;
+static int pwc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)
+{
+       int i;
 
-                       if ( *i ) {     /* Only one INPUT is supported */
-                               PWC_DEBUG_IOCTL("Only one input source is"\
-                                       " supported with this webcam.\n");
-                               return -EINVAL;
-                       }
+       for (i = 0; i < sizeof(pwc_controls) / sizeof(struct v4l2_queryctrl); i++) {
+               if (pwc_controls[i].id == c->id) {
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
+                       memcpy(c, &pwc_controls[i], sizeof(struct v4l2_queryctrl));
                        return 0;
                }
+       }
+       return -EINVAL;
+}
 
-               /* TODO: */
-               case VIDIOC_QUERYCTRL:
-               {
-                       struct v4l2_queryctrl *c = arg;
-                       int i;
-
-                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id);
-                       for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) {
-                               if (pwc_controls[i].id == c->id) {
-                                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
-                                       memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl));
-                                       return 0;
-                               }
-                       }
-                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n");
+static int pwc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int ret;
 
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               c->value = pwc_get_brightness(pdev);
+               if (c->value < 0)
                        return -EINVAL;
-               }
-               case VIDIOC_G_CTRL:
-               {
-                       struct v4l2_control *c = arg;
-                       int ret;
-
-                       switch (c->id)
-                       {
-                               case V4L2_CID_BRIGHTNESS:
-                                       c->value = pwc_get_brightness(pdev);
-                                       if (c->value<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_CONTRAST:
-                                       c->value = pwc_get_contrast(pdev);
-                                       if (c->value<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_SATURATION:
-                                       ret = pwc_get_saturation(pdev, &c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_GAMMA:
-                                       c->value = pwc_get_gamma(pdev);
-                                       if (c->value<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_RED_BALANCE:
-                                       ret = pwc_get_red_gain(pdev, &c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       c->value >>= 8;
-                                       return 0;
-                               case V4L2_CID_BLUE_BALANCE:
-                                       ret = pwc_get_blue_gain(pdev, &c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       c->value >>= 8;
-                                       return 0;
-                               case V4L2_CID_AUTO_WHITE_BALANCE:
-                                       ret = pwc_get_awb(pdev);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       c->value = (ret == PWC_WB_MANUAL)?0:1;
-                                       return 0;
-                               case V4L2_CID_GAIN:
-                                       ret = pwc_get_agc(pdev, &c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       c->value >>= 8;
-                                       return 0;
-                               case V4L2_CID_AUTOGAIN:
-                                       ret = pwc_get_agc(pdev, &c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       c->value = (c->value < 0)?1:0;
-                                       return 0;
-                               case V4L2_CID_EXPOSURE:
-                                       ret = pwc_get_shutter_speed(pdev, &c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_COLOUR_MODE:
-                                       ret = pwc_get_colour_mode(pdev, &c->value);
-                                       if (ret < 0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_AUTOCONTOUR:
-                                       ret = pwc_get_contour(pdev, &c->value);
-                                       if (ret < 0)
-                                               return -EINVAL;
-                                       c->value=(c->value == -1?1:0);
-                                       return 0;
-                               case V4L2_CID_PRIVATE_CONTOUR:
-                                       ret = pwc_get_contour(pdev, &c->value);
-                                       if (ret < 0)
-                                               return -EINVAL;
-                                       c->value >>= 10;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_BACKLIGHT:
-                                       ret = pwc_get_backlight(pdev, &c->value);
-                                       if (ret < 0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_FLICKERLESS:
-                                       ret = pwc_get_flicker(pdev, &c->value);
-                                       if (ret < 0)
-                                               return -EINVAL;
-                                       c->value=(c->value?1:0);
-                                       return 0;
-                               case V4L2_CID_PRIVATE_NOISE_REDUCTION:
-                                       ret = pwc_get_dynamic_noise(pdev, &c->value);
-                                       if (ret < 0)
-                                               return -EINVAL;
-                                       return 0;
-
-                               case V4L2_CID_PRIVATE_SAVE_USER:
-                               case V4L2_CID_PRIVATE_RESTORE_USER:
-                               case V4L2_CID_PRIVATE_RESTORE_FACTORY:
-                                       return -EINVAL;
-                       }
+               return 0;
+       case V4L2_CID_CONTRAST:
+               c->value = pwc_get_contrast(pdev);
+               if (c->value < 0)
                        return -EINVAL;
-               }
-               case VIDIOC_S_CTRL:
-               {
-                       struct v4l2_control *c = arg;
-                       int ret;
-
-                       switch (c->id)
-                       {
-                               case V4L2_CID_BRIGHTNESS:
-                                       c->value <<= 9;
-                                       ret = pwc_set_brightness(pdev, c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_CONTRAST:
-                                       c->value <<= 10;
-                                       ret = pwc_set_contrast(pdev, c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_SATURATION:
-                                       ret = pwc_set_saturation(pdev, c->value);
-                                       if (ret<0)
-                                         return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_GAMMA:
-                                       c->value <<= 11;
-                                       ret = pwc_set_gamma(pdev, c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_RED_BALANCE:
-                                       c->value <<= 8;
-                                       ret = pwc_set_red_gain(pdev, c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_BLUE_BALANCE:
-                                       c->value <<= 8;
-                                       ret = pwc_set_blue_gain(pdev, c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_AUTO_WHITE_BALANCE:
-                                       c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO;
-                                       ret = pwc_set_awb(pdev, c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_EXPOSURE:
-                                       c->value <<= 8;
-                                       ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_AUTOGAIN:
-                                       /* autogain off means nothing without a gain */
-                                       if (c->value == 0)
-                                               return 0;
-                                       ret = pwc_set_agc(pdev, c->value, 0);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_GAIN:
-                                       c->value <<= 8;
-                                       ret = pwc_set_agc(pdev, 0, c->value);
-                                       if (ret<0)
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_SAVE_USER:
-                                       if (pwc_save_user(pdev))
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_RESTORE_USER:
-                                       if (pwc_restore_user(pdev))
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_RESTORE_FACTORY:
-                                       if (pwc_restore_factory(pdev))
-                                               return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_COLOUR_MODE:
-                                       ret = pwc_set_colour_mode(pdev, c->value);
-                                       if (ret < 0)
-                                         return -EINVAL;
-                                       return 0;
-                               case V4L2_CID_PRIVATE_AUTOCONTOUR:
-                                 c->value=(c->value == 1)?-1:0;
-                                 ret = pwc_set_contour(pdev, c->value);
-                                 if (ret < 0)
-                                   return -EINVAL;
-                                 return 0;
-                               case V4L2_CID_PRIVATE_CONTOUR:
-                                 c->value <<= 10;
-                                 ret = pwc_set_contour(pdev, c->value);
-                                 if (ret < 0)
-                                   return -EINVAL;
-                                 return 0;
-                               case V4L2_CID_PRIVATE_BACKLIGHT:
-                                 ret = pwc_set_backlight(pdev, c->value);
-                                 if (ret < 0)
-                                   return -EINVAL;
-                                 return 0;
-                               case V4L2_CID_PRIVATE_FLICKERLESS:
-                                 ret = pwc_set_flicker(pdev, c->value);
-                                 if (ret < 0)
-                                   return -EINVAL;
-                               case V4L2_CID_PRIVATE_NOISE_REDUCTION:
-                                 ret = pwc_set_dynamic_noise(pdev, c->value);
-                                 if (ret < 0)
-                                   return -EINVAL;
-                                 return 0;
-
-                       }
+               return 0;
+       case V4L2_CID_SATURATION:
+               ret = pwc_get_saturation(pdev, &c->value);
+               if (ret < 0)
                        return -EINVAL;
-               }
+               return 0;
+       case V4L2_CID_GAMMA:
+               c->value = pwc_get_gamma(pdev);
+               if (c->value < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               ret = pwc_get_red_gain(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               c->value >>= 8;
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               ret = pwc_get_blue_gain(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               c->value >>= 8;
+               return 0;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               ret = pwc_get_awb(pdev);
+               if (ret < 0)
+                       return -EINVAL;
+               c->value = (ret == PWC_WB_MANUAL) ? 0 : 1;
+               return 0;
+       case V4L2_CID_GAIN:
+               ret = pwc_get_agc(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               c->value >>= 8;
+               return 0;
+       case V4L2_CID_AUTOGAIN:
+               ret = pwc_get_agc(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               c->value = (c->value < 0) ? 1 : 0;
+               return 0;
+       case V4L2_CID_EXPOSURE:
+               ret = pwc_get_shutter_speed(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_COLOUR_MODE:
+               ret = pwc_get_colour_mode(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_AUTOCONTOUR:
+               ret = pwc_get_contour(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               c->value = (c->value == -1 ? 1 : 0);
+               return 0;
+       case V4L2_CID_PRIVATE_CONTOUR:
+               ret = pwc_get_contour(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               c->value >>= 10;
+               return 0;
+       case V4L2_CID_PRIVATE_BACKLIGHT:
+               ret = pwc_get_backlight(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_FLICKERLESS:
+               ret = pwc_get_flicker(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               c->value = (c->value ? 1 : 0);
+               return 0;
+       case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+               ret = pwc_get_dynamic_noise(pdev, &c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
 
-               case VIDIOC_ENUM_FMT:
-               {
-                       struct v4l2_fmtdesc *f = arg;
-                       int index;
-
-                       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                             return -EINVAL;
-
-                       /* We only support two format: the raw format, and YUV */
-                       index = f->index;
-                       memset(f,0,sizeof(struct v4l2_fmtdesc));
-                       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       f->index = index;
-                       switch(index)
-                       {
-                               case 0:
-                                       /* RAW format */
-                                       f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2;
-                                       f->flags = V4L2_FMT_FLAG_COMPRESSED;
-                                       strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description));
-                                       break;
-                               case 1:
-                                       f->pixelformat = V4L2_PIX_FMT_YUV420;
-                                       strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description));
-                                       break;
-                               default:
-                                       return -EINVAL;
-                       }
-                       return 0;
-               }
+       case V4L2_CID_PRIVATE_SAVE_USER:
+       case V4L2_CID_PRIVATE_RESTORE_USER:
+       case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+               return -EINVAL;
+       }
+       return -EINVAL;
+}
 
-               case VIDIOC_G_FMT:
-               {
-                       struct v4l2_format *f = arg;
+static int pwc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int ret;
+
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               c->value <<= 9;
+               ret = pwc_set_brightness(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_CONTRAST:
+               c->value <<= 10;
+               ret = pwc_set_contrast(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_SATURATION:
+               ret = pwc_set_saturation(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_GAMMA:
+               c->value <<= 11;
+               ret = pwc_set_gamma(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               c->value <<= 8;
+               ret = pwc_set_red_gain(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               c->value <<= 8;
+               ret = pwc_set_blue_gain(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               c->value = (c->value == 0) ? PWC_WB_MANUAL : PWC_WB_AUTO;
+               ret = pwc_set_awb(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_EXPOSURE:
+               c->value <<= 8;
+               ret = pwc_set_shutter_speed(pdev, c->value ? 0 : 1, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_AUTOGAIN:
+               /* autogain off means nothing without a gain */
+               if (c->value == 0)
+                       return 0;
+               ret = pwc_set_agc(pdev, c->value, 0);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_GAIN:
+               c->value <<= 8;
+               ret = pwc_set_agc(pdev, 0, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_SAVE_USER:
+               if (pwc_save_user(pdev))
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_RESTORE_USER:
+               if (pwc_restore_user(pdev))
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+               if (pwc_restore_factory(pdev))
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_COLOUR_MODE:
+               ret = pwc_set_colour_mode(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_AUTOCONTOUR:
+               c->value = (c->value == 1) ? -1 : 0;
+               ret = pwc_set_contour(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_CONTOUR:
+               c->value <<= 10;
+               ret = pwc_set_contour(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_BACKLIGHT:
+               ret = pwc_set_backlight(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CID_PRIVATE_FLICKERLESS:
+               ret = pwc_set_flicker(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+       case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+               ret = pwc_set_dynamic_noise(pdev, c->value);
+               if (ret < 0)
+                       return -EINVAL;
+               return 0;
 
-                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y);
-                       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                             return -EINVAL;
+       }
+       return -EINVAL;
+}
 
-                       pwc_vidioc_fill_fmt(pdev, f);
+static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       /* We only support two format: the raw format, and YUV */
+       switch (f->index) {
+       case 0:
+               /* RAW format */
+               f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2;
+               f->flags = V4L2_FMT_FLAG_COMPRESSED;
+               strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description));
+               break;
+       case 1:
+               f->pixelformat = V4L2_PIX_FMT_YUV420;
+               strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description));
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
 
-                       return 0;
-               }
+static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct pwc_device *pdev = video_drvdata(file);
 
-               case VIDIOC_TRY_FMT:
-                       return pwc_vidioc_try_fmt(pdev, arg);
+       PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
+                       pdev->image.x, pdev->image.y);
+       pwc_vidioc_fill_fmt(pdev, f);
+       return 0;
+}
 
-               case VIDIOC_S_FMT:
-                       return pwc_vidioc_set_fmt(pdev, arg);
+static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct pwc_device *pdev = video_drvdata(file);
 
-               case VIDIOC_G_STD:
-               {
-                       v4l2_std_id *std = arg;
-                       *std = V4L2_STD_UNKNOWN;
-                       return 0;
-               }
+       return pwc_vidioc_try_fmt(pdev, f);
+}
 
-               case VIDIOC_S_STD:
-               {
-                       v4l2_std_id *std = arg;
-                       if (*std != V4L2_STD_UNKNOWN)
-                               return -EINVAL;
-                       return 0;
-               }
+static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct pwc_device *pdev = video_drvdata(file);
 
-               case VIDIOC_ENUMSTD:
-               {
-                       struct v4l2_standard *std = arg;
-                       if (std->index != 0)
-                               return -EINVAL;
-                       std->id = V4L2_STD_UNKNOWN;
-                       strlcpy(std->name, "webcam", sizeof(std->name));
-                       return 0;
-               }
+       return pwc_vidioc_set_fmt(pdev, f);
+}
 
-               case VIDIOC_REQBUFS:
-               {
-                       struct v4l2_requestbuffers *rb = arg;
-                       int nbuffers;
+static int pwc_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
+{
+       int nbuffers;
 
-                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count);
-                       if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                               return -EINVAL;
-                       if (rb->memory != V4L2_MEMORY_MMAP)
-                               return -EINVAL;
+       PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n", rb->count);
+       if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (rb->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
 
-                       nbuffers = rb->count;
-                       if (nbuffers < 2)
-                               nbuffers = 2;
-                       else if (nbuffers > pwc_mbufs)
-                               nbuffers = pwc_mbufs;
-                       /* Force to use our # of buffers */
-                       rb->count = pwc_mbufs;
-                       return 0;
-               }
+       nbuffers = rb->count;
+       if (nbuffers < 2)
+               nbuffers = 2;
+       else if (nbuffers > pwc_mbufs)
+               nbuffers = pwc_mbufs;
+       /* Force to use our # of buffers */
+       rb->count = pwc_mbufs;
+       return 0;
+}
 
-               case VIDIOC_QUERYBUF:
-               {
-                       struct v4l2_buffer *buf = arg;
-                       int index;
+static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int index;
 
-                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index);
-                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
-                               return -EINVAL;
-                       }
-                       if (buf->memory != V4L2_MEMORY_MMAP) {
-                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n");
-                               return -EINVAL;
-                       }
-                       index = buf->index;
-                       if (index < 0 || index >= pwc_mbufs) {
-                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
-                               return -EINVAL;
-                       }
+       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n", buf->index);
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
+               return -EINVAL;
+       }
+       index = buf->index;
+       if (index < 0 || index >= pwc_mbufs) {
+               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
+               return -EINVAL;
+       }
 
-                       memset(buf, 0, sizeof(struct v4l2_buffer));
-                       buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       buf->index = index;
-                       buf->m.offset = index * pdev->len_per_image;
-                       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-                               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
-                       else
-                               buf->bytesused = pdev->view.size;
-                       buf->field = V4L2_FIELD_NONE;
-                       buf->memory = V4L2_MEMORY_MMAP;
-                       //buf->flags = V4L2_BUF_FLAG_MAPPED;
-                       buf->length = pdev->len_per_image;
-
-                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index);
-                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset);
-                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused);
+       buf->m.offset = index * pdev->len_per_image;
+       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
+               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+       else
+               buf->bytesused = pdev->view.size;
+       buf->field = V4L2_FIELD_NONE;
+       buf->memory = V4L2_MEMORY_MMAP;
+       /*buf->flags = V4L2_BUF_FLAG_MAPPED;*/
+       buf->length = pdev->len_per_image;
 
-                       return 0;
-               }
+       PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n", buf->index);
+       PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n", buf->m.offset);
+       PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n", buf->bytesused);
 
-               case VIDIOC_QBUF:
-               {
-                       struct v4l2_buffer *buf = arg;
+       return 0;
+}
 
-                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index);
-                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                               return -EINVAL;
-                       if (buf->memory != V4L2_MEMORY_MMAP)
-                               return -EINVAL;
-                       if (buf->index >= pwc_mbufs)
-                               return -EINVAL;
+static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n", buf->index);
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (buf->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+       if (buf->index >= pwc_mbufs)
+               return -EINVAL;
 
-                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
-                       buf->flags &= ~V4L2_BUF_FLAG_DONE;
+       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+       buf->flags &= ~V4L2_BUF_FLAG_DONE;
 
-                       return 0;
-               }
+       return 0;
+}
 
-               case VIDIOC_DQBUF:
-               {
-                       struct v4l2_buffer *buf = arg;
-                       int ret;
+static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       struct pwc_device *pdev = video_drvdata(file);
+       int ret;
 
-                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
+       PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
 
-                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                               return -EINVAL;
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
 
-                       /* Add ourselves to the frame wait-queue.
-
-                          FIXME: needs auditing for safety.
-                          QUESTION: In what respect? I think that using the
-                                    frameq is safe now.
-                        */
-                       add_wait_queue(&pdev->frameq, &wait);
-                       while (pdev->full_frames == NULL) {
-                               if (pdev->error_status) {
-                                       remove_wait_queue(&pdev->frameq, &wait);
-                                       set_current_state(TASK_RUNNING);
-                                       return -pdev->error_status;
-                               }
+       add_wait_queue(&pdev->frameq, &wait);
+       while (pdev->full_frames == NULL) {
+               if (pdev->error_status) {
+                       remove_wait_queue(&pdev->frameq, &wait);
+                       set_current_state(TASK_RUNNING);
+                       return -pdev->error_status;
+               }
 
-                               if (signal_pending(current)) {
-                                       remove_wait_queue(&pdev->frameq, &wait);
-                                       set_current_state(TASK_RUNNING);
-                                       return -ERESTARTSYS;
-                               }
-                               mutex_unlock(&pdev->modlock);
-                               schedule();
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               mutex_lock(&pdev->modlock);
-                       }
+               if (signal_pending(current)) {
                        remove_wait_queue(&pdev->frameq, &wait);
                        set_current_state(TASK_RUNNING);
+                       return -ERESTARTSYS;
+               }
+               mutex_unlock(&pdev->modlock);
+               schedule();
+               set_current_state(TASK_INTERRUPTIBLE);
+               mutex_lock(&pdev->modlock);
+       }
+       remove_wait_queue(&pdev->frameq, &wait);
+       set_current_state(TASK_RUNNING);
 
-                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
-                       /* Decompress data in pdev->images[pdev->fill_image] */
-                       ret = pwc_handle_frame(pdev);
-                       if (ret)
-                               return -EFAULT;
-                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
-
-                       buf->index = pdev->fill_image;
-                       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-                               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
-                       else
-                               buf->bytesused = pdev->view.size;
-                       buf->flags = V4L2_BUF_FLAG_MAPPED;
-                       buf->field = V4L2_FIELD_NONE;
-                       do_gettimeofday(&buf->timestamp);
-                       buf->sequence = 0;
-                       buf->memory = V4L2_MEMORY_MMAP;
-                       buf->m.offset = pdev->fill_image * pdev->len_per_image;
-                       buf->length = pdev->len_per_image;
-                       pwc_next_image(pdev);
-
-                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index);
-                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length);
-                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset);
-                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused);
-                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
-                       return 0;
+       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
+       /* Decompress data in pdev->images[pdev->fill_image] */
+       ret = pwc_handle_frame(pdev);
+       if (ret)
+               return -EFAULT;
+       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
+
+       buf->index = pdev->fill_image;
+       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
+               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+       else
+               buf->bytesused = pdev->view.size;
+       buf->flags = V4L2_BUF_FLAG_MAPPED;
+       buf->field = V4L2_FIELD_NONE;
+       do_gettimeofday(&buf->timestamp);
+       buf->sequence = 0;
+       buf->memory = V4L2_MEMORY_MMAP;
+       buf->m.offset = pdev->fill_image * pdev->len_per_image;
+       buf->length = pdev->len_per_image;
+       pwc_next_image(pdev);
+
+       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n", buf->index);
+       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n", buf->length);
+       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n", buf->m.offset);
+       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n", buf->bytesused);
+       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
+       return 0;
 
-               }
+}
 
-               case VIDIOC_STREAMON:
-               {
-                       return pwc_isoc_init(pdev);
-               }
+static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+       struct pwc_device *pdev = video_drvdata(file);
 
-               case VIDIOC_STREAMOFF:
-               {
-                       pwc_isoc_cleanup(pdev);
-                       return 0;
-               }
+       return pwc_isoc_init(pdev);
+}
 
-               case VIDIOC_ENUM_FRAMESIZES:
-               {
-                       struct v4l2_frmsizeenum *fsize = arg;
-                       unsigned int i = 0, index = fsize->index;
-
-                       if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
-                               for (i = 0; i < PSZ_MAX; i++) {
-                                       if (pdev->image_mask & (1UL << i)) {
-                                               if (!index--) {
-                                                       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-                                                       fsize->discrete.width = pwc_image_sizes[i].x;
-                                                       fsize->discrete.height = pwc_image_sizes[i].y;
-                                                       return 0;
-                                               }
-                                       }
-                               }
-                       } else if (fsize->index == 0 &&
-                                  ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
-                                   (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
-
-                               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-                               fsize->discrete.width = pdev->abs_max.x;
-                               fsize->discrete.height = pdev->abs_max.y;
-                               return 0;
-                       }
-                       return -EINVAL;
-               }
+static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+       struct pwc_device *pdev = video_drvdata(file);
 
-               case VIDIOC_ENUM_FRAMEINTERVALS:
-               {
-                       struct v4l2_frmivalenum *fival = arg;
-                       int size = -1;
-                       unsigned int i;
-
-                       for (i = 0; i < PSZ_MAX; i++) {
-                               if (pwc_image_sizes[i].x == fival->width &&
-                                   pwc_image_sizes[i].y == fival->height) {
-                                       size = i;
-                                       break;
+       pwc_isoc_cleanup(pdev);
+       return 0;
+}
+
+static int pwc_enum_framesizes(struct file *file, void *fh,
+                                        struct v4l2_frmsizeenum *fsize)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       unsigned int i = 0, index = fsize->index;
+
+       if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
+               for (i = 0; i < PSZ_MAX; i++) {
+                       if (pdev->image_mask & (1UL << i)) {
+                               if (!index--) {
+                                       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+                                       fsize->discrete.width = pwc_image_sizes[i].x;
+                                       fsize->discrete.height = pwc_image_sizes[i].y;
+                                       return 0;
                                }
                        }
+               }
+       } else if (fsize->index == 0 &&
+                       ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
+                        (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
+
+               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               fsize->discrete.width = pdev->abs_max.x;
+               fsize->discrete.height = pdev->abs_max.y;
+               return 0;
+       }
+       return -EINVAL;
+}
 
-                       /* TODO: Support raw format */
-                       if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420) {
-                               return -EINVAL;
-                       }
+static int pwc_enum_frameintervals(struct file *file, void *fh,
+                                          struct v4l2_frmivalenum *fival)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int size = -1;
+       unsigned int i;
+
+       for (i = 0; i < PSZ_MAX; i++) {
+               if (pwc_image_sizes[i].x == fival->width &&
+                               pwc_image_sizes[i].y == fival->height) {
+                       size = i;
+                       break;
+               }
+       }
 
-                       i = pwc_get_fps(pdev, fival->index, size);
-                       if (!i)
-                               return -EINVAL;
+       /* TODO: Support raw format */
+       if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420)
+               return -EINVAL;
 
-                       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-                       fival->discrete.numerator = 1;
-                       fival->discrete.denominator = i;
+       i = pwc_get_fps(pdev, fival->index, size);
+       if (!i)
+               return -EINVAL;
 
-                       return 0;
-               }
+       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       fival->discrete.numerator = 1;
+       fival->discrete.denominator = i;
 
-               default:
-                       return pwc_ioctl(pdev, cmd, arg);
-       } /* ..switch */
        return 0;
 }
 
+static long pwc_default(struct file *file, void *fh, int cmd, void *arg)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       return pwc_ioctl(pdev, cmd, arg);
+}
+
+const struct v4l2_ioctl_ops pwc_ioctl_ops = {
+       .vidioc_querycap                    = pwc_querycap,
+       .vidioc_enum_input                  = pwc_enum_input,
+       .vidioc_g_input                     = pwc_g_input,
+       .vidioc_s_input                     = pwc_s_input,
+       .vidioc_enum_fmt_vid_cap            = pwc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap               = pwc_g_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap               = pwc_s_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap             = pwc_try_fmt_vid_cap,
+       .vidioc_queryctrl                   = pwc_queryctrl,
+       .vidioc_g_ctrl                      = pwc_g_ctrl,
+       .vidioc_s_ctrl                      = pwc_s_ctrl,
+       .vidioc_reqbufs                     = pwc_reqbufs,
+       .vidioc_querybuf                    = pwc_querybuf,
+       .vidioc_qbuf                        = pwc_qbuf,
+       .vidioc_dqbuf                       = pwc_dqbuf,
+       .vidioc_streamon                    = pwc_streamon,
+       .vidioc_streamoff                   = pwc_streamoff,
+       .vidioc_enum_framesizes             = pwc_enum_framesizes,
+       .vidioc_enum_frameintervals         = pwc_enum_frameintervals,
+       .vidioc_default             = pwc_default,
+};
+
+
 /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index 16bbc6d..e947766 100644 (file)
@@ -339,8 +339,7 @@ extern int pwc_camera_power(struct pwc_device *pdev, int power);
 /* Private ioctl()s; see pwc-ioctl.h */
 extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
 
-/** Functions in pwc-v4l.c */
-extern long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
+extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
 
 /** pwc-uncompress.c */
 /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */