1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Power supply driver for testing. 4 * 5 * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com> 6 * 7 * Dynamic module parameter code from the Virtual Battery Driver 8 * Copyright (C) 2008 Pylone, Inc. 9 * By: Masashi YOKOTA <yokota@pylone.jp> 10 * Originally found here: 11 * http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/power_supply.h> 17 #include <linux/errno.h> 18 #include <linux/delay.h> 19 #include <generated/utsrelease.h> 20 21 enum test_power_id { 22 TEST_AC, 23 TEST_BATTERY, 24 TEST_USB, 25 TEST_POWER_NUM, 26 }; 27 28 static int ac_online = 1; 29 static int usb_online = 1; 30 static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 31 static int battery_health = POWER_SUPPLY_HEALTH_GOOD; 32 static int battery_present = 1; /* true */ 33 static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; 34 static int battery_capacity = 50; 35 static int battery_voltage = 3300; 36 static int battery_charge_counter = -1000; 37 static int battery_current = -1600; 38 39 static bool module_initialized; 40 41 static int test_power_get_ac_property(struct power_supply *psy, 42 enum power_supply_property psp, 43 union power_supply_propval *val) 44 { 45 switch (psp) { 46 case POWER_SUPPLY_PROP_ONLINE: 47 val->intval = ac_online; 48 break; 49 default: 50 return -EINVAL; 51 } 52 return 0; 53 } 54 55 static int test_power_get_usb_property(struct power_supply *psy, 56 enum power_supply_property psp, 57 union power_supply_propval *val) 58 { 59 switch (psp) { 60 case POWER_SUPPLY_PROP_ONLINE: 61 val->intval = usb_online; 62 break; 63 default: 64 return -EINVAL; 65 } 66 return 0; 67 } 68 69 static int test_power_get_battery_property(struct power_supply *psy, 70 enum power_supply_property psp, 71 union power_supply_propval *val) 72 { 73 switch (psp) { 74 case POWER_SUPPLY_PROP_MODEL_NAME: 75 val->strval = "Test battery"; 76 break; 77 case POWER_SUPPLY_PROP_MANUFACTURER: 78 val->strval = "Linux"; 79 break; 80 case POWER_SUPPLY_PROP_SERIAL_NUMBER: 81 val->strval = UTS_RELEASE; 82 break; 83 case POWER_SUPPLY_PROP_STATUS: 84 val->intval = battery_status; 85 break; 86 case POWER_SUPPLY_PROP_CHARGE_TYPE: 87 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 88 break; 89 case POWER_SUPPLY_PROP_HEALTH: 90 val->intval = battery_health; 91 break; 92 case POWER_SUPPLY_PROP_PRESENT: 93 val->intval = battery_present; 94 break; 95 case POWER_SUPPLY_PROP_TECHNOLOGY: 96 val->intval = battery_technology; 97 break; 98 case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 99 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 100 break; 101 case POWER_SUPPLY_PROP_CAPACITY: 102 case POWER_SUPPLY_PROP_CHARGE_NOW: 103 val->intval = battery_capacity; 104 break; 105 case POWER_SUPPLY_PROP_CHARGE_COUNTER: 106 val->intval = battery_charge_counter; 107 break; 108 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 109 case POWER_SUPPLY_PROP_CHARGE_FULL: 110 val->intval = 100; 111 break; 112 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 113 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: 114 val->intval = 3600; 115 break; 116 case POWER_SUPPLY_PROP_TEMP: 117 val->intval = 26; 118 break; 119 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 120 val->intval = battery_voltage; 121 break; 122 case POWER_SUPPLY_PROP_CURRENT_AVG: 123 case POWER_SUPPLY_PROP_CURRENT_NOW: 124 val->intval = battery_current; 125 break; 126 default: 127 pr_info("%s: some properties deliberately report errors.\n", 128 __func__); 129 return -EINVAL; 130 } 131 return 0; 132 } 133 134 static enum power_supply_property test_power_ac_props[] = { 135 POWER_SUPPLY_PROP_ONLINE, 136 }; 137 138 static enum power_supply_property test_power_battery_props[] = { 139 POWER_SUPPLY_PROP_STATUS, 140 POWER_SUPPLY_PROP_CHARGE_TYPE, 141 POWER_SUPPLY_PROP_HEALTH, 142 POWER_SUPPLY_PROP_PRESENT, 143 POWER_SUPPLY_PROP_TECHNOLOGY, 144 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 145 POWER_SUPPLY_PROP_CHARGE_FULL, 146 POWER_SUPPLY_PROP_CHARGE_NOW, 147 POWER_SUPPLY_PROP_CHARGE_COUNTER, 148 POWER_SUPPLY_PROP_CAPACITY, 149 POWER_SUPPLY_PROP_CAPACITY_LEVEL, 150 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 151 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 152 POWER_SUPPLY_PROP_MODEL_NAME, 153 POWER_SUPPLY_PROP_MANUFACTURER, 154 POWER_SUPPLY_PROP_SERIAL_NUMBER, 155 POWER_SUPPLY_PROP_TEMP, 156 POWER_SUPPLY_PROP_VOLTAGE_NOW, 157 POWER_SUPPLY_PROP_CURRENT_AVG, 158 POWER_SUPPLY_PROP_CURRENT_NOW, 159 }; 160 161 static char *test_power_ac_supplied_to[] = { 162 "test_battery", 163 }; 164 165 static struct power_supply *test_power_supplies[TEST_POWER_NUM]; 166 167 static const struct power_supply_desc test_power_desc[] = { 168 [TEST_AC] = { 169 .name = "test_ac", 170 .type = POWER_SUPPLY_TYPE_MAINS, 171 .properties = test_power_ac_props, 172 .num_properties = ARRAY_SIZE(test_power_ac_props), 173 .get_property = test_power_get_ac_property, 174 }, 175 [TEST_BATTERY] = { 176 .name = "test_battery", 177 .type = POWER_SUPPLY_TYPE_BATTERY, 178 .properties = test_power_battery_props, 179 .num_properties = ARRAY_SIZE(test_power_battery_props), 180 .get_property = test_power_get_battery_property, 181 }, 182 [TEST_USB] = { 183 .name = "test_usb", 184 .type = POWER_SUPPLY_TYPE_USB, 185 .properties = test_power_ac_props, 186 .num_properties = ARRAY_SIZE(test_power_ac_props), 187 .get_property = test_power_get_usb_property, 188 }, 189 }; 190 191 static const struct power_supply_config test_power_configs[] = { 192 { 193 /* test_ac */ 194 .supplied_to = test_power_ac_supplied_to, 195 .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to), 196 }, { 197 /* test_battery */ 198 }, { 199 /* test_usb */ 200 .supplied_to = test_power_ac_supplied_to, 201 .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to), 202 }, 203 }; 204 205 static int __init test_power_init(void) 206 { 207 int i; 208 int ret; 209 210 BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_supplies)); 211 BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_configs)); 212 213 for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) { 214 test_power_supplies[i] = power_supply_register(NULL, 215 &test_power_desc[i], 216 &test_power_configs[i]); 217 if (IS_ERR(test_power_supplies[i])) { 218 pr_err("%s: failed to register %s\n", __func__, 219 test_power_desc[i].name); 220 ret = PTR_ERR(test_power_supplies[i]); 221 goto failed; 222 } 223 } 224 225 module_initialized = true; 226 return 0; 227 failed: 228 while (--i >= 0) 229 power_supply_unregister(test_power_supplies[i]); 230 return ret; 231 } 232 module_init(test_power_init); 233 234 static void __exit test_power_exit(void) 235 { 236 int i; 237 238 /* Let's see how we handle changes... */ 239 ac_online = 0; 240 usb_online = 0; 241 battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 242 for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) 243 power_supply_changed(test_power_supplies[i]); 244 pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n", 245 __func__); 246 ssleep(10); 247 248 for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) 249 power_supply_unregister(test_power_supplies[i]); 250 251 module_initialized = false; 252 } 253 module_exit(test_power_exit); 254 255 256 257 #define MAX_KEYLENGTH 256 258 struct battery_property_map { 259 int value; 260 char const *key; 261 }; 262 263 static struct battery_property_map map_ac_online[] = { 264 { 0, "off" }, 265 { 1, "on" }, 266 { -1, NULL }, 267 }; 268 269 static struct battery_property_map map_status[] = { 270 { POWER_SUPPLY_STATUS_CHARGING, "charging" }, 271 { POWER_SUPPLY_STATUS_DISCHARGING, "discharging" }, 272 { POWER_SUPPLY_STATUS_NOT_CHARGING, "not-charging" }, 273 { POWER_SUPPLY_STATUS_FULL, "full" }, 274 { -1, NULL }, 275 }; 276 277 static struct battery_property_map map_health[] = { 278 { POWER_SUPPLY_HEALTH_GOOD, "good" }, 279 { POWER_SUPPLY_HEALTH_OVERHEAT, "overheat" }, 280 { POWER_SUPPLY_HEALTH_DEAD, "dead" }, 281 { POWER_SUPPLY_HEALTH_OVERVOLTAGE, "overvoltage" }, 282 { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, "failure" }, 283 { -1, NULL }, 284 }; 285 286 static struct battery_property_map map_present[] = { 287 { 0, "false" }, 288 { 1, "true" }, 289 { -1, NULL }, 290 }; 291 292 static struct battery_property_map map_technology[] = { 293 { POWER_SUPPLY_TECHNOLOGY_NiMH, "NiMH" }, 294 { POWER_SUPPLY_TECHNOLOGY_LION, "LION" }, 295 { POWER_SUPPLY_TECHNOLOGY_LIPO, "LIPO" }, 296 { POWER_SUPPLY_TECHNOLOGY_LiFe, "LiFe" }, 297 { POWER_SUPPLY_TECHNOLOGY_NiCd, "NiCd" }, 298 { POWER_SUPPLY_TECHNOLOGY_LiMn, "LiMn" }, 299 { -1, NULL }, 300 }; 301 302 303 static int map_get_value(struct battery_property_map *map, const char *key, 304 int def_val) 305 { 306 char buf[MAX_KEYLENGTH]; 307 int cr; 308 309 strncpy(buf, key, MAX_KEYLENGTH); 310 buf[MAX_KEYLENGTH-1] = '\0'; 311 312 cr = strnlen(buf, MAX_KEYLENGTH) - 1; 313 if (cr < 0) 314 return def_val; 315 if (buf[cr] == '\n') 316 buf[cr] = '\0'; 317 318 while (map->key) { 319 if (strncasecmp(map->key, buf, MAX_KEYLENGTH) == 0) 320 return map->value; 321 map++; 322 } 323 324 return def_val; 325 } 326 327 328 static const char *map_get_key(struct battery_property_map *map, int value, 329 const char *def_key) 330 { 331 while (map->key) { 332 if (map->value == value) 333 return map->key; 334 map++; 335 } 336 337 return def_key; 338 } 339 340 static inline void signal_power_supply_changed(struct power_supply *psy) 341 { 342 if (module_initialized) 343 power_supply_changed(psy); 344 } 345 346 static int param_set_ac_online(const char *key, const struct kernel_param *kp) 347 { 348 ac_online = map_get_value(map_ac_online, key, ac_online); 349 signal_power_supply_changed(test_power_supplies[TEST_AC]); 350 return 0; 351 } 352 353 static int param_get_ac_online(char *buffer, const struct kernel_param *kp) 354 { 355 return sprintf(buffer, "%s\n", 356 map_get_key(map_ac_online, ac_online, "unknown")); 357 } 358 359 static int param_set_usb_online(const char *key, const struct kernel_param *kp) 360 { 361 usb_online = map_get_value(map_ac_online, key, usb_online); 362 signal_power_supply_changed(test_power_supplies[TEST_USB]); 363 return 0; 364 } 365 366 static int param_get_usb_online(char *buffer, const struct kernel_param *kp) 367 { 368 return sprintf(buffer, "%s\n", 369 map_get_key(map_ac_online, usb_online, "unknown")); 370 } 371 372 static int param_set_battery_status(const char *key, 373 const struct kernel_param *kp) 374 { 375 battery_status = map_get_value(map_status, key, battery_status); 376 signal_power_supply_changed(test_power_supplies[TEST_BATTERY]); 377 return 0; 378 } 379 380 static int param_get_battery_status(char *buffer, const struct kernel_param *kp) 381 { 382 return sprintf(buffer, "%s\n", 383 map_get_key(map_ac_online, battery_status, "unknown")); 384 } 385 386 static int param_set_battery_health(const char *key, 387 const struct kernel_param *kp) 388 { 389 battery_health = map_get_value(map_health, key, battery_health); 390 signal_power_supply_changed(test_power_supplies[TEST_BATTERY]); 391 return 0; 392 } 393 394 static int param_get_battery_health(char *buffer, const struct kernel_param *kp) 395 { 396 return sprintf(buffer, "%s\n", 397 map_get_key(map_ac_online, battery_health, "unknown")); 398 } 399 400 static int param_set_battery_present(const char *key, 401 const struct kernel_param *kp) 402 { 403 battery_present = map_get_value(map_present, key, battery_present); 404 signal_power_supply_changed(test_power_supplies[TEST_AC]); 405 return 0; 406 } 407 408 static int param_get_battery_present(char *buffer, 409 const struct kernel_param *kp) 410 { 411 return sprintf(buffer, "%s\n", 412 map_get_key(map_ac_online, battery_present, "unknown")); 413 } 414 415 static int param_set_battery_technology(const char *key, 416 const struct kernel_param *kp) 417 { 418 battery_technology = map_get_value(map_technology, key, 419 battery_technology); 420 signal_power_supply_changed(test_power_supplies[TEST_BATTERY]); 421 return 0; 422 } 423 424 static int param_get_battery_technology(char *buffer, 425 const struct kernel_param *kp) 426 { 427 return sprintf(buffer, "%s\n", 428 map_get_key(map_ac_online, battery_technology, 429 "unknown")); 430 } 431 432 static int param_set_battery_capacity(const char *key, 433 const struct kernel_param *kp) 434 { 435 int tmp; 436 437 if (1 != sscanf(key, "%d", &tmp)) 438 return -EINVAL; 439 440 battery_capacity = tmp; 441 signal_power_supply_changed(test_power_supplies[TEST_BATTERY]); 442 return 0; 443 } 444 445 #define param_get_battery_capacity param_get_int 446 447 static int param_set_battery_voltage(const char *key, 448 const struct kernel_param *kp) 449 { 450 int tmp; 451 452 if (1 != sscanf(key, "%d", &tmp)) 453 return -EINVAL; 454 455 battery_voltage = tmp; 456 signal_power_supply_changed(test_power_supplies[TEST_BATTERY]); 457 return 0; 458 } 459 460 #define param_get_battery_voltage param_get_int 461 462 static int param_set_battery_charge_counter(const char *key, 463 const struct kernel_param *kp) 464 { 465 int tmp; 466 467 if (1 != sscanf(key, "%d", &tmp)) 468 return -EINVAL; 469 470 battery_charge_counter = tmp; 471 signal_power_supply_changed(test_power_supplies[TEST_BATTERY]); 472 return 0; 473 } 474 475 #define param_get_battery_charge_counter param_get_int 476 477 static int param_set_battery_current(const char *key, 478 const struct kernel_param *kp) 479 { 480 int tmp; 481 482 if (1 != sscanf(key, "%d", &tmp)) 483 return -EINVAL; 484 485 battery_current = tmp; 486 signal_power_supply_changed(test_power_supplies[TEST_BATTERY]); 487 return 0; 488 } 489 490 #define param_get_battery_current param_get_int 491 492 static const struct kernel_param_ops param_ops_ac_online = { 493 .set = param_set_ac_online, 494 .get = param_get_ac_online, 495 }; 496 497 static const struct kernel_param_ops param_ops_usb_online = { 498 .set = param_set_usb_online, 499 .get = param_get_usb_online, 500 }; 501 502 static const struct kernel_param_ops param_ops_battery_status = { 503 .set = param_set_battery_status, 504 .get = param_get_battery_status, 505 }; 506 507 static const struct kernel_param_ops param_ops_battery_present = { 508 .set = param_set_battery_present, 509 .get = param_get_battery_present, 510 }; 511 512 static const struct kernel_param_ops param_ops_battery_technology = { 513 .set = param_set_battery_technology, 514 .get = param_get_battery_technology, 515 }; 516 517 static const struct kernel_param_ops param_ops_battery_health = { 518 .set = param_set_battery_health, 519 .get = param_get_battery_health, 520 }; 521 522 static const struct kernel_param_ops param_ops_battery_capacity = { 523 .set = param_set_battery_capacity, 524 .get = param_get_battery_capacity, 525 }; 526 527 static const struct kernel_param_ops param_ops_battery_voltage = { 528 .set = param_set_battery_voltage, 529 .get = param_get_battery_voltage, 530 }; 531 532 static const struct kernel_param_ops param_ops_battery_charge_counter = { 533 .set = param_set_battery_charge_counter, 534 .get = param_get_battery_charge_counter, 535 }; 536 537 static const struct kernel_param_ops param_ops_battery_current = { 538 .set = param_set_battery_current, 539 .get = param_get_battery_current, 540 }; 541 542 #define param_check_ac_online(name, p) __param_check(name, p, void); 543 #define param_check_usb_online(name, p) __param_check(name, p, void); 544 #define param_check_battery_status(name, p) __param_check(name, p, void); 545 #define param_check_battery_present(name, p) __param_check(name, p, void); 546 #define param_check_battery_technology(name, p) __param_check(name, p, void); 547 #define param_check_battery_health(name, p) __param_check(name, p, void); 548 #define param_check_battery_capacity(name, p) __param_check(name, p, void); 549 #define param_check_battery_voltage(name, p) __param_check(name, p, void); 550 #define param_check_battery_charge_counter(name, p) __param_check(name, p, void); 551 #define param_check_battery_current(name, p) __param_check(name, p, void); 552 553 554 module_param(ac_online, ac_online, 0644); 555 MODULE_PARM_DESC(ac_online, "AC charging state <on|off>"); 556 557 module_param(usb_online, usb_online, 0644); 558 MODULE_PARM_DESC(usb_online, "USB charging state <on|off>"); 559 560 module_param(battery_status, battery_status, 0644); 561 MODULE_PARM_DESC(battery_status, 562 "battery status <charging|discharging|not-charging|full>"); 563 564 module_param(battery_present, battery_present, 0644); 565 MODULE_PARM_DESC(battery_present, 566 "battery presence state <good|overheat|dead|overvoltage|failure>"); 567 568 module_param(battery_technology, battery_technology, 0644); 569 MODULE_PARM_DESC(battery_technology, 570 "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>"); 571 572 module_param(battery_health, battery_health, 0644); 573 MODULE_PARM_DESC(battery_health, 574 "battery health state <good|overheat|dead|overvoltage|failure>"); 575 576 module_param(battery_capacity, battery_capacity, 0644); 577 MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); 578 579 module_param(battery_voltage, battery_voltage, 0644); 580 MODULE_PARM_DESC(battery_voltage, "battery voltage (millivolts)"); 581 582 module_param(battery_charge_counter, battery_charge_counter, 0644); 583 MODULE_PARM_DESC(battery_charge_counter, 584 "battery charge counter (microampere-hours)"); 585 586 module_param(battery_current, battery_current, 0644); 587 MODULE_PARM_DESC(battery_current, "battery current (milliampere)"); 588 589 MODULE_DESCRIPTION("Power supply driver for testing"); 590 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); 591 MODULE_LICENSE("GPL"); 592