* [PATCH 0/4] media: uvcvideo: Map known XU controls
@ 2025-11-17 20:14 Ricardo Ribalda
2025-11-17 20:14 ` [PATCH 1/4] media: uvcvideo: Remove nodrop parameter Ricardo Ribalda
` (3 more replies)
0 siblings, 4 replies; 23+ messages in thread
From: Ricardo Ribalda @ 2025-11-17 20:14 UTC (permalink / raw)
To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
Greg Kroah-Hartman
Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda,
Manav Gautama, Martin Rubli
The UVC driver uses a custom ioctl `UVCIOC_CTRL_MAP` to map XU controls
into v4l2 controls. The most well know user of this feature is the
uvcdynctrl app.
This app has a set of XML files which contains the list of mappings.
Some of these mappings are standard and other ones are custom.
This series move the standard mappings to the kernel driver, so
userspace do not need to depend on external apps to use them.
While we are at it we realized that some of the mappings can be harmful
for the privacy of the user. This series introduce a mechanism to block
those mappings.
While we are at it, we complete the deprecation of the nodrop parameter.
Ideally, this patch should belong in a different series, but then we
will have conflicts... and who wants to works twice?
I have tried this series with a Logitech Webcam Pro 9000, that has been
donated by Hans de Goede (Thanks Hans!!!).
Without this patch and uvcdynctrl the device has 14 controls. (Ctrls A)
With this patch the device has 15 controls (Ctrls B):
Ctrls A
+
control 0x009a090a `Focus, Absolute' min 0 max 255 step 0 default 0 current 0
With uvcdynctrl and this patch the device has 17 controls (Ctrls C):
Ctrls B
+
control 0x0a046d71 `Disable video processing' min 0 max 1 step 1 default 0 current 0
control 0x0a046d72 `Raw bits per pixel' min 0 max 1 step 1 default 0 current 0
With uvcdynctrl and without this patch the device has 19 controls:
Ctrls C
+
control 0x0a046d05 `LED1 Mode' min 0 max 3 step 1 default 3 current 3
0: Off
1: On
2: Blinking
3: Auto (*)
control 0x0a046d06 `LED1 Frequency' min 0 max 255 step 1 default 0 current 0
BTW, Driver tested with virtme-ng. First time that I use it for uvc
development, and it works like a charm :).
virtme-run --kimg arch/x86/boot/bzImage --mods auto --show-command \
--show-boot-console --verbose --qemu-opts -usb -device qemu-xhci \
-device usb-host,hostbus=1,hostport=4
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
---
Ricardo Ribalda (4):
media: uvcvideo: Remove nodrop parameter
media: uvcvideo: Import standard controls from uvcdynctrl
media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP
media: uvcvideo: Introduce allow_privacy_override
.../userspace-api/media/drivers/uvcvideo.rst | 2 +
drivers/media/usb/uvc/uvc_ctrl.c | 161 +++++++++++++++++++++
drivers/media/usb/uvc/uvc_driver.c | 24 +--
drivers/media/usb/uvc/uvc_queue.c | 25 ----
drivers/media/usb/uvc/uvc_v4l2.c | 36 +++++
drivers/media/usb/uvc/uvcvideo.h | 2 +-
include/linux/usb/uvc.h | 10 ++
7 files changed, 215 insertions(+), 45 deletions(-)
---
base-commit: 1f2353f5a1af995efbf7bea44341aa0d03460b28
change-id: 20251117-uvcdynctrl-7b80f5bfbb41
Best regards,
--
Ricardo Ribalda <ribalda@chromium.org>
^ permalink raw reply [flat|nested] 23+ messages in thread* [PATCH 1/4] media: uvcvideo: Remove nodrop parameter 2025-11-17 20:14 [PATCH 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda @ 2025-11-17 20:14 ` Ricardo Ribalda 2025-11-19 4:20 ` Laurent Pinchart 2025-11-17 20:14 ` [PATCH 2/4] media: uvcvideo: Import standard controls from uvcdynctrl Ricardo Ribalda ` (2 subsequent siblings) 3 siblings, 1 reply; 23+ messages in thread From: Ricardo Ribalda @ 2025-11-17 20:14 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda We announced the deprecation intentions one year ago in the commit commit 40ed9e9b2808 ("media: uvcvideo: Announce the user our deprecation intentions"). We have not hear any complains, lets remove the nodrop parameter. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- drivers/media/usb/uvc/uvc_driver.c | 19 ------------------- drivers/media/usb/uvc/uvc_queue.c | 25 ------------------------- drivers/media/usb/uvc/uvcvideo.h | 1 - 3 files changed, 45 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index ee4f54d6834962414979a046afc59c5036455124..71563d8f4bcf581694ccd4b665ff52b629caa0b6 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -32,7 +32,6 @@ unsigned int uvc_clock_param = CLOCK_MONOTONIC; unsigned int uvc_hw_timestamps_param; -unsigned int uvc_no_drop_param = 1; static unsigned int uvc_quirks_param = -1; unsigned int uvc_dbg_param; unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; @@ -2468,24 +2467,6 @@ MODULE_PARM_DESC(clock, "Video buffers timestamp clock"); module_param_named(hwtimestamps, uvc_hw_timestamps_param, uint, 0644); MODULE_PARM_DESC(hwtimestamps, "Use hardware timestamps"); -static int param_set_nodrop(const char *val, const struct kernel_param *kp) -{ - pr_warn_once("uvcvideo: " - DEPRECATED - "nodrop parameter will be eventually removed.\n"); - return param_set_bool(val, kp); -} - -static const struct kernel_param_ops param_ops_nodrop = { - .set = param_set_nodrop, - .get = param_get_uint, -}; - -param_check_uint(nodrop, &uvc_no_drop_param); -module_param_cb(nodrop, ¶m_ops_nodrop, &uvc_no_drop_param, 0644); -__MODULE_PARM_TYPE(nodrop, "uint"); -MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); - module_param_named(quirks, uvc_quirks_param, uint, 0644); MODULE_PARM_DESC(quirks, "Forced device quirks"); module_param_named(trace, uvc_dbg_param, uint, 0644); diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index 790184c9843d211d34fa7d66801631d5a07450bd..3bc54456b4d98ed50b1ea250ce8501e67141e1ef 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -331,34 +331,9 @@ struct uvc_buffer *uvc_queue_get_current_buffer(struct uvc_video_queue *queue) return nextbuf; } -/* - * uvc_queue_buffer_requeue: Requeue a buffer on our internal irqqueue - * - * Reuse a buffer through our internal queue without the need to 'prepare'. - * The buffer will be returned to userspace through the uvc_buffer_queue call if - * the device has been disconnected. - */ -static void uvc_queue_buffer_requeue(struct uvc_video_queue *queue, - struct uvc_buffer *buf) -{ - buf->error = 0; - buf->state = UVC_BUF_STATE_QUEUED; - buf->bytesused = 0; - vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0); - - uvc_buffer_queue(&buf->buf.vb2_buf); -} - static void uvc_queue_buffer_complete(struct kref *ref) { struct uvc_buffer *buf = container_of(ref, struct uvc_buffer, ref); - struct vb2_buffer *vb = &buf->buf.vb2_buf; - struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); - - if (buf->error && !uvc_no_drop_param) { - uvc_queue_buffer_requeue(queue, buf); - return; - } buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused); diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index ed7bad31f75ca474c1037d666d5310c78dd764df..9a86d7f1f6ea022dace87614030bf0fde0d260f0 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -659,7 +659,6 @@ static inline struct uvc_fh *to_uvc_fh(struct file *filp) #define UVC_WARN_XU_GET_RES 2 extern unsigned int uvc_clock_param; -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; -- 2.52.0.rc1.455.g30608eb744-goog ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 1/4] media: uvcvideo: Remove nodrop parameter 2025-11-17 20:14 ` [PATCH 1/4] media: uvcvideo: Remove nodrop parameter Ricardo Ribalda @ 2025-11-19 4:20 ` Laurent Pinchart 0 siblings, 0 replies; 23+ messages in thread From: Laurent Pinchart @ 2025-11-19 4:20 UTC (permalink / raw) To: Ricardo Ribalda Cc: Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb On Mon, Nov 17, 2025 at 08:14:16PM +0000, Ricardo Ribalda wrote: > We announced the deprecation intentions one year ago in the commit > commit 40ed9e9b2808 ("media: uvcvideo: Announce the user our deprecation > intentions"). > > We have not hear any complains, lets remove the nodrop parameter. A year is short for users who run distributions based on LTS kernels. I don't object though. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> > --- > drivers/media/usb/uvc/uvc_driver.c | 19 ------------------- > drivers/media/usb/uvc/uvc_queue.c | 25 ------------------------- > drivers/media/usb/uvc/uvcvideo.h | 1 - > 3 files changed, 45 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c > index ee4f54d6834962414979a046afc59c5036455124..71563d8f4bcf581694ccd4b665ff52b629caa0b6 100644 > --- a/drivers/media/usb/uvc/uvc_driver.c > +++ b/drivers/media/usb/uvc/uvc_driver.c > @@ -32,7 +32,6 @@ > > unsigned int uvc_clock_param = CLOCK_MONOTONIC; > unsigned int uvc_hw_timestamps_param; > -unsigned int uvc_no_drop_param = 1; > static unsigned int uvc_quirks_param = -1; > unsigned int uvc_dbg_param; > unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; > @@ -2468,24 +2467,6 @@ MODULE_PARM_DESC(clock, "Video buffers timestamp clock"); > module_param_named(hwtimestamps, uvc_hw_timestamps_param, uint, 0644); > MODULE_PARM_DESC(hwtimestamps, "Use hardware timestamps"); > > -static int param_set_nodrop(const char *val, const struct kernel_param *kp) > -{ > - pr_warn_once("uvcvideo: " > - DEPRECATED > - "nodrop parameter will be eventually removed.\n"); > - return param_set_bool(val, kp); > -} > - > -static const struct kernel_param_ops param_ops_nodrop = { > - .set = param_set_nodrop, > - .get = param_get_uint, > -}; > - > -param_check_uint(nodrop, &uvc_no_drop_param); > -module_param_cb(nodrop, ¶m_ops_nodrop, &uvc_no_drop_param, 0644); > -__MODULE_PARM_TYPE(nodrop, "uint"); > -MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); > - > module_param_named(quirks, uvc_quirks_param, uint, 0644); > MODULE_PARM_DESC(quirks, "Forced device quirks"); > module_param_named(trace, uvc_dbg_param, uint, 0644); > diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c > index 790184c9843d211d34fa7d66801631d5a07450bd..3bc54456b4d98ed50b1ea250ce8501e67141e1ef 100644 > --- a/drivers/media/usb/uvc/uvc_queue.c > +++ b/drivers/media/usb/uvc/uvc_queue.c > @@ -331,34 +331,9 @@ struct uvc_buffer *uvc_queue_get_current_buffer(struct uvc_video_queue *queue) > return nextbuf; > } > > -/* > - * uvc_queue_buffer_requeue: Requeue a buffer on our internal irqqueue > - * > - * Reuse a buffer through our internal queue without the need to 'prepare'. > - * The buffer will be returned to userspace through the uvc_buffer_queue call if > - * the device has been disconnected. > - */ > -static void uvc_queue_buffer_requeue(struct uvc_video_queue *queue, > - struct uvc_buffer *buf) > -{ > - buf->error = 0; > - buf->state = UVC_BUF_STATE_QUEUED; > - buf->bytesused = 0; > - vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0); > - > - uvc_buffer_queue(&buf->buf.vb2_buf); > -} > - > static void uvc_queue_buffer_complete(struct kref *ref) > { > struct uvc_buffer *buf = container_of(ref, struct uvc_buffer, ref); > - struct vb2_buffer *vb = &buf->buf.vb2_buf; > - struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); > - > - if (buf->error && !uvc_no_drop_param) { > - uvc_queue_buffer_requeue(queue, buf); > - return; > - } > > buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; > vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused); > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h > index ed7bad31f75ca474c1037d666d5310c78dd764df..9a86d7f1f6ea022dace87614030bf0fde0d260f0 100644 > --- a/drivers/media/usb/uvc/uvcvideo.h > +++ b/drivers/media/usb/uvc/uvcvideo.h > @@ -659,7 +659,6 @@ static inline struct uvc_fh *to_uvc_fh(struct file *filp) > #define UVC_WARN_XU_GET_RES 2 > > extern unsigned int uvc_clock_param; > -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; -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 2/4] media: uvcvideo: Import standard controls from uvcdynctrl 2025-11-17 20:14 [PATCH 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda 2025-11-17 20:14 ` [PATCH 1/4] media: uvcvideo: Remove nodrop parameter Ricardo Ribalda @ 2025-11-17 20:14 ` Ricardo Ribalda 2025-11-19 4:21 ` Laurent Pinchart 2025-11-17 20:14 ` [PATCH 3/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP Ricardo Ribalda 2025-11-17 20:14 ` [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override Ricardo Ribalda 3 siblings, 1 reply; 23+ messages in thread From: Ricardo Ribalda @ 2025-11-17 20:14 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda, Manav Gautama, Martin Rubli 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. 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 = V4L2_CID_FLASH_MODE, .entity = UVC_GUID_SIS_LED_HW_CONTROL, .selector = 4, .size = 4, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask = 0x3, .menu_mapping = { 0x20, 0x22 }, .menu_names = { "Off", "On" }, }, { .id = V4L2_CID_FLASH_FREQUENCY, .entity = UVC_GUID_SIS_LED_HW_CONTROL, .selector = 4, .size = 8, .offset = 16, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_LED1_MODE, .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, .selector = 1, .size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask = 0xF, .menu_mapping = { 0, 1, 2, 3 }, .menu_names = { "Off", "On", "Blinking", "Auto" }, }, { .id = V4L2_CID_LED1_FREQUENCY, .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, .selector = 1, .size = 8, .offset = 16, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_DISABLE_PROCESSING, .entity = UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector = 5, .size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id = V4L2_CID_RAW_BITS_PER_PIXEL, .entity = UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector = 8, .size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_RAW_BITS_PER_PIXEL, .entity = UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector = 8, .size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_LED1_MODE, .entity = UVC_GUID_LOGITECH_PERIPHERAL, .selector = 0x09, .size = 2, .offset = 8, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask = 0xF, .menu_mapping = { 0, 1, 2, 3 }, .menu_names = { "Off", "On", "Blink", "Auto" }, }, { .id = V4L2_CID_LED1_FREQUENCY, .entity = UVC_GUID_LOGITECH_PERIPHERAL, .selector = 0x09, .size = 8, .offset = 24, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = 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 = constant.find(ns + "id").text value = constant.find(ns + "value").text return (id, value) def get_constants(ns, root): out = dict() for constant in root.iter(ns + "constant"): attr = constant.attrib if attr["type"] == "integer": id, value = get_single_guid(ns, constant) if id in out: print(f"dupe constant {id}") out[id] = value return out def get_guids(ns, root): out = dict() for constant in root.iter(ns + "constant"): attr = constant.attrib if attr["type"] == "guid": id, value = get_single_guid(ns, constant) if id in out: print(f"dupe guid {id}") out[id] = value return out def get_single_control(ns, control): out = {} for id in "entity", "selector", "index", "size", "description": v = control.find(ns + id) if v is None and id == "description": continue out[id] = v.text reqs = set() for r in control.find(ns + "requests"): reqs.add(r.text) out["requests"] = reqs return (control.attrib["id"], out) def get_controls(ns, root): out = dict() for control in root.iter(ns + "control"): id, value = get_single_control(ns, control) if id in out: print(f"Dupe control id {id}") out[id] = value return out def get_single_mapping(ns, mapping): out = {} out["name"] = mapping.find(ns + "name").text uvc = mapping.find(ns + "uvc") for id in "size", "offset", "uvc_type": out[id] = uvc.find(ns + id).text out["control_ref"] = uvc.find(ns + "control_ref").attrib["idref"] v4l2 = mapping.find(ns + "v4l2") for id in "id", "v4l2_type": out[id] = v4l2.find(ns + id).text menu = {} for entry in v4l2.iter(ns + "menu_entry"): menu[entry.attrib["name"]] = entry.attrib["value"] if menu: out["menu"] = menu return out def get_mapping(ns, root): out = [] for control in root.iter(ns + "mapping"): mapping = get_single_mapping(ns, control) out += [mapping] return out def print_guids(guids): for g in guids: print(f"#define {g} \\") u_bytes = uuid.UUID(guids[g]).bytes_le u_bytes = [f"0x{b:02x}" for b in u_bytes] print("\t{ " + ", ".join(u_bytes) + " }") def print_flags(flags): get_range = {"GET_MIN", "GET_DEF", "GET_MAX", "GET_CUR", "GET_RES"} if get_range.issubset(flags): flags -= get_range flags.add("GET_RANGE") flags = list(flags) flags.sort() out = "" for f in flags[:-1]: out += f"UVC_CTRL_FLAG_{f}\n\t\t\t\t| " out += 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 = controls[id] if "description" in c: print_description(c["description"]) print( f"""\t{{ \t\t.entity\t\t= {c["entity"]}, \t\t.selector\t= {cons[c["selector"]]}, \t\t.index\t\t= {c["index"]}, \t\t.size\t\t= {c["size"]}, \t\t.flags\t\t= {print_flags(c["requests"])}, \t}},""" ) def menu_mapping_txt(menu): out = f"\n\t\t.menu_mask\t= 0x{((1<<len(menu))-1):X},\n" out += f"\t\t.menu_mapping\t= {{ {", ".join(menu.values())} }},\n" out += f"\t\t.menu_names\t= {{ \"{"\", \"".join(menu.keys())}\" }},\n" return out def print_mappings(mappings, controls, cons): for m in mappings: c = controls[m["control_ref"]] if "menu" in m: menu_mapping = menu_mapping_txt(m["menu"]) else: menu_mapping = "" print( f"""\t{{ \t\t.id\t\t= {m["id"]}, \t\t.entity\t\t= {c["entity"]}, \t\t.selector\t= {cons[c["selector"]]}, \t\t.size\t\t= {m["size"]}, \t\t.offset\t\t= {m["offset"]}, \t\t.v4l2_type\t= {m["v4l2_type"]}, \t\t.data_type\t= {m["uvc_type"]},{menu_mapping} \t}},""" ) def print_code(guids, cons, controls, mappings): used_controls = set() for m in mappings: used_controls.add(m["control_ref"]) used_guids = set() for c in used_controls: used_guids.add(controls[c]["entity"]) print("\n######GUIDs#######\n") print_guids({id: guids[id] for id in guids if id in used_guids}) print("\n######CONTROLS#######\n") print_controls({id: controls[id] for id in controls if id in used_controls}, cons) print("\n######MAPPINGS#######\n") print_mappings(mappings, controls, cons) # print(guids) # print(used_controls) root = ET.fromstring(sys.stdin.read()) ns = get_namespace(root) cons = get_constants(ns, root) guids = get_guids(ns, root) controls = get_controls(ns, root) mappings = get_mapping(ns, root) print_code(guids, cons, controls, mappings) Cc: Manav Gautama <bandwidthcrunch@gmail.com> Cc: Martin Rubli <martin_rubli@logitech.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- drivers/media/usb/uvc/uvc_ctrl.c | 161 +++++++++++++++++++++++++++++++++++++++ include/linux/usb/uvc.h | 6 ++ 2 files changed, 167 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 2905505c240c060e5034ea12d33b59d5702f2e1f..5c0398c81334649649ff654f903d03e16381a865 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -385,6 +385,86 @@ static const struct uvc_control_info uvc_ctrls[] = { | 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 = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 1, + .index = 0, + .size = 4, + .flags = 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 = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 2, + .index = 1, + .size = 1, + .flags = 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 = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 3, + .index = 2, + .size = 6, + .flags = 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, + }, + { + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 1, + .index = 0, + .size = 4, + .flags = 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, + }, + { + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 2, + .index = 1, + .size = 1, + .flags = 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, + }, }; static const u32 uvc_control_classes[] = { @@ -1009,6 +1089,87 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .menu_mask = BIT(V4L2_COLORFX_VIVID) | BIT(V4L2_COLORFX_NONE), }, + { + .id = V4L2_CID_PAN_RELATIVE, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 1, + .size = 16, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_TILT_RELATIVE, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 1, + .size = 16, + .offset = 16, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_PAN_RESET, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 2, + .size = 1, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_TILT_RESET, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 2, + .size = 1, + .offset = 1, + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_PAN_RELATIVE, + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 1, + .size = 16, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_TILT_RELATIVE, + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 1, + .size = 16, + .offset = 16, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_PAN_RESET, + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 2, + .size = 1, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_TILT_RESET, + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 2, + .size = 1, + .offset = 1, + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_FOCUS_ABSOLUTE, + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector = 3, + .size = 8, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, }; /* ------------------------------------------------------------------------ diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index 22e0dab0809e296e089940620ae0e8838e109701..b939a01da11466747249c64c72a3ea40cd364a59 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -35,6 +35,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 } /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ #define UVC_MSXU_CONTROL_FOCUS 0x01 -- 2.52.0.rc1.455.g30608eb744-goog ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 2/4] media: uvcvideo: Import standard controls from uvcdynctrl 2025-11-17 20:14 ` [PATCH 2/4] media: uvcvideo: Import standard controls from uvcdynctrl Ricardo Ribalda @ 2025-11-19 4:21 ` Laurent Pinchart 0 siblings, 0 replies; 23+ messages in thread From: Laurent Pinchart @ 2025-11-19 4:21 UTC (permalink / raw) To: Ricardo Ribalda Cc: Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb, Manav Gautama, Martin Rubli Hi Ricardo, Thank you for the patch. On Mon, Nov 17, 2025 at 08:14:17PM +0000, Ricardo Ribalda wrote: > 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. I'd expand this a bit for historians: 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. > This patch adds the mappings from the uvcdynctrl into the driver. Hopefully > this effort can help in deprecating the UVCIOC_CTRL_MAP ioctl. > > 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 = V4L2_CID_FLASH_MODE, > .entity = UVC_GUID_SIS_LED_HW_CONTROL, > .selector = 4, > .size = 4, > .offset = 0, > .v4l2_type = V4L2_CTRL_TYPE_MENU, > .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > .menu_mask = 0x3, > .menu_mapping = { 0x20, 0x22 }, > .menu_names = { "Off", "On" }, > > }, > { > .id = V4L2_CID_FLASH_FREQUENCY, > .entity = UVC_GUID_SIS_LED_HW_CONTROL, > .selector = 4, > .size = 8, > .offset = 16, > .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > }, > { > .id = V4L2_CID_LED1_MODE, > .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, > .selector = 1, > .size = 8, > .offset = 0, > .v4l2_type = V4L2_CTRL_TYPE_MENU, > .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > .menu_mask = 0xF, > .menu_mapping = { 0, 1, 2, 3 }, > .menu_names = { "Off", "On", "Blinking", "Auto" }, > > }, > { > .id = V4L2_CID_LED1_FREQUENCY, > .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, > .selector = 1, > .size = 8, > .offset = 16, > .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > }, > { > .id = V4L2_CID_DISABLE_PROCESSING, > .entity = UVC_GUID_LOGITECH_VIDEO_PIPE_V1, > .selector = 5, > .size = 8, > .offset = 0, > .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, > .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, > }, > { > .id = V4L2_CID_RAW_BITS_PER_PIXEL, > .entity = UVC_GUID_LOGITECH_VIDEO_PIPE_V1, > .selector = 8, > .size = 8, > .offset = 0, > .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > }, > { > .id = V4L2_CID_RAW_BITS_PER_PIXEL, > .entity = UVC_GUID_LOGITECH_VIDEO_PIPE_V1, > .selector = 8, > .size = 8, > .offset = 0, > .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > }, Duplicate control. > { > .id = V4L2_CID_LED1_MODE, > .entity = UVC_GUID_LOGITECH_PERIPHERAL, > .selector = 0x09, > .size = 2, > .offset = 8, > .v4l2_type = V4L2_CTRL_TYPE_MENU, > .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > .menu_mask = 0xF, > .menu_mapping = { 0, 1, 2, 3 }, > .menu_names = { "Off", "On", "Blink", "Auto" }, > > }, > { > .id = V4L2_CID_LED1_FREQUENCY, > .entity = UVC_GUID_LOGITECH_PERIPHERAL, > .selector = 0x09, > .size = 8, > .offset = 24, > .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > .data_type = 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 = constant.find(ns + "id").text > value = constant.find(ns + "value").text > return (id, value) > > def get_constants(ns, root): > out = dict() > for constant in root.iter(ns + "constant"): > attr = constant.attrib > if attr["type"] == "integer": > id, value = get_single_guid(ns, constant) > if id in out: > print(f"dupe constant {id}") > out[id] = value > > return out > > def get_guids(ns, root): > out = dict() > for constant in root.iter(ns + "constant"): > attr = constant.attrib > if attr["type"] == "guid": > id, value = get_single_guid(ns, constant) > if id in out: > print(f"dupe guid {id}") > out[id] = value > > return out > > def get_single_control(ns, control): > out = {} > for id in "entity", "selector", "index", "size", "description": > v = control.find(ns + id) > if v is None and id == "description": > continue > out[id] = v.text > > reqs = set() > for r in control.find(ns + "requests"): > reqs.add(r.text) > out["requests"] = reqs > > return (control.attrib["id"], out) > > def get_controls(ns, root): > out = dict() > for control in root.iter(ns + "control"): > id, value = get_single_control(ns, control) > if id in out: > print(f"Dupe control id {id}") > out[id] = value > > return out > > def get_single_mapping(ns, mapping): > out = {} > out["name"] = mapping.find(ns + "name").text > uvc = mapping.find(ns + "uvc") > for id in "size", "offset", "uvc_type": > out[id] = uvc.find(ns + id).text > out["control_ref"] = uvc.find(ns + "control_ref").attrib["idref"] > > v4l2 = mapping.find(ns + "v4l2") > for id in "id", "v4l2_type": > out[id] = v4l2.find(ns + id).text > > menu = {} > for entry in v4l2.iter(ns + "menu_entry"): > menu[entry.attrib["name"]] = entry.attrib["value"] > if menu: > out["menu"] = menu > > return out > > def get_mapping(ns, root): > out = [] > for control in root.iter(ns + "mapping"): > mapping = get_single_mapping(ns, control) > out += [mapping] > > return out > > def print_guids(guids): > for g in guids: > print(f"#define {g} \\") > u_bytes = uuid.UUID(guids[g]).bytes_le > u_bytes = [f"0x{b:02x}" for b in u_bytes] > print("\t{ " + ", ".join(u_bytes) + " }") > > def print_flags(flags): > get_range = {"GET_MIN", "GET_DEF", "GET_MAX", "GET_CUR", "GET_RES"} > if get_range.issubset(flags): > flags -= get_range > flags.add("GET_RANGE") > > flags = list(flags) > flags.sort() > out = "" > for f in flags[:-1]: > out += f"UVC_CTRL_FLAG_{f}\n\t\t\t\t| " > > out += 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 = controls[id] > if "description" in c: > print_description(c["description"]) > print( > f"""\t{{ > \t\t.entity\t\t= {c["entity"]}, > \t\t.selector\t= {cons[c["selector"]]}, > \t\t.index\t\t= {c["index"]}, > \t\t.size\t\t= {c["size"]}, > \t\t.flags\t\t= {print_flags(c["requests"])}, > \t}},""" > ) > > def menu_mapping_txt(menu): > out = f"\n\t\t.menu_mask\t= 0x{((1<<len(menu))-1):X},\n" > out += f"\t\t.menu_mapping\t= {{ {", ".join(menu.values())} }},\n" > out += f"\t\t.menu_names\t= {{ \"{"\", \"".join(menu.keys())}\" }},\n" > return out > > def print_mappings(mappings, controls, cons): > for m in mappings: > c = controls[m["control_ref"]] > > if "menu" in m: > menu_mapping = menu_mapping_txt(m["menu"]) > else: > menu_mapping = "" > print( > f"""\t{{ > \t\t.id\t\t= {m["id"]}, > \t\t.entity\t\t= {c["entity"]}, > \t\t.selector\t= {cons[c["selector"]]}, > \t\t.size\t\t= {m["size"]}, > \t\t.offset\t\t= {m["offset"]}, > \t\t.v4l2_type\t= {m["v4l2_type"]}, > \t\t.data_type\t= {m["uvc_type"]},{menu_mapping} > \t}},""" > ) > > def print_code(guids, cons, controls, mappings): > used_controls = set() > for m in mappings: > used_controls.add(m["control_ref"]) > > used_guids = set() > for c in used_controls: > used_guids.add(controls[c]["entity"]) > > print("\n######GUIDs#######\n") > print_guids({id: guids[id] for id in guids if id in used_guids}) > print("\n######CONTROLS#######\n") > print_controls({id: controls[id] for id in controls if id in used_controls}, cons) > print("\n######MAPPINGS#######\n") > print_mappings(mappings, controls, cons) > # print(guids) > # print(used_controls) > > root = ET.fromstring(sys.stdin.read()) > ns = get_namespace(root) > cons = get_constants(ns, root) > guids = get_guids(ns, root) > controls = get_controls(ns, root) > mappings = get_mapping(ns, root) > print_code(guids, cons, controls, mappings) > > Cc: Manav Gautama <bandwidthcrunch@gmail.com> > Cc: Martin Rubli <martin_rubli@logitech.com> > Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> > --- > drivers/media/usb/uvc/uvc_ctrl.c | 161 +++++++++++++++++++++++++++++++++++++++ > include/linux/usb/uvc.h | 6 ++ > 2 files changed, 167 insertions(+) > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > index 2905505c240c060e5034ea12d33b59d5702f2e1f..5c0398c81334649649ff654f903d03e16381a865 100644 > --- a/drivers/media/usb/uvc/uvc_ctrl.c > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > @@ -385,6 +385,86 @@ static const struct uvc_control_info uvc_ctrls[] = { > | 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 = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, > + .selector = 1, > + .index = 0, > + .size = 4, > + .flags = 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 = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, > + .selector = 2, > + .index = 1, > + .size = 1, > + .flags = 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 = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, > + .selector = 3, > + .index = 2, > + .size = 6, > + .flags = 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, > + }, A comment would be nice here too. With that, Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > + { > + .entity = UVC_GUID_LOGITECH_PERIPHERAL, > + .selector = 1, > + .index = 0, > + .size = 4, > + .flags = 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, > + }, > + { > + .entity = UVC_GUID_LOGITECH_PERIPHERAL, > + .selector = 2, > + .index = 1, > + .size = 1, > + .flags = 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, > + }, > }; > > static const u32 uvc_control_classes[] = { > @@ -1009,6 +1089,87 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { > .menu_mask = BIT(V4L2_COLORFX_VIVID) | > BIT(V4L2_COLORFX_NONE), > }, > + { > + .id = V4L2_CID_PAN_RELATIVE, > + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, > + .selector = 1, > + .size = 16, > + .offset = 0, > + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, > + }, > + { > + .id = V4L2_CID_TILT_RELATIVE, > + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, > + .selector = 1, > + .size = 16, > + .offset = 16, > + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, > + }, > + { > + .id = V4L2_CID_PAN_RESET, > + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, > + .selector = 2, > + .size = 1, > + .offset = 0, > + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, > + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > + }, > + { > + .id = V4L2_CID_TILT_RESET, > + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, > + .selector = 2, > + .size = 1, > + .offset = 1, > + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, > + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > + }, > + { > + .id = V4L2_CID_PAN_RELATIVE, > + .entity = UVC_GUID_LOGITECH_PERIPHERAL, > + .selector = 1, > + .size = 16, > + .offset = 0, > + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, > + }, > + { > + .id = V4L2_CID_TILT_RELATIVE, > + .entity = UVC_GUID_LOGITECH_PERIPHERAL, > + .selector = 1, > + .size = 16, > + .offset = 16, > + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, > + }, > + { > + .id = V4L2_CID_PAN_RESET, > + .entity = UVC_GUID_LOGITECH_PERIPHERAL, > + .selector = 2, > + .size = 1, > + .offset = 0, > + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, > + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > + }, > + { > + .id = V4L2_CID_TILT_RESET, > + .entity = UVC_GUID_LOGITECH_PERIPHERAL, > + .selector = 2, > + .size = 1, > + .offset = 1, > + .v4l2_type = V4L2_CTRL_TYPE_BUTTON, > + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > + }, > + { > + .id = V4L2_CID_FOCUS_ABSOLUTE, > + .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, > + .selector = 3, > + .size = 8, > + .offset = 0, > + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, > + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, > + }, > }; > > /* ------------------------------------------------------------------------ > diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h > index 22e0dab0809e296e089940620ae0e8838e109701..b939a01da11466747249c64c72a3ea40cd364a59 100644 > --- a/include/linux/usb/uvc.h > +++ b/include/linux/usb/uvc.h > @@ -35,6 +35,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 } > > /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ > #define UVC_MSXU_CONTROL_FOCUS 0x01 -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 3/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP 2025-11-17 20:14 [PATCH 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda 2025-11-17 20:14 ` [PATCH 1/4] media: uvcvideo: Remove nodrop parameter Ricardo Ribalda 2025-11-17 20:14 ` [PATCH 2/4] media: uvcvideo: Import standard controls from uvcdynctrl Ricardo Ribalda @ 2025-11-17 20:14 ` Ricardo Ribalda 2025-11-19 4:21 ` Laurent Pinchart 2025-11-17 20:14 ` [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override Ricardo Ribalda 3 siblings, 1 reply; 23+ messages in thread From: Ricardo Ribalda @ 2025-11-17 20:14 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda 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. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- 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/Documentation/userspace-api/media/drivers/uvcvideo.rst index dbb30ad389ae4d53bc734b4269ebea20ecdd7535..b09d2f8ba66ecde67f1e35fd77858a505ad44eb1 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**This IOCTL is deprecated and will be eventually removed** + Argument: struct uvc_xu_control_mapping **Description**: diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 9e4a251eca88085a1b4e0e854370015855be92ee..03c64b5698bf4331fed8437fa6e9c726a07450bd 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1044,6 +1044,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); case UVCIOC_CTRL_QUERY: @@ -1158,6 +1160,8 @@ static long uvc_v4l2_compat_ioctl32(struct file *file, switch (cmd) { case UVCIOC_CTRL_MAP32: + pr_warn_once("uvcvideo: " DEPRECATED + "UVCIOC_CTRL_MAP32 ioctl will be eventually removed.\n"); ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); if (ret) break; -- 2.52.0.rc1.455.g30608eb744-goog ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 3/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP 2025-11-17 20:14 ` [PATCH 3/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP Ricardo Ribalda @ 2025-11-19 4:21 ` Laurent Pinchart 0 siblings, 0 replies; 23+ messages in thread From: Laurent Pinchart @ 2025-11-19 4:21 UTC (permalink / raw) To: Ricardo Ribalda Cc: Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Ricardo, Thank you for the patch. On Mon, Nov 17, 2025 at 08:14:18PM +0000, Ricardo Ribalda wrote: > 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. > > Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > 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/Documentation/userspace-api/media/drivers/uvcvideo.rst > index dbb30ad389ae4d53bc734b4269ebea20ecdd7535..b09d2f8ba66ecde67f1e35fd77858a505ad44eb1 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 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > +**This IOCTL is deprecated and will be eventually removed** > + > Argument: struct uvc_xu_control_mapping > > **Description**: > diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c > index 9e4a251eca88085a1b4e0e854370015855be92ee..03c64b5698bf4331fed8437fa6e9c726a07450bd 100644 > --- a/drivers/media/usb/uvc/uvc_v4l2.c > +++ b/drivers/media/usb/uvc/uvc_v4l2.c > @@ -1044,6 +1044,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); > > case UVCIOC_CTRL_QUERY: > @@ -1158,6 +1160,8 @@ static long uvc_v4l2_compat_ioctl32(struct file *file, > > switch (cmd) { > case UVCIOC_CTRL_MAP32: > + pr_warn_once("uvcvideo: " DEPRECATED > + "UVCIOC_CTRL_MAP32 ioctl will be eventually removed.\n"); > ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); > if (ret) > break; -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-17 20:14 [PATCH 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda ` (2 preceding siblings ...) 2025-11-17 20:14 ` [PATCH 3/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP Ricardo Ribalda @ 2025-11-17 20:14 ` Ricardo Ribalda 2025-11-17 21:10 ` Gergo Koteles 2025-11-18 11:14 ` Greg Kroah-Hartman 3 siblings, 2 replies; 23+ messages in thread From: Ricardo Ribalda @ 2025-11-17 20:14 UTC (permalink / raw) To: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb, Ricardo Ribalda 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. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> --- drivers/media/usb/uvc/uvc_driver.c | 5 +++++ drivers/media/usb/uvc/uvc_v4l2.c | 32 ++++++++++++++++++++++++++++++++ drivers/media/usb/uvc/uvcvideo.h | 1 + include/linux/usb/uvc.h | 4 ++++ 4 files changed, 42 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 71563d8f4bcf581694ccd4b665ff52b629caa0b6..d50c501121e6f774dfd6cfdb859279e0860d06a5 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -35,6 +35,7 @@ unsigned int uvc_hw_timestamps_param; static unsigned int uvc_quirks_param = -1; unsigned int uvc_dbg_param; unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; +bool uvc_allow_privacy_override_param; static struct usb_driver uvc_driver; @@ -2473,6 +2474,10 @@ module_param_named(trace, uvc_dbg_param, uint, 0644); MODULE_PARM_DESC(trace, "Trace level bitmask"); module_param_named(timeout, uvc_timeout_param, uint, 0644); MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); +module_param_named(allow_privacy_override, uvc_allow_privacy_override_param, + bool, 0644); +MODULE_PARM_DESC(allow_privacy_override, + "Allow UVCIOC_CTRL_MAP ioctl map privacy related control"); /* ------------------------------------------------------------------------ * Driver initialization and cleanup diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 03c64b5698bf4331fed8437fa6e9c726a07450bd..e067b8f38500299fe6acc7e3b9770f7374748823 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -18,6 +18,7 @@ #include <linux/mm.h> #include <linux/wait.h> #include <linux/atomic.h> +#include <linux/usb/uvc.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> @@ -121,6 +122,32 @@ static int uvc_control_add_xu_mapping(struct uvc_video_chain *chain, /* ------------------------------------------------------------------------ * UVC ioctls */ + +static bool uvc_is_privacy_mapping(struct uvc_xu_control_mapping *xmap) +{ + struct mapping { + u8 entity[16]; + u8 selector; + } privacy_mappings[] = { + { + .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, + .selector = 1, + }, + { + .entity = UVC_GUID_LOGITECH_PERIPHERAL, + .selector = 9, + }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(privacy_mappings); i++) + if (!memcmp(xmap->entity, privacy_mappings[i].entity, 16) && + xmap->selector == privacy_mappings[i].selector) + return true; + + return false; +} + static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, struct uvc_xu_control_mapping *xmap) { @@ -133,6 +160,11 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, return -EINVAL; } + if (uvc_is_privacy_mapping(xmap) && !uvc_allow_privacy_override_param) { + pr_warn_once("uvcvideo: Privacy related controls can only be mapped if param allow_privacy_override is true\n"); + return -EINVAL; + } + map = kzalloc(sizeof(*map), GFP_KERNEL); if (map == NULL) return -ENOMEM; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 9a86d7f1f6ea022dace87614030bf0fde0d260f0..1895e4fe45e9c0246b7f0613dd2bc51f60b78759 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -662,6 +662,7 @@ extern unsigned int uvc_clock_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; #define uvc_dbg(_dev, flag, fmt, ...) \ do { \ diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index b939a01da11466747249c64c72a3ea40cd364a59..f2d6cf52427ce9c0a62a80ca3629c6e350fa02c8 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -41,6 +41,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 } + /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ #define UVC_MSXU_CONTROL_FOCUS 0x01 -- 2.52.0.rc1.455.g30608eb744-goog ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-17 20:14 ` [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override Ricardo Ribalda @ 2025-11-17 21:10 ` Gergo Koteles 2025-11-18 6:21 ` Ricardo Ribalda 2025-11-18 11:14 ` Greg Kroah-Hartman 1 sibling, 1 reply; 23+ messages in thread From: Gergo Koteles @ 2025-11-17 21:10 UTC (permalink / raw) To: Ricardo Ribalda, Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman Cc: linux-media, linux-kernel, linux-usb Hi Ricardo, On Mon, 2025-11-17 at 20:14 +0000, Ricardo Ribalda wrote: > + if (uvc_is_privacy_mapping(xmap) && !uvc_allow_privacy_override_param) { > + pr_warn_once("uvcvideo: Privacy related controls can only be mapped if param allow_privacy_override is true\n"); > + return -EINVAL; > + } > + To really prevent the LED from being turned off, it should also be added to uvc_xu_ctrl_query. But why has it become so important after 10+ years that it cannot be turned off on Linux? What has changed? The majority of users use open-source software, they can view the source at any time. Gergo ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-17 21:10 ` Gergo Koteles @ 2025-11-18 6:21 ` Ricardo Ribalda 2025-11-18 8:48 ` Gergo Koteles 0 siblings, 1 reply; 23+ messages in thread From: Ricardo Ribalda @ 2025-11-18 6:21 UTC (permalink / raw) To: Gergo Koteles Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb On Mon, 17 Nov 2025 at 22:10, Gergo Koteles <soyer@irl.hu> wrote: > > Hi Ricardo, Hi Gergo > > On Mon, 2025-11-17 at 20:14 +0000, Ricardo Ribalda wrote: > > + if (uvc_is_privacy_mapping(xmap) && !uvc_allow_privacy_override_param) { > > + pr_warn_once("uvcvideo: Privacy related controls can only be mapped if param allow_privacy_override is true\n"); > > + return -EINVAL; > > + } > > + > > To really prevent the LED from being turned off, it should also be > added to uvc_xu_ctrl_query. Will add in in v2. Thanks. I wanted to get the ball rolling first :) > > But why has it become so important after 10+ years that it cannot be > turned off on Linux? What has changed? > The majority of users use open-source software, they can view the > source at any time. Most users expect that the led is always on when the camera is active. I think the usecases where the led should not be turned on are spooky or very limited. Even if you use open-source software, when it parses user generated data, there is a risk for bugs. If there is a bug the only thing protecting the security of the camera is the membership of the video group which is a very low barrier. And once you manage to change the LED behaviour will persist in other unrelated apps. With the current proposal you need to actively enable the privacy_override_param, which typically requires root access. Regards! > > > Gergo -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 6:21 ` Ricardo Ribalda @ 2025-11-18 8:48 ` Gergo Koteles 2025-11-18 9:25 ` Ricardo Ribalda 0 siblings, 1 reply; 23+ messages in thread From: Gergo Koteles @ 2025-11-18 8:48 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Ricardo, On Tue, 2025-11-18 at 07:21 +0100, Ricardo Ribalda wrote: > > Most users expect that the led is always on when the camera is active. > I think the usecases where the led should not be turned on are spooky > or very limited. > Or do most users expect that if a piece of hardware has a setting, they can set it without module parameters? > Even if you use open-source software, when it parses user generated > data, there is a risk for bugs. If there is a bug the only thing > protecting the security of the camera is the membership of the video > group which is a very low barrier. And once you manage to change the > LED behaviour will persist in other unrelated apps. > So this is about what if an attacker accessed my passwords, private keys, OTP tokens, emails, pictures and then couldn't take a fresh picture of me in the dark without an LED? I'm smart as hell and I use a privacy tape anyway ;) I think freedom is worth more than this kind of fear. Gergo ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 8:48 ` Gergo Koteles @ 2025-11-18 9:25 ` Ricardo Ribalda 2025-11-18 11:14 ` Gergo Koteles 2025-11-19 4:19 ` Laurent Pinchart 0 siblings, 2 replies; 23+ messages in thread From: Ricardo Ribalda @ 2025-11-18 9:25 UTC (permalink / raw) To: Gergo Koteles Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Gergo On Tue, 18 Nov 2025 at 09:48, Gergo Koteles <soyer@irl.hu> wrote: > > Hi Ricardo, > > On Tue, 2025-11-18 at 07:21 +0100, Ricardo Ribalda wrote: > > > > Most users expect that the led is always on when the camera is active. > > I think the usecases where the led should not be turned on are spooky > > or very limited. > > > > Or do most users expect that if a piece of hardware has a setting, they > can set it without module parameters? A piece of hardware that has a non-standard, undocumented setting. Do you have a compelling use-case for turning off the privacy LED? > > > Even if you use open-source software, when it parses user generated > > data, there is a risk for bugs. If there is a bug the only thing > > protecting the security of the camera is the membership of the video > > group which is a very low barrier. And once you manage to change the > > LED behaviour will persist in other unrelated apps. > > > > So this is about what if an attacker accessed my passwords, private > keys, OTP tokens, emails, pictures and then couldn't take a fresh > picture of me in the dark without an LED? I'm smart as hell and I use a > privacy tape anyway ;) My core goal is simple: if the camera is in use, the privacy LED must be ON. If the LED is ON unexpectedly, it serves as a clear indication that something unusual is happening. Gaining access to the video node does not automatically grant access to sensitive data like browser information; there are sandboxes in place for that. Also open source does not equate to secure or non-malicious code. > > I think freedom is worth more than this kind of fear. No freedom is lost. This change simply increases the trustworthiness/reliability of your device. On ChromeOS, I don't use a privacy tape, but that's because I know how the LED is wired :). I want to achieve a similar level of trust/reliability for everyone else. In other words, I want to know if someone has seen me without t-shirt, eating ice-cream and crying while I am re-watching Coco. > > > Gergo -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 9:25 ` Ricardo Ribalda @ 2025-11-18 11:14 ` Gergo Koteles 2025-11-18 14:26 ` Hans de Goede 2025-11-19 4:19 ` Laurent Pinchart 1 sibling, 1 reply; 23+ messages in thread From: Gergo Koteles @ 2025-11-18 11:14 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Ricardo, On Tue, 2025-11-18 at 10:25 +0100, Ricardo Ribalda wrote: > Hi Gergo > > On Tue, 18 Nov 2025 at 09:48, Gergo Koteles <soyer@irl.hu> wrote: > > > > Hi Ricardo, > > > > On Tue, 2025-11-18 at 07:21 +0100, Ricardo Ribalda wrote: > > > > > > Most users expect that the led is always on when the camera is active. > > > I think the usecases where the led should not be turned on are spooky > > > or very limited. > > > > > > > Or do most users expect that if a piece of hardware has a setting, they > > can set it without module parameters? > > A piece of hardware that has a non-standard, undocumented setting. > > Do you have a compelling use-case for turning off the privacy LED? > As a pet camera, it is useful to be able to turn off the LED. In some cases, it can also eliminate unwanted reflections. Some cameras may have blue LED, and if someone hates blue LEDs.. > > > > > Even if you use open-source software, when it parses user generated > > > data, there is a risk for bugs. If there is a bug the only thing > > > protecting the security of the camera is the membership of the video > > > group which is a very low barrier. And once you manage to change the > > > LED behaviour will persist in other unrelated apps. > > > > > > > So this is about what if an attacker accessed my passwords, private > > keys, OTP tokens, emails, pictures and then couldn't take a fresh > > picture of me in the dark without an LED? I'm smart as hell and I use a > > privacy tape anyway ;) > > My core goal is simple: if the camera is in use, the privacy LED must > be ON. If the LED is ON unexpectedly, it serves as a clear indication > that something unusual is happening. > > Gaining access to the video node does not automatically grant access > to sensitive data like browser information; there are sandboxes in > place for that. Also open source does not equate to secure or > non-malicious code. > Applications that access a video node usually have multiple permissions (at least on my system). But I understand there may be cases where they only have access to a video node and then this can be useful. > > > > I think freedom is worth more than this kind of fear. > > No freedom is lost. This change simply increases the > trustworthiness/reliability of your device. It will decrease to the extent that fewer people will know that such an option exists because they will not read the description of the module's parameters. And people won't even know that it can be turned off as root, and even a curl | sudo... installation can take a picture of them without an LED. And it's not possible to be sure that there isn't another undocumented option in the firmware to turn it off the LED. A physical switch would be the best for this control, but that's not an option :( Gergo ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 11:14 ` Gergo Koteles @ 2025-11-18 14:26 ` Hans de Goede 2025-11-18 15:36 ` Gergo Koteles 0 siblings, 1 reply; 23+ messages in thread From: Hans de Goede @ 2025-11-18 14:26 UTC (permalink / raw) To: Gergo Koteles, Ricardo Ribalda Cc: Laurent Pinchart, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi George, On 18-Nov-25 12:14 PM, Gergo Koteles wrote: .. >> Do you have a compelling use-case for turning off the privacy LED? >> > > As a pet camera, it is useful to be able to turn off the LED. > In some cases, it can also eliminate unwanted reflections. > Some cameras may have blue LED, and if someone hates blue LEDs.. And almost all cameras already do not allow manually overriding the LED turning on while streaming. There is a very low-tech solution for this, put some black isolation tape over the LED :) >> My core goal is simple: if the camera is in use, the privacy LED must >> be ON. If the LED is ON unexpectedly, it serves as a clear indication >> that something unusual is happening. ... >> No freedom is lost. This change simply increases the >> trustworthiness/reliability of your device. > > It will decrease to the extent that fewer people will know that such an > option exists because they will not read the description of the > module's parameters. People currently already will not know that the option exists. Seeing the current LED controls on Logitech cams requires 2 manual steps: 1. Install uvcdynctrl which maps the custom GUIDs to the LED controls Note distros do not install this be default 2. Use either a GUI v4l2-control app like qv4l2ucp or gtk-v4l, or v4l-ctrl -l to list controls and then change the setting. So there already is close to 0 discoverability for this Logitech only feature. For the new MIPI cameras on laptops we have deliberately made it impossible to disable the privacy LED while streaming even though it is often controlled by a separate GPIO because of privacy reasons. For the same privacy reasons I fully agree with Ricardo that this should be behind a module option. Which replaces step 1. with creating a /etc/modprobe.d/uvc.conf file, so just about as much work. > And it's not possible to be sure that there isn't another undocumented > option in the firmware to turn it off the LED. > > A physical switch would be the best for this control, but that's not an > option :( Sure but remember perfect is the enemy of good. Having a v4l2-ctrl to force the LED to always be off will make it a lot easier for an attacker to use the camera without the LED turning on. Security is all about layers / defense in depth and the module option is a nice and simple way to make things harder for pervert spyware. Regards, Hans ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 14:26 ` Hans de Goede @ 2025-11-18 15:36 ` Gergo Koteles 2025-11-18 18:30 ` Ricardo Ribalda 0 siblings, 1 reply; 23+ messages in thread From: Gergo Koteles @ 2025-11-18 15:36 UTC (permalink / raw) To: Hans de Goede, Ricardo Ribalda Cc: Laurent Pinchart, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Hans, On Tue, 2025-11-18 at 15:26 +0100, Hans de Goede wrote: > > > > Do you have a compelling use-case for turning off the privacy LED? > > > > > > > As a pet camera, it is useful to be able to turn off the LED. > > In some cases, it can also eliminate unwanted reflections. > > Some cameras may have blue LED, and if someone hates blue LEDs.. > > And almost all cameras already do not allow manually overriding the LED > turning on while streaming. There is a very low-tech solution for this, > put some black isolation tape over the LED :) > Yes, this is also a good and stable solution. :) > > > My core goal is simple: if the camera is in use, the privacy LED must > > > be ON. If the LED is ON unexpectedly, it serves as a clear indication > > > that something unusual is happening. > > ... > > > > No freedom is lost. This change simply increases the > > > trustworthiness/reliability of your device. > > > > It will decrease to the extent that fewer people will know that such an > > option exists because they will not read the description of the > > module's parameters. > > People currently already will not know that the option exists. > > Seeing the current LED controls on Logitech cams requires 2 manual steps: > > 1. Install uvcdynctrl which maps the custom GUIDs to the LED controls > Note distros do not install this be default > 2. Use either a GUI v4l2-control app like qv4l2ucp or gtk-v4l, or > v4l-ctrl -l to list controls and then change the setting. > > So there already is close to 0 discoverability for this Logitech > only feature. This is not completely true. The cameractrls uses these extensions and controls with uvc_xu_control_query() and has over 140k downloads on Flathub alone. > > For the new MIPI cameras on laptops we have deliberately made it > impossible to disable the privacy LED while streaming even though > it is often controlled by a separate GPIO because of privacy reasons. > > For the same privacy reasons I fully agree with Ricardo that this should > be behind a module option. Which replaces step 1. with creating > a /etc/modprobe.d/uvc.conf file, so just about as much work. > I agree that this will be useful. The module parameter is also simpler than per-V4L2 control permission management. And the latter is not needed in other cases, I think. However, if allow_privacy_override is enabled, would it be worth mapping these controls by the kernel? So uvcdynctrl or cameractrls would not be needed for this control. > Regards, Gergo ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 15:36 ` Gergo Koteles @ 2025-11-18 18:30 ` Ricardo Ribalda 2025-11-19 21:34 ` Gergo Koteles 0 siblings, 1 reply; 23+ messages in thread From: Ricardo Ribalda @ 2025-11-18 18:30 UTC (permalink / raw) To: Gergo Koteles Cc: Hans de Goede, Laurent Pinchart, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Gergo On Tue, 18 Nov 2025 at 16:36, Gergo Koteles <soyer@irl.hu> wrote: > > Hi Hans, > > On Tue, 2025-11-18 at 15:26 +0100, Hans de Goede wrote: > > > > > > > Do you have a compelling use-case for turning off the privacy LED? > > > > > > > > > > As a pet camera, it is useful to be able to turn off the LED. > > > In some cases, it can also eliminate unwanted reflections. > > > Some cameras may have blue LED, and if someone hates blue LEDs.. > > > > And almost all cameras already do not allow manually overriding the LED > > turning on while streaming. There is a very low-tech solution for this, > > put some black isolation tape over the LED :) > > > > Yes, this is also a good and stable solution. :) > > > > > My core goal is simple: if the camera is in use, the privacy LED must > > > > be ON. If the LED is ON unexpectedly, it serves as a clear indication > > > > that something unusual is happening. > > > > ... > > > > > > No freedom is lost. This change simply increases the > > > > trustworthiness/reliability of your device. > > > > > > It will decrease to the extent that fewer people will know that such an > > > option exists because they will not read the description of the > > > module's parameters. > > > > People currently already will not know that the option exists. > > > > Seeing the current LED controls on Logitech cams requires 2 manual steps: > > > > 1. Install uvcdynctrl which maps the custom GUIDs to the LED controls > > Note distros do not install this be default > > 2. Use either a GUI v4l2-control app like qv4l2ucp or gtk-v4l, or > > v4l-ctrl -l to list controls and then change the setting. > > > > So there already is close to 0 discoverability for this Logitech > > only feature. > > This is not completely true. > The cameractrls uses these extensions and controls with > uvc_xu_control_query() and has over 140k downloads on Flathub alone. > > > > > For the new MIPI cameras on laptops we have deliberately made it > > impossible to disable the privacy LED while streaming even though > > it is often controlled by a separate GPIO because of privacy reasons. > > > > For the same privacy reasons I fully agree with Ricardo that this should > > be behind a module option. Which replaces step 1. with creating > > a /etc/modprobe.d/uvc.conf file, so just about as much work. > > > > I agree that this will be useful. The module parameter is also simpler > than per-V4L2 control permission management. And the latter is not > needed in other cases, I think. > > However, if allow_privacy_override is enabled, would it be worth > mapping these controls by the kernel? > So uvcdynctrl or cameractrls would not be needed for this control. If allow_privacy_override is enabled and there is a standard control in include/uapi/linux/v4l2-controls.h that supports such control: I have no issue adding the mapping for it. Right now we only have V4L2_CID_PRIVACY which is a boolean and has usually been used to tell if the privacy shutter is on or off, not to configure the LED. In any case, the default value of allow_privacy_override should be false. I would even argue that the best approach is to block all the known LED config controls after a deprecation period. Check: https://lore.kernel.org/linux-media/CANiDSCuv8UG6TMx6pK348okK+NYzAorPEgPYzoRCEZiBDgPP=A@mail.gmail.com/ > > > > Regards, > Gergo -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 18:30 ` Ricardo Ribalda @ 2025-11-19 21:34 ` Gergo Koteles 0 siblings, 0 replies; 23+ messages in thread From: Gergo Koteles @ 2025-11-19 21:34 UTC (permalink / raw) To: Ricardo Ribalda Cc: Hans de Goede, Laurent Pinchart, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb Hi Ricardo, On Tue, 2025-11-18 at 19:30 +0100, Ricardo Ribalda wrote: ... > > > > > > > > For the new MIPI cameras on laptops we have deliberately made it > > > impossible to disable the privacy LED while streaming even though > > > it is often controlled by a separate GPIO because of privacy reasons. > > > > > > For the same privacy reasons I fully agree with Ricardo that this should > > > be behind a module option. Which replaces step 1. with creating > > > a /etc/modprobe.d/uvc.conf file, so just about as much work. > > > > > > > I agree that this will be useful. The module parameter is also simpler > > than per-V4L2 control permission management. And the latter is not > > needed in other cases, I think. > > > > However, if allow_privacy_override is enabled, would it be worth > > mapping these controls by the kernel? > > So uvcdynctrl or cameractrls would not be needed for this control. > > If allow_privacy_override is enabled and there is a standard control > in include/uapi/linux/v4l2-controls.h that supports such control: I > have no issue adding the mapping for it. > I was misled by V4L2_CID_LED1_MODE in uvcdynctrl's logitech.xml. That is not in v4l-controls.h. > Right now we only have V4L2_CID_PRIVACY which is a boolean and has > usually been used to tell if the privacy shutter is on or off, not to > configure the LED. > > In any case, the default value of allow_privacy_override should be > false. I would even argue that the best approach is to block all the > known LED config controls after a deprecation period. > Check: https://lore.kernel.org/linux-media/CANiDSCuv8UG6TMx6pK348okK+NYzAorPEgPYzoRCEZiBDgPP=A@mail.gmail.com/ > I use these controls now and would use them in 1-2-3 years, so I don't think removing them completely is a good idea :) Almost no one compiles their own kernel anymore, so the usefulness of putting them behind a kernel configuration is questionable. I also saw these being used in the users of motion project. If someone is using it as a surveillance camera, there is no need for it to light up. The c920 has LEDs like this, that are not easy to cover up with tape and definitely not aesthetic. https://www.nikktech.com/main/images/pics/reviews/logitech/c920_webcam/logitech_c920_015.JPG Regards, Gergo ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 9:25 ` Ricardo Ribalda 2025-11-18 11:14 ` Gergo Koteles @ 2025-11-19 4:19 ` Laurent Pinchart 1 sibling, 0 replies; 23+ messages in thread From: Laurent Pinchart @ 2025-11-19 4:19 UTC (permalink / raw) To: Ricardo Ribalda Cc: Gergo Koteles, Hans de Goede, Mauro Carvalho Chehab, Greg Kroah-Hartman, linux-media, linux-kernel, linux-usb On Tue, Nov 18, 2025 at 10:25:42AM +0100, Ricardo Ribalda wrote: > On Tue, 18 Nov 2025 at 09:48, Gergo Koteles wrote: > > On Tue, 2025-11-18 at 07:21 +0100, Ricardo Ribalda wrote: > > > > > > Most users expect that the led is always on when the camera is active. > > > I think the usecases where the led should not be turned on are spooky > > > or very limited. > > > > Or do most users expect that if a piece of hardware has a setting, they > > can set it without module parameters? > > A piece of hardware that has a non-standard, undocumented setting. > > Do you have a compelling use-case for turning off the privacy LED? The use case that Logitech added this XU control to support is avoiding the reflection of the privacy LED in users' glasses. > > > Even if you use open-source software, when it parses user generated > > > data, there is a risk for bugs. If there is a bug the only thing > > > protecting the security of the camera is the membership of the video > > > group which is a very low barrier. In modern systems the answer to this would be pipewire and portals (or similar solutions for vendor operating systems). We'll still need time until the user won't have direct access to the video device nodes though. > > > And once you manage to change the > > > LED behaviour will persist in other unrelated apps. Maybe that's something we want to address, and make the control per-file-handle ? > > So this is about what if an attacker accessed my passwords, private > > keys, OTP tokens, emails, pictures and then couldn't take a fresh > > picture of me in the dark without an LED? I'm smart as hell and I use a > > privacy tape anyway ;) > > My core goal is simple: if the camera is in use, the privacy LED must > be ON. If the LED is ON unexpectedly, it serves as a clear indication > that something unusual is happening. > > Gaining access to the video node does not automatically grant access > to sensitive data like browser information; there are sandboxes in > place for that. Also open source does not equate to secure or > non-malicious code. > > > I think freedom is worth more than this kind of fear. > > No freedom is lost. This change simply increases the > trustworthiness/reliability of your device. > > On ChromeOS, I don't use a privacy tape, but that's because I know how > the LED is wired :). I want to achieve a similar level of > trust/reliability for everyone else. I'd argue that a privacy tape is useful on those devices too. Far more common than attack scenarios are cases when you unvoluntarily turn your webcam on during a call. This is however beside the point. > In other words, I want to know if someone has seen me without t-shirt, > eating ice-cream and crying while I am re-watching Coco. -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-17 20:14 ` [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override Ricardo Ribalda 2025-11-17 21:10 ` Gergo Koteles @ 2025-11-18 11:14 ` Greg Kroah-Hartman 2025-11-18 14:09 ` Mauro Carvalho Chehab 1 sibling, 1 reply; 23+ messages in thread From: Greg Kroah-Hartman @ 2025-11-18 11:14 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb On Mon, Nov 17, 2025 at 08:14:19PM +0000, Ricardo Ribalda wrote: > 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 not the 1990's, please do not add new module parameters, they do not scale, nor work properly at all for modern hardware where you can have multiple devices in the same system. This isn't an agreement that we should do this feature at all, just that if you do, it should NOT be a module parameter. thanks, greg k-h ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 11:14 ` Greg Kroah-Hartman @ 2025-11-18 14:09 ` Mauro Carvalho Chehab 2025-11-18 16:01 ` Michal Pecio ` (2 more replies) 0 siblings, 3 replies; 23+ messages in thread From: Mauro Carvalho Chehab @ 2025-11-18 14:09 UTC (permalink / raw) To: Ricardo Ribalda Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb, Greg Kroah-Hartman On Tue, Nov 18, 2025 at 06:14:09AM -0500, Greg Kroah-Hartman wrote: > On Mon, Nov 17, 2025 at 08:14:19PM +0000, Ricardo Ribalda wrote: > > 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 not the 1990's, please do not add new module parameters, they do > not scale, nor work properly at all for modern hardware where you can > have multiple devices in the same system. > > This isn't an agreement that we should do this feature at all, just that > if you do, it should NOT be a module parameter. I agree with Greg: modprobe makes things harder specially on usb. Also, in the specific case of privacy leds, IMO it should never be possible to directly disable it, not even root via a modprobe or runtime parameter. Ok, as it might be some case where someone really wants to disable for his special pet toy. If such cases are relevant, a Kconfig parameter could be added (maybe depending on BROKEN), having privacy LED enabled by default. This way, any sane distro-generated Kernel should always have the privacy LED on when camera is in use. On other words, if someone has secure boot enabled, he can be more confident that a distro-vendor signed Kernel will honour the privacy LED, and not even the root can tamper with - as BIOS access to disable secure boot would be needed to change it - plus, booting a non-signed kernel. Regards, Mauro ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 14:09 ` Mauro Carvalho Chehab @ 2025-11-18 16:01 ` Michal Pecio 2025-11-18 18:28 ` Ricardo Ribalda 2025-11-19 4:19 ` Laurent Pinchart 2 siblings, 0 replies; 23+ messages in thread From: Michal Pecio @ 2025-11-18 16:01 UTC (permalink / raw) To: Mauro Carvalho Chehab Cc: Ricardo Ribalda, Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb, Greg Kroah-Hartman On Tue, 18 Nov 2025 15:09:16 +0100, Mauro Carvalho Chehab wrote: > On other words, if someone has secure boot enabled, he can be more > confident that a distro-vendor signed Kernel will honour the privacy > LED, and not even the root can tamper with - as BIOS access to > disable secure boot would be needed to change it - plus, booting a > non-signed kernel. IMHO users are better off trusting duct tape than any chain of trust, and those with tinfoil hats already do. Rational people with any clue will simply assume their computer broke and put duct tape over the LED, carefully not to cover the lens ;) Regards, Michal ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 14:09 ` Mauro Carvalho Chehab 2025-11-18 16:01 ` Michal Pecio @ 2025-11-18 18:28 ` Ricardo Ribalda 2025-11-19 4:19 ` Laurent Pinchart 2 siblings, 0 replies; 23+ messages in thread From: Ricardo Ribalda @ 2025-11-18 18:28 UTC (permalink / raw) To: Mauro Carvalho Chehab Cc: Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb, Greg Kroah-Hartman Hi Mauro On Tue, 18 Nov 2025 at 15:09, Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote: > > On Tue, Nov 18, 2025 at 06:14:09AM -0500, Greg Kroah-Hartman wrote: > > On Mon, Nov 17, 2025 at 08:14:19PM +0000, Ricardo Ribalda wrote: > > > 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 not the 1990's, please do not add new module parameters, they do > > not scale, nor work properly at all for modern hardware where you can > > have multiple devices in the same system. > > > > This isn't an agreement that we should do this feature at all, just that > > if you do, it should NOT be a module parameter. > > I agree with Greg: modprobe makes things harder, especially on usb. If the argument is that with parameters you cannot have a different parameter for each USB camera, I would say that I see this option as a system-wide policy, not as a per-device option. But yeah, the less parameters that we have, the better. > > Also, in the specific case of privacy leds, IMO it should never be > possible to directly disable it, not even root via a modprobe or > runtime parameter. +1 > > Ok, as it might be some case where someone really wants to disable for his > special pet toy. If such cases are relevant, a Kconfig parameter could > be added (maybe depending on BROKEN), having privacy LED enabled by default. > > This way, any sane distro-generated Kernel should always have the privacy > LED on when camera is in use. > > On other words, if someone has secure boot enabled, he can be more confident > that a distro-vendor signed Kernel will honour the privacy LED, and not > even the root can tamper with - as BIOS access to disable secure boot would > be needed to change it - plus, booting a non-signed kernel. If most of the people agree that the final goal is to block all the LED privacy access from userspace we could have a mixed approach. 1. We introduce the allow_privacy_override parameter with default off. If the user sets allow_privacy_override, they are welcomed with a message like: uvcvideo: [DEPRECATION]: Access to the privacy controls will be eventually blocked. 2. In one year, if nobody screams at us we remove the parameter and call it a day. 3. If someone depends on this feature, we will move it into a kernel configuration behind BROKEN. What do you think? > > Regards, > Mauro -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override 2025-11-18 14:09 ` Mauro Carvalho Chehab 2025-11-18 16:01 ` Michal Pecio 2025-11-18 18:28 ` Ricardo Ribalda @ 2025-11-19 4:19 ` Laurent Pinchart 2 siblings, 0 replies; 23+ messages in thread From: Laurent Pinchart @ 2025-11-19 4:19 UTC (permalink / raw) To: Mauro Carvalho Chehab Cc: Ricardo Ribalda, Hans de Goede, Mauro Carvalho Chehab, linux-media, linux-kernel, linux-usb, Greg Kroah-Hartman On Tue, Nov 18, 2025 at 03:09:16PM +0100, Mauro Carvalho Chehab wrote: > On Tue, Nov 18, 2025 at 06:14:09AM -0500, Greg Kroah-Hartman wrote: > > On Mon, Nov 17, 2025 at 08:14:19PM +0000, Ricardo Ribalda wrote: > > > 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 not the 1990's, please do not add new module parameters, they do > > not scale, nor work properly at all for modern hardware where you can > > have multiple devices in the same system. > > > > This isn't an agreement that we should do this feature at all, just that > > if you do, it should NOT be a module parameter. > > I agree with Greg: modprobe makes things harder specially on usb. > > Also, in the specific case of privacy leds, IMO it should never be > possible to directly disable it, not even root via a modprobe or > runtime parameter. > > Ok, as it might be some case where someone really wants to disable for his > special pet toy. If such cases are relevant, a Kconfig parameter could > be added (maybe depending on BROKEN), having privacy LED enabled by default. The feature was added by Logitech to their webcams to avoid the red privacy LED showing as a reflection on users' glasses. Whether or not users ended up caring, I don't know. The situation is different for webcams embedded in devices (even if they're internally UVC cameras), as the privacy LED is typically smaller and less bright in those devices. > This way, any sane distro-generated Kernel should always have the privacy > LED on when camera is in use. > > On other words, if someone has secure boot enabled, he can be more confident > that a distro-vendor signed Kernel will honour the privacy LED, and not > even the root can tamper with - as BIOS access to disable secure boot would > be needed to change it - plus, booting a non-signed kernel. -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2025-11-19 21:34 UTC | newest] Thread overview: 23+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-11-17 20:14 [PATCH 0/4] media: uvcvideo: Map known XU controls Ricardo Ribalda 2025-11-17 20:14 ` [PATCH 1/4] media: uvcvideo: Remove nodrop parameter Ricardo Ribalda 2025-11-19 4:20 ` Laurent Pinchart 2025-11-17 20:14 ` [PATCH 2/4] media: uvcvideo: Import standard controls from uvcdynctrl Ricardo Ribalda 2025-11-19 4:21 ` Laurent Pinchart 2025-11-17 20:14 ` [PATCH 3/4] media: uvcvideo: Announce deprecation intentions for UVCIOC_CTRL_MAP Ricardo Ribalda 2025-11-19 4:21 ` Laurent Pinchart 2025-11-17 20:14 ` [PATCH 4/4] media: uvcvideo: Introduce allow_privacy_override Ricardo Ribalda 2025-11-17 21:10 ` Gergo Koteles 2025-11-18 6:21 ` Ricardo Ribalda 2025-11-18 8:48 ` Gergo Koteles 2025-11-18 9:25 ` Ricardo Ribalda 2025-11-18 11:14 ` Gergo Koteles 2025-11-18 14:26 ` Hans de Goede 2025-11-18 15:36 ` Gergo Koteles 2025-11-18 18:30 ` Ricardo Ribalda 2025-11-19 21:34 ` Gergo Koteles 2025-11-19 4:19 ` Laurent Pinchart 2025-11-18 11:14 ` Greg Kroah-Hartman 2025-11-18 14:09 ` Mauro Carvalho Chehab 2025-11-18 16:01 ` Michal Pecio 2025-11-18 18:28 ` Ricardo Ribalda 2025-11-19 4:19 ` Laurent Pinchart
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox