From patchwork Tue Oct 25 05:55:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018495 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA3A1C38A2D for ; Tue, 25 Oct 2022 05:55:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230526AbiJYFzr (ORCPT ); Tue, 25 Oct 2022 01:55:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43534 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229954AbiJYFzm (ORCPT ); Tue, 25 Oct 2022 01:55:42 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4AE537FA7 for ; Mon, 24 Oct 2022 22:55:40 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-36b1a68bfa6so68755317b3.22 for ; Mon, 24 Oct 2022 22:55:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Rf+QfS6eMeyUYkxYbAECemXyio0W9qEY2bjKVVvIDeQ=; b=ELfhMm7C2ZO81IwRufvZn9argc0/c67hUlx7dLQ6qw9lOKPhug6CIbciGVy2fUlYm7 4gzFqdY0KPnWRwLhD9zicSilDrZXtQP6rU356zqRkRdWC+g3Z+ppxrii8TQaFTKePr2x 9GfJG13RMjm7QjoEdp1uIXJXyAp71YVrNigIv1PasZlgMQ5cDU6YnSLg7aALkyhuD/Tp 8/nOKOjP6hhYT4fh/34soBXBg8hvC/iwkR6xOmkc1TP6teQk65H+Aory3kxZkT/+lXUf nDjtniHlQmpAV92n2miaHUKThR304/wi6RiCm7jPJR4rdjFXzFyzqPpTnpjJVH2HsZCk lN0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Rf+QfS6eMeyUYkxYbAECemXyio0W9qEY2bjKVVvIDeQ=; b=0I5sJ/JR66o+hI91F8Hiwx6Q0ng/0f7Yjp8YI46tGXv3SiYlqmAuH30UD5PKIJgCk9 kO2R2KpccHDhiKIeUQmqTDokixF0OmE01knvc/Mob7N0Pl8mDZPUnPIG7V69LeBtsS5h HnVv5GQuTZEAOez6C2Q5Uwfn82qXFoQ2lzc/ZwA+05eTzq2FClKtfHk0QR6M9maPltbN Z+jk9wND0TMTHYPcBYks/yciF0HJuywYIIcPPHbSkpJizHwohOv3bX4q5XO2a71SwCzT sNUhPzZqSWjsLHd4jR9d3DtPkGOMqBB+kcB7WKpqZAHpLt/b4fhmDwwlmO1ou/XgGDI1 Mt4Q== X-Gm-Message-State: ACrzQf1P76KBeEMWJeI5oNHiEdXzftwO08nUwwNgbBw6jW0i0Odw0WjS +5SF13zRWZ/ohEn+CAJLWmCPLmRJ8qU= X-Google-Smtp-Source: AMsMyM6wpPManJOHpah+q4uv4GzTkHaMch0Z4qqnoQF23QirLrGp7oTX+yoVYSlQQcuodNdRVe2xHxQ/uuE= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a05:6902:1148:b0:6ca:79c4:dcbc with SMTP id p8-20020a056902114800b006ca79c4dcbcmr16739081ybu.622.1666677339948; Mon, 24 Oct 2022 22:55:39 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:18 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-2-yunkec@google.com> Subject: [PATCH v9 01/11] media: v4l2_ctrl: Add V4L2_CTRL_TYPE_RECT From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add p_rect to struct v4l2_ext_control with basic support in v4l2-ctrls. Reviewed-by: Laurent Pinchart Reviewed-by: Ricardo Ribalda Signed-off-by: Yunke Cao --- Changelog since v8: - No change. Changelog since v7: - Document V4L2_CTRL_TYPE_RECT in vidioc-queryctrl.rst. - Rebased to media-stage master. - Do not assign each field in std_equal. .../media/v4l/vidioc-g-ext-ctrls.rst | 4 ++++ .../userspace-api/media/v4l/vidioc-queryctrl.rst | 7 +++++++ .../media/videodev2.h.rst.exceptions | 1 + drivers/media/v4l2-core/v4l2-ctrls-core.c | 15 +++++++++++++++ include/media/v4l2-ctrls.h | 2 ++ include/uapi/linux/videodev2.h | 2 ++ 6 files changed, 31 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index 892cfeb8b988..927ef397f1ce 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -189,6 +189,10 @@ still cause this situation. - ``p_area`` - A pointer to a struct :c:type:`v4l2_area`. Valid if this control is of type ``V4L2_CTRL_TYPE_AREA``. + * - struct :c:type:`v4l2_rect` * + - ``p_rect`` + - A pointer to a struct :c:type:`v4l2_rect`. Valid if this control is + of type ``V4L2_CTRL_TYPE_RECT``. * - struct :c:type:`v4l2_ctrl_h264_sps` * - ``p_h264_sps`` - A pointer to a struct :c:type:`v4l2_ctrl_h264_sps`. Valid if this control is diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst index a20dfa2a933b..58982cd382e3 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -441,6 +441,13 @@ See also the examples in :ref:`control`. - n/a - A struct :c:type:`v4l2_area`, containing the width and the height of a rectangular area. Units depend on the use case. + * - ``V4L2_CTRL_TYPE_RECT`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_rect`, containing a rectangle described by + the position of its top-left corner, the width and the height. Units + depend on the use case. * - ``V4L2_CTRL_TYPE_H264_SPS`` - n/a - n/a diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions index 2a589d34b80e..828cca8e2daa 100644 --- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions @@ -150,6 +150,7 @@ replace symbol V4L2_CTRL_TYPE_HEVC_SPS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_PPS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_AREA :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_RECT :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_FWHT_PARAMS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_VP8_FRAME :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR :c:type:`v4l2_ctrl_type` diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 0dab1d7b90f0..0ac36ebc45dd 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -350,6 +350,11 @@ void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl) case V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS: pr_cont("HEVC_DECODE_PARAMS"); break; + case V4L2_CTRL_TYPE_RECT: + pr_cont("%ux%u@%dx%d", + ptr.p_rect->width, ptr.p_rect->height, + ptr.p_rect->left, ptr.p_rect->top); + break; default: pr_cont("unknown type %d", ctrl->type); break; @@ -569,6 +574,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering; struct v4l2_ctrl_hevc_decode_params *p_hevc_decode_params; struct v4l2_area *area; + struct v4l2_rect *rect; void *p = ptr.p + idx * ctrl->elem_size; unsigned int i; @@ -918,6 +924,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, return -EINVAL; break; + case V4L2_CTRL_TYPE_RECT: + rect = p; + if (!rect->width || !rect->height) + return -EINVAL; + break; + default: return -EINVAL; } @@ -1605,6 +1617,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, case V4L2_CTRL_TYPE_AREA: elem_size = sizeof(struct v4l2_area); break; + case V4L2_CTRL_TYPE_RECT: + elem_size = sizeof(struct v4l2_rect); + break; default: if (type < V4L2_CTRL_COMPOUND_TYPES) elem_size = sizeof(s32); diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index e59d9a234631..1846caf9dd53 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -52,6 +52,7 @@ struct video_device; * @p_hdr10_cll: Pointer to an HDR10 Content Light Level structure. * @p_hdr10_mastering: Pointer to an HDR10 Mastering Display structure. * @p_area: Pointer to an area. + * @p_rect: Pointer to a rectangle. * @p: Pointer to a compound value. * @p_const: Pointer to a constant compound value. */ @@ -81,6 +82,7 @@ union v4l2_ctrl_ptr { struct v4l2_ctrl_hdr10_cll_info *p_hdr10_cll; struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering; struct v4l2_area *p_area; + struct v4l2_rect *p_rect; void *p; const void *p_const; }; diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 86cae23cc446..a81951c51325 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1780,6 +1780,7 @@ struct v4l2_ext_control { __u16 __user *p_u16; __u32 __user *p_u32; struct v4l2_area __user *p_area; + struct v4l2_rect __user *p_rect; struct v4l2_ctrl_h264_sps __user *p_h264_sps; struct v4l2_ctrl_h264_pps *p_h264_pps; struct v4l2_ctrl_h264_scaling_matrix __user *p_h264_scaling_matrix; @@ -1844,6 +1845,7 @@ enum v4l2_ctrl_type { V4L2_CTRL_TYPE_U16 = 0x0101, V4L2_CTRL_TYPE_U32 = 0x0102, V4L2_CTRL_TYPE_AREA = 0x0106, + V4L2_CTRL_TYPE_RECT = 0x0107, V4L2_CTRL_TYPE_HDR10_CLL_INFO = 0x0110, V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY = 0x0111, From patchwork Tue Oct 25 05:55:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018496 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC83CC04A95 for ; Tue, 25 Oct 2022 05:55:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229785AbiJYFzs (ORCPT ); Tue, 25 Oct 2022 01:55:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230525AbiJYFzr (ORCPT ); Tue, 25 Oct 2022 01:55:47 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D62CA402C3 for ; Mon, 24 Oct 2022 22:55:45 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-368e6c449f2so109025397b3.5 for ; Mon, 24 Oct 2022 22:55:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=8WUw8DbrB9vOMp1sQYuLlmg+N/S18v3TkuImlQpQcV0=; b=m79MqKB7e74+Nz2HbMqQ4e1DZ5LLXiPzE8iHEGPnP1H6qzw7BPN0Sdj0p2wMTPFuN9 zrzrsLsBo/+KfVvWAw4B0eUc4ZZgrEOLQGRKBT9IhB7Ta7qw3fqf+1zYSEa8R+qnPwC3 TxeJaqTymP995JllkE6UJ+E833Un8IbzSb7WOEfn88Z1+lKZiw1UKgZN4jirn5BTRKXC jiBHd17TvbcaYJVkHRfEw8GGUimIBVwpzOldU4U4J/CzWt1qPaoahP2naeMeF6WgvzhL 8NIwF4XYiowmiBqZxBubHQJ7OzVj386SYTHY4EIUiA23YysGDrUtXgYBvAIWzVZRueKs QlbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=8WUw8DbrB9vOMp1sQYuLlmg+N/S18v3TkuImlQpQcV0=; b=goM45PdD/OZXuyecmW9J+sy/AWTEwxth9NqQ5EXvX9o6+wD0HvqdsODzJrMcfLg0ic RCNvx9OwajgFEzoLnhlR2uscgSwV6UF5MQ0f1yHD+gn6yUaKAT0m+sd/C15XUn0gf2PN BOQg6Wie9gm1PFE490boFGLcQgDR481K8Ae5/TI+H1rpvU7JpIvtt6Y445gbWye3REmN GD934w5k2+mhuG7uaqcl8myL/glr7hPUTfZ5FdrjNxbRS++GwUdJFO+pKdirWbc0CHrw lMlo4ePNz3SypL7Bfg7os/VEkxM6ixOvvrUu7ebEBLAABBOjQlM6Gb4UUvvkSNFq1Twl 1bhw== X-Gm-Message-State: ACrzQf2IX/493eEtkWG2rH3TUevSs+kALiH/jxgv1z62tLPcMbpSG2re OiEYvxhO10BjTtkGY/bNMlmHgt9TA5I= X-Google-Smtp-Source: AMsMyM67e3O3kDGqeZgezGO6c5nTzTC/zLcRqj5A2A99Ea7nG+I941tEVaWaCW30IdJoqLsua4huvx+doAc= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a25:4fc1:0:b0:6bc:c570:f99e with SMTP id d184-20020a254fc1000000b006bcc570f99emr32209399ybb.58.1666677345164; Mon, 24 Oct 2022 22:55:45 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:19 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-3-yunkec@google.com> Subject: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Introduce uvc_ctrl_get_boundary(), making it easier to extend to support compound controls and V4L2_CTRL_WHICH_MIN/MAX_VAL in the following patches. For now, it simply returns EINVAL for compound controls and calls __query_v4l2_ctrl() for non-compound controls. Reviewed-by: Ricardo Ribalda Signed-off-by: Yunke Cao --- Changelog since v8: - No Change. Changelog since v7: - Rename uvc_ctrl_get_fixed() to uvc_ctrl_get_boundary(). - Move refactor (introduce __uvc_ctrl_get_boundary_std()) in this patch instead of in the patch where we implement compound control. - Fix locking. uvc_ctrl_get_boundary() now acquires ctrl_mutex. __uvc_ctrl_get_boundary_std() calls __uvc_query_v4l2_ctrl() while holding the mutex. - Define a uvc_ctrl_mapping_is_compound() for readability. drivers/media/usb/uvc/uvc_ctrl.c | 48 ++++++++++++++++++++++++++++++++ drivers/media/usb/uvc/uvc_v4l2.c | 6 +--- drivers/media/usb/uvc/uvcvideo.h | 2 ++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index c95a2229f4fa..6997e7466a2b 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -837,6 +837,12 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping, } } +static bool +uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping) +{ + return mapping->v4l2_type >= V4L2_CTRL_COMPOUND_TYPES; +} + /* ------------------------------------------------------------------------ * Terminal and unit management */ @@ -1743,6 +1749,48 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); } +int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain, + struct uvc_control *ctrl, + struct uvc_control_mapping *mapping, + struct v4l2_ext_control *xctrl) +{ + struct v4l2_queryctrl qc = { .id = xctrl->id }; + + int ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &qc); + + if (ret < 0) + return ret; + + xctrl->value = qc.default_value; + return 0; +} + +int uvc_ctrl_get_boundary(struct uvc_video_chain *chain, + struct v4l2_ext_control *xctrl) +{ + struct uvc_control *ctrl; + struct uvc_control_mapping *mapping; + int ret; + + if (mutex_lock_interruptible(&chain->ctrl_mutex)) + return -ERESTARTSYS; + + ctrl = uvc_find_control(chain, xctrl->id, &mapping); + if (!ctrl) { + ret = -EINVAL; + goto done; + } + + if (uvc_ctrl_mapping_is_compound(mapping)) + ret = -EINVAL; + else + ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, xctrl); + +done: + mutex_unlock(&chain->ctrl_mutex); + return ret; +} + int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl) { diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f4d4c33b6dfb..e807e348aa41 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1046,15 +1046,11 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) { for (i = 0; i < ctrls->count; ++ctrl, ++i) { - struct v4l2_queryctrl qc = { .id = ctrl->id }; - - ret = uvc_query_v4l2_ctrl(chain, &qc); + ret = uvc_ctrl_get_boundary(chain, ctrl); if (ret < 0) { ctrls->error_idx = i; return ret; } - - ctrl->value = qc.default_value; } return 0; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index df93db259312..b2ee3d59a4c8 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -759,6 +759,8 @@ static inline int uvc_ctrl_rollback(struct uvc_fh *handle) } int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl); +int uvc_ctrl_get_boundary(struct uvc_video_chain *chain, + struct v4l2_ext_control *xctrl); int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl); int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, bool read); From patchwork Tue Oct 25 05:55:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018497 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6A5DC38A2D for ; Tue, 25 Oct 2022 05:55:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230005AbiJYFz4 (ORCPT ); Tue, 25 Oct 2022 01:55:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230167AbiJYFzy (ORCPT ); Tue, 25 Oct 2022 01:55:54 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2DA0948E8C for ; Mon, 24 Oct 2022 22:55:51 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id d18-20020a170902ced200b00180680b8ed1so7606416plg.1 for ; Mon, 24 Oct 2022 22:55:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Wv6dMsttfIS/yNccLcgdn9kGfrfq9OLbuIFlF3os57Y=; b=MHjUMlZeiByYW4d4EBxdR4ODMF9cBqunFEDD0DrmzRcpJUju47LL94x57BI4YV8/ZZ lOmRtFT0o4/JBHdqeuOJ/K4gJKiZHyLHlheVT3oh4iGzGGyBTdCHoBIES9bSkiqJKjLJ bPOok7cerCXT7YShr4YLuljSNeg6vgdiIY9FP49ceZihLxokBzc9vNbMGrsk+t6ndA9Z VjPCElI70DZZb9OQBa4T6LZD7wgYZ406Fu2Fb85EBzOTTmEz0EkRML+rc1xWR0fv0AwB 7/vJSX3HRtZSNPoel+TOsdB0megB/0XUkefXFEn2M8F/pU/9nRw3yVezq0t7LNDcyIEA c6PQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Wv6dMsttfIS/yNccLcgdn9kGfrfq9OLbuIFlF3os57Y=; b=wtX5quI0uuLXym9kIeINU4u4VmWRrj5I8KoxFUwsG4+H7YcVS3Suap7DZkrQ03PPJE vaFSb35d6UYRUG/Jb/GG1ajRVYCjN/ia79dlSJe1LsQR+u1W9z6jemSK8tA9CWadBrEE CSSuNSmsZ1/T4Q1BM/HbB2RIMYaRUfmXm0kZof98GdSamwBH7ew+AFcq1Q9iqGnOcLRP CqIjkuWVGMtzlf8h/ARvGUnwLfnuunYXSnIoKc5oqw5d4V5Rf6x8XTAJr4syUO0zJYEF KfCWgRyGXMZmrlTV8/jNGm363rE+P3j545h3paSG6vIeuPIFaocLQi55BL2xmQR4F0Eu Pfmg== X-Gm-Message-State: ACrzQf3sNGxkpbhe6jfrFQLgCtdvnSviGJaA1Tglf5Iby1vBBdc3xBZG JSAHs9YdT04WINXpEQNwh+0I+73uMyw= X-Google-Smtp-Source: AMsMyM5y/21vCrgKicWIDbd7MfIBjtQZXMdB+kodl1wJK9qBCrg3Lmvs87ygTX1Dw67q8DGS/5ITYlA9YgI= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a17:90a:b794:b0:20a:eab5:cf39 with SMTP id m20-20020a17090ab79400b0020aeab5cf39mr4154572pjr.1.1666677350169; Mon, 24 Oct 2022 22:55:50 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:20 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-4-yunkec@google.com> Subject: [PATCH v9 03/11] media: uvcvideo: introduce __uvc_ctrl_get_std() From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Refactor uvc_ctrl to make adding compound control easier. Currently uvc_ctrl_get() only work for non-compound controls. Move the logic into uvc_ctrl_std(), return error for compound controls. Signed-off-by: Yunke Cao --- Changelog since v8: - No change. Changelog since v7: - Newly added patch. Split the refactoring of uvc_ctrl_get from v7 3/7. drivers/media/usb/uvc/uvc_ctrl.c | 40 +++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 6997e7466a2b..40c5d01364d9 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1028,15 +1028,15 @@ static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain, return ret; } -static int __uvc_ctrl_get(struct uvc_video_chain *chain, - struct uvc_control *ctrl, - struct uvc_control_mapping *mapping, - s32 *value) +static int __uvc_ctrl_get_std(struct uvc_video_chain *chain, + struct uvc_control *ctrl, + struct uvc_control_mapping *mapping, + s32 *value) { int ret; - if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) - return -EACCES; + if (uvc_ctrl_mapping_is_compound(mapping)) + return -EINVAL; ret = __uvc_ctrl_load_cur(chain, ctrl); if (ret < 0) @@ -1153,8 +1153,13 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, __uvc_find_control(ctrl->entity, mapping->master_id, &master_map, &master_ctrl, 0); if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) { - s32 val; - int ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val); + s32 val = 0; + int ret; + + if (uvc_ctrl_mapping_is_compound(master_map)) + return -EINVAL; + + ret = __uvc_ctrl_get_std(chain, master_ctrl, master_map, &val); if (ret < 0) return ret; @@ -1399,7 +1404,8 @@ static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain, if (ctrl == NULL) return; - if (__uvc_ctrl_get(chain, ctrl, mapping, &val) == 0) + if (uvc_ctrl_mapping_is_compound(mapping) || + __uvc_ctrl_get_std(chain, ctrl, mapping, &val) == 0) changes |= V4L2_EVENT_CTRL_CH_VALUE; uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes); @@ -1566,7 +1572,8 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; s32 val = 0; - if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) + if (uvc_ctrl_mapping_is_compound(mapping) || + __uvc_ctrl_get_std(handle->chain, ctrl, mapping, &val) == 0) changes |= V4L2_EVENT_CTRL_CH_VALUE; uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val, @@ -1746,7 +1753,10 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, if (ctrl == NULL) return -EINVAL; - return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); + if (uvc_ctrl_mapping_is_compound(mapping)) + return -EINVAL; + else + return __uvc_ctrl_get_std(chain, ctrl, mapping, &xctrl->value); } int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain, @@ -1892,8 +1902,12 @@ int uvc_ctrl_set(struct uvc_fh *handle, ctrl->info.size); } - mapping->set(mapping, value, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + if (!uvc_ctrl_mapping_is_compound(mapping)) + mapping->set(mapping, value, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + else + return -EINVAL; + if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) ctrl->handle = handle; From patchwork Tue Oct 25 05:55:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018498 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 79D4BC38A2D for ; Tue, 25 Oct 2022 05:56:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230522AbiJYF4A (ORCPT ); Tue, 25 Oct 2022 01:56:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45388 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230016AbiJYFz6 (ORCPT ); Tue, 25 Oct 2022 01:55:58 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 79B9B52084 for ; Mon, 24 Oct 2022 22:55:56 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-3691846091fso108592087b3.9 for ; Mon, 24 Oct 2022 22:55:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=HQnPv7+EaiL5Cc8HI8WCoWz3xx2ejfpWom3dlENssUA=; b=WKu5DZrOj+WhadQkndovryoHiRrA/UBe4/VKDQQJcymCVh6mwe7XPCbm2CWqe/H4ZH HonFpuqW/Caq+UZKIUWju4wFq8nzAWOuh9GY4wGsRv/oJy/IY+wnzyHDKSe1XiXD2t6y RnxOUb0rHy4QqJLrwoJzhCvCRUJiIOWopaOKecyOzA2LX7eCvtltBbnjuq6a7iiBTLeg HTkSM6riRXovooJHLShpK61Yx/Hgwi856gEr0gEnetk5LAvbS725LolYVwwIaVJnSWMj jF1uCZ/OQFrhz93/GxyzoUi8P+dOfGdGUzml46ZHbuT7/+9oiful4CmJV6MGQjdMDdXK D8hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=HQnPv7+EaiL5Cc8HI8WCoWz3xx2ejfpWom3dlENssUA=; b=vBLaC7NOw6rRECy5AjITVYWKY/Fyew2JnB8l5aLX92Mhk926jBtQgAyh3pPX5sVKIL vKFw18MW9jUkwdJnh8TozM2A2RSIo8+SaK/ruYtDx7xdHD9si4rmJ7XIsZalGCsKCKGz poeSdrftFp9XmtVT0bdAvFQRViycWHM0dtoUwdao3z7XfpKfp0PH137Apmxe3hpeaduE rqFoAYe32/C/db8rSSB1tIf2PaZaX0zLaEKEZim1r3TfQv4l3GwNOfRVhMCE1f3MxH7L C6iMrEcTrclIQu+GojQDcCMoR8smPid4SJt5e0K3ttNyWFOmpnKMu3y5JXBREahePi65 7i/w== X-Gm-Message-State: ACrzQf0E79GXVC3bdjjTvdIB+xBoAay0NCvXnUkkCxIBDgSOAqcKTQwC M9dcmxMO0q65MSKecoZ3SKp8QgK6Tw8= X-Google-Smtp-Source: AMsMyM6mU1FAzcBTEBVMHL41v/xsTpg3STrgBEw8+kii4G+U1vHxMd9QK3fHgjPiC6geZEFwQGBE7rLd34w= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a25:9d84:0:b0:6bd:2acd:61c0 with SMTP id v4-20020a259d84000000b006bd2acd61c0mr32585336ybp.556.1666677355518; Mon, 24 Oct 2022 22:55:55 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:21 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-5-yunkec@google.com> Subject: [PATCH v9 04/11] media: uvcvideo: Split uvc_control_mapping.size to v4l2 and data size From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Rename the existing size to data_size to represent uvc control data size, add a separate field for v4l2 control size. v4l2 control size will be used the compound controls. Also modify the uvc driver documents to clarify the size in uvc_xu_control_mapping corresponds to the uvc control data size. Signed-off-by: Yunke Cao --- Changelog since v8: - Newly added patch. Changelog since v7: - Newly added patch. .../userspace-api/media/drivers/uvcvideo.rst | 2 +- drivers/media/usb/uvc/uvc_ctrl.c | 78 +++++++++---------- drivers/media/usb/uvc/uvc_driver.c | 2 +- drivers/media/usb/uvc/uvc_v4l2.c | 2 +- drivers/media/usb/uvc/uvcvideo.h | 6 +- 5 files changed, 47 insertions(+), 43 deletions(-) diff --git a/Documentation/userspace-api/media/drivers/uvcvideo.rst b/Documentation/userspace-api/media/drivers/uvcvideo.rst index a290f9fadae9..aab4304e6bb5 100644 --- a/Documentation/userspace-api/media/drivers/uvcvideo.rst +++ b/Documentation/userspace-api/media/drivers/uvcvideo.rst @@ -157,7 +157,7 @@ Argument: struct uvc_xu_control_mapping __u8 name[32] V4L2 control name __u8 entity[16] UVC extension unit GUID __u8 selector UVC control selector - __u8 size V4L2 control size (in bits) + __u8 size UVC control data size (in bits) __u8 offset V4L2 control offset (in bits) enum v4l2_ctrl_type v4l2_type V4L2 control type diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 40c5d01364d9..020303e2593b 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -436,7 +436,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_BRIGHTNESS, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_BRIGHTNESS_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -445,7 +445,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_CONTRAST, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_CONTRAST_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -454,7 +454,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_HUE, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_HUE_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -465,7 +465,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_SATURATION, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_SATURATION_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -474,7 +474,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_SHARPNESS, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_SHARPNESS_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -483,7 +483,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_GAMMA, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_GAMMA_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -492,7 +492,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_BACKLIGHT_COMPENSATION, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -501,7 +501,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_GAIN, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_GAIN_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -510,7 +510,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_HUE_AUTO, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_HUE_AUTO_CONTROL, - .size = 1, + .data_size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, @@ -520,7 +520,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_EXPOSURE_AUTO, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_AE_MODE_CONTROL, - .size = 4, + .data_size = 4, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_BITMASK, @@ -532,7 +532,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_AE_PRIORITY_CONTROL, - .size = 1, + .data_size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, @@ -541,7 +541,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_EXPOSURE_ABSOLUTE, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, - .size = 32, + .data_size = 32, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -552,7 +552,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_AUTO_WHITE_BALANCE, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, - .size = 1, + .data_size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, @@ -562,7 +562,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -573,7 +573,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_AUTO_WHITE_BALANCE, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, - .size = 1, + .data_size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, @@ -584,7 +584,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_BLUE_BALANCE, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -595,7 +595,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_RED_BALANCE, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, - .size = 16, + .data_size = 16, .offset = 16, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -606,7 +606,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_FOCUS_ABSOLUTE, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -617,7 +617,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_FOCUS_AUTO, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_FOCUS_AUTO_CONTROL, - .size = 1, + .data_size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, @@ -627,7 +627,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_IRIS_ABSOLUTE, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -636,7 +636,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_IRIS_RELATIVE, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_IRIS_RELATIVE_CONTROL, - .size = 8, + .data_size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -645,7 +645,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_ZOOM_ABSOLUTE, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, @@ -654,7 +654,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_ZOOM_CONTINUOUS, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, - .size = 0, + .data_size = 0, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -665,7 +665,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_PAN_ABSOLUTE, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, - .size = 32, + .data_size = 32, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -674,7 +674,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_TILT_ABSOLUTE, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, - .size = 32, + .data_size = 32, .offset = 32, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -683,7 +683,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_PAN_SPEED, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, - .size = 16, + .data_size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -694,7 +694,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_TILT_SPEED, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, - .size = 16, + .data_size = 16, .offset = 16, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, @@ -705,7 +705,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_PRIVACY, .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PRIVACY_CONTROL, - .size = 1, + .data_size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, @@ -714,7 +714,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_PRIVACY, .entity = UVC_GUID_EXT_GPIO_CONTROLLER, .selector = UVC_CT_PRIVACY_CONTROL, - .size = 1, + .data_size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, @@ -726,7 +726,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings_uvc11[] = { .id = V4L2_CID_POWER_LINE_FREQUENCY, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, - .size = 2, + .data_size = 2, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_ENUM, @@ -740,7 +740,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings_uvc15[] = { .id = V4L2_CID_POWER_LINE_FREQUENCY, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, - .size = 2, + .data_size = 2, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_ENUM, @@ -769,7 +769,7 @@ static inline void uvc_clear_bit(u8 *data, int bit) } /* - * Extract the bit string specified by mapping->offset and mapping->size + * Extract the bit string specified by mapping->offset and mapping->data_size * from the little-endian data stored at 'data' and return the result as * a signed 32bit integer. Sign extension will be performed if the mapping * references a signed data type. @@ -777,7 +777,7 @@ static inline void uvc_clear_bit(u8 *data, int bit) static s32 uvc_get_le_value(struct uvc_control_mapping *mapping, u8 query, const u8 *data) { - int bits = mapping->size; + int bits = mapping->data_size; int offset = mapping->offset; s32 value = 0; u8 mask; @@ -800,19 +800,19 @@ static s32 uvc_get_le_value(struct uvc_control_mapping *mapping, /* Sign-extend the value if needed. */ if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) - value |= -(value & (1 << (mapping->size - 1))); + value |= -(value & (1 << (mapping->data_size - 1))); return value; } /* - * Set the bit string specified by mapping->offset and mapping->size + * Set the bit string specified by mapping->offset and mapping->data_size * in the little-endian data stored at 'data' to the value 'value'. */ static void uvc_set_le_value(struct uvc_control_mapping *mapping, s32 value, u8 *data) { - int bits = mapping->size; + int bits = mapping->data_size; int offset = mapping->offset; u8 mask; @@ -1889,7 +1889,7 @@ int uvc_ctrl_set(struct uvc_fh *handle, * needs to be loaded from the device to perform the read-modify-write * operation. */ - if ((ctrl->info.size * 8) != mapping->size) { + if ((ctrl->info.size * 8) != mapping->data_size) { ret = __uvc_ctrl_load_cur(chain, ctrl); if (ret < 0) return ret; @@ -2378,8 +2378,8 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, } /* Validate the user-provided bit-size and offset */ - if (mapping->size > 32 || - mapping->offset + mapping->size > ctrl->info.size * 8) { + if (mapping->data_size > 32 || + mapping->offset + mapping->data_size > ctrl->info.size * 8) { ret = -EINVAL; goto done; } diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 215fb483efb0..06317843c486 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2382,7 +2382,7 @@ static const struct uvc_control_mapping uvc_ctrl_power_line_mapping_limited = { .id = V4L2_CID_POWER_LINE_FREQUENCY, .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, - .size = 2, + .data_size = 2, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_ENUM, diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index e807e348aa41..36ff1d0d6edb 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -51,7 +51,7 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, } memcpy(map->entity, xmap->entity, sizeof(map->entity)); map->selector = xmap->selector; - map->size = xmap->size; + map->data_size = xmap->size; map->offset = xmap->offset; map->v4l2_type = xmap->v4l2_type; map->data_type = xmap->data_type; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index b2ee3d59a4c8..8f7938205a63 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -111,7 +111,11 @@ struct uvc_control_mapping { u8 entity[16]; u8 selector; - u8 size; + /* Size of the v4l2 control. Required for compound controls. */ + u8 v4l2_size; + /* UVC data size. Required for all controls. */ + u8 data_size; + u8 offset; enum v4l2_ctrl_type v4l2_type; u32 data_type; From patchwork Tue Oct 25 05:55:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018499 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0DB9C04A95 for ; Tue, 25 Oct 2022 05:56:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230221AbiJYF4D (ORCPT ); Tue, 25 Oct 2022 01:56:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229515AbiJYF4C (ORCPT ); Tue, 25 Oct 2022 01:56:02 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B569711A1C for ; Mon, 24 Oct 2022 22:56:00 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id px13-20020a17090b270d00b0020aa188aae8so3877731pjb.8 for ; Mon, 24 Oct 2022 22:56:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=IwHS4vIW0jJG3nZTaGFH5sDH7lB1W6QpcNxlqsnVoBQ=; b=mXHSNaYQb35k8uvJIPsOE9/SeebasfZxyusGfRG/zZA8mVY29I8CJD4hQQ5ydcntvl dga58oCokWvnx9I93scfMWs22u+0HpWxPr2RChLuK63n4kHxItKQlhK/y0sQNbCBboqm WTjkj1dan1XUnRqVhmIqf1sbrnkx1ZWcQIzNyD7ITNNTW50v04rem9DkW5D6lrgMajsT eAfW67fX72myIHVEPVgm8vB3fi2QNY2BvTBTP0gvxhUbUk7pkjeJ8wBKdymcLQ+9aHX6 uG3t5YzPpvZfUmjekP4r8gjRtundiFrEb8NmmL0psa6g05ggLQIvdoiltobS7Jn3vU0v Bm6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=IwHS4vIW0jJG3nZTaGFH5sDH7lB1W6QpcNxlqsnVoBQ=; b=imzQ5u83ynGdvaOUputbifhUacG5+PMMNOCmizWHauncahqmG7WIYqCuTZwoi+92Un FYfa4lxnHhZEJf0tYq1rxXzCOB0ER19PbAIcSC/6nJipDRAGGeoyYWJ4oiaUtXQvg1Xw kFKEaX+IO5aLQfOzgKdg8Bhp1Gr0c0MPABbB9xKpG4g9y0R5rR+/bJIZvRn3cbIOidF4 XtJ4Se7rN/ZUxqWz8j+mnYyFgeHpXYdyQnqWCtd+KEvH4ZIStRa/JnPjTPvcSJEL+DOu BTI7CFNpl1tyAO0E63zyRSEmMimrCLxaziDhzjXvdYYYaF6Qe1bd4WeWthHwXCCzJMSn x8Jw== X-Gm-Message-State: ACrzQf3nyRmjNm94ucSAJahwCNPKCHOF7QZDWuZ+boJMuIOw/9eM54vZ pOoozUd0iinIVW5Kjrj+QxLcEiqSA5g= X-Google-Smtp-Source: AMsMyM6uhgSGmafONkjoEErggpy8GaAjMIh/j62W83L40aKtK1hV+Q0FB0hITt5hI59OZxaHzkfe+JoX8Sc= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a17:90a:a415:b0:20a:f813:83a3 with SMTP id y21-20020a17090aa41500b0020af81383a3mr43210816pjp.238.1666677360340; Mon, 24 Oct 2022 22:56:00 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:22 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-6-yunkec@google.com> Subject: [PATCH v9 05/11] media: uvcvideo: Add support for compound controls From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Supports getting/setting current value. Supports getting default value. Handles V4L2_CTRL_FLAG_NEXT_COMPOUND. Signed-off-by: Yunke Cao Reviewed-by: Ricardo Ribalda --- Changelog since v8: - No change. Changelog since v7: - Fixed comments styles, indentation and a few other style issues. - Renamed uvc_g/set_array() to uvc_g/set_compound(). - Moved size check to __uvc_ctrl_add_mapping(). - After setting a new value, copy it back to user. - In __uvc_ctrl_set_compound(), check size before allocating. drivers/media/usb/uvc/uvc_ctrl.c | 184 ++++++++++++++++++++++++++++--- drivers/media/usb/uvc/uvcvideo.h | 4 + 2 files changed, 170 insertions(+), 18 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 020303e2593b..fcfaa1ee892d 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -837,6 +837,28 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping, } } +/* + * Extract the byte array specified by mapping->offset and mapping->data_size + * stored at 'data' to the output array 'data_out'. + */ +static int uvc_get_compound(struct uvc_control_mapping *mapping, const u8 *data, + u8 *data_out) +{ + memcpy(data_out, data + mapping->offset / 8, mapping->data_size / 8); + return 0; +} + +/* + * Copy the byte array 'data_in' to the destination specified by mapping->offset + * and mapping->data_size stored at 'data'. + */ +static int uvc_set_compound(struct uvc_control_mapping *mapping, + const u8 *data_in, u8 *data) +{ + memcpy(data + mapping->offset / 8, data_in, mapping->data_size / 8); + return 0; +} + static bool uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping) { @@ -859,7 +881,7 @@ static int uvc_entity_match_guid(const struct uvc_entity *entity, static void __uvc_find_control(struct uvc_entity *entity, u32 v4l2_id, struct uvc_control_mapping **mapping, struct uvc_control **control, - int next) + int next, int next_compound) { struct uvc_control *ctrl; struct uvc_control_mapping *map; @@ -874,14 +896,17 @@ static void __uvc_find_control(struct uvc_entity *entity, u32 v4l2_id, continue; list_for_each_entry(map, &ctrl->info.mappings, list) { - if ((map->id == v4l2_id) && !next) { + if (map->id == v4l2_id && !next && !next_compound) { *control = ctrl; *mapping = map; return; } if ((*mapping == NULL || (*mapping)->id > map->id) && - (map->id > v4l2_id) && next) { + (map->id > v4l2_id) && + ((!uvc_ctrl_mapping_is_compound(map) && next) || + (uvc_ctrl_mapping_is_compound(map) && + next_compound))) { *control = ctrl; *mapping = map; } @@ -895,6 +920,7 @@ static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, struct uvc_control *ctrl = NULL; struct uvc_entity *entity; int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL; + int next_compound = v4l2_id & V4L2_CTRL_FLAG_NEXT_COMPOUND; *mapping = NULL; @@ -903,12 +929,13 @@ static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, /* Find the control. */ list_for_each_entry(entity, &chain->entities, chain) { - __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); - if (ctrl && !next) + __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next, + next_compound); + if (ctrl && !next && !next_compound) return ctrl; } - if (ctrl == NULL && !next) + if (!ctrl && !next && !next_compound) uvc_dbg(chain->dev, CONTROL, "Control 0x%08x not found\n", v4l2_id); @@ -1048,10 +1075,59 @@ static int __uvc_ctrl_get_std(struct uvc_video_chain *chain, return 0; } +static int __uvc_ctrl_get_compound(struct uvc_control_mapping *mapping, + struct uvc_control *ctrl, + int id, + struct v4l2_ext_control *xctrl) +{ + u8 size; + u8 *data; + int ret; + + size = mapping->v4l2_size / 8; + if (xctrl->size < size) { + xctrl->size = size; + return -ENOSPC; + } + + data = kmalloc(size, GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = mapping->get_compound(mapping, uvc_ctrl_data(ctrl, id), data); + if (ret < 0) + goto out; + + ret = copy_to_user(xctrl->ptr, data, size) ? -EFAULT : 0; + +out: + kfree(data); + return ret; +} + +static int __uvc_ctrl_get_compound_cur(struct uvc_video_chain *chain, + struct uvc_control *ctrl, + struct uvc_control_mapping *mapping, + struct v4l2_ext_control *xctrl) +{ + int ret; + + if (!uvc_ctrl_mapping_is_compound(mapping)) + return -EINVAL; + + ret = __uvc_ctrl_load_cur(chain, ctrl); + if (ret < 0) + return ret; + + return __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_CURRENT, + xctrl); +} + static int __uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id, u32 found_id) { bool find_next = req_id & V4L2_CTRL_FLAG_NEXT_CTRL; + bool find_next_compound = req_id & V4L2_CTRL_FLAG_NEXT_COMPOUND; unsigned int i; req_id &= V4L2_CTRL_ID_MASK; @@ -1059,7 +1135,7 @@ static int __uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id, for (i = 0; i < ARRAY_SIZE(uvc_control_classes); i++) { if (!(chain->ctrl_class_bitmap & BIT(i))) continue; - if (!find_next) { + if (!find_next && !find_next_compound) { if (uvc_control_classes[i] == req_id) return i; continue; @@ -1151,7 +1227,7 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, if (mapping->master_id) __uvc_find_control(ctrl->entity, mapping->master_id, - &master_map, &master_ctrl, 0); + &master_map, &master_ctrl, 0, 0); if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) { s32 val = 0; int ret; @@ -1167,6 +1243,15 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; } + if (v4l2_ctrl->type >= V4L2_CTRL_COMPOUND_TYPES) { + v4l2_ctrl->flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD; + v4l2_ctrl->default_value = 0; + v4l2_ctrl->minimum = 0; + v4l2_ctrl->maximum = 0; + v4l2_ctrl->step = 0; + return 0; + } + if (!ctrl->cached) { int ret = uvc_ctrl_populate_cache(chain, ctrl); if (ret < 0) @@ -1400,7 +1485,7 @@ static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain, u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; s32 val = 0; - __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0); + __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0, 0); if (ctrl == NULL) return; @@ -1706,7 +1791,7 @@ static int uvc_ctrl_find_ctrl_idx(struct uvc_entity *entity, for (i = 0; i < ctrls->count; i++) { __uvc_find_control(entity, ctrls->controls[i].id, &mapping, - &ctrl_found, 0); + &ctrl_found, 0, 0); if (uvc_control == ctrl_found) return i; } @@ -1754,7 +1839,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, return -EINVAL; if (uvc_ctrl_mapping_is_compound(mapping)) - return -EINVAL; + return __uvc_ctrl_get_compound_cur(chain, ctrl, mapping, xctrl); else return __uvc_ctrl_get_std(chain, ctrl, mapping, &xctrl->value); } @@ -1775,6 +1860,25 @@ int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain, return 0; } +static int __uvc_ctrl_get_boundary_compound(struct uvc_video_chain *chain, + struct uvc_control *ctrl, + struct uvc_control_mapping *mapping, + struct v4l2_ext_control *xctrl) +{ + int ret; + + if (!uvc_ctrl_mapping_is_compound(mapping)) + return -EINVAL; + + if (!ctrl->cached) { + ret = uvc_ctrl_populate_cache(chain, ctrl); + if (ret < 0) + return ret; + } + + return __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_DEF, xctrl); +} + int uvc_ctrl_get_boundary(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl) { @@ -1792,7 +1896,8 @@ int uvc_ctrl_get_boundary(struct uvc_video_chain *chain, } if (uvc_ctrl_mapping_is_compound(mapping)) - ret = -EINVAL; + ret = __uvc_ctrl_get_boundary_compound(chain, ctrl, mapping, + xctrl); else ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, xctrl); @@ -1801,6 +1906,34 @@ int uvc_ctrl_get_boundary(struct uvc_video_chain *chain, return ret; } +int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping, + struct v4l2_ext_control *xctrl, + struct uvc_control *ctrl) +{ + u8 *data; + int ret; + + if (xctrl->size != mapping->v4l2_size / 8) + return -EINVAL; + + data = kmalloc(xctrl->size, GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = copy_from_user(data, xctrl->ptr, xctrl->size); + if (ret < 0) + goto out; + + ret = mapping->set_compound(mapping, data, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + + __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_CURRENT, xctrl); + +out: + kfree(data); + return ret; +} + int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl) { @@ -1902,12 +2035,14 @@ int uvc_ctrl_set(struct uvc_fh *handle, ctrl->info.size); } - if (!uvc_ctrl_mapping_is_compound(mapping)) + if (!uvc_ctrl_mapping_is_compound(mapping)) { mapping->set(mapping, value, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); - else - return -EINVAL; - + } else { + ret = __uvc_ctrl_set_compound(mapping, xctrl, ctrl); + if (ret < 0) + return ret; + } if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) ctrl->handle = handle; @@ -2307,10 +2442,23 @@ static int __uvc_ctrl_add_mapping(struct uvc_video_chain *chain, return -ENOMEM; } - if (map->get == NULL) + if (uvc_ctrl_mapping_is_compound(map)) { + if (map->data_size != map->v4l2_size) + return -EINVAL; + + /* Only supports byte-aligned data. */ + if (WARN_ON(map->offset % 8 || map->data_size % 8)) + return -EINVAL; + } + + if (!map->get && !uvc_ctrl_mapping_is_compound(map)) map->get = uvc_get_le_value; - if (map->set == NULL) + if (!map->set && !uvc_ctrl_mapping_is_compound(map)) map->set = uvc_set_le_value; + if (!map->get_compound && uvc_ctrl_mapping_is_compound(map)) + map->get_compound = uvc_get_compound; + if (!map->set_compound && uvc_ctrl_mapping_is_compound(map)) + map->set_compound = uvc_set_compound; for (i = 0; i < ARRAY_SIZE(uvc_control_classes); i++) { if (V4L2_CTRL_ID2WHICH(uvc_control_classes[i]) == diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 8f7938205a63..1e1bccd3b2e5 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -129,8 +129,12 @@ struct uvc_control_mapping { s32 (*get)(struct uvc_control_mapping *mapping, u8 query, const u8 *data); + int (*get_compound)(struct uvc_control_mapping *mapping, const u8 *data, + u8 *data_out); void (*set)(struct uvc_control_mapping *mapping, s32 value, u8 *data); + int (*set_compound)(struct uvc_control_mapping *mapping, const u8 *data_in, + u8 *data); }; struct uvc_control { From patchwork Tue Oct 25 05:55:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018500 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64D78C04A95 for ; Tue, 25 Oct 2022 05:56:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230259AbiJYF4J (ORCPT ); Tue, 25 Oct 2022 01:56:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46514 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231126AbiJYF4I (ORCPT ); Tue, 25 Oct 2022 01:56:08 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4373B80F7A for ; Mon, 24 Oct 2022 22:56:06 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-360b9418f64so108984747b3.7 for ; Mon, 24 Oct 2022 22:56:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=vlVpKJO/rOMEpPSm22d//I4S0R7nHZReqxbrGEZ11/g=; b=p3RqWzj1q+3NCLdM8738wA1H680vETkambS/kHU0Sa1iCFkAD1+TaY0Y7F3GWkS27M fk9RI2AZIwGE8U2rlCehPGopnbS2Kte/y6NfpTkuT7Uv717A6xO7bZdHxor9xpym5gZJ uOi+bqvlqB9/gWRH1v4/eAyu9y8rDyyJFp0SE+d0vnJvGknO223wVoVCNxlXSCRMD76N wSxReL4z6ekKe6BlYKcWK7htP3FLHtYmSXxqM5h+CsdRLt212VdDLzFWKTeRdSez1TCi 6N9ZNv5K40Ng2ETMqnRu2EPeB9TDCCF+1ewW3hiwkd+8F+5lLDFk06JhdBKO+oqNF5/I sN8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=vlVpKJO/rOMEpPSm22d//I4S0R7nHZReqxbrGEZ11/g=; b=nE4Qb3mhONIeycQWiPvX9cHSQNb+0lTf7TLVJKf7w/IOZ93Kk3NnfQTIv/tgceqOOB /eAXInAWYz+l35h6USbIJs6oUFWxD3Jv6M1XPpKU07lHTEpy9I6GtoBgEGE7HUjBPlhy h+kPCVPmiO19tR9GFcyZKV1lD1Z+shCDT/dQwPEgrPL4oINCjDuDhpqSw+Yn4UQoKTsi ANpS8jNmvkfXlPc7p/HptkjsGXTUvcwCfhopTyJQfnyP90eHdm6JmjjSxrDDHzldOwzB zR9AjdNuQjPseUbxxG0W5P20k7RWKgjrenCqwS9C7rhu2aRM+IFJlzJOMISjOVkZfqAB u0Aw== X-Gm-Message-State: ACrzQf33y9cMfTLuqLt1vdF9WXc8OaQETCrvXtID/HOYMCqAtob1SCpb drHXcUHgmLQyeyKEkZ/gKrIQ78c7K0w= X-Google-Smtp-Source: AMsMyM62aWm3+HNvr99EzbZsF4qUASGdd4UNU4TKsTOLs51lMyok0wBqJZDuEtEndYm9RVskbavICize3Tg= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a25:ac64:0:b0:6bc:d2c9:7a10 with SMTP id r36-20020a25ac64000000b006bcd2c97a10mr0ybd.585.1666677364644; Mon, 24 Oct 2022 22:56:04 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:23 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-7-yunkec@google.com> Subject: [PATCH v9 06/11] media: uvcvideo: implement UVC v1.5 ROI From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Implement support for ROI as described in UVC 1.5: 4.2.2.1.20 Digital Region of Interest (ROI) Control ROI control is implemented using V4L2 control API as two UVC-specific controls: V4L2_CID_UVC_REGION_OF_INTEREST_RECT and V4L2_CID_UVC_REGION_OF_INTEREST_AUTO. Signed-off-by: Yunke Cao Reviewed-by: Ricardo Ribalda --- Changelog since v8: - No change. Changelog since v7: - Fix a few style issues. - Only allow 4-byte aligned data. - Add control names. - Move initialization to 7/10. Question: - Is V4L2_CID_CAMERA_UVC_BASE defined correctly? Should we use V4L2_CID_PRIVATE_BASE? drivers/media/usb/uvc/uvc_ctrl.c | 111 +++++++++++++++++++++++++++-- drivers/media/usb/uvc/uvc_v4l2.c | 5 +- drivers/media/usb/uvc/uvcvideo.h | 7 ++ include/uapi/linux/usb/video.h | 1 + include/uapi/linux/uvcvideo.h | 13 ++++ include/uapi/linux/v4l2-controls.h | 9 +++ 6 files changed, 140 insertions(+), 6 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index fcfaa1ee892d..3616505e22b4 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -356,6 +356,24 @@ static const struct uvc_control_info uvc_ctrls[] = { .flags = UVC_CTRL_FLAG_GET_CUR | UVC_CTRL_FLAG_AUTO_UPDATE, }, + /* + * UVC_CTRL_FLAG_AUTO_UPDATE is needed because the RoI may get updated + * by sensors. + * "This RoI should be the same as specified in most recent SET_CUR + * except in the case where the ‘Auto Detect and Track’ and/or + * ‘Image Stabilization’ bit have been set." + * 4.2.2.1.20 Digital Region of Interest (ROI) Control + */ + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = UVC_CT_REGION_OF_INTEREST_CONTROL, + .index = 21, + .size = 10, + .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR + | UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_AUTO_UPDATE, + }, }; static const u32 uvc_control_classes[] = { @@ -431,6 +449,57 @@ static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping, data[first+1] = min_t(int, abs(value), 0xff); } +static int uvc_to_v4l2_rect(struct v4l2_rect *v4l2_rect, + const struct uvc_rect *uvc_rect) +{ + if (uvc_rect->top < uvc_rect->bottom || + uvc_rect->right < uvc_rect->left) + return -EINVAL; + + v4l2_rect->top = uvc_rect->top; + v4l2_rect->left = uvc_rect->left; + v4l2_rect->height = uvc_rect->bottom - uvc_rect->top + 1; + v4l2_rect->width = uvc_rect->right - uvc_rect->left + 1; + return 0; +} + +static int v4l2_to_uvc_rect(struct uvc_rect *uvc_rect, + const struct v4l2_rect *v4l2_rect) +{ + /* Safely converts s32 and u32 to u16. */ + if (v4l2_rect->top > U16_MAX || v4l2_rect->top < 0 || + v4l2_rect->left > U16_MAX || v4l2_rect->left < 0 || + v4l2_rect->height > U16_MAX || v4l2_rect->height == 0 || + v4l2_rect->width > U16_MAX || v4l2_rect->width == 0 || + v4l2_rect->height + v4l2_rect->top - 1 > U16_MAX || + v4l2_rect->width + v4l2_rect->left - 1 > U16_MAX) + return -ERANGE; + + uvc_rect->top = v4l2_rect->top; + uvc_rect->left = v4l2_rect->left; + uvc_rect->bottom = v4l2_rect->height + v4l2_rect->top - 1; + uvc_rect->right = v4l2_rect->width + v4l2_rect->left - 1; + return 0; +} + +static int uvc_get_compound_rect(struct uvc_control_mapping *mapping, + const u8 *data, u8 *data_out) +{ + struct uvc_rect *uvc_rect; + + uvc_rect = (struct uvc_rect *)(data + mapping->offset / 8); + return uvc_to_v4l2_rect((struct v4l2_rect *)data_out, uvc_rect); +} + +static int uvc_set_compound_rect(struct uvc_control_mapping *mapping, + const u8 *data_in, u8 *data) +{ + struct uvc_rect *uvc_rect; + + uvc_rect = (struct uvc_rect *)(data + mapping->offset / 8); + return v4l2_to_uvc_rect(uvc_rect, (struct v4l2_rect *)data_in); +} + static const struct uvc_control_mapping uvc_ctrl_mappings[] = { { .id = V4L2_CID_BRIGHTNESS, @@ -719,6 +788,29 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, + { + .id = V4L2_CID_UVC_REGION_OF_INTEREST_RECT, + .entity = UVC_GUID_UVC_CAMERA, + .selector = UVC_CT_REGION_OF_INTEREST_CONTROL, + .v4l2_size = sizeof(struct v4l2_rect) * 8, + .data_size = sizeof(struct uvc_rect) * 8, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_RECT, + .data_type = UVC_CTRL_DATA_TYPE_RECT, + .get_compound = uvc_get_compound_rect, + .set_compound = uvc_set_compound_rect, + .name = "Region Of Interest Rectangle", + }, + { + .id = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO, + .entity = UVC_GUID_UVC_CAMERA, + .selector = UVC_CT_REGION_OF_INTEREST_CONTROL, + .data_size = 16, + .offset = 64, + .v4l2_type = V4L2_CTRL_TYPE_BITMASK, + .data_type = UVC_CTRL_DATA_TYPE_BITMASK, + .name = "Region Of Interest Auto Controls", + }, }; static const struct uvc_control_mapping uvc_ctrl_mappings_uvc11[] = { @@ -2443,12 +2535,21 @@ static int __uvc_ctrl_add_mapping(struct uvc_video_chain *chain, } if (uvc_ctrl_mapping_is_compound(map)) { - if (map->data_size != map->v4l2_size) - return -EINVAL; + switch (map->v4l2_type) { + case V4L2_CTRL_TYPE_RECT: + /* Only supports 4 bytes-aligned data. */ + if (WARN_ON(map->offset % 32)) + return -EINVAL; + break; + default: + if (WARN_ON(map->data_size != map->v4l2_size)) + return -EINVAL; + + /* Only supports byte-aligned data. */ + if (WARN_ON(map->offset % 8 || map->data_size % 8)) + return -EINVAL; + } - /* Only supports byte-aligned data. */ - if (WARN_ON(map->offset % 8 || map->data_size % 8)) - return -EINVAL; } if (!map->get && !uvc_ctrl_mapping_is_compound(map)) diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 36ff1d0d6edb..52a7dc9ad4b9 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1002,7 +1002,10 @@ static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh, qec->step = qc.step; qec->default_value = qc.default_value; qec->flags = qc.flags; - qec->elem_size = 4; + if (qc.type == V4L2_CTRL_TYPE_RECT) + qec->elem_size = sizeof(struct v4l2_rect); + else + qec->elem_size = 4; qec->elems = 1; qec->nr_of_dims = 0; memset(qec->dims, 0, sizeof(qec->dims)); diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 1e1bccd3b2e5..c47304a63a7d 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -291,6 +291,13 @@ struct uvc_streaming_header { u8 bTriggerUsage; }; +struct uvc_rect { + u16 top; + u16 left; + u16 bottom; + u16 right; +} __packed; + enum uvc_buffer_state { UVC_BUF_STATE_IDLE = 0, UVC_BUF_STATE_QUEUED = 1, diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h index bfdae12cdacf..9076a444758a 100644 --- a/include/uapi/linux/usb/video.h +++ b/include/uapi/linux/usb/video.h @@ -104,6 +104,7 @@ #define UVC_CT_ROLL_ABSOLUTE_CONTROL 0x0f #define UVC_CT_ROLL_RELATIVE_CONTROL 0x10 #define UVC_CT_PRIVACY_CONTROL 0x11 +#define UVC_CT_REGION_OF_INTEREST_CONTROL 0x14 /* A.9.5. Processing Unit Control Selectors */ #define UVC_PU_CONTROL_UNDEFINED 0x00 diff --git a/include/uapi/linux/uvcvideo.h b/include/uapi/linux/uvcvideo.h index 8288137387c0..ae5eaa14eca2 100644 --- a/include/uapi/linux/uvcvideo.h +++ b/include/uapi/linux/uvcvideo.h @@ -16,6 +16,7 @@ #define UVC_CTRL_DATA_TYPE_BOOLEAN 3 #define UVC_CTRL_DATA_TYPE_ENUM 4 #define UVC_CTRL_DATA_TYPE_BITMASK 5 +#define UVC_CTRL_DATA_TYPE_RECT 6 /* Control flags */ #define UVC_CTRL_FLAG_SET_CUR (1 << 0) @@ -36,6 +37,18 @@ UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES | \ UVC_CTRL_FLAG_GET_DEF) +/* V4L2 driver-specific controls */ +#define V4L2_CID_UVC_REGION_OF_INTEREST_RECT (V4L2_CID_CAMERA_UVC_BASE + 1) +#define V4L2_CID_UVC_REGION_OF_INTEREST_AUTO (V4L2_CID_CAMERA_UVC_BASE + 2) +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_EXPOSURE (1 << 0) +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IRIS (1 << 1) +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_WHITE_BALANCE (1 << 2) +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FOCUS (1 << 3) +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FACE_DETECT (1 << 4) +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK (1 << 5) +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION (1 << 6) +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY (1 << 7) + struct uvc_menu_info { __u32 value; __u8 name[32]; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index b5e7d082b8ad..b3544355be8f 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1019,6 +1019,15 @@ enum v4l2_auto_focus_range { #define V4L2_CID_CAMERA_SENSOR_ROTATION (V4L2_CID_CAMERA_CLASS_BASE+35) +/* CAMERA-class private control IDs */ + +/* + * The base for the uvc driver controls. + * See linux/uvcvideo.h for the list of controls. + * We reserve 64 controls for this driver. + */ +#define V4L2_CID_CAMERA_UVC_BASE (V4L2_CID_CAMERA_CLASS_BASE + 0x1000) + /* FM Modulator class control IDs */ #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) From patchwork Tue Oct 25 05:55:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018502 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BB373FA373E for ; Tue, 25 Oct 2022 05:56:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230525AbiJYF4Z (ORCPT ); Tue, 25 Oct 2022 01:56:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229907AbiJYF4W (ORCPT ); Tue, 25 Oct 2022 01:56:22 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4291B564D0 for ; Mon, 24 Oct 2022 22:56:21 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id t7-20020a62ea07000000b005619a832f68so5782657pfh.11 for ; Mon, 24 Oct 2022 22:56:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=hvNy0lvg9ksF4dKtaZTXhH5QcDP3otwgJcxIB2tsJZg=; b=IatvIP7sZ3JJCMjJu5rtSMq/rw760Gk4UsES4xp3DX9ucsh987lcue4KqvOqNyVNK2 hlHXXi1kYst3Qd7C60KrpleIAwcULR/NtFCFwXEJfDt3xlYjtdgw2LhrYGM53eFdQIpc 5bvpbF4j40yYojIL2n1YzR604AOSSxDasTi9lF9YwJ8gEZ12rp5Z/St7NalCBG1WLlFq hfchhKn2JZlNqL2t3DEa0/mNURA8kEmT9WsmUjtQcRgQSZrYNQB7azs0HhMuvtqjw2hm uw+C+H25EjsXlYlu4mszMBeKxE/vrqFUSuCJcNjCftvzZrqnGmrKDJPJDD9gaVB04yNV ouhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hvNy0lvg9ksF4dKtaZTXhH5QcDP3otwgJcxIB2tsJZg=; b=sqysPdMzb553ADOBLsDyiHiBfb5JdTgT1BbyO4Bpxri60A/rrcbecHH0YuEHZWewgO 36f7KppQ4VuUt/Tog6Y4ViUy9uFMA95zXlTw4+zd6zaz6NMIwtUbTibRnG64F+6PAQHt lPRUv4vzmZ4FI/9zskJ1lA0LMFBuaZS6A60/YjnZssZzI10XnhHB+H7pjT/mopNHh+jk lTpZu/hIfUcBGLgU/t7gwO66dPcffczosJ8ZHVzEEChV8z735QA+kDwI08vaB0sqZPzF w+YntlTJWlBEfAIzAZawhH79XaA6Y9G04Wr23R/uqjHka1/Ep2fUGjay9o8oCpVy40h+ Wjsg== X-Gm-Message-State: ACrzQf19tslKP88WxSz/ymWjdVlkgNgHdgNZyjXKroECAG0bI0t0q4IQ UEgjHNl9qfeZCseoWsft4YBdx5oHGe8= X-Google-Smtp-Source: AMsMyM4v1JdrxbN0rQZduYLe5qPWYa/NE9oo8Mb3mhQkP/wu/hgmctKnPTnh7jzicGYDg3fB8fCfzESBFv8= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a05:6a00:ac6:b0:530:3197:48b6 with SMTP id c6-20020a056a000ac600b00530319748b6mr36733534pfl.80.1666677370286; Mon, 24 Oct 2022 22:56:10 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:24 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-8-yunkec@google.com> Subject: [PATCH v9 07/11] media: uvcvideo: initilaize ROI control to default value From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add an init function to uvc_control_info. Use the function to initialize ROI control to default value. Also moves utility functions to the top of uvc_ctrl.c, above the uvc_ctrls definition. uvc_ctrl_init_roi() calls uvc_ctrl_data() and need to be declared before uvc_ctrls. Signed-off-by: Yunke Cao --- Changelog since v8: - No change. Changelog since v7: - Newly added patch. Split initializing from the previous patch. - Add an init operation to uvc_control_info and use it for ROI initialization. drivers/media/usb/uvc/uvc_ctrl.c | 272 ++++++++++++++++++------------- drivers/media/usb/uvc/uvcvideo.h | 3 + 2 files changed, 159 insertions(+), 116 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 3616505e22b4..33199de7f1be 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -30,6 +30,157 @@ #define UVC_CTRL_DATA_DEF 5 #define UVC_CTRL_DATA_LAST 6 +/* ------------------------------------------------------------------------ + * Utility functions + */ + +static inline u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) +{ + return ctrl->uvc_data + id * ctrl->info.size; +} + +static inline int uvc_test_bit(const u8 *data, int bit) +{ + return (data[bit >> 3] >> (bit & 7)) & 1; +} + +static inline void uvc_clear_bit(u8 *data, int bit) +{ + data[bit >> 3] &= ~(1 << (bit & 7)); +} + +/* + * Extract the bit string specified by mapping->offset and mapping->data_size + * from the little-endian data stored at 'data' and return the result as + * a signed 32bit integer. Sign extension will be performed if the mapping + * references a signed data type. + */ +static s32 uvc_get_le_value(struct uvc_control_mapping *mapping, + u8 query, const u8 *data) +{ + int bits = mapping->data_size; + int offset = mapping->offset; + s32 value = 0; + u8 mask; + + data += offset / 8; + offset &= 7; + mask = ((1LL << bits) - 1) << offset; + + while (1) { + u8 byte = *data & mask; + + value |= offset > 0 ? (byte >> offset) : (byte << (-offset)); + bits -= 8 - (offset > 0 ? offset : 0); + if (bits <= 0) + break; + + offset -= 8; + mask = (1 << bits) - 1; + data++; + } + + /* Sign-extend the value if needed. */ + if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) + value |= -(value & (1 << (mapping->data_size - 1))); + + return value; +} + +/* + * Set the bit string specified by mapping->offset and mapping->data_size + * in the little-endian data stored at 'data' to the value 'value'. + */ +static void uvc_set_le_value(struct uvc_control_mapping *mapping, + s32 value, u8 *data) +{ + int bits = mapping->data_size; + int offset = mapping->offset; + u8 mask; + + /* + * According to the v4l2 spec, writing any value to a button control + * should result in the action belonging to the button control being + * triggered. UVC devices however want to see a 1 written -> override + * value. + */ + if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON) + value = -1; + + data += offset / 8; + offset &= 7; + + for (; bits > 0; data++) { + mask = ((1LL << bits) - 1) << offset; + *data = (*data & ~mask) | ((value << offset) & mask); + value >>= offset ? offset : 8; + bits -= 8 - offset; + offset = 0; + } +} + +/* + * Extract the byte array specified by mapping->offset and mapping->data_size + * stored at 'data' to the output array 'data_out'. + */ +static int uvc_get_compound(struct uvc_control_mapping *mapping, const u8 *data, + u8 *data_out) +{ + memcpy(data_out, data + mapping->offset / 8, mapping->data_size / 8); + return 0; +} + +/* + * Copy the byte array 'data_in' to the destination specified by mapping->offset + * and mapping->data_size stored at 'data'. + */ +static int uvc_set_compound(struct uvc_control_mapping *mapping, + const u8 *data_in, u8 *data) +{ + memcpy(data + mapping->offset / 8, data_in, mapping->data_size / 8); + return 0; +} + +static bool +uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping) +{ + return mapping->v4l2_type >= V4L2_CTRL_COMPOUND_TYPES; +} + +static int uvc_ctrl_init_roi(struct uvc_device *dev, struct uvc_control *ctrl) +{ + int ret; + + ret = uvc_query_ctrl(dev, UVC_GET_DEF, ctrl->entity->id, dev->intfnum, + UVC_CT_REGION_OF_INTEREST_CONTROL, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF), + ctrl->info.size); + if (ret) + goto out; + + /* + * Most firmwares have wrong GET_CUR configuration. E.g. it's + * below GET_MIN, or have rectangle coordinates mixed up. This + * causes problems sometimes, because we are unable to set + * auto-controls value without first setting ROI rectangle to + * valid configuration. + * + * We expect that default configuration is always correct and + * is within the GET_MIN / GET_MAX boundaries. + * + * Set current ROI configuration to GET_DEF, so that we will + * always have properly configured ROI. + */ + ret = uvc_query_ctrl(dev, UVC_SET_CUR, 1, dev->intfnum, + UVC_CT_REGION_OF_INTEREST_CONTROL, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF), + ctrl->info.size); +out: + if (ret) + dev_err(&dev->udev->dev, "Failed to fixup ROI (%d).\n", ret); + return ret; +} + /* ------------------------------------------------------------------------ * Controls */ @@ -373,6 +524,7 @@ static const struct uvc_control_info uvc_ctrls[] = { | UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_AUTO_UPDATE, + .init = uvc_ctrl_init_roi, }, }; @@ -841,122 +993,6 @@ static const struct uvc_control_mapping uvc_ctrl_mappings_uvc15[] = { }, }; -/* ------------------------------------------------------------------------ - * Utility functions - */ - -static inline u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) -{ - return ctrl->uvc_data + id * ctrl->info.size; -} - -static inline int uvc_test_bit(const u8 *data, int bit) -{ - return (data[bit >> 3] >> (bit & 7)) & 1; -} - -static inline void uvc_clear_bit(u8 *data, int bit) -{ - data[bit >> 3] &= ~(1 << (bit & 7)); -} - -/* - * Extract the bit string specified by mapping->offset and mapping->data_size - * from the little-endian data stored at 'data' and return the result as - * a signed 32bit integer. Sign extension will be performed if the mapping - * references a signed data type. - */ -static s32 uvc_get_le_value(struct uvc_control_mapping *mapping, - u8 query, const u8 *data) -{ - int bits = mapping->data_size; - int offset = mapping->offset; - s32 value = 0; - u8 mask; - - data += offset / 8; - offset &= 7; - mask = ((1LL << bits) - 1) << offset; - - while (1) { - u8 byte = *data & mask; - value |= offset > 0 ? (byte >> offset) : (byte << (-offset)); - bits -= 8 - (offset > 0 ? offset : 0); - if (bits <= 0) - break; - - offset -= 8; - mask = (1 << bits) - 1; - data++; - } - - /* Sign-extend the value if needed. */ - if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) - value |= -(value & (1 << (mapping->data_size - 1))); - - return value; -} - -/* - * Set the bit string specified by mapping->offset and mapping->data_size - * in the little-endian data stored at 'data' to the value 'value'. - */ -static void uvc_set_le_value(struct uvc_control_mapping *mapping, - s32 value, u8 *data) -{ - int bits = mapping->data_size; - int offset = mapping->offset; - u8 mask; - - /* - * According to the v4l2 spec, writing any value to a button control - * should result in the action belonging to the button control being - * triggered. UVC devices however want to see a 1 written -> override - * value. - */ - if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON) - value = -1; - - data += offset / 8; - offset &= 7; - - for (; bits > 0; data++) { - mask = ((1LL << bits) - 1) << offset; - *data = (*data & ~mask) | ((value << offset) & mask); - value >>= offset ? offset : 8; - bits -= 8 - offset; - offset = 0; - } -} - -/* - * Extract the byte array specified by mapping->offset and mapping->data_size - * stored at 'data' to the output array 'data_out'. - */ -static int uvc_get_compound(struct uvc_control_mapping *mapping, const u8 *data, - u8 *data_out) -{ - memcpy(data_out, data + mapping->offset / 8, mapping->data_size / 8); - return 0; -} - -/* - * Copy the byte array 'data_in' to the destination specified by mapping->offset - * and mapping->data_size stored at 'data'. - */ -static int uvc_set_compound(struct uvc_control_mapping *mapping, - const u8 *data_in, u8 *data) -{ - memcpy(data + mapping->offset / 8, data_in, mapping->data_size / 8); - return 0; -} - -static bool -uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping) -{ - return mapping->v4l2_type >= V4L2_CTRL_COMPOUND_TYPES; -} - /* ------------------------------------------------------------------------ * Terminal and unit management */ @@ -2758,6 +2794,10 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, * GET_INFO on standard controls. */ uvc_ctrl_get_flags(chain->dev, ctrl, &ctrl->info); + + if (info->init) + info->init(chain->dev, ctrl); + break; } } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index c47304a63a7d..c7d20333ca8a 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -86,6 +86,7 @@ struct gpio_desc; struct sg_table; struct uvc_device; +struct uvc_control; /* * TODO: Put the most frequently accessed fields at the beginning of @@ -100,6 +101,8 @@ struct uvc_control_info { u16 size; u32 flags; + + int (*init)(struct uvc_device *dev, struct uvc_control *ctrl); }; struct uvc_control_mapping { From patchwork Tue Oct 25 05:55:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018501 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A63CFC38A2D for ; Tue, 25 Oct 2022 05:56:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229970AbiJYF4Y (ORCPT ); Tue, 25 Oct 2022 01:56:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47792 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231126AbiJYF4V (ORCPT ); Tue, 25 Oct 2022 01:56:21 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 943C86B15E for ; Mon, 24 Oct 2022 22:56:17 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id y126-20020a257d84000000b006c554365f5aso10970594ybc.9 for ; Mon, 24 Oct 2022 22:56:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=gEuOFUOoAzEDPRV8Iy1cV/PuXKk6trw5qxXz0h2mEnE=; b=hiaMuSShX/fLgWV5+h9gdGMifNV+URdyEuTAYGUv85TuLr17EWTdvgij/J6IChkg0s qGrFDnGg562U7XkYyX/GGmIaNGLzD5QYHB2mxXjNmmRynhG2ZU+OUnSyXdYyBihM4FBn UAtXDCcH33LKKt42ALhzQCd0WSHbZi3z6MAPlC+cdqhxJcx4HDYnUOQVYIpZfdlyaA2p ZegTdup5TsvzFG2t/Y4kfTB+6y5K1mhHZz+rMLM0DCxUPh8BYsFJfUP7dQkAThNoBN83 fUm3u9EiBu1Br6lzpNiJtFfGDse8LZM7rMdZ9mtrqxwXozKVxDcEvaIYs1yEX+hnip2J xs/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=gEuOFUOoAzEDPRV8Iy1cV/PuXKk6trw5qxXz0h2mEnE=; b=juSFRey30rbocctWoNjVYFlGhXkGFodt8KeuemZy1gjhjfeVloxEzhYrPa+CTi77cl QAsuhy7UiEEiG/NF8KnWykQ+KdCRBVydHFd0AS0r1dtV69ACOtQV+FZ0sxxYRtmtCEdL 3KuDJes1OXRIunI2vj3AhuZHQxFKIXA01+C1sUgcuoF1eUw9CzoLLYI1kqEgA0xRdxL/ 1ywhyU5W67ovEHTN//Op61HRZZLd4swndsWJXPto3IlmRmctsaAbNnSCDpThQ3z7X9XX VQyj8rM0tEcUH5/0l4BnJSqE5tjaYYyIx5I8UNORD9boRwqcBLQBfgbVKlaWJxPMv/9l odOw== X-Gm-Message-State: ACrzQf2OfbtiJHQkrQa75yT4jROKBtLw62hXdoltcAIhDLS7+WBid8bd sYc2mkCJT/aAl1ww0PKZtP4Oh7LYy/w= X-Google-Smtp-Source: AMsMyM4uI8JEgRWh7LalosTMiALlezZXQr5uhCV0AOVWoPYteK2gc+UK8imM+r6LS8Hbrm+TGOqOuJFxZUY= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a25:d253:0:b0:6ca:4ee7:e831 with SMTP id j80-20020a25d253000000b006ca4ee7e831mr0ybg.301.1666677375424; Mon, 24 Oct 2022 22:56:15 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:25 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-9-yunkec@google.com> Subject: [PATCH v9 08/11] v4l2-ctrls: add support for V4L2_CTRL_WHICH_MIN/MAX_VAL From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil Add the capability of retrieving the min and max values of a compound control. Signed-off-by: Hans Verkuil Signed-off-by: Yunke Cao --- Changelog since v8: - Return ENODATA when min/max is not implemented. Document this behavior. - Created a shared helper function __v4l2_ctrl_type_op_init that takes "which" as a parameter. Call it in def, min and max operations. Changelog since v7: - Document that the definition of the min/max are provided by compound controls are defined in control documentation. - Return error, instead of zeroed memory for v4l2_ctrl_ptr_create(NULL). git am from https://lore.kernel.org/all/20191119113457.57833-3-hverkuil-cisco@xs4all.nl/ - Fixed some merge conflits. - Fixed the build error in drivers/media/platform/qcom/venus. .../media/v4l/vidioc-g-ext-ctrls.rst | 11 +- .../media/videodev2.h.rst.exceptions | 2 + drivers/media/i2c/imx214.c | 5 +- .../media/platform/qcom/venus/venc_ctrls.c | 9 +- drivers/media/v4l2-core/v4l2-ctrls-api.c | 57 +++++-- drivers/media/v4l2-core/v4l2-ctrls-core.c | 156 +++++++++++++++--- drivers/media/v4l2-core/v4l2-ioctl.c | 4 +- include/media/v4l2-ctrls.h | 34 +++- include/uapi/linux/videodev2.h | 2 + 9 files changed, 236 insertions(+), 44 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index 927ef397f1ce..1cc21ee229aa 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -304,14 +304,21 @@ still cause this situation. - Which value of the control to get/set/try. * - :cspan:`2` ``V4L2_CTRL_WHICH_CUR_VAL`` will return the current value of the control, ``V4L2_CTRL_WHICH_DEF_VAL`` will return the default + value of the control, ``V4L2_CTRL_WHICH_MIN_VAL`` will return the minimum + value of the control, ``V4L2_CTRL_WHICH_MAX_VAL`` will return the maximum value of the control and ``V4L2_CTRL_WHICH_REQUEST_VAL`` indicates that these controls have to be retrieved from a request or tried/set for a request. In the latter case the ``request_fd`` field contains the file descriptor of the request that should be used. If the device does not support requests, then ``EACCES`` will be returned. - When using ``V4L2_CTRL_WHICH_DEF_VAL`` be aware that you can only - get the default value of the control, you cannot set or try it. + When using ``V4L2_CTRL_WHICH_DEF_VAL``, ``V4L2_CTRL_WHICH_MIN_VAL`` + or ``V4L2_CTRL_WHICH_MAX_VAL`` be aware that you can only get the + default/minimum/maximum value of the control, you cannot set or try it. + The definition of minimum/maximum values for compound types are provided by + the control documentation. If the control documentation does not + document the meaning of minimum/maximum value, then it is not supported. + Querying its minmimum/maximum value will result in -ENODATA. For backwards compatibility you can also use a control class here (see :ref:`ctrl-class`). In that case all controls have to diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions index 828cca8e2daa..6295b0fa5716 100644 --- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions @@ -563,6 +563,8 @@ ignore define V4L2_CTRL_DRIVER_PRIV ignore define V4L2_CTRL_MAX_DIMS ignore define V4L2_CTRL_WHICH_CUR_VAL ignore define V4L2_CTRL_WHICH_DEF_VAL +ignore define V4L2_CTRL_WHICH_MIN_VAL +ignore define V4L2_CTRL_WHICH_MAX_VAL ignore define V4L2_CTRL_WHICH_REQUEST_VAL ignore define V4L2_OUT_CAP_CUSTOM_TIMINGS ignore define V4L2_CID_MAX_CTRLS diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 710c9fb515fd..bd11bd8105aa 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -1037,7 +1037,10 @@ static int imx214_probe(struct i2c_client *client) imx214->unit_size = v4l2_ctrl_new_std_compound(&imx214->ctrls, NULL, V4L2_CID_UNIT_CELL_SIZE, - v4l2_ctrl_ptr_create((void *)&unit_size)); + v4l2_ctrl_ptr_create((void *)&unit_size), + v4l2_ctrl_ptr_create(NULL), + v4l2_ctrl_ptr_create(NULL)); + ret = imx214->ctrls.error; if (ret) { dev_err(&client->dev, "%s control init failed (%d)\n", diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c index 7468e43800a9..28eca8f9d148 100644 --- a/drivers/media/platform/qcom/venus/venc_ctrls.c +++ b/drivers/media/platform/qcom/venus/venc_ctrls.c @@ -607,11 +607,16 @@ int venc_ctrl_init(struct venus_inst *inst) v4l2_ctrl_new_std_compound(&inst->ctrl_handler, &venc_ctrl_ops, V4L2_CID_COLORIMETRY_HDR10_CLL_INFO, - v4l2_ctrl_ptr_create(&p_hdr10_cll)); + v4l2_ctrl_ptr_create(&p_hdr10_cll), + v4l2_ctrl_ptr_create(NULL), + v4l2_ctrl_ptr_create(NULL)); v4l2_ctrl_new_std_compound(&inst->ctrl_handler, &venc_ctrl_ops, V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY, - v4l2_ctrl_ptr_create((void *)&p_hdr10_mastering)); + v4l2_ctrl_ptr_create((void *)&p_hdr10_mastering), + v4l2_ctrl_ptr_create(NULL), + v4l2_ctrl_ptr_create(NULL)); + v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE, diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c index d0a3aa3806fb..3bfab11fe148 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c @@ -94,6 +94,34 @@ static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) return ptr_to_user(c, ctrl, ctrl->p_new); } +/* Helper function: copy the minimum control value back to the caller */ +static int min_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) +{ + int idx, ret; + + for (idx = 0; idx < ctrl->elems; idx++) { + ret = ctrl->type_ops->minimum(ctrl, idx, ctrl->p_new); + if (ret) + return ret; + } + + return ptr_to_user(c, ctrl, ctrl->p_new); +} + +/* Helper function: copy the maximum control value back to the caller */ +static int max_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) +{ + int idx, ret; + + for (idx = 0; idx < ctrl->elems; idx++) { + ret = ctrl->type_ops->maximum(ctrl, idx, ctrl->p_new); + if (ret) + return ret; + } + + return ptr_to_user(c, ctrl, ctrl->p_new); +} + /* Helper function: copy the caller-provider value as the new control value */ static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) { @@ -228,8 +256,8 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, cs->error_idx = i; if (cs->which && - cs->which != V4L2_CTRL_WHICH_DEF_VAL && - cs->which != V4L2_CTRL_WHICH_REQUEST_VAL && + (cs->which < V4L2_CTRL_WHICH_DEF_VAL || + cs->which > V4L2_CTRL_WHICH_MAX_VAL) && V4L2_CTRL_ID2WHICH(id) != cs->which) { dprintk(vdev, "invalid which 0x%x or control id 0x%x\n", @@ -367,8 +395,8 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, */ static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) { - if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL || - which == V4L2_CTRL_WHICH_REQUEST_VAL) + if (which == 0 || (which >= V4L2_CTRL_WHICH_DEF_VAL && + which <= V4L2_CTRL_WHICH_MAX_VAL)) return 0; return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL; } @@ -388,10 +416,12 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_helper *helpers = helper; int ret; int i, j; - bool is_default, is_request; + bool is_default, is_request, is_min, is_max; is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL); + is_min = (cs->which == V4L2_CTRL_WHICH_MIN_VAL); + is_max = (cs->which == V4L2_CTRL_WHICH_MAX_VAL); cs->error_idx = cs->count; cs->which = V4L2_CTRL_ID2WHICH(cs->which); @@ -431,13 +461,14 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, /* * g_volatile_ctrl will update the new control values. - * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and + * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL, + * V4L2_CTRL_WHICH_MIN_VAL, V4L2_CTRL_WHICH_MAX_VAL and * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests * it is v4l2_ctrl_request_complete() that copies the * volatile controls at the time of request completion * to the request, so you don't want to do that again. */ - if (!is_default && !is_request && + if (!is_default && !is_request && !is_min && !is_max && ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || (master->has_volatiles && !is_cur_manual(master)))) { for (j = 0; j < master->ncontrols; j++) @@ -466,6 +497,10 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, ret = -ENOMEM; else if (is_request && ref->p_req_valid) ret = req_to_user(cs->controls + idx, ref); + else if (is_min) + ret = min_to_user(cs->controls + idx, ref->ctrl); + else if (is_max) + ret = max_to_user(cs->controls + idx, ref->ctrl); else if (is_volatile) ret = new_to_user(cs->controls + idx, ref->ctrl); else @@ -563,9 +598,11 @@ int try_set_ext_ctrls_common(struct v4l2_fh *fh, cs->error_idx = cs->count; - /* Default value cannot be changed */ - if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) { - dprintk(vdev, "%s: cannot change default value\n", + /* Default/minimum/maximum values cannot be changed */ + if (cs->which == V4L2_CTRL_WHICH_DEF_VAL || + cs->which == V4L2_CTRL_WHICH_MIN_VAL || + cs->which == V4L2_CTRL_WHICH_MAX_VAL) { + dprintk(vdev, "%s: cannot change default/min/max value\n", video_device_node_name(vdev)); return -EINVAL; } diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 0ac36ebc45dd..f8de0a974f16 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -177,29 +177,72 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, } } -void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, +static int std_min_compound(const struct v4l2_ctrl *ctrl, u32 idx, union v4l2_ctrl_ptr ptr) +{ + void *p = ptr.p + idx * ctrl->elem_size; + + if (!ctrl->p_min.p_const) + return -ENODATA; + + memcpy(p, ctrl->p_min.p_const, ctrl->elem_size); + return 0; +} + +static int std_max_compound(const struct v4l2_ctrl *ctrl, u32 idx, + union v4l2_ctrl_ptr ptr) +{ + void *p = ptr.p + idx * ctrl->elem_size; + + if (!ctrl->p_max.p_const) + return -ENODATA; + + memcpy(p, ctrl->p_max.p_const, ctrl->elem_size); + return 0; +} + +static int __v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, + u32 which, union v4l2_ctrl_ptr ptr) { unsigned int i; u32 tot_elems = ctrl->elems; u32 elems = tot_elems - from_idx; + s64 value; + int ret; if (from_idx >= tot_elems) - return; + return -EINVAL; + + switch (which) { + case V4L2_CTRL_WHICH_DEF_VAL: + value = ctrl->default_value; + break; + case V4L2_CTRL_WHICH_MAX_VAL: + value = ctrl->maximum; + break; + case V4L2_CTRL_WHICH_MIN_VAL: + value = ctrl->minimum; + break; + default: + return -EINVAL; + } switch (ctrl->type) { case V4L2_CTRL_TYPE_STRING: + if (which == V4L2_CTRL_WHICH_DEF_VAL) + value = ctrl->minimum; + for (i = from_idx; i < tot_elems; i++) { unsigned int offset = i * ctrl->elem_size; - memset(ptr.p_char + offset, ' ', ctrl->minimum); - ptr.p_char[offset + ctrl->minimum] = '\0'; + memset(ptr.p_char + offset, ' ', value); + ptr.p_char[offset + value] = '\0'; } break; case V4L2_CTRL_TYPE_INTEGER64: - if (ctrl->default_value) { + if (value) { for (i = from_idx; i < tot_elems; i++) - ptr.p_s64[i] = ctrl->default_value; + ptr.p_s64[i] = value; } else { memset(ptr.p_s64 + from_idx, 0, elems * sizeof(s64)); } @@ -209,9 +252,9 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_BITMASK: case V4L2_CTRL_TYPE_BOOLEAN: - if (ctrl->default_value) { + if (value) { for (i = from_idx; i < tot_elems; i++) - ptr.p_s32[i] = ctrl->default_value; + ptr.p_s32[i] = value; } else { memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32)); } @@ -221,32 +264,69 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32)); break; case V4L2_CTRL_TYPE_U8: - memset(ptr.p_u8 + from_idx, ctrl->default_value, elems); + memset(ptr.p_u8 + from_idx, value, elems); break; case V4L2_CTRL_TYPE_U16: - if (ctrl->default_value) { + if (value) { for (i = from_idx; i < tot_elems; i++) - ptr.p_u16[i] = ctrl->default_value; + ptr.p_u16[i] = value; } else { memset(ptr.p_u16 + from_idx, 0, elems * sizeof(u16)); } break; case V4L2_CTRL_TYPE_U32: - if (ctrl->default_value) { + if (value) { for (i = from_idx; i < tot_elems; i++) - ptr.p_u32[i] = ctrl->default_value; + ptr.p_u32[i] = value; } else { memset(ptr.p_u32 + from_idx, 0, elems * sizeof(u32)); } break; default: - for (i = from_idx; i < tot_elems; i++) - std_init_compound(ctrl, i, ptr); + for (i = from_idx; i < tot_elems; i++) { + switch (which) { + case V4L2_CTRL_WHICH_DEF_VAL: + std_init_compound(ctrl, i, ptr); + break; + case V4L2_CTRL_WHICH_MAX_VAL: + ret = std_max_compound(ctrl, i, ptr); + if (ret) + return ret; + break; + case V4L2_CTRL_WHICH_MIN_VAL: + ret = std_min_compound(ctrl, i, ptr); + if (ret) + return ret; + break; + } + } break; } + + return 0; +} + +void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, + union v4l2_ctrl_ptr ptr) +{ + __v4l2_ctrl_type_op_init(ctrl, from_idx, V4L2_CTRL_WHICH_DEF_VAL, ptr); } EXPORT_SYMBOL(v4l2_ctrl_type_op_init); +static int v4l2_ctrl_type_op_minimum(const struct v4l2_ctrl *ctrl, u32 from_idx, + union v4l2_ctrl_ptr ptr) +{ + return __v4l2_ctrl_type_op_init(ctrl, from_idx, + V4L2_CTRL_WHICH_MIN_VAL, ptr); +} + +static int v4l2_ctrl_type_op_maximum(const struct v4l2_ctrl *ctrl, u32 from_idx, + union v4l2_ctrl_ptr ptr) +{ + return __v4l2_ctrl_type_op_init(ctrl, from_idx, + V4L2_CTRL_WHICH_MAX_VAL, ptr); +} + void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl) { union v4l2_ctrl_ptr ptr = ctrl->p_cur; @@ -1043,6 +1123,8 @@ EXPORT_SYMBOL(v4l2_ctrl_type_op_validate); static const struct v4l2_ctrl_type_ops std_type_ops = { .equal = v4l2_ctrl_type_op_equal, .init = v4l2_ctrl_type_op_init, + .minimum = v4l2_ctrl_type_op_minimum, + .maximum = v4l2_ctrl_type_op_maximum, .log = v4l2_ctrl_type_op_log, .validate = v4l2_ctrl_type_op_validate, }; @@ -1514,7 +1596,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, s64 min, s64 max, u64 step, s64 def, const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size, u32 flags, const char * const *qmenu, - const s64 *qmenu_int, const union v4l2_ctrl_ptr p_def, + const s64 *qmenu_int, + const union v4l2_ctrl_ptr p_def, + const union v4l2_ctrl_ptr p_min, + const union v4l2_ctrl_ptr p_max, void *priv) { struct v4l2_ctrl *ctrl; @@ -1634,6 +1719,14 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, handler_set_err(hdl, -ERANGE); return NULL; } + + if ((!p_def.p_const && p_min.p_const) || + (p_min.p_const && !p_max.p_const) || + (!p_min.p_const && p_max.p_const)) { + handler_set_err(hdl, -EINVAL); + return NULL; + } + err = check_range(type, min, max, step, def); if (err) { handler_set_err(hdl, err); @@ -1675,6 +1768,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) sz_extra += elem_size; + if (type >= V4L2_CTRL_COMPOUND_TYPES && p_min.p_const) + sz_extra += elem_size * 2; ctrl = kvzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL); if (ctrl == NULL) { @@ -1740,6 +1835,14 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, memcpy(ctrl->p_def.p, p_def.p_const, elem_size); } + if (type >= V4L2_CTRL_COMPOUND_TYPES && + p_min.p_const && p_max.p_const) { + ctrl->p_min.p = ctrl->p_def.p + elem_size; + memcpy(ctrl->p_min.p, p_min.p_const, elem_size); + ctrl->p_max.p = ctrl->p_min.p + elem_size; + memcpy(ctrl->p_max.p, p_max.p_const, elem_size); + } + ctrl->type_ops->init(ctrl, 0, ctrl->p_cur); cur_to_new(ctrl); @@ -1790,7 +1893,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, type, min, max, is_menu ? cfg->menu_skip_mask : step, def, cfg->dims, cfg->elem_size, - flags, qmenu, qmenu_int, cfg->p_def, priv); + flags, qmenu, qmenu_int, cfg->p_def, cfg->p_min, + cfg->p_max, priv); if (ctrl) ctrl->is_private = cfg->is_private; return ctrl; @@ -1815,7 +1919,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, } return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, min, max, step, def, NULL, 0, - flags, NULL, NULL, ptr_null, NULL); + flags, NULL, NULL, ptr_null, ptr_null, + ptr_null, NULL); } EXPORT_SYMBOL(v4l2_ctrl_new_std); @@ -1848,7 +1953,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, } return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 0, max, mask, def, NULL, 0, - flags, qmenu, qmenu_int, ptr_null, NULL); + flags, qmenu, qmenu_int, ptr_null, ptr_null, + ptr_null, NULL); } EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); @@ -1880,7 +1986,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl, } return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 0, max, mask, def, NULL, 0, - flags, qmenu, NULL, ptr_null, NULL); + flags, qmenu, NULL, ptr_null, ptr_null, + ptr_null, NULL); } EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); @@ -1888,7 +1995,9 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); /* Helper function for standard compound controls */ struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, - const union v4l2_ctrl_ptr p_def) + const union v4l2_ctrl_ptr p_def, + const union v4l2_ctrl_ptr p_min, + const union v4l2_ctrl_ptr p_max) { const char *name; enum v4l2_ctrl_type type; @@ -1902,7 +2011,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, } return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, min, max, step, def, NULL, 0, - flags, NULL, NULL, p_def, NULL); + flags, NULL, NULL, p_def, p_min, p_max, NULL); } EXPORT_SYMBOL(v4l2_ctrl_new_std_compound); @@ -1926,7 +2035,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, } return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 0, max, 0, def, NULL, 0, - flags, NULL, qmenu_int, ptr_null, NULL); + flags, NULL, qmenu_int, ptr_null, ptr_null, + ptr_null, NULL); } EXPORT_SYMBOL(v4l2_ctrl_new_int_menu); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index fddba75d9074..5d49e6d71b64 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -893,7 +893,9 @@ static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl) return false; break; case V4L2_CTRL_WHICH_DEF_VAL: - /* Default value cannot be changed */ + case V4L2_CTRL_WHICH_MIN_VAL: + case V4L2_CTRL_WHICH_MAX_VAL: + /* Default, minimum or maximum value cannot be changed */ if (ioctl == VIDIOC_S_EXT_CTRLS || ioctl == VIDIOC_TRY_EXT_CTRLS) { c->error_idx = c->count; diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 1846caf9dd53..6feeb18411e4 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -125,6 +125,8 @@ struct v4l2_ctrl_ops { * * @equal: return true if all ctrl->elems array elements are equal. * @init: initialize the value for array elements from from_idx to ctrl->elems. + * @minimum: set the value to the minimum value of the control. + * @maximum: set the value to the maximum value of the control. * @log: log the value. * @validate: validate the value for ctrl->new_elems array elements. * Return 0 on success and a negative value otherwise. @@ -134,6 +136,10 @@ struct v4l2_ctrl_type_ops { union v4l2_ctrl_ptr ptr1, union v4l2_ctrl_ptr ptr2); void (*init)(const struct v4l2_ctrl *ctrl, u32 from_idx, union v4l2_ctrl_ptr ptr); + int (*minimum)(const struct v4l2_ctrl *ctrl, u32 idx, + union v4l2_ctrl_ptr ptr); + int (*maximum)(const struct v4l2_ctrl *ctrl, u32 idx, + union v4l2_ctrl_ptr ptr); void (*log)(const struct v4l2_ctrl *ctrl); int (*validate)(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr); }; @@ -239,6 +245,12 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); * @p_def: The control's default value represented via a union which * provides a standard way of accessing control types * through a pointer (for compound controls only). + * @p_min: The control's minimum value represented via a union which + * provides a standard way of accessing control types + * through a pointer (for compound controls only). + * @p_max: The control's maximum value represented via a union which + * provides a standard way of accessing control types + * through a pointer (for compound controls only). * @p_cur: The control's current value represented via a union which * provides a standard way of accessing control types * through a pointer. @@ -298,6 +310,8 @@ struct v4l2_ctrl { } cur; union v4l2_ctrl_ptr p_def; + union v4l2_ctrl_ptr p_min; + union v4l2_ctrl_ptr p_max; union v4l2_ctrl_ptr p_new; union v4l2_ctrl_ptr p_cur; }; @@ -417,6 +431,8 @@ struct v4l2_ctrl_handler { * @step: The control's step value for non-menu controls. * @def: The control's default value. * @p_def: The control's default value for compound controls. + * @p_min: The control's minimum value for compound controls. + * @p_max: The control's maximum value for compound controls. * @dims: The size of each dimension. * @elem_size: The size in bytes of the control. * @flags: The control's flags. @@ -446,6 +462,8 @@ struct v4l2_ctrl_config { u64 step; s64 def; union v4l2_ctrl_ptr p_def; + union v4l2_ctrl_ptr p_min; + union v4l2_ctrl_ptr p_max; u32 dims[V4L2_CTRL_MAX_DIMS]; u32 elem_size; u32 flags; @@ -715,17 +733,23 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl, * @ops: The control ops. * @id: The control ID. * @p_def: The control's default value. + * @p_min: The control's minimum value. + * @p_max: The control's maximum value. * - * Sames as v4l2_ctrl_new_std(), but with support to compound controls, thanks - * to the @p_def field. Use v4l2_ctrl_ptr_create() to create @p_def from a - * pointer. Use v4l2_ctrl_ptr_create(NULL) if the default value of the - * compound control should be all zeroes. + * Same as v4l2_ctrl_new_std(), but with support to compound controls, thanks + * to the @p_def/min/max fields. Use v4l2_ctrl_ptr_create() to create + * @p_def/min/max from a pointer. Use v4l2_ctrl_ptr_create(NULL) if the + * default value of the compound control should be all zeroes. Use + * v4l2_ctrl_ptr_create(NULL) if the min/max value of the compound control + * is not defined, -ENODATA will be returned in this case. * */ struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, - const union v4l2_ctrl_ptr p_def); + const union v4l2_ctrl_ptr p_def, + const union v4l2_ctrl_ptr p_min, + const union v4l2_ctrl_ptr p_max); /** * v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control. diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index a81951c51325..5f698b49c02e 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1827,6 +1827,8 @@ struct v4l2_ext_controls { #define V4L2_CTRL_WHICH_CUR_VAL 0 #define V4L2_CTRL_WHICH_DEF_VAL 0x0f000000 #define V4L2_CTRL_WHICH_REQUEST_VAL 0x0f010000 +#define V4L2_CTRL_WHICH_MIN_VAL 0x0f020000 +#define V4L2_CTRL_WHICH_MAX_VAL 0x0f030000 enum v4l2_ctrl_type { V4L2_CTRL_TYPE_INTEGER = 1, From patchwork Tue Oct 25 05:55:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018503 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8876FFA373F for ; Tue, 25 Oct 2022 05:56:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229619AbiJYF41 (ORCPT ); Tue, 25 Oct 2022 01:56:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47960 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229851AbiJYF4Y (ORCPT ); Tue, 25 Oct 2022 01:56:24 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 649E9AF19E for ; Mon, 24 Oct 2022 22:56:21 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-33dc888dc62so109560597b3.4 for ; Mon, 24 Oct 2022 22:56:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=AcvfZjZlnpNT367BjsbpG6KxYYbzuCMnjTLt4Jb7b+s=; b=bJhMyDwFtqqzt+GBaoGOFOO2akXeDrdp13/tcTMaFrQ6iHeZ3vnuyeIm+ivQhYe6s3 JMU3/m2MKBQ/c/QnMZj5I3dm5eaPOr9OC/J5j2VAyFafgRsk9y4Bpsz168Lrq3u3Mu0G kSnzex9Paxp+ZaE/+G23Aalax6hG3f9FxAXLL7IwnBC5646JZgq4xfOgkk5P9c/CE+Jb 9QObN9IVJ8kf/8WkBQoJC0utlYz3wMd7Q1bynyY0Ye8gDoFehSToPxgVWkfcU10Olawc 7pKFj7/YKLNrKPzwsPYV7rLMRSNPFUNW2cdKAqtdKbK8p3Zwobgj3BQ9RrRc7yMa7xTb hVIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=AcvfZjZlnpNT367BjsbpG6KxYYbzuCMnjTLt4Jb7b+s=; b=c/axItF8hL+QyPOpA6ZOwZWrNWeB1RDax/XDwKR5Tl+HVJ67PkbdvSfh70hnpmbD1A Pq5k4pxRxAr4X/T2NemVKi5MrwTGiTa712wytqBKZPOBbrfUuGXSu9wVsKZsFo2IcUgR Wz8zBU+koGpK5UxaT0GXKoAkr0geSOSK+ugvJV0vmPGNhxMx/UUSuunCU9/MULFV1TwT lAWEOdxdvedMWkNclfS9ltflYOOKlTdegNR39g9Xh0aQKB76eJwQuf5rSYQ4w94EwmB4 GzvVr/b2NyVd6fJu2of5kq9vSRWU0vv41DUZygJs47+gSz/PZ83n4TKONrsk6XuTNrEK 2ovA== X-Gm-Message-State: ACrzQf3wEkX+8msm258WAerdocy3xRG3hp4ziuyjRpGpWXYg/BaW+jZG 1acQ5eolZWiQDDiTJvxWLKM8ZZUYJzA= X-Google-Smtp-Source: AMsMyM66CcjNhgdoiH66FaWoZYwgnVGV4ZcFC+H2B3NtRulGFyONxt9ClXxFcmmDqy8BCYHVr2tSEcW43Og= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a25:49c6:0:b0:6bc:17dc:4441 with SMTP id w189-20020a2549c6000000b006bc17dc4441mr32909468yba.593.1666677380716; Mon, 24 Oct 2022 22:56:20 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:26 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-10-yunkec@google.com> Subject: [PATCH v9 09/11] media: v4l2: document the usage of min/max for V4L2_CTRL_TYPE_RECT From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Document the default implementation of min/max for rectangle controls. Signed-off-by: Yunke Cao --- Changelog since v8: - New patch. Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst index 58982cd382e3..efa07428ba7a 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -447,7 +447,11 @@ See also the examples in :ref:`control`. - n/a - A struct :c:type:`v4l2_rect`, containing a rectangle described by the position of its top-left corner, the width and the height. Units - depend on the use case. + depend on the use case. Use ``V4L2_CTRL_WHICH_MIN_VAL`` and + ``V4L2_CTRL_WHICH_MAX_VAL`` to query the range of rectangle sizes. The + top-left corner of the minimum and maximum rectangles should be the + same. For example, a control can have a minimum rectangle of 1x1@0x0 and + a maximum of 640x480@0x0. * - ``V4L2_CTRL_TYPE_H264_SPS`` - n/a - n/a From patchwork Tue Oct 25 05:55:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018504 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0A277C04A95 for ; Tue, 25 Oct 2022 05:56:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231127AbiJYF43 (ORCPT ); Tue, 25 Oct 2022 01:56:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48286 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230307AbiJYF42 (ORCPT ); Tue, 25 Oct 2022 01:56:28 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 28349B6033 for ; Mon, 24 Oct 2022 22:56:26 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id p18-20020a63e652000000b0046b27534651so5792576pgj.17 for ; Mon, 24 Oct 2022 22:56:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=b5iOvP3Gdr4MKRN77xIkxqpXJxhJX3EY4/F/SDqLgNw=; b=QGL225yysyjEb4q/sPfZJh4kZwmaQ0MiBvQ3i7hORvveajZXZaEl61gU7b/KxxqYmQ XsmC/IL/LQWouIIkxrB6yzI7JiSxWBgVINL3UQxnq8livLFq3mP38EdmJgAn2Vg7Rr5q KsHu41nZdJwQweKxr7m3NYAiy+R15PLRWUItUM3k/crMwhQxLXTxa1tGcSlAZ0clOoml RwIDNoNGk1M78s/vdBrzUizCMf4AVpDpWJsumAPZtUiGy77fQrsZoXhOBN4SfsRFD1qd ny/ldDZCNt4S7lyaFiIA4poy2Oq1uWSo73/YemFMqXYcLdPkbuTSAx370OgfPFVK+vP0 w7XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=b5iOvP3Gdr4MKRN77xIkxqpXJxhJX3EY4/F/SDqLgNw=; b=02J0ZA7RDn7aKAOP+N32DXw42KZum60f5O3urGJqFUF7EV+g0eMugkbGShP8Zc8ua/ Df+si2eqDmujNLGRD0dx1fsZwE/bGFV4osy9UIsnyLPRKe7l2k5n+KOKTgwdVM3hhHax hzV1qzuvNrqI3OaM35SJ0aNl0UkXC9dd7ebwd6WSf0eIWLLJokBNtkoPYMQJbMokUMMM GALVm/jYrE+YjZbJflPD/BTR7gU3iUxkGUjHUu+q6iKpnbUlvUYSYh8379iuf0kX5WCu EA2DZYMqEQRbhpHwmapCxhbls6x1JxVBP+bYnx2/BavxYawh68TgxyFB9yNi9tvbDGOT 848A== X-Gm-Message-State: ACrzQf0zsKDLhzsaI1xAnetnKQGor19DhrZpUQ3V8zEiSr0KVMj/glc6 exPZunccs5NEDI/dtOzcw+T4iK2O9QE= X-Google-Smtp-Source: AMsMyM6U7X94WgoVfyI7AHm50K3nGsLTpvo/vSLHrYwo4SiWvU6LX6XQ+izoFSy4ha6Zfao/fh4+HtlI4Ko= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a17:90b:1c8c:b0:203:89fb:ba79 with SMTP id oo12-20020a17090b1c8c00b0020389fbba79mr78451125pjb.92.1666677385731; Mon, 24 Oct 2022 22:56:25 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:27 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-11-yunkec@google.com> Subject: [PATCH v9 10/11] media: uvcvideo: support V4L2_CTRL_WHICH_MIN/MAX_VAL From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add support for V4L2_CTRL_WHICH_MIN/MAX_VAL in uvc driver. It is useful for the V4L2_CID_UVC_REGION_OF_INTEREST_RECT control. Signed-off-by: Yunke Cao Reviewed-by: Ricardo Ribalda --- Changelog since v8: - No change. Changelog since v7: - Address some comments. drivers/media/usb/uvc/uvc_ctrl.c | 45 +++++++++++++++++++++++++++----- drivers/media/usb/uvc/uvc_v4l2.c | 11 ++++++-- drivers/media/usb/uvc/uvcvideo.h | 3 ++- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 33199de7f1be..0713685f8005 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1975,6 +1975,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain, struct uvc_control *ctrl, struct uvc_control_mapping *mapping, + u32 v4l2_which, struct v4l2_ext_control *xctrl) { struct v4l2_queryctrl qc = { .id = xctrl->id }; @@ -1984,19 +1985,47 @@ int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain, if (ret < 0) return ret; - xctrl->value = qc.default_value; + switch (v4l2_which) { + case V4L2_CTRL_WHICH_DEF_VAL: + xctrl->value = qc.default_value; + break; + case V4L2_CTRL_WHICH_MIN_VAL: + xctrl->value = qc.minimum; + break; + case V4L2_CTRL_WHICH_MAX_VAL: + xctrl->value = qc.maximum; + break; + } + return 0; } static int __uvc_ctrl_get_boundary_compound(struct uvc_video_chain *chain, struct uvc_control *ctrl, struct uvc_control_mapping *mapping, + u32 v4l2_which, struct v4l2_ext_control *xctrl) { + u32 flag, id; int ret; - if (!uvc_ctrl_mapping_is_compound(mapping)) - return -EINVAL; + switch (v4l2_which) { + case V4L2_CTRL_WHICH_DEF_VAL: + flag = UVC_CTRL_FLAG_GET_DEF; + id = UVC_CTRL_DATA_DEF; + break; + case V4L2_CTRL_WHICH_MIN_VAL: + flag = UVC_CTRL_FLAG_GET_MIN; + id = UVC_CTRL_DATA_MIN; + break; + case V4L2_CTRL_WHICH_MAX_VAL: + flag = UVC_CTRL_FLAG_GET_MAX; + id = UVC_CTRL_DATA_MAX; + break; + } + + if (!(ctrl->info.flags & flag) && flag != UVC_CTRL_FLAG_GET_DEF) + return -EACCES; if (!ctrl->cached) { ret = uvc_ctrl_populate_cache(chain, ctrl); @@ -2004,11 +2033,11 @@ static int __uvc_ctrl_get_boundary_compound(struct uvc_video_chain *chain, return ret; } - return __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_DEF, xctrl); + return __uvc_ctrl_get_compound(mapping, ctrl, id, xctrl); } int uvc_ctrl_get_boundary(struct uvc_video_chain *chain, - struct v4l2_ext_control *xctrl) + struct v4l2_ext_control *xctrl, u32 v4l2_which) { struct uvc_control *ctrl; struct uvc_control_mapping *mapping; @@ -2025,9 +2054,11 @@ int uvc_ctrl_get_boundary(struct uvc_video_chain *chain, if (uvc_ctrl_mapping_is_compound(mapping)) ret = __uvc_ctrl_get_boundary_compound(chain, ctrl, mapping, - xctrl); + v4l2_which, xctrl); else - ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, xctrl); + ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, + v4l2_which, xctrl); + done: mutex_unlock(&chain->ctrl_mutex); diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 52a7dc9ad4b9..08060145700a 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1047,9 +1047,12 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, if (ret < 0) return ret; - if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) { + switch (ctrls->which) { + case V4L2_CTRL_WHICH_DEF_VAL: + case V4L2_CTRL_WHICH_MIN_VAL: + case V4L2_CTRL_WHICH_MAX_VAL: for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_get_boundary(chain, ctrl); + ret = uvc_ctrl_get_boundary(chain, ctrl, ctrls->which); if (ret < 0) { ctrls->error_idx = i; return ret; @@ -1057,6 +1060,10 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, } return 0; + case V4L2_CTRL_WHICH_CUR_VAL: + break; + default: + return -EINVAL; } ret = uvc_ctrl_begin(chain); diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index c7d20333ca8a..5c3b4ce85615 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -778,7 +778,8 @@ static inline int uvc_ctrl_rollback(struct uvc_fh *handle) int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl); int uvc_ctrl_get_boundary(struct uvc_video_chain *chain, - struct v4l2_ext_control *xctrl); + struct v4l2_ext_control *xctrl, + u32 v4l2_which); int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl); int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, bool read); From patchwork Tue Oct 25 05:55:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 13018505 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7851AC04A95 for ; Tue, 25 Oct 2022 05:56:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231131AbiJYF4d (ORCPT ); Tue, 25 Oct 2022 01:56:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48618 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229841AbiJYF4c (ORCPT ); Tue, 25 Oct 2022 01:56:32 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42109B6033 for ; Mon, 24 Oct 2022 22:56:31 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id a33-20020a630b61000000b00429d91cc649so5718890pgl.8 for ; Mon, 24 Oct 2022 22:56:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ezLrf769O+Wse50EkEHQq9Ctgcj8uVimY3Uk5weLHGQ=; b=Kag1sNegnCpQmuxr7od2hYfqOhb8jn5GctySjBpmkjK2YcQIw5BQBTApC1hNuyU5R2 15uZc9otHvyZMRD58gdLcWXZaoPcHYIRK0DH+u0Q82QkDJYSPb5HA54POGr/D4vw0251 ExygmTg71mD7GTXSDjZdacy/1y5oL0deGVFyyn3Mlw3ZtT5S/JSmX6yb8sI7/6izKHGr v4HuG0sEQh/C92h8kWHKcVUTpXiS2W1pE/W+fn8pp4GuMBFu2VxfKCCHDVZVl72wUs9B vC2Sj3DyMTMc4vV9IqVnJVrpy53gKZ4dKGuS7jPM1DhULDBjOhrPZ7/RA12eHymTYQae ql3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ezLrf769O+Wse50EkEHQq9Ctgcj8uVimY3Uk5weLHGQ=; b=LhPsj87PS78VyqC83R8pQj+G3piVu3nST2+UuPDSWuMDT2h5ZQG7feXK9f6J+vZWu+ BUQlFb+o0M3+ZkDVqo/LKWo84MNzce/oKw7dJSi/fa5ClJA3t2wfJB9JHAtna+1yhdwh D6NmklLQ+YF4KgK+eB7VuKXBwFmoTt47Aod5ldmJE+YQInLct82TIKmcUHENrN9MeDJN E8dwoI+DaopqMv60NYZaeJoaw+fQIALciUVSHIaoqdL3MtiDDkN6N4ev5BVGrOpv0IFq TRBakXjX34sfKOrajasH/MmqY2lB7Jmd/SPVWZLaiNemD4zyXtFGZwFVZ6vrZUzPOaGf 6uRQ== X-Gm-Message-State: ACrzQf2/FXHf4UrFmWGFqNuGS56JwIH6WY4lQEIQZDresxjdXAiO+ZD+ gy6lVYdCVi/+nOJjGUqIG65a+VskQJc= X-Google-Smtp-Source: AMsMyM5P6NTxtE7MUq7nMVUkDaD39QoajN4UYuDEjAfqEiy7Wfz0yuWdchAxvY1Rwr4svW/YdlIMKfofwJU= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:7ee8:fa64:12b0:14f3]) (user=yunkec job=sendgmr) by 2002:a05:6a00:cd1:b0:563:8df5:2b8b with SMTP id b17-20020a056a000cd100b005638df52b8bmr37401482pfv.67.1666677390746; Mon, 24 Oct 2022 22:56:30 -0700 (PDT) Date: Tue, 25 Oct 2022 14:55:28 +0900 In-Reply-To: <20221025055528.1117251-1-yunkec@google.com> Mime-Version: 1.0 References: <20221025055528.1117251-1-yunkec@google.com> X-Mailer: git-send-email 2.38.0.135.g90850a2211-goog Message-ID: <20221025055528.1117251-12-yunkec@google.com> Subject: [PATCH v9 11/11] media: uvcvideo: document UVC v1.5 ROI From: Yunke Cao To: Hans Verkuil , Laurent Pinchart Cc: Nicolas Dufresne , Mauro Carvalho Chehab , Tomasz Figa , Sergey Senozhatsky , Ricardo Ribalda , linux-media@vger.kernel.org, Yunke Cao Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Added documentation of V4L2_CID_UVC_REGION_OF_INTEREST_RECT and V4L2_CID_UVC_REGION_OF_INTEREST_AUTO. Signed-off-by: Yunke Cao Reviewed-by: Ricardo Ribalda --- Changelog since v8: - No change. Changelog since v7: - Fix documentation for automatic exposure based on comment in v7. Some descriptions for some V4L2_UVC_REGION_OF_INTEREST_AUTO_* are vague because I copied these options from the UVC spec. .../userspace-api/media/drivers/uvcvideo.rst | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/Documentation/userspace-api/media/drivers/uvcvideo.rst b/Documentation/userspace-api/media/drivers/uvcvideo.rst index aab4304e6bb5..3dc062221f8b 100644 --- a/Documentation/userspace-api/media/drivers/uvcvideo.rst +++ b/Documentation/userspace-api/media/drivers/uvcvideo.rst @@ -181,6 +181,7 @@ Argument: struct uvc_xu_control_mapping UVC_CTRL_DATA_TYPE_BOOLEAN Boolean UVC_CTRL_DATA_TYPE_ENUM Enumeration UVC_CTRL_DATA_TYPE_BITMASK Bitmask + UVC_CTRL_DATA_TYPE_RECT Rectangular area UVCIOC_CTRL_QUERY - Query a UVC XU control @@ -255,3 +256,64 @@ Argument: struct uvc_xu_control_query __u8 query Request code to send to the device __u16 size Control data size (in bytes) __u8 *data Control value + + +Driver-specific V4L2 controls +----------------------------- + +The uvcvideo driver implements the following UVC-specific controls: + +``V4L2_CID_UVC_REGION_OF_INTEREST_RECT (struct)`` + This control determines the region of interest (ROI). ROI is a + rectangular area represented by a struct :c:type:`v4l2_rect`. The + rectangle is in global sensor coordinates and pixel units. It is + independent of the field of view, not impacted by any cropping or + scaling. + + Use ``V4L2_CTRL_WHICH_MIN_VAL`` and ``V4L2_CTRL_WHICH_MAX_VAL`` to query + the range of rectangle sizes. The left/top coordinates of a minimum or + maximum rectangle are always 0. For example, a device can have a minimum + ROI rectangle of 1x1@0x0 and a maximum of 640x480@0x0. + + Setting a ROI allows the camera to optimize the capture for the region. + The value of ``V4L2_CID_REGION_OF_INTEREST_AUTO`` control determines + the detailed behavior. + + +``V4L2_CID_UVC_REGION_OF_INTEREST_AUTO (bitmask)`` + This determines which, if any, on board features should track to the + Region of Interest specified by the current value of + ``V4L2_CID_UVD__REGION_OF_INTEREST_RECT``. + + Max value is a mask indicating all supported Auto Controls. + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + + * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_EXPOSURE`` + - Setting this to true causes automatic exposure to track the region of + interest instead of the whole image. + * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_IRIS`` + - Setting this to true causes automatic iris to track the region of + interest instead of the whole image. + * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_WHITE_BALANCE`` + - Setting this to true causes automatic white balance to track the region + of interest instead of the whole image. + * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_FOCUS`` + - Setting this to true causes automatic focus adjustment to track the + region of interest instead of the whole image. + * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_FACE_DETECT`` + - Setting this to true causes automatic face detection to track the + region of interest instead of the whole image. + * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK`` + - Setting this to true enables automatic face detection and tracking. The + current value of ``V4L2_CID_REGION_OF_INTEREST_RECT`` may be updated by + the driver. + * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION`` + - Setting this to true enables automatic image stabilization. The + current value of ``V4L2_CID_REGION_OF_INTEREST_RECT`` may be updated by + the driver. + * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY`` + - Setting this to true enables automatically capture the specified region + with higher quality if possible.