diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index e7f28c670bed..b00cc7a67697 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -245,6 +245,7 @@
./services/hardware/illum.nix
./services/hardware/interception-tools.nix
./services/hardware/irqbalance.nix
+ ./services/hardware/lcd.nix
./services/hardware/nvidia-optimus.nix
./services/hardware/pcscd.nix
./services/hardware/pommed.nix
diff --git a/nixos/modules/services/hardware/lcd.nix b/nixos/modules/services/hardware/lcd.nix
new file mode 100644
index 000000000000..d78d742cd318
--- /dev/null
+++ b/nixos/modules/services/hardware/lcd.nix
@@ -0,0 +1,172 @@
+{ 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.
+
+
+ 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
+ and
+ . In order to find the
+ values, you can run the lsusb command. Example
+ output:
+
+
+
+ Bus 005 Device 002: ID 0403:c630 Future Technology Devices International, Ltd lcd2usb interface
+
+
+
+ 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" ];
+ 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";
+ # Allow restarting for eternity
+ StartLimitIntervalSec = lib.mkIf cfg.client.restartForever "0";
+ StartLimitBurst = lib.mkIf cfg.client.restartForever "0";
+ };
+ };
+ };
+
+ systemd.targets.lcd = {
+ description = "LCD client/server";
+ after = [ "lcdd.service" "lcdproc.service" ];
+ wantedBy = [ "multi-user.target" ];
+ };
+ };
+}