summary refs log tree commit diff
path: root/nixos/modules/services/hardware/lcd.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/hardware/lcd.nix')
-rw-r--r--nixos/modules/services/hardware/lcd.nix171
1 files changed, 171 insertions, 0 deletions
diff --git a/nixos/modules/services/hardware/lcd.nix b/nixos/modules/services/hardware/lcd.nix
new file mode 100644
index 00000000000..dc8595ea60c
--- /dev/null
+++ b/nixos/modules/services/hardware/lcd.nix
@@ -0,0 +1,171 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.hardware.lcd;
+  pkg = lib.getBin pkgs.lcdproc;
+
+  serverCfg = pkgs.writeText "lcdd.conf" ''
+    [server]
+    DriverPath=${pkg}/lib/lcdproc/
+    ReportToSyslog=false
+    Bind=${cfg.serverHost}
+    Port=${toString cfg.serverPort}
+    ${cfg.server.extraConfig}
+  '';
+
+  clientCfg = pkgs.writeText "lcdproc.conf" ''
+    [lcdproc]
+    Server=${cfg.serverHost}
+    Port=${toString cfg.serverPort}
+    ReportToSyslog=false
+    ${cfg.client.extraConfig}
+  '';
+
+  serviceCfg = {
+    DynamicUser = true;
+    Restart = "on-failure";
+    Slice = "lcd.slice";
+  };
+
+in with lib; {
+
+  meta.maintainers = with maintainers; [ peterhoeg ];
+
+  options = with types; {
+    services.hardware.lcd = {
+      serverHost = mkOption {
+        type = str;
+        default = "localhost";
+        description = "Host on which LCDd is listening.";
+      };
+
+      serverPort = mkOption {
+        type = int;
+        default = 13666;
+        description = "Port on which LCDd is listening.";
+      };
+
+      server = {
+        enable = mkOption {
+          type = bool;
+          default = false;
+          description = "Enable the LCD panel server (LCDd)";
+        };
+
+        openPorts = mkOption {
+          type = bool;
+          default = false;
+          description = "Open the ports in the firewall";
+        };
+
+        usbPermissions = mkOption {
+          type = bool;
+          default = false;
+          description = ''
+            Set group-write permissions on a USB device.
+            </para>
+            <para>
+            A USB connected LCD panel will most likely require having its
+            permissions modified for lcdd to write to it. Enabling this option
+            sets group-write permissions on the device identified by
+            <option>services.hardware.lcd.usbVid</option> and
+            <option>services.hardware.lcd.usbPid</option>. In order to find the
+            values, you can run the <command>lsusb</command> command. Example
+            output:
+            </para>
+            <para>
+            <literal>
+            Bus 005 Device 002: ID 0403:c630 Future Technology Devices International, Ltd lcd2usb interface
+            </literal>
+            </para>
+            <para>
+            In this case the vendor id is 0403 and the product id is c630.
+          '';
+        };
+
+        usbVid = mkOption {
+          type = str;
+          default = "";
+          description = "The vendor ID of the USB device to claim.";
+        };
+
+        usbPid = mkOption {
+          type = str;
+          default = "";
+          description = "The product ID of the USB device to claim.";
+        };
+
+        usbGroup = mkOption {
+          type = str;
+          default = "dialout";
+          description = "The group to use for settings permissions. This group must exist or you will have to create it.";
+        };
+
+        extraConfig = mkOption {
+          type = lines;
+          default = "";
+          description = "Additional configuration added verbatim to the server config.";
+        };
+      };
+
+      client = {
+        enable = mkOption {
+          type = bool;
+          default = false;
+          description = "Enable the LCD panel client (LCDproc)";
+        };
+
+        extraConfig = mkOption {
+          type = lines;
+          default = "";
+          description = "Additional configuration added verbatim to the client config.";
+        };
+
+        restartForever = mkOption {
+          type = bool;
+          default = true;
+          description = "Try restarting the client forever.";
+        };
+      };
+    };
+  };
+
+  config = mkIf (cfg.server.enable || cfg.client.enable) {
+    networking.firewall.allowedTCPPorts = mkIf (cfg.server.enable && cfg.server.openPorts) [ cfg.serverPort ];
+
+    services.udev.extraRules = mkIf (cfg.server.enable && cfg.server.usbPermissions) ''
+      ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="${cfg.server.usbVid}", ATTRS{idProduct}=="${cfg.server.usbPid}", MODE="660", GROUP="${cfg.server.usbGroup}"
+    '';
+
+    systemd.services = {
+      lcdd = mkIf cfg.server.enable {
+        description = "LCDproc - server";
+        wantedBy = [ "lcd.target" ];
+        serviceConfig = serviceCfg // {
+          ExecStart = "${pkg}/bin/LCDd -f -c ${serverCfg}";
+          SupplementaryGroups = cfg.server.usbGroup;
+        };
+      };
+
+      lcdproc = mkIf cfg.client.enable {
+        description = "LCDproc - client";
+        after = [ "lcdd.service" ];
+        wantedBy = [ "lcd.target" ];
+        # Allow restarting for eternity
+        startLimitIntervalSec = lib.mkIf cfg.client.restartForever 0;
+        serviceConfig = serviceCfg // {
+          ExecStart = "${pkg}/bin/lcdproc -f -c ${clientCfg}";
+          # If the server is being restarted at the same time, the client will
+          # fail as it cannot connect, so space it out a bit.
+          RestartSec = "5";
+        };
+      };
+    };
+
+    systemd.targets.lcd = {
+      description = "LCD client/server";
+      after = [ "lcdd.service" "lcdproc.service" ];
+      wantedBy = [ "multi-user.target" ];
+    };
+  };
+}