diff options
author | Vladimír Čunát <v@cunat.cz> | 2019-09-04 11:00:56 +0200 |
---|---|---|
committer | Vladimír Čunát <v@cunat.cz> | 2019-09-04 11:00:56 +0200 |
commit | 4aad2947f8d680f18e5b01e115cf8cff22186998 (patch) | |
tree | a7a3d020efc6ec7be822bc06e08eca3ac311c9e2 /nixos/modules/hardware | |
parent | 2c5835b09a1d4966756212902d36b1b8ab242da6 (diff) | |
parent | 1d8a3973f46a2d1360f855eaa0f3a19859771793 (diff) | |
download | nixlib-4aad2947f8d680f18e5b01e115cf8cff22186998.tar nixlib-4aad2947f8d680f18e5b01e115cf8cff22186998.tar.gz nixlib-4aad2947f8d680f18e5b01e115cf8cff22186998.tar.bz2 nixlib-4aad2947f8d680f18e5b01e115cf8cff22186998.tar.lz nixlib-4aad2947f8d680f18e5b01e115cf8cff22186998.tar.xz nixlib-4aad2947f8d680f18e5b01e115cf8cff22186998.tar.zst nixlib-4aad2947f8d680f18e5b01e115cf8cff22186998.zip |
Merge branch 'master' into staging-next
Diffstat (limited to 'nixos/modules/hardware')
-rw-r--r-- | nixos/modules/hardware/openrazer.nix | 133 | ||||
-rw-r--r-- | nixos/modules/hardware/printers.nix | 135 |
2 files changed, 268 insertions, 0 deletions
diff --git a/nixos/modules/hardware/openrazer.nix b/nixos/modules/hardware/openrazer.nix new file mode 100644 index 000000000000..883db7f2f4f1 --- /dev/null +++ b/nixos/modules/hardware/openrazer.nix @@ -0,0 +1,133 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.hardware.openrazer; + kernelPackages = config.boot.kernelPackages; + + toPyBoolStr = b: if b then "True" else "False"; + + daemonExe = "${pkgs.openrazer-daemon}/bin/openrazer-daemon --config ${daemonConfFile}"; + + daemonConfFile = pkgs.writeTextFile { + name = "razer.conf"; + text = '' + [General] + verbose_logging = ${toPyBoolStr cfg.verboseLogging} + + [Startup] + sync_effects_enabled = ${toPyBoolStr cfg.syncEffectsEnabled} + devices_off_on_screensaver = ${toPyBoolStr cfg.devicesOffOnScreensaver} + mouse_battery_notifier = ${toPyBoolStr cfg.mouseBatteryNotifier} + + [Statistics] + key_statistics = ${toPyBoolStr cfg.keyStatistics} + ''; + }; + + dbusServiceFile = pkgs.writeTextFile rec { + name = "org.razer.service"; + destination = "/share/dbus-1/services/${name}"; + text = '' + [D-BUS Service] + Name=org.razer + Exec=${daemonExe} + SystemdService=openrazer-daemon.service + ''; + }; + + drivers = [ + "razerkbd" + "razermouse" + "razerfirefly" + "razerkraken" + "razermug" + "razercore" + ]; +in +{ + options = { + hardware.openrazer = { + enable = mkEnableOption "OpenRazer drivers and userspace daemon."; + + verboseLogging = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable verbose logging. Logs debug messages. + ''; + }; + + syncEffectsEnabled = mkOption { + type = types.bool; + default = true; + description = '' + Set the sync effects flag to true so any assignment of + effects will work across devices. + ''; + }; + + devicesOffOnScreensaver = mkOption { + type = types.bool; + default = true; + description = '' + Turn off the devices when the systems screensaver kicks in. + ''; + }; + + mouseBatteryNotifier = mkOption { + type = types.bool; + default = true; + description = '' + Mouse battery notifier. + ''; + }; + + keyStatistics = mkOption { + type = types.bool; + default = false; + description = '' + Collects number of keypresses per hour per key used to + generate a heatmap. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + boot.extraModulePackages = [ kernelPackages.openrazer ]; + boot.kernelModules = drivers; + + # Makes the man pages available so you can succesfully run + # > systemctl --user help openrazer-daemon + environment.systemPackages = [ pkgs.python3Packages.openrazer-daemon.man ]; + + services.udev.packages = [ kernelPackages.openrazer ]; + services.dbus.packages = [ dbusServiceFile ]; + + # A user must be a member of the plugdev group in order to start + # the openrazer-daemon. Therefore we make sure that the plugdev + # group exists. + users.groups.plugdev = {}; + + systemd.user.services.openrazer-daemon = { + description = "Daemon to manage razer devices in userspace"; + unitConfig.Documentation = "man:openrazer-daemon(8)"; + # Requires a graphical session so the daemon knows when the screensaver + # starts. See the 'devicesOffOnScreensaver' option. + wantedBy = [ "graphical-session.target" ]; + partOf = [ "graphical-session.target" ]; + serviceConfig = { + Type = "dbus"; + BusName = "org.razer"; + ExecStart = "${daemonExe} --foreground"; + Restart = "always"; + }; + }; + }; + + meta = { + maintainers = with lib.maintainers; [ roelvandijk ]; + }; +} diff --git a/nixos/modules/hardware/printers.nix b/nixos/modules/hardware/printers.nix new file mode 100644 index 000000000000..12ee5516d4ed --- /dev/null +++ b/nixos/modules/hardware/printers.nix @@ -0,0 +1,135 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.hardware.printers; + ppdOptionsString = options: optionalString (options != {}) + (concatStringsSep " " + (mapAttrsToList (name: value: "-o '${name}'='${value}'") options) + ); + ensurePrinter = p: '' + ${pkgs.cups}/bin/lpadmin -p '${p.name}' -E \ + ${optionalString (p.location != null) "-L '${p.location}'"} \ + ${optionalString (p.description != null) "-D '${p.description}'"} \ + -v '${p.deviceUri}' \ + -m '${p.model}' \ + ${ppdOptionsString p.ppdOptions} + ''; + ensureDefaultPrinter = name: '' + ${pkgs.cups}/bin/lpoptions -d '${name}' + ''; + + # "graph but not # or /" can't be implemented as regex alone due to missing lookahead support + noInvalidChars = str: all (c: c != "#" && c != "/") (stringToCharacters str); + printerName = (types.addCheck (types.strMatching "[[:graph:]]+") noInvalidChars) + // { description = "printable string without spaces, # and /"; }; + + +in { + options = { + hardware.printers = { + ensureDefaultPrinter = mkOption { + type = types.nullOr printerName; + default = null; + description = '' + Ensures the named printer is the default CUPS printer / printer queue. + ''; + }; + ensurePrinters = mkOption { + description = '' + Will regularly ensure that the given CUPS printers are configured as declared here. + If a printer's options are manually changed afterwards, they will be overwritten eventually. + This option will never delete any printer, even if removed from this list. + You can check existing printers with <command>lpstat -s</command> + and remove printers with <command>lpadmin -x <printer-name></command>. + Printers not listed here can still be manually configured. + ''; + default = []; + type = types.listOf (types.submodule { + options = { + name = mkOption { + type = printerName; + example = "BrotherHL_Workroom"; + description = '' + Name of the printer / printer queue. + May contain any printable characters except "/", "#", and space. + ''; + }; + location = mkOption { + type = types.nullOr types.str; + default = null; + example = "Workroom"; + description = '' + Optional human-readable location. + ''; + }; + description = mkOption { + type = types.nullOr types.str; + default = null; + example = "Brother HL-5140"; + description = '' + Optional human-readable description. + ''; + }; + deviceUri = mkOption { + type = types.str; + example = [ + "ipp://printserver.local/printers/BrotherHL_Workroom" + "usb://HP/DESKJET%20940C?serial=CN16E6C364BH" + ]; + description = '' + How to reach the printer. + <command>lpinfo -v</command> shows a list of supported device URIs and schemes. + ''; + }; + model = mkOption { + type = types.str; + example = literalExample '' + gutenprint.''${lib.version.majorMinor (lib.getVersion pkgs.cups)}://brother-hl-5140/expert + ''; + description = '' + Location of the ppd driver file for the printer. + <command>lpinfo -m</command> shows a list of supported models. + ''; + }; + ppdOptions = mkOption { + type = types.attrsOf types.str; + example = { + "PageSize" = "A4"; + "Duplex" = "DuplexNoTumble"; + }; + default = {}; + description = '' + Sets PPD options for the printer. + <command>lpoptions [-p printername] -l</command> shows suported PPD options for the given printer. + ''; + }; + }; + }); + }; + }; + }; + + config = mkIf (cfg.ensurePrinters != [] && config.services.printing.enable) { + systemd.services."ensure-printers" = let + cupsUnit = if config.services.printing.startWhenNeeded then "cups.socket" else "cups.service"; + in { + description = "Ensure NixOS-configured CUPS printers"; + wantedBy = [ "multi-user.target" ]; + requires = [ cupsUnit ]; + # in contrast to cups.socket, for cups.service, this is actually not enough, + # as the cups service reports its activation before clients can actually interact with it. + # Because of this, commands like `lpinfo -v` will report a bad file descriptor + # due to the missing UNIX socket without sufficient sleep time. + after = [ cupsUnit ]; + + serviceConfig = { + Type = "oneshot"; + }; + + # sleep 10 is required to wait until cups.service is actually initialized and has created its UNIX socket file + script = (optionalString (!config.services.printing.startWhenNeeded) "sleep 10\n") + + (concatMapStringsSep "\n" ensurePrinter cfg.ensurePrinters) + + optionalString (cfg.ensureDefaultPrinter != null) (ensureDefaultPrinter cfg.ensureDefaultPrinter); + }; + }; +} |