1# Upower daemon.
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8
9 cfg = config.services.upower;
10
11in
12
13{
14
15 ###### interface
16
17 options = {
18
19 services.upower = {
20
21 enable = mkOption {
22 type = types.bool;
23 default = false;
24 description = ''
25 Whether to enable Upower, a DBus service that provides power
26 management support to applications.
27 '';
28 };
29
30 package = mkOption {
31 type = types.package;
32 default = pkgs.upower;
33 defaultText = "pkgs.upower";
34 example = lib.literalExample "pkgs.upower";
35 description = ''
36 Which upower package to use.
37 '';
38 };
39
40 enableWattsUpPro = mkOption {
41 type = types.bool;
42 default = false;
43 description = ''
44 Enable the Watts Up Pro device.
45
46 The Watts Up Pro contains a generic FTDI USB device without a specific
47 vendor and product ID. When we probe for WUP devices, we can cause
48 the user to get a perplexing "Device or resource busy" error when
49 attempting to use their non-WUP device.
50
51 The generic FTDI device is known to also be used on:
52
53 <itemizedlist>
54 <listitem><para>Sparkfun FT232 breakout board</para></listitem>
55 <listitem><para>Parallax Propeller</para></listitem>
56 </itemizedlist>
57 '';
58 };
59
60 noPollBatteries = mkOption {
61 type = types.bool;
62 default = false;
63 description = ''
64 Don't poll the kernel for battery level changes.
65
66 Some hardware will send us battery level changes through
67 events, rather than us having to poll for it. This option
68 allows disabling polling for hardware that sends out events.
69 '';
70 };
71
72 ignoreLid = mkOption {
73 type = types.bool;
74 default = false;
75 description = ''
76 Do we ignore the lid state
77
78 Some laptops are broken. The lid state is either inverted, or stuck
79 on or off. We can't do much to fix these problems, but this is a way
80 for users to make the laptop panel vanish, a state that might be used
81 by a couple of user-space daemons. On Linux systems, see also
82 logind.conf(5).
83 '';
84 };
85
86 usePercentageForPolicy = mkOption {
87 type = types.bool;
88 default = true;
89 description = ''
90 Policy for warnings and action based on battery levels
91
92 Whether battery percentage based policy should be used. The default
93 is to use the percentage, which
94 should work around broken firmwares. It is also more reliable than
95 the time left (frantically saving all your files is going to use more
96 battery than letting it rest for example).
97 '';
98 };
99
100 percentageLow = mkOption {
101 type = types.ints.unsigned;
102 default = 10;
103 description = ''
104 When <literal>usePercentageForPolicy</literal> is
105 <literal>true</literal>, the levels at which UPower will consider the
106 battery low.
107
108 This will also be used for batteries which don't have time information
109 such as that of peripherals.
110
111 If any value (of <literal>percentageLow</literal>,
112 <literal>percentageCritical</literal> and
113 <literal>percentageAction</literal>) is invalid, or not in descending
114 order, the defaults will be used.
115 '';
116 };
117
118 percentageCritical = mkOption {
119 type = types.ints.unsigned;
120 default = 3;
121 description = ''
122 When <literal>usePercentageForPolicy</literal> is
123 <literal>true</literal>, the levels at which UPower will consider the
124 battery critical.
125
126 This will also be used for batteries which don't have time information
127 such as that of peripherals.
128
129 If any value (of <literal>percentageLow</literal>,
130 <literal>percentageCritical</literal> and
131 <literal>percentageAction</literal>) is invalid, or not in descending
132 order, the defaults will be used.
133 '';
134 };
135
136 percentageAction = mkOption {
137 type = types.ints.unsigned;
138 default = 2;
139 description = ''
140 When <literal>usePercentageForPolicy</literal> is
141 <literal>true</literal>, the levels at which UPower will take action
142 for the critical battery level.
143
144 This will also be used for batteries which don't have time information
145 such as that of peripherals.
146
147 If any value (of <literal>percentageLow</literal>,
148 <literal>percentageCritical</literal> and
149 <literal>percentageAction</literal>) is invalid, or not in descending
150 order, the defaults will be used.
151 '';
152 };
153
154 timeLow = mkOption {
155 type = types.ints.unsigned;
156 default = 1200;
157 description = ''
158 When <literal>usePercentageForPolicy</literal> is
159 <literal>false</literal>, the time remaining at which UPower will
160 consider the battery low.
161
162 If any value (of <literal>timeLow</literal>,
163 <literal>timeCritical</literal> and <literal>timeAction</literal>) is
164 invalid, or not in descending order, the defaults will be used.
165 '';
166 };
167
168 timeCritical = mkOption {
169 type = types.ints.unsigned;
170 default = 300;
171 description = ''
172 When <literal>usePercentageForPolicy</literal> is
173 <literal>false</literal>, the time remaining at which UPower will
174 consider the battery critical.
175
176 If any value (of <literal>timeLow</literal>,
177 <literal>timeCritical</literal> and <literal>timeAction</literal>) is
178 invalid, or not in descending order, the defaults will be used.
179 '';
180 };
181
182 timeAction = mkOption {
183 type = types.ints.unsigned;
184 default = 120;
185 description = ''
186 When <literal>usePercentageForPolicy</literal> is
187 <literal>false</literal>, the time remaining at which UPower will
188 take action for the critical battery level.
189
190 If any value (of <literal>timeLow</literal>,
191 <literal>timeCritical</literal> and <literal>timeAction</literal>) is
192 invalid, or not in descending order, the defaults will be used.
193 '';
194 };
195
196 criticalPowerAction = mkOption {
197 type = types.enum [ "PowerOff" "Hibernate" "HybridSleep" ];
198 default = "HybridSleep";
199 description = ''
200 The action to take when <literal>timeAction</literal> or
201 <literal>percentageAction</literal> has been reached for the batteries
202 (UPS or laptop batteries) supplying the computer
203 '';
204 };
205
206 };
207
208 };
209
210
211 ###### implementation
212
213 config = mkIf cfg.enable {
214
215 environment.systemPackages = [ cfg.package ];
216
217 services.dbus.packages = [ cfg.package ];
218
219 services.udev.packages = [ cfg.package ];
220
221 systemd.packages = [ cfg.package ];
222
223 environment.etc."UPower/UPower.conf".text = generators.toINI {} {
224 UPower = {
225 EnableWattsUpPro = cfg.enableWattsUpPro;
226 NoPollBatteries = cfg.noPollBatteries;
227 IgnoreLid = cfg.ignoreLid;
228 UsePercentageForPolicy = cfg.usePercentageForPolicy;
229 PercentageLow = cfg.percentageLow;
230 PercentageCritical = cfg.percentageCritical;
231 PercentageAction = cfg.percentageAction;
232 TimeLow = cfg.timeLow;
233 TimeCritical = cfg.timeCritical;
234 TimeAction = cfg.timeAction;
235 CriticalPowerAction = cfg.criticalPowerAction;
236 };
237 };
238 };
239
240}