2 * Power supply driver for testing.
4 * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com>
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
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/power_supply.h>
20 #include <linux/errno.h>
21 #include <linux/delay.h>
22 #include <linux/vermagic.h>
31 static int ac_online
= 1;
32 static int usb_online
= 1;
33 static int battery_status
= POWER_SUPPLY_STATUS_DISCHARGING
;
34 static int battery_health
= POWER_SUPPLY_HEALTH_GOOD
;
35 static int battery_present
= 1; /* true */
36 static int battery_technology
= POWER_SUPPLY_TECHNOLOGY_LION
;
37 static int battery_capacity
= 50;
38 static int battery_voltage
= 3300;
40 static bool module_initialized
;
42 static int test_power_get_ac_property(struct power_supply
*psy
,
43 enum power_supply_property psp
,
44 union power_supply_propval
*val
)
47 case POWER_SUPPLY_PROP_ONLINE
:
48 val
->intval
= ac_online
;
56 static int test_power_get_usb_property(struct power_supply
*psy
,
57 enum power_supply_property psp
,
58 union power_supply_propval
*val
)
61 case POWER_SUPPLY_PROP_ONLINE
:
62 val
->intval
= usb_online
;
70 static int test_power_get_battery_property(struct power_supply
*psy
,
71 enum power_supply_property psp
,
72 union power_supply_propval
*val
)
75 case POWER_SUPPLY_PROP_MODEL_NAME
:
76 val
->strval
= "Test battery";
78 case POWER_SUPPLY_PROP_MANUFACTURER
:
79 val
->strval
= "Linux";
81 case POWER_SUPPLY_PROP_SERIAL_NUMBER
:
82 val
->strval
= UTS_RELEASE
;
84 case POWER_SUPPLY_PROP_STATUS
:
85 val
->intval
= battery_status
;
87 case POWER_SUPPLY_PROP_CHARGE_TYPE
:
88 val
->intval
= POWER_SUPPLY_CHARGE_TYPE_FAST
;
90 case POWER_SUPPLY_PROP_HEALTH
:
91 val
->intval
= battery_health
;
93 case POWER_SUPPLY_PROP_PRESENT
:
94 val
->intval
= battery_present
;
96 case POWER_SUPPLY_PROP_TECHNOLOGY
:
97 val
->intval
= battery_technology
;
99 case POWER_SUPPLY_PROP_CAPACITY_LEVEL
:
100 val
->intval
= POWER_SUPPLY_CAPACITY_LEVEL_NORMAL
;
102 case POWER_SUPPLY_PROP_CAPACITY
:
103 case POWER_SUPPLY_PROP_CHARGE_NOW
:
104 val
->intval
= battery_capacity
;
106 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
:
107 case POWER_SUPPLY_PROP_CHARGE_FULL
:
110 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG
:
111 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW
:
114 case POWER_SUPPLY_PROP_TEMP
:
117 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
118 val
->intval
= battery_voltage
;
121 pr_info("%s: some properties deliberately report errors.\n",
128 static enum power_supply_property test_power_ac_props
[] = {
129 POWER_SUPPLY_PROP_ONLINE
,
132 static enum power_supply_property test_power_battery_props
[] = {
133 POWER_SUPPLY_PROP_STATUS
,
134 POWER_SUPPLY_PROP_CHARGE_TYPE
,
135 POWER_SUPPLY_PROP_HEALTH
,
136 POWER_SUPPLY_PROP_PRESENT
,
137 POWER_SUPPLY_PROP_TECHNOLOGY
,
138 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
,
139 POWER_SUPPLY_PROP_CHARGE_FULL
,
140 POWER_SUPPLY_PROP_CHARGE_NOW
,
141 POWER_SUPPLY_PROP_CAPACITY
,
142 POWER_SUPPLY_PROP_CAPACITY_LEVEL
,
143 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG
,
144 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW
,
145 POWER_SUPPLY_PROP_MODEL_NAME
,
146 POWER_SUPPLY_PROP_MANUFACTURER
,
147 POWER_SUPPLY_PROP_SERIAL_NUMBER
,
148 POWER_SUPPLY_PROP_TEMP
,
149 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
152 static char *test_power_ac_supplied_to
[] = {
156 static struct power_supply
*test_power_supplies
[TEST_POWER_NUM
];
158 static const struct power_supply_desc test_power_desc
[] = {
161 .type
= POWER_SUPPLY_TYPE_MAINS
,
162 .properties
= test_power_ac_props
,
163 .num_properties
= ARRAY_SIZE(test_power_ac_props
),
164 .get_property
= test_power_get_ac_property
,
167 .name
= "test_battery",
168 .type
= POWER_SUPPLY_TYPE_BATTERY
,
169 .properties
= test_power_battery_props
,
170 .num_properties
= ARRAY_SIZE(test_power_battery_props
),
171 .get_property
= test_power_get_battery_property
,
175 .type
= POWER_SUPPLY_TYPE_USB
,
176 .properties
= test_power_ac_props
,
177 .num_properties
= ARRAY_SIZE(test_power_ac_props
),
178 .get_property
= test_power_get_usb_property
,
182 static const struct power_supply_config test_power_configs
[] = {
185 .supplied_to
= test_power_ac_supplied_to
,
186 .num_supplicants
= ARRAY_SIZE(test_power_ac_supplied_to
),
191 .supplied_to
= test_power_ac_supplied_to
,
192 .num_supplicants
= ARRAY_SIZE(test_power_ac_supplied_to
),
196 static int __init
test_power_init(void)
201 BUILD_BUG_ON(TEST_POWER_NUM
!= ARRAY_SIZE(test_power_supplies
));
202 BUILD_BUG_ON(TEST_POWER_NUM
!= ARRAY_SIZE(test_power_configs
));
204 for (i
= 0; i
< ARRAY_SIZE(test_power_supplies
); i
++) {
205 test_power_supplies
[i
] = power_supply_register(NULL
,
207 &test_power_configs
[i
]);
208 if (IS_ERR(test_power_supplies
[i
])) {
209 pr_err("%s: failed to register %s\n", __func__
,
210 test_power_desc
[i
].name
);
211 ret
= PTR_ERR(test_power_supplies
[i
]);
216 module_initialized
= true;
220 power_supply_unregister(test_power_supplies
[i
]);
223 module_init(test_power_init
);
225 static void __exit
test_power_exit(void)
229 /* Let's see how we handle changes... */
232 battery_status
= POWER_SUPPLY_STATUS_DISCHARGING
;
233 for (i
= 0; i
< ARRAY_SIZE(test_power_supplies
); i
++)
234 power_supply_changed(test_power_supplies
[i
]);
235 pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n",
239 for (i
= 0; i
< ARRAY_SIZE(test_power_supplies
); i
++)
240 power_supply_unregister(test_power_supplies
[i
]);
242 module_initialized
= false;
244 module_exit(test_power_exit
);
248 #define MAX_KEYLENGTH 256
249 struct battery_property_map
{
254 static struct battery_property_map map_ac_online
[] = {
260 static struct battery_property_map map_status
[] = {
261 { POWER_SUPPLY_STATUS_CHARGING
, "charging" },
262 { POWER_SUPPLY_STATUS_DISCHARGING
, "discharging" },
263 { POWER_SUPPLY_STATUS_NOT_CHARGING
, "not-charging" },
264 { POWER_SUPPLY_STATUS_FULL
, "full" },
268 static struct battery_property_map map_health
[] = {
269 { POWER_SUPPLY_HEALTH_GOOD
, "good" },
270 { POWER_SUPPLY_HEALTH_OVERHEAT
, "overheat" },
271 { POWER_SUPPLY_HEALTH_DEAD
, "dead" },
272 { POWER_SUPPLY_HEALTH_OVERVOLTAGE
, "overvoltage" },
273 { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
, "failure" },
277 static struct battery_property_map map_present
[] = {
283 static struct battery_property_map map_technology
[] = {
284 { POWER_SUPPLY_TECHNOLOGY_NiMH
, "NiMH" },
285 { POWER_SUPPLY_TECHNOLOGY_LION
, "LION" },
286 { POWER_SUPPLY_TECHNOLOGY_LIPO
, "LIPO" },
287 { POWER_SUPPLY_TECHNOLOGY_LiFe
, "LiFe" },
288 { POWER_SUPPLY_TECHNOLOGY_NiCd
, "NiCd" },
289 { POWER_SUPPLY_TECHNOLOGY_LiMn
, "LiMn" },
294 static int map_get_value(struct battery_property_map
*map
, const char *key
,
297 char buf
[MAX_KEYLENGTH
];
300 strncpy(buf
, key
, MAX_KEYLENGTH
);
301 buf
[MAX_KEYLENGTH
-1] = '\0';
303 cr
= strnlen(buf
, MAX_KEYLENGTH
) - 1;
308 if (strncasecmp(map
->key
, buf
, MAX_KEYLENGTH
) == 0)
317 static const char *map_get_key(struct battery_property_map
*map
, int value
,
321 if (map
->value
== value
)
329 static inline void signal_power_supply_changed(struct power_supply
*psy
)
331 if (module_initialized
)
332 power_supply_changed(psy
);
335 static int param_set_ac_online(const char *key
, const struct kernel_param
*kp
)
337 ac_online
= map_get_value(map_ac_online
, key
, ac_online
);
338 signal_power_supply_changed(test_power_supplies
[TEST_AC
]);
342 static int param_get_ac_online(char *buffer
, const struct kernel_param
*kp
)
344 strcpy(buffer
, map_get_key(map_ac_online
, ac_online
, "unknown"));
345 return strlen(buffer
);
348 static int param_set_usb_online(const char *key
, const struct kernel_param
*kp
)
350 usb_online
= map_get_value(map_ac_online
, key
, usb_online
);
351 signal_power_supply_changed(test_power_supplies
[TEST_USB
]);
355 static int param_get_usb_online(char *buffer
, const struct kernel_param
*kp
)
357 strcpy(buffer
, map_get_key(map_ac_online
, usb_online
, "unknown"));
358 return strlen(buffer
);
361 static int param_set_battery_status(const char *key
,
362 const struct kernel_param
*kp
)
364 battery_status
= map_get_value(map_status
, key
, battery_status
);
365 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
369 static int param_get_battery_status(char *buffer
, const struct kernel_param
*kp
)
371 strcpy(buffer
, map_get_key(map_status
, battery_status
, "unknown"));
372 return strlen(buffer
);
375 static int param_set_battery_health(const char *key
,
376 const struct kernel_param
*kp
)
378 battery_health
= map_get_value(map_health
, key
, battery_health
);
379 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
383 static int param_get_battery_health(char *buffer
, const struct kernel_param
*kp
)
385 strcpy(buffer
, map_get_key(map_health
, battery_health
, "unknown"));
386 return strlen(buffer
);
389 static int param_set_battery_present(const char *key
,
390 const struct kernel_param
*kp
)
392 battery_present
= map_get_value(map_present
, key
, battery_present
);
393 signal_power_supply_changed(test_power_supplies
[TEST_AC
]);
397 static int param_get_battery_present(char *buffer
,
398 const struct kernel_param
*kp
)
400 strcpy(buffer
, map_get_key(map_present
, battery_present
, "unknown"));
401 return strlen(buffer
);
404 static int param_set_battery_technology(const char *key
,
405 const struct kernel_param
*kp
)
407 battery_technology
= map_get_value(map_technology
, key
,
409 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
413 static int param_get_battery_technology(char *buffer
,
414 const struct kernel_param
*kp
)
417 map_get_key(map_technology
, battery_technology
, "unknown"));
418 return strlen(buffer
);
421 static int param_set_battery_capacity(const char *key
,
422 const struct kernel_param
*kp
)
426 if (1 != sscanf(key
, "%d", &tmp
))
429 battery_capacity
= tmp
;
430 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
434 #define param_get_battery_capacity param_get_int
436 static int param_set_battery_voltage(const char *key
,
437 const struct kernel_param
*kp
)
441 if (1 != sscanf(key
, "%d", &tmp
))
444 battery_voltage
= tmp
;
445 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
449 #define param_get_battery_voltage param_get_int
451 static const struct kernel_param_ops param_ops_ac_online
= {
452 .set
= param_set_ac_online
,
453 .get
= param_get_ac_online
,
456 static const struct kernel_param_ops param_ops_usb_online
= {
457 .set
= param_set_usb_online
,
458 .get
= param_get_usb_online
,
461 static const struct kernel_param_ops param_ops_battery_status
= {
462 .set
= param_set_battery_status
,
463 .get
= param_get_battery_status
,
466 static const struct kernel_param_ops param_ops_battery_present
= {
467 .set
= param_set_battery_present
,
468 .get
= param_get_battery_present
,
471 static const struct kernel_param_ops param_ops_battery_technology
= {
472 .set
= param_set_battery_technology
,
473 .get
= param_get_battery_technology
,
476 static const struct kernel_param_ops param_ops_battery_health
= {
477 .set
= param_set_battery_health
,
478 .get
= param_get_battery_health
,
481 static const struct kernel_param_ops param_ops_battery_capacity
= {
482 .set
= param_set_battery_capacity
,
483 .get
= param_get_battery_capacity
,
486 static const struct kernel_param_ops param_ops_battery_voltage
= {
487 .set
= param_set_battery_voltage
,
488 .get
= param_get_battery_voltage
,
491 #define param_check_ac_online(name, p) __param_check(name, p, void);
492 #define param_check_usb_online(name, p) __param_check(name, p, void);
493 #define param_check_battery_status(name, p) __param_check(name, p, void);
494 #define param_check_battery_present(name, p) __param_check(name, p, void);
495 #define param_check_battery_technology(name, p) __param_check(name, p, void);
496 #define param_check_battery_health(name, p) __param_check(name, p, void);
497 #define param_check_battery_capacity(name, p) __param_check(name, p, void);
498 #define param_check_battery_voltage(name, p) __param_check(name, p, void);
501 module_param(ac_online
, ac_online
, 0644);
502 MODULE_PARM_DESC(ac_online
, "AC charging state <on|off>");
504 module_param(usb_online
, usb_online
, 0644);
505 MODULE_PARM_DESC(usb_online
, "USB charging state <on|off>");
507 module_param(battery_status
, battery_status
, 0644);
508 MODULE_PARM_DESC(battery_status
,
509 "battery status <charging|discharging|not-charging|full>");
511 module_param(battery_present
, battery_present
, 0644);
512 MODULE_PARM_DESC(battery_present
,
513 "battery presence state <good|overheat|dead|overvoltage|failure>");
515 module_param(battery_technology
, battery_technology
, 0644);
516 MODULE_PARM_DESC(battery_technology
,
517 "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>");
519 module_param(battery_health
, battery_health
, 0644);
520 MODULE_PARM_DESC(battery_health
,
521 "battery health state <good|overheat|dead|overvoltage|failure>");
523 module_param(battery_capacity
, battery_capacity
, 0644);
524 MODULE_PARM_DESC(battery_capacity
, "battery capacity (percentage)");
526 module_param(battery_voltage
, battery_voltage
, 0644);
527 MODULE_PARM_DESC(battery_voltage
, "battery voltage (millivolts)");
529 MODULE_DESCRIPTION("Power supply driver for testing");
530 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
531 MODULE_LICENSE("GPL");