From patchwork Wed Sep 21 09:12:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 608126 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 5D03BECAAD8 for ; Wed, 21 Sep 2022 09:12:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230326AbiIUJMh (ORCPT ); Wed, 21 Sep 2022 05:12:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230073AbiIUJMg (ORCPT ); Wed, 21 Sep 2022 05:12:36 -0400 Received: from mail-ej1-x630.google.com (mail-ej1-x630.google.com [IPv6:2a00:1450:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F3D318C471 for ; Wed, 21 Sep 2022 02:12:34 -0700 (PDT) Received: by mail-ej1-x630.google.com with SMTP id sd10so3756530ejc.2 for ; Wed, 21 Sep 2022 02:12:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date; bh=7SbWdOzYyZ4DvXywVbhtnQssUKjn+mgaC4ezA3WwW3o=; b=YijMFEwnZJDizWX0f+eH3pCP+PWv7I8ClvZqfqQGbyTBg+SvtkVyjU+P/WvwbEE50S +NMSIRy+dcM8bTM+wYAEYkmvlr62VDaH4EORp+cAmhjRqroexl8TKoEEkfPCBirUHQQq 2nk1JtH8nEHYdjTzZelWVV5p/wOPvnz5WuvUQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date; bh=7SbWdOzYyZ4DvXywVbhtnQssUKjn+mgaC4ezA3WwW3o=; b=M0uPOnxQ/qB6WUG/z248qpMiwjlUoa2rAjchYaDt21CVIwaZWem684wMmbFIa0yqdu SHANV2tyMHxjnU5NOVBRhX9qawSk1l3jt+fyVZtZIYoRfat6IdKaeaMBKFeI2jPAhbwf JRlBuik1E+k+ITYBM7xlJEhi8ABSegY5WHGp/2Ur/KtGRUMLP45GlROh8qLFsOBHooEe koJ30wVl+t92Gc8Jav/p4GGPIgBU36flnMBocNkitrpVedHEI9c9kr6TTh1SKpFxjwDN m6cLYarGtNHS8EjkN6P+CA7BNI04KnH+g1yBThz50D9PtLamvwZnLQ4GkknsiFhLrrWL hO4g== X-Gm-Message-State: ACrzQf3pyPrsi/u5WkVVIRHhFIOd7rfs5x0XNEkcopVJvq7FWik1YNxD b888BqG5zaA3OKCm6zk1yxQJug== X-Google-Smtp-Source: AMsMyM6wc3c0+orkPQiXhGroUrR/GRGODLFbNoe8tE5I0NOINNXOXlik+5dSr3v4pts5Z1EB9057ZQ== X-Received: by 2002:a17:906:fd82:b0:770:7e61:3707 with SMTP id xa2-20020a170906fd8200b007707e613707mr19611883ejb.143.1663751553499; Wed, 21 Sep 2022 02:12:33 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:160b:cee7:2e8b:f72c]) by smtp.gmail.com with ESMTPSA id v4-20020a17090690c400b00771cb506149sm1031913ejw.59.2022.09.21.02.12.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Sep 2022 02:12:33 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 21 Sep 2022 11:12:10 +0200 Subject: [PATCH v2 1/7] media: uvcvideo: uvc_ctrl_is_accessible: check for INACTIVE MIME-Version: 1.0 Message-Id: <20220920-resend-v4l2-compliance-v2-1-7c0942040004@chromium.org> References: <20220920-resend-v4l2-compliance-v2-0-7c0942040004@chromium.org> In-Reply-To: <20220920-resend-v4l2-compliance-v2-0-7c0942040004@chromium.org> To: Mauro Carvalho Chehab Cc: Laurent Pinchart , linux-media@vger.kernel.org, Hans Verkuil , Ricardo Ribalda , linux-kernel@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=5006; i=ribalda@chromium.org; h=from:subject:message-id; bh=xRue/wJ3pUDw9TYU7ZEzphzigf/XRMvyyhrkUV+XLC0=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjKtV1Mb5wbPhj9MC58ku5ntzQRAlRcyVv7zWahjM8 r72EY9OJAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCYyrVdQAKCRDRN9E+zzrEiEfAD/ 48ZhGIcYGmGxqiQ9n40ihVBvUK3jJ5KfCOYT746WdTq+vT7eQg0JAwOlmXpgIDYIvA2mZ+jIKKqh4s S9ERooFZUEtDxxTiNZIwFbPfJ6AcYWK/qzkK3qmo/j2u7WPN2m3XAal0Ne/h1ENt9KbZxJkdHYHJfE s0Zt1F5zv3W562TVf3gfjqwtZ0icqgUCFcFlkFo6qKssvpxxiXw0/GPwWcc4oIY5Ztu8z4KYU8SNaF o0fy5HTn3hzw89cygG/v9/Jo+pckc1PZ+UTQrmtL9DM6sfsR7yQ857Ojbx37W19BGJv9jG/KN3/Pa5 hJRFaIicwCRKIMmOqYLxPcO8/37lazhxmNpmXAFHzl6nwCQNiueLFnFwfAEZara8dkBICWbZnFrkXg ke8rsUfY1mupBQgrzGs5vHashKNrBT9IM+wWrORTgdTFTj7Gk84efHFbsZylQPPzWU3GVVM1s7p9np cX3xpAiQ89KXf8nyR5j/fx2FFCFK9o5r+PRhbpmWetUKvrF8/Lvq2b44jc93W/ye5Enw9vCaSDv7MS AFxdNN9dfdrH6aRey1HaFyPj1hgGHl9HXnS9edAA97785Ym9KHDeoCrnFsMT1jUChF0zf/FtVF1/5f IfFk8gaeJdxv4p3xwT5tX2U5kRoBG5A1oqn2tpTG3z6jJW1HFA8Vgd464pYQ== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil Check for inactive controls in uvc_ctrl_is_accessible(). Use the new value for the master_id controls if present, otherwise use the existing value to determine if it is OK to set the control. Doing this here avoids attempting to set an inactive control, which will return an error from the USB device, which returns an invalid errorcode. This fixes: warn: v4l2-test-controls.cpp(483): s_ctrl returned EIO   warn: v4l2-test-controls.cpp(483): s_ctrl returned EIO test VIDIOC_G/S_CTRL: OK   warn: v4l2-test-controls.cpp(739): s_ext_ctrls returned EIO   warn: v4l2-test-controls.cpp(739): s_ext_ctrls returned EIO   warn: v4l2-test-controls.cpp(816): s_ext_ctrls returned EIO test VIDIOC_G/S/TRY_EXT_CTRLS: OK Tested with: v4l2-ctl -c auto_exposure=1 OK v4l2-ctl -c exposure_time_absolute=251 OK v4l2-ctl -c auto_exposure=3 OK v4l2-ctl -c exposure_time_absolute=251 VIDIOC_S_EXT_CTRLS: failed: Input/output error exposure_time_absolute: Input/output error ERROR v4l2-ctl -c auto_exposure=3,exposure_time_absolute=251,auto_exposure=1 v4l2-ctl -C auto_exposure,exposure_time_absolute   auto_exposure: 1 exposure_time_absolute: 251 Reviewed-by: Ricardo Ribalda Signed-off-by: Hans Verkuil diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 8c208db9600b..7153ee5aabb1 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1064,11 +1064,33 @@ static int uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id, return 0; } +/** + * uvc_ctrl_is_accessible() - Check if a control can be read/writen/tried. + * @chain: uvc_video_chain that the controls belong to. + * @v4l2_id: video4linux id of the control. + * @ctrl: Other controls that will be accessed in the ioctl. + * @ioctl: ioctl used to access the control. + * + * Check if a control can be accessed by a specicific ioctl operation, + * assuming that other controls are also going to be accessed by that ioctl. + * We need to check the value of the other controls, to support operations + * where a master value is changed with a slave value. Eg. + * auto_exposure=1,exposure_time_absolute=251 + * + */ int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, - bool read) + const struct v4l2_ext_controls *ctrls, + unsigned long ioctl) { + struct uvc_control_mapping *master_map = NULL; + struct uvc_control *master_ctrl = NULL; struct uvc_control_mapping *mapping; struct uvc_control *ctrl; + bool read = ioctl == VIDIOC_G_EXT_CTRLS; + bool try = ioctl == VIDIOC_TRY_EXT_CTRLS; + s32 val; + int ret; + int i; if (__uvc_query_v4l2_class(chain, v4l2_id, 0) >= 0) return -EACCES; @@ -1083,6 +1105,29 @@ int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id, if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) && !read) return -EACCES; + if (read || try || !mapping->master_id) + return 0; + + /* + * Iterate backwards in cases where the master control is accessed + * multiple times in the same ioctl. We want the last value. + */ + for (i = ctrls->count - 1; i >= 0; i--) { + if (ctrls->controls[i].id == mapping->master_id) + return ctrls->controls[i].value == + mapping->master_manual ? 0 : -EACCES; + } + + __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)) + return 0; + + ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val); + if (ret >= 0 && val != mapping->master_manual) + return -EACCES; + return 0; } diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 4cc3fa6b8c98..d95168cdc2d1 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1020,8 +1020,8 @@ static int uvc_ctrl_check_access(struct uvc_video_chain *chain, int ret = 0; for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_is_accessible(chain, ctrl->id, - ioctl == VIDIOC_G_EXT_CTRLS); + ret = uvc_ctrl_is_accessible(chain, ctrl->id, ctrls, + ioctl); if (ret) break; } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 24c911aeebce..644d5fcf2eef 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -905,7 +905,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_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); + const struct v4l2_ext_controls *ctrls, + unsigned long ioctl); int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control_query *xqry); From patchwork Wed Sep 21 09:12:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 608125 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 78FF5C6FA8B for ; Wed, 21 Sep 2022 09:12:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230409AbiIUJMl (ORCPT ); Wed, 21 Sep 2022 05:12:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41120 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229974AbiIUJMi (ORCPT ); Wed, 21 Sep 2022 05:12:38 -0400 Received: from mail-ej1-x633.google.com (mail-ej1-x633.google.com [IPv6:2a00:1450:4864:20::633]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D8EFB8C471 for ; Wed, 21 Sep 2022 02:12:36 -0700 (PDT) Received: by mail-ej1-x633.google.com with SMTP id y17so12143161ejo.6 for ; Wed, 21 Sep 2022 02:12:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date; bh=fZx/rWrR7bth2k3zX90922HeFwXDXF4+XRCwzM0uxDU=; b=XTQI0onfMaHBbtdQRuQf8MDtTygrDqa/VSdYaoxUM+eeXFUGyDA4s6uMV+EW6KJZVE 4uA4zUWou6VgpnP1jfM+PNq4tAyqOnwdltiKlX5aFCmI0O9TiZl0uazpwsZO09h8+dOD 5vsyWR64mnxxsJvirPzNyf7n0gsEcZmXYABL4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date; bh=fZx/rWrR7bth2k3zX90922HeFwXDXF4+XRCwzM0uxDU=; b=2IziVdlAqN3RW77wndmIU2atHzWkganitwYBoo1zWFPTqE51EsYOmfyr+/lbrVIva6 x1+erIn0+iORn8qg8l4OD8NxSesaveGhgJKqY1fXiaJfDmNZiV6nSY3wB2XIkiODsKpJ 5K6QyYFlsyUYd4An7tfKr3KWzlaJ58AWvQHKXHmqMYQ8Md82j4Lte4SJy3D/z2qFkBAI lyNIS4u126clSh/bqTui66EXuMWlXQMJkvoC2im+vZq9XAYoU+AxpDo0SwqgKmbYa6uO t2nUCfzozYaVDhf0tqB81YZ/zc20+UpECInDV2NzJ5hijZ0i1B9lfsIsfQsKXngJY1N2 XGlg== X-Gm-Message-State: ACrzQf0OvR5nvpIfzDJU2tPEn2R1WSWz/yLctU3sHSzWMGKQj/pqx0mo bImBup3OA/jwkyjNI5GhAwR3xw== X-Google-Smtp-Source: AMsMyM5C5U51pqKsCjwMiaIc9LnHXhy1k02TcRKZqYKkqXUVk0pBMQXu/uScAX+Mmnt0Zi0QsklyMg== X-Received: by 2002:a17:907:7293:b0:782:2665:aa39 with SMTP id dt19-20020a170907729300b007822665aa39mr588302ejc.303.1663751555406; Wed, 21 Sep 2022 02:12:35 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:160b:cee7:2e8b:f72c]) by smtp.gmail.com with ESMTPSA id v4-20020a17090690c400b00771cb506149sm1031913ejw.59.2022.09.21.02.12.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Sep 2022 02:12:35 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 21 Sep 2022 11:12:12 +0200 Subject: [PATCH v2 3/7] media: uvcvideo: Return -EACCES for Wrong state error MIME-Version: 1.0 Message-Id: <20220920-resend-v4l2-compliance-v2-3-7c0942040004@chromium.org> References: <20220920-resend-v4l2-compliance-v2-0-7c0942040004@chromium.org> In-Reply-To: <20220920-resend-v4l2-compliance-v2-0-7c0942040004@chromium.org> To: Mauro Carvalho Chehab Cc: Laurent Pinchart , linux-media@vger.kernel.org, Hans Verkuil , Ricardo Ribalda , linux-kernel@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=854; i=ribalda@chromium.org; h=from:subject:message-id; bh=l3Tve8hGJ5W5tTbag9O5QNFnAI00qvVi1fN45JRNTAM=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjKtV41S1sqbl3AcCGC0bbfcwzPIlmTH+3xTAvTXu1 WH5B4Y+JAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCYyrVeAAKCRDRN9E+zzrEiJZYD/ sHsPdAVHioOyDsFUawCfvmCQEtk3WOcmFioNVLGFFdB9Jw2J3myyLOCET3ojk3irhXmXIi5EyP5JK2 scg6aBpNHP+066OOhMwymngr1F74FEz/9Y6CD7oflu7DhUColNSr73o3e9X7j0Oba4tCX1YZktm3ty kbEB3a5STpzjlLMqSbE/SpRy5eQ64FKNexZGJc+ZGlOYREdEoHhVXU6Qv+eFRhDfmfyscZl5RVCuXJ pX5IyTiyS5fT5Pix82M/oXlpjWpZAUcMS8jKNTt3ZgFTVQ6djCI2yt9VR3qFY4uykkhz39rF28IBIt 9wD96ZzR+eldZq288z+b7Z/JJKBvX15VLztM8MHWzkf2IpoVv0qXp9h5P9KSTcv6pXq7Y5S8K7wS8i +CprRps6omD7uPJVDhDPJNavD+9rO7OrzBiwEyW2rWfybZEqWeQVnGwXsTfKjpdEPH3Tk9JiYAS1tM RV3pQgB06j+SBNFwYZfomyhwouzBzQtb6wSPTVFjBPspxK1N0Kwhn7zKirlqgQU2qkCwXTkJ1h9mQq NHS0+mKCAFZ2lB8KmOq/PkC2YSPMjjIpBjiVB9OjN7k0bhkA9Oo3aRr3B7A5ES1CcuQcfTXN/OJEkj NUdyF8a/2x7QVzGr6PjG24nKfveBBwsW3pTChO+e9MiWaW5EdAA8G8zIAtgA== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org For error 2 (Wrong state) return -EACCES instead of -EILSEQ. EACCES is a much more appropriate error code. EILSEQ will return "Invalid or incomplete multibyte or wide character." in strerror(), which is a *very* confusing message. Suggested-by: Hans Verkuil Signed-off-by: Ricardo Ribalda diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 2cf7f692c0bb..497073a50194 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -108,7 +108,7 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, case 1: /* Not ready */ return -EBUSY; case 2: /* Wrong state */ - return -EILSEQ; + return -EACCES; case 3: /* Power */ return -EREMOTE; case 4: /* Out of range */ From patchwork Wed Sep 21 09:12:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 608124 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 628FBC32771 for ; Wed, 21 Sep 2022 09:12:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231145AbiIUJMu (ORCPT ); Wed, 21 Sep 2022 05:12:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230402AbiIUJMk (ORCPT ); Wed, 21 Sep 2022 05:12:40 -0400 Received: from mail-ed1-x52a.google.com (mail-ed1-x52a.google.com [IPv6:2a00:1450:4864:20::52a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 970548E0E4 for ; Wed, 21 Sep 2022 02:12:38 -0700 (PDT) Received: by mail-ed1-x52a.google.com with SMTP id 29so7701178edv.2 for ; Wed, 21 Sep 2022 02:12:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date; bh=UQpZaYJCKWK0Pu7l712TNk2BJuL6CIWDc5YrLh30wjs=; b=MgXgDx//fd0NqwJytxhHSEaaNmr//wmBDBr0bEO3dLg66V/stnsiHXKtG46bTGVHcx yd/hN01VxmfOhhVLDUn9Nz1iNG6fiovULNK/htb/fwDk1EDecd+mvzveLnkCM+R9VU0A 51JCOXBeE1byB7GnjfwiBjzOaYDy7Yo9fGBKo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date; bh=UQpZaYJCKWK0Pu7l712TNk2BJuL6CIWDc5YrLh30wjs=; b=IgD/ddbbxE5CSEqPNg9nERtO9oBpIPhbbT7aIGUxJXyWCLnrvfXQOuLlHHOzq+GV3e BeL5qQTZSWwu9SV8j0a9AMrYYXK+6ZcoHt6Ge2euv+hA9z/oIUVejMljdjJ0DqUEP6YY l0Oz8wTKUpYvI+JDVqQnTjuc5D7Zium9NBIgN5W9ckuH068BsANdDDsAbP1Fg7BBoev8 xFz/Hy5Fv0IvYwEVHwYqIYusoi5X6xTz8dZrF+g/+vNtQs7C4ITwcwUPzM9qN3xgIKpS XnpOWyhxxa02alFLWqrhLvmSzBg+6iYPy+liLxRWuOaLqvihDwyKNsj58N2zIScoXKhK N6IQ== X-Gm-Message-State: ACrzQf1k9+tSySc8AJqDdwG/KmlBye0u4/8RSylrKKyuJYsnNcbdDjW8 NW/eQn4HTXcjGGeEfEsOSyF0mQ== X-Google-Smtp-Source: AMsMyM7muKLEbH6Q9UiO/fiHShwtGLWxRfl/6UH6w9rUIgVTIwfXxRFbMACiXwud2rsq7aZ9a1rGbg== X-Received: by 2002:aa7:ca50:0:b0:44e:973b:461e with SMTP id j16-20020aa7ca50000000b0044e973b461emr23671691edt.414.1663751556860; Wed, 21 Sep 2022 02:12:36 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:160b:cee7:2e8b:f72c]) by smtp.gmail.com with ESMTPSA id v4-20020a17090690c400b00771cb506149sm1031913ejw.59.2022.09.21.02.12.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Sep 2022 02:12:36 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 21 Sep 2022 11:12:14 +0200 Subject: [PATCH v2 5/7] media: uvcvideo: Fix handling on Bitmask controls MIME-Version: 1.0 Message-Id: <20220920-resend-v4l2-compliance-v2-5-7c0942040004@chromium.org> References: <20220920-resend-v4l2-compliance-v2-0-7c0942040004@chromium.org> In-Reply-To: <20220920-resend-v4l2-compliance-v2-0-7c0942040004@chromium.org> To: Mauro Carvalho Chehab Cc: Laurent Pinchart , linux-media@vger.kernel.org, Hans Verkuil , Ricardo Ribalda , linux-kernel@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=3891; i=ribalda@chromium.org; h=from:subject:message-id; bh=/j8z6PN7/Plr9CdgjDkkTYHlK0/ZUdYfEEIDx5PJha0=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjKtV7XWu1XTOSLsSuTXNJ12oJ1lLl4CG1/yGmfOPp dFsycSqJAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCYyrVewAKCRDRN9E+zzrEiLI8D/ 47MLxXYeeZ2bUqGtxERKbyJHuNsPThzQcMnXwfke15DM1fdQSCz3VmQNmJDt6HeJ9JzCcXzcfhsKw1 ZrSdvN6/3CJWK/seaPYR0+XzeS1+n2DnnrPTtBt8cH/BY7+Vkm2An8bkvNIWYVRBSHuBCw9tTJBnaU zARKsxKsrwn+dPOFj1ZMk8FB7M4YOT3xl1McBKxRJM04QOb/2zOAk0RHHtHwM0mbzTQshBFqlVUS3J Jtyui4IMIv4JlAL95sMPvEadvUNfLCGlUHgAAVaca8FZ9HwviEXJSTEquv86L7LGeXzPQ0i5w2MlJu wPrQfTb4zOFR97rhyWgxQ23BKGTMm7qZqkqAcj0yl0xnu8IYCg4uGSYIU0x/48G985XxwT5C9fzQsV BGLSYAhEHFe3HFfc/+92iEvIdhc0RxRSVABAoyTAuyu3sWttxBw43pLHignXeLyKlknGyBtTffTQwq WCjctyljkCsOkZPLUKTRWNcZTCWDXM237I+1b8aPSl378S3uHlihuKmvoe71EQxp1d/QMlSarvLxMF aS7zLZF1TbWlVDPk16yPfUAx0IXSXA3zbapH7Ye3YYP+NUdecixYDYy5LADJ5MgfCKfZhV7IzfWtie gSahxwFFY1DeqF9Ox52ehIcuiD9p7EQI3hmGkiXovpz96PdO2T0+CeOnSOWA== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Minimum and step values for V4L2_CTRL_TYPE_BITMASK controls should be 0. There is no need to query the camera firmware about this and maybe get invalid results. Also value should be masked to the max value advertised by the hardware. Finally, handle uvc 1.5 mask controls that use MAX instead of RES to describe the valid bits. Fixes v4l2-compliane: Control ioctls (Input 0): fail: v4l2-test-controls.cpp(97): minimum must be 0 for a bitmask control test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: FAIL Signed-off-by: Ricardo Ribalda diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 7153ee5aabb1..526572044e82 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1145,6 +1145,25 @@ static const char *uvc_map_get_name(const struct uvc_control_mapping *map) return "Unknown Control"; } +static u32 uvc_get_ctrl_bitmap(struct uvc_control *ctrl, + struct uvc_control_mapping *mapping) +{ + /* + * Some controls, like CT_AE_MODE_CONTROL use GET_RES to + * represent the number of bits supported, those controls + * do not list GET_MAX as supported. + */ + if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) + return mapping->get(mapping, UVC_GET_MAX, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); + + if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) + return mapping->get(mapping, UVC_GET_RES, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); + + return ~0; +} + static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, struct uvc_control *ctrl, struct uvc_control_mapping *mapping, @@ -1219,6 +1238,12 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, v4l2_ctrl->step = 0; return 0; + case V4L2_CTRL_TYPE_BITMASK: + v4l2_ctrl->minimum = 0; + v4l2_ctrl->maximum = uvc_get_ctrl_bitmap(ctrl, mapping); + v4l2_ctrl->step = 0; + return 0; + default: break; } @@ -1320,19 +1345,14 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain, menu_info = &mapping->menu_info[query_menu->index]; - if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK && - (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) { - s32 bitmap; - + if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK) { if (!ctrl->cached) { ret = uvc_ctrl_populate_cache(chain, ctrl); if (ret < 0) goto done; } - bitmap = mapping->get(mapping, UVC_GET_RES, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); - if (!(bitmap & menu_info->value)) { + if (!(uvc_get_ctrl_bitmap(ctrl, mapping) & menu_info->value)) { ret = -EINVAL; goto done; } @@ -1815,6 +1835,18 @@ int uvc_ctrl_set(struct uvc_fh *handle, value = xctrl->value; break; + case V4L2_CTRL_TYPE_BITMASK: + if (!ctrl->cached) { + ret = uvc_ctrl_populate_cache(chain, ctrl); + if (ret < 0) + return ret; + } + + xctrl->value = max(0, xctrl->value); + xctrl->value &= uvc_get_ctrl_bitmap(ctrl, mapping); + value = xctrl->value; + break; + case V4L2_CTRL_TYPE_BOOLEAN: xctrl->value = clamp(xctrl->value, 0, 1); value = xctrl->value; @@ -1829,17 +1861,14 @@ int uvc_ctrl_set(struct uvc_fh *handle, * Valid menu indices are reported by the GET_RES request for * UVC controls that support it. */ - if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK && - (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) { + if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK) { if (!ctrl->cached) { ret = uvc_ctrl_populate_cache(chain, ctrl); if (ret < 0) return ret; } - step = mapping->get(mapping, UVC_GET_RES, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); - if (!(step & value)) + if (!(uvc_get_ctrl_bitmap(ctrl, mapping) & value)) return -EINVAL; } From patchwork Wed Sep 21 09:12:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 608123 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 64469C6FA8B for ; Wed, 21 Sep 2022 09:12:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231317AbiIUJMz (ORCPT ); Wed, 21 Sep 2022 05:12:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41428 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231179AbiIUJMr (ORCPT ); Wed, 21 Sep 2022 05:12:47 -0400 Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [IPv6:2a00:1450:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5018F8E0C4 for ; Wed, 21 Sep 2022 02:12:40 -0700 (PDT) Received: by mail-ej1-x634.google.com with SMTP id bj12so12042245ejb.13 for ; Wed, 21 Sep 2022 02:12:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date; bh=IPOvEFbsB3f+Xwz9TxbpevOhlT2MGP0OcSyaH0auNNw=; b=Tj200QQJw9+NtFY0Ev0n6R0/HlzFwYxa8T0LVPganI/F4XjAqLOVwq6wihuKBbB4ng sn5nxFv6BpgRP4TavkMZTQ8HBoYQ8XSkTnxYF4BQh6eh3L+XFkqgFpbx4ocscPNS5/hO s5gJyeZocz+9kDlzrCsy6TMENdhZ1mzli/dBo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date; bh=IPOvEFbsB3f+Xwz9TxbpevOhlT2MGP0OcSyaH0auNNw=; b=58b6zsreQXH/xeLGTxqNgGBf82dHtL4s3K6TGDAWDdQm66ebb8p8acoXaaCVovXWrK 4x6lIwfP+JGuapRyDEJc4m+H868fWeonFkr3x6GNQccHnnBNGxdGd0br0WlqhZVMKiAu XU3VsJ7yRl5SFqpEn8p3M8Ed0iV/04pu7M6sSrZWFSrKvXSxSw6VsjNDCpR30dPXwo1/ KZXk2ux4SN7BLScryZs+TJivgTRV0e3DroqMwp/DzC70+OVvejqXos0t2xMnHnCSvO5l a3SpM1w8HvyBaDr60sClNdooUQ3bI8RXv+jE1NnlDnTEma/QeCOAHaSJCAuCmodASvIL FTiw== X-Gm-Message-State: ACrzQf3H2YVo7JYUAMMnQ9/IqMD/AwsXuFboxanF8AH6vaPQxQSUMQel Ux1ShtyMrFcig7w3Sdf+OnR7XQ== X-Google-Smtp-Source: AMsMyM4ecOHpR34kdUcnOeywfC/HPo1+hgxqPlHtytpalNmPFiKPof6Pex+OKub0LsgW/CnrjTiUAQ== X-Received: by 2002:a17:907:9803:b0:782:2d55:f98b with SMTP id ji3-20020a170907980300b007822d55f98bmr193753ejc.338.1663751558634; Wed, 21 Sep 2022 02:12:38 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:160b:cee7:2e8b:f72c]) by smtp.gmail.com with ESMTPSA id v4-20020a17090690c400b00771cb506149sm1031913ejw.59.2022.09.21.02.12.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Sep 2022 02:12:38 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 21 Sep 2022 11:12:16 +0200 Subject: [PATCH v2 7/7] media: uvcvideo: Use standard names for menus MIME-Version: 1.0 Message-Id: <20220920-resend-v4l2-compliance-v2-7-7c0942040004@chromium.org> References: <20220920-resend-v4l2-compliance-v2-0-7c0942040004@chromium.org> In-Reply-To: <20220920-resend-v4l2-compliance-v2-0-7c0942040004@chromium.org> To: Mauro Carvalho Chehab Cc: Laurent Pinchart , linux-media@vger.kernel.org, Hans Verkuil , Ricardo Ribalda , linux-kernel@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=12523; i=ribalda@chromium.org; h=from:subject:message-id; bh=GW6t7Dmti9DcWTCthX+5ZUlKrr4OzM2PZwBAycFJFmo=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjKtV+sIe0xcdE1X8D36H6gQ/ml3TkZInpODZhzCSy S0ChjSKJAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCYyrVfgAKCRDRN9E+zzrEiCTpEA CYO9HPOgxMHW09z2qfIwn3ZzeFqN1qPcqRYeFxYhpU+r82dTLZfjIVyWIm5wRHdYQeDi4QCAWnHRlt /vl41Pkwj1QER9LXpg75PKV6kSlPAodzKomdMu9HtdyAaczBUX+pg5y7QMEIpIJ6hg4DWmHMK0lYGd Pz8kFJ9hYSU+8lwpkRwIjVPjlXWqRJ+xBXm4x+LCvPunYoYrNVl9H1boVPERUD0ZS/rwlBNtj00hgb Jhsjs5u5kTMkAyCAa8AzlUBWAVteOsnQNM7sscfxnY0WBeru9JbuPy+ZmlSKHx0O+dyfwEQ2M4Ltqa 630tvHjtQfVE1wFZwZDPlgJOHFotdvibbrJ4eXVXto1oOgxifj1cdE5nDkDZLekYEisg/wg3lPm+e7 Ig/hOJQegRfRMXMKjDZ5OqCH+Hq9uWBwBhWhbTpzrQt8ALODwDvfyFXAhBpNe4AvaS5kmfEi3t5TWA h5K/VoSU/JaTiSHSuToDbkJNWvQFNvZaNZqRgeheZ2CmXgDT2wjAfbneLCdNdlvNbG3YDJ7Ijs/SYS 7CiX7Rh1gDJ7qRFCU5j4NOIjC2KimIV7OPw3SWN6H8VMxrxoTLT175MpXa7m1OR22z64Okn63I3ATW ltc79N/Lo/lnxHeenumJnzgO4/mUUibJZTiOiFNjLvi9whO5lU7CTdE8YrYw== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Instead of duplicating the menu info, use the one from the core. Also, do not use extra memory for 1:1 mappings. Signed-off-by: Ricardo Ribalda Suggested-by: Laurent Pinchart diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index df273b829961..5c28d8aace37 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -363,19 +363,31 @@ static const u32 uvc_control_classes[] = { V4L2_CID_USER_CLASS, }; -static const struct uvc_menu_info power_line_frequency_controls[] = { - { 0, "Disabled" }, - { 1, "50 Hz" }, - { 2, "60 Hz" }, - { 3, "Auto" }, -}; +static const int exposure_auto_mapping[] = { 2, 1, 4, 8 }; -static const struct uvc_menu_info exposure_auto_controls[] = { - { 2, "Auto Mode" }, - { 1, "Manual Mode" }, - { 4, "Shutter Priority Mode" }, - { 8, "Aperture Priority Mode" }, -}; +static u32 uvc_mapping_get_menu_value(struct uvc_control_mapping *mapping, + u32 idx) +{ + if (!test_bit(idx, &mapping->menu_mask)) + return 0; + + if (mapping->menu_mapping) + return mapping->menu_mapping[idx]; + + return idx; +} + +static const char +*uvc_mapping_get_menu_name(struct uvc_control_mapping *mapping, u32 idx) +{ + if (!test_bit(idx, &mapping->menu_mask)) + return NULL; + + if (mapping->menu_names) + return mapping->menu_names[idx]; + + return v4l2_ctrl_get_menu(mapping->id)[idx]; +} static s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, u8 query, const u8 *data) @@ -524,8 +536,8 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_BITMASK, - .menu_info = exposure_auto_controls, - .menu_mask = BIT_MASK(ARRAY_SIZE(exposure_auto_controls)), + .menu_mapping = exposure_auto_mapping, + .menu_mask = GENMASK(ARRAY_SIZE(exposure_auto_mapping) - 1, 0), .slave_ids = { V4L2_CID_EXPOSURE_ABSOLUTE, }, }, { @@ -730,8 +742,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings_uvc11[] = { .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_ENUM, - .menu_info = power_line_frequency_controls, - .menu_mask = BIT_MASK(ARRAY_SIZE(power_line_frequency_controls) - 1), + .menu_mask = GENMASK(V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0), }, }; @@ -744,8 +755,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings_uvc15[] = { .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_ENUM, - .menu_info = power_line_frequency_controls, - .menu_mask = BIT_MASK(ARRAY_SIZE(power_line_frequency_controls)), + .menu_mask = GENMASK(V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0), }, }; @@ -972,13 +982,17 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, s32 value = mapping->get(mapping, UVC_GET_CUR, data); if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { - const struct uvc_menu_info *menu = mapping->menu_info; unsigned int i; - for (i = 0; BIT(i) <= mapping->menu_mask; ++i, ++menu) { + for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { + u32 menu_value; + if (!test_bit(i, &mapping->menu_mask)) continue; - if (menu->value == value) { + + menu_value = uvc_mapping_get_menu_value(mapping, i); + + if (menu_value == value) { value = i; break; } @@ -1174,7 +1188,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, { struct uvc_control_mapping *master_map = NULL; struct uvc_control *master_ctrl = NULL; - const struct uvc_menu_info *menu; unsigned int i; memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl)); @@ -1219,11 +1232,15 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, v4l2_ctrl->maximum = fls(mapping->menu_mask) - 1; v4l2_ctrl->step = 1; - menu = mapping->menu_info; - for (i = 0; BIT(i) <= mapping->menu_mask; ++i, ++menu) { + for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { + u32 menu_value; + if (!test_bit(i, &mapping->menu_mask)) continue; - if (menu->value == v4l2_ctrl->default_value) { + + menu_value = uvc_mapping_get_menu_value(mapping, i); + + if (menu_value == v4l2_ctrl->default_value) { v4l2_ctrl->default_value = i; break; } @@ -1322,11 +1339,11 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, int uvc_query_v4l2_menu(struct uvc_video_chain *chain, struct v4l2_querymenu *query_menu) { - const struct uvc_menu_info *menu_info; struct uvc_control_mapping *mapping; struct uvc_control *ctrl; u32 index = query_menu->index; u32 id = query_menu->id; + const char *name; int ret; memset(query_menu, 0, sizeof(*query_menu)); @@ -1348,22 +1365,28 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain, goto done; } - menu_info = &mapping->menu_info[query_menu->index]; - if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK) { + u32 menu_value; + if (!ctrl->cached) { ret = uvc_ctrl_populate_cache(chain, ctrl); if (ret < 0) goto done; } - if (!(uvc_get_ctrl_bitmap(ctrl, mapping) & menu_info->value)) { + menu_value = uvc_mapping_get_menu_value(mapping, + query_menu->index); + if (!(uvc_get_ctrl_bitmap(ctrl, mapping) & menu_value)) { ret = -EINVAL; goto done; } } - strscpy(query_menu->name, menu_info->name, sizeof(query_menu->name)); + name = uvc_mapping_get_menu_name(mapping, query_menu->index); + if (name) + strscpy(query_menu->name, name, sizeof(query_menu->name)); + else + ret = -EINVAL; done: mutex_unlock(&chain->ctrl_mutex); @@ -1865,7 +1888,7 @@ int uvc_ctrl_set(struct uvc_fh *handle, if (!test_bit(xctrl->value, &mapping->menu_mask)) return -EINVAL; - value = mapping->menu_info[xctrl->value].value; + value = uvc_mapping_get_menu_value(mapping, xctrl->value); /* * Valid menu indices are reported by the GET_RES request for @@ -2311,12 +2334,28 @@ static int __uvc_ctrl_add_mapping(struct uvc_video_chain *chain, INIT_LIST_HEAD(&map->ev_subs); - size = sizeof(*mapping->menu_info) * fls(mapping->menu_mask); - map->menu_info = kmemdup(mapping->menu_info, size, GFP_KERNEL); - if (map->menu_info == NULL) { - kfree(map->name); - kfree(map); - return -ENOMEM; + if (mapping->menu_mapping && mapping->menu_mask) { + size = sizeof(mapping->menu_mapping[0]) * + fls(mapping->menu_mask); + map->menu_mapping = kmemdup(mapping->menu_mapping, size, + GFP_KERNEL); + if (!map->menu_mapping) { + kfree(map->name); + kfree(map); + return -ENOMEM; + } + } + if (mapping->menu_names && mapping->menu_mask) { + size = sizeof(mapping->menu_names[0]) * + fls(mapping->menu_mask); + map->menu_names = kmemdup(mapping->menu_names, size, + GFP_KERNEL); + if (!map->menu_names) { + kfree(map->menu_mapping); + kfree(map->name); + kfree(map); + return -ENOMEM; + } } if (map->get == NULL) @@ -2661,7 +2700,8 @@ static void uvc_ctrl_cleanup_mappings(struct uvc_device *dev, list_for_each_entry_safe(mapping, nm, &ctrl->info.mappings, list) { list_del(&mapping->list); - kfree(mapping->menu_info); + kfree(mapping->menu_names); + kfree(mapping->menu_mapping); kfree(mapping->name); kfree(mapping); } diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index abdb9ca7eed6..97c267e75fa4 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2661,11 +2661,6 @@ MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); * Driver initialization and cleanup */ -static const struct uvc_menu_info power_line_frequency_controls_limited[] = { - { 1, "50 Hz" }, - { 2, "60 Hz" }, -}; - static const struct uvc_control_mapping uvc_ctrl_power_line_mapping_limited = { .id = V4L2_CID_POWER_LINE_FREQUENCY, .entity = UVC_GUID_UVC_PROCESSING, @@ -2674,8 +2669,8 @@ static const struct uvc_control_mapping uvc_ctrl_power_line_mapping_limited = { .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_ENUM, - .menu_info = power_line_frequency_controls_limited, - .menu_mask = BIT_MASK(ARRAY_SIZE(power_line_frequency_controls_limited)), + .menu_mask = GENMASK(V4L2_CID_POWER_LINE_FREQUENCY_60HZ, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ), }; static const struct uvc_device_info uvc_ctrl_power_line_limited = { diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index e6792fd46bf5..89581c1559df 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -25,6 +25,64 @@ #include "uvcvideo.h" +static int uvc_control_xu_2_mapping(struct uvc_control_mapping *map, + struct uvc_xu_control_mapping *xmap) +{ + char (*names)[UVC_MENU_NAME_LEN]; + unsigned int i; + u32 *mapping; + size_t size; + + /* Prevent excessive memory consumption, as well as integer + * overflows. + */ + if (xmap->menu_count == 0 || + xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) + return -EINVAL; + + map->menu_mask = BIT_MASK(xmap->menu_count); + + size = xmap->menu_count * sizeof(*map->menu_mapping); + mapping = kzalloc(size, GFP_KERNEL); + if (!mapping) + return -ENOMEM; + + for (i = 0; i < xmap->menu_count ; i++) + if (copy_from_user(&mapping[i], &xmap->menu_info[i].value, + sizeof(mapping[i]))) { + kfree(mapping); + return -ENOMEM; + } + + map->menu_mapping = mapping; + + /* + * Always use the standard naming if available. + */ + if (v4l2_ctrl_get_menu(map->id)) + return 0; + + size = xmap->menu_count * sizeof(map->menu_names[0]); + names = kzalloc(size, GFP_KERNEL); + if (!names) { + kfree(mapping); + return -ENOMEM; + } + + for (i = 0; i < xmap->menu_count ; i++) { + /* sizeof(names[i]) - 1: to take care of \0 */ + if (copy_from_user(&names[i], &xmap->menu_info[i].name, + sizeof(names[i]) - 1)) { + kfree(names); + kfree(mapping); + return -ENOMEM; + } + } + map->menu_names = names; + + return 0; +} + /* ------------------------------------------------------------------------ * UVC ioctls */ @@ -32,7 +90,6 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, struct uvc_xu_control_mapping *xmap) { struct uvc_control_mapping *map; - unsigned int size; int ret; map = kzalloc(sizeof(*map), GFP_KERNEL); @@ -63,24 +120,9 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, break; case V4L2_CTRL_TYPE_MENU: - /* - * Prevent excessive memory consumption, as well as integer - * overflows. - */ - if (xmap->menu_count == 0 || - xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) { - ret = -EINVAL; - goto free_map; - } - - size = xmap->menu_count * sizeof(*map->menu_info); - map->menu_info = memdup_user(xmap->menu_info, size); - if (IS_ERR(map->menu_info)) { - ret = PTR_ERR(map->menu_info); + ret = uvc_control_xu_2_mapping(map, xmap); + if (ret) goto free_map; - } - - map->menu_mask = BIT_MASK(xmap->menu_count); break; default: @@ -92,7 +134,8 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, ret = uvc_ctrl_add_mapping(chain, map); - kfree(map->menu_info); + kfree(map->menu_names); + kfree(map->menu_mapping); free_map: kfree(map); diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 7e2339fc256e..8ebd7ee2934d 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -254,7 +254,8 @@ struct uvc_control_mapping { enum v4l2_ctrl_type v4l2_type; u32 data_type; - const struct uvc_menu_info *menu_info; + const u32 *menu_mapping; + const char (*menu_names)[UVC_MENU_NAME_LEN]; unsigned long menu_mask; u32 master_id; diff --git a/include/uapi/linux/uvcvideo.h b/include/uapi/linux/uvcvideo.h index 8288137387c0..1b64b6aa40b5 100644 --- a/include/uapi/linux/uvcvideo.h +++ b/include/uapi/linux/uvcvideo.h @@ -36,9 +36,10 @@ UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES | \ UVC_CTRL_FLAG_GET_DEF) +#define UVC_MENU_NAME_LEN 32 struct uvc_menu_info { __u32 value; - __u8 name[32]; + __u8 name[UVC_MENU_NAME_LEN]; }; struct uvc_xu_control_mapping {