diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-subdev.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-subdev.c | 103 |
1 files changed, 86 insertions, 17 deletions
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index dced41c1d99..058c1a6e839 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -305,11 +305,23 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) fse); } - case VIDIOC_SUBDEV_G_FRAME_INTERVAL: + case VIDIOC_SUBDEV_G_FRAME_INTERVAL: { + struct v4l2_subdev_frame_interval *fi = arg; + + if (fi->pad >= sd->entity.num_pads) + return -EINVAL; + return v4l2_subdev_call(sd, video, g_frame_interval, arg); + } + + case VIDIOC_SUBDEV_S_FRAME_INTERVAL: { + struct v4l2_subdev_frame_interval *fi = arg; + + if (fi->pad >= sd->entity.num_pads) + return -EINVAL; - case VIDIOC_SUBDEV_S_FRAME_INTERVAL: return v4l2_subdev_call(sd, video, s_frame_interval, arg); + } case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: { struct v4l2_subdev_frame_interval_enum *fie = arg; @@ -349,11 +361,54 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) sd, pad, set_selection, subdev_fh, sel); } - case VIDIOC_SUBDEV_G_EDID: - return v4l2_subdev_call(sd, pad, get_edid, arg); + case VIDIOC_G_EDID: { + struct v4l2_subdev_edid *edid = arg; + + if (edid->pad >= sd->entity.num_pads) + return -EINVAL; + if (edid->blocks && edid->edid == NULL) + return -EINVAL; - case VIDIOC_SUBDEV_S_EDID: - return v4l2_subdev_call(sd, pad, set_edid, arg); + return v4l2_subdev_call(sd, pad, get_edid, edid); + } + + case VIDIOC_S_EDID: { + struct v4l2_subdev_edid *edid = arg; + + if (edid->pad >= sd->entity.num_pads) + return -EINVAL; + if (edid->blocks && edid->edid == NULL) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, set_edid, edid); + } + + case VIDIOC_SUBDEV_DV_TIMINGS_CAP: { + struct v4l2_dv_timings_cap *cap = arg; + + if (cap->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, dv_timings_cap, cap); + } + + case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: { + struct v4l2_enum_dv_timings *dvt = arg; + + if (dvt->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt); + } + + case VIDIOC_SUBDEV_QUERY_DV_TIMINGS: + return v4l2_subdev_call(sd, video, query_dv_timings, arg); + + case VIDIOC_SUBDEV_G_DV_TIMINGS: + return v4l2_subdev_call(sd, video, g_dv_timings, arg); + + case VIDIOC_SUBDEV_S_DV_TIMINGS: + return v4l2_subdev_call(sd, video, s_dv_timings, arg); #endif default: return v4l2_subdev_call(sd, core, ioctl, cmd, arg); @@ -368,6 +423,17 @@ static long subdev_ioctl(struct file *file, unsigned int cmd, return video_usercopy(file, cmd, arg, subdev_do_ioctl); } +#ifdef CONFIG_COMPAT +static long subdev_compat_ioctl32(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + + return v4l2_subdev_call(sd, core, compat_ioctl32, cmd, arg); +} +#endif + static unsigned int subdev_poll(struct file *file, poll_table *wait) { struct video_device *vdev = video_devdata(file); @@ -389,6 +455,9 @@ const struct v4l2_file_operations v4l2_subdev_fops = { .owner = THIS_MODULE, .open = subdev_open, .unlocked_ioctl = subdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = subdev_compat_ioctl32, +#endif .release = subdev_close, .poll = subdev_poll, }; @@ -412,20 +481,20 @@ static int v4l2_subdev_link_validate_get_format(struct media_pad *pad, struct v4l2_subdev_format *fmt) { - switch (media_entity_type(pad->entity)) { - case MEDIA_ENT_T_V4L2_SUBDEV: + if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) { + struct v4l2_subdev *sd = + media_entity_to_v4l2_subdev(pad->entity); + fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE; fmt->pad = pad->index; - return v4l2_subdev_call(media_entity_to_v4l2_subdev( - pad->entity), - pad, get_fmt, NULL, fmt); - default: - WARN(1, "Driver bug! Wrong media entity type %d, entity %s\n", - media_entity_type(pad->entity), pad->entity->name); - /* Fall through */ - case MEDIA_ENT_T_DEVNODE_V4L: - return -EINVAL; + return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt); } + + WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L, + "Driver bug! Wrong media entity type 0x%08x, entity %s\n", + pad->entity->type, pad->entity->name); + + return -EINVAL; } int v4l2_subdev_link_validate(struct media_link *link) |
