Load automatically kernel module, and deal with parameters

Hello,

I’m trying to write a derivation for droidcam, that defines its own kernel module v4l2loopback-dc. The compilation goes well, however at the end I need to manually load the module using something like:

sudo insmod /nix/store/3r3p1y1nqmgkslm36g51kk30p0xyj5h6-v4l2loopback-dc-0/lib/modules/5.4.66/kernels/media/video/v4l2loopback-dc.ko width=320 height=240

but first it’s quite ugly, then it’s not great to hardcode the hash, and I’d like it to be loaded automatically. I tried to write boot.extraModulePackages = [ v4l2loopback-dc ] but it does not change anything.

Any idea how to automatically run insmod? Can I also configure it with some parameters automatically ?

Also, I need the snd-aloop module (I will use the packaged one here), how can I load it automatically ?

Thanks!

PS: For references, here are my derivations:

droidcam.nix:

{ stdenv, fetchFromGitHub, pkgconfig, libusbmuxd, libplist, speex, libav, alsaLib, gtk3, libappindicator-gtk3, libjpeg_turbo }:
# Thanks nix-locate ! (do not forget to nix-index first)
# And to get only most relevant packages: nix-locate 'yoursearch' --top-level
# https://github.com/aramg/droidcam/tree/v1.5/linux
# libavutil-dev --> seems to be present in ffmpeg and libav
# libswscale-dev --> in ffmpeg and libav
# libasound2-dev --> alsaLib?
# libspeex-dev --> ffmpeg and speex
# libusbmuxd-dev --> ok
# libplist-dev --> ok
# 
# gtk+-3.0               # Only needed for GUI client
# libappindicator3-dev   # Only needed for GUI client
# try gtk3-x11 maybe?

stdenv.mkDerivation rec {
  pname = "droidcam";
  version = "1.5";

  src = fetchFromGitHub {
    owner = "aramg";
    repo = "droidcam";
    rev = "v1.5";
    sha256 = "tIb7wqzAjSHoT9169NiUO+z6w5DrJVYvkQ3OxDqI1DA=";
  };

  sourceRoot = "source/linux";

  buildInputs = [ pkgconfig ];
  nativeBuildInputs = [ libappindicator-gtk3 speex libav gtk3 libjpeg_turbo libusbmuxd libplist alsaLib ];

  makeFlags = [ "JPEG_DIR=${libjpeg_turbo.out}" "JPEG_LIB=${libjpeg_turbo.out}/lib" ];
  postPatch = ''
    sed -i -e 's:(JPEG_LIB)/libturbojpeg.a:(JPEG_LIB)/libturbojpeg.so:' Makefile
  '';

  installPhase = ''
    mkdir -p $out/bin
    cp droidcam droidcam-cli $out/bin/
  '';

  meta = with stdenv.lib; {
    description = "DroidCam Linux client";
    homepage = https://github.com/aramg/droidcam;
  };
}

v4l2loopback.nix:

{ stdenv, fetchFromGitHub, kernel }:

stdenv.mkDerivation rec {
  pname = "v4l2loopback-dc";
  version = "0";

  src = fetchFromGitHub {
    owner = "aramg";
    repo = "droidcam";
    rev = "v1.5";
    sha256 = "tIb7wqzAjSHoT9169NiUO+z6w5DrJVYvkQ3OxDqI1DA=";
  };

  sourceRoot = "source/linux/v4l2loopback";

  KVER = "${kernel.modDirVersion}";
  KBUILD_DIR = "${kernel.dev}/lib/modules/${kernel.modDirVersion}/build";

  nativeBuildInputs = kernel.moduleBuildDependencies;

  makeFlags = [
    "KERNELRELEASE=${kernel.modDirVersion}"
    "KERNEL_DIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
  ] ;

  installPhase = ''
    mkdir -p $out/lib/modules/${KVER}/kernels/media/video
    cp v4l2loopback-dc.ko $out/lib/modules/${KVER}/kernels/media/video/
  '';

  meta = with stdenv.lib; {
    description = "DroidCam kernel module v4l2loopback-dc";
    homepage = https://github.com/aramg/droidcam;
  };
}

to import from configuration.nix:

{ config, pkgs, lib, ... }:
let v4l2loopback-dc = config.boot.kernelPackages.callPackage ./v4l2loopback-dc.nix { };
    droidcam = pkgs.callPackage ./droidcam.nix {};
in {
  boot.extraModulePackages = [ v4l2loopback-dc ];
  environment.systemPackages = [ droidcam ];
}
1 Like

Thanks to clever help, I clarified everything.

So basically, when you put a module inside boot.extraModulePackages, it is used to make the modules available to modprobe, but it will not load them automatically (modprobe will search for module names inside inside /run/current-system/kernel-modules/lib/modules/$KER_VER). So for example, we can load our module manually with:

sudo modprobe v4l2loopback-dc

or if the module has options:

sudo modprobe v4l2loopback-dc width=320 height=240

Now, if we want the module to autoload, we need to insert it inside boot.kernelModules:

boot.kernelModules = [ "v4l2loopback-dc" ];

if we want to autoload snd-aloop, we can just add it to the list:

boot.kernelModules = [ "v4l2loopback-dc" "snd-aloop" ];

We can also define default options by adding an entry in boot.extraModprobeConfig (the module must still be in kernelModules) in order to specify default options if necessary:

boot.extraModprobeConfig = ''
  options v4l2loopback-dc width=320 height=240
'';

Beware, the modules will only be loaded at reboot time, and the default options will only apply if you reload a module, for example using:

sudo modprobe -r v4l2loopback-dc
sudo modprobe v4l2loopback-dc

so you should manually load the module using:

sudo modprobe v4l2loopback-dc

or create a systemd daemon that loads the module for you (wireguard’s for example does modprobe wg at startup automatically).

Finally, some modules have parameters that can be changed automatically without reloading the module. See the parameters in:

ls /sys/module/zfs/parameters/ -al

for example to see some parameters that are writable. Note however that it’s up to the module to take these live-change of parameter into account.

5 Likes