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 name = "imx708-overlay"; 174 dtsText = '' 175 // SPDX-License-Identifier: GPL-2.0-only 176 // Definitions for IMX708 camera module on VC I2C bus 177 /dts-v1/; 178 /plugin/; 179 180 /{ 181 compatible = "${cfg.deviceTreeCompatible}"; 182 183 fragment@0 { 184 target = <&i2c0if>; 185 __overlay__ { 186 status = "okay"; 187 }; 188 }; 189 190 clk_frag: fragment@1 { 191 target = <&cam1_clk>; 192 __overlay__ { 193 status = "okay"; 194 clock-frequency = <24000000>; 195 }; 196 }; 197 198 fragment@2 { 199 target = <&i2c0mux>; 200 __overlay__ { 201 status = "okay"; 202 }; 203 }; 204 205 reg_frag: fragment@3 { 206 target = <&cam1_reg>; 207 cam_reg: __overlay__ { 208 startup-delay-us = <70000>; 209 off-on-delay-us = <30000>; 210 regulator-min-microvolt = <2700000>; 211 regulator-max-microvolt = <2700000>; 212 }; 213 }; 214 215 i2c_frag: fragment@100 { 216 target = <&i2c_csi_dsi>; 217 __overlay__ { 218 #address-cells = <1>; 219 #size-cells = <0>; 220 status = "okay"; 221 222 cam_node: imx708@1a { 223 compatible = "sony,imx708"; 224 reg = <0x1a>; 225 status = "okay"; 226 227 clocks = <&cam1_clk>; 228 clock-names = "inclk"; 229 230 vana1-supply = <&cam1_reg>; 231 vana2-supply = <&cam_dummy_reg>; 232 vdig-supply = <&cam_dummy_reg>; 233 vddl-supply = <&cam_dummy_reg>; 234 235 rotation = <180>; 236 orientation = <2>; 237 238 port { 239 cam_endpoint: endpoint { 240 clock-lanes = <0>; 241 data-lanes = <1 2>; 242 clock-noncontinuous; 243 link-frequencies = 244 /bits/ 64 <450000000>; 245 }; 246 }; 247 }; 248 249 vcm_node: dw9817@c { 250 compatible = "dongwoon,dw9817-vcm"; 251 reg = <0x0c>; 252 status = "okay"; 253 VDD-supply = <&cam1_reg>; 254 }; 255 }; 256 }; 257 258 csi_frag: fragment@101 { 259 target = <&csi1>; 260 csi: __overlay__ { 261 status = "okay"; 262 brcm,media-controller; 263 264 port { 265 csi_ep: endpoint { 266 remote-endpoint = <&cam_endpoint>; 267 clock-lanes = <0>; 268 data-lanes = <1 2>; 269 clock-noncontinuous; 270 }; 271 }; 272 }; 273 }; 274 275 __overrides__ { 276 rotation = <&cam_node>,"rotation:0"; 277 orientation = <&cam_node>,"orientation:0"; 278 media-controller = <&csi>,"brcm,media-controller?"; 279 cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, 280 <&csi_frag>, "target:0=",<&csi0>, 281 <&clk_frag>, "target:0=",<&cam0_clk>, 282 <&reg_frag>, "target:0=",<&cam0_reg>, 283 <&cam_node>, "clocks:0=",<&cam0_clk>, 284 <&cam_node>, "vana1-supply:0=",<&cam0_reg>, 285 <&vcm_node>, "VDD-supply:0=",<&cam0_reg>; 286 vcm = <&vcm_node>, "status", 287 <0>, "=4"; 288 link-frequency = <&cam_endpoint>,"link-frequencies#0"; 289 }; 290 }; 291 292 &cam_endpoint { 293 remote-endpoint = <&csi_ep>; 294 }; 295 ''; 296 } 297 ]; 298 299 hardware.enableRedistributableFirmware = true; 300 301 sdImage.populateFirmwareCommands = lib.mkAfter '' 302 chmod u+w ./firmware/config.txt 303 cat >> ./firmware/config.txt << EOF 304 305 # Camera support - Pi Camera v3 (IMX708) 306 gpu_mem=${toString cfg.gpuMem} 307 EOF 308 309 if [ -d ${pkgs.raspberrypifw}/share/raspberrypi/boot/overlays ]; then 310 cp -r ${pkgs.raspberrypifw}/share/raspberrypi/boot/overlays ./firmware/ 311 fi 312 ''; 313 314 networking.firewall.allowedTCPPorts = [ 315 22 316 1984 317 8554 318 ]; 319 }; 320 }; 321}