From patchwork Wed May 18 06:24:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 574064 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 00327C433EF for ; Wed, 18 May 2022 06:24:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231261AbiERGYn (ORCPT ); Wed, 18 May 2022 02:24:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231234AbiERGYm (ORCPT ); Wed, 18 May 2022 02:24:42 -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 A46BFD029B for ; Tue, 17 May 2022 23:24:41 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-2fecc57ec14so12087387b3.11 for ; Tue, 17 May 2022 23:24:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Xfvt1LaVaO+T3m/5lCLIEq9AbZw96kCNK23AJ/3Wj+c=; b=qUyd+mH67n7xtiP9ghaNJERRUyDiOrDZfrnsT+9tpAnN6btycm5UtBpzq4a4LbsTB9 gExfiazysG01ttrm7NvMrhI51fgmdxV6Rm8biRK4uaeYyV1IhAGvsMur6zJO4OujdcKY iDMhHi+iEjKVp14xLmOwEGXRnMqywF+gE9WzAxOxQSBzcfAJm45bBGC/fEwNp7G3Pf/f WBHS+4fWlin6S6NDcB8q3/RWgg9NyiDXTcNAU8gFNCUeji3sCqR3i3YgT9WXmg7qT0/x 896ABlesPKaFoU3/BU1KLEFlvAc7QlUwayigjXW4HH8gbwcZ2/glwX0IoqRI6U9HxFH9 mMoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Xfvt1LaVaO+T3m/5lCLIEq9AbZw96kCNK23AJ/3Wj+c=; b=ZZZ8mconiVcKRbYR4RmWdWI4B1aDNguGKyFLZs3kQEczKFeTpjqzH11bDq8HgXk2po 8LFS2hv0CsRMpAmycCQs68lU2nal5X6TzaUL1vpkY1TeQgGxnSZNYHClBRHRsucAvoM5 w6OWEaFbN2Elm102nb/ngEuO7FZOBM+4PRrwyVj9N8rPbrwhGJgSzPfBo5HeG5EKCIpv tgVst6odxaDrzIDHI5gH4zXKDJCDr2P90vEiVNoovqFYmTh5beKULunBcuP3349f3ZpF F234M3MRDsjBK1dZUVlSSMxbB5X+VZ6/MMmV+pGtUDke/UPVVyVnS0zMAzcbZDJ6mtP6 5VVQ== X-Gm-Message-State: AOAM531ENbxqP+Tje5TM3XkUhz5/IyjsbJJDaotLUVosFxccaxpc291h eJan7W8Aj9sdRn8sAQ00/r2eWsLMuaQ= X-Google-Smtp-Source: ABdhPJxdG1afxcQ1dsYjxqM2FzHAkaFZ2zgzKst/7A22+uc8etBxOX9Is4ZDipk/WzKHrR4jG7bQAihOqUQ= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:d4d4:2a73:fa69:7d32]) (user=yunkec job=sendgmr) by 2002:a81:4fd4:0:b0:2ff:2c4c:a687 with SMTP id d203-20020a814fd4000000b002ff2c4ca687mr6317148ywb.500.1652855080882; Tue, 17 May 2022 23:24:40 -0700 (PDT) Date: Wed, 18 May 2022 15:24:08 +0900 In-Reply-To: <20220518062412.2375586-1-yunkec@google.com> Message-Id: <20220518062412.2375586-3-yunkec@google.com> Mime-Version: 1.0 References: <20220518062412.2375586-1-yunkec@google.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog Subject: [PATCH v3 2/6] media: v4l2_ctrl: Add region of interest auto control From: Yunke Cao To: Hans Verkuil , Laurent Pinchart , Nicolas Dufresne Cc: 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 Follows the UVC v1.5 class specification. Signed-off-by: Yunke Cao --- Changelog since v2: - Better documentation. - Rename V4L2_CID_REGION_OF_INTEREST_AUTO_EXPOSURE to V4L2_REGION_OF_INTEREST_AUTO_EXPOSURE, etc. The bit masks shouldn't have "CID" in it. .../media/v4l/ext-ctrls-camera.rst | 39 +++++++++++++++++++ drivers/media/v4l2-core/v4l2-ctrls-defs.c | 3 ++ include/uapi/linux/v4l2-controls.h | 9 +++++ 3 files changed, 51 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst index c988a72b97b2..c26c28cfcf6a 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst @@ -671,3 +671,42 @@ enum v4l2_scene_mode - Setting a region of interest 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_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_REGION_OF_INTEREST_RECT``. + + Max value is a mask indicating all supported Auto + Controls. + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + + * - ``V4L2_REGION_OF_INTEREST_AUTO_EXPOSURE`` + - Setting this to true enables automatic exposure time for the specified + region. + * - ``V4L2_REGION_OF_INTEREST_AUTO_IRIS`` + - Setting this to true enables automatic iris aperture for the specified + region. + * - ``V4L2_REGION_OF_INTEREST_AUTO_WHITE_BALANCE`` + - Setting this to true enables automatic white balance adjustment for the + specified region. + * - ``V4L2_REGION_OF_INTEREST_AUTO_FOCUS`` + - Setting this to true enables automatic focus adjustment for the + specified region. + * - ``V4L2_REGION_OF_INTEREST_AUTO_FACE_DETECT`` + - Setting this to true enables automatic face detection for the + specified region. + * - ``V4L2_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK`` + - Setting this to true enables automatic detection and tracking. The + current value of ``V4L2_CID_REGION_OF_INTEREST_RECT`` may be updated by + the firmware. + * - ``V4L2_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 firmware. + * - ``V4L2_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY`` + - Setting this to true enables automatically capture the specified region + with higher quality if possible. diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 95f39a2d2ad2..220afc4d5244 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -1043,6 +1043,8 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_CAMERA_ORIENTATION: return "Camera Orientation"; case V4L2_CID_CAMERA_SENSOR_ROTATION: return "Camera Sensor Rotation"; case V4L2_CID_REGION_OF_INTEREST_RECT: return "Region Of Interest Rectangle"; + case V4L2_CID_REGION_OF_INTEREST_AUTO: return "Region Of Interest Auto Controls"; + /* FM Radio Modulator controls */ /* Keep the order of the 'case's the same as in v4l2-controls.h! */ @@ -1415,6 +1417,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_JPEG_ACTIVE_MARKER: case V4L2_CID_3A_LOCK: case V4L2_CID_AUTO_FOCUS_STATUS: + case V4L2_CID_REGION_OF_INTEREST_AUTO: case V4L2_CID_DV_TX_HOTPLUG: case V4L2_CID_DV_TX_RXSENSE: case V4L2_CID_DV_TX_EDID_PRESENT: diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 499fcddb6254..13db0638533c 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1009,6 +1009,15 @@ enum v4l2_auto_focus_range { #define V4L2_CID_CAMERA_SENSOR_ROTATION (V4L2_CID_CAMERA_CLASS_BASE+35) #define V4L2_CID_REGION_OF_INTEREST_RECT (V4L2_CID_CAMERA_CLASS_BASE+36) +#define V4L2_CID_REGION_OF_INTEREST_AUTO (V4L2_CID_CAMERA_CLASS_BASE+37) +#define V4L2_REGION_OF_INTEREST_AUTO_EXPOSURE (1 << 0) +#define V4L2_REGION_OF_INTEREST_AUTO_IRIS (1 << 1) +#define V4L2_REGION_OF_INTEREST_AUTO_WHITE_BALANCE (1 << 2) +#define V4L2_REGION_OF_INTEREST_AUTO_FOCUS (1 << 3) +#define V4L2_REGION_OF_INTEREST_AUTO_FACE_DETECT (1 << 4) +#define V4L2_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK (1 << 5) +#define V4L2_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION (1 << 6) +#define V4L2_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY (1 << 7) /* FM Modulator class control IDs */ From patchwork Wed May 18 06:24:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 574063 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 C5E64C433EF for ; Wed, 18 May 2022 06:24:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231271AbiERGY7 (ORCPT ); Wed, 18 May 2022 02:24:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36926 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231234AbiERGY5 (ORCPT ); Wed, 18 May 2022 02:24:57 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90E36D410D for ; Tue, 17 May 2022 23:24:54 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id k17-20020a252411000000b0064ea6c388baso303749ybk.0 for ; Tue, 17 May 2022 23:24:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=k264VNsDpyULhLTrUqqg/PWq084cX97YdRjNrc6OMs8=; b=pKiYKOzn1eTxVjRETKWc7Zye8lxzQbrpJNaqY90AA8jm0m00deSEIANMmNTOUjTNew 8ZOnBnL6FgZUTpWgAaVSpSr1OOb4sH1de+nbNfCVp1l5Auwse41gGeZR+xHPwCDhgKKe C/Vds8varzCwxUrkzVN5um9genRM7LROPayYU+f9KD+NdniNbHpPPtfLCiNU278q8q9Y C/sRrtaVQDOv2wK9mt9+1lfMbETJ670OpWd8LTuYnn0N3ZFgl/6bwa5pMGxxOvno/ww+ X9pf4sZaGWwbDVxwRYAeoPz3Zl4/s2tfJ/yWYty5dx36FkxAwfg/veayUftFW6MLKhEy EMww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=k264VNsDpyULhLTrUqqg/PWq084cX97YdRjNrc6OMs8=; b=c79ZHu+v9dNW2UGJBnuSTnqES9puy3EnCe8HuHF4vhmEnrqAuFuEHEWXCxNcpWSkPJ qMrYpWbdl3smvg8q2NtfARt5gctsZSSswAr/jCNrPTi8cjovWkhKS2dDX9EP/qwyY6/n 0JgXA1UDSe5rGpUwqGujNopQtS9+YzvluPXC7TY8NMMh0uDdGWNb8LdqsgzUPEeROUnQ UKVjq3XRUfh0IMYAwgqnhHpBV11/v6IqEIVm5Qj2vDUZ4zq6cRSLExr/T9wzV3g2mWvG q2Cr/gIGBzC8SaXuzPocSYLU/XnqY59dkq0U5WHcWtBMqdGzc1OnoaaFIWDz3qn/mhbb L9zw== X-Gm-Message-State: AOAM530kzLBXYDMN0niH/cmdlGSTO0gHXnH85FSjh9ILd+tKW2HljkqO PzUIaWmjxkL/2Av7YEs8wdubemjt/B0= X-Google-Smtp-Source: ABdhPJyRfAp3tlb+QDf/xO0aRtVhOUBKT312Vr9WdFw4AqF3vUkF/vUa0kM4FNhK0kapecEO5t991hVTuIU= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:d4d4:2a73:fa69:7d32]) (user=yunkec job=sendgmr) by 2002:a25:da90:0:b0:64e:acc1:e381 with SMTP id n138-20020a25da90000000b0064eacc1e381mr1728ybf.619.1652855093811; Tue, 17 May 2022 23:24:53 -0700 (PDT) Date: Wed, 18 May 2022 15:24:10 +0900 In-Reply-To: <20220518062412.2375586-1-yunkec@google.com> Message-Id: <20220518062412.2375586-5-yunkec@google.com> Mime-Version: 1.0 References: <20220518062412.2375586-1-yunkec@google.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog Subject: [PATCH v3 4/6] media: uvcvideo: implement UVC v1.5 ROI From: Yunke Cao To: Hans Verkuil , Laurent Pinchart , Nicolas Dufresne Cc: 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 GET_CUR, GET_DEF, GET_MIN and GET_MAX requests for UVC v1.5 using V4L2 control API. References a rejected attempt that uses v4l2 selection API: https://lore.kernel.org/lkml/20210501082001.100533-2-senozhatsky@chromium.org Signed-off-by: Yunke Cao --- Changelog since v2: - Add UVC_CTRL_FLAG_AUTO_UPDATE flag. .../userspace-api/media/drivers/uvcvideo.rst | 1 + drivers/media/usb/uvc/uvc_ctrl.c | 174 ++++++++++++++++-- drivers/media/usb/uvc/uvc_v4l2.c | 12 +- drivers/media/usb/uvc/uvcvideo.h | 10 +- include/uapi/linux/usb/video.h | 1 + include/uapi/linux/uvcvideo.h | 1 + 6 files changed, 174 insertions(+), 25 deletions(-) diff --git a/Documentation/userspace-api/media/drivers/uvcvideo.rst b/Documentation/userspace-api/media/drivers/uvcvideo.rst index e5fd8fad333c..43b8431b0d9f 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 diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index b4f6edf968bc..0abe174231ab 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -355,6 +355,16 @@ static const struct uvc_control_info uvc_ctrls[] = { .flags = UVC_CTRL_FLAG_GET_CUR | UVC_CTRL_FLAG_AUTO_UPDATE, }, + { + .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[] = { @@ -728,6 +738,24 @@ 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_REGION_OF_INTEREST_RECT, + .entity = UVC_GUID_UVC_CAMERA, + .selector = UVC_CT_REGION_OF_INTEREST_CONTROL, + .size = 64, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_RECT, + .data_type = UVC_CTRL_DATA_TYPE_RECT, + }, + { + .id = V4L2_CID_REGION_OF_INTEREST_AUTO, + .entity = UVC_GUID_UVC_CAMERA, + .selector = UVC_CT_REGION_OF_INTEREST_CONTROL, + .size = 16, + .offset = 64, + .v4l2_type = V4L2_CTRL_TYPE_BITMASK, + .data_type = UVC_CTRL_DATA_TYPE_BITMASK, + }, }; /* ------------------------------------------------------------------------ @@ -749,6 +777,33 @@ static inline void uvc_clear_bit(u8 *data, int bit) data[bit >> 3] &= ~(1 << (bit & 7)); } +static void uvc_to_v4l2_rect(struct v4l2_rect *v4l2_rect, + const struct uvc_rect *uvc_rect) +{ + 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; +} + +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->width > U16_MAX || + 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; +} + /* Extract the bit string specified by mapping->offset and mapping->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 @@ -963,11 +1018,23 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, return value; } +static void __uvc_ctrl_get_v4l2_rect(struct uvc_control *ctrl, + struct uvc_control_mapping *mapping, + u32 id, + struct v4l2_rect *rect) +{ + struct uvc_rect *uvc_rect = + (struct uvc_rect *)(uvc_ctrl_data(ctrl, id) + + mapping->offset / 8); + uvc_to_v4l2_rect(rect, uvc_rect); +} + static int __uvc_ctrl_get(struct uvc_video_chain *chain, struct uvc_control *ctrl, struct uvc_control_mapping *mapping, - s32 *value) + struct v4l2_ext_control *xctrl) { int ret; + struct v4l2_rect v4l2_rect; if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) return -EACCES; @@ -993,8 +1060,17 @@ static int __uvc_ctrl_get(struct uvc_video_chain *chain, ctrl->loaded = 1; } - *value = __uvc_ctrl_get_value(mapping, + switch (mapping->v4l2_type) { + case V4L2_CTRL_TYPE_RECT: + __uvc_ctrl_get_v4l2_rect(ctrl, mapping, UVC_CTRL_DATA_CURRENT, + &v4l2_rect); + return copy_to_user(xctrl->p_rect, &v4l2_rect, + sizeof(v4l2_rect)); + + default: + xctrl->value = __uvc_ctrl_get_value(mapping, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + } return 0; } @@ -1104,13 +1180,14 @@ 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); + struct v4l2_ext_control xctrl; + int ret = + __uvc_ctrl_get(chain, master_ctrl, master_map, &xctrl); if (ret < 0) return ret; - if (val != mapping->master_manual) - v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + if (xctrl.value != mapping->master_manual) + v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; } if (!ctrl->cached) { @@ -1344,16 +1421,16 @@ static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain, struct uvc_control_mapping *mapping = NULL; struct uvc_control *ctrl = NULL; u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; - s32 val = 0; + struct v4l2_ext_control xctrl; __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0); if (ctrl == NULL) return; - if (__uvc_ctrl_get(chain, ctrl, mapping, &val) == 0) + if (__uvc_ctrl_get(chain, ctrl, mapping, &xctrl) == 0) changes |= V4L2_EVENT_CTRL_CH_VALUE; - uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes); + uvc_ctrl_send_event(chain, handle, ctrl, mapping, xctrl.value, changes); } void uvc_ctrl_status_event(struct uvc_video_chain *chain, @@ -1515,13 +1592,13 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) { struct v4l2_event ev; u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; - s32 val = 0; + struct v4l2_ext_control xctrl; - if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) + if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &xctrl) == 0) changes |= V4L2_EVENT_CTRL_CH_VALUE; - uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val, - changes); + uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, + xctrl.value, changes); /* Mark the queue as active, allowing this initial event to be accepted. */ sev->elems = elems; @@ -1682,10 +1759,14 @@ int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback, } int uvc_ctrl_get(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; + int ret; + u32 flag; + u32 id; + u8 query; if (__uvc_query_v4l2_class(chain, xctrl->id, 0) >= 0) return -EACCES; @@ -1694,7 +1775,46 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, if (ctrl == NULL) return -EINVAL; - return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); + switch (v4l2_which) { + case V4L2_CTRL_WHICH_DEF_VAL: + flag = UVC_CTRL_FLAG_GET_DEF; + id = UVC_CTRL_DATA_DEF; + query = UVC_GET_DEF; + break; + case V4L2_CTRL_WHICH_MIN_VAL: + flag = UVC_CTRL_FLAG_GET_MIN; + id = UVC_CTRL_DATA_MIN; + query = UVC_GET_MIN; + break; + case V4L2_CTRL_WHICH_MAX_VAL: + flag = UVC_CTRL_FLAG_GET_MAX; + id = UVC_CTRL_DATA_MAX; + query = UVC_GET_MAX; + break; + case V4L2_CTRL_WHICH_CUR_VAL: + default: + return __uvc_ctrl_get(chain, ctrl, mapping, xctrl); + } + + if (!ctrl->cached) { + ret = uvc_ctrl_populate_cache(chain, ctrl); + if (ret < 0) + return ret; + } + + if (!(ctrl->info.flags & flag)) + return -EACCES; + + if (mapping->v4l2_type == V4L2_CTRL_TYPE_RECT) { + struct v4l2_rect rect; + + __uvc_ctrl_get_v4l2_rect(ctrl, mapping, id, &rect); + return copy_to_user(xctrl->p_rect, &rect, sizeof(rect)); + } + + xctrl->value = mapping->get(mapping, query, uvc_ctrl_data(ctrl, id)); + + return 0; } int uvc_ctrl_set(struct uvc_fh *handle, @@ -1703,6 +1823,8 @@ int uvc_ctrl_set(struct uvc_fh *handle, struct uvc_video_chain *chain = handle->chain; struct uvc_control *ctrl; struct uvc_control_mapping *mapping; + struct v4l2_rect v4l2_rect; + struct uvc_rect uvc_rect; s32 value; u32 step; s32 min; @@ -1774,6 +1896,16 @@ int uvc_ctrl_set(struct uvc_fh *handle, break; + case V4L2_CTRL_TYPE_RECT: + ret = copy_from_user(&v4l2_rect, xctrl->p_rect, + sizeof(v4l2_rect)); + if (ret < 0) + return ret; + ret = v4l2_to_uvc_rect(&uvc_rect, &v4l2_rect); + if (ret < 0) + return ret; + break; + default: value = xctrl->value; break; @@ -1807,8 +1939,16 @@ int uvc_ctrl_set(struct uvc_fh *handle, ctrl->info.size); } - mapping->set(mapping, value, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + switch (mapping->data_type) { + case UVC_CTRL_DATA_TYPE_RECT: + memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT) + + mapping->offset / 8, + &uvc_rect, sizeof(uvc_rect)); + break; + default: + mapping->set(mapping, value, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + } if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS) ctrl->handle = handle; diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 711556d13d03..a88d3fe6de93 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1038,17 +1038,15 @@ 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) { + if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL || + ctrls->which == V4L2_CTRL_WHICH_MIN_VAL || + ctrls->which == V4L2_CTRL_WHICH_MAX_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(chain, ctrl, ctrls->which); if (ret < 0) { ctrls->error_idx = i; return ret; } - - ctrl->value = qc.default_value; } return 0; @@ -1059,7 +1057,7 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, return ret; for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_get(chain, ctrl); + ret = uvc_ctrl_get(chain, ctrl, ctrls->which); if (ret < 0) { uvc_ctrl_rollback(handle); ctrls->error_idx = i; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 143230b3275b..f414ad7d57b2 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -424,6 +424,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, @@ -897,7 +904,8 @@ static inline int uvc_ctrl_rollback(struct uvc_fh *handle) return __uvc_ctrl_commit(handle, 1, NULL); } -int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl); +int uvc_ctrl_get(struct uvc_video_chain *chain, 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); 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..d7d77602a5e7 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) From patchwork Wed May 18 06:24:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 574062 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 9F0F4C433F5 for ; Wed, 18 May 2022 06:25:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231297AbiERGZK (ORCPT ); Wed, 18 May 2022 02:25:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231288AbiERGZH (ORCPT ); Wed, 18 May 2022 02:25:07 -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 B8325D4104 for ; Tue, 17 May 2022 23:25:06 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id i17-20020a259d11000000b0064cd3084085so1073364ybp.9 for ; Tue, 17 May 2022 23:25:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=IL247PX6DIraKPCB4Qq4FB+o6HNS1RKeiQ6Tz/uvjRQ=; b=FdxeR+8skMynSecmFetvLVn67Fcw6lsg9c8nc7s2TSvLKG4ZrTG3v0h0c9nhwIjmBE Y8IP8ZLZwHsMBVL4fPpzHjE6enWFHhXlwIhBTgcu0X+SWhKmevc8cYdSjaErAsAhWHa7 Sxd98lMF246Z6KyxpC3azJHrZZgkhmYL0QVabLrHAh1lysi+L/u+bdTP0Va/UL0FZhwv X0PD6H60LU3f3a3Vn8MAnyq3tJfdB9itWEKUHIkkI/2CVTx0RY1gPZSkwt9nJ5DqzDwA DDPuwQkSxInnLGyzipmBmQPIvHjyU6ahF30dnRCN5nwSDfhlbEELd/H54aKfbtlMcnRO +QAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=IL247PX6DIraKPCB4Qq4FB+o6HNS1RKeiQ6Tz/uvjRQ=; b=xwEX3ox5xR24EExVOCS9hkZHkKLWaj7R0qAn51jteRqiH7fxeGKVVi/KilnbFqbgT5 63g8bTCQ4zwK93rqYl82K07/DLO1rasaSjcZxILl2u6SjUa/DSk7wCjrVDT6uNyGo8Gn e53T9d9K/F3Cm+t6IbLcQ4BNqvwT6iPz63sYTeUKZT5lbTkfXNasABeGurQRCNO5Sr/V BAJAKW0uKqhsVnb6EHuvReUu/r73JqszoGk7XWXydmTzpKg/ev4t/ZMjMbtpDtR+nl+d QtzY5gTo5+sVBlLwinifwJHacbpqtGg14b6b5i5B1lWBWFMFCXwwcS59gygH95+eHtH5 Ttog== X-Gm-Message-State: AOAM530Cr7VV5Gosnprvmnr7tyqJFHRqr3Z+y5oG6nkq+5BQdrAjbiiy UUtvH8f5uz+uKh9yhM/I3gF+1F4u8Jc= X-Google-Smtp-Source: ABdhPJw9C7pZGG4d0mBb5yg4XC7baOuBg8BA07JJ5Kl87enb+uEwdsrQ401Dyorm5sx9BkvdySoFdMeUgac= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:d4d4:2a73:fa69:7d32]) (user=yunkec job=sendgmr) by 2002:a25:2488:0:b0:64e:a74d:fc7e with SMTP id k130-20020a252488000000b0064ea74dfc7emr399038ybk.563.1652855105948; Tue, 17 May 2022 23:25:05 -0700 (PDT) Date: Wed, 18 May 2022 15:24:12 +0900 In-Reply-To: <20220518062412.2375586-1-yunkec@google.com> Message-Id: <20220518062412.2375586-7-yunkec@google.com> Mime-Version: 1.0 References: <20220518062412.2375586-1-yunkec@google.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog Subject: [PATCH v3 6/6] media: vivid: Add a roi rectangle control From: Yunke Cao To: Hans Verkuil , Laurent Pinchart , Nicolas Dufresne Cc: 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 The control supports current, default, minimum and maximum. Tested by calling ioctls from the user space. Signed-off-by: Yunke Cao --- .../media/test-drivers/vivid/vivid-ctrls.c | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/media/test-drivers/vivid/vivid-ctrls.c b/drivers/media/test-drivers/vivid/vivid-ctrls.c index e7516dc1227b..79093882d386 100644 --- a/drivers/media/test-drivers/vivid/vivid-ctrls.c +++ b/drivers/media/test-drivers/vivid/vivid-ctrls.c @@ -34,6 +34,7 @@ #define VIVID_CID_U8_4D_ARRAY (VIVID_CID_CUSTOM_BASE + 10) #define VIVID_CID_AREA (VIVID_CID_CUSTOM_BASE + 11) #define VIVID_CID_RO_INTEGER (VIVID_CID_CUSTOM_BASE + 12) +#define VIVID_CID_RECT (VIVID_CID_CUSTOM_BASE + 13) #define VIVID_CID_VIVID_BASE (0x00f00000 | 0xf000) #define VIVID_CID_VIVID_CLASS (0x00f00000 | 1) @@ -292,6 +293,38 @@ static const struct v4l2_ctrl_config vivid_ctrl_area = { .p_def.p_const = &area, }; +static const struct v4l2_rect def_rect = { + .left = 0, + .top = 0, + .width = 1000, + .height = 2000, +}; + +static const struct v4l2_rect min_rect = { + .left = 0, + .top = 0, + .width = 1, + .height = 2, +}; + +static const struct v4l2_rect max_rect = { + .left = 0, + .top = 0, + .width = 2000, + .height = 4000, +}; + +static const struct v4l2_ctrl_config vivid_ctrl_rect = { + .ops = &vivid_user_gen_ctrl_ops, + .id = VIVID_CID_RECT, + .name = "Region of Interest Rectangle", + .type = V4L2_CTRL_TYPE_RECT, + .p_def.p_const = &def_rect, + .p_min.p_const = &min_rect, + .p_max.p_const = &max_rect, +}; + + static const struct v4l2_ctrl_config vivid_ctrl_ro_int32 = { .ops = &vivid_user_gen_ctrl_ops, .id = VIVID_CID_RO_INTEGER, @@ -1611,6 +1644,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL); dev->ro_int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_ro_int32, NULL); v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_area, NULL); + v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_rect, NULL); v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL); v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL); v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);