From patchwork Wed Jun 10 11:17:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda Delgado X-Patchwork-Id: 6578631 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 53B49C0020 for ; Wed, 10 Jun 2015 11:18:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F07FB2037E for ; Wed, 10 Jun 2015 11:18:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 31245203A1 for ; Wed, 10 Jun 2015 11:18:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754202AbbFJLR7 (ORCPT ); Wed, 10 Jun 2015 07:17:59 -0400 Received: from mail-la0-f46.google.com ([209.85.215.46]:34247 "EHLO mail-la0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754173AbbFJLR6 (ORCPT ); Wed, 10 Jun 2015 07:17:58 -0400 Received: by laew7 with SMTP id w7so30604036lae.1 for ; Wed, 10 Jun 2015 04:17:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=tnjz3TKIelTHi09tFf8J179IcZfBF18sPjEhw0LV7yU=; b=xLX6oWvp2BN8ZbYXXF4y+dIV7X6Xw2jZrEzeP+NFpfFrP5CsuagSatsGbUZSQZbnQQ 1foywC8DJswmsuZr5SYDYIsv6s235YOwaNXQjnimV4Z0OQRptMIB2o2/u5mJJO+OcoZz p2+gxtDBbjLxr0kg2DSSZXxiJ/GEzT9wHT5DsC1bbCkzduxXGwrgnejumjYOmPuiiS+8 gsXA8Tjtb3Hx10mKAwXjYg9zirqJXx3ho9fCb2nSzdBwvR3CePhDBZFMPnAe147BSwk/ eZpmjQIFkiEUJGq6H5o56O1eNuyxluMZ6nMQJHRqAJPkRW3JsmOuJupDJa1yUHdGjh/w OEfg== X-Received: by 10.112.83.135 with SMTP id q7mr3196535lby.13.1433935076070; Wed, 10 Jun 2015 04:17:56 -0700 (PDT) Received: from neopili.qtec.com (cpe.xe-3-0-1-778.vbrnqe10.dk.customer.tdc.net. [80.197.57.18]) by mx.google.com with ESMTPSA id e3sm2110068lag.26.2015.06.10.04.17.55 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 10 Jun 2015 04:17:55 -0700 (PDT) From: Ricardo Ribalda Delgado To: Hans Verkuil , Sakari Ailus , Laurent Pinchart , Mauro Carvalho Chehab , Guennadi Liakhovetski , linux-media@vger.kernel.org Cc: Ricardo Ribalda Delgado Subject: [RFC] media: New ioct VIDIOC_INITIAL_EXT_CTRLS Date: Wed, 10 Jun 2015 13:17:53 +0200 Message-Id: <1433935073-24104-1-git-send-email-ricardo.ribalda@gmail.com> X-Mailer: git-send-email 2.1.4 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Integer controls provide a way to get their default/initial value, but any other control (p_u32, p_u8.....) provide no other way to get the initial value than unloading the module and loading it back. *What is the actual problem? I have a custom control with WIDTH integer values. Every value represents the calibrated FPN (fixed pattern noise) correction value for that column -Application A changes the FPN correction value -Application B wants to restore the calibrated value but it cant :( *What is the proposed solution? -Add a new ioctl VIDIOC_INITIAL_EXT_CTRLS, with the same API as G_EXT_CTRLS, but that returns the initial value of a given control *This code is not splited in different patches and there is no doc! Yes, at this point I want your feedback about the ioctl, and an initial piece of code could help the disscussion. Of course, once we agreed I will provide the documentation and a properly build patchset. So, shoot me: What do you think? THANKS! Signed-off-by: Ricardo Ribalda Delgado --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 ++ drivers/media/v4l2-core/v4l2-ctrls.c | 65 ++++++++++++++++++++++++--- drivers/media/v4l2-core/v4l2-ioctl.c | 20 +++++++++ drivers/media/v4l2-core/v4l2-subdev.c | 3 ++ include/media/v4l2-ctrls.h | 2 + include/media/v4l2-ioctl.h | 2 + include/uapi/linux/videodev2.h | 4 +- 7 files changed, 92 insertions(+), 8 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index af635430524e..1e3272e28b2d 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -817,6 +817,7 @@ static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) +#define VIDIOC_INITIAL_EXT_CTRLS32 _IOWR('V', 104, struct v4l2_ext_controls32) #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32) #define VIDIOC_STREAMON32 _IOW ('V', 18, s32) @@ -859,6 +860,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break; case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break; + case VIDIOC_INITIAL_EXT_CTRLS32: cmd = VIDIOC_INITIAL_EXT_CTRLS; break; case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break; case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break; case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; @@ -937,6 +939,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_G_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: + case VIDIOC_INITIAL_EXT_CTRLS: err = get_v4l2_ext_controls32(&karg.v2ecs, up); compatible_arg = 0; break; @@ -964,6 +967,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_G_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: + case VIDIOC_INITIAL_EXT_CTRLS: if (put_v4l2_ext_controls32(&karg.v2ecs, up)) err = -EFAULT; break; diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index b462165a7f0c..465f73acc644 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1449,6 +1449,40 @@ static const struct v4l2_ctrl_type_ops std_type_ops = { .validate = std_validate, }; +/* Helper function: copy the initial value back to the caller */ +static int init_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) +{ + int idx; + int ret; + long size; + union v4l2_ctrl_ptr ptr; + + if (!ctrl->is_ptr){ + ptr.p = &c->value; + ctrl->type_ops->init(ctrl, 0, ptr); + return 0; + } + + size = ctrl->elem_size * ctrl->elems; + if (c->size < size){ + c->size = size; + return -ENOSPC; + } + + ptr.p = kzalloc(size, GFP_KERNEL); + if (!ptr.p) + return -ENOMEM; + + for (idx=0; idxelems; idx++) + ctrl->type_ops->init(ctrl, idx, ptr); + + ret = copy_to_user(c->ptr, ptr.p, size); + + kfree(ptr.p); + + return ret ? -EFAULT : 0; +} + /* Helper function: copy the given control value back to the caller */ static int ptr_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl, @@ -2806,10 +2840,10 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 ctrl_class) return find_ref_lock(hdl, ctrl_class | 1) ? 0 : -EINVAL; } - - /* Get extended controls. Allocates the helpers array if needed. */ -int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs) +static int v4l2_g_ext_ctrls_initial(struct v4l2_ctrl_handler *hdl, + struct v4l2_ext_controls *cs, + bool initial_value) { struct v4l2_ctrl_helper helper[4]; struct v4l2_ctrl_helper *helpers = helper; @@ -2840,10 +2874,11 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs ret = -EACCES; for (i = 0; !ret && i < cs->count; i++) { - int (*ctrl_to_user)(struct v4l2_ext_control *c, - struct v4l2_ctrl *ctrl) = cur_to_user; + int (*ctrl_to_user)(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl); struct v4l2_ctrl *master; + ctrl_to_user = initial_value ? init_to_user : cur_to_user; + if (helpers[i].mref == NULL) continue; @@ -2853,8 +2888,9 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs v4l2_ctrl_lock(master); /* g_volatile_ctrl will update the new control values */ - if ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || - (master->has_volatiles && !is_cur_manual(master))) { + if ((!(master->flags & V4L2_CTRL_FLAG_VOLATILE) || + (master->has_volatiles && !is_cur_manual(master))) && + !initial_value) { for (j = 0; j < master->ncontrols; j++) cur_to_new(master->cluster[j]); ret = call_op(master, g_volatile_ctrl); @@ -2879,6 +2915,10 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs kfree(helpers); return ret; } + +int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs){ + return v4l2_g_ext_ctrls_initial(hdl, cs, false); +} EXPORT_SYMBOL(v4l2_g_ext_ctrls); int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs) @@ -2887,6 +2927,17 @@ int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs } EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls); +int v4l2_initial_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs){ + return v4l2_g_ext_ctrls_initial(hdl, cs, true); +} +EXPORT_SYMBOL(v4l2_initial_ext_ctrls); + +int v4l2_subdev_initial_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs) +{ + return v4l2_initial_ext_ctrls(sd->ctrl_handler, cs); +} +EXPORT_SYMBOL(v4l2_subdev_initial_ext_ctrls); + /* Helper function to get a single control */ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) { diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 8712168a3b0a..e68d9ec8832a 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1812,6 +1812,25 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, -EINVAL; } +static int v4l_initial_ext_ctrls(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct video_device *vfd = video_devdata(file); + struct v4l2_ext_controls *p = arg; + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + + p->error_idx = p->count; + if (vfh && vfh->ctrl_handler) + return v4l2_initial_ext_ctrls(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_initial_ext_ctrls(vfd->ctrl_handler, p); + if (ops->vidioc_initial_ext_ctrls == NULL) + return -ENOTTY; + return check_ext_ctrls(p, 0) ? ops->vidioc_initial_ext_ctrls(file, fh, p) : + -EINVAL; +} + static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -2285,6 +2304,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_G_SLICED_VBI_CAP, v4l_g_sliced_vbi_cap, v4l_print_sliced_vbi_cap, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0), IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), + IOCTL_INFO_FNC(VIDIOC_INITIAL_EXT_CTRLS, v4l_initial_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL), IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), IOCTL_INFO_STD(VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 19a034e79be4..6ed308df9d2f 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -206,6 +206,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_G_EXT_CTRLS: return v4l2_g_ext_ctrls(vfh->ctrl_handler, arg); + case VIDIOC_INITIAL_EXT_CTRLS: + return v4l2_initial_ext_ctrls(vfh->ctrl_handler, arg); + case VIDIOC_S_EXT_CTRLS: return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, arg); diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index ec63d8c44f4e..6521f54718ca 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -815,6 +815,7 @@ int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl); int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl); int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c); +int v4l2_initial_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c); int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c); int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c); @@ -824,6 +825,7 @@ int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc); int v4l2_subdev_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qm); int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs); +int v4l2_subdev_initial_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs); int v4l2_subdev_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs); int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs); int v4l2_subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 8537983b9b22..16a289bc46b1 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -166,6 +166,8 @@ struct v4l2_ioctl_ops { struct v4l2_control *a); int (*vidioc_g_ext_ctrls) (struct file *file, void *fh, struct v4l2_ext_controls *a); + int (*vidioc_initial_ext_ctrls)(struct file *file, void *fh, + struct v4l2_ext_controls *a); int (*vidioc_s_ext_ctrls) (struct file *file, void *fh, struct v4l2_ext_controls *a); int (*vidioc_try_ext_ctrls) (struct file *file, void *fh, diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 2b26d23f9b04..9b84f1755d5f 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -2204,8 +2204,10 @@ struct v4l2_create_buffers { #define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl) +#define VIDIOC_INITIAL_EXT_CTRLS _IOWR('V', 104, struct v4l2_ext_controls) + /* Reminder: when adding new ioctls please add support for them to - drivers/media/video/v4l2-compat-ioctl32.c as well! */ + drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */ #define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */