~ubuntu-branches/debian/sid/hal/sid

« back to all changes in this revision

Viewing changes to hald/device_pm.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2007-10-23 12:33:58 UTC
  • Revision ID: james.westby@ubuntu.com-20071023123358-xaf8mjc5n84d5gtz
Tags: upstream-0.5.10
ImportĀ upstreamĀ versionĀ 0.5.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *
 
3
 * device_pm.c - Various power management related utilities that need to use
 
4
 *               HalDevice. This is not suitable for use in addons and probers.
 
5
 *
 
6
 * Copyright (C) 2005-2007 Richard Hughes <richard@hughsie.com>
 
7
 * Copyright (C) 2005 Danny Kukawka <danny.kukawka@web.de>
 
8
 *
 
9
 * Licensed under the Academic Free License version 2.1
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software
 
23
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
24
 *
 
25
 **************************************************************************/
 
26
 
 
27
#include <stdio.h>
 
28
#include <string.h>
 
29
#include <time.h>
 
30
#include <ctype.h>
 
31
#include <stdint.h>
 
32
 
 
33
#include <glib.h>
 
34
 
 
35
#include "logger.h"
 
36
#include "util_pm.h"
 
37
#include "device_pm.h"
 
38
#include "device_store.h"
 
39
 
 
40
/** 
 
41
 *  device_pm_abstract_props:
 
42
 *  @d:         Valid battery HalDevice
 
43
 *
 
44
 * Convert the buggy 'reporting' keys into 'charge_level' keys so stuff like
 
45
 * desktop power managers do not have to deal with odd quirks.
 
46
 */
 
47
void
 
48
device_pm_abstract_props (HalDevice *d)
 
49
{
 
50
        const char *reporting_unit;
 
51
        int reporting_current;
 
52
        int reporting_lastfull;
 
53
        int reporting_rate;
 
54
        int normalised_current;
 
55
        int normalised_lastfull;
 
56
        int normalised_rate;
 
57
        int design_voltage;
 
58
        int voltage;
 
59
        gboolean charging;
 
60
        gboolean discharging;
 
61
 
 
62
        /* get all the data we know */
 
63
        reporting_unit = hal_device_property_get_string (d,
 
64
                                        "battery.reporting.unit");
 
65
        reporting_current = hal_device_property_get_int (d,
 
66
                                        "battery.reporting.current");
 
67
        reporting_lastfull = hal_device_property_get_int (d,
 
68
                                        "battery.reporting.last_full");
 
69
        reporting_rate = hal_device_property_get_int (d,
 
70
                                        "battery.reporting.rate");
 
71
 
 
72
        /* ACPI gives out the special 'Ones' value for rate when it's unable
 
73
         * to calculate the true rate. We should set the rate zero, and wait
 
74
         * for the BIOS to stabilise. */
 
75
        if (reporting_rate == 0xffff) {
 
76
                reporting_rate = 0;
 
77
        }
 
78
 
 
79
        /* We are converting the unknown units into mWh because of ACPI's nature
 
80
         * of not having a standard unit. */
 
81
        if (reporting_unit && strcmp (reporting_unit, "mAh") == 0) {
 
82
                /* convert mAh to mWh by multiplying by voltage.  due to the
 
83
                 * general wonkiness of ACPI implementations, this is a lot
 
84
                 * harder than it should have to be... */
 
85
 
 
86
                design_voltage = hal_device_property_get_int (d, "battery.voltage.design");
 
87
                voltage = hal_device_property_get_int (d, "battery.voltage.current");
 
88
 
 
89
                /* Just in case we don't get design voltage information, then
 
90
                 * this will pretend that we have 1V.  This degrades our
 
91
                 * ability to report accurate times on multi-battery systems
 
92
                 * but will always prevent negative charge levels and allow
 
93
                 * accurate reporting on single-battery systems. */
 
94
                if (design_voltage <= 0)
 
95
                        design_voltage = 1000; /* mV */
 
96
 
 
97
                /* If the current voltage is unknown, smaller than 50% of design voltage (fd.o #8593) 
 
98
                 * or greater than design, then use design voltage. */
 
99
                if (voltage < (design_voltage/2)  || voltage > design_voltage) {
 
100
                        HAL_DEBUG (("Current voltage is unknown, smaller than 50%% or greater than design"));
 
101
                        voltage = design_voltage;
 
102
                }
 
103
 
 
104
                normalised_current = (reporting_current * voltage) / 1000;
 
105
                normalised_lastfull = (reporting_lastfull * voltage) / 1000;
 
106
                normalised_rate = (reporting_rate * voltage) / 1000;
 
107
        } else {
 
108
                /* handle as if mWh (which don't need conversion), which is
 
109
                 * the most common case. */
 
110
                normalised_current = reporting_current;
 
111
                normalised_lastfull = reporting_lastfull;
 
112
                normalised_rate = reporting_rate;
 
113
        }
 
114
 
 
115
        /*
 
116
         * Check the normalised keys to see if positive.
 
117
         */
 
118
        if (normalised_current < 0)
 
119
                normalised_current = 0;
 
120
        if (normalised_lastfull < 0)
 
121
                normalised_lastfull = 0;
 
122
        if (normalised_rate < 0)
 
123
                normalised_rate = 0;
 
124
 
 
125
        /* Some laptops report a rate even when not charging or discharging.
 
126
         * If not charging and not discharging force rate to be zero. */
 
127
        charging = hal_device_property_get_bool (d, "battery.rechargeable.is_charging");
 
128
        discharging = hal_device_property_get_bool (d, "battery.rechargeable.is_discharging");
 
129
 
 
130
        if (!charging && !discharging)
 
131
                normalised_rate = 0;
 
132
 
 
133
        /* Some laptops report current charge much larger than
 
134
         * full charge when at 100%.  Clamp back down to 100%. */
 
135
        if (normalised_current > normalised_lastfull)
 
136
                normalised_current = normalised_lastfull;
 
137
 
 
138
        hal_device_property_set_int (d, "battery.charge_level.current", normalised_current);
 
139
        hal_device_property_set_int (d, "battery.charge_level.last_full", normalised_lastfull);
 
140
        hal_device_property_set_int (d, "battery.charge_level.rate", normalised_rate);
 
141
}
 
