Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 320113
b: refs/heads/master
c: 27cd2ab
h: refs/heads/master
i:
  320111: 776b46a
v: v3
  • Loading branch information
Hans Verkuil authored and Mauro Carvalho Chehab committed Jul 6, 2012
1 parent 513cffd commit 485c0b4
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 63 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4839e6c2ac7c1a25d285b66240e702bb9b5fdcbf
refs/heads/master: 27cd2aba172dffb7819b9ca49a6a8acdbb8cf7e5
103 changes: 41 additions & 62 deletions trunk/drivers/media/video/v4l2-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,14 +394,19 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)

struct v4l2_ioctl_info {
unsigned int ioctl;
u16 flags;
u32 flags;
const char * const name;
};

/* This control needs a priority check */
#define INFO_FL_PRIO (1 << 0)
/* This control can be valid if the filehandle passes a control handler. */
#define INFO_FL_CTRL (1 << 1)
/* Zero struct from after the field to the end */
#define INFO_FL_CLEAR(v4l2_struct, field) \
((offsetof(struct v4l2_struct, field) + \
sizeof(((struct v4l2_struct *)0)->field)) << 16)
#define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16)

#define IOCTL_INFO(_ioctl, _flags) [_IOC_NR(_ioctl)] = { \
.ioctl = _ioctl, \
Expand All @@ -411,66 +416,66 @@ struct v4l2_ioctl_info {

static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO(VIDIOC_QUERYCAP, 0),
IOCTL_INFO(VIDIOC_ENUM_FMT, 0),
IOCTL_INFO(VIDIOC_G_FMT, 0),
IOCTL_INFO(VIDIOC_ENUM_FMT, INFO_FL_CLEAR(v4l2_fmtdesc, type)),
IOCTL_INFO(VIDIOC_G_FMT, INFO_FL_CLEAR(v4l2_format, type)),
IOCTL_INFO(VIDIOC_S_FMT, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_REQBUFS, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QUERYBUF, 0),
IOCTL_INFO(VIDIOC_QUERYBUF, INFO_FL_CLEAR(v4l2_buffer, length)),
IOCTL_INFO(VIDIOC_G_FBUF, 0),
IOCTL_INFO(VIDIOC_S_FBUF, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_OVERLAY, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QBUF, 0),
IOCTL_INFO(VIDIOC_DQBUF, 0),
IOCTL_INFO(VIDIOC_STREAMON, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_STREAMOFF, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_PARM, 0),
IOCTL_INFO(VIDIOC_G_PARM, INFO_FL_CLEAR(v4l2_streamparm, type)),
IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_STD, 0),
IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_ENUMSTD, 0),
IOCTL_INFO(VIDIOC_ENUMINPUT, 0),
IOCTL_INFO(VIDIOC_ENUMSTD, INFO_FL_CLEAR(v4l2_standard, index)),
IOCTL_INFO(VIDIOC_ENUMINPUT, INFO_FL_CLEAR(v4l2_input, index)),
IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_G_TUNER, 0),
IOCTL_INFO(VIDIOC_G_TUNER, INFO_FL_CLEAR(v4l2_tuner, index)),
IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_AUDIO, 0),
IOCTL_INFO(VIDIOC_S_AUDIO, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)),
IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
IOCTL_INFO(VIDIOC_G_INPUT, 0),
IOCTL_INFO(VIDIOC_S_INPUT, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_OUTPUT, 0),
IOCTL_INFO(VIDIOC_G_OUTPUT, INFO_FL_CLEAR(v4l2_output, index)),
IOCTL_INFO(VIDIOC_S_OUTPUT, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0),
IOCTL_INFO(VIDIOC_G_AUDOUT, 0),
IOCTL_INFO(VIDIOC_S_AUDOUT, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_MODULATOR, 0),
IOCTL_INFO(VIDIOC_G_MODULATOR, INFO_FL_CLEAR(v4l2_modulator, index)),
IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_FREQUENCY, 0),
IOCTL_INFO(VIDIOC_G_FREQUENCY, INFO_FL_CLEAR(v4l2_frequency, tuner)),
IOCTL_INFO(VIDIOC_S_FREQUENCY, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_CROPCAP, 0),
IOCTL_INFO(VIDIOC_G_CROP, 0),
IOCTL_INFO(VIDIOC_CROPCAP, INFO_FL_CLEAR(v4l2_cropcap, type)),
IOCTL_INFO(VIDIOC_G_CROP, INFO_FL_CLEAR(v4l2_crop, type)),
IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_SELECTION, 0),
IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0),
IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QUERYSTD, 0),
IOCTL_INFO(VIDIOC_TRY_FMT, 0),
IOCTL_INFO(VIDIOC_ENUMAUDIO, 0),
IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0),
IOCTL_INFO(VIDIOC_ENUMAUDIO, INFO_FL_CLEAR(v4l2_audio, index)),
IOCTL_INFO(VIDIOC_ENUMAUDOUT, INFO_FL_CLEAR(v4l2_audioout, index)),
IOCTL_INFO(VIDIOC_G_PRIORITY, 0),
IOCTL_INFO(VIDIOC_S_PRIORITY, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0),
IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)),
IOCTL_INFO(VIDIOC_LOG_STATUS, 0),
IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_PRIO | INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0),
IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0),
IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0),
IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)),
IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, INFO_FL_CLEAR(v4l2_frmivalenum, height)),
IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0),
IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0),
IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
IOCTL_INFO(VIDIOC_DECODER_CMD, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0),
#ifdef CONFIG_VIDEO_ADV_DEBUG
Expand Down Expand Up @@ -2106,45 +2111,6 @@ static long __video_do_ioctl(struct file *file,
return ret;
}

