Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 93d5a30b authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

[media] v4l2-ioctl: more -ENOTTY fixes



  explicitly instead of using a macro.
  ioctls and the ENUMSTD, S_STD and G_PARM ioctls.

Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 2b5d9480
Loading
Loading
Loading
Loading
+145 −61
Original line number Diff line number Diff line
@@ -55,13 +55,18 @@
	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
	0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))

#define no_ioctl_err(foo) ( (						\
#define have_fmt_ops(foo) (						\
	ops->vidioc_##foo##_fmt_vid_cap ||				\
	ops->vidioc_##foo##_fmt_vid_out ||				\
	ops->vidioc_##foo##_fmt_vid_cap_mplane ||			\
	ops->vidioc_##foo##_fmt_vid_out_mplane ||			\
	ops->vidioc_##foo##_fmt_vid_overlay ||				\
	ops->vidioc_##foo##_fmt_type_private) ? -EINVAL : -ENOTTY)
	ops->vidioc_##foo##_fmt_vbi_cap ||				\
	ops->vidioc_##foo##_fmt_vid_out_overlay ||			\
	ops->vidioc_##foo##_fmt_vbi_out ||				\
	ops->vidioc_##foo##_fmt_sliced_vbi_cap ||			\
	ops->vidioc_##foo##_fmt_sliced_vbi_out ||			\
	ops->vidioc_##foo##_fmt_type_private)

struct std_descr {
	v4l2_std_id std;
@@ -551,6 +556,7 @@ static long __video_do_ioctl(struct file *file,
	struct v4l2_fh *vfh = NULL;
	struct v4l2_format f_copy;
	int use_fh_prio = 0;
	long ret_prio = 0;
	long ret = -ENOTTY;

	if (ops == NULL) {
@@ -570,39 +576,8 @@ static long __video_do_ioctl(struct file *file,
		use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
	}

	if (use_fh_prio) {
		switch (cmd) {
		case VIDIOC_S_CTRL:
		case VIDIOC_S_STD:
		case VIDIOC_S_INPUT:
		case VIDIOC_S_OUTPUT:
		case VIDIOC_S_TUNER:
		case VIDIOC_S_FREQUENCY:
		case VIDIOC_S_FMT:
		case VIDIOC_S_CROP:
		case VIDIOC_S_AUDIO:
		case VIDIOC_S_AUDOUT:
		case VIDIOC_S_EXT_CTRLS:
		case VIDIOC_S_FBUF:
		case VIDIOC_S_PRIORITY:
		case VIDIOC_S_DV_PRESET:
		case VIDIOC_S_DV_TIMINGS:
		case VIDIOC_S_JPEGCOMP:
		case VIDIOC_S_MODULATOR:
		case VIDIOC_S_PARM:
		case VIDIOC_S_HW_FREQ_SEEK:
		case VIDIOC_ENCODER_CMD:
		case VIDIOC_OVERLAY:
		case VIDIOC_REQBUFS:
		case VIDIOC_STREAMON:
		case VIDIOC_STREAMOFF:
			ret = v4l2_prio_check(vfd->prio, vfh->prio);
			if (ret)
				goto exit_prio;
			ret = -ENOTTY;
			break;
		}
	}
	if (use_fh_prio)
		ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);

	switch (cmd) {

@@ -651,7 +626,9 @@ static long __video_do_ioctl(struct file *file,
		if (ops->vidioc_s_priority)
			ret = ops->vidioc_s_priority(file, fh, *p);
		else
			ret = v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
			ret = ret_prio ? ret_prio :
				v4l2_prio_change(&vfd->v4l2_dev->prio,
							&vfh->prio, *p);
		break;
	}

@@ -701,8 +678,14 @@ static long __video_do_ioctl(struct file *file,
				(f->pixelformat >> 16) & 0xff,
				(f->pixelformat >> 24) & 0xff,
				f->description);
		else if (ret == -ENOTTY)
			ret = no_ioctl_err(enum);
		else if (ret == -ENOTTY &&
			 (ops->vidioc_enum_fmt_vid_cap ||
			  ops->vidioc_enum_fmt_vid_out ||
			  ops->vidioc_enum_fmt_vid_cap_mplane ||
			  ops->vidioc_enum_fmt_vid_out_mplane ||
			  ops->vidioc_enum_fmt_vid_overlay ||
			  ops->vidioc_enum_fmt_type_private))
			ret = -EINVAL;
		break;
	}
	case VIDIOC_G_FMT:
@@ -827,8 +810,8 @@ static long __video_do_ioctl(struct file *file,
								fh, f);
			break;
		}
		if (unlikely(ret == -ENOTTY))
			ret = no_ioctl_err(g);
		if (unlikely(ret == -ENOTTY && have_fmt_ops(g)))
			ret = -EINVAL;

