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