v4l: Support extending the v4l2_pix_format structure
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tue, 27 May 2014 12:41:05 +0000 (14:41 +0200)
committerStephane Desneux <stephane.desneux@open.eurogiciel.org>
Wed, 4 Feb 2015 10:15:24 +0000 (11:15 +0100)
The v4l2_pix_format structure has no reserved field. It is embedded in
the v4l2_framebuffer structure which has no reserved fields either, and
in the v4l2_format structure which has reserved fields that were not
previously required to be zeroed out by applications.

To allow extending v4l2_pix_format, inline it in the v4l2_framebuffer
structure, and use the priv field as a magic value to indicate that the
application has set all v4l2_pix_format extended fields and zeroed all
reserved fields following the v4l2_pix_format field in the v4l2_format
structure.

The availability of this API extension is reported to userspace through
the new V4L2_CAP_EXT_PIX_FORMAT capability flag. Just checking that the
priv field is still set to the magic value at [GS]_FMT return wouldn't
be enough, as older kernels don't zero the priv field on return.

To simplify the internal API towards drivers zero the extended fields
and set the priv field to the magic value for applications not aware of
the extensions.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
(cherry picked from commit af7553db487e1dbcd069d1bb9426fc8c591ea1f4)
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Conflicts:
Documentation/DocBook/media/v4l/v4l2.xml
Documentation/DocBook/media/v4l/vidioc-querycap.xml
drivers/media/platform/davinci/vpif_display.c
drivers/media/platform/mem2mem_testdev.c
include/uapi/linux/videodev2.h

26 files changed:
Documentation/DocBook/media/Makefile
Documentation/DocBook/media/v4l/pixfmt.xml
drivers/media/parport/bw-qcam.c
drivers/media/pci/cx18/cx18-ioctl.c
drivers/media/pci/cx25821/cx25821-video.c
drivers/media/pci/ivtv/ivtv-ioctl.c
drivers/media/pci/meye/meye.c
drivers/media/pci/saa7134/saa7134-empress.c
drivers/media/pci/saa7134/saa7134-video.c
drivers/media/pci/sta2x11/sta2x11_vip.c
drivers/media/platform/coda.c
drivers/media/platform/omap/omap_vout.c
drivers/media/platform/sh_veu.c
drivers/media/platform/vino.c
drivers/media/platform/vivi.c
drivers/media/usb/cx231xx/cx231xx-417.c
drivers/media/usb/cx231xx/cx231xx-video.c
drivers/media/usb/gspca/gspca.c
drivers/media/usb/hdpvr/hdpvr-video.c
drivers/media/usb/stkwebcam/stk-webcam.c
drivers/media/usb/tlg2300/pd-video.c
drivers/media/usb/tm6000/tm6000-video.c
drivers/media/usb/zr364xx/zr364xx.c
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/media/v4l2-core/v4l2-ioctl.c
include/uapi/linux/videodev2.h

index 1d27f0a..494da94 100644 (file)
@@ -174,7 +174,7 @@ FILENAME = \
 DOCUMENTED = \
        -e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1<link linkend=\"\2\">v4l2_mpeg_cx2341x_video_\2<\/link>/g" \
        -e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1<link linkend=\"\3\">\3<\/link>/g" \
-       -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /<link linkend=\"\1\">\1<\/link> /g" \
+       -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\)\(\s\+v4l2_fourcc\)/<link linkend=\"\1\">\1<\/link>\2/g" \
        -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
        -e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g"
 
index 72d72bd..6e1e520 100644 (file)
@@ -103,9 +103,28 @@ see <xref linkend="colorspaces" />.</entry>
        <row>
          <entry>__u32</entry>
          <entry><structfield>priv</structfield></entry>
-         <entry>Reserved for custom (driver defined) additional
-information about formats. When not used drivers and applications must
-set this field to zero.</entry>
+         <entry><para>This field indicates whether the remaining fields of the
+<structname>v4l2_pix_format</structname> structure, also called the extended
+fields, are valid. When set to <constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, it
+indicates that the extended fields have been correctly initialized. When set to
+any other value it indicates that the extended fields contain undefined values.
+</para>
+<para>Applications that wish to use the pixel format extended fields must first
+ensure that the feature is supported by querying the device for the
+<link linkend="querycap"><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></link>
+capability. If the capability isn't set the pixel format extended fields are not
+supported and using the extended fields will lead to undefined results.</para>
+<para>To use the extended fields, applications must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, initialize all the extended fields
+and zero the unused bytes of the <structname>v4l2_format</structname>
+<structfield>raw_data</structfield> field.</para>
+<para>When the <structfield>priv</structfield> field isn't set to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> drivers must act as if all the
+extended fields were set to zero. On return drivers must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> and all the extended field to
+applicable values.</para></entry>
        </row>
       </tbody>
     </tgroup>
