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 1d27f0a1abd1e1872b0e05693ab35d6ecd64b0f2..494da944b39db6c298337f58764cc23058d52ec4 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 72d72bd67d0a9eb00836b5495a0b9e6c4821d5f3..6e1e520a2750a27cd086093ccc48e656b1699f55 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 d12bd33f39cb3c7f322a0ef4d2965d1ebfa542c6..b711b5b5b01a6c954df6209b30c5c4632fbb13fd 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 1110bcb14e2f680a9436b1af21a21546bb2413b2..c4c3ff30d0a3339396dfa3d202a620df7a2728fc 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 d270819fd8751417bb6fb60c2af1483e23a8a19a..c7ae087b668b9460172c1bd153fbb24378cd0e5a 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 807b275a847e696b762c10d083874b618d30ee89..d4d0f0ecab98449bdb76142de619b3ac9b300209 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 54d5c821007cb4280ff5a41e5fbda3bfd2f5484c..4e7fba034a314cf4760b2f7aabec8ddbec0f277a 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 0a9047e754b9765de54f6e99ff791d68be0bb305..71bf87204c5b18bfdcd443cd61a2b09b070ce143 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 40396e8b16a870df37d19b1276ddfbf6ee41a8b4..c8c22156991b9d551307131b5d041f9c98e97791 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 e5cfb6cfa18da513e70e7e41d9a06084eedd1555..7219c598ef5082ff9309e45ba020b479155dc65e 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 61f3dbcc259f40f8a0f6f2b4bfa9b52ed6bf24ee..21c31bc5c380eccca47d298653298a30c1493f76 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 dfd0a21a06588b26ee7ccc290e59e9f853175ea2..17b44401948e2b5ddf4deb2972c7740283f32be1 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 744e43b480bcc217f3da9522cc992061fa7f691a..8dc279d4d5610fac3219cb253aa9d383108ab3d4 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 c6af974c5b45c82eced9d54ee8d2337b2d276800..e58796e66ab1496236567174f503fb7ad1a3e876 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 2d4e73b45c5e3b05d7e4615f6f6fd0d46bd56656..4807225d63db01da6ae43616608908872be66977 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 2f63029e7a363675c62d17955a4d4c5fdc974fae..78a2e34a3286505a8dd1122ec2002f5d44941fd3 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 990626101718c54369538c2391d9ac4de4008e46..71f10832f97b8de12b5281958bc8c1134aa604e9 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 f3a7ace0fac9cc8bd4e2b2c8b82038dc85aa7068..1b3d7bf8dab690d57299dcc9abaae6504c2ce946 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 6bce01a674f9e12f9874636e962378f6965a4fad..caeae8ff365bce654557a6ce1667eed94c7b5ca7 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 be77482c30704a5b81615199f563770c0147ec0f..adfa8320849ab2a1f9320f99c6b1fae4af0e8a40 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 8df668d06552bb4323ab0213889d12105e09422f..8cd7f02fcf9fc7080ea6444bfb56c50854c6c80e 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 cc1aa14996ff04ebc75f4d8c050075bb34c7128e..97ad689c794e5a62d60014c106b63f0098bc957d 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 74d56df3347f59329ec6c4538023592c863bc1ac..0f63954ee1d448ef6d7bec5b59147b8244339e7d 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 fca336b65351d40dd06922ddcfc7e1a0012bf578..d0d6530c0b64bdc7495f91d48b82825fb33bb547 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 707aef705a475bd49fac2cdcf78e06f5e30c5ccd..feb9e3441c9d070f815c0f873321e0e24c2e580c 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 63274c1d037c88fbe28f2b7171b45e4d39e6bf13..e6b41cf2c6b28c17bb2714d96decbf9fc1323844 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