1 // SPDX-License-Identifier: GPL-2.0-only
3 * Power supply driver for testing.
5 * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com>
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
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>
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;
39 static bool module_initialized
;
41 static int test_power_get_ac_property(struct power_supply
*psy
,
42 enum power_supply_property psp
,
43 union power_supply_propval
*val
)
46 case POWER_SUPPLY_PROP_ONLINE
:
47 val
->intval
= ac_online
;
55 static int test_power_get_usb_property(struct power_supply
*psy
,
56 enum power_supply_property psp
,
57 union power_supply_propval
*val
)
60 case POWER_SUPPLY_PROP_ONLINE
:
61 val
->intval
= usb_online
;
69 static int test_power_get_battery_property(struct power_supply
*psy
,
70 enum power_supply_property psp
,
71 union power_supply_propval
*val
)
74 case POWER_SUPPLY_PROP_MODEL_NAME
:
75 val
->strval
= "Test battery";
77 case POWER_SUPPLY_PROP_MANUFACTURER
:
78 val
->strval
= "Linux";
80 case POWER_SUPPLY_PROP_SERIAL_NUMBER
:
81 val
->strval
= UTS_RELEASE
;
83 case POWER_SUPPLY_PROP_STATUS
:
84 val
->intval
= battery_status
;
86 case POWER_SUPPLY_PROP_CHARGE_TYPE
:
87 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_FAST
;
89 case POWER_SUPPLY_PROP_HEALTH
:
90 val
->intval
= battery_health
;
92 case POWER_SUPPLY_PROP_PRESENT
:
93 val
->intval
= battery_present
;
95 case POWER_SUPPLY_PROP_TECHNOLOGY
:
96 val
->intval
= battery_technology
;
98 case POWER_SUPPLY_PROP_CAPACITY_LEVEL
:
99 val
->intval
= POWER_SUPPLY_CAPACITY_LEVEL_NORMAL
;
101 case POWER_SUPPLY_PROP_CAPACITY
:
102 case POWER_SUPPLY_PROP_CHARGE_NOW
:
103 val
->intval
= battery_capacity
;
105 case POWER_SUPPLY_PROP_CHARGE_COUNTER
:
106 val
->intval
= battery_charge_counter
;
108 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
:
109 case POWER_SUPPLY_PROP_CHARGE_FULL
:
112 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG
:
113 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW
:
116 case POWER_SUPPLY_PROP_TEMP
:
119 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
120 val
->intval
= battery_voltage
;
122 case POWER_SUPPLY_PROP_CURRENT_AVG
:
123 case POWER_SUPPLY_PROP_CURRENT_NOW
:
124 val
->intval
= battery_current
;
127 pr_info("%s: some properties deliberately report errors.\n",
134 static enum power_supply_property test_power_ac_props
[] = {
135 POWER_SUPPLY_PROP_ONLINE
,
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
,
161 static char *test_power_ac_supplied_to
[] = {
165 static struct power_supply
*test_power_supplies
[TEST_POWER_NUM
];
167 static const struct power_supply_desc test_power_desc
[] = {
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
,
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
,
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
,
191 static const struct power_supply_config test_power_configs
[] = {
194 .supplied_to
= test_power_ac_supplied_to
,
195 .num_supplicants
= ARRAY_SIZE(test_power_ac_supplied_to
),
200 .supplied_to
= test_power_ac_supplied_to
,
201 .num_supplicants
= ARRAY_SIZE(test_power_ac_supplied_to
),
205 static int __init
test_power_init(void)
210 BUILD_BUG_ON(TEST_POWER_NUM
!= ARRAY_SIZE(test_power_supplies
));
211 BUILD_BUG_ON(TEST_POWER_NUM
!= ARRAY_SIZE(test_power_configs
));
213 for (i
= 0; i
< ARRAY_SIZE(test_power_supplies
); i
++) {
214 test_power_supplies
[i
] = power_supply_register(NULL
,
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
]);
225 module_initialized
= true;
229 power_supply_unregister(test_power_supplies
[i
]);
232 module_init(test_power_init
);
234 static void __exit
test_power_exit(void)
238 /* Let's see how we handle changes... */
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",
248 for (i
= 0; i
< ARRAY_SIZE(test_power_supplies
); i
++)
249 power_supply_unregister(test_power_supplies
[i
]);
251 module_initialized
= false;
253 module_exit(test_power_exit
);
257 #define MAX_KEYLENGTH 256
258 struct battery_property_map
{
263 static struct battery_property_map map_ac_online
[] = {
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" },
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" },
286 static struct battery_property_map map_present
[] = {
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" },
303 static int map_get_value(struct battery_property_map
*map
, const char *key
,
306 char buf
[MAX_KEYLENGTH
];
309 strncpy(buf
, key
, MAX_KEYLENGTH
);
310 buf
[MAX_KEYLENGTH
-1] = '\0';
312 cr
= strnlen(buf
, MAX_KEYLENGTH
) - 1;
319 if (strncasecmp(map
->key
, buf
, MAX_KEYLENGTH
) == 0)
328 static const char *map_get_key(struct battery_property_map
*map
, int value
,
332 if (map
->value
== value
)
340 static inline void signal_power_supply_changed(struct power_supply
*psy
)
342 if (module_initialized
)
343 power_supply_changed(psy
);
346 static int param_set_ac_online(const char *key
, const struct kernel_param
*kp
)
348 ac_online
= map_get_value(map_ac_online
, key
, ac_online
);
349 signal_power_supply_changed(test_power_supplies
[TEST_AC
]);
353 static int param_get_ac_online(char *buffer
, const struct kernel_param
*kp
)
355 return sprintf(buffer
, "%s\n",
356 map_get_key(map_ac_online
, ac_online
, "unknown"));
359 static int param_set_usb_online(const char *key
, const struct kernel_param
*kp
)
361 usb_online
= map_get_value(map_ac_online
, key
, usb_online
);
362 signal_power_supply_changed(test_power_supplies
[TEST_USB
]);
366 static int param_get_usb_online(char *buffer
, const struct kernel_param
*kp
)
368 return sprintf(buffer
, "%s\n",
369 map_get_key(map_ac_online
, usb_online
, "unknown"));
372 static int param_set_battery_status(const char *key
,
373 const struct kernel_param
*kp
)
375 battery_status
= map_get_value(map_status
, key
, battery_status
);
376 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
380 static int param_get_battery_status(char *buffer
, const struct kernel_param
*kp
)
382 return sprintf(buffer
, "%s\n",
383 map_get_key(map_ac_online
, battery_status
, "unknown"));
386 static int param_set_battery_health(const char *key
,
387 const struct kernel_param
*kp
)
389 battery_health
= map_get_value(map_health
, key
, battery_health
);
390 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
394 static int param_get_battery_health(char *buffer
, const struct kernel_param
*kp
)
396 return sprintf(buffer
, "%s\n",
397 map_get_key(map_ac_online
, battery_health
, "unknown"));
400 static int param_set_battery_present(const char *key
,
401 const struct kernel_param
*kp
)
403 battery_present
= map_get_value(map_present
, key
, battery_present
);
404 signal_power_supply_changed(test_power_supplies
[TEST_AC
]);
408 static int param_get_battery_present(char *buffer
,
409 const struct kernel_param
*kp
)
411 return sprintf(buffer
, "%s\n",
412 map_get_key(map_ac_online
, battery_present
, "unknown"));
415 static int param_set_battery_technology(const char *key
,
416 const struct kernel_param
*kp
)
418 battery_technology
= map_get_value(map_technology
, key
,
420 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
424 static int param_get_battery_technology(char *buffer
,
425 const struct kernel_param
*kp
)
427 return sprintf(buffer
, "%s\n",
428 map_get_key(map_ac_online
, battery_technology
,
432 static int param_set_battery_capacity(const char *key
,
433 const struct kernel_param
*kp
)
437 if (1 != sscanf(key
, "%d", &tmp
))
440 battery_capacity
= tmp
;
441 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
445 #define param_get_battery_capacity param_get_int
447 static int param_set_battery_voltage(const char *key
,
448 const struct kernel_param
*kp
)
452 if (1 != sscanf(key
, "%d", &tmp
))
455 battery_voltage
= tmp
;
456 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
460 #define param_get_battery_voltage param_get_int
462 static int param_set_battery_charge_counter(const char *key
,
463 const struct kernel_param
*kp
)
467 if (1 != sscanf(key
, "%d", &tmp
))
470 battery_charge_counter
= tmp
;
471 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
475 #define param_get_battery_charge_counter param_get_int
477 static int param_set_battery_current(const char *key
,
478 const struct kernel_param
*kp
)
482 if (1 != sscanf(key
, "%d", &tmp
))
485 battery_current
= tmp
;
486 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
490 #define param_get_battery_current param_get_int
492 static const struct kernel_param_ops param_ops_ac_online
= {
493 .set
= param_set_ac_online
,
494 .get
= param_get_ac_online
,
497 static const struct kernel_param_ops param_ops_usb_online
= {
498 .set
= param_set_usb_online
,
499 .get
= param_get_usb_online
,
502 static const struct kernel_param_ops param_ops_battery_status
= {
503 .set
= param_set_battery_status
,
504 .get
= param_get_battery_status
,
507 static const struct kernel_param_ops param_ops_battery_present
= {
508 .set
= param_set_battery_present
,
509 .get
= param_get_battery_present
,
512 static const struct kernel_param_ops param_ops_battery_technology
= {
513 .set
= param_set_battery_technology
,
514 .get
= param_get_battery_technology
,
517 static const struct kernel_param_ops param_ops_battery_health
= {
518 .set
= param_set_battery_health
,
519 .get
= param_get_battery_health
,
522 static const struct kernel_param_ops param_ops_battery_capacity
= {
523 .set
= param_set_battery_capacity
,
524 .get
= param_get_battery_capacity
,
527 static const struct kernel_param_ops param_ops_battery_voltage
= {
528 .set
= param_set_battery_voltage
,
529 .get
= param_get_battery_voltage
,
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
,
537 static const struct kernel_param_ops param_ops_battery_current
= {
538 .set
= param_set_battery_current
,
539 .get
= param_get_battery_current
,
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);
554 module_param(ac_online
, ac_online
, 0644);
555 MODULE_PARM_DESC(ac_online
, "AC charging state <on|off>");
557 module_param(usb_online
, usb_online
, 0644);
558 MODULE_PARM_DESC(usb_online
, "USB charging state <on|off>");
560 module_param(battery_status
, battery_status
, 0644);
561 MODULE_PARM_DESC(battery_status
,
562 "battery status <charging|discharging|not-charging|full>");
564 module_param(battery_present
, battery_present
, 0644);
565 MODULE_PARM_DESC(battery_present
,
566 "battery presence state <good|overheat|dead|overvoltage|failure>");
568 module_param(battery_technology
, battery_technology
, 0644);
569 MODULE_PARM_DESC(battery_technology
,
570 "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>");
572 module_param(battery_health
, battery_health
, 0644);
573 MODULE_PARM_DESC(battery_health
,
574 "battery health state <good|overheat|dead|overvoltage|failure>");
576 module_param(battery_capacity
, battery_capacity
, 0644);
577 MODULE_PARM_DESC(battery_capacity
, "battery capacity (percentage)");
579 module_param(battery_voltage
, battery_voltage
, 0644);
580 MODULE_PARM_DESC(battery_voltage
, "battery voltage (millivolts)");
582 module_param(battery_charge_counter
, battery_charge_counter
, 0644);
583 MODULE_PARM_DESC(battery_charge_counter
,
584 "battery charge counter (microampere-hours)");
586 module_param(battery_current
, battery_current
, 0644);
587 MODULE_PARM_DESC(battery_current
, "battery current (milliampere)");
589 MODULE_DESCRIPTION("Power supply driver for testing");
590 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
591 MODULE_LICENSE("GPL");