From patchwork Mon Jan 20 12:46:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 3512461 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.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C7631C02DC for ; Mon, 20 Jan 2014 12:47:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9225A200C6 for ; Mon, 20 Jan 2014 12:47:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5163020108 for ; Mon, 20 Jan 2014 12:47:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753512AbaATMrE (ORCPT ); Mon, 20 Jan 2014 07:47:04 -0500 Received: from smtp-vbr4.xs4all.nl ([194.109.24.24]:4240 "EHLO smtp-vbr4.xs4all.nl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753299AbaATMqw (ORCPT ); Mon, 20 Jan 2014 07:46:52 -0500 Received: from tschai.lan (173-38-208-169.cisco.com [173.38.208.169]) (authenticated bits=0) by smtp-vbr4.xs4all.nl (8.13.8/8.13.8) with ESMTP id s0KCkeNE077167; Mon, 20 Jan 2014 13:46:42 +0100 (CET) (envelope-from hverkuil@xs4all.nl) Received: from tschai.cisco.com (localhost [127.0.0.1]) by tschai.lan (Postfix) with ESMTPSA id CEDBA2A00B1; Mon, 20 Jan 2014 13:46:16 +0100 (CET) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: m.chehab@samsung.com, laurent.pinchart@ideasonboard.com, t.stanislaws@samsung.com, Hans Verkuil Subject: [RFCv2 PATCH 16/21] v4l2-ctrls: add matrix support. Date: Mon, 20 Jan 2014 13:46:09 +0100 Message-Id: <1390221974-28194-17-git-send-email-hverkuil@xs4all.nl> X-Mailer: git-send-email 1.8.5.2 In-Reply-To: <1390221974-28194-1-git-send-email-hverkuil@xs4all.nl> References: <1390221974-28194-1-git-send-email-hverkuil@xs4all.nl> X-Virus-Scanned: by XS4ALL Virus Scanner Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham 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 From: Hans Verkuil Finish the userspace-facing matrix support. Signed-off-by: Hans Verkuil --- drivers/media/v4l2-core/v4l2-ctrls.c | 106 ++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 913ea7c..0559c1b 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1164,6 +1164,8 @@ static void std_init(const struct v4l2_ctrl *ctrl, u32 idx, ptr.p_s32[idx] = ctrl->default_value; break; default: + idx *= ctrl->elem_size; + memset(ptr.p + idx, 0, ctrl->elem_size); break; } } @@ -1281,7 +1283,7 @@ static int ptr_to_user(struct v4l2_ext_control *c, u32 len; if (ctrl->is_ptr && !ctrl->is_string) - return copy_to_user(c->p, ptr.p, ctrl->elem_size); + return copy_to_user(c->p, ptr.p, c->size); switch (ctrl->type) { case V4L2_CTRL_TYPE_STRING: @@ -1325,8 +1327,17 @@ static int user_to_ptr(struct v4l2_ext_control *c, u32 size; ctrl->is_new = 1; - if (ctrl->is_ptr && !ctrl->is_string) - return copy_from_user(ptr.p, c->p, ctrl->elem_size); + if (ctrl->is_ptr && !ctrl->is_string) { + unsigned idx; + + ret = copy_from_user(ptr.p, c->p, c->size); + if (ret || !ctrl->is_matrix) + return ret; + for (idx = c->size / ctrl->elem_size; + idx < ctrl->rows * ctrl->cols; idx++) + ctrl->type_ops->init(ctrl, idx, ptr); + return 0; + } switch (ctrl->type) { case V4L2_CTRL_TYPE_INTEGER64: @@ -1369,21 +1380,7 @@ static void ptr_to_ptr(struct v4l2_ctrl *ctrl, { if (ctrl == NULL) return; - switch (ctrl->type) { - case V4L2_CTRL_TYPE_STRING: - /* strings are always 0-terminated */ - strcpy(to.p_char, from.p_char); - break; - case V4L2_CTRL_TYPE_INTEGER64: - *to.p_s64 = *from.p_s64; - break; - default: - if (ctrl->is_ptr) - memcpy(to.p, from.p, ctrl->elem_size); - else - *to.p_s32 = *from.p_s32; - break; - } + memcpy(to.p, from.p, ctrl->rows * ctrl->cols * ctrl->elem_size); } /* Copy the new value to the current value. */ @@ -1435,15 +1432,19 @@ static void cur_to_new(struct v4l2_ctrl *ctrl) static int cluster_changed(struct v4l2_ctrl *master) { bool changed = false; + unsigned idx; int i; for (i = 0; i < master->ncontrols; i++) { struct v4l2_ctrl *ctrl = master->cluster[i]; + bool ctrl_changed = false; if (ctrl == NULL) continue; - ctrl->has_changed = !ctrl->type_ops->equal(ctrl, 0, + for (idx = 0; idx < ctrl->rows * ctrl->cols; idx++) + ctrl_changed |= !ctrl->type_ops->equal(ctrl, idx, ctrl->stores[0], ctrl->new); + ctrl->has_changed = ctrl_changed; changed |= ctrl->has_changed; } return changed; @@ -1490,26 +1491,32 @@ static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) { union v4l2_ctrl_ptr ptr; - - switch (ctrl->type) { - case V4L2_CTRL_TYPE_INTEGER: - case V4L2_CTRL_TYPE_INTEGER_MENU: - case V4L2_CTRL_TYPE_MENU: - case V4L2_CTRL_TYPE_BITMASK: - case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_BUTTON: - case V4L2_CTRL_TYPE_CTRL_CLASS: - ptr.p_s32 = &c->value; - return ctrl->type_ops->validate(ctrl, 0, ptr); - - case V4L2_CTRL_TYPE_INTEGER64: - ptr.p_s64 = &c->value64; - return ctrl->type_ops->validate(ctrl, 0, ptr); - - default: - ptr.p = c->p; - return ctrl->type_ops->validate(ctrl, 0, ptr); + unsigned idx; + int err = 0; + + if (!ctrl->is_ptr) { + switch (ctrl->type) { + case V4L2_CTRL_TYPE_INTEGER: + case V4L2_CTRL_TYPE_INTEGER_MENU: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_BITMASK: + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_BUTTON: + case V4L2_CTRL_TYPE_CTRL_CLASS: + ptr.p_s32 = &c->value; + return ctrl->type_ops->validate(ctrl, 0, ptr); + + case V4L2_CTRL_TYPE_INTEGER64: + ptr.p_s64 = &c->value64; + return ctrl->type_ops->validate(ctrl, 0, ptr); + default: + break; + } } + ptr.p = c->p; + for (idx = 0; !err && idx < c->size / ctrl->elem_size; idx++) + err = ctrl->type_ops->validate(ctrl, idx, ptr); + return err; } static inline u32 node2id(struct list_head *node) @@ -1736,6 +1743,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl *ctrl; bool is_matrix; unsigned sz_extra, tot_ctrl_size; + unsigned idx; void *data; int err; int s; @@ -1845,7 +1853,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, ctrl->stores[0].p = data; } for (s = -1; s <= 0; s++) - ctrl->type_ops->init(ctrl, 0, ctrl->stores[s]); + for (idx = 0; idx < rows * cols; idx++) + ctrl->type_ops->init(ctrl, idx, ctrl->stores[s]); if (handler_new_ref(hdl, ctrl)) { kfree(ctrl); @@ -2532,12 +2541,16 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, have_clusters = true; if (ctrl->cluster[0] != ctrl) ref = find_ref_lock(hdl, ctrl->cluster[0]->id); - if (ctrl->is_ptr && !ctrl->is_string && c->size < ctrl->elem_size) { - if (get) { - c->size = ctrl->elem_size; - return -ENOSPC; + if (ctrl->is_ptr && !ctrl->is_string) { + if (c->size == 0 || c->size % ctrl->elem_size) { + if (get) { + c->size = ctrl->rows * ctrl->cols * ctrl->elem_size; + return -ENOSPC; + } + return -EFAULT; } - return -EFAULT; + if (c->size > ctrl->rows * ctrl->cols * ctrl->elem_size) + c->size = ctrl->rows * ctrl->cols * ctrl->elem_size; } /* Store the ref to the master control of the cluster */ h->mref = ref; @@ -3077,7 +3090,7 @@ EXPORT_SYMBOL(v4l2_ctrl_notify); int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, s64 min, s64 max, u64 step, s64 def) { - int ret = check_range(ctrl->type, min, max, step, def); + int ret; struct v4l2_ext_control c; switch (ctrl->type) { @@ -3087,6 +3100,9 @@ int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER_MENU: case V4L2_CTRL_TYPE_BITMASK: + if (ctrl->is_matrix) + return -EINVAL; + ret = check_range(ctrl->type, min, max, step, def); if (ret) return ret; break;