index d12bd33..b711b5b 100644 (file)
@@ -757,7 +757,6 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
        pix->sizeimage = pix->width * pix->height;
        /* Just a guess */
        pix->colorspace = V4L2_COLORSPACE_SRGB;
-       pix->priv = 0;
        return 0;
 }
 
@@ -783,7 +782,6 @@ static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format
        pix->sizeimage = pix->width * pix->height;
        /* Just a guess */
        pix->colorspace = V4L2_COLORSPACE_SRGB;
-       pix->priv = 0;
        return 0;
 }
 
index 1110bcb..c4c3ff3 100644 (file)
@@ -156,7 +156,6 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
        pixfmt->height = cx->cxhdl.height;
        pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
        pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
        if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
                pixfmt->pixelformat = s->pixelformat;
                pixfmt->sizeimage = s->vb_bytes_per_frame;
index d270819..c7ae087 100644 (file)
@@ -576,7 +576,6 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
        f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -615,7 +614,6 @@ static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -867,7 +865,6 @@ static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv,
        f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
index 807b275..d4d0f0e 100644 (file)
@@ -351,7 +351,6 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
        pixfmt->height = itv->cxhdl.height;
        pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
        pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
        if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
                pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
                /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
@@ -418,7 +417,6 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
        pixfmt->height = itv->main_rect.height;
        pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
        pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
        if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
                switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
                case IVTV_YUV_MODE_INTERLACED:
@@ -1384,7 +1382,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
        fb->fmt.bytesperline = fb->fmt.width;
        fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
        fb->fmt.field = V4L2_FIELD_INTERLACED;
-       fb->fmt.priv = 0;
        if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
                fb->fmt.bytesperline *= 2;
        if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
index 54d5c82..4e7fba0 100644 (file)
@@ -1166,7 +1166,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
        f->fmt.pix.sizeimage = f->fmt.pix.height *
                               f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = 0;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -1232,7 +1231,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
        f->fmt.pix.sizeimage = f->fmt.pix.height *
                               f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = 0;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
index 0a9047e..71bf872 100644 (file)
@@ -189,7 +189,6 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -207,7 +206,6 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -225,7 +223,6 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
index 40396e8..c8c2215 100644 (file)
@@ -1347,7 +1347,6 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.sizeimage =
                f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
@@ -1429,7 +1428,6 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.sizeimage =
                f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
index e5cfb6c..7219c59 100644 (file)
@@ -642,7 +642,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
        f->fmt.pix.sizeimage = f->fmt.pix.width * 2 * f->fmt.pix.height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
index 61f3dbc..21c31bc 100644 (file)
@@ -613,8 +613,6 @@ static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec,
                BUG();
        }
 
-       f->fmt.pix.priv = 0;
-
        return 0;
 }
 
index dfd0a21..17b4440 100644 (file)
@@ -165,7 +165,6 @@ static int omap_vout_try_format(struct v4l2_pix_format *pix)
 
        pix->pixelformat = omap_formats[ifmt].pixelformat;
        pix->field = V4L2_FIELD_ANY;
-       pix->priv = 0;
 
        switch (pix->pixelformat) {
        case V4L2_PIX_FMT_YUYV:
@@ -1895,7 +1894,6 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
        pix->field = V4L2_FIELD_ANY;
        pix->bytesperline = pix->width * 2;
        pix->sizeimage = pix->bytesperline * pix->height;
-       pix->priv = 0;
        pix->colorspace = V4L2_COLORSPACE_JPEG;
 
        vout->bpp = RGB565_BPP;
index 744e43b..8dc279d 100644 (file)
@@ -425,7 +425,6 @@ static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
        pix->bytesperline       = vfmt->bytesperline;
        pix->sizeimage          = vfmt->bytesperline * pix->height *
                vfmt->fmt->depth / vfmt->fmt->ydepth;
-       pix->priv               = 0;
        dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__,
                f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat);
 
@@ -473,7 +472,6 @@ static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt
 
        pix->pixelformat        = fmt->fourcc;
        pix->colorspace         = sh_veu_4cc2cspace(pix->pixelformat);
-       pix->priv               = 0;
 
        pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage);
 
index c6af974..e58796e 100644 (file)
@@ -3147,7 +3147,6 @@ static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
        pf->colorspace =
                vino_data_formats[tempvcs.data_format].colorspace;
 
-       pf->priv = 0;
        return 0;
 }
 
