From patchwork Tue Jun 28 07:57:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 585754 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 957B7CCA47E for ; Tue, 28 Jun 2022 07:57:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243166AbiF1H5n (ORCPT ); Tue, 28 Jun 2022 03:57:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52814 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245258AbiF1H5e (ORCPT ); Tue, 28 Jun 2022 03:57:34 -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 F248615FCC for ; Tue, 28 Jun 2022 00:57:33 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id z188-20020a2565c5000000b0066c086258ddso9243435ybb.9 for ; Tue, 28 Jun 2022 00:57:33 -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=OqDXLLw2gE6LQdAoQryltTRk36RdCADaFwUGEHVSOFw=; b=lvx8Eq2c2z7wJL13ExsGRrVD+J5W7bjUHw8XK27bKlM6dNf1HfnltTuJQ5vnnItG1F P1H2saKf+Ae/+2Njq9XarXNmSY1p0BJVJjh0ELTTzsmS+IFe4b+OefY6IRa+pZ6GNKYn oLUcQEyGuuov9X0Kg5ConWElpc0tQpzUtDKvCGhAiDED04As+QwZxEj/D1qsFDw18GbP YwyaXyYprxbqtTUjC3MQMrCyqjHt/6tiGgbeT6QKd10LriQb+bPy0IrxZJ43qN9Vqfn5 LcN492aJB+n91BkgdSr7oRwAuQXXreIP8mwNJOtllC+sq7yNsiFnteRMfUWxcMY01plw /Q5g== 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=OqDXLLw2gE6LQdAoQryltTRk36RdCADaFwUGEHVSOFw=; b=xz78qV4m5b9NEjl5hC5J9jUfpQB79dUTEH22G9sugYpWXO+dt8jQChTB+xgVKL7ObI NOWCvOwipFHvN6K2MHAckCuFG1akOspbq6Ts75AuuOHcUU46nilzRVO2meuuUyAcxhZB +DkKq/Mb4xyoOtNBNY2b4Bj0yq5P6ueByq/Y5z4iO/Sw3CIcckc8RRf18X5TK3slT0Po 4GUZ/I+jUSyMZrUw2w9YLGnbvV4ACyd3IefmzGTFpTLyLfpLGc5BpCS+9XhzkqLSY6yo A7zZgddbfmGxhtFqmY4HFv5Pypvs/2ZDMVWY7hk1PY60h3Jl/jk0jjZDBO4+cK4sKeU7 Jg1w== X-Gm-Message-State: AJIora/Q3a2O3pQdO41g1n6itnyheCzcVPZPKe6Ed/WePPF2ExUUJL1p dQU0E9D3uB1oPoPY6RH7D6ai06WYBm4= X-Google-Smtp-Source: AGRyM1s6eRUV406pXEDDD57cJuAJRvis8QgsmqE6fK30UleksKv+k/BrCuMrWwRHTaI/ZIVhJTgfLHWKnfU= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:983d:14d6:e059:135f]) (user=yunkec job=sendgmr) by 2002:a05:6902:1186:b0:64e:b02c:4f99 with SMTP id m6-20020a056902118600b0064eb02c4f99mr17855922ybu.165.1656403053324; Tue, 28 Jun 2022 00:57:33 -0700 (PDT) Date: Tue, 28 Jun 2022 16:57:00 +0900 In-Reply-To: <20220628075705.2278044-1-yunkec@google.com> Message-Id: <20220628075705.2278044-3-yunkec@google.com> Mime-Version: 1.0 References: <20220628075705.2278044-1-yunkec@google.com> X-Mailer: git-send-email 2.37.0.rc0.161.g10f37bed90-goog Subject: [PATCH v7 2/7] media: uvcvideo: add uvc_ctrl_get_fixed for getting default value From: Yunke Cao To: Hans Verkuil , Laurent Pinchart , Nicolas Dufresne , Mauro Carvalho Chehab 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 Introduce a new uvc_ctrl_get_fixed. It simply calls query_v4l2_ctrl() for now, but is easier to extend to support compound controls and V4L2_CTRL_WHICH_MIN/MAX_VAL in the following patches. Reviewed-by: Ricardo Ribalda Signed-off-by: Yunke Cao --- drivers/media/usb/uvc/uvc_ctrl.c | 13 +++++++++++++ drivers/media/usb/uvc/uvc_v4l2.c | 6 +----- drivers/media/usb/uvc/uvcvideo.h | 2 ++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 0e78233fc8a0..772d9d28a520 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1697,6 +1697,19 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); } +int uvc_ctrl_get_fixed(struct uvc_video_chain *chain, + struct v4l2_ext_control *xctrl) +{ + struct v4l2_queryctrl qc = { .id = xctrl->id }; + int ret = uvc_query_v4l2_ctrl(chain, &qc); + + if (ret < 0) + return ret; + + xctrl->value = qc.default_value; + return 0; +} + 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 648dcd579e81..0366d05895a9 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1042,15 +1042,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_fixed(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 c5b4febd2d94..ba028ba7c34e 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -901,6 +901,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_fixed(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 Jun 28 07:57:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 585753 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 89CB6C433EF for ; Tue, 28 Jun 2022 07:58:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243087AbiF1H6E (ORCPT ); Tue, 28 Jun 2022 03:58:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52970 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243551AbiF1H5p (ORCPT ); Tue, 28 Jun 2022 03:57:45 -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 3394313FA7 for ; Tue, 28 Jun 2022 00:57:44 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-31ba792c793so46924127b3.20 for ; Tue, 28 Jun 2022 00:57:44 -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:content-transfer-encoding; bh=aIbHKbVVcaZVM4752YjpEFdZQCRYFrEKvf1iqr1v6tU=; b=oydepxdL9EIhOyT5K3L5QeA343Lx3DF8Irejv8eqsq3/bc8so60fhsTQgZbd6nLC1s XuniwmgfE1TU28yCEj2OieNEwPcRv91aSSThdyLieCBieedd3atoqFYd+u4P8mwoq/LK qrS0lsVZlsNm/n0Q9lbjz24CzVIN2KBeTzzU86/gO/aHYv0JAFQcv6RTD5QE0iifZV+1 mFk0c+J5xxV3yAAW48fBHgu+LUwIJTQDN4cF4U1iU2NBnH474yZHctw2xPk8VOhSp1dQ 4hQnZueRqekvFesibX1K2qCuxdquuAuHOHC59b6KbvIoJTrAbHGbe8KE8hsCCXLa7FPb ljXQ== 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:content-transfer-encoding; bh=aIbHKbVVcaZVM4752YjpEFdZQCRYFrEKvf1iqr1v6tU=; b=J484YFp9EcqF51EHzbxCieBtIIGQHB9MtdDIHQS+80aADkAzBtOb47Tdb0FY8IiEUJ bCGoo1jaA58oIfzrvspjxdT1OFgx+YW4Hlc1mTlqpPbSkFNQMVBUlyGtKBmXpPv4FeSD bPCAShHzWlfXS3IiRlMuASVwgEH50GieJYPI7XhQfi0Kw1gVc4j/2s0Fd4qplwqDRp3D WzeMUYDhPoAI2IEgSgcI5anrG9CxxpqoDjmFJWjVrRMEN5eaXtypfy4P7u/83yKjn0y/ U8xPJpbp0bM6O3JYJsZor8pJQWNbwMNi5LRzWZ/fuNvMvXQGnUnauqa7+Wd8r1op79f+ lTPA== X-Gm-Message-State: AJIora8uPrwDHLskCnRA/Tc8LVw1eDbNcH3EdD3XUr0mAig++b8ifHxN 2s7vE4eWuWpSAQS2W3bn7wJvx0P0OMo= X-Google-Smtp-Source: AGRyM1tIowpdcqdpLuYbwAevXdRvy74xHNPctloEva3gHz6Xql2Qf7Cl9gYrDFed21UMy7D8XSxIMF1l4bI= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:983d:14d6:e059:135f]) (user=yunkec job=sendgmr) by 2002:a81:990f:0:b0:2f8:c347:d11a with SMTP id q15-20020a81990f000000b002f8c347d11amr20012421ywg.507.1656403063541; Tue, 28 Jun 2022 00:57:43 -0700 (PDT) Date: Tue, 28 Jun 2022 16:57:02 +0900 In-Reply-To: <20220628075705.2278044-1-yunkec@google.com> Message-Id: <20220628075705.2278044-5-yunkec@google.com> Mime-Version: 1.0 References: <20220628075705.2278044-1-yunkec@google.com> X-Mailer: git-send-email 2.37.0.rc0.161.g10f37bed90-goog Subject: [PATCH v7 4/7] media: uvcvideo: implement UVC v1.5 ROI From: Yunke Cao To: Hans Verkuil , Laurent Pinchart , Nicolas Dufresne , Mauro Carvalho Chehab 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 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 --- drivers/media/usb/uvc/uvc_ctrl.c | 146 ++++++++++++++++++++++++++++- 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 | 8 ++ 6 files changed, 178 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 508ee04afbcd..00482269233a 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -355,6 +355,23 @@ 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[] = { @@ -429,6 +446,64 @@ static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping, data[first+1] = min_t(int, abs(value), 0xff); } +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->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_array_rect(struct uvc_control_mapping *mapping, + const u8 *data, u8 *data_out) +{ + struct uvc_rect *uvc_rect; + + if (WARN_ON(mapping->offset % 8 || mapping->size % 8)) + return -EINVAL; + if (WARN_ON(mapping->size / 8 != sizeof(struct uvc_rect))) + return -EINVAL; + + uvc_rect = (struct uvc_rect *)(data + mapping->offset / 8); + uvc_to_v4l2_rect((struct v4l2_rect *)data_out, uvc_rect); + + return 0; +} + +static int uvc_set_array_rect(struct uvc_control_mapping *mapping, + const u8 *data_in, u8 *data) +{ + struct uvc_rect *uvc_rect; + + if (WARN_ON(mapping->offset % 8 || mapping->size % 8)) + return -EINVAL; + if (WARN_ON(mapping->size / 8 != sizeof(struct uvc_rect))) + return -EINVAL; + + 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, @@ -728,6 +803,26 @@ 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, + .size = 64, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_RECT, + .data_type = UVC_CTRL_DATA_TYPE_RECT, + .get_array = uvc_get_array_rect, + .set_array = uvc_set_array_rect, + }, + { + .id = V4L2_CID_UVC_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, + }, }; /* ------------------------------------------------------------------------ @@ -1061,7 +1156,16 @@ static int __uvc_ctrl_get_compound_to_user(struct uvc_control_mapping *mapping, if (WARN_ON(!mapping->size % 8)) return -EINVAL; - size = mapping->size / 8; + switch (mapping->v4l2_type) { + case V4L2_CTRL_TYPE_RECT: + size = sizeof(struct v4l2_rect); + break; + + default: + size = mapping->size / 8; + break; + } + if (xctrl->size < size) { xctrl->size = size; return -ENOSPC; @@ -2578,6 +2682,40 @@ static void uvc_ctrl_prune_entity(struct uvc_device *dev, } } +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_CURRENT 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; +} + /* * Add control information and hardcoded stock control mappings to the given * device. @@ -2590,6 +2728,7 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, const struct uvc_control_mapping *mapping = uvc_ctrl_mappings; const struct uvc_control_mapping *mend = mapping + ARRAY_SIZE(uvc_ctrl_mappings); + const u8 camera_entity[16] = UVC_GUID_UVC_CAMERA; /* XU controls initialization requires querying the device for control * information. As some buggy UVC devices will crash when queried @@ -2610,6 +2749,11 @@ 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 (ctrl->info.selector == + UVC_CT_REGION_OF_INTEREST_CONTROL && + uvc_entity_match_guid(ctrl->entity, camera_entity)) + uvc_ctrl_init_roi(chain->dev, ctrl); break; } } diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 0366d05895a9..aad61af36271 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -998,7 +998,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 2f9b75faae83..9ff95bbad251 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -431,6 +431,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..e2feee15cb1b 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 private 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 dfff69ed88f7..d85be46e46f2 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1013,6 +1013,14 @@ 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 16 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 Jun 28 07:57:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yunke Cao X-Patchwork-Id: 585752 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 B63B2C433EF for ; Tue, 28 Jun 2022 07:58:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243310AbiF1H6c (ORCPT ); Tue, 28 Jun 2022 03:58:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53964 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243514AbiF1H6V (ORCPT ); Tue, 28 Jun 2022 03:58:21 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4AAE022B3F for ; Tue, 28 Jun 2022 00:57:54 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id li4-20020a17090b48c400b001eeec855ae1so1879048pjb.3 for ; Tue, 28 Jun 2022 00:57: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=BVnCtq4DRmPQW5iFurXbHjb7kWgxbL0xarKsJFp9Ck4=; b=TS+p2JsiWhwAX2uA9migG+CHniNgSrHwwCQlyxfVdeJ59DiYoRpF8XqKj8d3mgssCG eWGb/VCsW4AS2af9wSNocj/PthX6495Ku/1j2jaexJ6VELKY2kPqcuitLNwk/864DEaq WfuPKSyZpnh5EePAwW9MRiBo2V67SpAmLs58DcfUwPXmj6wvUCrOJC0jgg/jAjolNA2K fFM+GUwElrurc6T7brts50eG5GJtAAapJ+t8+NL9HCAPusdTq7yG+Z/MRbaNhhFw2Lrv hBh9x6L1R5sFOqoTWkYigixwyu4wjbptdrACjuMLv8faUXvTxgVhLWRap/4F65Lke+Ma vpyQ== 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=BVnCtq4DRmPQW5iFurXbHjb7kWgxbL0xarKsJFp9Ck4=; b=EDvhrgfDNuGqVE54KbhzwokP3pCRqpWx0UJk5uNmBegaFjCUGNSmxieRzhTxtUEddb nGUCjG5TEazdSop7yp0ACQKqo1nygJJcu/4UBVGKCI6fkSLMeHjFPcEEcf2FjVt9Mmvz eWcxAIUf+lW1Oj1R4hJw9VYBB0qnd+LNjvPfnyOawvCgS3fWGQmtZDpuCi/cqRRIat3n 29Fm59WGMSQo6N5vHsmJgZ9ndYKiVvNwZN/VuRkNqvOgYy5nX+RAjr31lv0RvamQOagj mYvk/ZUGoxyOz2XVJaGkScxSSMtT0UXfUyTWkujT1UfsxKzdFE8fVUYLFyWEK0Y1m64t svdg== X-Gm-Message-State: AJIora+P2yp0zusa23GRSrID7ut22L6TOeZosfVDZI0g8oEg+I5TF64M k+JP5btyottoNKv5JwGcxfcTNDX2Shs= X-Google-Smtp-Source: AGRyM1v2n//BOzFWYUoP9dCqHyfTQakFN+97p2nIduvFwMUfVNKjEaGtygMXMm3GJh+Tf39cEzwBAOCpQLI= X-Received: from yunkec1.tok.corp.google.com ([2401:fa00:8f:203:983d:14d6:e059:135f]) (user=yunkec job=sendgmr) by 2002:a17:902:7105:b0:168:dfe3:66e0 with SMTP id a5-20020a170902710500b00168dfe366e0mr3715978pll.88.1656403073833; Tue, 28 Jun 2022 00:57:53 -0700 (PDT) Date: Tue, 28 Jun 2022 16:57:04 +0900 In-Reply-To: <20220628075705.2278044-1-yunkec@google.com> Message-Id: <20220628075705.2278044-7-yunkec@google.com> Mime-Version: 1.0 References: <20220628075705.2278044-1-yunkec@google.com> X-Mailer: git-send-email 2.37.0.rc0.161.g10f37bed90-goog Subject: [PATCH v7 6/7] media: uvcvideo: support V4L2_CTRL_WHICH_MIN/MAX_VAL From: Yunke Cao To: Hans Verkuil , Laurent Pinchart , Nicolas Dufresne , Mauro Carvalho Chehab 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 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 --- drivers/media/usb/uvc/uvc_ctrl.c | 73 ++++++++++++++++++++++++++------ drivers/media/usb/uvc/uvc_v4l2.c | 11 +++-- drivers/media/usb/uvc/uvcvideo.h | 3 +- 3 files changed, 70 insertions(+), 17 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 00482269233a..b569d6824ac1 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1923,7 +1923,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain, } int __uvc_ctrl_get_fixed_std(struct uvc_video_chain *chain, - struct v4l2_ext_control *xctrl) + struct v4l2_ext_control *xctrl, u32 v4l2_which) { struct v4l2_queryctrl qc = { .id = xctrl->id }; int ret = uvc_query_v4l2_ctrl(chain, &qc); @@ -1931,16 +1931,69 @@ int __uvc_ctrl_get_fixed_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; + default: + return -EINVAL; + } + return 0; } +static int __uvc_ctrl_get_fixed_compound(struct uvc_video_chain *chain, + struct uvc_control_mapping *mapping, + struct uvc_control *ctrl, + u32 v4l2_which, + struct v4l2_ext_control *xctrl) +{ + int ret; + u32 flag, id; + + if (mapping->v4l2_type < V4L2_CTRL_COMPOUND_TYPES) + 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; + default: + return -EINVAL; + } + + if (!(ctrl->info.flags & flag) && flag != UVC_CTRL_FLAG_GET_DEF) + return -EACCES; + + if (!ctrl->cached) { + ret = uvc_ctrl_populate_cache(chain, ctrl); + if (ret < 0) + return ret; + } + + return __uvc_ctrl_get_compound_to_user(mapping, ctrl, id, xctrl); +} + int uvc_ctrl_get_fixed(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; if (__uvc_query_v4l2_class(chain, xctrl->id, 0) >= 0) return -EACCES; @@ -1950,16 +2003,10 @@ int uvc_ctrl_get_fixed(struct uvc_video_chain *chain, return -EINVAL; if (mapping->v4l2_type < V4L2_CTRL_COMPOUND_TYPES) - return __uvc_ctrl_get_fixed_std(chain, xctrl); + return __uvc_ctrl_get_fixed_std(chain, xctrl, v4l2_which); - if (!ctrl->cached) { - ret = uvc_ctrl_populate_cache(chain, ctrl); - if (ret < 0) - return ret; - } - - return __uvc_ctrl_get_compound_to_user(mapping, ctrl, UVC_CTRL_DATA_DEF, - xctrl); + return __uvc_ctrl_get_fixed_compound(chain, mapping, ctrl, v4l2_which, + xctrl); } int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping, diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index aad61af36271..004e3b764737 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1043,16 +1043,21 @@ 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_fixed(chain, ctrl); + ret = uvc_ctrl_get_fixed(chain, ctrl, ctrls->which); if (ret < 0) { ctrls->error_idx = i; return ret; } } - return 0; + + default: + break; } ret = uvc_ctrl_begin(chain); diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 9ff95bbad251..54cc47bc2d33 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -913,7 +913,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_fixed(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);