aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core/v4l2-ioctl.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-05-27 08:41:05 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-17 11:44:47 -0400
commitd52e23813672c3c72f92e7b39c7408d4b9a40a96 (patch)
treea06c0a574588b3222a6795064c2ca4da37ceea91 /drivers/media/v4l2-core/v4l2-ioctl.c
parentb04ef7c075e8806fa18bc849e32d6a3163150cec (diff)
[media] v4l: Support extending the v4l2_pix_format structure
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> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c')
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c65
1 files changed, 61 insertions, 4 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 96bc117f66b2..2e630005676f 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -973,13 +973,48 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
973 return -EINVAL; 973 return -EINVAL;
974} 974}
975 975
976static void v4l_sanitize_format(struct v4l2_format *fmt)
977{
978 unsigned int offset;
979
980 /*
981 * The v4l2_pix_format structure has been extended with fields that were
982 * not previously required to be set to zero by applications. The priv
983 * field, when set to a magic value, indicates the the extended fields
984 * are valid. Otherwise they will contain undefined values. To simplify
985 * the API towards drivers zero the extended fields and set the priv
986 * field to the magic value when the extended pixel format structure
987 * isn't used by applications.
988 */
989
990 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
991 fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
992 return;
993
994 if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
995 return;
996
997 fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
998
999 offset = offsetof(struct v4l2_pix_format, priv)
1000 + sizeof(fmt->fmt.pix.priv);
1001 memset(((void *)&fmt->fmt.pix) + offset, 0,
1002 sizeof(fmt->fmt.pix) - offset);
1003}
1004
976static int v4l_querycap(const struct v4l2_ioctl_ops *ops, 1005static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
977 struct file *file, void *fh, void *arg) 1006 struct file *file, void *fh, void *arg)
978{ 1007{
979 struct v4l2_capability *cap = (struct v4l2_capability *)arg; 1008 struct v4l2_capability *cap = (struct v4l2_capability *)arg;
1009 int ret;
980 1010
981 cap->version = LINUX_VERSION_CODE; 1011 cap->version = LINUX_VERSION_CODE;
982 return ops->vidioc_querycap(file, fh, cap); 1012
1013 ret = ops->vidioc_querycap(file, fh, cap);
1014
1015 cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
1016
1017 return ret;
983} 1018}
984 1019
985static int v4l_s_input(const struct v4l2_ioctl_ops *ops, 1020static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
@@ -1103,12 +1138,17 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
1103 bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 1138 bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
1104 bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 1139 bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
1105 bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1140 bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
1141 int ret;
1142
1143 p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1106 1144
1107 switch (p->type) { 1145 switch (p->type) {
1108 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1146 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1109 if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap)) 1147 if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
1110 break; 1148 break;
1111 return ops->vidioc_g_fmt_vid_cap(file, fh, arg); 1149 ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg);
1150 p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1151 return ret;
1112 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 1152 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1113 if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane)) 1153 if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
1114 break; 1154 break;
@@ -1128,7 +1168,9 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
1128 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 1168 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1129 if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out)) 1169 if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
1130 break; 1170 break;
1131 return ops->vidioc_g_fmt_vid_out(file, fh, arg); 1171 ret = ops->vidioc_g_fmt_vid_out(file, fh, arg);
1172 p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1173 return ret;
1132 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 1174 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1133 if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane)) 1175 if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
1134 break; 1176 break;
@@ -1163,6 +1205,8 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
1163 bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 1205 bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
1164 bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1206 bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
1165 1207
1208 v4l_sanitize_format(p);
1209
1166 switch (p->type) { 1210 switch (p->type) {
1167 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1211 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1168 if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap)) 1212 if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap))
@@ -1233,6 +1277,8 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
1233 bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 1277 bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
1234 bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1278 bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
1235 1279
1280 v4l_sanitize_format(p);
1281
1236 switch (p->type) { 1282 switch (p->type) {
1237 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1283 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1238 if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap)) 1284 if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap))
@@ -1516,7 +1562,18 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
1516 struct v4l2_create_buffers *create = arg; 1562 struct v4l2_create_buffers *create = arg;
1517 int ret = check_fmt(file, create->format.type); 1563 int ret = check_fmt(file, create->format.type);
1518 1564
1519 return ret ? ret : ops->vidioc_create_bufs(file, fh, create); 1565 if (ret)
1566 return ret;
1567
1568 v4l_sanitize_format(&create->format);
1569
1570 ret = ops->vidioc_create_bufs(file, fh, create);
1571
1572 if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
1573 create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1574 create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1575
1576 return ret;
1520} 1577}
1521 1578
1522static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, 1579static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,