Commit 48e93b0c authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab
Browse files

media: v4l2: Sanitize colorspace values in the framework



Extend the format sanitization code in the framework to handle invalid
values for the colorspace-related fields.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 718d2153
Loading
Loading
Loading
Loading
+58 −13
Original line number Original line Diff line number Diff line
@@ -1007,6 +1007,31 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
	return -EINVAL;
	return -EINVAL;
}
}


static void v4l_sanitize_colorspace(u32 pixelformat, u32 *colorspace,
				    u32 *encoding, u32 *quantization,
				    u32 *xfer_func)
{
	bool is_hsv = pixelformat == V4L2_PIX_FMT_HSV24 ||
		      pixelformat == V4L2_PIX_FMT_HSV32;

	if (!v4l2_is_colorspace_valid(*colorspace)) {
		*colorspace = V4L2_COLORSPACE_DEFAULT;
		*encoding = V4L2_YCBCR_ENC_DEFAULT;
		*quantization = V4L2_QUANTIZATION_DEFAULT;
		*xfer_func = V4L2_XFER_FUNC_DEFAULT;
	}

	if ((!is_hsv && !v4l2_is_ycbcr_enc_valid(*encoding)) ||
	    (is_hsv && !v4l2_is_hsv_enc_valid(*encoding)))
		*encoding = V4L2_YCBCR_ENC_DEFAULT;

	if (!v4l2_is_quant_valid(*quantization))
		*quantization = V4L2_QUANTIZATION_DEFAULT;

	if (!v4l2_is_xfer_func_valid(*xfer_func))
		*xfer_func = V4L2_XFER_FUNC_DEFAULT;
}

static void v4l_sanitize_format(struct v4l2_format *fmt)
static void v4l_sanitize_format(struct v4l2_format *fmt)
{
{
	unsigned int offset;
	unsigned int offset;
@@ -1026,14 +1051,9 @@ static void v4l_sanitize_format(struct v4l2_format *fmt)
	 * field to the magic value when the extended pixel format structure
	 * field to the magic value when the extended pixel format structure
	 * isn't used by applications.
	 * isn't used by applications.
	 */
	 */

	if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
	    fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
	    fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
		if (fmt->fmt.pix.priv != V4L2_PIX_FMT_PRIV_MAGIC) {
		return;

	if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
		return;

			fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
			fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;


			offset = offsetof(struct v4l2_pix_format, priv)
			offset = offsetof(struct v4l2_pix_format, priv)
@@ -1041,6 +1061,31 @@ static void v4l_sanitize_format(struct v4l2_format *fmt)
			memset(((void *)&fmt->fmt.pix) + offset, 0,
			memset(((void *)&fmt->fmt.pix) + offset, 0,
			       sizeof(fmt->fmt.pix) - offset);
			       sizeof(fmt->fmt.pix) - offset);
		}
		}
	}

	/* Replace invalid colorspace values with defaults. */
	if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
	    fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		v4l_sanitize_colorspace(fmt->fmt.pix.pixelformat,
					&fmt->fmt.pix.colorspace,
					&fmt->fmt.pix.ycbcr_enc,
					&fmt->fmt.pix.quantization,
					&fmt->fmt.pix.xfer_func);
	} else if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
		   fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		u32 ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc;
		u32 quantization = fmt->fmt.pix_mp.quantization;
		u32 xfer_func = fmt->fmt.pix_mp.xfer_func;

		v4l_sanitize_colorspace(fmt->fmt.pix_mp.pixelformat,
					&fmt->fmt.pix_mp.colorspace, &ycbcr_enc,
					&quantization, &xfer_func);

		fmt->fmt.pix_mp.ycbcr_enc = ycbcr_enc;
		fmt->fmt.pix_mp.quantization = quantization;
		fmt->fmt.pix_mp.xfer_func = xfer_func;
	}
}


static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
				struct file *file, void *fh, void *arg)
				struct file *file, void *fh, void *arg)