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