at 25.11-pre 2.9 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.pcscd; 9 cfgFile = pkgs.writeText "reader.conf" ( 10 builtins.concatStringsSep "\n\n" config.services.pcscd.readerConfigs 11 ); 12 13 package = if config.security.polkit.enable then pkgs.pcscliteWithPolkit else pkgs.pcsclite; 14 15 pluginEnv = pkgs.buildEnv { 16 name = "pcscd-plugins"; 17 paths = map (p: "${p}/pcsc/drivers") config.services.pcscd.plugins; 18 }; 19 20in 21{ 22 imports = [ 23 (lib.mkChangedOptionModule 24 [ "services" "pcscd" "readerConfig" ] 25 [ "services" "pcscd" "readerConfigs" ] 26 ( 27 config: 28 let 29 readerConfig = lib.getAttrFromPath [ "services" "pcscd" "readerConfig" ] config; 30 in 31 [ readerConfig ] 32 ) 33 ) 34 ]; 35 36 options.services.pcscd = { 37 enable = lib.mkEnableOption "PCSC-Lite daemon, to access smart cards using SCard API (PC/SC)"; 38 39 plugins = lib.mkOption { 40 type = lib.types.listOf lib.types.package; 41 defaultText = lib.literalExpression "[ pkgs.ccid ]"; 42 example = lib.literalExpression "[ pkgs.pcsc-cyberjack ]"; 43 description = "Plugin packages to be used for PCSC-Lite."; 44 }; 45 46 readerConfigs = lib.mkOption { 47 type = lib.types.listOf lib.types.lines; 48 default = [ ]; 49 example = [ 50 '' 51 FRIENDLYNAME "Some serial reader" 52 DEVICENAME /dev/ttyS0 53 LIBPATH /path/to/serial_reader.so 54 CHANNELID 1 55 '' 56 ]; 57 description = '' 58 Configuration for devices that aren't hotpluggable. 59 60 See {manpage}`reader.conf(5)` for valid options. 61 ''; 62 }; 63 64 extraArgs = lib.mkOption { 65 type = lib.types.listOf lib.types.str; 66 default = [ ]; 67 description = "Extra command line arguments to be passed to the PCSC daemon."; 68 }; 69 }; 70 71 config = lib.mkIf config.services.pcscd.enable { 72 environment.etc."reader.conf".source = cfgFile; 73 74 environment.systemPackages = [ package ]; 75 systemd.packages = [ package ]; 76 77 services.pcscd.plugins = [ pkgs.ccid ]; 78 79 systemd.sockets.pcscd.wantedBy = [ "sockets.target" ]; 80 81 systemd.services.pcscd = { 82 environment.PCSCLITE_HP_DROPDIR = pluginEnv; 83 84 # If the cfgFile is empty and not specified (in which case the default 85 # /etc/reader.conf is assumed), pcscd will happily start going through the 86 # entire confdir (/etc in our case) looking for a config file and try to 87 # parse everything it finds. Doesn't take a lot of imagination to see how 88 # well that works. It really shouldn't do that to begin with, but to work 89 # around it, we force the path to the cfgFile. 90 # 91 # https://github.com/NixOS/nixpkgs/issues/121088 92 serviceConfig.ExecStart = [ 93 "" 94 "${lib.getExe package} -f -x -c ${cfgFile} ${lib.escapeShellArgs cfg.extraArgs}" 95 ]; 96 }; 97 }; 98}