feat(cooling): Package OpenLinkHub and add module

Change-Id: I2273a14c6242df77aef4378f1ed1a455b3815a4e
Reviewed-on: https://git.clicks.codes/c/Chimera/NixFiles/+/827
Tested-by: Samuel Shuert <coded@clicks.codes>
Reviewed-by: Skyler Grey <minion@clicks.codes>
diff --git a/modules/nixos/cooling/OpenLinkHub/default.nix b/modules/nixos/cooling/OpenLinkHub/default.nix
new file mode 100644
index 0000000..6150765
--- /dev/null
+++ b/modules/nixos/cooling/OpenLinkHub/default.nix
@@ -0,0 +1,87 @@
+{
+  lib
+, config
+, pkgs
+, ...
+}: let
+  cfg = config.chimera.cooling.OpenLinkHub;
+in {
+  options.chimera.cooling.OpenLinkHub = {
+    enable = lib.mkEnableOption "Enable OpenLinkHub service for Corsair iCUE Link";
+    package = lib.mkOption {
+      type = lib.types.package;
+      description = "OpenLinkHub package to use for the module";
+      default = pkgs.chimera.OpenLinkHub;
+    };
+    config = lib.mkOption {
+      type = lib.types.path;
+      default = "${cfg.package}/var/lib/OpenLinkHub/config.json";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    users.groups.OpenLinkHub = {};
+
+    users.users.OpenLinkHub = {
+      isSystemUser = true;
+      group = config.users.groups.OpenLinkHub.name;
+      extraGroups = [ config.users.groups.input.name ];
+    };
+
+    systemd.services.OpenLinkHub = let
+      path = "/var/lib/OpenLinkHub";
+    in {
+      enable = true;
+      description = "Open source interface for iCUE LINK System Hub, Corsair AIOs and Hubs";
+
+      preStart = ''
+        mkdir -p ${path}/database
+        [ -f ${path}/database/rgb.json ] || cp ${cfg.package}/var/lib/OpenLinkHub/rgb.json ${path}/database/rgb.json
+        mkdir -p ${path}/database/temperatures
+        mkdir -p ${path}/database/profiles
+        mkdir -p /run/udev/rules.d
+
+        cp ${cfg.config} ${path}/config.json
+
+        [ -L ${path}/static ] || ln -s ${cfg.package}/var/lib/OpenLinkHub/static ${path}/static
+        [ -L ${path}/web ] || ln -s ${cfg.package}/var/lib/OpenLinkHub/web ${path}/web
+
+        ${pkgs.usbutils}/bin/lsusb -d 1b1c: | while read -r line; do
+        ids=$(echo "$line" | ${pkgs.gawk}/bin/awk '{print $6}')
+        vendor_id=$(${pkgs.coreutils}/bin/echo "$ids" | ${pkgs.coreutils}/bin/cut -d':' -f1)
+        device_id=$(${pkgs.coreutils}/bin/echo "$ids" | ${pkgs.coreutils}/bin/cut -d':' -f2)
+        ${pkgs.coreutils}/bin/cat > /run/udev/rules.d/99-corsair-openlinkhub-"$device_id".rules <<- EOM
+        KERNEL=="hidraw*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="$vendor_id", ATTRS{idProduct}=="$device_id", MODE="0666"
+        EOM
+        done
+
+        ${pkgs.coreutils}/bin/chmod -R 744 ${path}
+        ${pkgs.coreutils}/bin/chown -R OpenLinkHub:OpenLinkHub ${path}
+
+        ${pkgs.systemd}/bin/udevadm control --reload
+        ${pkgs.systemd}/bin/udevadm trigger
+      '';
+
+      postStop = ''
+        ${pkgs.coreutils}/bin/rm /run/udev/rules.d/99-corsair-openlinkhub-*.rules
+
+        ${pkgs.systemd}/bin/udevadm control --reload
+        ${pkgs.systemd}/bin/udevadm trigger
+      '';
+
+      path = [ pkgs.pciutils ];
+
+      serviceConfig = {
+        DynamicUser = true;
+        ExecStart = "${cfg.package}/bin/OpenLinkHub";
+        ExecReload = "${pkgs.coreutils}/bin/kill -s HUP \$MAINPID";
+        RestartSec = 5;
+        PermissionsStartOnly = true;
+        StateDirectory = "OpenLinkHub";
+        WorkingDirectory = "/var/lib/OpenLinkHub";
+      };
+
+      wantedBy = [ "multi-user.target" ];
+    };
+  };
+}
diff --git a/packages/OpenLinkHub/default.nix b/packages/OpenLinkHub/default.nix
new file mode 100644
index 0000000..f9119f2
--- /dev/null
+++ b/packages/OpenLinkHub/default.nix
@@ -0,0 +1,33 @@
+{ lib
+, buildGoModule
+, fetchFromGitHub
+, pkg-config
+, systemd
+}:
+let
+  version = "0.2.1";
+  OpenLinkHub = fetchFromGitHub {
+    owner = "jurkovic-nikola";
+    repo = "OpenLinkHub";
+    rev = version;
+    hash = "sha256-2naNOGRPKy8H9I4e6X+uX3muT20M9YX2BGrPmY7RVAo=";
+  };
+in
+buildGoModule {
+  pname = "OpenLinkHub";
+  inherit version;
+
+  src = OpenLinkHub;
+
+  nativeBuildInputs = [ pkg-config ];
+  buildInputs = [ systemd.dev ];
+
+  postInstall = ''
+    mkdir -p $out/var/lib/OpenLinkHub
+    cp -r ${OpenLinkHub}/{static,web} $out/var/lib/OpenLinkHub
+    cp ${OpenLinkHub}/config.json $out/var/lib/OpenLinkHub
+    cp ${OpenLinkHub}/database/rgb.json $out/var/lib/OpenLinkHub
+  '';
+
+  vendorHash = "sha256-Sv2gGnI3mJvOl866idKC1q+6jh4ysEot0eLLBKPb0T0=";
+}
diff --git a/systems/x86_64-linux/shorthair/default.nix b/systems/x86_64-linux/shorthair/default.nix
index 4a39549..d0aabb2 100644
--- a/systems/x86_64-linux/shorthair/default.nix
+++ b/systems/x86_64-linux/shorthair/default.nix
@@ -7,6 +7,7 @@
     ./compositor
     ./console
     ./games
+    ./hardware/cooling
     ./hardware/cpu
     ./hardware/filesystems
     ./networking
diff --git a/systems/x86_64-linux/shorthair/hardware/cooling/default.nix b/systems/x86_64-linux/shorthair/hardware/cooling/default.nix
new file mode 100644
index 0000000..8badc94
--- /dev/null
+++ b/systems/x86_64-linux/shorthair/hardware/cooling/default.nix
@@ -0,0 +1,4 @@
+{ ... }:
+{
+  chimera.cooling.OpenLinkHub.enable = true;
+}