@@ -3175,8 +3174,6 @@ static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
        pf->colorspace =
                vino_data_formats[vcs->data_format].colorspace;
 
-       pf->priv = 0;
-
        spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
        return 0;
 }
@@ -3219,8 +3216,6 @@ static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
        pf->colorspace =
                vino_data_formats[vcs->data_format].colorspace;
 
-       pf->priv = 0;
-
        spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
        return 0;
 }
index 2d4e73b..4807225 100644 (file)
@@ -1015,7 +1015,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
        else
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
index 2f63029..78a2e34 100644 (file)
@@ -1563,7 +1563,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.width = dev->ts1.width;
        f->fmt.pix.height = dev->ts1.height;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.priv = 0;
        dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
                dev->ts1.width, dev->ts1.height);
        dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
@@ -1582,7 +1581,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
        dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
                dev->ts1.width, dev->ts1.height);
        dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
index 9906261..71f1083 100644 (file)
@@ -886,7 +886,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -931,7 +930,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
index f3a7ace..1b3d7bf 100644 (file)
@@ -1102,8 +1102,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        struct gspca_dev *gspca_dev = video_drvdata(file);
 
        fmt->fmt.pix = gspca_dev->pixfmt;
-       /* some drivers use priv internally, zero it before giving it to
-          userspace */
+       /* some drivers use priv internally, zero it before giving it back to
+          the core */
        fmt->fmt.pix.priv = 0;
        return 0;
 }
@@ -1139,8 +1139,8 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
                fmt->fmt.pix.height = h;
                gspca_dev->sd_desc->try_fmt(gspca_dev, fmt);
        }
-       /* some drivers use priv internally, zero it before giving it to
-          userspace */
+       /* some drivers use priv internally, zero it before giving it back to
+          the core */
        fmt->fmt.pix.priv = 0;
        return mode;                    /* used when s_fmt */
 }
index 6bce01a..caeae8f 100644 (file)
@@ -1022,7 +1022,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh,
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.sizeimage    = dev->bulk_in_size;
        f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.priv         = 0;
        if (f->fmt.pix.width == 720) {
                /* SDTV formats */
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
index be77482..adfa832 100644 (file)
@@ -923,7 +923,6 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
                pix_format->bytesperline = 2 * pix_format->width;
        pix_format->sizeimage = pix_format->bytesperline
                                * pix_format->height;
-       pix_format->priv = 0;
        return 0;
 }
 
@@ -967,7 +966,6 @@ static int stk_try_fmt_vid_cap(struct file *filp,
                fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
        fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline
                * fmtd->fmt.pix.height;
-       fmtd->fmt.pix.priv = 0;
        return 0;
 }
 
index 8df668d..8cd7f02 100644 (file)
@@ -1321,7 +1321,6 @@ static void init_video_context(struct running_context *context)
                                .bytesperline   = 720 * 2,
                                .sizeimage      = 720 * 576 * 2,
                                .colorspace     = V4L2_COLORSPACE_SMPTE170M,
-                               .priv           = 0
                        };
 }
 
index cc1aa14..97ad689 100644 (file)
@@ -918,7 +918,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
                (f->fmt.pix.width * fh->fmt->depth) >> 3;
        f->fmt.pix.sizeimage =
                f->fmt.pix.height * f->fmt.pix.bytesperline;
-       f->fmt.pix.priv = 0;
 
        return 0;
 }
@@ -959,7 +958,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.width &= ~0x01;
 
        f->fmt.pix.field = field;
-       f->fmt.pix.priv = 0;
 
        f->fmt.pix.bytesperline =
                (f->fmt.pix.width * fmt->depth) >> 3;
index 74d56df..0f63954 100644 (file)
@@ -806,7 +806,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
        DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
            decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
            f->fmt.pix.field);
@@ -829,7 +828,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
        return 0;
 }
 
@@ -866,7 +864,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
        cam->vb_vidq.field = f->fmt.pix.field;
 
        if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
index fca336b..d0d6530 100644 (file)
@@ -540,7 +540,16 @@ struct v4l2_framebuffer32 {
        __u32                   capability;
        __u32                   flags;
        compat_caddr_t          base;
-       struct v4l2_pix_format  fmt;
+       struct {
+               __u32           width;
+               __u32           height;
+               __u32           pixelformat;
+               __u32           field;
+               __u32           bytesperline;
+               __u32           sizeimage;
+               __u32           colorspace;
+               __u32           priv;
+       } fmt;
 };
 
 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
@@ -550,10 +559,10 @@ static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
        if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
                get_user(tmp, &up->base) ||
                get_user(kp->capability, &up->capability) ||
