From 82776d7da4faaad2b2ec3cd78cbf4cc44c315713 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Fri, 10 Jul 2026 09:32:52 +0100 Subject: [PATCH] docs(webcam): portal/Flatpak IR gap is v4l2-only (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ship the recommended document-only path: WirePlumber hideIrSensor acts on the v4l2 monitor only; libcamera / xdg-desktop-portal / Flatpak camera pickers can still list the internal IR sensor. - HARDWARE.md §7: dual-sensor subsection (scope, workaround, deferred) - ROADMAP § Webcam: ✓ #71; (b)/(c) stay hardware-gated - README option row + HARDWARE-QUEUE T14s check for (b)/(c) - Close BACKLOG #71; no libcamera rules Verified: V0 (docs only). --- README.md | 2 +- agent/HARDWARE-QUEUE.md | 5 +++++ docs/HARDWARE.md | 32 +++++++++++++++++++++++++++++++- docs/ROADMAP.md | 13 +++++++++---- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b56d85b..e8a0945 100644 --- a/README.md +++ b/README.md @@ -279,7 +279,7 @@ option, e.g. `services.easyeffects.enable = lib.mkForce false;` — see | `nomarchy.hardware.fingerprint.pam` | `false` | Opt-in: use the fingerprint for login + sudo (PAM) | | `nomarchy.hardware.npu.enable` | `false` | Opt-in/experimental: load the on-die NPU driver (`amdxdna`/`intel_vpu`); userspace runtime is BYO | | `nomarchy.hardware.latestKernel` | `false` | Opt-in: ship `linuxPackages_latest` instead of the default kernel — for very new hardware whose drivers landed recently | -| `nomarchy.hardware.camera.hideIrSensor` | `false` | Hide a dual-sensor webcam's IR node from PipeWire so apps only ever see the colour camera (the "second, dark Integrated Camera"); installer-set on a paired RGB+IR webcam. `/dev/video*` stays open, so Howdy-style face unlock still works; `.irMatch` overrides the IR-name regex | +| `nomarchy.hardware.camera.hideIrSensor` | `false` | Hide a dual-sensor webcam's IR node from PipeWire's **v4l2** path so apps only ever see the colour camera (the "second, dark Integrated Camera"); installer-set on a paired RGB+IR webcam. `/dev/video*` stays open, so Howdy-style face unlock still works; `.irMatch` overrides the IR-name regex. Does **not** hide IR from libcamera / portal / Flatpak pickers — see [HARDWARE.md §7](docs/HARDWARE.md) | | `nomarchy.hardware.i2c.enable` | `false` | I2C devices support — access to `/dev/i2c-*` (RGB controllers, sensors, DDC/CI monitor control) | | `nomarchy.hardware.i2c.ddcci` | `false` (distro default: **`true`**) | the ddcci-driver kernel module, exposing external monitors as standard backlight devices via DDC/CI so brightness keys and swayosd natively control them | | `nomarchy.services.tailscale.enable` | `false` | Opt-in: Tailscale mesh VPN — the login user is made the operator, so `tailscale up/down/set` and the System › VPN menu work without sudo | diff --git a/agent/HARDWARE-QUEUE.md b/agent/HARDWARE-QUEUE.md index e504d1d..4c22bc6 100644 --- a/agent/HARDWARE-QUEUE.md +++ b/agent/HARDWARE-QUEUE.md @@ -377,3 +377,8 @@ QA machine), the **T14s** (webcam case). RGB+IR pair, bakes `hardware.camera.hideIrSensor`; `wpctl status` shows one colour source; an app picker lists one camera; Howdy-style direct `/dev/video2` reads still work. +- [ ] **Portal/Flatpak libcamera IR (b)/(c)** — after #71 docs: on hardware, + confirm a Flatpak/portal picker still lists the internal IR node; + only then investigate (b) WirePlumber libcamera GREY-only monitor + rule or (c) libcamera/udev-layer hide. Do not ship either without a + live dual-sensor check (see HARDWARE.md §7 / ROADMAP § Webcam). diff --git a/docs/HARDWARE.md b/docs/HARDWARE.md index a65351e..45ce924 100644 --- a/docs/HARDWARE.md +++ b/docs/HARDWARE.md @@ -250,6 +250,36 @@ needs a maintainer + hardware-queue coverage. | Model quirks missing | Set better `hardwareProfile` (see §8) | System | | OpenRGB / printing / Steam | `nomarchy.services.*` | System | +### Dual-sensor webcam / IR hide + +Many dual-sensor modules (e.g. ThinkPad T14s) expose colour + IR as two +identically named “Integrated Camera” nodes. Picking the IR node yields a +black/dark greyscale frame — the classic “my webcam is dark” symptom. + +`nomarchy.hardware.camera.hideIrSensor` (installer-on when RGB+IR names +are detected; overridable `irMatch`) drops the IR node from **WirePlumber’s +v4l2 monitor** so native PipeWire pickers only offer the colour camera. +The kernel `/dev/video*` node stays open, so Howdy-style face unlock still +works. Design history: [ROADMAP § Webcam](ROADMAP.md). + +**What it does not cover:** apps that list cameras via **libcamera** or +the **xdg-desktop-portal** / **Flatpak** camera path still see both +sensors — a Flatpak Zoom (or similar) user can still pick the black IR +“camera”. That is intentional: a blanket libcamera disable would risk +external USB cams that need the libcamera path, and surgical internal-only +libcamera rules could not match early enough (only `device.api` binds +before the WirePlumber monitor rule). + +**Workaround:** prefer the colour device in the picker (or any non-IR +name). Apps that default to the first v4l2 colour source without a picker +are fine. + +**Further engineering (needs T14s-class hardware):** (b) a WirePlumber +*libcamera* monitor rule disabling GREY-only nodes; (c) a libcamera/udev +quirk at the libcamera layer. Neither is implemented — the recommended +path is document-only until those can be verified on real dual-sensor +hardware (see `agent/HARDWARE-QUEUE.md` › T14s). + Theme switches never touch drivers (Home Manager only). ## 8. Unsupported or unlisted machines @@ -364,7 +394,7 @@ Full tables: [README § options](../README.md). Hardware-shaped surface: | `nomarchy.hardware.fingerprint.enable` / `.pam` | fprintd + PAM | | `nomarchy.hardware.npu.enable` | in-kernel NPU only | | `nomarchy.hardware.latestKernel` | `linuxPackages_latest` | -| `nomarchy.hardware.camera.hideIrSensor` / `.irMatch` | dual-sensor webcams | +| `nomarchy.hardware.camera.hideIrSensor` / `.irMatch` | dual-sensor webcams (v4l2 only; §7) | | `nomarchy.hardware.i2c.enable` / `.ddcci` | I2C + external backlight | | `nomarchy.system.power.*` | PPD/TLP, laptop, thermald, charge limit | | `nomarchy.system.bluetooth.enable` | BT stack | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 6a336de..f77d01a 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -539,10 +539,15 @@ Design/decision records and a running log of shipped work (items marked generated drop-in's serialized content is valid WP-0.5 config; and the exact shipped `irMatch` was re-confirmed live (1 V4L2 source = the colour `/dev/video0`, libcamera untouched, IR node disabled in the WirePlumber log). - Remaining: an on-Nomarchy end-to-end check; optional `v4l-utils` + - `cameractrls` for the rare genuine-tuning case; and a follow-up for - portal/Flatpak apps that consume the libcamera path (where the internal IR is - still listed, since libcamera stays on). + Remaining: an on-Nomarchy end-to-end check (HARDWARE-QUEUE › T14s); + optional `v4l-utils` + `cameractrls` already commented in the template. + - ✓ **Portal/Flatpak IR gap documented (#71, docs only):** the shipped + v4l2 IR-hide does **not** cover libcamera / xdg-desktop-portal / + Flatpak camera pickers (IR can still appear there). User-facing note + in [`HARDWARE.md` §7](HARDWARE.md). Engineering options (b) WirePlumber + libcamera GREY-only rule and (c) libcamera/udev-layer hide stay + deferred — both need a T14s-class dual-sensor machine to verify; no + libcamera rules in-tree. - ✓ **Memory-pressure protection (earlyoom, default-on):** `modules/nixos/oom.nix` — running out of memory kills the offending process instead of freezing the desktop. **earlyoom over systemd-oomd,