summary refs log tree commit diff
path: root/nixos/modules/services/hardware
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2016-02-14 08:33:51 +0100
committerVladimír Čunát <vcunat@gmail.com>2016-02-14 08:33:51 +0100
commitd039c879845ddcde6108203781e4b001c409e2c2 (patch)
tree1f9e2a99d95c8866ddbef81b4bfa6a49ce979451 /nixos/modules/services/hardware
parent34922a3951a0ada7af4fe808250abaf5feb4e28e (diff)
parent6a036d9fca013265b4109ffcaf6df62efa010fa3 (diff)
downloadnixlib-d039c879845ddcde6108203781e4b001c409e2c2.tar
nixlib-d039c879845ddcde6108203781e4b001c409e2c2.tar.gz
nixlib-d039c879845ddcde6108203781e4b001c409e2c2.tar.bz2
nixlib-d039c879845ddcde6108203781e4b001c409e2c2.tar.lz
nixlib-d039c879845ddcde6108203781e4b001c409e2c2.tar.xz
nixlib-d039c879845ddcde6108203781e4b001c409e2c2.tar.zst
nixlib-d039c879845ddcde6108203781e4b001c409e2c2.zip
Merge branch 'master' into closure-size
Diffstat (limited to 'nixos/modules/services/hardware')
-rw-r--r--nixos/modules/services/hardware/acpid.nix174
-rw-r--r--nixos/modules/services/hardware/bluetooth.nix60
-rw-r--r--nixos/modules/services/hardware/udev.nix87
3 files changed, 161 insertions, 160 deletions
diff --git a/nixos/modules/services/hardware/acpid.nix b/nixos/modules/services/hardware/acpid.nix
index 48b2b6be09ed..bb17c8859d84 100644
--- a/nixos/modules/services/hardware/acpid.nix
+++ b/nixos/modules/services/hardware/acpid.nix
@@ -4,111 +4,38 @@ with lib;
 
 let
 
