Commit e91926e9ea9073d8ce95b74602e8c2d775f5a793

Authored by Anton Vorontsov
1 parent ae4bb15290

apm_power: check I.intval for zero value, we use it as the divisor

Signed-off-by: Anton Vorontsov <cbou@mail.ru>

Showing 1 changed file with 3 additions and 0 deletions Inline Diff

drivers/power/apm_power.c
1 /* 1 /*
2 * Copyright © 2007 Anton Vorontsov <cbou@mail.ru> 2 * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
3 * Copyright © 2007 Eugeny Boger <eugenyboger@dgap.mipt.ru> 3 * Copyright © 2007 Eugeny Boger <eugenyboger@dgap.mipt.ru>
4 * 4 *
5 * Author: Eugeny Boger <eugenyboger@dgap.mipt.ru> 5 * Author: Eugeny Boger <eugenyboger@dgap.mipt.ru>
6 * 6 *
7 * Use consistent with the GNU GPL is permitted, 7 * Use consistent with the GNU GPL is permitted,
8 * provided that this copyright notice is 8 * provided that this copyright notice is
9 * preserved in its entirety in all copies and derived works. 9 * preserved in its entirety in all copies and derived works.
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/power_supply.h> 13 #include <linux/power_supply.h>
14 #include <linux/apm-emulation.h> 14 #include <linux/apm-emulation.h>
15 15
16 16
17 #define PSY_PROP(psy, prop, val) psy->get_property(psy, \ 17 #define PSY_PROP(psy, prop, val) psy->get_property(psy, \
18 POWER_SUPPLY_PROP_##prop, val) 18 POWER_SUPPLY_PROP_##prop, val)
19 19
20 #define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \ 20 #define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \
21 prop, val) 21 prop, val)
22 22
23 #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val) 23 #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
24 24
25 static DEFINE_MUTEX(apm_mutex); 25 static DEFINE_MUTEX(apm_mutex);
26 static struct power_supply *main_battery; 26 static struct power_supply *main_battery;
27 27
28 enum apm_source { 28 enum apm_source {
29 SOURCE_ENERGY, 29 SOURCE_ENERGY,
30 SOURCE_CHARGE, 30 SOURCE_CHARGE,
31 SOURCE_VOLTAGE, 31 SOURCE_VOLTAGE,
32 }; 32 };
33 33
34 struct find_bat_param { 34 struct find_bat_param {
35 struct power_supply *main; 35 struct power_supply *main;
36 struct power_supply *bat; 36 struct power_supply *bat;
37 struct power_supply *max_charge_bat; 37 struct power_supply *max_charge_bat;
38 struct power_supply *max_energy_bat; 38 struct power_supply *max_energy_bat;
39 union power_supply_propval full; 39 union power_supply_propval full;
40 int max_charge; 40 int max_charge;
41 int max_energy; 41 int max_energy;
42 }; 42 };
43 43
44 static int __find_main_battery(struct device *dev, void *data) 44 static int __find_main_battery(struct device *dev, void *data)
45 { 45 {
46 struct find_bat_param *bp = (struct find_bat_param *)data; 46 struct find_bat_param *bp = (struct find_bat_param *)data;
47 47
48 bp->bat = dev_get_drvdata(dev); 48 bp->bat = dev_get_drvdata(dev);
49 49
50 if (bp->bat->use_for_apm) { 50 if (bp->bat->use_for_apm) {
51 /* nice, we explicitly asked to report this battery. */ 51 /* nice, we explicitly asked to report this battery. */
52 bp->main = bp->bat; 52 bp->main = bp->bat;
53 return 1; 53 return 1;
54 } 54 }
55 55
56 if (!PSY_PROP(bp->bat, CHARGE_FULL_DESIGN, &bp->full) || 56 if (!PSY_PROP(bp->bat, CHARGE_FULL_DESIGN, &bp->full) ||
57 !PSY_PROP(bp->bat, CHARGE_FULL, &bp->full)) { 57 !PSY_PROP(bp->bat, CHARGE_FULL, &bp->full)) {
58 if (bp->full.intval > bp->max_charge) { 58 if (bp->full.intval > bp->max_charge) {
59 bp->max_charge_bat = bp->bat; 59 bp->max_charge_bat = bp->bat;
60 bp->max_charge = bp->full.intval; 60 bp->max_charge = bp->full.intval;
61 } 61 }
62 } else if (!PSY_PROP(bp->bat, ENERGY_FULL_DESIGN, &bp->full) || 62 } else if (!PSY_PROP(bp->bat, ENERGY_FULL_DESIGN, &bp->full) ||
63 !PSY_PROP(bp->bat, ENERGY_FULL, &bp->full)) { 63 !PSY_PROP(bp->bat, ENERGY_FULL, &bp->full)) {
64 if (bp->full.intval > bp->max_energy) { 64 if (bp->full.intval > bp->max_energy) {
65 bp->max_energy_bat = bp->bat; 65 bp->max_energy_bat = bp->bat;
66 bp->max_energy = bp->full.intval; 66 bp->max_energy = bp->full.intval;
67 } 67 }
68 } 68 }
69 return 0; 69 return 0;
70 } 70 }
71 71
72 static void find_main_battery(void) 72 static void find_main_battery(void)
73 { 73 {
74 struct find_bat_param bp; 74 struct find_bat_param bp;
75 int error; 75 int error;
76 76
77 memset(&bp, 0, sizeof(struct find_bat_param)); 77 memset(&bp, 0, sizeof(struct find_bat_param));
78 main_battery = NULL; 78 main_battery = NULL;
79 bp.main = main_battery; 79 bp.main = main_battery;
80 80
81 error = class_for_each_device(power_supply_class, &bp, 81 error = class_for_each_device(power_supply_class, &bp,
82 __find_main_battery); 82 __find_main_battery);
83 if (error) { 83 if (error) {
84 main_battery = bp.main; 84 main_battery = bp.main;
85 return; 85 return;
86 } 86 }
87 87
88 if ((bp.max_energy_bat && bp.max_charge_bat) && 88 if ((bp.max_energy_bat && bp.max_charge_bat) &&
89 (bp.max_energy_bat != bp.max_charge_bat)) { 89 (bp.max_energy_bat != bp.max_charge_bat)) {
90 /* try guess battery with more capacity */ 90 /* try guess battery with more capacity */
91 if (!PSY_PROP(bp.max_charge_bat, VOLTAGE_MAX_DESIGN, 91 if (!PSY_PROP(bp.max_charge_bat, VOLTAGE_MAX_DESIGN,
92 &bp.full)) { 92 &bp.full)) {
93 if (bp.max_energy > bp.max_charge * bp.full.intval) 93 if (bp.max_energy > bp.max_charge * bp.full.intval)
94 main_battery = bp.max_energy_bat; 94 main_battery = bp.max_energy_bat;
95 else 95 else
96 main_battery = bp.max_charge_bat; 96 main_battery = bp.max_charge_bat;
97 } else if (!PSY_PROP(bp.max_energy_bat, VOLTAGE_MAX_DESIGN, 97 } else if (!PSY_PROP(bp.max_energy_bat, VOLTAGE_MAX_DESIGN,
98 &bp.full)) { 98 &bp.full)) {
99 if (bp.max_charge > bp.max_energy / bp.full.intval) 99 if (bp.max_charge > bp.max_energy / bp.full.intval)
100 main_battery = bp.max_charge_bat; 100 main_battery = bp.max_charge_bat;
101 else 101 else
102 main_battery = bp.max_energy_bat; 102 main_battery = bp.max_energy_bat;
103 } else { 103 } else {
104 /* give up, choice any */ 104 /* give up, choice any */
105 main_battery = bp.max_energy_bat; 105 main_battery = bp.max_energy_bat;
106 } 106 }
107 } else if (bp.max_charge_bat) { 107 } else if (bp.max_charge_bat) {
108 main_battery = bp.max_charge_bat; 108 main_battery = bp.max_charge_bat;
109 } else if (bp.max_energy_bat) { 109 } else if (bp.max_energy_bat) {
110 main_battery = bp.max_energy_bat; 110 main_battery = bp.max_energy_bat;
111 } else { 111 } else {
112 /* give up, try the last if any */ 112 /* give up, try the last if any */
113 main_battery = bp.bat; 113 main_battery = bp.bat;
114 } 114 }
115 } 115 }
116 116
117 static int do_calculate_time(int status, enum apm_source source) 117 static int do_calculate_time(int status, enum apm_source source)
118 { 118 {
119 union power_supply_propval full; 119 union power_supply_propval full;
120 union power_supply_propval empty; 120 union power_supply_propval empty;
121 union power_supply_propval cur; 121 union power_supply_propval cur;
122 union power_supply_propval I; 122 union power_supply_propval I;
123 enum power_supply_property full_prop; 123 enum power_supply_property full_prop;
124 enum power_supply_property full_design_prop; 124 enum power_supply_property full_design_prop;
125 enum power_supply_property empty_prop; 125 enum power_supply_property empty_prop;
126 enum power_supply_property empty_design_prop; 126 enum power_supply_property empty_design_prop;
127 enum power_supply_property cur_avg_prop; 127 enum power_supply_property cur_avg_prop;
128 enum power_supply_property cur_now_prop; 128 enum power_supply_property cur_now_prop;
129 129
130 if (MPSY_PROP(CURRENT_AVG, &I)) { 130 if (MPSY_PROP(CURRENT_AVG, &I)) {
131 /* if battery can't report average value, use momentary */ 131 /* if battery can't report average value, use momentary */
132 if (MPSY_PROP(CURRENT_NOW, &I)) 132 if (MPSY_PROP(CURRENT_NOW, &I))
133 return -1; 133 return -1;
134 } 134 }
135 135
136 if (!I.intval)
137 return 0;
138
136 switch (source) { 139 switch (source) {
137 case SOURCE_CHARGE: 140 case SOURCE_CHARGE:
138 full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; 141 full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
139 full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; 142 full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
140 empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 143 empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
141 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 144 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
142 cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; 145 cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
143 cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; 146 cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
144 break; 147 break;
145 case SOURCE_ENERGY: 148 case SOURCE_ENERGY:
146 full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; 149 full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
147 full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; 150 full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
148 empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; 151 empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
149 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 152 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
150 cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; 153 cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
151 cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; 154 cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
152 break; 155 break;
153 case SOURCE_VOLTAGE: 156 case SOURCE_VOLTAGE:
154 full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; 157 full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
155 full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN; 158 full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN;
156 empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; 159 empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
157 empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN; 160 empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN;
158 cur_avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG; 161 cur_avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG;
159 cur_now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW; 162 cur_now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW;
160 break; 163 break;
161 default: 164 default:
162 printk(KERN_ERR "Unsupported source: %d\n", source); 165 printk(KERN_ERR "Unsupported source: %d\n", source);
163 return -1; 166 return -1;
164 } 167 }
165 168
166 if (_MPSY_PROP(full_prop, &full)) { 169 if (_MPSY_PROP(full_prop, &full)) {
167 /* if battery can't report this property, use design value */ 170 /* if battery can't report this property, use design value */
168 if (_MPSY_PROP(full_design_prop, &full)) 171 if (_MPSY_PROP(full_design_prop, &full))
169 return -1; 172 return -1;
170 } 173 }
171 174
172 if (_MPSY_PROP(empty_prop, &empty)) { 175 if (_MPSY_PROP(empty_prop, &empty)) {
173 /* if battery can't report this property, use design value */ 176 /* if battery can't report this property, use design value */
174 if (_MPSY_PROP(empty_design_prop, &empty)) 177 if (_MPSY_PROP(empty_design_prop, &empty))
175 empty.intval = 0; 178 empty.intval = 0;
176 } 179 }
177 180
178 if (_MPSY_PROP(cur_avg_prop, &cur)) { 181 if (_MPSY_PROP(cur_avg_prop, &cur)) {
179 /* if battery can't report average value, use momentary */ 182 /* if battery can't report average value, use momentary */
180 if (_MPSY_PROP(cur_now_prop, &cur)) 183 if (_MPSY_PROP(cur_now_prop, &cur))
181 return -1; 184 return -1;
182 } 185 }
183 186
184 if (status == POWER_SUPPLY_STATUS_CHARGING) 187 if (status == POWER_SUPPLY_STATUS_CHARGING)
185 return ((cur.intval - full.intval) * 60L) / I.intval; 188 return ((cur.intval - full.intval) * 60L) / I.intval;
186 else 189 else
187 return -((cur.intval - empty.intval) * 60L) / I.intval; 190 return -((cur.intval - empty.intval) * 60L) / I.intval;
188 } 191 }
189 192
190 static int calculate_time(int status) 193 static int calculate_time(int status)
191 { 194 {
192 int time; 195 int time;
193 196
194 time = do_calculate_time(status, SOURCE_ENERGY); 197 time = do_calculate_time(status, SOURCE_ENERGY);
195 if (time != -1) 198 if (time != -1)
196 return time; 199 return time;
197 200
198 time = do_calculate_time(status, SOURCE_CHARGE); 201 time = do_calculate_time(status, SOURCE_CHARGE);
199 if (time != -1) 202 if (time != -1)
200 return time; 203 return time;
201 204
202 time = do_calculate_time(status, SOURCE_VOLTAGE); 205 time = do_calculate_time(status, SOURCE_VOLTAGE);
203 if (time != -1) 206 if (time != -1)
204 return time; 207 return time;
205 208
206 return -1; 209 return -1;
207 } 210 }
208 211
209 static int calculate_capacity(enum apm_source source) 212 static int calculate_capacity(enum apm_source source)
210 { 213 {
211 enum power_supply_property full_prop, empty_prop; 214 enum power_supply_property full_prop, empty_prop;
212 enum power_supply_property full_design_prop, empty_design_prop; 215 enum power_supply_property full_design_prop, empty_design_prop;
213 enum power_supply_property now_prop, avg_prop; 216 enum power_supply_property now_prop, avg_prop;
214 union power_supply_propval empty, full, cur; 217 union power_supply_propval empty, full, cur;
215 int ret; 218 int ret;
216 219
217 switch (source) { 220 switch (source) {
218 case SOURCE_CHARGE: 221 case SOURCE_CHARGE:
219 full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; 222 full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
220 empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; 223 empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
221 full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; 224 full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
222 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN; 225 empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
223 now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; 226 now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
224 avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; 227 avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
225 break; 228 break;
226 case SOURCE_ENERGY: 229 case SOURCE_ENERGY:
227 full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; 230 full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
228 empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; 231 empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
229 full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; 232 full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
230 empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; 233 empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
231 now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; 234 now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
232 avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; 235 avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
233 case SOURCE_VOLTAGE: 236 case SOURCE_VOLTAGE:
234 full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; 237 full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
235 empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; 238 empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
236 full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN; 239 full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN;
237 empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN; 240 empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN;
238 now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW; 241 now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW;
239 avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG; 242 avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG;
240 break; 243 break;
241 default: 244 default:
242 printk(KERN_ERR "Unsupported source: %d\n", source); 245 printk(KERN_ERR "Unsupported source: %d\n", source);
243 return -1; 246 return -1;
244 } 247 }
245 248
246 if (_MPSY_PROP(full_prop, &full)) { 249 if (_MPSY_PROP(full_prop, &full)) {
247 /* if battery can't report this property, use design value */ 250 /* if battery can't report this property, use design value */
248 if (_MPSY_PROP(full_design_prop, &full)) 251 if (_MPSY_PROP(full_design_prop, &full))
249 return -1; 252 return -1;
250 } 253 }
251 254
252 if (_MPSY_PROP(avg_prop, &cur)) { 255 if (_MPSY_PROP(avg_prop, &cur)) {
253 /* if battery can't report average value, use momentary */ 256 /* if battery can't report average value, use momentary */
254 if (_MPSY_PROP(now_prop, &cur)) 257 if (_MPSY_PROP(now_prop, &cur))
255 return -1; 258 return -1;
256 } 259 }
257 260
258 if (_MPSY_PROP(empty_prop, &empty)) { 261 if (_MPSY_PROP(empty_prop, &empty)) {
259 /* if battery can't report this property, use design value */ 262 /* if battery can't report this property, use design value */
260 if (_MPSY_PROP(empty_design_prop, &empty)) 263 if (_MPSY_PROP(empty_design_prop, &empty))
261 empty.intval = 0; 264 empty.intval = 0;
262 } 265 }
263 266
264 if (full.intval - empty.intval) 267 if (full.intval - empty.intval)
265 ret = ((cur.intval - empty.intval) * 100L) / 268 ret = ((cur.intval - empty.intval) * 100L) /
266 (full.intval - empty.intval); 269 (full.intval - empty.intval);
267 else 270 else
268 return -1; 271 return -1;
269 272
270 if (ret > 100) 273 if (ret > 100)
271 return 100; 274 return 100;
272 else if (ret < 0) 275 else if (ret < 0)
273 return 0; 276 return 0;
274 277
275 return ret; 278 return ret;
276 } 279 }
277 280
278 static void apm_battery_apm_get_power_status(struct apm_power_info *info) 281 static void apm_battery_apm_get_power_status(struct apm_power_info *info)
279 { 282 {
280 union power_supply_propval status; 283 union power_supply_propval status;
281 union power_supply_propval capacity, time_to_full, time_to_empty; 284 union power_supply_propval capacity, time_to_full, time_to_empty;
282 285
283 mutex_lock(&apm_mutex); 286 mutex_lock(&apm_mutex);
284 find_main_battery(); 287 find_main_battery();
285 if (!main_battery) { 288 if (!main_battery) {
286 mutex_unlock(&apm_mutex); 289 mutex_unlock(&apm_mutex);
287 return; 290 return;
288 } 291 }
289 292
290 /* status */ 293 /* status */
291 294
292 if (MPSY_PROP(STATUS, &status)) 295 if (MPSY_PROP(STATUS, &status))
293 status.intval = POWER_SUPPLY_STATUS_UNKNOWN; 296 status.intval = POWER_SUPPLY_STATUS_UNKNOWN;
294 297
295 /* ac line status */ 298 /* ac line status */
296 299
297 if ((status.intval == POWER_SUPPLY_STATUS_CHARGING) || 300 if ((status.intval == POWER_SUPPLY_STATUS_CHARGING) ||
298 (status.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) || 301 (status.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) ||
299 (status.intval == POWER_SUPPLY_STATUS_FULL)) 302 (status.intval == POWER_SUPPLY_STATUS_FULL))
300 info->ac_line_status = APM_AC_ONLINE; 303 info->ac_line_status = APM_AC_ONLINE;
301 else 304 else
302 info->ac_line_status = APM_AC_OFFLINE; 305 info->ac_line_status = APM_AC_OFFLINE;
303 306
304 /* battery life (i.e. capacity, in percents) */ 307 /* battery life (i.e. capacity, in percents) */
305 308
306 if (MPSY_PROP(CAPACITY, &capacity) == 0) { 309 if (MPSY_PROP(CAPACITY, &capacity) == 0) {
307 info->battery_life = capacity.intval; 310 info->battery_life = capacity.intval;
308 } else { 311 } else {
309 /* try calculate using energy */ 312 /* try calculate using energy */
310 info->battery_life = calculate_capacity(SOURCE_ENERGY); 313 info->battery_life = calculate_capacity(SOURCE_ENERGY);
311 /* if failed try calculate using charge instead */ 314 /* if failed try calculate using charge instead */
312 if (info->battery_life == -1) 315 if (info->battery_life == -1)
313 info->battery_life = calculate_capacity(SOURCE_CHARGE); 316 info->battery_life = calculate_capacity(SOURCE_CHARGE);
314 if (info->battery_life == -1) 317 if (info->battery_life == -1)
315 info->battery_life = calculate_capacity(SOURCE_VOLTAGE); 318 info->battery_life = calculate_capacity(SOURCE_VOLTAGE);
316 } 319 }
317 320
318 /* charging status */ 321 /* charging status */
319 322
320 if (status.intval == POWER_SUPPLY_STATUS_CHARGING) { 323 if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
321 info->battery_status = APM_BATTERY_STATUS_CHARGING; 324 info->battery_status = APM_BATTERY_STATUS_CHARGING;
322 } else { 325 } else {
323 if (info->battery_life > 50) 326 if (info->battery_life > 50)
324 info->battery_status = APM_BATTERY_STATUS_HIGH; 327 info->battery_status = APM_BATTERY_STATUS_HIGH;
325 else if (info->battery_life > 5) 328 else if (info->battery_life > 5)
326 info->battery_status = APM_BATTERY_STATUS_LOW; 329 info->battery_status = APM_BATTERY_STATUS_LOW;
327 else 330 else
328 info->battery_status = APM_BATTERY_STATUS_CRITICAL; 331 info->battery_status = APM_BATTERY_STATUS_CRITICAL;
329 } 332 }
330 info->battery_flag = info->battery_status; 333 info->battery_flag = info->battery_status;
331 334
332 /* time */ 335 /* time */
333 336
334 info->units = APM_UNITS_MINS; 337 info->units = APM_UNITS_MINS;
335 338
336 if (status.intval == POWER_SUPPLY_STATUS_CHARGING) { 339 if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
337 if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) || 340 if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) ||
338 !MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full)) 341 !MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
339 info->time = time_to_full.intval / 60; 342 info->time = time_to_full.intval / 60;
340 else 343 else
341 info->time = calculate_time(status.intval); 344 info->time = calculate_time(status.intval);
342 } else { 345 } else {
343 if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) || 346 if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) ||
344 !MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty)) 347 !MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
345 info->time = time_to_empty.intval / 60; 348 info->time = time_to_empty.intval / 60;
346 else 349 else
347 info->time = calculate_time(status.intval); 350 info->time = calculate_time(status.intval);
348 } 351 }
349 352
350 mutex_unlock(&apm_mutex); 353 mutex_unlock(&apm_mutex);
351 } 354 }
352 355
353 static int __init apm_battery_init(void) 356 static int __init apm_battery_init(void)
354 { 357 {
355 printk(KERN_INFO "APM Battery Driver\n"); 358 printk(KERN_INFO "APM Battery Driver\n");
356 359
357 apm_get_power_status = apm_battery_apm_get_power_status; 360 apm_get_power_status = apm_battery_apm_get_power_status;
358 return 0; 361 return 0;
359 } 362 }
360 363
361 static void __exit apm_battery_exit(void) 364 static void __exit apm_battery_exit(void)
362 { 365 {
363 apm_get_power_status = NULL; 366 apm_get_power_status = NULL;
364 } 367 }
365 368
366 module_init(apm_battery_init); 369 module_init(apm_battery_init);
367 module_exit(apm_battery_exit); 370 module_exit(apm_battery_exit);
368 371
369 MODULE_AUTHOR("Eugeny Boger <eugenyboger@dgap.mipt.ru>"); 372 MODULE_AUTHOR("Eugeny Boger <eugenyboger@dgap.mipt.ru>");
370 MODULE_DESCRIPTION("APM emulation driver for battery monitoring class"); 373 MODULE_DESCRIPTION("APM emulation driver for battery monitoring class");
371 MODULE_LICENSE("GPL"); 374 MODULE_LICENSE("GPL");
372 375