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