diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-subdev.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-subdev.c | 81 | 
1 files changed, 75 insertions, 6 deletions
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 996c248dea4..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; + +		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; -	case VIDIOC_SUBDEV_S_EDID: -		return v4l2_subdev_call(sd, pad, set_edid, 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,  };  | 
