1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.acpid;
7
8 canonicalHandlers = {
9 powerEvent = {
10 event = "button/power.*";
11 action = cfg.powerEventCommands;
12 };
13
14 lidEvent = {
15 event = "button/lid.*";
16 action = cfg.lidEventCommands;
17 };
18
19 acEvent = {
20 event = "ac_adapter.*";
21 action = cfg.acEventCommands;
22 };
23 };
24
25 acpiConfDir = pkgs.runCommand "acpi-events" { preferLocalBuild = true; }
26 ''
27 mkdir -p $out
28 ${
29 # Generate a configuration file for each event. (You can't have
30 # multiple events in one config file...)
31 let f = name: handler:
32 ''
33 fn=$out/${name}
34 echo "event=${handler.event}" > $fn
35 echo "action=${pkgs.writeShellScriptBin "${name}.sh" handler.action }/bin/${name}.sh '%e'" >> $fn
36 '';
37 in concatStringsSep "\n" (mapAttrsToList f (canonicalHandlers // cfg.handlers))
38 }
39 '';
40
41in
42
43{
44
45 ###### interface
46
47 options = {
48
49 services.acpid = {
50
51 enable = mkEnableOption (lib.mdDoc "the ACPI daemon");
52
53 logEvents = mkOption {
54 type = types.bool;
55 default = false;
56 description = lib.mdDoc "Log all event activity.";
57 };
58
59 handlers = mkOption {
60 type = types.attrsOf (types.submodule {
61 options = {
62 event = mkOption {
63 type = types.str;
64 example = literalExpression ''"button/power.*" "button/lid.*" "ac_adapter.*" "button/mute.*" "button/volumedown.*" "cd/play.*" "cd/next.*"'';
65 description = lib.mdDoc "Event type.";
66 };
67
68 action = mkOption {
69 type = types.lines;
70 description = lib.mdDoc "Shell commands to execute when the event is triggered.";
71 };
72 };
73 });
74
75 description = lib.mdDoc ''
76 Event handlers.
77
78 ::: {.note}
79 Handler can be a single command.
80 :::
81 '';
82 default = {};
83 example = {
84 ac-power = {
85 event = "ac_adapter/*";
86 action = ''
87 vals=($1) # space separated string to array of multiple values
88 case ''${vals[3]} in
89 00000000)
90 echo unplugged >> /tmp/acpi.log
91 ;;
92 00000001)
93 echo plugged in >> /tmp/acpi.log
94 ;;
95 *)
96 echo unknown >> /tmp/acpi.log
97 ;;
98 esac
99 '';
100 };
101 };
102 };
103
104 powerEventCommands = mkOption {
105 type = types.lines;
106 default = "";
107 description = lib.mdDoc "Shell commands to execute on a button/power.* event.";
108 };
109
110 lidEventCommands = mkOption {
111 type = types.lines;
112 default = "";
113 description = lib.mdDoc "Shell commands to execute on a button/lid.* event.";
114 };
115
116 acEventCommands = mkOption {
117 type = types.lines;
118 default = "";
119 description = lib.mdDoc "Shell commands to execute on an ac_adapter.* event.";
120 };
121
122 };
123
124 };
125
126
127 ###### implementation
128
129 config = mkIf cfg.enable {
130
131 systemd.services.acpid = {
132 description = "ACPI Daemon";
133 documentation = [ "man:acpid(8)" ];
134
135 wantedBy = [ "multi-user.target" ];
136
137 serviceConfig = {
138 ExecStart = escapeShellArgs
139 ([ "${pkgs.acpid}/bin/acpid"
140 "--foreground"
141 "--netlink"
142 "--confdir" "${acpiConfDir}"
143 ] ++ optional cfg.logEvents "--logevents"
144 );
145 };
146 unitConfig = {
147 ConditionVirtualization = "!systemd-nspawn";
148 ConditionPathExists = [ "/proc/acpi" ];
149 };
150
151 };
152
153 };
154
155}