summary refs log blame commit diff
path: root/upstart-jobs/udev.nix
blob: 5d8e8269cea9fe7c5cfb2df99221ee72381c91b3 (plain) (tree)
1
2
3
4
5
6
7
                                                                                     
                    
                  
  


   






























                                                                                                                  


                                                  

                                    
                    
                                             
                       


                                                          




                                            
            


                               



                                 
 








                                                                     
  



                


















                                                                         

                                                                 



                                                                         
                                                                       













                                                                    
 
                                  
 
{ stdenv, writeText, substituteAll, cleanSource, udev, procps, firmwareDirs, modprobe
, extraUdevPkgs ? []
, sndMode ? "0600"
}:

let

  firmwareLoader = substituteAll {
    src = ./udev-firmware-loader.sh;
    path = "${stdenv.coreutils}/bin";
    isExecutable = true;
    inherit firmwareDirs;
  };
    
  nixRules = writeText "10-nix.rules" ''
  
    # Miscellaneous devices.
    KERNEL=="sonypi",               MODE="0666"
    KERNEL=="kvm",                  MODE="0666"
    KERNEL=="kqemu",		    NAME="%k", MODE="0666"

    # Create a symlink for the CD-ROM device.
    #KERNEL=="hd[a-z]", BUS=="ide", SYSFS{removable}=="1", SYSFS{device/media}=="cdrom", SYMLINK+="cdrom cdrom-%k"
    #KERNEL=="sr[0-9]", BUS=="scsi", SYMLINK+="cdrom cdrom-%k"

    # ALSA sound devices.
    KERNEL=="controlC[0-9]*",       NAME="snd/%k", MODE="${sndMode}"
    KERNEL=="hwC[D0-9]*",           NAME="snd/%k", MODE="${sndMode}"
    KERNEL=="pcmC[D0-9cp]*",        NAME="snd/%k", MODE="${sndMode}"
    KERNEL=="midiC[D0-9]*",         NAME="snd/%k", MODE="${sndMode}"
    KERNEL=="timer",                NAME="snd/%k", MODE="${sndMode}"
    KERNEL=="seq",                  NAME="snd/%k", MODE="${sndMode}"

    # Firmware loading.
    SUBSYSTEM=="firmware",          ACTION=="add", RUN+="${firmwareLoader}"
    
  '';
  
  # Perform substitutions in all udev rules files.
  udevRules = stdenv.mkDerivation {
    name = "udev-rules";
    #src = cleanSource ./udev-rules;
    buildCommand = ''
      ensureDir $out
      ln -s ${nixRules} $out/${nixRules.name}
      shopt -s nullglob
      cp ${udev}/etc/udev/rules.d/*.rules $out/
      substituteInPlace $out/80-drivers.rules \
        --replace /sbin/modprobe ${modprobe}/sbin/modprobe
      for i in ${toString extraUdevPkgs}; do
        for j in $i/etc/udev/rules.d/*; do
          ln -s $j $out/$(basename $j)
        done
      done
    ''; # */
  };

  # The udev configuration file
  conf = writeText "udev.conf" ''
    udev_rules="${udevRules}"
    #udev_log="debug"
  '';

  # Dummy file indicating whether we've run udevtrigger/udevsettle.
  # Since that *recreates* all device nodes with default permissions,
  # it's not nice to do that when a user is logged in (it messes up
  # the permissions set by pam_devperm).
  # !!! Actually, this makes the udev configuration less declarative;
  # changes may not take effect until the user reboots.  We should
  # find a better way to preserve the permissions of logged-in users.
  devicesCreated = "/var/run/devices-created";

in

{
  name = "udev";
  
  job = ''
    start on startup
    stop on shutdown

    env UDEV_CONFIG_FILE=${conf}

    start script
	echo "" > /proc/sys/kernel/hotplug

	# Get rid of possible old udev processes.
	${procps}/bin/pkill -u root "^udevd$" || true

	# Start udev.
	${udev}/sbin/udevd --daemon

	# Let udev create device nodes for all modules that have already
	# been loaded into the kernel (or for which support is built into
	# the kernel).
	if ! test -e ${devicesCreated}; then
	    ${udev}/sbin/udevadm trigger
	    ${udev}/sbin/udevadm settle # wait for udev to finish
	    touch ${devicesCreated}
	fi

	# Kill udev, let Upstart restart and monitor it.  (This is nasty,
	# but we have to run `udevadm trigger' first.  Maybe we can use
	# Upstart's `binary' keyword, but it isn't implemented yet.)
	if ! ${procps}/bin/pkill -u root "^udevd$"; then
	    echo "couldn't stop udevd"
	fi

	while ${procps}/bin/pgrep -u root "^udevd$"; do
	    sleep 1
	done

	initctl emit new-devices
    end script

    respawn ${udev}/sbin/udevd
  '';

  passthru = {inherit udevRules;};
}