		break;
	}
@@ -836,6 +819,14 @@ static long __video_do_ioctl(struct file *file,
	{
		struct v4l2_format *f = (struct v4l2_format *)arg;

		if (!have_fmt_ops(s))
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		ret = -EINVAL;

		/* FIXME: Should be one dump per type */
		dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));

@@ -966,8 +957,6 @@ static long __video_do_ioctl(struct file *file,
								fh, f);
			break;
		}
		if (unlikely(ret == -ENOTTY))
			ret = no_ioctl_err(g);
		break;
	}
	case VIDIOC_TRY_FMT:
@@ -1097,8 +1086,6 @@ static long __video_do_ioctl(struct file *file,
			if (likely(ops->vidioc_try_fmt_sliced_vbi_out))
				ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
								fh, f);
			else
				ret = no_ioctl_err(try);
			break;
		case V4L2_BUF_TYPE_PRIVATE:
			/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
@@ -1107,8 +1094,8 @@ static long __video_do_ioctl(struct file *file,
								fh, f);
			break;
		}
		if (unlikely(ret == -ENOTTY))
			ret = no_ioctl_err(g);
		if (unlikely(ret == -ENOTTY && have_fmt_ops(try)))
			ret = -EINVAL;
		break;
	}
	/* FIXME: Those buf reqs could be handled here,
@@ -1121,6 +1108,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_reqbufs)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		ret = check_fmt(ops, p->type);
		if (ret)
			break;
@@ -1186,6 +1177,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_overlay)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "value=%d\n", *i);
		ret = ops->vidioc_overlay(file, fh, *i);
		break;
@@ -1211,6 +1206,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_fbuf)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
			p->capability, p->flags, (unsigned long)p->base);
		v4l_print_pix_fmt(vfd, &p->fmt);
@@ -1223,6 +1222,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_streamon)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
		ret = ops->vidioc_streamon(file, fh, i);
		break;
@@ -1233,6 +1236,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_streamoff)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
		ret = ops->vidioc_streamoff(file, fh, i);
		break;
@@ -1245,6 +1252,10 @@ static long __video_do_ioctl(struct file *file,
		unsigned int index = p->index, i, j = 0;
		const char *descr = "";

		if (id == 0)
			break;
		ret = -EINVAL;

		/* Return norm array in a canonical way */
		for (i = 0; i <= index && id; i++) {
			/* last std value in the standards array is 0, so this
@@ -1298,12 +1309,19 @@ static long __video_do_ioctl(struct file *file,

		dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);

		if (!ops->vidioc_s_std)
			break;

		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		ret = -EINVAL;
		norm = (*id) & vfd->tvnorms;
		if (vfd->tvnorms && !norm)	/* Check if std is supported */
			break;

		/* Calls the specific handler */
		if (ops->vidioc_s_std)
		ret = ops->vidioc_s_std(file, fh, &norm);

		/* Updates standard information */
@@ -1373,6 +1391,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_input)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "value=%d\n", *i);
		ret = ops->vidioc_s_input(file, fh, *i);
		break;
@@ -1425,6 +1447,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_output)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "value=%d\n", *i);
		ret = ops->vidioc_s_output(file, fh, *i);
		break;
@@ -1494,6 +1520,10 @@ static long __video_do_ioctl(struct file *file,
		if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
			!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}

		dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);

@@ -1519,6 +1549,8 @@ static long __video_do_ioctl(struct file *file,
		ctrl.value = p->value;
		if (check_ext_ctrls(&ctrls, 1))
			ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
		else
			ret = -EINVAL;
		break;
	}
	case VIDIOC_G_EXT_CTRLS:
