From nobody Tue Apr 7 02:54:32 2026 Received: from mail-lf1-f42.google.com (mail-lf1-f42.google.com [209.85.167.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D20E2399018 for ; Mon, 16 Mar 2026 13:34:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668090; cv=none; b=F6fvKFbcHrMSAhj6C9C+eaIytwFbpI9V/XLIHYzv9ViyDWM3FajN3nvtwW9R7p7pTRseXV7Y5d1QcT28lxTHEdgEHxfOlq58pOKoXPgbX5hv0ZLBw6x/ciOa0lfvgHDv5NMo8UCERsgaDm4nYOhroigDzm1h8lmTnweekXCp6SE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668090; c=relaxed/simple; bh=j3lc1kn/wJoX+9cZrghmGTWwf9ptFSHlpETfxL8/X+g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FEcutgbYumMm9BBvsSZwwh/n5+uHgqSCjAuLRKKiws1Nmi0pfgySYx7y4dmob0GEi3uhtEYnODhgrG9y/3ixIVDRxwSsURCc+XOqgh0ayxVrC2JomRaDlMcoS/xVPYuKBVCGtJwTum4X175YgpZf3Q8gye4u9R+okUHS4elFmnc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=Mac0nOBh; arc=none smtp.client-ip=209.85.167.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Mac0nOBh" Received: by mail-lf1-f42.google.com with SMTP id 2adb3069b0e04-59e4989dacdso5161133e87.1 for ; Mon, 16 Mar 2026 06:34:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1773668087; x=1774272887; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=DulSoSsXGHcpQnyTZ9WUFnrdzO4ZXeWwNRNkWSs9pxw=; b=Mac0nOBheEOqgeYLVD2qN0okA6KPMeUJ+UHcDaxXTTyFDqb9cSEvSLt0D1J2lWXhg2 fMdQRw4CuVprGQXhw0DVXUJ86HodaraRoaAEZQpB6hIqO547xJ8Hq9nyYVoyrFW+IHMc tGNQFYlk3fKbITuM1FGh+RRcyENlFs8MxhfZs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773668087; x=1774272887; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=DulSoSsXGHcpQnyTZ9WUFnrdzO4ZXeWwNRNkWSs9pxw=; b=i79Zx4sZMb9JBSv5Gk/mgbLsKV3RRF270gIdAIpbzpizIz/lJRKlavXnc7wwPIopza XlngdVDiLSLmtvoaMflKqdkVO3TRonIaQz7ustzefUWA8R3iwVy9H7yohaoHU7mL2Ij8 ZlfhvXtUZCOSFKKk4m0G0y6oyFFzC9a28z0iGavUMZJZPp9enwawn5aHuTBcdEeVS4NI XNG3GXds2e1rMWOQQX6j8ZWE36pUuUtXLPxLnDlca92NmUZZO3xbbWwY6pP2mb3n3Lkr VL8fv7CTJwrA7Vztes9Y6oIY2qZod3+x6Nab73ax/WuS8fX/xVen7fqbQAeBDK5JApNe kPrg== X-Forwarded-Encrypted: i=1; AJvYcCWka1TlODTyVqTS8mEKVaok2hsrAn5src9b8os6x1kZ7NH8mPHJPT3TyeDcxKpJddCOZ33fEWDMD4TQzUY=@vger.kernel.org X-Gm-Message-State: AOJu0Yweg3M/+67YuANOQM27nNN/sdmNMaI5rR3U4GgsPHNaV4Jd1i/k d9pI+Dy45P4Bwgva/Zxki3yX6EMHkd1foXTwIPa6z2vZSuGb4/WkLv2SDJYJ1vL5EA== X-Gm-Gg: ATEYQzzTbYuoa3BoOmNSwZNtFnxPshJnKViC11PLC1ZLMa+TywU4P7UNwV5f5ciIhKE bj2E2XtNNsZ/0WQz6NibO5nsGYonFnVwhdcyS8g+S0EjH66c2HtDWx7Mb1Yaa9qxHU9w5KmqZ3Z kjrudhMMQta9jVwWk71eCd+cqAn/Q9DDEfkkPzNaB655KiaHWhD8dKHrWzyADu5daIukjB76/mA 72zFRzXqFJrNETo2YuZH8pwOy5WpLPXUVnyydHeWRpB+N/Q24qRZH0L+zF8fIL9yTaMve2NodRg r5RXnxxxsnbeTNpFId1ng4RxGkMFmTNeBC1zKkUQbAUp4Oze22Kd/4PfIAO7KEat/Qu5GaIgS55 f5Zuwd8R1NB704cy9v75cwsZnRJJYJXiDvca3jIY9TNSmTHBNnwZ0PSVFITgYyuTUS1q1QiIl9Y pc/HSKPbbZ720gWp0fhmUftNadIHoJVJ5Qe4/k1CX7b/25/ch+u6KCtvW+uFNhU5iW14kh1N5bD w== X-Received: by 2002:a05:6512:2c07:b0:5a1:45fc:34f4 with SMTP id 2adb3069b0e04-5a162ae9fc4mr3900183e87.22.1773668087000; Mon, 16 Mar 2026 06:34:47 -0700 (PDT) Received: from ribalda.c.googlers.com (27.69.88.34.bc.googleusercontent.com. [34.88.69.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5a156366a7fsm3481473e87.76.2026.03.16.06.34.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Mar 2026 06:34:46 -0700 (PDT) From: Ricardo Ribalda Date: Mon, 16 Mar 2026 13:34:44 +0000 Subject: [PATCH v3 1/4] media: uvcvideo: Import standard controls from uvcdynctrl Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260316-uvcdynctrl-v3-1-19cd4657e1f3@chromium.org> References: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> In-Reply-To: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> To: Laurent Pinchart , Hans de Goede , Mauro Carvalho Chehab , Greg Kroah-Hartman Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Ricardo Ribalda , Manav Gautama , Martin Rubli X-Mailer: b4 0.14.3 The uvcdynctrl tool from libwebcam: https://sourceforge.net/projects/libwebcam/ maps proprietary controls into v4l2 controls using the UVCIOC_CTRL_MAP ioctl. The tool has not been updated for 10+ years now, and there is no reason for the UVC driver to not do the mapping by itself. This patch adds the mappings from the uvcdynctrl into the driver. Hopefully this effort can help in deprecating the UVCIOC_CTRL_MAP ioctl. Some background about UVCIOC_CTRL_MAP (thanks Laurent for the context): ``` this was envisioned as the base of a vibrant ecosystem where a large number of vendors would submit XML files that describe their XU control mappings, at a pace faster than could be supported by adding XU mappings to the driver. This vision failed to materialize and the tool has not been updated for 10+ years now. There is no reason to believe the situation will change. ``` During the porting, the following mappings where NOT imported because they were not using standard v4l2 IDs. It is recommended that userspace moves to UVCIOC_CTRL_QUERY for non standard controls. { .id =3D V4L2_CID_FLASH_MODE, .entity =3D UVC_GUID_SIS_LED_HW_CONTROL, .selector =3D 4, .size =3D 4, .offset =3D 0, .v4l2_type =3D V4L2_CTRL_TYPE_MENU, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask =3D 0x3, .menu_mapping =3D { 0x20, 0x22 }, .menu_names =3D { "Off", "On" }, }, { .id =3D V4L2_CID_FLASH_FREQUENCY, .entity =3D UVC_GUID_SIS_LED_HW_CONTROL, .selector =3D 4, .size =3D 8, .offset =3D 16, .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id =3D V4L2_CID_LED1_MODE, .entity =3D UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, .selector =3D 1, .size =3D 8, .offset =3D 0, .v4l2_type =3D V4L2_CTRL_TYPE_MENU, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask =3D 0xF, .menu_mapping =3D { 0, 1, 2, 3 }, .menu_names =3D { "Off", "On", "Blinking", "Auto" }, }, { .id =3D V4L2_CID_LED1_FREQUENCY, .entity =3D UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, .selector =3D 1, .size =3D 8, .offset =3D 16, .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id =3D V4L2_CID_DISABLE_PROCESSING, .entity =3D UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector =3D 5, .size =3D 8, .offset =3D 0, .v4l2_type =3D V4L2_CTRL_TYPE_BOOLEAN, .data_type =3D UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id =3D V4L2_CID_RAW_BITS_PER_PIXEL, .entity =3D UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector =3D 8, .size =3D 8, .offset =3D 0, .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id =3D V4L2_CID_LED1_MODE, .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, .selector =3D 0x09, .size =3D 2, .offset =3D 8, .v4l2_type =3D V4L2_CTRL_TYPE_MENU, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask =3D 0xF, .menu_mapping =3D { 0, 1, 2, 3 }, .menu_names =3D { "Off", "On", "Blink", "Auto" }, }, { .id =3D V4L2_CID_LED1_FREQUENCY, .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, .selector =3D 0x09, .size =3D 8, .offset =3D 24, .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, }, This script has been used to generate the mappings. They were then reformatted manually to follow the driver style. import sys import uuid import re import xml.etree.ElementTree as ET def get_namespace(root): return re.match(r"\{.*\}", root.tag).group(0) def get_single_guid(ns, constant): id =3D constant.find(ns + "id").text value =3D constant.find(ns + "value").text return (id, value) def get_constants(ns, root): out =3D dict() for constant in root.iter(ns + "constant"): attr =3D constant.attrib if attr["type"] =3D=3D "integer": id, value =3D get_single_guid(ns, constant) if id in out: print(f"dupe constant {id}") out[id] =3D value return out def get_guids(ns, root): out =3D dict() for constant in root.iter(ns + "constant"): attr =3D constant.attrib if attr["type"] =3D=3D "guid": id, value =3D get_single_guid(ns, constant) if id in out: print(f"dupe guid {id}") out[id] =3D value return out def get_single_control(ns, control): out =3D {} for id in "entity", "selector", "index", "size", "description": v =3D control.find(ns + id) if v is None and id =3D=3D "description": continue out[id] =3D v.text reqs =3D set() for r in control.find(ns + "requests"): reqs.add(r.text) out["requests"] =3D reqs return (control.attrib["id"], out) def get_controls(ns, root): out =3D dict() for control in root.iter(ns + "control"): id, value =3D get_single_control(ns, control) if id in out: print(f"Dupe control id {id}") out[id] =3D value return out def get_single_mapping(ns, mapping): out =3D {} out["name"] =3D mapping.find(ns + "name").text uvc =3D mapping.find(ns + "uvc") for id in "size", "offset", "uvc_type": out[id] =3D uvc.find(ns + id).text out["control_ref"] =3D uvc.find(ns + "control_ref").attrib["idref"] v4l2 =3D mapping.find(ns + "v4l2") for id in "id", "v4l2_type": out[id] =3D v4l2.find(ns + id).text menu =3D {} for entry in v4l2.iter(ns + "menu_entry"): menu[entry.attrib["name"]] =3D entry.attrib["value"] if menu: out["menu"] =3D menu return out def get_mapping(ns, root): out =3D [] for control in root.iter(ns + "mapping"): mapping =3D get_single_mapping(ns, control) out +=3D [mapping] return out def print_guids(guids): for g in guids: print(f"#define {g} \\") u_bytes =3D uuid.UUID(guids[g]).bytes_le u_bytes =3D [f"0x{b:02x}" for b in u_bytes] print("\t{ " + ", ".join(u_bytes) + " }") def print_flags(flags): get_range =3D {"GET_MIN", "GET_DEF", "GET_MAX", "GET_CUR", "GET_RES"} if get_range.issubset(flags): flags -=3D get_range flags.add("GET_RANGE") flags =3D list(flags) flags.sort() out =3D "" for f in flags[:-1]: out +=3D f"UVC_CTRL_FLAG_{f}\n\t\t\t\t| " out +=3D f"UVC_CTRL_FLAG_{flags[-1]}" return out def print_description(desc): print("/*") for line in desc.strip().splitlines(): print(f" * {line.strip()}") print("*/") def print_controls(controls, cons): for id in controls: c =3D controls[id] if "description" in c: print_description(c["description"]) print( f"""\t{{ \t\t.entity\t\t=3D {c["entity"]}, \t\t.selector\t=3D {cons[c["selector"]]}, \t\t.index\t\t=3D {c["index"]}, \t\t.size\t\t=3D {c["size"]}, \t\t.flags\t\t=3D {print_flags(c["requests"])}, \t}},""" ) def menu_mapping_txt(menu): out =3D f"\n\t\t.menu_mask\t=3D 0x{((1< Cc: Martin Rubli Reviewed-by: Laurent Pinchart Signed-off-by: Ricardo Ribalda --- drivers/media/usb/uvc/uvc_ctrl.c | 174 +++++++++++++++++++++++++++++++++++= ++++ include/linux/usb/uvc.h | 6 ++ 2 files changed, 180 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_c= trl.c index b9a3d9257a11..b6e020b41671 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -385,6 +385,99 @@ static const struct uvc_control_info uvc_ctrls[] =3D { | UVC_CTRL_FLAG_GET_RANGE | UVC_CTRL_FLAG_RESTORE, }, + /* + * Allows the control of pan/tilt motor movements for camera models + * that support mechanical pan/tilt. + * + * Bits 0 to 15 control pan, bits 16 to 31 control tilt. + * The unit of the pan/tilt values is 1/64th of a degree and the + * resolution is 1 degree. + */ + { + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 1, + .index =3D 0, + .size =3D 4, + .flags =3D UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Reset the pan/tilt motors to their original position for camera + * models that support mechanical pan/tilt. + * + * Setting bit 0 resets the pan position. + * Setting bit 1 resets the tilt position. + * + * Both bits can be set at the same time to reset both, pan and tilt, + * at the same time. + */ + { + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 2, + .index =3D 1, + .size =3D 1, + .flags =3D UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Allows the control of focus motor movements for camera models that + * support mechanical focus. + * + * Bits 0 to 7 allow selection of the desired lens position. + * There are no physical units, instead, the focus range is spread over + * 256 logical units with 0 representing infinity focus and 255 being + * macro focus. + */ + { + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 3, + .index =3D 2, + .size =3D 6, + .flags =3D UVC_CTRL_FLAG_GET_CUR + | UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Allows the control of pan/tilt motor movements for camera models + * that support mechanical pan/tilt. + * + * Bits 0 to 15 control pan, bits 16 to 31 control tilt. + */ + { + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 1, + .index =3D 0, + .size =3D 4, + .flags =3D UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_GET_RES + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Reset the pan/tilt motors to their original position for camera + * models that support mechanical pan/tilt. + * + * Setting bit 0 resets the pan position. + * Setting bit 1 resets the tilt position. + */ + { + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 2, + .index =3D 1, + .size =3D 1, + .flags =3D UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_GET_RES + | UVC_CTRL_FLAG_SET_CUR, + }, }; =20 static const u32 uvc_control_classes[] =3D { @@ -1009,6 +1102,87 @@ static const struct uvc_control_mapping uvc_ctrl_map= pings[] =3D { .menu_mask =3D BIT(V4L2_COLORFX_VIVID) | BIT(V4L2_COLORFX_NONE), }, + { + .id =3D V4L2_CID_PAN_RELATIVE, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 1, + .size =3D 16, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id =3D V4L2_CID_TILT_RELATIVE, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 1, + .size =3D 16, + .offset =3D 16, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id =3D V4L2_CID_PAN_RESET, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 2, + .size =3D 1, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_BUTTON, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id =3D V4L2_CID_TILT_RESET, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 2, + .size =3D 1, + .offset =3D 1, + .v4l2_type =3D V4L2_CTRL_TYPE_BUTTON, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id =3D V4L2_CID_PAN_RELATIVE, + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 1, + .size =3D 16, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id =3D V4L2_CID_TILT_RELATIVE, + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 1, + .size =3D 16, + .offset =3D 16, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id =3D V4L2_CID_PAN_RESET, + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 2, + .size =3D 1, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_BUTTON, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id =3D V4L2_CID_TILT_RESET, + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 2, + .size =3D 1, + .offset =3D 1, + .v4l2_type =3D V4L2_CTRL_TYPE_BUTTON, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id =3D V4L2_CID_FOCUS_ABSOLUTE, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 3, + .size =3D 8, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, }; =20 /* ------------------------------------------------------------------------ diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index ea92ac623a45..dea23aabbad4 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -43,6 +43,12 @@ #define UVC_GUID_MSXU_1_5 \ {0xdc, 0x95, 0x3f, 0x0f, 0x32, 0x26, 0x4e, 0x4c, \ 0x92, 0xc9, 0xa0, 0x47, 0x82, 0xf4, 0x3b, 0xc8} +#define UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 \ + {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ + 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56 } +#define UVC_GUID_LOGITECH_PERIPHERAL \ + {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \ + 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd } =20 /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-e= xtensions-1-5#222-extension-unit-controls */ #define UVC_MSXU_CONTROL_FOCUS 0x01 --=20 2.53.0.851.ga537e3e6e9-goog From nobody Tue Apr 7 02:54:32 2026 Received: from mail-lf1-f42.google.com (mail-lf1-f42.google.com [209.85.167.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D89839A047 for ; Mon, 16 Mar 2026 13:34:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668091; cv=none; b=Y7M+saRpESi9f19OEMJ88La1960Uv67qL2qBupY80Ppf2CcSXJcU2mZHoEmyZ4soJxoF0qoMamH645N98XgDSr8XsBF2pIMe5/TEYdidonxH2ftm9YSR3bujuEF7miSqZ8HpBSi2Q1KH20YuFB0cL837GlSvWp6b/9J6twDRjgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668091; c=relaxed/simple; bh=980emBb3/yN2Du8H038v0fkSEDBFS2aUJO1xAU2v8cs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dErP0So3lPWIsYnLICyhW9r2cZz8fzQo8dmEICHpL+BCrP8mFB94nsXA46BaoddcQd7izkAlB6odC59UFwZ1jSZcWhSd2glAGpQxdCBR5MWYu1/pYWQt7yT9lApsJTysf6Sixz8/2yZgp+UBTmAIR4IRn+25QEva3GLrjlieruA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=RIguvXTx; arc=none smtp.client-ip=209.85.167.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="RIguvXTx" Received: by mail-lf1-f42.google.com with SMTP id 2adb3069b0e04-5a12c19affeso6260731e87.1 for ; Mon, 16 Mar 2026 06:34:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1773668088; x=1774272888; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=zRxqb7jp+TCy3hg1xHflJENuVb/8wn/xUKsac5LhXZU=; b=RIguvXTxOrj/U4FQTfrn182eChPRoLxaOWkxfnPIaL810xw1CeniUSKBFvSb/syXqA Z1YPcwm0dGl6lRxqTpHuVYxoMJZlTa1sYa5a3thU9TyVXptIZXKipY61v/05KXqGNupp pw8Rs/hc+g0hLgDV9bl52VwjFKI4npAEu0NI8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773668088; x=1774272888; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=zRxqb7jp+TCy3hg1xHflJENuVb/8wn/xUKsac5LhXZU=; b=jZ8ppu/b7Dj0wjUSS9UR1vywDXp6z0wrwOrrkFUOt61yHm502f1DH2TSSYzrJQaX9Q eo7BoShNUeHHvwzd6wTv4WFJywn8hBPcvqXz8pjbMWTuxfNXwzTecV9EvZ1gEXOWuP3Z iDvInCXvdWrUQsw+hCbHwtJaKjRIsXLZko0gsuIJaoMCTqUTwkqdd0+XSpNlmSWgXtTI kHGbM7wYrfkJzGKHH/6EJ5v/y71Mxi9FKkP8xAMsQRyMIbboMjbyrlJIg7G47TEYZetw xsl3WpsjBDX+LF9T490YWpEX23mCYvu2G7h3K5D2Hzb+DujZytPk/N7jneSobwWSKFd/ MLww== X-Forwarded-Encrypted: i=1; AJvYcCVRDEDO8NDJyo0rP2OvPIhs1FJKYB4WAoZX0P/JliVY3F0DlDsUDHto9TN2pFM5tf/DLSGNYxGJ1JYawDQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yxb+6G50HtPiPIp9lMWqiltcnZrgxYN5yzQ96ombdF2QSsWWuOB sQ7wUXYmLXqgBAldndMeSY/FtruUhaHDG2/FIEbo6suATNwcX+f3HrzuLPQVFjYroT/A0zBy3tG zmkMa/max X-Gm-Gg: ATEYQzyKBkaBF5fkdpQumbueq5r8w1nF5KGSwVptDYW209vdaICvvmuyR72X5a4zEe5 7Q7tZWYRDi2WPX4MRZrN/ukHyd+hzYjkiRNxSP68yZqRIAuwSSlzoSgi8XfY9P6e0HUKoJcfNEy JR2Bcta7PYlXCs7AvAHGekLVT5Vp0LAiXap3F2tpYC58cKN7b2tv43ZI2MuC/jhJ2sQU9jMrGRm kNk3QNYL3MB5/GiRx/KsV6aNL5ZbjJ5zq374gcEsn0LKfOP3uwKfBktgpggESDR1xKxY7wyTMEj /ZIZm4Db+utiKhl4JOWEFpNLyvTNlrztG8wNhWgE3axiI5eSfpPh05M9oW5KP0O+JSpWEwrKvjS +SaWrEA64NE9Zn+7HDHuTw3Qu6o324Js3MLzZQ1k1FMS0s3MVTNyuYY2pWbhEtq7ZRty6rnBVfD A9ECwAMLhGnLggbyvSqaVT1ivhOochOzzWnpNLtgetDvwERPtecU7izLBTS87RkH36plkx3jS6O w== X-Received: by 2002:a05:6512:3c87:b0:5a1:26c:7fb4 with SMTP id 2adb3069b0e04-5a15a4cda88mr6195149e87.21.1773668087880; Mon, 16 Mar 2026 06:34:47 -0700 (PDT) Received: from ribalda.c.googlers.com (27.69.88.34.bc.googleusercontent.com. [34.88.69.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5a156366a7fsm3481473e87.76.2026.03.16.06.34.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Mar 2026 06:34:47 -0700 (PDT) From: Ricardo Ribalda Date: Mon, 16 Mar 2026 13:34:45 +0000 Subject: [PATCH v3 2/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260316-uvcdynctrl-v3-2-19cd4657e1f3@chromium.org> References: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> In-Reply-To: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> To: Laurent Pinchart , Hans de Goede , Mauro Carvalho Chehab , Greg Kroah-Hartman Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Ricardo Ribalda X-Mailer: b4 0.14.3 The UVCIOC_CTRL_MAP lets userspace create a mapping for a custom control. This mapping is usually created by the uvcdynctrl userspace utility. We would like to get the mappings into the driver instead. Reviewed-by: Laurent Pinchart Signed-off-by: Ricardo Ribalda --- Documentation/userspace-api/media/drivers/uvcvideo.rst | 2 ++ drivers/media/usb/uvc/uvc_v4l2.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Documentation/userspace-api/media/drivers/uvcvideo.rst b/Docum= entation/userspace-api/media/drivers/uvcvideo.rst index dbb30ad389ae..b09d2f8ba66e 100644 --- a/Documentation/userspace-api/media/drivers/uvcvideo.rst +++ b/Documentation/userspace-api/media/drivers/uvcvideo.rst @@ -109,6 +109,8 @@ IOCTL reference UVCIOC_CTRL_MAP - Map a UVC control to a V4L2 control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ =20 +**This IOCTL is deprecated and will be eventually removed** + Argument: struct uvc_xu_control_mapping =20 **Description**: diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v= 4l2.c index d5860661c115..f9049e9c0d3a 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1046,6 +1046,8 @@ static long uvc_ioctl_default(struct file *file, void= *priv, bool valid_prio, switch (cmd) { /* Dynamic controls. */ case UVCIOC_CTRL_MAP: + pr_warn_once("uvcvideo: " DEPRECATED + "UVCIOC_CTRL_MAP ioctl will be eventually removed.\n"); return uvc_ioctl_xu_ctrl_map(chain, arg); =20 case UVCIOC_CTRL_QUERY: @@ -1160,6 +1162,8 @@ static long uvc_v4l2_compat_ioctl32(struct file *file, =20 switch (cmd) { case UVCIOC_CTRL_MAP32: + pr_warn_once("uvcvideo: " DEPRECATED + "UVCIOC_CTRL_MAP32 ioctl will be eventually removed.\n"); ret =3D uvc_v4l2_get_xu_mapping(&karg.xmap, up); if (ret) break; --=20 2.53.0.851.ga537e3e6e9-goog From nobody Tue Apr 7 02:54:32 2026 Received: from mail-lf1-f51.google.com (mail-lf1-f51.google.com [209.85.167.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0424639A07C for ; Mon, 16 Mar 2026 13:34:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668093; cv=none; b=oiNYaREGbIdRaR/rudFobTbD4/1UX29hGe6GeL13OuEQojymth86MzH+SVhYCGrk2id6MqGUCHZdRAUROy+WzVm0cRV3P3VBhlLi7DvHnDtAugZiDPu2MnOSEWfzM3B9gPok+2Z1TCFo3ZDh+BX40380r39OS7vabfaFaPrG258= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668093; c=relaxed/simple; bh=ZqtbkN9X0RvpKTXiACrFylvAxPZu6LxQ+9wsTyXgq08=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PxtA5PuFDCUubiCSFUg6ImGD/9QPMv37O0uXj4o7tKL5l4V51WSq3+PVcIBU1gAKmiOQSNJid1/8lUpbEIBEGmHS0jyEh93wvzeGb7qTaBn0kgkfdyTX0iFYl3z6127i1zXgN8aPbzSfT0NRyM9NUS6PVoQRPa4CeXxbhEFl/dc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=OiceH/G3; arc=none smtp.client-ip=209.85.167.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="OiceH/G3" Received: by mail-lf1-f51.google.com with SMTP id 2adb3069b0e04-5a13a06fc85so5378580e87.1 for ; Mon, 16 Mar 2026 06:34:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1773668089; x=1774272889; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=6bVigAWa0kFOUeMtknvqHxM/1nuFW2KCUzcM3K92o58=; b=OiceH/G3ab3NHy4p9dksCLz87q+QYv+FiEsntgzWKueMN5vYbyP9orrP9UX2Xzto0u LDoVdTrPD9WdPgiscOumwGAW8wmTPpwM8t2Mmy1IRQLVP3iR0TcfFxvibHh+wdO4PjFn r3qFu2eI1CszRbOqG6Cx3dhTnfug9ZbmS3SsI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773668089; x=1774272889; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=6bVigAWa0kFOUeMtknvqHxM/1nuFW2KCUzcM3K92o58=; b=ZcInHkQkRxXd12oUuombmhVY2RIWE5yZeUEnTVQlkclxWU7J2C5Rjoq31KuBVVzQhd hjlZt9xWoNAEIZpZXdmETwGk8F4N4h6jQzWwU+zPeGIADC3R4CnB9bU9+WQ8ZMEecYSO PQL2mWrx/l2s1cWQ2HDJbhv85Smhz4LD6O8ROlm+/T5tkk2VNnxXKp2CjO7Hrmj3lnr2 PPOUDsvpCQ/fE9gKoVlfqo2qtS00HkSnIJF/bhGy7ntOsHPJID49cVP+F3o5Fr70ywPK LrFBYqerPi9gTLjcUbzH7eLKhoCMLUtzqPHysYs7xJV7q+7n6mqJi09r2eYsfT4s7MrE 07FQ== X-Forwarded-Encrypted: i=1; AJvYcCWrMGv7c0T2XytGBJpmEgHj9C12BP9/DVVIrLp4LSYL7yWJuqnC+dTYMQBGSgzPadP/o97KEvgzdl1kQc4=@vger.kernel.org X-Gm-Message-State: AOJu0YzmkMIMV3TEKnVl88OqFVXj0NigpMcFQuKlUue51oP2X/g+DJQG cIoeGRww+i8uj9WOFMRkBt5aJCJhTdx6KhckWJ6+ccPVjp6LflhG/015EQ2UJMrPAX/Vdl0R7Vu tTlvaubBk X-Gm-Gg: ATEYQzzD2arndW6r70VEShzN6AU9PTNBScVpLNRHx1FP1Nr/ark3evWJUB9UjD4ezaA mMzGP2o3DoaQpXCvbyYsBgsCZsTpSm5xKzu+OxtTaVg+Fk1Gu/dlo2YVeAG8XrTvG37SjlrZUie 3xLgTqP33s4kUUgxykAerNyY670DiaUTLYf4xz63TFUh6XwYooP9TcjSvCk+zBqWbEaN5rzGGrB lEtJesEZS1GBTHaJmhGhz1TF23r/TVynrzzMDQT8N49xkRJFe/gh1ATKb5IBEnHlRBx5/ubwjEB kB4QhZBRiM+EAHKGrNJMjP4xPQ3NxfdKG/6hXdkk03Ex72o3CjuIFPlNukXJIde2b1vu4LSfIgL 0LToyqSOntnvAt9z9pIGcxhRw3l1dm+usikoloX/GdcQhCKfWtdVIWXzSVVgSv16We6LfJ9det5 osXVFDfedmeTy5g2/iWRB9+mgMJYbrnoZnluz5WmW/33xPFaSrKuc+3jW7WNpC44WRNHUozIU+e w== X-Received: by 2002:ac2:50a5:0:b0:5a1:1496:920 with SMTP id 2adb3069b0e04-5a162b124bamr3566254e87.26.1773668089070; Mon, 16 Mar 2026 06:34:49 -0700 (PDT) Received: from ribalda.c.googlers.com (27.69.88.34.bc.googleusercontent.com. [34.88.69.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5a156366a7fsm3481473e87.76.2026.03.16.06.34.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Mar 2026 06:34:48 -0700 (PDT) From: Ricardo Ribalda Date: Mon, 16 Mar 2026 13:34:46 +0000 Subject: [PATCH v3 3/4] media: uvcvideo: Introduce allow_privacy_override module parameter Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260316-uvcdynctrl-v3-3-19cd4657e1f3@chromium.org> References: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> In-Reply-To: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> To: Laurent Pinchart , Hans de Goede , Mauro Carvalho Chehab , Greg Kroah-Hartman Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Ricardo Ribalda X-Mailer: b4 0.14.3 Some camera modules have XU controls that can configure the behaviour of the privacy LED. Block mapping of those controls, unless the module is configured with a new parameter: allow_privacy_override. This is just an interim solution. Based on the users feedback, we will either put the privacy controls behind a CONFIG option, or completely block them. Signed-off-by: Ricardo Ribalda --- drivers/media/usb/uvc/uvc_ctrl.c | 38 ++++++++++++++++++++++++++++++++++= ++++ drivers/media/usb/uvc/uvc_driver.c | 20 ++++++++++++++++++++ drivers/media/usb/uvc/uvc_v4l2.c | 7 +++++++ drivers/media/usb/uvc/uvcvideo.h | 2 ++ include/linux/usb/uvc.h | 4 ++++ 5 files changed, 71 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_c= trl.c index b6e020b41671..3ca108b83f1d 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -3001,6 +3001,35 @@ static int uvc_ctrl_init_xu_ctrl(struct uvc_device *= dev, return ret; } =20 +bool uvc_ctrl_is_privacy_control(u8 entity[16], u8 selector) +{ + /* + * This list is not exhaustive, it is a best effort to block access to + * non documented controls that can affect user's privacy. + */ + struct privacy_control { + u8 entity[16]; + u8 selector; + } privacy_control[] =3D { + { + .entity =3D UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, + .selector =3D 1, + }, + { + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 9, + }, + }; + int i; + + for (i =3D 0; i < ARRAY_SIZE(privacy_control); i++) + if (!memcmp(entity, privacy_control[i].entity, 16) && + selector =3D=3D privacy_control[i].selector) + return true; + + return false; +} + int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control_query *xqry) { @@ -3045,6 +3074,15 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, return -ENOENT; } =20 + if (uvc_ctrl_is_privacy_control(entity->guid, xqry->selector) && + !uvc_allow_privacy_override_param) { + dev_warn_once(&chain->dev->intf->dev, + "Privacy related controls can only be accessed if module paramete= r allow_privacy_override is true\n"); + uvc_dbg(chain->dev, CONTROL, "Blocking access to privacy related Control= %pUl/%u\n", + entity->guid, xqry->selector); + return -EACCES; + } + if (mutex_lock_interruptible(&chain->ctrl_mutex)) return -ERESTARTSYS; =20 diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc= _driver.c index b0ca81d924b6..74c9dea29d36 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -36,6 +36,7 @@ unsigned int uvc_no_drop_param =3D 1; static unsigned int uvc_quirks_param =3D -1; unsigned int uvc_dbg_param; unsigned int uvc_timeout_param =3D UVC_CTRL_STREAMING_TIMEOUT; +bool uvc_allow_privacy_override_param; =20 static struct usb_driver uvc_driver; =20 @@ -2505,6 +2506,25 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); module_param_named(timeout, uvc_timeout_param, uint, 0644); MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); =20 +static int param_set_privacy(const char *val, const struct kernel_param *k= p) +{ + pr_warn_once("uvcvideo: " DEPRECATED + "allow_privacy_override parameter will be eventually removed.\n"); + return param_set_bool(val, kp); +} + +static const struct kernel_param_ops param_ops_privacy =3D { + .set =3D param_set_privacy, + .get =3D param_get_bool, +}; + +param_check_bool(allow_privacy_override, &uvc_allow_privacy_override_param= ); +module_param_cb(allow_privacy_override, ¶m_ops_privacy, + &uvc_allow_privacy_override_param, 0644); +__MODULE_PARM_TYPE(allow_privacy_override, "bool"); +MODULE_PARM_DESC(allow_privacy_override, + "Allow access to privacy related controls"); + /* ------------------------------------------------------------------------ * Driver initialization and cleanup */ diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v= 4l2.c index f9049e9c0d3a..6d4f027c8402 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -133,6 +133,13 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chai= n *chain, return -EINVAL; } =20 + if (uvc_ctrl_is_privacy_control(xmap->entity, xmap->selector) && + !uvc_allow_privacy_override_param) { + dev_warn_once(&chain->dev->intf->dev, + "Privacy related controls can only be mapped if module parameter = allow_privacy_override is true\n"); + return -EACCES; + } + map =3D kzalloc_obj(*map); if (map =3D=3D NULL) return -ENOMEM; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvi= deo.h index 8480d65ecb85..362110d58ca3 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -664,6 +664,7 @@ extern unsigned int uvc_no_drop_param; extern unsigned int uvc_dbg_param; extern unsigned int uvc_timeout_param; extern unsigned int uvc_hw_timestamps_param; +extern bool uvc_allow_privacy_override_param; =20 #define uvc_dbg(_dev, flag, fmt, ...) \ do { \ @@ -794,6 +795,7 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control_query *xqry); =20 void uvc_ctrl_cleanup_fh(struct uvc_fh *handle); +bool uvc_ctrl_is_privacy_control(u8 entity[16], u8 selector); =20 /* Utility functions */ struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alt= s, diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index dea23aabbad4..70c2a7d25236 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -49,6 +49,10 @@ #define UVC_GUID_LOGITECH_PERIPHERAL \ {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \ 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd } +#define UVC_GUID_LOGITECH_USER_HW_CONTROL_V1 \ + {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ + 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f } + =20 /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-e= xtensions-1-5#222-extension-unit-controls */ #define UVC_MSXU_CONTROL_FOCUS 0x01 --=20 2.53.0.851.ga537e3e6e9-goog From nobody Tue Apr 7 02:54:32 2026 Received: from mail-lf1-f42.google.com (mail-lf1-f42.google.com [209.85.167.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C02D239B4BE for ; Mon, 16 Mar 2026 13:34:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668093; cv=none; b=FrMl0p5E5YtwIanICIpOVHBFsEO28yvq7DxkLiSVZQOIzBk8wPrdPBP+oRe2EmdbcFttUF9q3BAHCmwq3TREO7yrpHpGyU8djcxOW3FIffU/9kXv8RgkIb9K2VKaUrOdirY9OMyGeZt2/j6MxInASyLdupMac6CJHJSeFtOYFbo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668093; c=relaxed/simple; bh=t4X4K5vFnBQTTs4ZuZurlfNMkVH5xrm/oy3JiEkG6OQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fYUwmuN7SEy7wD/IkIC0GSyBOfeyherlQKmjJoB9k1QSk3D7xpx7jHeHmZ1PMJHl6P+epA6uR4odtos0hVYzFhPwSTrzm5ersqyPFdFIXiAVPFHQCY10npgeevqzXKGXyhBcshIryCZw4X1u+E54aVz1ttZkbCSB9L3coZUJtPk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=EpUjj/sJ; arc=none smtp.client-ip=209.85.167.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="EpUjj/sJ" Received: by mail-lf1-f42.google.com with SMTP id 2adb3069b0e04-5a12cd0bcd8so5256058e87.3 for ; Mon, 16 Mar 2026 06:34:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1773668090; x=1774272890; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=yAs/NGIMe6yEYwcK3Dv3ybFWLR+6vTJh3GyoeoXUzuc=; b=EpUjj/sJz9Ow3LOwmEtGX5lNS4FnjDMDQKj+Sb0YKUg7N0DGxo11T7kyuKmoXiOssr fp+9Fjb/6I2fPxZlCuuG/Txo/W/iUaI4nKu1ROQ3o3d9g4tF5/a6tBaMwaQtfi/9coz9 /8VjzH4gXCWEfuEJAyfYxcnwOsEzxb5C08wns= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773668090; x=1774272890; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=yAs/NGIMe6yEYwcK3Dv3ybFWLR+6vTJh3GyoeoXUzuc=; b=XlUEz+Kt0Z0eKoC7A+L3Hv4q53KqzEriylapEBLYpwOg4ToIA5TcDtbTFDNRFH1iHI 8eiwboGwJB5voEb/7Iw2twefb0oVkHldt9TIMyl4BmmSbNe043D+ZVfRzR1fKDxYtSeL kUHO/GShhQ9FsOGCMSILmaF9xPV/ezatiGqAJI4T7UADc8lin+q/omXGzT3k90WWmOPx AOHFto0BMAJi3NQphF8OU30KpnboSXm0pf8QgR6CI4v+UWxicsqE8dCYGntxSTMtNJ6+ +yb/VUFPQeqPrNOeOXp/Da21PohPVDtm4tnsFQpGcCdy4WghwtDqF3nGwcidgAVADlhR LKJw== X-Forwarded-Encrypted: i=1; AJvYcCXKyoX/2EwmPn0uA/I3fHpxj1b2rzA2QHoEEXlePTZSkrf0cbyFAP1Yj+x68VIXRNH2Ic2yk1UB89nC4gg=@vger.kernel.org X-Gm-Message-State: AOJu0YxWx3dJMhhUbfi2CSOAjOm0wSaX7BrqHIG0DTukQLUfzuwMRO0f ms6NfD64vx9a4oeezW/vL9guDdLixKnnKcv/aT7TAzo+pgqoRGuHakAiq+AXG86Bog== X-Gm-Gg: ATEYQzzhybmGVpmDgGZqUDOzaUsJT443Np7EZvnxo4jvRwaes6temNprvw+OT4bnfpg MXgwDFJ9d1rMvNiqC5QpR3e0rXMglk9UYYkDnT92pPOjT1Igcg8NK1MDl2cx7pNghENHqPNhq19 I6McD63cLK66Ykk76yU700EGaGrhH7rm9F/F5FRGZm/g++Bdj2WyUdim9lo7MckWDnwIzkCcbQM BU27Yyswuk26zjSle4aHNdCp9NurAs0rgdZUiqFA33kcKImUZTBOeKTc9pE7jUXzIWMYTbFbUMI 9XJBTuWTPCV8eZRh0nx2XaIt3RMpQd8hUKh3QCRgBtXSczCkOkXVbpNZFnfDiS+v3lFqmXefc/Q yMCWfThRh4Ul0SfdNZcUs4BsQkWyHjf56sDcWaYQq+IUOhNgrIMfH/Bk8ulfimQj2sPSPNhNsgn mqNw9a6XwoRHWEeazNpzOSSv2yQ/swmcfGVP42iOJbt6dtm14LY8zHGpZKQirfV+Zr6hwkDv5L3 w== X-Received: by 2002:a05:6512:10d1:b0:5a1:3e69:b186 with SMTP id 2adb3069b0e04-5a1629f4182mr4265107e87.19.1773668089954; Mon, 16 Mar 2026 06:34:49 -0700 (PDT) Received: from ribalda.c.googlers.com (27.69.88.34.bc.googleusercontent.com. [34.88.69.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5a156366a7fsm3481473e87.76.2026.03.16.06.34.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Mar 2026 06:34:49 -0700 (PDT) From: Ricardo Ribalda Date: Mon, 16 Mar 2026 13:34:47 +0000 Subject: [PATCH v3 4/4] media: uvcvideo: RFC: Convert allow_privacy_override into Kconfig Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260316-uvcdynctrl-v3-4-19cd4657e1f3@chromium.org> References: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> In-Reply-To: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> To: Laurent Pinchart , Hans de Goede , Mauro Carvalho Chehab , Greg Kroah-Hartman Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Ricardo Ribalda X-Mailer: b4 0.14.3 This patch is just shared for discussion purposes! Do not land. In a perfect world, after a deprecation process, we will be able to remove allow_privacy_override and block all privacy related controls. If there is any usecase out in the field that resists, we shall move it into a Kconfig. This patch shows how the transition to Kconfig can look. Signed-off-by: Ricardo Ribalda --- drivers/media/usb/uvc/Kconfig | 11 +++++++++++ drivers/media/usb/uvc/uvc_ctrl.c | 4 ++-- drivers/media/usb/uvc/uvc_driver.c | 20 -------------------- drivers/media/usb/uvc/uvc_v4l2.c | 4 ++-- drivers/media/usb/uvc/uvcvideo.h | 1 - 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/media/usb/uvc/Kconfig b/drivers/media/usb/uvc/Kconfig index 579532272fd6..7c0f2260d135 100644 --- a/drivers/media/usb/uvc/Kconfig +++ b/drivers/media/usb/uvc/Kconfig @@ -20,3 +20,14 @@ config USB_VIDEO_CLASS_INPUT_EVDEV to report button events. =20 If you are in doubt, say Y. + +config USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE + bool "Allow overriding the privacy controls" + default n + depends on USB_VIDEO_CLASS && BROKEN + help + If this option is enabled, the privacy related controls, such as + the ones controlling the privacy LED will be accessible from + userspace. + + If you are in doubt, say N. diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_c= trl.c index 3ca108b83f1d..c9c195974765 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -3075,9 +3075,9 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, } =20 if (uvc_ctrl_is_privacy_control(entity->guid, xqry->selector) && - !uvc_allow_privacy_override_param) { + !IS_ENABLED(CONFIG_USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE)) { dev_warn_once(&chain->dev->intf->dev, - "Privacy related controls can only be accessed if module paramete= r allow_privacy_override is true\n"); + "Privacy related controls can only be accessed if CONFIG_USB_VIDE= O_CLASS_ALLOW_PRIVACY_OVERRIDE is true\n"); uvc_dbg(chain->dev, CONTROL, "Blocking access to privacy related Control= %pUl/%u\n", entity->guid, xqry->selector); return -EACCES; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc= _driver.c index 74c9dea29d36..b0ca81d924b6 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -36,7 +36,6 @@ unsigned int uvc_no_drop_param =3D 1; static unsigned int uvc_quirks_param =3D -1; unsigned int uvc_dbg_param; unsigned int uvc_timeout_param =3D UVC_CTRL_STREAMING_TIMEOUT; -bool uvc_allow_privacy_override_param; =20 static struct usb_driver uvc_driver; =20 @@ -2506,25 +2505,6 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); module_param_named(timeout, uvc_timeout_param, uint, 0644); MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); =20 -static int param_set_privacy(const char *val, const struct kernel_param *k= p) -{ - pr_warn_once("uvcvideo: " DEPRECATED - "allow_privacy_override parameter will be eventually removed.\n"); - return param_set_bool(val, kp); -} - -static const struct kernel_param_ops param_ops_privacy =3D { - .set =3D param_set_privacy, - .get =3D param_get_bool, -}; - -param_check_bool(allow_privacy_override, &uvc_allow_privacy_override_param= ); -module_param_cb(allow_privacy_override, ¶m_ops_privacy, - &uvc_allow_privacy_override_param, 0644); -__MODULE_PARM_TYPE(allow_privacy_override, "bool"); -MODULE_PARM_DESC(allow_privacy_override, - "Allow access to privacy related controls"); - /* ------------------------------------------------------------------------ * Driver initialization and cleanup */ diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v= 4l2.c index 6d4f027c8402..f83abbd13aca 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -134,9 +134,9 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain= *chain, } =20 if (uvc_ctrl_is_privacy_control(xmap->entity, xmap->selector) && - !uvc_allow_privacy_override_param) { + !IS_ENABLED(CONFIG_USB_VIDEO_CLASS_ALLOW_PRIVACY_OVERRIDE)) { dev_warn_once(&chain->dev->intf->dev, - "Privacy related controls can only be mapped if module parameter = allow_privacy_override is true\n"); + "Privacy related controls can only be mapped if CONFIG_USB_VIDEO_= CLASS_ALLOW_PRIVACY_OVERRIDE is true\n"); return -EACCES; } =20 diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvi= deo.h index 362110d58ca3..2898384d5f78 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -664,7 +664,6 @@ extern unsigned int uvc_no_drop_param; extern unsigned int uvc_dbg_param; extern unsigned int uvc_timeout_param; extern unsigned int uvc_hw_timestamps_param; -extern bool uvc_allow_privacy_override_param; =20 #define uvc_dbg(_dev, flag, fmt, ...) \ do { \ --=20 2.53.0.851.ga537e3e6e9-goog