[PATCH] cafe_ccic: add support for VIDIOC_ENUM_FRAMESIZES and VIDIOC_ENUM_FRAMEINTERVALS

Dan Williams dcbw at redhat.com
Fri Jul 6 17:37:45 EDT 2007


Newer gstreamer v4l2 plugins require these ioctls to determine supported
frame sizes and rates.  Unfortunately, the kernel v4l2 bits don't have
members in 'struct video_device' for these ioctls, so we have to
override the generic ioctl handler for these two functions.  They report
only VGA size @ 30fps as being supported for now.

Signed-off-by: Dan Williams <dcbw at redhat.com>

diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 4710044..41cdb69 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -1716,6 +1716,63 @@ static int cafe_vidioc_s_parm(struct file *filp, void *priv,
 	return ret;
 }
 
+static int cafe_vidioc_enum_framesizes(struct cafe_camera* cam,
+		void __user * arg)
+{
+	struct v4l2_frmsizeenum frmsize;
+
+	if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
+		return -EFAULT;
+
+	if (frmsize.index != 0)
+		return -EINVAL;
+
+	if (frmsize.pixel_format != V4L2_PIX_FMT_YUYV &&
+	    frmsize.pixel_format != V4L2_PIX_FMT_RGB444 &&
+	    frmsize.pixel_format != V4L2_PIX_FMT_RGB565)
+		return -EINVAL;
+
+	frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE;
+
+	frmsize.discrete.width = VGA_WIDTH;
+	frmsize.discrete.height = VGA_HEIGHT;
+	memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
+
+	if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int cafe_vidioc_enum_frameintervals(struct cafe_camera* cam,
+		void __user * arg)
+{
+	struct v4l2_frmivalenum frmival;
+
+	if (copy_from_user(&frmival, arg, sizeof(frmival)))
+		return -EFAULT;
+
+	if (frmival.index != 0)
+		return -EINVAL;
+
+	if (frmival.pixel_format != V4L2_PIX_FMT_YUYV &&
+	    frmival.pixel_format != V4L2_PIX_FMT_RGB444 &&
+	    frmival.pixel_format != V4L2_PIX_FMT_RGB565)
+		return -EINVAL;
+
+	if (frmival.width != VGA_WIDTH || frmival.height != VGA_HEIGHT)
+		return -EINVAL;
+
+	frmival.type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	frmival.discrete.numerator = 1;
+	frmival.discrete.denominator = 30;
+	memset(&frmival.reserved, 0, sizeof(frmival.reserved));
+
+	if (copy_to_user(arg, &frmival, sizeof(frmival)))
+		return -EFAULT;
+
+	return 0;
+}
 
 static void cafe_v4l_dev_release(struct video_device *vd)
 {
@@ -1724,6 +1781,23 @@ static void cafe_v4l_dev_release(struct video_device *vd)
 	kfree(cam);
 }
 
+static int cafe_v4l_ioctl(struct inode* inode, struct file* filp,
+			     unsigned int cmd, unsigned long arg)
+{
+	struct cafe_camera *cam = filp->private_data;
+
+	switch (cmd) {
+	case VIDIOC_ENUM_FRAMESIZES:
+		return cafe_vidioc_enum_framesizes(cam, (void __user *)arg);
+	case VIDIOC_ENUM_FRAMEINTERVALS:
+		return cafe_vidioc_enum_frameintervals(cam, (void __user *)arg);
+	default:
+		break;
+	}
+
+	return video_ioctl2(inode, filp, cmd, arg);
+}
+
 
 /*
  * This template device holds all of those v4l2 methods; we
@@ -1737,7 +1811,7 @@ static const struct file_operations cafe_v4l_fops = {
 	.read = cafe_v4l_read,
 	.poll = cafe_v4l_poll,
 	.mmap = cafe_v4l_mmap,
-	.ioctl = video_ioctl2,
+	.ioctl = cafe_v4l_ioctl,
 	.llseek = no_llseek,
 };
 





More information about the Devel mailing list