Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: Make test_power driver more dynamic.

In 2008 Masashi YOKOTA <yokota@pylone.jp> created the virtual
battery driver found here:
http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2

It found use out of tree, but was never merged upstream.
Since then the test_power driver has been merged, which provides
very similar functionality.

This patch extends the test_power driver to be more dynamic
at runtime, by merging portions of the Virtual Battery Driver
by Masashi YOKOTA.

With this patch, I can tweak the values in:
/sys/module/test_power/parameters/* and watch the behavior of
the gnome power managment daemon or other battery UI software.

CC: Anton Vorontsov <cbouatmailru@gmail.com>
CC: Akihiro MAEDA <sola.1980.a@gmail.com>
CC: Masashi YOKOTA <yokota@pylone.jp>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>

authored by

John Stultz and committed by
Anton Vorontsov
f17ef9b2 73c244a8

+266 -10
+266 -10
drivers/power/test_power.c
··· 3 3 * 4 4 * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com> 5 5 * 6 + * Dynamic module parameter code from the Virtual Battery Driver 7 + * Copyright (C) 2008 Pylone, Inc. 8 + * By: Masashi YOKOTA <yokota@pylone.jp> 9 + * Originally found here: 10 + * http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2 11 + * 6 12 * This program is free software; you can redistribute it and/or modify 7 13 * it under the terms of the GNU General Public License version 2 as 8 14 * published by the Free Software Foundation. ··· 21 15 #include <linux/delay.h> 22 16 #include <linux/vermagic.h> 23 17 24 - static int test_power_ac_online = 1; 25 - static int test_power_battery_status = POWER_SUPPLY_STATUS_CHARGING; 18 + static int ac_online = 1; 19 + static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 20 + static int battery_health = POWER_SUPPLY_HEALTH_GOOD; 21 + static int battery_present = 1; /* true */ 22 + static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; 23 + static int battery_capacity = 50; 26 24 27 25 static int test_power_get_ac_property(struct power_supply *psy, 28 26 enum power_supply_property psp, ··· 34 24 { 35 25 switch (psp) { 36 26 case POWER_SUPPLY_PROP_ONLINE: 37 - val->intval = test_power_ac_online; 27 + val->intval = ac_online; 38 28 break; 39 29 default: 40 30 return -EINVAL; ··· 57 47 val->strval = UTS_RELEASE; 58 48 break; 59 49 case POWER_SUPPLY_PROP_STATUS: 60 - val->intval = test_power_battery_status; 50 + val->intval = battery_status; 61 51 break; 62 52 case POWER_SUPPLY_PROP_CHARGE_TYPE: 63 53 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 64 54 break; 65 55 case POWER_SUPPLY_PROP_HEALTH: 66 - val->intval = POWER_SUPPLY_HEALTH_GOOD; 56 + val->intval = battery_health; 57 + break; 58 + case POWER_SUPPLY_PROP_PRESENT: 59 + val->intval = battery_present; 67 60 break; 68 61 case POWER_SUPPLY_PROP_TECHNOLOGY: 69 - val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 62 + val->intval = battery_technology; 70 63 break; 71 64 case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 72 65 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 73 66 break; 74 67 case POWER_SUPPLY_PROP_CAPACITY: 75 - val->intval = 50; 68 + case POWER_SUPPLY_PROP_CHARGE_NOW: 69 + val->intval = battery_capacity; 70 + break; 71 + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 72 + case POWER_SUPPLY_PROP_CHARGE_FULL: 73 + val->intval = 100; 76 74 break; 77 75 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 78 76 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: ··· 102 84 POWER_SUPPLY_PROP_STATUS, 103 85 POWER_SUPPLY_PROP_CHARGE_TYPE, 104 86 POWER_SUPPLY_PROP_HEALTH, 87 + POWER_SUPPLY_PROP_PRESENT, 105 88 POWER_SUPPLY_PROP_TECHNOLOGY, 89 + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 106 90 POWER_SUPPLY_PROP_CHARGE_FULL, 107 - POWER_SUPPLY_PROP_CHARGE_EMPTY, 91 + POWER_SUPPLY_PROP_CHARGE_NOW, 108 92 POWER_SUPPLY_PROP_CAPACITY, 109 93 POWER_SUPPLY_PROP_CAPACITY_LEVEL, 110 94 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, ··· 138 118 }, 139 119 }; 140 120 121 + 141 122 static int __init test_power_init(void) 142 123 { 143 124 int i; ··· 166 145 int i; 167 146 168 147 /* Let's see how we handle changes... */ 169 - test_power_ac_online = 0; 170 - test_power_battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 148 + ac_online = 0; 149 + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 171 150 for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) 172 151 power_supply_changed(&test_power_supplies[i]); 173 152 pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n", ··· 178 157 power_supply_unregister(&test_power_supplies[i]); 179 158 } 180 159 module_exit(test_power_exit); 160 + 161 + 162 + 163 + #define MAX_KEYLENGTH 256 164 + struct battery_property_map { 165 + int value; 166 + char const *key; 167 + }; 168 + 169 + static struct battery_property_map map_ac_online[] = { 170 + { 0, "on" }, 171 + { 1, "off" }, 172 + { -1, NULL }, 173 + }; 174 + 175 + static struct battery_property_map map_status[] = { 176 + { POWER_SUPPLY_STATUS_CHARGING, "charging" }, 177 + { POWER_SUPPLY_STATUS_DISCHARGING, "discharging" }, 178 + { POWER_SUPPLY_STATUS_NOT_CHARGING, "not-charging" }, 179 + { POWER_SUPPLY_STATUS_FULL, "full" }, 180 + { -1, NULL }, 181 + }; 182 + 183 + static struct battery_property_map map_health[] = { 184 + { POWER_SUPPLY_HEALTH_GOOD, "good" }, 185 + { POWER_SUPPLY_HEALTH_OVERHEAT, "overheat" }, 186 + { POWER_SUPPLY_HEALTH_DEAD, "dead" }, 187 + { POWER_SUPPLY_HEALTH_OVERVOLTAGE, "overvoltage" }, 188 + { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, "failure" }, 189 + { -1, NULL }, 190 + }; 191 + 192 + static struct battery_property_map map_present[] = { 193 + { 0, "false" }, 194 + { 1, "true" }, 195 + { -1, NULL }, 196 + }; 197 + 198 + static struct battery_property_map map_technology[] = { 199 + { POWER_SUPPLY_TECHNOLOGY_NiMH, "NiMH" }, 200 + { POWER_SUPPLY_TECHNOLOGY_LION, "LION" }, 201 + { POWER_SUPPLY_TECHNOLOGY_LIPO, "LIPO" }, 202 + { POWER_SUPPLY_TECHNOLOGY_LiFe, "LiFe" }, 203 + { POWER_SUPPLY_TECHNOLOGY_NiCd, "NiCd" }, 204 + { POWER_SUPPLY_TECHNOLOGY_LiMn, "LiMn" }, 205 + { -1, NULL }, 206 + }; 207 + 208 + 209 + static int map_get_value(struct battery_property_map *map, const char *key, 210 + int def_val) 211 + { 212 + char buf[MAX_KEYLENGTH]; 213 + int cr; 214 + 215 + strncpy(buf, key, MAX_KEYLENGTH); 216 + buf[MAX_KEYLENGTH-1] = '\0'; 217 + 218 + cr = strnlen(buf, MAX_KEYLENGTH) - 1; 219 + if (buf[cr] == '\n') 220 + buf[cr] = '\0'; 221 + 222 + while (map->key) { 223 + if (strncasecmp(map->key, buf, MAX_KEYLENGTH) == 0) 224 + return map->value; 225 + map++; 226 + } 227 + 228 + return def_val; 229 + } 230 + 231 + 232 + static const char *map_get_key(struct battery_property_map *map, int value, 233 + const char *def_key) 234 + { 235 + while (map->key) { 236 + if (map->value == value) 237 + return map->key; 238 + map++; 239 + } 240 + 241 + return def_key; 242 + } 243 + 244 + static int param_set_ac_online(const char *key, const struct kernel_param *kp) 245 + { 246 + ac_online = map_get_value(map_ac_online, key, ac_online); 247 + power_supply_changed(&test_power_supplies[0]); 248 + return 0; 249 + } 250 + 251 + static int param_get_ac_online(char *buffer, const struct kernel_param *kp) 252 + { 253 + strcpy(buffer, map_get_key(map_ac_online, ac_online, "unknown")); 254 + return strlen(buffer); 255 + } 256 + 257 + static int param_set_battery_status(const char *key, 258 + const struct kernel_param *kp) 259 + { 260 + battery_status = map_get_value(map_status, key, battery_status); 261 + power_supply_changed(&test_power_supplies[1]); 262 + return 0; 263 + } 264 + 265 + static int param_get_battery_status(char *buffer, const struct kernel_param *kp) 266 + { 267 + strcpy(buffer, map_get_key(map_status, battery_status, "unknown")); 268 + return strlen(buffer); 269 + } 270 + 271 + static int param_set_battery_health(const char *key, 272 + const struct kernel_param *kp) 273 + { 274 + battery_health = map_get_value(map_health, key, battery_health); 275 + power_supply_changed(&test_power_supplies[1]); 276 + return 0; 277 + } 278 + 279 + static int param_get_battery_health(char *buffer, const struct kernel_param *kp) 280 + { 281 + strcpy(buffer, map_get_key(map_health, battery_health, "unknown")); 282 + return strlen(buffer); 283 + } 284 + 285 + static int param_set_battery_present(const char *key, 286 + const struct kernel_param *kp) 287 + { 288 + battery_present = map_get_value(map_present, key, battery_present); 289 + power_supply_changed(&test_power_supplies[0]); 290 + return 0; 291 + } 292 + 293 + static int param_get_battery_present(char *buffer, 294 + const struct kernel_param *kp) 295 + { 296 + strcpy(buffer, map_get_key(map_present, battery_present, "unknown")); 297 + return strlen(buffer); 298 + } 299 + 300 + static int param_set_battery_technology(const char *key, 301 + const struct kernel_param *kp) 302 + { 303 + battery_technology = map_get_value(map_technology, key, 304 + battery_technology); 305 + power_supply_changed(&test_power_supplies[1]); 306 + return 0; 307 + } 308 + 309 + static int param_get_battery_technology(char *buffer, 310 + const struct kernel_param *kp) 311 + { 312 + strcpy(buffer, 313 + map_get_key(map_technology, battery_technology, "unknown")); 314 + return strlen(buffer); 315 + } 316 + 317 + static int param_set_battery_capacity(const char *key, 318 + const struct kernel_param *kp) 319 + { 320 + int tmp; 321 + 322 + if (1 != sscanf(key, "%d", &tmp)) 323 + return -EINVAL; 324 + 325 + battery_capacity = tmp; 326 + power_supply_changed(&test_power_supplies[1]); 327 + return 0; 328 + } 329 + 330 + #define param_get_battery_capacity param_get_int 331 + 332 + 333 + 334 + static struct kernel_param_ops param_ops_ac_online = { 335 + .set = param_set_ac_online, 336 + .get = param_get_ac_online, 337 + }; 338 + 339 + static struct kernel_param_ops param_ops_battery_status = { 340 + .set = param_set_battery_status, 341 + .get = param_get_battery_status, 342 + }; 343 + 344 + static struct kernel_param_ops param_ops_battery_present = { 345 + .set = param_set_battery_present, 346 + .get = param_get_battery_present, 347 + }; 348 + 349 + static struct kernel_param_ops param_ops_battery_technology = { 350 + .set = param_set_battery_technology, 351 + .get = param_get_battery_technology, 352 + }; 353 + 354 + static struct kernel_param_ops param_ops_battery_health = { 355 + .set = param_set_battery_health, 356 + .get = param_get_battery_health, 357 + }; 358 + 359 + static struct kernel_param_ops param_ops_battery_capacity = { 360 + .set = param_set_battery_capacity, 361 + .get = param_get_battery_capacity, 362 + }; 363 + 364 + 365 + #define param_check_ac_online(name, p) __param_check(name, p, void); 366 + #define param_check_battery_status(name, p) __param_check(name, p, void); 367 + #define param_check_battery_present(name, p) __param_check(name, p, void); 368 + #define param_check_battery_technology(name, p) __param_check(name, p, void); 369 + #define param_check_battery_health(name, p) __param_check(name, p, void); 370 + #define param_check_battery_capacity(name, p) __param_check(name, p, void); 371 + 372 + 373 + module_param(ac_online, ac_online, 0644); 374 + MODULE_PARM_DESC(ac_online, "AC charging state <on|off>"); 375 + 376 + module_param(battery_status, battery_status, 0644); 377 + MODULE_PARM_DESC(battery_status, 378 + "battery status <charging|discharging|not-charging|full>"); 379 + 380 + module_param(battery_present, battery_present, 0644); 381 + MODULE_PARM_DESC(battery_present, 382 + "battery presence state <good|overheat|dead|overvoltage|failure>"); 383 + 384 + module_param(battery_technology, battery_technology, 0644); 385 + MODULE_PARM_DESC(battery_technology, 386 + "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>"); 387 + 388 + module_param(battery_health, battery_health, 0644); 389 + MODULE_PARM_DESC(battery_health, 390 + "battery health state <good|overheat|dead|overvoltage|failure>"); 391 + 392 + module_param(battery_capacity, battery_capacity, 0644); 393 + MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); 394 + 181 395 182 396 MODULE_DESCRIPTION("Power supply driver for testing"); 183 397 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");