-               get_user(kp->flags, &up->flags))
+               get_user(kp->flags, &up->flags) ||
+               copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
                        return -EFAULT;
        kp->base = compat_ptr(tmp);
-       get_v4l2_pix_format(&kp->fmt, &up->fmt);
        return 0;
 }
 
@@ -564,9 +573,9 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
        if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
                put_user(tmp, &up->base) ||
                put_user(kp->capability, &up->capability) ||
-               put_user(kp->flags, &up->flags))
+               put_user(kp->flags, &up->flags) ||
+               copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
                        return -EFAULT;
-       put_v4l2_pix_format(&kp->fmt, &up->fmt);
        return 0;
 }
 
index 707aef7..feb9e34 100644 (file)
@@ -936,13 +936,48 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
        return -EINVAL;
 }
 
+static void v4l_sanitize_format(struct v4l2_format *fmt)
+{
+       unsigned int offset;
+
+       /*
+        * The v4l2_pix_format structure has been extended with fields that were
+        * not previously required to be set to zero by applications. The priv
+        * field, when set to a magic value, indicates the the extended fields
+        * are valid. Otherwise they will contain undefined values. To simplify
+        * the API towards drivers zero the extended fields and set the priv
+        * field to the magic value when the extended pixel format structure
+        * isn't used by applications.
+        */
+
+       if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return;
+
+       if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
+               return;
+
+       fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+       offset = offsetof(struct v4l2_pix_format, priv)
+              + sizeof(fmt->fmt.pix.priv);
+       memset(((void *)&fmt->fmt.pix) + offset, 0,
+              sizeof(fmt->fmt.pix) - offset);
+}
+
 static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_capability *cap = (struct v4l2_capability *)arg;
+       int ret;
 
        cap->version = LINUX_VERSION_CODE;
-       return ops->vidioc_querycap(file, fh, cap);
+
+       ret = ops->vidioc_querycap(file, fh, cap);
+
+       cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
+
+       return ret;
 }
 
 static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
@@ -1061,12 +1096,17 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
        bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+       int ret;
+
+       v4l_sanitize_format(p);
 
        switch (p->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
                        break;
-               return ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+               ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+               p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+               return ret;
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
                if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
                        break;
@@ -1086,7 +1126,9 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
                if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
                        break;
-               return ops->vidioc_g_fmt_vid_out(file, fh, arg);
+               ret = ops->vidioc_g_fmt_vid_out(file, fh, arg);
+               p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+               return ret;
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
                if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
                        break;
@@ -1446,7 +1488,18 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
        struct v4l2_create_buffers *create = arg;
        int ret = check_fmt(file, create->format.type);
 
-       return ret ? ret : ops->vidioc_create_bufs(file, fh, create);
+       if (ret)
+               return ret;
+
+       v4l_sanitize_format(&create->format);
+
+       ret = ops->vidioc_create_bufs(file, fh, create);
+
+       if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+       return ret;
 }
 
 static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
index 63274c1..e6b41cf 100644 (file)
@@ -264,6 +264,7 @@ struct v4l2_capability {
 #define V4L2_CAP_RADIO                 0x00040000  /* is a radio device */
 #define V4L2_CAP_MODULATOR             0x00080000  /* has a modulator */
 
+#define V4L2_CAP_EXT_PIX_FORMAT                0x00200000  /* Supports the extended pixel format */
 #define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
 #define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
 #define V4L2_CAP_STREAMING              0x04000000  /* streaming I/O ioctls */
@@ -439,6 +440,9 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
 #define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
 
+/* priv field value to indicates that subsequent fields are valid. */
+#define V4L2_PIX_FMT_PRIV_MAGIC                0xdeadbeef
+
 /*
  *     F O R M A T   E N U M E R A T I O N
  */
@@ -732,7 +736,16 @@ struct v4l2_framebuffer {
 /* FIXME: in theory we should pass something like PCI device + memory
  * region + offset instead of some physical address */
        void                    *base;
-       struct v4l2_pix_format  fmt;
+       struct {
+               __u32           width;
+               __u32           height;
+               __u32           pixelformat;
+               __u32           field;          /* enum v4l2_field */
+               __u32           bytesperline;   /* for padding, zero if unused */
+               __u32           sizeimage;
+               __u32           colorspace;     /* enum v4l2_colorspace */
+               __u32           priv;           /* private data, depends on pixelformat */
+       } fmt;
 };
 /*  Flags for the 'capability' field. Read only */
 #define V4L2_FBUF_CAP_EXTERNOVERLAY    0x0001