-  acpiConfDir = pkgs.runCommand "acpi-events" {}
-    ''
-      mkdir -p $out
-      ${
-        # Generate a configuration file for each event. (You can't have
-        # multiple events in one config file...)
-        let f = event:
-          ''
-            fn=$out/${event.name}
-            echo "event=${event.event}" > $fn
-            echo "action=${pkgs.writeScript "${event.name}.sh" event.action}" >> $fn
-          '';
-        in lib.concatMapStrings f events
-      }
-    '';
-
-  events = [powerEvent lidEvent acEvent muteEvent volumeDownEvent volumeUpEvent cdPlayEvent cdNextEvent cdPrevEvent];
-
-  # Called when the power button is pressed.
-  powerEvent =
-    { name = "power-button";
+  canonicalHandlers = {
+    powerEvent = {
       event = "button/power.*";
-      action =
-        ''
-          #! ${pkgs.bash}/bin/sh
-          ${config.services.acpid.powerEventCommands}
-        '';
+      action = config.services.acpid.powerEventCommands;
     };
 
-  # Called when the laptop lid is opened/closed.
-  lidEvent =
-    { name = "lid";
+    lidEvent = {
       event = "button/lid.*";
-      action =
-        ''
-          #! ${pkgs.bash}/bin/sh
-          ${config.services.acpid.lidEventCommands}
-        '';
+      action = config.services.acpid.lidEventCommands;
     };
 
-  # Called when the AC power is connected or disconnected.
-  acEvent =
-    { name = "ac-power";
+    acEvent = {
       event = "ac_adapter.*";
-      action =
-        ''
-          #! ${pkgs.bash}/bin/sh
-          ${config.services.acpid.acEventCommands}
-        '';
+      action = config.services.acpid.acEventCommands;
     };
-
-  muteEvent = {
-    name = "mute";
-    event = "button/mute.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.muteCommands}
-    '';
-  };
-
-  volumeDownEvent = {
-    name = "volume-down";
-    event = "button/volumedown.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.volumeDownEventCommands}
-    '';
   };
 
-  volumeUpEvent = {
-    name = "volume-up";
-    event = "button/volumeup.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.volumeUpEventCommands}
-    '';
-  };
-
-  cdPlayEvent = {
-    name = "cd-play";
-    event = "cd/play.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.cdPlayEventCommands}
-    '';
-  };
-
-  cdNextEvent = {
-    name = "cd-next";
-    event = "cd/next.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.cdNextEventCommands}
-    '';
-  };
-
-  cdPrevEvent = {
-    name = "cd-prev";
-    event = "cd/prev.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.cdPrevEventCommands}
+  acpiConfDir = pkgs.runCommand "acpi-events" {}
+    ''
+      mkdir -p $out
+      ${
+        # Generate a configuration file for each event. (You can't have
+        # multiple events in one config file...)
+        let f = name: handler:
+          ''
+            fn=$out/${name}
+            echo "event=${handler.event}" > $fn
+            echo "action=${pkgs.writeScript "${name}.sh" (concatStringsSep "\n" [ "#! ${pkgs.bash}/bin/sh" handler.action ])}" >> $fn
+          '';
+        in concatStringsSep "\n" (mapAttrsToList f (canonicalHandlers // config.services.acpid.handlers))
+      }
     '';
-  };
-
 
 in
 
@@ -126,58 +53,45 @@ in
         description = "Whether to enable the ACPI daemon.";
       };
 
-      powerEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on a button/power.* event.";
-      };
+      handlers = mkOption {
+        type = types.attrsOf (types.submodule {
+          options = {
+            event = mkOption {
+              type = types.str;
+              example = [ "button/power.*" "button/lid.*" "ac_adapter.*" "button/mute.*" "button/volumedown.*" "cd/play.*" "cd/next.*" ];
+              description = "Event type.";
+            };
 
-      lidEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on a button/lid.* event.";
-      };
+            action = mkOption {
+              type = types.lines;
+              description = "Shell commands to execute when the event is triggered.";
+            };
+          };
+        });
 
-      acEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on an ac_adapter.* event.";
-      };
-
-      muteCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on an button/mute.* event.";
-      };
+        description = "Event handlers.";
+        default = {};
+        example = { mute = { event = "button/mute.*"; action = "amixer set Master toggle"; }; };
 
-      volumeDownEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on an button/volumedown.* event.";
-      };
 
-      volumeUpEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on an button/volumeup.* event.";
       };
 