142
 
 
143
/** 
 
144
 *  device_pm_calculate_percentage:
 
145
 *  @d:         Valid battery HalDevice
 
146
 *
 
147
 * Calculate the percentage from the current levels and the last full level
 
148
 * when the hardware has not given us a value.
 
149
 */
 
150
void
 
151
device_pm_calculate_percentage (HalDevice *d)
 
152
{
 
153
        int percentage;
 
154
        int current;
 
155
        int lastfull;
 
156
 
 
157
        /* default to fully charge to avoid triggering low power warnings on
 
158
         * really broken batteries */
 
159
        percentage = 100;
 
160
 
 
161
        /* use the charge level compared to the last full amount */
 
162
        current = hal_device_property_get_int (d, "battery.charge_level.current");
 
163
        lastfull = hal_device_property_get_int (d, "battery.charge_level.last_full");
 
164
 
 
165
        /* make sure we have current */
 
166
        if (current <= 0) {
 
167
                HAL_WARNING (("battery.charge_level.current %i, returning -1!", current));
 
168
        } else if (lastfull <= 0) {
 
169
                HAL_WARNING (("battery.charge_level.lastfull %i, percentage returning -1!", lastfull));
 
170
        } else {
 
171
                percentage = ((double) current / (double) lastfull) * 100;
 
172
                /* Some bios's will report this out of range of 0..100, limit it here */
 
173
                if (percentage > 100)
 
174
                        percentage = 100;
 
175
                else if (percentage < 0)
 
176
                        percentage = 1;
 
177
        }
 
178
        hal_device_property_set_int (d, "battery.charge_level.percentage", percentage);
 
179
}
 
180
 
 
181
/** 
 
182
 *  device_pm_calculate_time:
 
183
 *  @d:         Valid battery HalDevice
 
184
 *
 
185
 * Calculate the time from the rate and the last full level
 
186
 * when the hardware has not given us a time value.
 
187
 */
 
188
void
 
189
device_pm_calculate_time (HalDevice *d)
 