@@ -1530,8 +1562,10 @@ static long __video_do_ioctl(struct file *file,
			ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
		else if (vfd->ctrl_handler)
			ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
		else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
			ret = ops->vidioc_g_ext_ctrls(file, fh, p);
		else if (ops->vidioc_g_ext_ctrls)
			ret = check_ext_ctrls(p, 0) ?
				ops->vidioc_g_ext_ctrls(file, fh, p) :
				-EINVAL;
		else
			break;
		v4l_print_ext_ctrls(cmd, vfd, p, !ret);
@@ -1545,6 +1579,10 @@ static long __video_do_ioctl(struct file *file,
		if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
				!ops->vidioc_s_ext_ctrls)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		v4l_print_ext_ctrls(cmd, vfd, p, 1);
		if (vfh && vfh->ctrl_handler)
			ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
@@ -1552,6 +1590,8 @@ static long __video_do_ioctl(struct file *file,
			ret = v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
		else if (check_ext_ctrls(p, 0))
			ret = ops->vidioc_s_ext_ctrls(file, fh, p);
		else
			ret = -EINVAL;
		break;
	}
	case VIDIOC_TRY_EXT_CTRLS:
@@ -1569,6 +1609,8 @@ static long __video_do_ioctl(struct file *file,
			ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
		else if (check_ext_ctrls(p, 0))
			ret = ops->vidioc_try_ext_ctrls(file, fh, p);
		else
			ret = -EINVAL;
		break;
	}
	case VIDIOC_QUERYMENU:
@@ -1629,6 +1671,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_audio)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
					"mode=0x%x\n", p->index, p->name,
					p->capability, p->mode);
@@ -1669,6 +1715,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_audout)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "index=%d, name=%s, capability=%d, "
					"mode=%d\n", p->index, p->name,
					p->capability, p->mode);
@@ -1698,6 +1748,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_modulator)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "index=%d, name=%s, capability=%d, "
				"rangelow=%d, rangehigh=%d, txsubchans=%d\n",
				p->index, p->name, p->capability, p->rangelow,
@@ -1724,6 +1778,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_crop)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
		dbgrect(vfd, "", &p->c);
		ret = ops->vidioc_s_crop(file, fh, p);
@@ -1767,6 +1825,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_g_jpegcomp)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
					"COM_len=%d, jpeg_markers=%d\n",
					p->quality, p->APPn, p->APP_len,
@@ -1792,6 +1854,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_encoder_cmd)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		ret = ops->vidioc_encoder_cmd(file, fh, p);
		if (!ret)
			dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1812,6 +1878,8 @@ static long __video_do_ioctl(struct file *file,
	{
		struct v4l2_streamparm *p = arg;

		if (!ops->vidioc_g_parm && !vfd->current_norm)
			break;
		if (ops->vidioc_g_parm) {
			ret = check_fmt(ops, p->type);
			if (ret)
@@ -1820,14 +1888,13 @@ static long __video_do_ioctl(struct file *file,
		} else {
			v4l2_std_id std = vfd->current_norm;

			ret = -EINVAL;
			if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
				break;

			ret = 0;
			if (ops->vidioc_g_std)
				ret = ops->vidioc_g_std(file, fh, &std);
			else if (std == 0)
				ret = -ENOTTY;
			if (ret == 0)
				v4l2_video_std_frame_period(std,
						    &p->parm.capture.timeperframe);
@@ -1842,6 +1909,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_parm)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		ret = check_fmt(ops, p->type);
		if (ret)
			break;
@@ -1877,6 +1948,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_tuner)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
		dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1911,6 +1986,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_frequency)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
				p->tuner, p->type, p->frequency);
		ret = ops->vidioc_s_frequency(file, fh, p);
@@ -1985,6 +2064,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_hw_freq_seek)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}
		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
		dbgarg(cmd,
@@ -2089,6 +2172,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_dv_preset)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}

		dbgarg(cmd, "preset=%d\n", p->preset);
		ret = ops->vidioc_s_dv_preset(file, fh, p);
@@ -2124,6 +2211,10 @@ static long __video_do_ioctl(struct file *file,

		if (!ops->vidioc_s_dv_timings)
			break;
		if (ret_prio) {
			ret = ret_prio;
			break;
		}

		switch (p->type) {
		case V4L2_DV_BT_656_1120:
@@ -2232,19 +2323,12 @@ static long __video_do_ioctl(struct file *file,
		break;
	}
	default:
	{
		bool valid_prio = true;

		if (!ops->vidioc_default)
			break;
		if (use_fh_prio)
			valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
		ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
		ret = ops->vidioc_default(file, fh, ret_prio >= 0, cmd, arg);
		break;
	}
	} /* switch */

exit_prio:
	if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
		if (ret < 0) {
			v4l_print_ioctl(vfd->name, cmd);