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