diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-ioctl.c | 73 | 
1 files changed, 66 insertions, 7 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 6e7b8b682d13..4c76d17b4629 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -343,8 +343,9 @@ static void v4l_print_format(const void *arg, bool write_only)  	case V4L2_BUF_TYPE_META_OUTPUT:  		meta = &p->fmt.meta;  		pixelformat = meta->dataformat; -		pr_cont(", dataformat=%p4cc, buffersize=%u\n", -			&pixelformat, meta->buffersize); +		pr_cont(", dataformat=%p4cc, buffersize=%u, width=%u, height=%u, bytesperline=%u\n", +			&pixelformat, meta->buffersize, meta->width, +			meta->height, meta->bytesperline);  		break;  	}  } @@ -489,6 +490,14 @@ static void v4l_print_create_buffers(const void *arg, bool write_only)  	v4l_print_format(&p->format, write_only);  } +static void v4l_print_remove_buffers(const void *arg, bool write_only) +{ +	const struct v4l2_remove_buffers *p = arg; + +	pr_cont("type=%s, index=%u, count=%u\n", +		prt_names(p->type, v4l2_type_names), p->index, p->count); +} +  static void v4l_print_streamparm(const void *arg, bool write_only)  {  	const struct v4l2_streamparm *p = arg; @@ -1312,6 +1321,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  	case V4L2_PIX_FMT_Y10BPACK:	descr = "10-bit Greyscale (Packed)"; break;  	case V4L2_PIX_FMT_Y10P:		descr = "10-bit Greyscale (MIPI Packed)"; break;  	case V4L2_PIX_FMT_IPU3_Y10:	descr = "10-bit greyscale (IPU3 Packed)"; break; +	case V4L2_PIX_FMT_Y12P:		descr = "12-bit Greyscale (MIPI Packed)"; break; +	case V4L2_PIX_FMT_Y14P:		descr = "14-bit Greyscale (MIPI Packed)"; break;  	case V4L2_PIX_FMT_Y8I:		descr = "Interleaved 8-bit Greyscale"; break;  	case V4L2_PIX_FMT_Y12I:		descr = "Interleaved 12-bit Greyscale"; break;  	case V4L2_PIX_FMT_Z16:		descr = "16-bit Depth"; break; @@ -1452,6 +1463,13 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  	case V4L2_PIX_FMT_Y210:		descr = "10-bit YUYV Packed"; break;  	case V4L2_PIX_FMT_Y212:		descr = "12-bit YUYV Packed"; break;  	case V4L2_PIX_FMT_Y216:		descr = "16-bit YUYV Packed"; break; +	case V4L2_META_FMT_GENERIC_8:	descr = "8-bit Generic Metadata"; break; +	case V4L2_META_FMT_GENERIC_CSI2_10:	descr = "8-bit Generic Meta, 10b CSI-2"; break; +	case V4L2_META_FMT_GENERIC_CSI2_12:	descr = "8-bit Generic Meta, 12b CSI-2"; break; +	case V4L2_META_FMT_GENERIC_CSI2_14:	descr = "8-bit Generic Meta, 14b CSI-2"; break; +	case V4L2_META_FMT_GENERIC_CSI2_16:	descr = "8-bit Generic Meta, 16b CSI-2"; break; +	case V4L2_META_FMT_GENERIC_CSI2_20:	descr = "8-bit Generic Meta, 20b CSI-2"; break; +	case V4L2_META_FMT_GENERIC_CSI2_24:	descr = "8-bit Generic Meta, 24b CSI-2"; break;  	default:  		/* Compressed formats */ @@ -1522,6 +1540,22 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  		}  	} +	if (fmt->type == V4L2_BUF_TYPE_META_CAPTURE) { +		switch (fmt->pixelformat) { +		case V4L2_META_FMT_GENERIC_8: +		case V4L2_META_FMT_GENERIC_CSI2_10: +		case V4L2_META_FMT_GENERIC_CSI2_12: +		case V4L2_META_FMT_GENERIC_CSI2_14: +		case V4L2_META_FMT_GENERIC_CSI2_16: +		case V4L2_META_FMT_GENERIC_CSI2_20: +		case V4L2_META_FMT_GENERIC_CSI2_24: +			fmt->flags |= V4L2_FMT_FLAG_META_LINE_BASED; +			break; +		default: +			fmt->flags &= ~V4L2_FMT_FLAG_META_LINE_BASED; +		} +	} +  	if (descr)  		WARN_ON(strscpy(fmt->description, descr, sz) < 0);  	fmt->flags |= flags; @@ -2092,6 +2126,7 @@ static int v4l_overlay(const struct v4l2_ioctl_ops *ops,  static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,  				struct file *file, void *fh, void *arg)  { +	struct video_device *vfd = video_devdata(file);  	struct v4l2_requestbuffers *p = arg;  	int ret = check_fmt(file, p->type); @@ -2100,6 +2135,10 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,  	memset_after(p, 0, flags); +	p->capabilities = 0; +	if (is_valid_ioctl(vfd, VIDIOC_REMOVE_BUFS)) +		p->capabilities = V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS; +  	return ops->vidioc_reqbufs(file, fh, p);  } @@ -2133,6 +2172,7 @@ static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops,  static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,  				struct file *file, void *fh, void *arg)  { +	struct video_device *vfd = video_devdata(file);  	struct v4l2_create_buffers *create = arg;  	int ret = check_fmt(file, create->format.type); @@ -2143,6 +2183,10 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,  	v4l_sanitize_format(&create->format); +	create->capabilities = 0; +	if (is_valid_ioctl(vfd, VIDIOC_REMOVE_BUFS)) +		create->capabilities = V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS; +  	ret = ops->vidioc_create_bufs(file, fh, create);  	if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || @@ -2161,6 +2205,17 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,  	return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);  } +static int v4l_remove_bufs(const struct v4l2_ioctl_ops *ops, +			   struct file *file, void *fh, void *arg) +{ +	struct v4l2_remove_buffers *remove = arg; + +	if (ops->vidioc_remove_bufs) +		return ops->vidioc_remove_bufs(file, fh, remove); + +	return -ENOTTY; +} +  static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,  				struct file *file, void *fh, void *arg)  { @@ -2910,6 +2965,7 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = {  	IOCTL_INFO(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),  	IOCTL_INFO(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),  	IOCTL_INFO(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)), +	IOCTL_INFO(VIDIOC_REMOVE_BUFS, v4l_remove_bufs, v4l_print_remove_buffers, INFO_FL_PRIO | INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_remove_buffers, type)),  };  #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -3147,13 +3203,13 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,  	case VIDIOC_SUBDEV_S_ROUTING: {  		struct v4l2_subdev_routing *routing = parg; -		if (routing->num_routes > 256) +		if (routing->len_routes > 256)  			return -E2BIG;  		*user_ptr = u64_to_user_ptr(routing->routes);  		*kernel_ptr = (void **)&routing->routes;  		*array_size = sizeof(struct v4l2_subdev_route) -			    * routing->num_routes; +			    * routing->len_routes;  		ret = 1;  		break;  	} @@ -3407,11 +3463,14 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg,  	 * FIXME: subdev IOCTLS are partially handled here and partially in  	 * v4l2-subdev.c and the 'always_copy' flag can only be set for IOCTLS  	 * defined here as part of the 'v4l2_ioctls' array. As -	 * VIDIOC_SUBDEV_G_ROUTING needs to return results to applications even -	 * in case of failure, but it is not defined here as part of the +	 * VIDIOC_SUBDEV_[GS]_ROUTING needs to return results to applications +	 * even in case of failure, but it is not defined here as part of the  	 * 'v4l2_ioctls' array, insert an ad-hoc check to address that.  	 */ -	if (err < 0 && !always_copy && cmd != VIDIOC_SUBDEV_G_ROUTING) +	if (cmd == VIDIOC_SUBDEV_G_ROUTING || cmd == VIDIOC_SUBDEV_S_ROUTING) +		always_copy = true; + +	if (err < 0 && !always_copy)  		goto out;  	if (has_array_args) {  |