diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-ioctl.c | 77 | 
1 files changed, 50 insertions, 27 deletions
| diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 05d5db3d85e5..31d0109ce5a8 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -869,7 +869,7 @@ static void v4l_print_default(const void *arg, bool write_only)  	pr_cont("driver-specific ioctl\n");  } -static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) +static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl)  {  	__u32 i; @@ -878,23 +878,41 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)  	for (i = 0; i < c->count; i++)  		c->controls[i].reserved2[0] = 0; -	/* V4L2_CID_PRIVATE_BASE cannot be used as control class -	   when using extended controls. -	   Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL -	   is it allowed for backwards compatibility. -	 */ -	if (!allow_priv && c->which == V4L2_CID_PRIVATE_BASE) -		return 0; -	if (!c->which) -		return 1; +	switch (c->which) { +	case V4L2_CID_PRIVATE_BASE: +		/* +		 * V4L2_CID_PRIVATE_BASE cannot be used as control class +		 * when using extended controls. +		 * Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL +		 * is it allowed for backwards compatibility. +		 */ +		if (ioctl == VIDIOC_G_CTRL || ioctl == VIDIOC_S_CTRL) +			return false; +		break; +	case V4L2_CTRL_WHICH_DEF_VAL: +		/* Default value cannot be changed */ +		if (ioctl == VIDIOC_S_EXT_CTRLS || +		    ioctl == VIDIOC_TRY_EXT_CTRLS) { +			c->error_idx = c->count; +			return false; +		} +		return true; +	case V4L2_CTRL_WHICH_CUR_VAL: +		return true; +	case V4L2_CTRL_WHICH_REQUEST_VAL: +		c->error_idx = c->count; +		return false; +	} +  	/* Check that all controls are from the same control class. */  	for (i = 0; i < c->count; i++) {  		if (V4L2_CTRL_ID2WHICH(c->controls[i].id) != c->which) { -			c->error_idx = i; -			return 0; +			c->error_idx = ioctl == VIDIOC_TRY_EXT_CTRLS ? i : +								      c->count; +			return false;  		}  	} -	return 1; +	return true;  }  static int check_fmt(struct file *file, enum v4l2_buf_type type) @@ -1274,7 +1292,6 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  	case V4L2_PIX_FMT_YUV410:	descr = "Planar YUV 4:1:0"; break;  	case V4L2_PIX_FMT_YUV420:	descr = "Planar YUV 4:2:0"; break;  	case V4L2_PIX_FMT_HI240:	descr = "8-bit Dithered RGB (BTTV)"; break; -	case V4L2_PIX_FMT_HM12:		descr = "YUV 4:2:0 (16x16 Macroblocks)"; break;  	case V4L2_PIX_FMT_M420:		descr = "YUV 4:2:0 (M420)"; break;  	case V4L2_PIX_FMT_NV12:		descr = "Y/CbCr 4:2:0"; break;  	case V4L2_PIX_FMT_NV21:		descr = "Y/CrCb 4:2:0"; break; @@ -1282,6 +1299,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  	case V4L2_PIX_FMT_NV61:		descr = "Y/CrCb 4:2:2"; break;  	case V4L2_PIX_FMT_NV24:		descr = "Y/CbCr 4:4:4"; break;  	case V4L2_PIX_FMT_NV42:		descr = "Y/CrCb 4:4:4"; break; +	case V4L2_PIX_FMT_NV12_4L4:	descr = "Y/CbCr 4:2:0 (4x4 Linear)"; break; +	case V4L2_PIX_FMT_NV12_16L16:	descr = "Y/CbCr 4:2:0 (16x16 Linear)"; break; +	case V4L2_PIX_FMT_NV12_32L32:   descr = "Y/CbCr 4:2:0 (32x32 Linear)"; break;  	case V4L2_PIX_FMT_NV12M:	descr = "Y/CbCr 4:2:0 (N-C)"; break;  	case V4L2_PIX_FMT_NV21M:	descr = "Y/CrCb 4:2:0 (N-C)"; break;  	case V4L2_PIX_FMT_NV16M:	descr = "Y/CbCr 4:2:2 (N-C)"; break; @@ -1346,6 +1366,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  	case V4L2_PIX_FMT_TM6000:	descr = "A/V + VBI Mux Packet"; break;  	case V4L2_PIX_FMT_CIT_YYVYUY:	descr = "GSPCA CIT YYVYUY"; break;  	case V4L2_PIX_FMT_KONICA420:	descr = "GSPCA KONICA420"; break; +	case V4L2_PIX_FMT_MM21:		descr = "Mediatek 8-bit Block Format"; break;  	case V4L2_PIX_FMT_HSV24:	descr = "24-bit HSV 8-8-8"; break;  	case V4L2_PIX_FMT_HSV32:	descr = "32-bit XHSV 8-8-8-8"; break;  	case V4L2_SDR_FMT_CU8:		descr = "Complex U8"; break; @@ -1415,7 +1436,6 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  		case V4L2_PIX_FMT_SE401:	descr = "GSPCA SE401"; break;  		case V4L2_PIX_FMT_S5C_UYVY_JPG:	descr = "S5C73MX interleaved UYVY/JPEG"; break;  		case V4L2_PIX_FMT_MT21C:	descr = "Mediatek Compressed Format"; break; -		case V4L2_PIX_FMT_SUNXI_TILED_NV12: descr = "Sunxi Tiled NV12 Format"; break;  		default:  			if (fmt->description[0])  				return; @@ -2004,7 +2024,7 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,  	if (ret)  		return ret; -	CLEAR_AFTER_FIELD(p, capabilities); +	CLEAR_AFTER_FIELD(p, flags);  	return ops->vidioc_reqbufs(file, fh, p);  } @@ -2045,7 +2065,7 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,  	if (ret)  		return ret; -	CLEAR_AFTER_FIELD(create, capabilities); +	CLEAR_AFTER_FIELD(create, flags);  	v4l_sanitize_format(&create->format); @@ -2187,7 +2207,7 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops,  	ctrls.controls = &ctrl;  	ctrl.id = p->id;  	ctrl.value = p->value; -	if (check_ext_ctrls(&ctrls, 1)) { +	if (check_ext_ctrls(&ctrls, VIDIOC_G_CTRL)) {  		int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);  		if (ret == 0) @@ -2206,6 +2226,7 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,  		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;  	struct v4l2_ext_controls ctrls;  	struct v4l2_ext_control ctrl; +	int ret;  	if (vfh && vfh->ctrl_handler)  		return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); @@ -2221,9 +2242,11 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,  	ctrls.controls = &ctrl;  	ctrl.id = p->id;  	ctrl.value = p->value; -	if (check_ext_ctrls(&ctrls, 1)) -		return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); -	return -EINVAL; +	if (!check_ext_ctrls(&ctrls, VIDIOC_S_CTRL)) +		return -EINVAL; +	ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls); +	p->value = ctrl.value; +	return ret;  }  static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, @@ -2243,8 +2266,8 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops,  					vfd, vfd->v4l2_dev->mdev, p);  	if (ops->vidioc_g_ext_ctrls == NULL)  		return -ENOTTY; -	return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : -					-EINVAL; +	return check_ext_ctrls(p, VIDIOC_G_EXT_CTRLS) ? +				ops->vidioc_g_ext_ctrls(file, fh, p) : -EINVAL;  }  static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, @@ -2264,8 +2287,8 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops,  					vfd, vfd->v4l2_dev->mdev, p);  	if (ops->vidioc_s_ext_ctrls == NULL)  		return -ENOTTY; -	return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : -					-EINVAL; +	return check_ext_ctrls(p, VIDIOC_S_EXT_CTRLS) ? +				ops->vidioc_s_ext_ctrls(file, fh, p) : -EINVAL;  }  static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, @@ -2285,8 +2308,8 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops,  					  vfd, vfd->v4l2_dev->mdev, p);  	if (ops->vidioc_try_ext_ctrls == NULL)  		return -ENOTTY; -	return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : -					-EINVAL; +	return check_ext_ctrls(p, VIDIOC_TRY_EXT_CTRLS) ? +			ops->vidioc_try_ext_ctrls(file, fh, p) : -EINVAL;  }  /* |