190
{
 
191
        int time;
 
192
 
 
193
        time = util_compute_time_remaining (
 
194
                hal_device_get_udi (d), 
 
195
                hal_device_property_get_int (d, "battery.charge_level.rate"),
 
196
                hal_device_property_get_int (d, "battery.charge_level.current"),
 
197
                hal_device_property_get_int (d, "battery.charge_level.last_full"),
 
198
                hal_device_property_get_bool (d, "battery.rechargeable.is_discharging"),
 
199
                hal_device_property_get_bool (d, "battery.rechargeable.is_charging"),
 
200
                hal_device_property_get_bool (d, "battery.remaining_time.calculate_per_time"));
 
201
 
 
202
        /* zero time is unknown */
 
203
        if (time > 0)
 
204
                hal_device_property_set_int (d, "battery.remaining_time", time);
 
205
        else
 
206
                hal_device_property_remove (d, "battery.remaining_time");
 
207
}
 
208
 
 
209
/** 
 
210
 *  device_pm_remove_optional_props:
 
211
 *  @d:         Valid battery HalDevice
 
212
 *
 
213
 *  Removes all the optional hardware battery.* keys., i.e. the ones that are
 
214
 *  no longer valid when the battery cell is removed or changed.
 
215
 *  If the battery _device_ completely vanishes (e.g. in a docking bay) then
 
216
 *  the HalDevice should be completely removed from the device tree.
 
217
 *
 
218
 *  Note: Removing a key that doesn't exist is OK.
 
219
 */
 
220
void
 
221
device_pm_remove_optional_props (HalDevice *d)
 
222
{
 
223
        hal_device_property_remove (d, "battery.is_rechargeable");
 
224
        hal_device_property_remove (d, "battery.rechargeable.is_charging");
 
225
        hal_device_property_remove (d, "battery.rechargeable.is_discharging");
 
226
        hal_device_property_remove (d, "battery.vendor");
 
227
        hal_device_property_remove (d, "battery.model");
 
228
        hal_device_property_remove (d, "battery.serial");
 
229
        hal_device_property_remove (d, "battery.reporting.technology");
 
230
        hal_device_property_remove (d, "battery.technology");
 
231
        hal_device_property_remove (d, "battery.vendor");
 
232
        hal_device_property_remove (d, "battery.charge_level.unit");
 
233
        hal_device_property_remove (d, "battery.charge_level.current");
 
234
        hal_device_property_remove (d, "battery.charge_level.percentage");
 
235
        hal_device_property_remove (d, "battery.charge_level.last_full");
 
236
        hal_device_property_remove (d, "battery.charge_level.design");
 
237
        hal_device_property_remove (d, "battery.charge_level.capacity_state");
 
238
        hal_device_property_remove (d, "battery.charge_level.warning");
 
239
        hal_device_property_remove (d, "battery.charge_level.low");
 
240
        hal_device_property_remove (d, "battery.charge_level.granularity_1");
 
241
        hal_device_property_remove (d, "battery.charge_level.granularity_2");
 
242
        hal_device_property_remove (d, "battery.charge_level.rate");
 
243
        hal_device_property_remove (d, "battery.voltage.unit");
 
244
        hal_device_property_remove (d, "battery.voltage.design");
 
245
        hal_device_property_remove (d, "battery.voltage.current");
 
246
        hal_device_property_remove (d, "battery.alarm.unit");
 
247
        hal_device_property_remove (d, "battery.alarm.design");
 
248
        hal_device_property_remove (d, "battery.reporting.current");
 
249
        hal_device_property_remove (d, "battery.reporting.last_full");
 
250
        hal_device_property_remove (d, "battery.reporting.design");
 
251
        hal_device_property_remove (d, "battery.reporting.rate");
 
252
        hal_device_property_remove (d, "battery.reporting.warning");
 
253
        hal_device_property_remove (d, "battery.reporting.low");
 
254
        hal_device_property_remove (d, "battery.reporting.granularity_1");
 
255
        hal_device_property_remove (d, "battery.reporting.granularity_2");
 
256
        hal_device_property_remove (d, "battery.reporting.unit");
 
257
        hal_device_property_remove (d, "battery.remaining_time");
 
258
}
 
259