Commit 48ea0be0 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] v4l2-dev/ioctl: determine the valid ioctls upfront

Rather than testing whether an ioctl is implemented in the driver or not
every time the ioctl is called, do it upfront when the device is registered.

This also allows a driver to disable certain ioctls based on the capabilities
of the detected board, something you can't do today without creating separate
v4l2_ioctl_ops structs for each new variation.

For the most part it is pretty straightforward, but for control ioctls a flag
is needed since it is possible that you have per-filehandle controls, and that
can't be determined upfront of course.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Acked-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 8ab75e3e
...@@ -516,6 +516,175 @@ static int get_index(struct video_device *vdev) ...@@ -516,6 +516,175 @@ static int get_index(struct video_device *vdev)
return find_first_zero_bit(used, VIDEO_NUM_DEVICES); return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
} }
#define SET_VALID_IOCTL(ops, cmd, op) \
if (ops->op) \
set_bit(_IOC_NR(cmd), valid_ioctls)
/* This determines which ioctls are actually implemented in the driver.
It's a one-time thing which simplifies video_ioctl2 as it can just do
a bit test.
Note that drivers can override this by setting bits to 1 in
vdev->valid_ioctls. If an ioctl is marked as 1 when this function is
called, then that ioctl will actually be marked as unimplemented.
It does that by first setting up the local valid_ioctls bitmap, and
at the end do a:
vdev->valid_ioctls = valid_ioctls & ~(vdev->valid_ioctls)
*/
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;
bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE);
SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap);
if (ops->vidioc_g_priority ||
test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
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 ||
ops->vidioc_enum_fmt_type_private)
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 ||
ops->vidioc_g_fmt_type_private)
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 ||
ops->vidioc_s_fmt_type_private)
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 ||
ops->vidioc_try_fmt_type_private)
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);
SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
if (vdev->tvnorms)
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);
/* 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
be valid if the filehandle passed the control handler. */
if (vdev->ctrl_handler || ops->vidioc_queryctrl)
set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls)
set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls)
set_bit(_IOC_NR(VIDIOC_S_CTRL), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_g_ext_ctrls)
set_bit(_IOC_NR(VIDIOC_G_EXT_CTRLS), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_s_ext_ctrls)
set_bit(_IOC_NR(VIDIOC_S_EXT_CTRLS), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_try_ext_ctrls)
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->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_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);
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);
/* yes, really vidioc_subscribe_event */
SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event);
SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event);
SET_VALID_IOCTL(ops, VIDIOC_UNSUBSCRIBE_EVENT, vidioc_unsubscribe_event);
SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
bitmap_andnot(vdev->valid_ioctls, valid_ioctls, vdev->valid_ioctls,
BASE_VIDIOC_PRIVATE);
}
/** /**
* __video_register_device - register video4linux devices * __video_register_device - register video4linux devices
* @vdev: video device structure we want to register * @vdev: video device structure we want to register
...@@ -663,6 +832,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr, ...@@ -663,6 +832,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
vdev->index = get_index(vdev); vdev->index = get_index(vdev);
mutex_unlock(&videodev_lock); mutex_unlock(&videodev_lock);
if (vdev->ioctl_ops)
determine_valid_ioctls(vdev);
/* Part 3: Initialize the character device */ /* Part 3: Initialize the character device */
vdev->cdev = cdev_alloc(); vdev->cdev = cdev_alloc();
if (vdev->cdev == NULL) { if (vdev->cdev == NULL) {
......
...@@ -55,19 +55,6 @@ ...@@ -55,19 +55,6 @@
memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \ memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field)) 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
#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_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 { struct std_descr {
v4l2_std_id std; v4l2_std_id std;
const char *descr; const char *descr;
...@@ -198,93 +185,98 @@ static const char *v4l2_memory_names[] = { ...@@ -198,93 +185,98 @@ static const char *v4l2_memory_names[] = {
struct v4l2_ioctl_info { struct v4l2_ioctl_info {
unsigned int ioctl; unsigned int ioctl;
u16 flags;
const char * const name; const char * const name;
}; };
#define IOCTL_INFO(_ioctl) [_IOC_NR(_ioctl)] = { \ /* This control can be valid if the filehandle passes a control handler. */
#define INFO_FL_CTRL (1 << 1)
#define IOCTL_INFO(_ioctl, _flags) [_IOC_NR(_ioctl)] = { \
.ioctl = _ioctl, \ .ioctl = _ioctl, \
.flags = _flags, \
.name = #_ioctl, \ .name = #_ioctl, \
} }
static struct v4l2_ioctl_info v4l2_ioctls[] = { static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO(VIDIOC_QUERYCAP), IOCTL_INFO(VIDIOC_QUERYCAP, 0),
IOCTL_INFO(VIDIOC_ENUM_FMT), IOCTL_INFO(VIDIOC_ENUM_FMT, 0),
IOCTL_INFO(VIDIOC_G_FMT), IOCTL_INFO(VIDIOC_G_FMT, 0),
IOCTL_INFO(VIDIOC_S_FMT), IOCTL_INFO(VIDIOC_S_FMT, 0),
IOCTL_INFO(VIDIOC_REQBUFS), IOCTL_INFO(VIDIOC_REQBUFS, 0),
IOCTL_INFO(VIDIOC_QUERYBUF), IOCTL_INFO(VIDIOC_QUERYBUF, 0),
IOCTL_INFO(VIDIOC_G_FBUF), IOCTL_INFO(VIDIOC_G_FBUF, 0),
IOCTL_INFO(VIDIOC_S_FBUF), IOCTL_INFO(VIDIOC_S_FBUF, 0),
IOCTL_INFO(VIDIOC_OVERLAY), IOCTL_INFO(VIDIOC_OVERLAY, 0),
IOCTL_INFO(VIDIOC_QBUF), IOCTL_INFO(VIDIOC_QBUF, 0),
IOCTL_INFO(VIDIOC_DQBUF), IOCTL_INFO(VIDIOC_DQBUF, 0),
IOCTL_INFO(VIDIOC_STREAMON), IOCTL_INFO(VIDIOC_STREAMON, 0),
IOCTL_INFO(VIDIOC_STREAMOFF), IOCTL_INFO(VIDIOC_STREAMOFF, 0),
IOCTL_INFO(VIDIOC_G_PARM), IOCTL_INFO(VIDIOC_G_PARM, 0),
IOCTL_INFO(VIDIOC_S_PARM), IOCTL_INFO(VIDIOC_S_PARM, 0),
IOCTL_INFO(VIDIOC_G_STD), IOCTL_INFO(VIDIOC_G_STD, 0),
IOCTL_INFO(VIDIOC_S_STD), IOCTL_INFO(VIDIOC_S_STD, 0),
IOCTL_INFO(VIDIOC_ENUMSTD), IOCTL_INFO(VIDIOC_ENUMSTD, 0),
IOCTL_INFO(VIDIOC_ENUMINPUT), IOCTL_INFO(VIDIOC_ENUMINPUT, 0),
IOCTL_INFO(VIDIOC_G_CTRL), IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_S_CTRL), IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_G_TUNER), IOCTL_INFO(VIDIOC_G_TUNER, 0),
IOCTL_INFO(VIDIOC_S_TUNER), IOCTL_INFO(VIDIOC_S_TUNER, 0),
IOCTL_INFO(VIDIOC_G_AUDIO), IOCTL_INFO(VIDIOC_G_AUDIO, 0),
IOCTL_INFO(VIDIOC_S_AUDIO), IOCTL_INFO(VIDIOC_S_AUDIO, 0),
IOCTL_INFO(VIDIOC_QUERYCTRL), IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_QUERYMENU), IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_G_INPUT), IOCTL_INFO(VIDIOC_G_INPUT, 0),
IOCTL_INFO(VIDIOC_S_INPUT), IOCTL_INFO(VIDIOC_S_INPUT, 0),
IOCTL_INFO(VIDIOC_G_OUTPUT), IOCTL_INFO(VIDIOC_G_OUTPUT, 0),
IOCTL_INFO(VIDIOC_S_OUTPUT), IOCTL_INFO(VIDIOC_S_OUTPUT, 0),
IOCTL_INFO(VIDIOC_ENUMOUTPUT), IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0),
IOCTL_INFO(VIDIOC_G_AUDOUT), IOCTL_INFO(VIDIOC_G_AUDOUT, 0),
IOCTL_INFO(VIDIOC_S_AUDOUT), IOCTL_INFO(VIDIOC_S_AUDOUT, 0),
IOCTL_INFO(VIDIOC_G_MODULATOR), IOCTL_INFO(VIDIOC_G_MODULATOR, 0),
IOCTL_INFO(VIDIOC_S_MODULATOR), IOCTL_INFO(VIDIOC_S_MODULATOR, 0),
IOCTL_INFO(VIDIOC_G_FREQUENCY), IOCTL_INFO(VIDIOC_G_FREQUENCY, 0),
IOCTL_INFO(VIDIOC_S_FREQUENCY), IOCTL_INFO(VIDIOC_S_FREQUENCY, 0),
IOCTL_INFO(VIDIOC_CROPCAP), IOCTL_INFO(VIDIOC_CROPCAP, 0),
IOCTL_INFO(VIDIOC_G_CROP), IOCTL_INFO(VIDIOC_G_CROP, 0),
IOCTL_INFO(VIDIOC_S_CROP), IOCTL_INFO(VIDIOC_S_CROP, 0),
IOCTL_INFO(VIDIOC_G_SELECTION), IOCTL_INFO(VIDIOC_G_SELECTION, 0),
IOCTL_INFO(VIDIOC_S_SELECTION), IOCTL_INFO(VIDIOC_S_SELECTION, 0),
IOCTL_INFO(VIDIOC_G_JPEGCOMP), IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0),
IOCTL_INFO(VIDIOC_S_JPEGCOMP), IOCTL_INFO(VIDIOC_S_JPEGCOMP, 0),
IOCTL_INFO(VIDIOC_QUERYSTD), IOCTL_INFO(VIDIOC_QUERYSTD, 0),
IOCTL_INFO(VIDIOC_TRY_FMT), IOCTL_INFO(VIDIOC_TRY_FMT, 0),
IOCTL_INFO(VIDIOC_ENUMAUDIO), IOCTL_INFO(VIDIOC_ENUMAUDIO, 0),
IOCTL_INFO(VIDIOC_ENUMAUDOUT), IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0),
IOCTL_INFO(VIDIOC_G_PRIORITY), IOCTL_INFO(VIDIOC_G_PRIORITY, 0),
IOCTL_INFO(VIDIOC_S_PRIORITY), IOCTL_INFO(VIDIOC_S_PRIORITY, 0),
IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP), IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0),
IOCTL_INFO(VIDIOC_LOG_STATUS), IOCTL_INFO(VIDIOC_LOG_STATUS, 0),
IOCTL_INFO(VIDIOC_G_EXT_CTRLS), IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_S_EXT_CTRLS), IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS), IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0),
IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES), IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0),
IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS), IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0),
IOCTL_INFO(VIDIOC_G_ENC_INDEX), IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0),
IOCTL_INFO(VIDIOC_ENCODER_CMD), IOCTL_INFO(VIDIOC_ENCODER_CMD, 0),
IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD), IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0),
IOCTL_INFO(VIDIOC_DECODER_CMD), IOCTL_INFO(VIDIOC_DECODER_CMD, 0),
IOCTL_INFO(VIDIOC_TRY_DECODER_CMD), IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0),
IOCTL_INFO(VIDIOC_DBG_S_REGISTER), IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0),
IOCTL_INFO(VIDIOC_DBG_G_REGISTER), IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0),
IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT), IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0),
IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK), IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, 0),
IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS), IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0),
IOCTL_INFO(VIDIOC_S_DV_PRESET), IOCTL_INFO(VIDIOC_S_DV_PRESET, 0),
IOCTL_INFO(VIDIOC_G_DV_PRESET), IOCTL_INFO(VIDIOC_G_DV_PRESET, 0),
IOCTL_INFO(VIDIOC_QUERY_DV_PRESET), IOCTL_INFO(VIDIOC_QUERY_DV_PRESET, 0),
IOCTL_INFO(VIDIOC_S_DV_TIMINGS), IOCTL_INFO(VIDIOC_S_DV_TIMINGS, 0),
IOCTL_INFO(VIDIOC_G_DV_TIMINGS), IOCTL_INFO(VIDIOC_G_DV_TIMINGS, 0),
IOCTL_INFO(VIDIOC_DQEVENT), IOCTL_INFO(VIDIOC_DQEVENT, 0),
IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT), IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0),
IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT), IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0),
IOCTL_INFO(VIDIOC_CREATE_BUFS), IOCTL_INFO(VIDIOC_CREATE_BUFS, 0),
IOCTL_INFO(VIDIOC_PREPARE_BUF), IOCTL_INFO(VIDIOC_PREPARE_BUF, 0),
}; };
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
...@@ -526,19 +518,26 @@ static long __video_do_ioctl(struct file *file, ...@@ -526,19 +518,26 @@ static long __video_do_ioctl(struct file *file,
return ret; return ret;
} }
if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
v4l_print_ioctl(vfd->name, cmd);
printk(KERN_CONT "\n");
}
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
vfh = file->private_data; vfh = file->private_data;
use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
}
if (use_fh_prio) if (use_fh_prio)
ret_prio = v4l2_prio_check(vfd->prio, vfh->prio); ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
}
if (v4l2_is_known_ioctl(cmd)) {
struct v4l2_ioctl_info *info = &v4l2_ioctls[_IOC_NR(cmd)];
if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
!((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
return -ENOTTY;
}
if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
v4l_print_ioctl(vfd->name, cmd);
printk(KERN_CONT "\n");
}
switch (cmd) { switch (cmd) {
...@@ -547,9 +546,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -547,9 +546,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_capability *cap = (struct v4l2_capability *)arg; struct v4l2_capability *cap = (struct v4l2_capability *)arg;
if (!ops->vidioc_querycap)
break;
cap->version = LINUX_VERSION_CODE; cap->version = LINUX_VERSION_CODE;
ret = ops->vidioc_querycap(file, fh, cap); ret = ops->vidioc_querycap(file, fh, cap);
if (!ret) if (!ret)
...@@ -600,6 +596,7 @@ static long __video_do_ioctl(struct file *file, ...@@ -600,6 +596,7 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_fmtdesc *f = arg; struct v4l2_fmtdesc *f = arg;
ret = -EINVAL;
switch (f->type) { switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (likely(ops->vidioc_enum_fmt_vid_cap)) if (likely(ops->vidioc_enum_fmt_vid_cap))
...@@ -632,7 +629,7 @@ static long __video_do_ioctl(struct file *file, ...@@ -632,7 +629,7 @@ static long __video_do_ioctl(struct file *file,
default: default:
break; break;
} }
if (likely (!ret)) if (likely(!ret))
dbgarg(cmd, "index=%d, type=%d, flags=%d, " dbgarg(cmd, "index=%d, type=%d, flags=%d, "
"pixelformat=%c%c%c%c, description='%s'\n", "pixelformat=%c%c%c%c, description='%s'\n",
f->index, f->type, f->flags, f->index, f->type, f->flags,
...@@ -641,14 +638,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -641,14 +638,6 @@ static long __video_do_ioctl(struct file *file,
(f->pixelformat >> 16) & 0xff, (f->pixelformat >> 16) & 0xff,
(f->pixelformat >> 24) & 0xff, (f->pixelformat >> 24) & 0xff,
f->description); f->description);
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; break;
} }
case VIDIOC_G_FMT: case VIDIOC_G_FMT:
...@@ -658,6 +647,7 @@ static long __video_do_ioctl(struct file *file, ...@@ -658,6 +647,7 @@ static long __video_do_ioctl(struct file *file,
/* FIXME: Should be one dump per type */ /* FIXME: Should be one dump per type */
dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names)); dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
ret = -EINVAL;
switch (f->type) { switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (ops->vidioc_g_fmt_vid_cap) if (ops->vidioc_g_fmt_vid_cap)
...@@ -719,17 +709,12 @@ static long __video_do_ioctl(struct file *file, ...@@ -719,17 +709,12 @@ static long __video_do_ioctl(struct file *file,
fh, f); fh, f);
break; break;
} }
if (unlikely(ret == -ENOTTY && have_fmt_ops(g)))
ret = -EINVAL;
break; break;
} }
case VIDIOC_S_FMT: case VIDIOC_S_FMT:
{ {
struct v4l2_format *f = (struct v4l2_format *)arg; struct v4l2_format *f = (struct v4l2_format *)arg;
if (!have_fmt_ops(s))
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -817,6 +802,7 @@ static long __video_do_ioctl(struct file *file, ...@@ -817,6 +802,7 @@ static long __video_do_ioctl(struct file *file,
/* FIXME: Should be one dump per type */ /* FIXME: Should be one dump per type */
dbgarg(cmd, "type=%s\n", prt_names(f->type, dbgarg(cmd, "type=%s\n", prt_names(f->type,
v4l2_type_names)); v4l2_type_names));
ret = -EINVAL;
switch (f->type) { switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.pix); CLEAR_AFTER_FIELD(f, fmt.pix);
...@@ -889,8 +875,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -889,8 +875,6 @@ static long __video_do_ioctl(struct file *file,
fh, f); fh, f);
break; break;
} }
if (unlikely(ret == -ENOTTY && have_fmt_ops(try)))
ret = -EINVAL;
break; break;
} }
/* FIXME: Those buf reqs could be handled here, /* FIXME: Those buf reqs could be handled here,
...@@ -901,8 +885,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -901,8 +885,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_requestbuffers *p = arg; struct v4l2_requestbuffers *p = arg;
if (!ops->vidioc_reqbufs)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -925,8 +907,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -925,8 +907,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_buffer *p = arg; struct v4l2_buffer *p = arg;
if (!ops->vidioc_querybuf)
break;
ret = check_fmt(ops, p->type); ret = check_fmt(ops, p->type);
if (ret) if (ret)
break; break;
...@@ -940,8 +920,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -940,8 +920,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_buffer *p = arg; struct v4l2_buffer *p = arg;
if (!ops->vidioc_qbuf)
break;
ret = check_fmt(ops, p->type); ret = check_fmt(ops, p->type);
if (ret) if (ret)
break; break;
...@@ -955,8 +933,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -955,8 +933,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_buffer *p = arg; struct v4l2_buffer *p = arg;
if (!ops->vidioc_dqbuf)
break;
ret = check_fmt(ops, p->type); ret = check_fmt(ops, p->type);
if (ret) if (ret)
break; break;
...@@ -970,8 +946,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -970,8 +946,6 @@ static long __video_do_ioctl(struct file *file,
{ {
int *i = arg; int *i = arg;
if (!ops->vidioc_overlay)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -984,8 +958,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -984,8 +958,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_framebuffer *p = arg; struct v4l2_framebuffer *p = arg;
if (!ops->vidioc_g_fbuf)
break;
ret = ops->vidioc_g_fbuf(file, fh, arg); ret = ops->vidioc_g_fbuf(file, fh, arg);
if (!ret) { if (!ret) {
dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n", dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
...@@ -999,8 +971,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -999,8 +971,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_framebuffer *p = arg; struct v4l2_framebuffer *p = arg;
if (!ops->vidioc_s_fbuf)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1015,8 +985,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1015,8 +985,6 @@ static long __video_do_ioctl(struct file *file,
{ {
enum v4l2_buf_type i = *(int *)arg; enum v4l2_buf_type i = *(int *)arg;
if (!ops->vidioc_streamon)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1029,8 +997,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1029,8 +997,6 @@ static long __video_do_ioctl(struct file *file,
{ {
enum v4l2_buf_type i = *(int *)arg; enum v4l2_buf_type i = *(int *)arg;
if (!ops->vidioc_streamoff)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1104,9 +1070,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1104,9 +1070,6 @@ static long __video_do_ioctl(struct file *file,
dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id); dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
if (!ops->vidioc_s_std)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1128,8 +1091,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1128,8 +1091,6 @@ static long __video_do_ioctl(struct file *file,
{ {
v4l2_std_id *p = arg; v4l2_std_id *p = arg;
if (!ops->vidioc_querystd)
break;
/* /*
* If nothing detected, it should return all supported * If nothing detected, it should return all supported
* Drivers just need to mask the std argument, in order * Drivers just need to mask the std argument, in order
...@@ -1163,9 +1124,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1163,9 +1124,6 @@ static long __video_do_ioctl(struct file *file,
if (ops->vidioc_s_dv_timings) if (ops->vidioc_s_dv_timings)
p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS; p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
if (!ops->vidioc_enum_input)
break;
ret = ops->vidioc_enum_input(file, fh, p); ret = ops->vidioc_enum_input(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "index=%d, name=%s, type=%d, " dbgarg(cmd, "index=%d, name=%s, type=%d, "
...@@ -1181,8 +1139,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1181,8 +1139,6 @@ static long __video_do_ioctl(struct file *file,
{ {
unsigned int *i = arg; unsigned int *i = arg;
if (!ops->vidioc_g_input)
break;
ret = ops->vidioc_g_input(file, fh, i); ret = ops->vidioc_g_input(file, fh, i);
if (!ret) if (!ret)
dbgarg(cmd, "value=%d\n", *i); dbgarg(cmd, "value=%d\n", *i);
...@@ -1192,8 +1148,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1192,8 +1148,6 @@ static long __video_do_ioctl(struct file *file,
{ {
unsigned int *i = arg; unsigned int *i = arg;
if (!ops->vidioc_s_input)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1208,9 +1162,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1208,9 +1162,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_output *p = arg; struct v4l2_output *p = arg;
if (!ops->vidioc_enum_output)
break;
/* /*
* We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
* CAP_STD here based on ioctl handler provided by the * CAP_STD here based on ioctl handler provided by the
...@@ -1237,8 +1188,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1237,8 +1188,6 @@ static long __video_do_ioctl(struct file *file,
{ {
unsigned int *i = arg; unsigned int *i = arg;
if (!ops->vidioc_g_output)
break;
ret = ops->vidioc_g_output(file, fh, i); ret = ops->vidioc_g_output(file, fh, i);
if (!ret) if (!ret)
dbgarg(cmd, "value=%d\n", *i); dbgarg(cmd, "value=%d\n", *i);
...@@ -1248,8 +1197,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1248,8 +1197,6 @@ static long __video_do_ioctl(struct file *file,
{ {
unsigned int *i = arg; unsigned int *i = arg;
if (!ops->vidioc_s_output)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1441,8 +1388,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1441,8 +1388,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_audio *p = arg; struct v4l2_audio *p = arg;
if (!ops->vidioc_enumaudio)
break;
ret = ops->vidioc_enumaudio(file, fh, p); ret = ops->vidioc_enumaudio(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
...@@ -1456,9 +1401,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1456,9 +1401,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_audio *p = arg; struct v4l2_audio *p = arg;
if (!ops->vidioc_g_audio)
break;
ret = ops->vidioc_g_audio(file, fh, p); ret = ops->vidioc_g_audio(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
...@@ -1472,8 +1414,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1472,8 +1414,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_audio *p = arg; struct v4l2_audio *p = arg;
if (!ops->vidioc_s_audio)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1488,8 +1428,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1488,8 +1428,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_audioout *p = arg; struct v4l2_audioout *p = arg;
if (!ops->vidioc_enumaudout)
break;
dbgarg(cmd, "Enum for index=%d\n", p->index); dbgarg(cmd, "Enum for index=%d\n", p->index);
ret = ops->vidioc_enumaudout(file, fh, p); ret = ops->vidioc_enumaudout(file, fh, p);
if (!ret) if (!ret)
...@@ -1502,9 +1440,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1502,9 +1440,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_audioout *p = arg; struct v4l2_audioout *p = arg;
if (!ops->vidioc_g_audout)
break;
ret = ops->vidioc_g_audout(file, fh, p); ret = ops->vidioc_g_audout(file, fh, p);
if (!ret) if (!ret)
dbgarg2("index=%d, name=%s, capability=%d, " dbgarg2("index=%d, name=%s, capability=%d, "
...@@ -1516,8 +1451,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1516,8 +1451,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_audioout *p = arg; struct v4l2_audioout *p = arg;
if (!ops->vidioc_s_audout)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1533,8 +1466,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1533,8 +1466,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_modulator *p = arg; struct v4l2_modulator *p = arg;
if (!ops->vidioc_g_modulator)
break;
ret = ops->vidioc_g_modulator(file, fh, p); ret = ops->vidioc_g_modulator(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "index=%d, name=%s, " dbgarg(cmd, "index=%d, name=%s, "
...@@ -1549,8 +1480,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1549,8 +1480,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_modulator *p = arg; struct v4l2_modulator *p = arg;
if (!ops->vidioc_s_modulator)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1566,9 +1495,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1566,9 +1495,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_crop *p = arg; struct v4l2_crop *p = arg;
if (!ops->vidioc_g_crop && !ops->vidioc_g_selection)
break;
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
if (ops->vidioc_g_crop) { if (ops->vidioc_g_crop) {
...@@ -1600,9 +1526,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1600,9 +1526,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_crop *p = arg; struct v4l2_crop *p = arg;
if (!ops->vidioc_s_crop && !ops->vidioc_s_selection)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1633,9 +1556,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1633,9 +1556,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_selection *p = arg; struct v4l2_selection *p = arg;
if (!ops->vidioc_g_selection)
break;
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
ret = ops->vidioc_g_selection(file, fh, p); ret = ops->vidioc_g_selection(file, fh, p);
...@@ -1647,9 +1567,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1647,9 +1567,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_selection *p = arg; struct v4l2_selection *p = arg;
if (!ops->vidioc_s_selection)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1666,9 +1583,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1666,9 +1583,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_cropcap *p = arg; struct v4l2_cropcap *p = arg;
/*FIXME: Should also show v4l2_fract pixelaspect */ /*FIXME: Should also show v4l2_fract pixelaspect */
if (!ops->vidioc_cropcap && !ops->vidioc_g_selection)
break;
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
if (ops->vidioc_cropcap) { if (ops->vidioc_cropcap) {
ret = ops->vidioc_cropcap(file, fh, p); ret = ops->vidioc_cropcap(file, fh, p);
...@@ -1712,9 +1626,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1712,9 +1626,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_jpegcompression *p = arg; struct v4l2_jpegcompression *p = arg;
if (!ops->vidioc_g_jpegcomp)
break;
ret = ops->vidioc_g_jpegcomp(file, fh, p); ret = ops->vidioc_g_jpegcomp(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "quality=%d, APPn=%d, " dbgarg(cmd, "quality=%d, APPn=%d, "
...@@ -1728,8 +1639,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1728,8 +1639,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_jpegcompression *p = arg; struct v4l2_jpegcompression *p = arg;
if (!ops->vidioc_g_jpegcomp)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1745,8 +1654,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1745,8 +1654,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_enc_idx *p = arg; struct v4l2_enc_idx *p = arg;
if (!ops->vidioc_g_enc_index)
break;
ret = ops->vidioc_g_enc_index(file, fh, p); ret = ops->vidioc_g_enc_index(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "entries=%d, entries_cap=%d\n", dbgarg(cmd, "entries=%d, entries_cap=%d\n",
...@@ -1757,8 +1664,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1757,8 +1664,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_encoder_cmd *p = arg; struct v4l2_encoder_cmd *p = arg;
if (!ops->vidioc_encoder_cmd)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1772,8 +1677,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1772,8 +1677,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_encoder_cmd *p = arg; struct v4l2_encoder_cmd *p = arg;
if (!ops->vidioc_try_encoder_cmd)
break;
ret = ops->vidioc_try_encoder_cmd(file, fh, p); ret = ops->vidioc_try_encoder_cmd(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
...@@ -1783,8 +1686,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1783,8 +1686,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_decoder_cmd *p = arg; struct v4l2_decoder_cmd *p = arg;
if (!ops->vidioc_decoder_cmd)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1798,8 +1699,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1798,8 +1699,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_decoder_cmd *p = arg; struct v4l2_decoder_cmd *p = arg;
if (!ops->vidioc_try_decoder_cmd)
break;
ret = ops->vidioc_try_decoder_cmd(file, fh, p); ret = ops->vidioc_try_decoder_cmd(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
...@@ -1809,8 +1708,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1809,8 +1708,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_streamparm *p = arg; struct v4l2_streamparm *p = arg;
if (!ops->vidioc_g_parm && !vfd->current_norm)
break;
if (ops->vidioc_g_parm) { if (ops->vidioc_g_parm) {
ret = check_fmt(ops, p->type); ret = check_fmt(ops, p->type);
if (ret) if (ret)
...@@ -1838,8 +1735,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1838,8 +1735,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_streamparm *p = arg; struct v4l2_streamparm *p = arg;
if (!ops->vidioc_s_parm)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1856,9 +1751,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1856,9 +1751,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_tuner *p = arg; struct v4l2_tuner *p = arg;
if (!ops->vidioc_g_tuner)
break;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
ret = ops->vidioc_g_tuner(file, fh, p); ret = ops->vidioc_g_tuner(file, fh, p);
...@@ -1877,8 +1769,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1877,8 +1769,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_tuner *p = arg; struct v4l2_tuner *p = arg;
if (!ops->vidioc_s_tuner)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1900,9 +1790,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1900,9 +1790,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_frequency *p = arg; struct v4l2_frequency *p = arg;
if (!ops->vidioc_g_frequency)
break;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
ret = ops->vidioc_g_frequency(file, fh, p); ret = ops->vidioc_g_frequency(file, fh, p);
...@@ -1916,8 +1803,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1916,8 +1803,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_frequency *p = arg; struct v4l2_frequency *p = arg;
enum v4l2_tuner_type type; enum v4l2_tuner_type type;
if (!ops->vidioc_s_frequency)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -1936,9 +1821,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1936,9 +1821,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_sliced_vbi_cap *p = arg; struct v4l2_sliced_vbi_cap *p = arg;
if (!ops->vidioc_g_sliced_vbi_cap)
break;
/* Clear up to type, everything after type is zerod already */ /* Clear up to type, everything after type is zerod already */
memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
...@@ -1950,8 +1832,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1950,8 +1832,6 @@ static long __video_do_ioctl(struct file *file,
} }
case VIDIOC_LOG_STATUS: case VIDIOC_LOG_STATUS:
{ {
if (!ops->vidioc_log_status)
break;
if (vfd->v4l2_dev) if (vfd->v4l2_dev)
pr_info("%s: ================= START STATUS =================\n", pr_info("%s: ================= START STATUS =================\n",
vfd->v4l2_dev->name); vfd->v4l2_dev->name);
...@@ -1966,12 +1846,10 @@ static long __video_do_ioctl(struct file *file, ...@@ -1966,12 +1846,10 @@ static long __video_do_ioctl(struct file *file,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
struct v4l2_dbg_register *p = arg; struct v4l2_dbg_register *p = arg;
if (ops->vidioc_g_register) {
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
ret = -EPERM; ret = -EPERM;
else else
ret = ops->vidioc_g_register(file, fh, p); ret = ops->vidioc_g_register(file, fh, p);
}
#endif #endif
break; break;
} }
...@@ -1980,12 +1858,10 @@ static long __video_do_ioctl(struct file *file, ...@@ -1980,12 +1858,10 @@ static long __video_do_ioctl(struct file *file,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
struct v4l2_dbg_register *p = arg; struct v4l2_dbg_register *p = arg;
if (ops->vidioc_s_register) {
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
ret = -EPERM; ret = -EPERM;
else else
ret = ops->vidioc_s_register(file, fh, p); ret = ops->vidioc_s_register(file, fh, p);
}
#endif #endif
break; break;
} }
...@@ -1993,8 +1869,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -1993,8 +1869,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_dbg_chip_ident *p = arg; struct v4l2_dbg_chip_ident *p = arg;
if (!ops->vidioc_g_chip_ident)
break;
p->ident = V4L2_IDENT_NONE; p->ident = V4L2_IDENT_NONE;
p->revision = 0; p->revision = 0;
ret = ops->vidioc_g_chip_ident(file, fh, p); ret = ops->vidioc_g_chip_ident(file, fh, p);
...@@ -2007,8 +1881,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2007,8 +1881,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_hw_freq_seek *p = arg; struct v4l2_hw_freq_seek *p = arg;
enum v4l2_tuner_type type; enum v4l2_tuner_type type;
if (!ops->vidioc_s_hw_freq_seek)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -2028,9 +1900,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2028,9 +1900,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_frmsizeenum *p = arg; struct v4l2_frmsizeenum *p = arg;
if (!ops->vidioc_enum_framesizes)
break;
ret = ops->vidioc_enum_framesizes(file, fh, p); ret = ops->vidioc_enum_framesizes(file, fh, p);
dbgarg(cmd, dbgarg(cmd,
"index=%d, pixelformat=%c%c%c%c, type=%d ", "index=%d, pixelformat=%c%c%c%c, type=%d ",
...@@ -2064,9 +1933,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2064,9 +1933,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_frmivalenum *p = arg; struct v4l2_frmivalenum *p = arg;
if (!ops->vidioc_enum_frameintervals)
break;
ret = ops->vidioc_enum_frameintervals(file, fh, p); ret = ops->vidioc_enum_frameintervals(file, fh, p);
dbgarg(cmd, dbgarg(cmd,
"index=%d, pixelformat=%d, width=%d, height=%d, type=%d ", "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
...@@ -2099,9 +1965,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2099,9 +1965,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_dv_enum_preset *p = arg; struct v4l2_dv_enum_preset *p = arg;
if (!ops->vidioc_enum_dv_presets)
break;
ret = ops->vidioc_enum_dv_presets(file, fh, p); ret = ops->vidioc_enum_dv_presets(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, dbgarg(cmd,
...@@ -2115,8 +1978,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2115,8 +1978,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_dv_preset *p = arg; struct v4l2_dv_preset *p = arg;
if (!ops->vidioc_s_dv_preset)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -2130,9 +1991,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2130,9 +1991,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_dv_preset *p = arg; struct v4l2_dv_preset *p = arg;
if (!ops->vidioc_g_dv_preset)
break;
ret = ops->vidioc_g_dv_preset(file, fh, p); ret = ops->vidioc_g_dv_preset(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "preset=%d\n", p->preset); dbgarg(cmd, "preset=%d\n", p->preset);
...@@ -2142,9 +2000,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2142,9 +2000,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_dv_preset *p = arg; struct v4l2_dv_preset *p = arg;
if (!ops->vidioc_query_dv_preset)
break;
ret = ops->vidioc_query_dv_preset(file, fh, p); ret = ops->vidioc_query_dv_preset(file, fh, p);
if (!ret) if (!ret)
dbgarg(cmd, "preset=%d\n", p->preset); dbgarg(cmd, "preset=%d\n", p->preset);
...@@ -2154,8 +2009,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2154,8 +2009,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_dv_timings *p = arg; struct v4l2_dv_timings *p = arg;
if (!ops->vidioc_s_dv_timings)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -2188,9 +2041,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2188,9 +2041,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_dv_timings *p = arg; struct v4l2_dv_timings *p = arg;
if (!ops->vidioc_g_dv_timings)
break;
ret = ops->vidioc_g_dv_timings(file, fh, p); ret = ops->vidioc_g_dv_timings(file, fh, p);
if (!ret) { if (!ret) {
switch (p->type) { switch (p->type) {
...@@ -2222,9 +2072,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2222,9 +2072,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_event *ev = arg; struct v4l2_event *ev = arg;
if (!ops->vidioc_subscribe_event)
break;
ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK); ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK);
if (ret < 0) { if (ret < 0) {
dbgarg(cmd, "no pending events?"); dbgarg(cmd, "no pending events?");
...@@ -2241,9 +2088,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2241,9 +2088,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_event_subscription *sub = arg; struct v4l2_event_subscription *sub = arg;
if (!ops->vidioc_subscribe_event)
break;
ret = ops->vidioc_subscribe_event(fh, sub); ret = ops->vidioc_subscribe_event(fh, sub);
if (ret < 0) { if (ret < 0) {
dbgarg(cmd, "failed, ret=%ld", ret); dbgarg(cmd, "failed, ret=%ld", ret);
...@@ -2256,9 +2100,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2256,9 +2100,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_event_subscription *sub = arg; struct v4l2_event_subscription *sub = arg;
if (!ops->vidioc_unsubscribe_event)
break;
ret = ops->vidioc_unsubscribe_event(fh, sub); ret = ops->vidioc_unsubscribe_event(fh, sub);
if (ret < 0) { if (ret < 0) {
dbgarg(cmd, "failed, ret=%ld", ret); dbgarg(cmd, "failed, ret=%ld", ret);
...@@ -2271,8 +2112,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2271,8 +2112,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_create_buffers *create = arg; struct v4l2_create_buffers *create = arg;
if (!ops->vidioc_create_bufs)
break;
if (ret_prio) { if (ret_prio) {
ret = ret_prio; ret = ret_prio;
break; break;
...@@ -2290,8 +2129,6 @@ static long __video_do_ioctl(struct file *file, ...@@ -2290,8 +2129,6 @@ static long __video_do_ioctl(struct file *file,
{ {
struct v4l2_buffer *b = arg; struct v4l2_buffer *b = arg;
if (!ops->vidioc_prepare_buf)
break;
ret = check_fmt(ops, b->type); ret = check_fmt(ops, b->type);
if (ret) if (ret)
break; break;
......
...@@ -126,6 +126,7 @@ struct video_device ...@@ -126,6 +126,7 @@ struct video_device
/* ioctl callbacks */ /* ioctl callbacks */
const struct v4l2_ioctl_ops *ioctl_ops; const struct v4l2_ioctl_ops *ioctl_ops;
DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
/* serialization lock */ /* serialization lock */
DECLARE_BITMAP(dont_use_lock, BASE_VIDIOC_PRIVATE); DECLARE_BITMAP(dont_use_lock, BASE_VIDIOC_PRIVATE);
...@@ -184,6 +185,16 @@ static inline void v4l2_dont_use_lock(struct video_device *vdev, unsigned int cm ...@@ -184,6 +185,16 @@ static inline void v4l2_dont_use_lock(struct video_device *vdev, unsigned int cm
set_bit(_IOC_NR(cmd), vdev->dont_use_lock); set_bit(_IOC_NR(cmd), vdev->dont_use_lock);
} }
/* Mark that this command isn't implemented, must be called before
video_device_register. See also the comments in determine_valid_ioctls().
This function allows drivers to provide just one v4l2_ioctl_ops struct, but
disable ioctls based on the specific card that is actually found. */
static inline void v4l2_dont_use_cmd(struct video_device *vdev, unsigned int cmd)
{
if (_IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
set_bit(_IOC_NR(cmd), vdev->valid_ioctls);
}
/* helper functions to access driver private data. */ /* helper functions to access driver private data. */
static inline void *video_get_drvdata(struct video_device *vdev) static inline void *video_get_drvdata(struct video_device *vdev)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment