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 nix.settings.trusted-users = [ "sean" ]; 112 113 networking.useDHCP = true; 114 nixpkgs.overlays = [ deviceTree_overlay ]; 115 116 boot.supportedFilesystems = lib.mkForce [ 117 "vfat" 118 "ext4" 119 ]; 120 boot.initrd.systemd.enable = false; 121 122 services.openssh = { 123 enable = true; 124 settings = { 125 PasswordAuthentication = false; 126 PermitRootLogin = "no"; 127 }; 128 }; 129 130 users.users.sean = { 131 isNormalUser = true; 132 extraGroups = [ 133 "wheel" 134 "video" 135 ]; 136 openssh.authorizedKeys.keys = [ 137 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCIqgZ7kedxo+mOW7YG73Vp3zel3h180y3GKvHtRsXfGlpIIvRDy7pgCBQ4AGXYD4y78URQmFohYSAPqCPOPaWcU2un3XG9KvCzEsHmsbskPonitUmCiKvrKkb6oW4jCBtd7AEtBn+AiajAQFtPZ7NN2Df3AmTypvR6Irg7R+nxnfc9NTIHmGvxSDyWcbb4pguL20sctUSqGL6xGh8q/bqhdOThSimM+z9bEUNxK/5rPhwkNniMrp4pJcUrUiAh5/4DiRFG6KT+oeg+/myoz/Z1sPvAs7u/8JDQI4RshRD8Hu0oTkRBN6Hxj478q2SXbeBUZlD6IdjP3RhGpmSecoDdtWqKbpuV3eVRtQtba3KL86GBeV/bugaOdJ1Aud+1SOFJreAAuvxzMMKT+cdQZk6oOPP148DA/No+mDm/2S43lcdCXh79wA6YRAmKQ8jmZxTCtPutrvuZK1rguvvUlEoG/vhdNHh7eDa4Td07V6bjCRPUl8qk/e4M0E3pwsTlZc=" 138 "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOIgEteUEW06dnBHe2z8vNLwz2iMKe8bba6JgMmOUpcBAAAABHNzaDo= sean@framework16" 139 ]; 140 }; 141 142 security.sudo.wheelNeedsPassword = false; 143 144 services.go2rtc = { 145 enable = true; 146 settings = { 147 ffmpeg.bin = "${pkgs.ffmpeg}/bin/ffmpeg"; 148 streams = { 149 "${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 -"; 150 }; 151 }; 152 }; 153 154 services.udev.extraRules = '' 155 SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660" 156 ''; 157 158 systemd.services.go2rtc.serviceConfig = { 159 User = lib.mkForce "root"; 160 }; 161 162 environment.systemPackages = [ 163 pkgs.ffmpeg 164 pkgs.libraspberrypi 165 libcamera-rpi 166 rpicam-apps 167 pkgs.v4l-utils 168 ]; 169 170 hardware.deviceTree.filter = cfg.deviceTreeFilter; 171 hardware.deviceTree.overlays = [ 172 { 173 # Increase CMA from 64MB to 256MB via device tree 174 # (cmdline cma= bypasses the DT node and /dev/dma_heap/linux,cma isn't created) 175 name = "cma-256m"; 176 dtsText = '' 177 /dts-v1/; 178 /plugin/; 179 180 / { 181 compatible = "${cfg.deviceTreeCompatible}"; 182 183 fragment@99 { 184 target-path = "/reserved-memory/linux,cma"; 185 __overlay__ { 186 size = <0x00 0x10000000>; /* 256MB */ 187 }; 188 }; 189 }; 190 ''; 191 } 192 { 193 name = "imx708-overlay"; 194 dtsText = '' 195 // SPDX-License-Identifier: GPL-2.0-only 196 // Definitions for IMX708 camera module on VC I2C bus 197 /dts-v1/; 198 /plugin/; 199 200 /{ 201 compatible = "${cfg.deviceTreeCompatible}"; 202 203 fragment@0 { 204 target = <&i2c0if>; 205 __overlay__ { 206 status = "okay"; 207 }; 208 }; 209 210 clk_frag: fragment@1 { 211 target = <&cam1_clk>; 212 __overlay__ { 213 status = "okay"; 214 clock-frequency = <24000000>; 215 }; 216 }; 217 218 fragment@2 { 219 target = <&i2c0mux>; 220 __overlay__ { 221 status = "okay"; 222 }; 223 }; 224 225 reg_frag: fragment@3 { 226 target = <&cam1_reg>; 227 cam_reg: __overlay__ { 228 startup-delay-us = <70000>; 229 off-on-delay-us = <30000>; 230 regulator-min-microvolt = <2700000>; 231 regulator-max-microvolt = <2700000>; 232 }; 233 }; 234 235 i2c_frag: fragment@100 { 236 target = <&i2c_csi_dsi>; 237 __overlay__ { 238 #address-cells = <1>; 239 #size-cells = <0>; 240 status = "okay"; 241 242 cam_node: imx708@1a { 243 compatible = "sony,imx708"; 244 reg = <0x1a>; 245 status = "okay"; 246 247 clocks = <&cam1_clk>; 248 clock-names = "inclk"; 249 250 vana1-supply = <&cam1_reg>; 251 vana2-supply = <&cam_dummy_reg>; 252 vdig-supply = <&cam_dummy_reg>; 253 vddl-supply = <&cam_dummy_reg>; 254 255 rotation = <180>; 256 orientation = <2>; 257 258 port { 259 cam_endpoint: endpoint { 260 clock-lanes = <0>; 261 data-lanes = <1 2>; 262 clock-noncontinuous; 263 link-frequencies = 264 /bits/ 64 <450000000>; 265 }; 266 }; 267 }; 268 269 vcm_node: dw9817@c { 270 compatible = "dongwoon,dw9817-vcm"; 271 reg = <0x0c>; 272 status = "okay"; 273 VDD-supply = <&cam1_reg>; 274 }; 275 }; 276 }; 277 278 csi_frag: fragment@101 { 279 target = <&csi1>; 280 csi: __overlay__ { 281 status = "okay"; 282 brcm,media-controller; 283 284 port { 285 csi_ep: endpoint { 286 remote-endpoint = <&cam_endpoint>; 287 clock-lanes = <0>; 288 data-lanes = <1 2>; 289 clock-noncontinuous; 290 }; 291 }; 292 }; 293 }; 294 295 __overrides__ { 296 rotation = <&cam_node>,"rotation:0"; 297 orientation = <&cam_node>,"orientation:0"; 298 media-controller = <&csi>,"brcm,media-controller?"; 299 cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, 300 <&csi_frag>, "target:0=",<&csi0>, 301 <&clk_frag>, "target:0=",<&cam0_clk>, 302 <&reg_frag>, "target:0=",<&cam0_reg>, 303 <&cam_node>, "clocks:0=",<&cam0_clk>, 304 <&cam_node>, "vana1-supply:0=",<&cam0_reg>, 305 <&vcm_node>, "VDD-supply:0=",<&cam0_reg>; 306 vcm = <&vcm_node>, "status", 307 <0>, "=4"; 308 link-frequency = <&cam_endpoint>,"link-frequencies#0"; 309 }; 310 }; 311 312 &cam_endpoint { 313 remote-endpoint = <&csi_ep>; 314 }; 315 ''; 316 } 317 ]; 318 319 hardware.enableRedistributableFirmware = true; 320 321 sdImage.populateFirmwareCommands = lib.mkAfter '' 322 chmod u+w ./firmware/config.txt 323 cat >> ./firmware/config.txt << EOF 324 325 # Camera support - Pi Camera v3 (IMX708) 326 gpu_mem=${toString cfg.gpuMem} 327 EOF 328 329 if [ -d ${pkgs.raspberrypifw}/share/raspberrypi/boot/overlays ]; then 330 cp -r ${pkgs.raspberrypifw}/share/raspberrypi/boot/overlays ./firmware/ 331 fi 332 ''; 333 334 networking.firewall.allowedTCPPorts = [ 335 22 336 1984 337 8554 338 ]; 339 }; 340 }; 341}