Loading nixos/modules/hardware/video/webcam/ipu6.nix +54 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ let inherit (lib) mkDefault mkEnableOption mkForce mkIf mkOption optional Loading Loading @@ -38,6 +39,19 @@ in ''; }; videoDeviceNumber = mkOption { type = types.int; default = 50; description = '' v4l2loopback device number for the relay output (`/dev/videoN`). Must be fixed so application camera permission grants, which are keyed to the PipeWire node name (derived from the sysfs device path), survive reboots. Choose a number above the IPU6 raw node range (typically 3-34) and any other v4l2loopback devices on the system. ''; }; }; config = mkIf cfg.enable { Loading @@ -51,10 +65,32 @@ in ivsc-firmware ]; # Restrict IPU6 raw nodes and media controller to root. DRIVERS== matches the # parent PCI device. TAG-="uaccess" blocks logind ACL grants at login. services.udev.extraRules = '' SUBSYSTEM=="intel-ipu6-psys", MODE="0660", GROUP="video" SUBSYSTEM=="media", DRIVERS=="intel-ipu6", MODE="0600", GROUP="root", TAG-="uaccess" SUBSYSTEM=="video4linux", DRIVERS=="intel-ipu6", MODE="0600", GROUP="root", TAG-="uaccess" ''; # ipu6-camera-hal writes AIQ tuning data and debug logs here. systemd.tmpfiles.rules = [ "d /run/camera 0755 root video -" ]; # Disable raw IPU6 nodes in WirePlumber. Matched via udev ID_V4L_PRODUCT=ipu6, # set by the kernel at device registration without requiring a device open. services.pipewire.wireplumber.extraConfig."ipu6-v4l2-rules" = { "monitor.v4l2.rules" = [ { matches = [ { "device.product.name" = "ipu6"; } ]; actions = { "update-props" = { "device.disabled" = true; }; }; } ]; }; services.v4l2-relayd.instances.ipu6 = { enable = mkDefault true; Loading @@ -72,5 +108,23 @@ in format = mkIf (cfg.platform != "ipu6") (mkDefault "NV12"); }; }; # Override preStart/postStop from the v4l2-relayd module: # - Use a fixed device number so PipeWire node names (and application permission # grants) are stable across reboots. Exit 17 (EEXIST) is success. # - Keep the device alive on stop so apps survive relay restarts via # VIDIOC_DQBUF blocking rather than receiving errors. systemd.services.v4l2-relayd-ipu6 = { preStart = mkForce '' mkdir -p "$(dirname "$V4L2_DEVICE_FILE")" ${config.boot.kernelPackages.v4l2loopback.bin}/bin/v4l2loopback-ctl \ add --name "Intel MIPI Camera" --exclusive-caps=1 ${toString cfg.videoDeviceNumber} || [ $? -eq 17 ] echo /dev/video${toString cfg.videoDeviceNumber} > "$V4L2_DEVICE_FILE" ''; postStop = mkForce '' rm -rf "$(dirname "$V4L2_DEVICE_FILE")" ''; }; }; } Loading
nixos/modules/hardware/video/webcam/ipu6.nix +54 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ let inherit (lib) mkDefault mkEnableOption mkForce mkIf mkOption optional Loading Loading @@ -38,6 +39,19 @@ in ''; }; videoDeviceNumber = mkOption { type = types.int; default = 50; description = '' v4l2loopback device number for the relay output (`/dev/videoN`). Must be fixed so application camera permission grants, which are keyed to the PipeWire node name (derived from the sysfs device path), survive reboots. Choose a number above the IPU6 raw node range (typically 3-34) and any other v4l2loopback devices on the system. ''; }; }; config = mkIf cfg.enable { Loading @@ -51,10 +65,32 @@ in ivsc-firmware ]; # Restrict IPU6 raw nodes and media controller to root. DRIVERS== matches the # parent PCI device. TAG-="uaccess" blocks logind ACL grants at login. services.udev.extraRules = '' SUBSYSTEM=="intel-ipu6-psys", MODE="0660", GROUP="video" SUBSYSTEM=="media", DRIVERS=="intel-ipu6", MODE="0600", GROUP="root", TAG-="uaccess" SUBSYSTEM=="video4linux", DRIVERS=="intel-ipu6", MODE="0600", GROUP="root", TAG-="uaccess" ''; # ipu6-camera-hal writes AIQ tuning data and debug logs here. systemd.tmpfiles.rules = [ "d /run/camera 0755 root video -" ]; # Disable raw IPU6 nodes in WirePlumber. Matched via udev ID_V4L_PRODUCT=ipu6, # set by the kernel at device registration without requiring a device open. services.pipewire.wireplumber.extraConfig."ipu6-v4l2-rules" = { "monitor.v4l2.rules" = [ { matches = [ { "device.product.name" = "ipu6"; } ]; actions = { "update-props" = { "device.disabled" = true; }; }; } ]; }; services.v4l2-relayd.instances.ipu6 = { enable = mkDefault true; Loading @@ -72,5 +108,23 @@ in format = mkIf (cfg.platform != "ipu6") (mkDefault "NV12"); }; }; # Override preStart/postStop from the v4l2-relayd module: # - Use a fixed device number so PipeWire node names (and application permission # grants) are stable across reboots. Exit 17 (EEXIST) is success. # - Keep the device alive on stop so apps survive relay restarts via # VIDIOC_DQBUF blocking rather than receiving errors. systemd.services.v4l2-relayd-ipu6 = { preStart = mkForce '' mkdir -p "$(dirname "$V4L2_DEVICE_FILE")" ${config.boot.kernelPackages.v4l2loopback.bin}/bin/v4l2loopback-ctl \ add --name "Intel MIPI Camera" --exclusive-caps=1 ${toString cfg.videoDeviceNumber} || [ $? -eq 17 ] echo /dev/video${toString cfg.videoDeviceNumber} > "$V4L2_DEVICE_FILE" ''; postStop = mkForce '' rm -rf "$(dirname "$V4L2_DEVICE_FILE")" ''; }; }; }