-      cdPlayEventCommands = mkOption {
+      powerEventCommands = mkOption {
         type = types.lines;
         default = "";
-        description = "Shell commands to execute on an cd/play.* event.";
+        description = "Shell commands to execute on a button/power.* event.";
       };
 
-      cdNextEventCommands = mkOption {
+      lidEventCommands = mkOption {
         type = types.lines;
         default = "";
-        description = "Shell commands to execute on an cd/next.* event.";
+        description = "Shell commands to execute on a button/lid.* event.";
       };
 
-      cdPrevEventCommands = mkOption {
+      acEventCommands = mkOption {
         type = types.lines;
         default = "";
-        description = "Shell commands to execute on an cd/prev.* event.";
+        description = "Shell commands to execute on an ac_adapter.* event.";
       };
 
     };
diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix
index 68d0406e63bd..fc95c4910bf7 100644
--- a/nixos/modules/services/hardware/bluetooth.nix
+++ b/nixos/modules/services/hardware/bluetooth.nix
@@ -1,6 +1,43 @@
 { config, lib, pkgs, ... }:
 
 with lib;
+let
+    bluez-bluetooth = if config.services.xserver.desktopManager.kde4.enable then pkgs.bluez else pkgs.bluez5;
+
+    configBluez = {
+        description = "Bluetooth Service";
+        serviceConfig = {
+          Type = "dbus";
+          BusName = "org.bluez";
+          ExecStart = "${bluez-bluetooth}/sbin/bluetoothd -n";
+        };
+        wantedBy = [ "bluetooth.target" ];
+    };
+
+    configBluez5 =  {
+        description = "Bluetooth Service";
+        serviceConfig = {
+          Type = "dbus";
+          BusName = "org.bluez";
+          ExecStart = "${bluez-bluetooth}/sbin/bluetoothd -n";
+          NotifyAccess="main";
+          CapabilityBoundingSet="CAP_NET_ADMIN CAP_NET_BIND_SERVICE";
+          LimitNPROC=1;
+        };
+        wantedBy = [ "bluetooth.target" ];
+    };
+
+    obexConfig = {
+        description = "Bluetooth OBEX service";
+        serviceConfig = {
+          Type = "dbus";
+          BusName = "org.bluez.obex";
+          ExecStart = "${bluez-bluetooth}/sbin/obexd";
+        };
+    };
+
+    bluezConfig = if config.services.xserver.desktopManager.kde4.enable then configBluez else configBluez5;
+in
 
 {
 
@@ -16,26 +53,15 @@ with lib;
 
   };
 
-
   ###### implementation
-
+  
   config = mkIf config.hardware.bluetooth.enable {
 
-    environment.systemPackages = [ pkgs.bluez pkgs.openobex pkgs.obexftp ];
-
-    services.udev.packages = [ pkgs.bluez ];
-
-    services.dbus.packages = [ pkgs.bluez ];
-
-    systemd.services."dbus-org.bluez" = {
-      description = "Bluetooth Service";
-      serviceConfig = {
-        Type = "dbus";
-        BusName = "org.bluez";
-        ExecStart = "${pkgs.bluez}/sbin/bluetoothd -n";
-      };
-      wantedBy = [ "bluetooth.target" ];
-    };
+    environment.systemPackages = [ bluez-bluetooth pkgs.openobex pkgs.obexftp ];
+    services.udev.packages = [ bluez-bluetooth ];
+    services.dbus.packages = [ bluez-bluetooth ];
+    systemd.services."dbus-org.bluez" = bluezConfig;
+    systemd.services."dbus-org.bluez.obex" = obexConfig;
 
   };
 
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index 107e1012b88d..369a50bd6a85 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -16,6 +16,12 @@ let
     destination = "/etc/udev/rules.d/10-local.rules";
   };
 
+  extraHwdbFile = pkgs.writeTextFile {
+    name = "extra-hwdb-file";
+    text = cfg.extraHwdb;
+    destination = "/etc/udev/hwdb.d/10-local.hwdb";
+  };
+
   nixosRules = ''
     # Miscellaneous devices.
     KERNEL=="kvm",                  MODE="0666"
@@ -55,7 +61,9 @@ let
           --replace \"/sbin/modprobe \"${config.system.sbin.modprobe}/sbin/modprobe \
           --replace \"/sbin/mdadm \"${pkgs.mdadm}/sbin/mdadm \
           --replace \"/sbin/blkid \"${pkgs.utillinux}/sbin/blkid \
-          --replace \"/bin/mount \"${pkgs.utillinux}/bin/mount
+          --replace \"/bin/mount \"${pkgs.utillinux}/bin/mount \
+          --replace /usr/bin/readlink ${pkgs.coreutils}/bin/readlink \
+          --replace /usr/bin/basename ${pkgs.coreutils}/bin/basename
       done
 
       echo -n "Checking that all programs called by relative paths in udev rules exist in ${udev}/lib/udev... "
@@ -86,10 +94,30 @@ let
       done
       echo "OK"
 
-      echo "Consider fixing the following udev rules:"
-      for i in ${toString cfg.packages}; do
-        grep -l '\(RUN+\|IMPORT{program}\)="\(/usr\)\?/s\?bin' $i/*/udev/rules.d/* || true
-      done
+      filesToFixup="$(for i in "$out"/*; do
+        grep -l '\B\(/usr\)\?/s\?bin' "$i" || :
+      done)"
+
+      if [ -n "$filesToFixup" ]; then
+        echo "Consider fixing the following udev rules:"
+        echo "$filesToFixup" | while read localFile; do
+          remoteFile="origin unknown"
+          for i in ${toString cfg.packages}; do
+            for j in "$i"/*/udev/rules.d/*; do
+              [ -e "$out/$(basename "$j")" ] || continue
+              [ "$(basename "$j")" = "$(basename "$localFile")" ] || continue
+              remoteFile="originally from $j"
+              break 2
+            done
+          done
+          refs="$(
+            grep -o '\B\(/usr\)\?/s\?bin/[^ "]\+' "$localFile" \
+              | sed -e ':r;N;''${s/\n/ and /;br};s/\n/, /g;br'
+          )"
+          echo "$localFile ($remoteFile) contains references to $refs."
+        done
+        exit 1
+      fi
 
       ${optionalString config.networking.usePredictableInterfaceNames ''
         cp ${./80-net-setup-link.rules} $out/80-net-setup-link.rules
@@ -104,6 +132,27 @@ let
     ''; # */
   };
 
