1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.hardware.logitech;
9
10 vendor = "046d";
11
12 daemon = "g15daemon";
13
14in
15{
16 imports = [
17 (lib.mkRenamedOptionModule
18 [ "hardware" "logitech" "enable" ]
19 [ "hardware" "logitech" "wireless" "enable" ]
20 )
21 (lib.mkRenamedOptionModule
22 [ "hardware" "logitech" "enableGraphical" ]
23 [ "hardware" "logitech" "wireless" "enableGraphical" ]
24 )
25 ];
26
27 options.hardware.logitech = {
28
29 lcd = {
30 enable = lib.mkEnableOption "support for Logitech LCD Devices";
31
32 startWhenNeeded = lib.mkOption {
33 type = lib.types.bool;
34 default = true;
35 description = ''
36 Only run the service when an actual supported device is plugged.
37 '';
38 };
39
40 devices = lib.mkOption {
41 type = lib.types.listOf lib.types.str;
42 default = [
43 "0a07"
44 "c222"
45 "c225"
46 "c227"
47 "c251"
48 ];
49 description = ''
50 List of USB device ids supported by g15daemon.
51
52 You most likely do not need to change this.
53 '';
54 };
55 };
56
57 wireless = {
58 enable = lib.mkEnableOption "support for Logitech Wireless Devices";
59
60 enableGraphical = lib.mkOption {
61 type = lib.types.bool;
62 default = false;
63 description = "Enable graphical support applications.";
64 };
65 };
66 };
67
68 config = lib.mkIf (cfg.wireless.enable || cfg.lcd.enable) {
69 environment.systemPackages =
70 [ ]
71 ++ lib.optional cfg.wireless.enable pkgs.ltunify
72 ++ lib.optional cfg.wireless.enableGraphical pkgs.solaar;
73
74 services.udev = {
75 # ltunifi and solaar both provide udev rules but the most up-to-date have been split
76 # out into a dedicated derivation
77
78 packages =
79 [ ]
80 ++ lib.optional cfg.wireless.enable pkgs.logitech-udev-rules
81 ++ lib.optional cfg.lcd.enable pkgs.g15daemon;
82
83 extraRules =
84 ''
85 # nixos: hardware.logitech.lcd
86 ''
87 + lib.concatMapStringsSep "\n" (
88 dev:
89 ''ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="${vendor}", ATTRS{idProduct}=="${dev}", TAG+="systemd", ENV{SYSTEMD_WANTS}+="${daemon}.service"''
90 ) cfg.lcd.devices;
91 };
92
93 systemd.services."${daemon}" = lib.mkIf cfg.lcd.enable {
94 description = "Logitech LCD Support Daemon";
95 documentation = [ "man:g15daemon(1)" ];
96 wantedBy = lib.mkIf (!cfg.lcd.startWhenNeeded) "multi-user.target";
97
98 serviceConfig = {
99 Type = "forking";
100 ExecStart = "${pkgs.g15daemon}/bin/g15daemon";
101 # we patch it to write to /run/g15daemon/g15daemon.pid instead of
102 # /run/g15daemon.pid so systemd will do the cleanup for us.
103 PIDFile = "/run/${daemon}/g15daemon.pid";
104 PrivateTmp = true;
105 PrivateNetwork = true;
106 ProtectHome = "tmpfs";
107 ProtectSystem = "full"; # strict doesn't work
108 RuntimeDirectory = daemon;
109 Restart = "on-failure";
110 };
111 };
112 };
113}