summary refs log tree commit diff
path: root/nixos/modules/services/hardware/upower.nix
blob: 81bf497c993db2ef7722712f47a33c7d68411c35 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# Upower daemon.

{ config, lib, pkgs, ... }:

with lib;

let

  cfg = config.services.upower;

in

{

  ###### interface

  options = {

    services.upower = {

      enable = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Whether to enable Upower, a DBus service that provides power
          management support to applications.
        '';
      };

      package = mkOption {
        type = types.package;
        default = pkgs.upower;
        defaultText = literalExpression "pkgs.upower";
        description = ''
          Which upower package to use.
        '';
      };

      enableWattsUpPro = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Enable the Watts Up Pro device.

          The Watts Up Pro contains a generic FTDI USB device without a specific
          vendor and product ID. When we probe for WUP devices, we can cause
          the user to get a perplexing "Device or resource busy" error when
          attempting to use their non-WUP device.

          The generic FTDI device is known to also be used on:

          <itemizedlist>
            <listitem><para>Sparkfun FT232 breakout board</para></listitem>
            <listitem><para>Parallax Propeller</para></listitem>
          </itemizedlist>
        '';
      };

      noPollBatteries = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Don't poll the kernel for battery level changes.

          Some hardware will send us battery level changes through
          events, rather than us having to poll for it. This option
          allows disabling polling for hardware that sends out events.
        '';
      };

      ignoreLid = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Do we ignore the lid state

          Some laptops are broken. The lid state is either inverted, or stuck
          on or off. We can't do much to fix these problems, but this is a way
          for users to make the laptop panel vanish, a state that might be used
          by a couple of user-space daemons. On Linux systems, see also
          logind.conf(5).
        '';
      };

      usePercentageForPolicy = mkOption {
        type = types.bool;
        default = true;
        description = ''
          Policy for warnings and action based on battery levels

          Whether battery percentage based policy should be used. The default
          is to use the percentage, which
          should work around broken firmwares. It is also more reliable than
          the time left (frantically saving all your files is going to use more
          battery than letting it rest for example).
        '';
      };

      percentageLow = mkOption {
        type = types.ints.unsigned;
        default = 10;
        description = ''
          When <literal>usePercentageForPolicy</literal> is
          <literal>true</literal>, the levels at which UPower will consider the
          battery low.

          This will also be used for batteries which don't have time information
          such as that of peripherals.

          If any value (of <literal>percentageLow</literal>,
          <literal>percentageCritical</literal> and
          <literal>percentageAction</literal>) is invalid, or not in descending
          order, the defaults will be used.
        '';
      };

      percentageCritical = mkOption {
        type = types.ints.unsigned;
        default = 3;
        description = ''
          When <literal>usePercentageForPolicy</literal> is
          <literal>true</literal>, the levels at which UPower will consider the
          battery critical.

          This will also be used for batteries which don't have time information
          such as that of peripherals.

          If any value (of <literal>percentageLow</literal>,
          <literal>percentageCritical</literal> and
          <literal>percentageAction</literal>) is invalid, or not in descending
          order, the defaults will be used.
        '';
      };

      percentageAction = mkOption {
        type = types.ints.unsigned;
        default = 2;
        description = ''
          When <literal>usePercentageForPolicy</literal> is
          <literal>true</literal>, the levels at which UPower will take action
          for the critical battery level.

          This will also be used for batteries which don't have time information
          such as that of peripherals.

          If any value (of <literal>percentageLow</literal>,
          <literal>percentageCritical</literal> and
          <literal>percentageAction</literal>) is invalid, or not in descending
          order, the defaults will be used.
        '';
      };

      timeLow = mkOption {
        type = types.ints.unsigned;
        default = 1200;
        description = ''
          When <literal>usePercentageForPolicy</literal> is
          <literal>false</literal>, the time remaining in seconds at which
          UPower will consider the battery low.

          If any value (of <literal>timeLow</literal>,
          <literal>timeCritical</literal> and <literal>timeAction</literal>) is
          invalid, or not in descending order, the defaults will be used.
        '';
      };

      timeCritical = mkOption {
        type = types.ints.unsigned;
        default = 300;
        description = ''
          When <literal>usePercentageForPolicy</literal> is
          <literal>false</literal>, the time remaining in seconds at which
          UPower will consider the battery critical.

          If any value (of <literal>timeLow</literal>,
          <literal>timeCritical</literal> and <literal>timeAction</literal>) is
          invalid, or not in descending order, the defaults will be used.
        '';
      };

      timeAction = mkOption {
        type = types.ints.unsigned;
        default = 120;
        description = ''
          When <literal>usePercentageForPolicy</literal> is
          <literal>false</literal>, the time remaining in seconds at which
          UPower will take action for the critical battery level.

          If any value (of <literal>timeLow</literal>,
          <literal>timeCritical</literal> and <literal>timeAction</literal>) is
          invalid, or not in descending order, the defaults will be used.
        '';
      };

      criticalPowerAction = mkOption {
        type = types.enum [ "PowerOff" "Hibernate" "HybridSleep" ];
        default = "HybridSleep";
        description = ''
          The action to take when <literal>timeAction</literal> or
          <literal>percentageAction</literal> has been reached for the batteries
          (UPS or laptop batteries) supplying the computer
        '';
      };

    };

  };


  ###### implementation

  config = mkIf cfg.enable {

    environment.systemPackages = [ cfg.package ];

    services.dbus.packages = [ cfg.package ];

    services.udev.packages = [ cfg.package ];

    systemd.packages = [ cfg.package ];

    environment.etc."UPower/UPower.conf".text = generators.toINI {} {
      UPower = {
        EnableWattsUpPro = cfg.enableWattsUpPro;
        NoPollBatteries = cfg.noPollBatteries;
        IgnoreLid = cfg.ignoreLid;
        UsePercentageForPolicy = cfg.usePercentageForPolicy;
        PercentageLow = cfg.percentageLow;
        PercentageCritical = cfg.percentageCritical;
        PercentageAction = cfg.percentageAction;
        TimeLow = cfg.timeLow;
        TimeCritical = cfg.timeCritical;
        TimeAction = cfg.timeAction;
        CriticalPowerAction = cfg.criticalPowerAction;
      };
    };
  };

}