+  hwdbBin = stdenv.mkDerivation {
+    name = "hwdb.bin";
+
+    preferLocalBuild = true;
+    allowSubstitutes = false;
+
+    buildCommand = ''
+      mkdir -p etc/udev/hwdb.d
+      for i in ${toString ([udev] ++ cfg.packages)}; do
+        echo "Adding hwdb files for package $i"
+        for j in $i/{etc,lib}/udev/hwdb.d/*; do
+          ln -s $j etc/udev/hwdb.d/$(basename $j)
+        done
+      done
+
+      echo "Generating hwdb database..."
+      ${udev}/bin/udevadm hwdb --update --root=$(pwd)
+      mv etc/udev/hwdb.bin $out
+    '';
+  };
+
   # Udev has a 512-character limit for ENV{PATH}, so create a symlink
   # tree to work around this.
   udevPath = pkgs.buildEnv {
@@ -168,6 +217,21 @@ in
         '';
       };
 
+      extraHwdb = mkOption {
+        default = "";
+        example = ''
+          evdev:input:b0003v05AFp8277*
+            KEYBOARD_KEY_70039=leftalt
+            KEYBOARD_KEY_700e2=leftctrl
+        '';
+        type = types.lines;
+        description = ''
+          Additional <command>hwdb</command> files. They'll be written
+          into file <filename>10-local.hwdb</filename>. Thus they are
+          read before all other files.
+        '';
+      };
+
     };
 
     hardware.firmware = mkOption {
@@ -216,7 +280,7 @@ in
 
     services.udev.extraRules = nixosRules;
 
-    services.udev.packages = [ extraUdevRules ];
+    services.udev.packages = [ extraUdevRules extraHwdbFile ];
 
     services.udev.path = [ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.utillinux udev ];
 
@@ -224,6 +288,9 @@ in
       [ { source = udevRules;
           target = "udev/rules.d";
         }
+        { source = hwdbBin;
+          target = "udev/hwdb.bin";
+        }
       ];
 
     system.requiredKernelConfig = with config.lib.kernelConfig; [
@@ -241,13 +308,6 @@ in
           echo "" > /proc/sys/kernel/hotplug
         fi
 
-        # Regenerate the hardware database /var/lib/udev/hwdb.bin
-        # whenever systemd changes.
-        if [ ! -e /var/lib/udev/prev-systemd -o "$(readlink /var/lib/udev/prev-systemd)" != ${config.systemd.package} ]; then
-          echo "regenerating udev hardware database..."
-          ${config.systemd.package}/bin/udevadm hwdb --update && ln -sfn ${config.systemd.package} /var/lib/udev/prev-systemd
-        fi
-
         # Allow the kernel to find our firmware.
         if [ -e /sys/module/firmware_class/parameters/path ]; then
           echo -n "${config.hardware.firmware}/lib/firmware" > /sys/module/firmware_class/parameters/path
@@ -256,6 +316,7 @@ in
 
     systemd.services.systemd-udevd =
       { environment.MODULE_DIR = "/run/booted-system/kernel-modules/lib/modules";
+        restartTriggers = cfg.packages;
       };
 
   };