From 204dd31958bb2b7a704509feaba91ccff62f72dc Mon Sep 17 00:00:00 2001 From: The_miro Date: Sat, 13 Jun 2026 22:41:24 +0200 Subject: [PATCH] fix(hyprlua): only offer real capture nodes; show howdy's enroll error The Brio (and most UVC webcams) expose a second /dev/video* node that is metadata-capture only. The chooser listed it, the existence-only guard accepted it, and howdy aborted with a bare exit 1 because that node can never deliver a frame. - list_cameras: skip nodes with no capture pixel formats (is_capture_device) - howdy_camera_ok: require an actual capture node, not just an existing path, so a stale metadata-node device_path triggers reconfiguration - howdy_add: tee howdy's output and surface the real reason on failure instead of only the exit code Co-Authored-By: Claude Opus 4.8 --- .../hyprlua/scripts/enroll-biometrics.sh | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/desktopenvs/hyprlua/scripts/enroll-biometrics.sh b/desktopenvs/hyprlua/scripts/enroll-biometrics.sh index 5901df7..0c49454 100755 --- a/desktopenvs/hyprlua/scripts/enroll-biometrics.sh +++ b/desktopenvs/hyprlua/scripts/enroll-biometrics.sh @@ -74,9 +74,18 @@ require_dialog() { } # ── Camera helpers ───────────────────────────────────────────────────────────── +# True only for nodes that actually deliver video frames. UVC webcams expose +# extra /dev/video* nodes for metadata capture (no pixel formats); pointing +# howdy at one of those makes it fail to read a frame and abort with exit 1. +is_capture_device() { + v4l2-ctl --device="$1" --list-formats 2>/dev/null \ + | grep -qE '^[[:space:]]*\[[0-9]+\]:' +} + list_cameras() { for dev in /dev/video*; do [[ -c "$dev" ]] || continue + is_capture_device "$dev" || continue local id="${dev#/dev/video}" local name name=$(v4l2-ctl --device="$dev" --info 2>/dev/null \ @@ -277,10 +286,12 @@ howdy_set_cfg() { howdy_set_device_path() { howdy_set_cfg device_path "$1"; } -# True when howdy points at a device node that actually exists. +# True when howdy points at a node that exists AND can actually capture video +# (not a metadata-only node, which would make enrollment fail with exit 1). howdy_camera_ok() { local dp; dp=$(howdy_get_device_path) - [[ -n "$dp" && "$dp" != none && -e "$dp" ]] + [[ -n "$dp" && "$dp" != none && -e "$dp" ]] || return 1 + is_capture_device "$dp" } # howdy's stock tuning assumes a Windows-Hello IR sensor. A regular colour @@ -356,7 +367,10 @@ howdy_add() { printf "\033[35m ─────────────────────────────────────────\033[0m\n\n" printf " Look at the camera and hold still.\n\n" # howdy has no label flag; the label is read from stdin during `add`. - printf '%s\n' "$name" | sudo howdy -U "$USER" add + # Tee the output so the actual reason (dark frames, no face, busy camera…) + # can be shown on failure instead of a bare exit code. + local log="$TMP_D/howdy_add.log" + printf '%s\n' "$name" | sudo howdy -U "$USER" add 2>&1 | tee "$log" local rc=${PIPESTATUS[1]} if [[ $rc -eq 0 ]]; then @@ -364,7 +378,10 @@ howdy_add() { "Face model '$name' added.\n\nYou may need to relogin for PAM changes to take effect." \ 9 58 else - msg "Failed" "Enrollment failed (code $rc).\n\nCheck camera and lighting." 8 52 + local why; why=$(grep -vE '^\s*$' "$log" 2>/dev/null | tail -n 4) + msg "Failed" \ + "Enrollment failed (code $rc).\n\nhowdy said:\n${why:-(no output captured)}\n\nIf it's a camera/frame error, re-run\n'configure camera' and pick another node." \ + 16 64 fi }