diff options
| author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-09-14 07:03:35 -0300 | 
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-09-26 14:41:54 -0300 | 
| commit | 4b20259fa642d6f7a2dabef0b3adc14ca9dadbde (patch) | |
| tree | e508b4e27cb2d82c5e68ffd1ff5a184725b5944b /drivers/media/v4l2-core/v4l2-dev.c | |
| parent | 954f340fc7f2fa2ae8812670da49e828d2686d8e (diff) | |
| download | olio-linux-3.10-4b20259fa642d6f7a2dabef0b3adc14ca9dadbde.tar.xz olio-linux-3.10-4b20259fa642d6f7a2dabef0b3adc14ca9dadbde.zip  | |
[media] v4l2-dev: improve ioctl validity checks
The ioctl validity checks have been improved and now take vfl_type
and vfl_dir into account.
During the 2012 Media Workshop it was decided that these improved
v4l2 core checks should be added as they simplified drivers and
made drivers behave consistently.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-dev.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-dev.c | 228 | 
1 files changed, 133 insertions, 95 deletions
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 498049fa43e..b437daa1f7d 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -551,6 +551,11 @@ static void determine_valid_ioctls(struct video_device *vdev)  {  	DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);  	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; +	bool is_vid = vdev->vfl_type == VFL_TYPE_GRABBER; +	bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI; +	bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO; +	bool is_rx = vdev->vfl_dir != VFL_DIR_TX; +	bool is_tx = vdev->vfl_dir != VFL_DIR_RX;  	bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE); @@ -561,66 +566,87 @@ static void determine_valid_ioctls(struct video_device *vdev)  	if (ops->vidioc_s_priority ||  			test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))  		set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls); -	if (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) -		set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls); -	if (ops->vidioc_g_fmt_vid_cap || -	    ops->vidioc_g_fmt_vid_out || -	    ops->vidioc_g_fmt_vid_cap_mplane || -	    ops->vidioc_g_fmt_vid_out_mplane || -	    ops->vidioc_g_fmt_vid_overlay || -	    ops->vidioc_g_fmt_vbi_cap || -	    ops->vidioc_g_fmt_vid_out_overlay || -	    ops->vidioc_g_fmt_vbi_out || -	    ops->vidioc_g_fmt_sliced_vbi_cap || -	    ops->vidioc_g_fmt_sliced_vbi_out) -		set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); -	if (ops->vidioc_s_fmt_vid_cap || -	    ops->vidioc_s_fmt_vid_out || -	    ops->vidioc_s_fmt_vid_cap_mplane || -	    ops->vidioc_s_fmt_vid_out_mplane || -	    ops->vidioc_s_fmt_vid_overlay || -	    ops->vidioc_s_fmt_vbi_cap || -	    ops->vidioc_s_fmt_vid_out_overlay || -	    ops->vidioc_s_fmt_vbi_out || -	    ops->vidioc_s_fmt_sliced_vbi_cap || -	    ops->vidioc_s_fmt_sliced_vbi_out) -		set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); -	if (ops->vidioc_try_fmt_vid_cap || -	    ops->vidioc_try_fmt_vid_out || -	    ops->vidioc_try_fmt_vid_cap_mplane || -	    ops->vidioc_try_fmt_vid_out_mplane || -	    ops->vidioc_try_fmt_vid_overlay || -	    ops->vidioc_try_fmt_vbi_cap || -	    ops->vidioc_try_fmt_vid_out_overlay || -	    ops->vidioc_try_fmt_vbi_out || -	    ops->vidioc_try_fmt_sliced_vbi_cap || -	    ops->vidioc_try_fmt_sliced_vbi_out) -		set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); +	if (is_vid) { +		if ((is_rx && (ops->vidioc_enum_fmt_vid_cap || +			       ops->vidioc_enum_fmt_vid_cap_mplane || +			       ops->vidioc_enum_fmt_vid_overlay)) || +		    (is_tx && (ops->vidioc_enum_fmt_vid_out || +			       ops->vidioc_enum_fmt_vid_out_mplane))) +			set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls); +		if ((is_rx && (ops->vidioc_g_fmt_vid_cap || +			       ops->vidioc_g_fmt_vid_cap_mplane || +			       ops->vidioc_g_fmt_vid_overlay)) || +		    (is_tx && (ops->vidioc_g_fmt_vid_out || +			       ops->vidioc_g_fmt_vid_out_mplane || +			       ops->vidioc_g_fmt_vid_out_overlay))) +			 set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); +		if ((is_rx && (ops->vidioc_s_fmt_vid_cap || +			       ops->vidioc_s_fmt_vid_cap_mplane || +			       ops->vidioc_s_fmt_vid_overlay)) || +		    (is_tx && (ops->vidioc_s_fmt_vid_out || +			       ops->vidioc_s_fmt_vid_out_mplane || +			       ops->vidioc_s_fmt_vid_out_overlay))) +			 set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); +		if ((is_rx && (ops->vidioc_try_fmt_vid_cap || +			       ops->vidioc_try_fmt_vid_cap_mplane || +			       ops->vidioc_try_fmt_vid_overlay)) || +		    (is_tx && (ops->vidioc_try_fmt_vid_out || +			       ops->vidioc_try_fmt_vid_out_mplane || +			       ops->vidioc_try_fmt_vid_out_overlay))) +			 set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); +	} else if (is_vbi) { +		if ((is_rx && (ops->vidioc_g_fmt_vbi_cap || +			       ops->vidioc_g_fmt_sliced_vbi_cap)) || +		    (is_tx && (ops->vidioc_g_fmt_vbi_out || +			       ops->vidioc_g_fmt_sliced_vbi_out))) +			set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); +		if ((is_rx && (ops->vidioc_s_fmt_vbi_cap || +			       ops->vidioc_s_fmt_sliced_vbi_cap)) || +		    (is_tx && (ops->vidioc_s_fmt_vbi_out || +			       ops->vidioc_s_fmt_sliced_vbi_out))) +			set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); +		if ((is_rx && (ops->vidioc_try_fmt_vbi_cap || +			       ops->vidioc_try_fmt_sliced_vbi_cap)) || +		    (is_tx && (ops->vidioc_try_fmt_vbi_out || +			       ops->vidioc_try_fmt_sliced_vbi_out))) +			set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); +	}  	SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);  	SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);  	SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);  	SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf); -	SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay); -	SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf); -	SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf); +	if (is_vid) { +		SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay); +		SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf); +		SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf); +	}  	SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);  	SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff); -	if (ops->vidioc_s_std) -		set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls); -	if (ops->vidioc_g_std || vdev->current_norm) -		set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls); -	SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std); -	SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd); -	SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input); -	SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input); -	SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input); -	SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output); -	SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output); -	SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output); +	if (!is_radio) { +		if (ops->vidioc_s_std) +			set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls); +		if (ops->vidioc_g_std || vdev->current_norm) +			set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls); +		SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std); +		if (is_rx) +			SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd); +		if (is_rx) { +			SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input); +			SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input); +			SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input); +			SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio); +			SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio); +			SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio); +		} +		if (is_tx) { +			SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output); +			SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output); +			SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output); +			SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout); +			SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout); +			SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout); +		} +	}  	/* Note: the control handler can also be passed through the filehandle,  	   and that can't be tested here. If the bit for these control ioctls  	   is set, then the ioctl is valid. But if it is 0, then it can still @@ -639,56 +665,68 @@ static void determine_valid_ioctls(struct video_device *vdev)  		set_bit(_IOC_NR(VIDIOC_TRY_EXT_CTRLS), valid_ioctls);  	if (vdev->ctrl_handler || ops->vidioc_querymenu)  		set_bit(_IOC_NR(VIDIOC_QUERYMENU), valid_ioctls); -	SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio); -	SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio); -	SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio); -	SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout); -	SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout); -	SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout); -	SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator); -	SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator); -	if (ops->vidioc_g_crop || ops->vidioc_g_selection) -		set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls); -	if (ops->vidioc_s_crop || ops->vidioc_s_selection) -		set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls); -	SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection); -	SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection); -	if (ops->vidioc_cropcap || ops->vidioc_g_selection) -		set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls); -	SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp); -	SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp); -	SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index); -	SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd); -	SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd); -	SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd); -	SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd); -	if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER && +	if (is_tx) { +		SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator); +		SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator); +	} +	if (!is_radio) { +		if (ops->vidioc_g_crop || ops->vidioc_g_selection) +			set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls); +		if (ops->vidioc_s_crop || ops->vidioc_s_selection) +			set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls); +		SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection); +		SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection); +		if (ops->vidioc_cropcap || ops->vidioc_g_selection) +			set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls); +	} +	if (is_vid) { +		SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp); +		SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp); +		SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index); +		SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd); +		SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd); +		SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd); +		SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd); +	} +	if (!is_radio) { +		if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER &&  					(ops->vidioc_g_std || vdev->current_norm))) -		set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls); -	SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm); -	SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner); -	SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner); +			set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls); +		SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm); +	} +	if (is_rx) { +		SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner); +		SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner); +	}  	SET_VALID_IOCTL(ops, VIDIOC_G_FREQUENCY, vidioc_g_frequency);  	SET_VALID_IOCTL(ops, VIDIOC_S_FREQUENCY, vidioc_s_frequency); -	SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap); +	if (is_vbi) +		SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);  	SET_VALID_IOCTL(ops, VIDIOC_LOG_STATUS, vidioc_log_status);  #ifdef CONFIG_VIDEO_ADV_DEBUG  	SET_VALID_IOCTL(ops, VIDIOC_DBG_G_REGISTER, vidioc_g_register);  	SET_VALID_IOCTL(ops, VIDIOC_DBG_S_REGISTER, vidioc_s_register);  #endif  	SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident); -	SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek); -	SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes); -	SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals); -	SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets); -	SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset); -	SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset); -	SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset); -	SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings); -	SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings); -	SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings); -	SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings); -	SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap); +	if (is_rx) +		SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek); +	if (is_vid) { +		SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes); +		SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals); +	} +	if (!is_radio) { +		SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets); +		SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset); +		SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset); +		if (is_rx) +			SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset); +		SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings); +		SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings); +		SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings); +		if (is_rx) +			SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings); +		SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap); +	}  	/* yes, really vidioc_subscribe_event */  	SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event);  	SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event);  |