/* In some cases, only a few fields are used as input, i.e. when the app sets
* "index" and then the driver fills in the rest of the structure for the thing
* with that index. We only need to copy up the first non-input field. */
static unsigned long cmd_input_size(unsigned int cmd)
{
/* Size of structure up to and including 'field' */
#define CMDINSIZE(cmd, type, field) \
case VIDIOC_##cmd: \
return offsetof(struct v4l2_##type, field) + \
sizeof(((struct v4l2_##type *)0)->field);

switch (cmd) {
CMDINSIZE(ENUM_FMT, fmtdesc, type);
CMDINSIZE(G_FMT, format, type);
CMDINSIZE(QUERYBUF, buffer, length);
CMDINSIZE(G_PARM, streamparm, type);
CMDINSIZE(ENUMSTD, standard, index);
CMDINSIZE(ENUMINPUT, input, index);
CMDINSIZE(G_CTRL, control, id);
CMDINSIZE(G_TUNER, tuner, index);
CMDINSIZE(QUERYCTRL, queryctrl, id);
CMDINSIZE(QUERYMENU, querymenu, index);
CMDINSIZE(ENUMOUTPUT, output, index);
CMDINSIZE(G_MODULATOR, modulator, index);
CMDINSIZE(G_FREQUENCY, frequency, tuner);
CMDINSIZE(CROPCAP, cropcap, type);
CMDINSIZE(G_CROP, crop, type);
CMDINSIZE(ENUMAUDIO, audio, index);
CMDINSIZE(ENUMAUDOUT, audioout, index);
CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
default:
return _IOC_SIZE(cmd);
}
}

static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
void * __user *user_ptr, void ***kernel_ptr)
{
Expand Down Expand Up @@ -2219,7 +2185,20 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,

err = -EFAULT;
if (_IOC_DIR(cmd) & _IOC_WRITE) {
unsigned long n = cmd_input_size(cmd);
unsigned int n = _IOC_SIZE(cmd);

/*
* In some cases, only a few fields are used as input,
* i.e. when the app sets "index" and then the driver
* fills in the rest of the structure for the thing
* with that index. We only need to copy up the first
* non-input field.
*/
if (v4l2_is_known_ioctl(cmd)) {
u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags;
if (flags & INFO_FL_CLEAR_MASK)
n = (flags & INFO_FL_CLEAR_MASK) >> 16;
}

if (copy_from_user(parg, (void __user *)arg, n))
goto out;
Expand Down

0 comments on commit 485c0b4

Please sign in to comment.