me like nix
0

Configure Feed

Select the types of activity you want to include in your feed.

1{ ... }: { 2 flake.modules.nixos.pi-camera = 3 { pkgs, lib, config, ... }: 4 let 5 cfg = config.pi; 6 7 deviceTree_overlay = _final: prev: { 8 deviceTree = { 9 applyOverlays = prev.callPackage ../hosts/pi-common/overlays/apply-overlays-dtmerge.nix { }; 10 compileDTS = prev.deviceTree.compileDTS; 11 }; 12 }; 13 14 libcamera-rpi = pkgs.libcamera.overrideAttrs (old: { 15 mesonFlags = (old.mesonFlags or [ ]) ++ [ 16 "-Dipas=rpi/vc4,rpi/pisp" 17 "-Dpipelines=rpi/vc4,rpi/pisp" 18 ]; 19 }); 20 21 rpicam-apps = pkgs.stdenv.mkDerivation rec { 22 pname = "rpicam-apps"; 23 version = "1.11.1"; 24 25 src = pkgs.fetchFromGitHub { 26 owner = "raspberrypi"; 27 repo = "rpicam-apps"; 28 rev = "v${version}"; 29 hash = "sha256-hVoKbvWFeramPkHuibJwUgFOPS9v588+K8828a1fNnA="; 30 }; 31 32 nativeBuildInputs = with pkgs; [ 33 meson 34 ninja 35 pkg-config 36 ]; 37 38 buildInputs = [ 39 libcamera-rpi 40 pkgs.libdrm 41 pkgs.libexif 42 pkgs.libjpeg 43 pkgs.libpng 44 pkgs.libtiff 45 pkgs.boost 46 pkgs.ffmpeg 47 ]; 48 49 mesonFlags = [ 50 "-Denable_libav=enabled" 51 "-Denable_drm=enabled" 52 "-Denable_egl=disabled" 53 "-Denable_qt=disabled" 54 "-Denable_opencv=disabled" 55 "-Denable_tflite=disabled" 56 "-Denable_hailo=disabled" 57 ]; 58 59 meta = with lib; { 60 description = "Raspberry Pi camera applications"; 61 homepage = "https://github.com/raspberrypi/rpicam-apps"; 62 license = licenses.bsd2; 63 platforms = [ "aarch64-linux" ]; 64 }; 65 }; 66 in 67 { 68 options.pi = { 69 streamName = lib.mkOption { 70 type = lib.types.str; 71 description = "Name of the camera stream"; 72 }; 73 resolution = { 74 width = lib.mkOption { 75 type = lib.types.int; 76 default = 1920; 77 description = "Camera resolution width"; 78 }; 79 height = lib.mkOption { 80 type = lib.types.int; 81 default = 1080; 82 description = "Camera resolution height"; 83 }; 84 }; 85 framerate = lib.mkOption { 86 type = lib.types.int; 87 default = 30; 88 description = "Camera framerate"; 89 }; 90 deviceTreeFilter = lib.mkOption { 91 type = lib.types.str; 92 description = "Device tree filter pattern"; 93 }; 94 deviceTreeCompatible = lib.mkOption { 95 type = lib.types.str; 96 description = "Device tree compatible string"; 97 }; 98 gpuMem = lib.mkOption { 99 type = lib.types.int; 100 default = 256; 101 description = "GPU memory allocation in MB"; 102 }; 103 flipCamera = lib.mkOption { 104 type = lib.types.bool; 105 default = false; 106 description = "Flip camera image 180 degrees"; 107 }; 108 }; 109 110 config = { 111 boot.kernelParams = [ "cma=256M" ]; 112 113 nix.settings.trusted-users = [ "sean" ]; 114 115 networking.useDHCP = true; 116 nixpkgs.overlays = [ deviceTree_overlay ]; 117 118 boot.supportedFilesystems = lib.mkForce [ 119 "vfat" 120 "ext4" 121 ]; 122 boot.initrd.systemd.enable = false; 123 124 services.openssh = { 125 enable = true; 126 settings = { 127 PasswordAuthentication = false; 128 PermitRootLogin = "no"; 129 }; 130 }; 131 132 users.users.sean = { 133 isNormalUser = true; 134 extraGroups = [ 135 "wheel" 136 "video" 137 ]; 138 openssh.authorizedKeys.keys = [ 139 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCIqgZ7kedxo+mOW7YG73Vp3zel3h180y3GKvHtRsXfGlpIIvRDy7pgCBQ4AGXYD4y78URQmFohYSAPqCPOPaWcU2un3XG9KvCzEsHmsbskPonitUmCiKvrKkb6oW4jCBtd7AEtBn+AiajAQFtPZ7NN2Df3AmTypvR6Irg7R+nxnfc9NTIHmGvxSDyWcbb4pguL20sctUSqGL6xGh8q/bqhdOThSimM+z9bEUNxK/5rPhwkNniMrp4pJcUrUiAh5/4DiRFG6KT+oeg+/myoz/Z1sPvAs7u/8JDQI4RshRD8Hu0oTkRBN6Hxj478q2SXbeBUZlD6IdjP3RhGpmSecoDdtWqKbpuV3eVRtQtba3KL86GBeV/bugaOdJ1Aud+1SOFJreAAuvxzMMKT+cdQZk6oOPP148DA/No+mDm/2S43lcdCXh79wA6YRAmKQ8jmZxTCtPutrvuZK1rguvvUlEoG/vhdNHh7eDa4Td07V6bjCRPUl8qk/e4M0E3pwsTlZc=" 140 "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOIgEteUEW06dnBHe2z8vNLwz2iMKe8bba6JgMmOUpcBAAAABHNzaDo= sean@framework16" 141 ]; 142 }; 143 144 security.sudo.wheelNeedsPassword = false; 145 146 services.go2rtc = { 147 enable = true; 148 settings = { 149 ffmpeg.bin = "${pkgs.ffmpeg}/bin/ffmpeg"; 150 streams = { 151 "${cfg.streamName}" = "exec:${rpicam-apps}/bin/rpicam-vid -t 0 --width ${toString cfg.resolution.width} --height ${toString cfg.resolution.height} --framerate ${toString cfg.framerate} --codec h264 --inline${lib.optionalString cfg.flipCamera " --vflip --hflip"} -o -"; 152 }; 153 }; 154 }; 155 156 services.udev.extraRules = '' 157 SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660" 158 ''; 159 160 systemd.services.go2rtc.serviceConfig = { 161 User = lib.mkForce "root"; 162 }; 163 164 environment.systemPackages = [ 165 pkgs.ffmpeg 166 pkgs.libraspberrypi 167 libcamera-rpi 168 rpicam-apps 169 pkgs.v4l-utils 170 ]; 171 172 hardware.deviceTree.filter = cfg.deviceTreeFilter; 173 hardware.deviceTree.overlays = [ 174 { 175 # Increase CMA from 64MB to 256MB via device tree 176 # (cmdline cma= bypasses the DT node and /dev/dma_heap/linux,cma isn't created) 177 name = "cma-256m"; 178 dtsText = '' 179 /dts-v1/; 180 /plugin/; 181 182 / { 183 compatible = "${cfg.deviceTreeCompatible}"; 184 185 fragment@99 { 186 target-path = "/reserved-memory/linux,cma"; 187 __overlay__ { 188 size = <0x00 0x10000000>; /* 256MB */ 189 }; 190 }; 191 }; 192 ''; 193 } 194 { 195 name = "imx708-overlay"; 196 dtsText = '' 197 // SPDX-License-Identifier: GPL-2.0-only 198 // Definitions for IMX708 camera module on VC I2C bus 199 /dts-v1/; 200 /plugin/; 201 202 /{ 203 compatible = "${cfg.deviceTreeCompatible}"; 204 205 fragment@0 { 206 target = <&i2c0if>; 207 __overlay__ { 208 status = "okay"; 209 }; 210 }; 211 212 clk_frag: fragment@1 { 213 target = <&cam1_clk>; 214 __overlay__ { 215 status = "okay"; 216 clock-frequency = <24000000>; 217 }; 218 }; 219 220 fragment@2 { 221 target = <&i2c0mux>; 222 __overlay__ { 223 status = "okay"; 224 }; 225 }; 226 227 reg_frag: fragment@3 { 228 target = <&cam1_reg>; 229 cam_reg: __overlay__ { 230 startup-delay-us = <70000>; 231 off-on-delay-us = <30000>; 232 regulator-min-microvolt = <2700000>; 233 regulator-max-microvolt = <2700000>; 234 }; 235 }; 236 237 i2c_frag: fragment@100 { 238 target = <&i2c_csi_dsi>; 239 __overlay__ { 240 #address-cells = <1>; 241 #size-cells = <0>; 242 status = "okay"; 243 244 cam_node: imx708@1a { 245 compatible = "sony,imx708"; 246 reg = <0x1a>; 247 status = "okay"; 248 249 clocks = <&cam1_clk>; 250 clock-names = "inclk"; 251 252 vana1-supply = <&cam1_reg>; 253 vana2-supply = <&cam_dummy_reg>; 254 vdig-supply = <&cam_dummy_reg>; 255 vddl-supply = <&cam_dummy_reg>; 256 257 rotation = <180>; 258 orientation = <2>; 259 260 port { 261 cam_endpoint: endpoint { 262 clock-lanes = <0>; 263 data-lanes = <1 2>; 264 clock-noncontinuous; 265 link-frequencies = 266 /bits/ 64 <450000000>; 267 }; 268 }; 269 }; 270 271 vcm_node: dw9817@c { 272 compatible = "dongwoon,dw9817-vcm"; 273 reg = <0x0c>; 274 status = "okay"; 275 VDD-supply = <&cam1_reg>; 276 }; 277 }; 278 }; 279 280 csi_frag: fragment@101 { 281 target = <&csi1>; 282 csi: __overlay__ { 283 status = "okay"; 284 brcm,media-controller; 285 286 port { 287 csi_ep: endpoint { 288 remote-endpoint = <&cam_endpoint>; 289 clock-lanes = <0>; 290 data-lanes = <1 2>; 291 clock-noncontinuous; 292 }; 293 }; 294 }; 295 }; 296 297 __overrides__ { 298 rotation = <&cam_node>,"rotation:0"; 299 orientation = <&cam_node>,"orientation:0"; 300 media-controller = <&csi>,"brcm,media-controller?"; 301 cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, 302 <&csi_frag>, "target:0=",<&csi0>, 303 <&clk_frag>, "target:0=",<&cam0_clk>, 304 <&reg_frag>, "target:0=",<&cam0_reg>, 305 <&cam_node>, "clocks:0=",<&cam0_clk>, 306 <&cam_node>, "vana1-supply:0=",<&cam0_reg>, 307 <&vcm_node>, "VDD-supply:0=",<&cam0_reg>; 308 vcm = <&vcm_node>, "status", 309 <0>, "=4"; 310 link-frequency = <&cam_endpoint>,"link-frequencies#0"; 311 }; 312 }; 313 314 &cam_endpoint { 315 remote-endpoint = <&csi_ep>; 316 }; 317 ''; 318 } 319 ]; 320 321 hardware.enableRedistributableFirmware = true; 322 323 sdImage.populateFirmwareCommands = lib.mkAfter '' 324 chmod u+w ./firmware/config.txt 325 cat >> ./firmware/config.txt << EOF 326 327 # Camera support - Pi Camera v3 (IMX708) 328 gpu_mem=${toString cfg.gpuMem} 329 EOF 330 331 if [ -d ${pkgs.raspberrypifw}/share/raspberrypi/boot/overlays ]; then 332 cp -r ${pkgs.raspberrypifw}/share/raspberrypi/boot/overlays ./firmware/ 333 fi 334 ''; 335 336 networking.firewall.allowedTCPPorts = [ 337 22 338 1984 339 8554 340 ]; 341 }; 342 }; 343}