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;
310 if (strncasecmp(map
->key
, buf
, MAX_KEYLENGTH
) == 0)
319 static const char *map_get_key(struct battery_property_map
*map
, int value
,
323 if (map
->value
== value
)
331 static inline void signal_power_supply_changed(struct power_supply
*psy
)
333 if (module_initialized
)
334 power_supply_changed(psy
);
337 static int param_set_ac_online(const char *key
, const struct kernel_param
*kp
)
339 ac_online
= map_get_value(map_ac_online
, key
, ac_online
);
340 signal_power_supply_changed(test_power_supplies
[TEST_AC
]);
344 static int param_get_ac_online(char *buffer
, const struct kernel_param
*kp
)
346 strcpy(buffer
, map_get_key(map_ac_online
, ac_online
, "unknown"));
347 return strlen(buffer
);
350 static int param_set_usb_online(const char *key
, const struct kernel_param
*kp
)
352 usb_online
= map_get_value(map_ac_online
, key
, usb_online
);
353 signal_power_supply_changed(test_power_supplies
[TEST_USB
]);
357 static int param_get_usb_online(char *buffer
, const struct kernel_param
*kp
)
359 strcpy(buffer
, map_get_key(map_ac_online
, usb_online
, "unknown"));
360 return strlen(buffer
);
363 static int param_set_battery_status(const char *key
,
364 const struct kernel_param
*kp
)
366 battery_status
= map_get_value(map_status
, key
, battery_status
);
367 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
371 static int param_get_battery_status(char *buffer
, const struct kernel_param
*kp
)
373 strcpy(buffer
, map_get_key(map_status
, battery_status
, "unknown"));
374 return strlen(buffer
);
377 static int param_set_battery_health(const char *key
,
378 const struct kernel_param
*kp
)
380 battery_health
= map_get_value(map_health
, key
, battery_health
);
381 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
385 static int param_get_battery_health(char *buffer
, const struct kernel_param
*kp
)
387 strcpy(buffer
, map_get_key(map_health
, battery_health
, "unknown"));
388 return strlen(buffer
);
391 static int param_set_battery_present(const char *key
,
392 const struct kernel_param
*kp
)
394 battery_present
= map_get_value(map_present
, key
, battery_present
);
395 signal_power_supply_changed(test_power_supplies
[TEST_AC
]);
399 static int param_get_battery_present(char *buffer
,
400 const struct kernel_param
*kp
)
402 strcpy(buffer
, map_get_key(map_present
, battery_present
, "unknown"));
403 return strlen(buffer
);
406 static int param_set_battery_technology(const char *key
,
407 const struct kernel_param
*kp
)
409 battery_technology
= map_get_value(map_technology
, key
,
411 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
415 static int param_get_battery_technology(char *buffer
,
416 const struct kernel_param
*kp
)
419 map_get_key(map_technology
, battery_technology
, "unknown"));
420 return strlen(buffer
);
423 static int param_set_battery_capacity(const char *key
,
424 const struct kernel_param
*kp
)
428 if (1 != sscanf(key
, "%d", &tmp
))
431 battery_capacity
= tmp
;
432 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
436 #define param_get_battery_capacity param_get_int
438 static int param_set_battery_voltage(const char *key
,
439 const struct kernel_param
*kp
)
443 if (1 != sscanf(key
, "%d", &tmp
))
446 battery_voltage
= tmp
;
447 signal_power_supply_changed(test_power_supplies
[TEST_BATTERY
]);
451 #define param_get_battery_voltage param_get_int
453 static const struct kernel_param_ops param_ops_ac_online
= {
454 .set
= param_set_ac_online
,
455 .get
= param_get_ac_online
,
458 static const struct kernel_param_ops param_ops_usb_online
= {
459 .set
= param_set_usb_online
,
460 .get
= param_get_usb_online
,
463 static const struct kernel_param_ops param_ops_battery_status
= {
464 .set
= param_set_battery_status
,
465 .get
= param_get_battery_status
,
468 static const struct kernel_param_ops param_ops_battery_present
= {
469 .set
= param_set_battery_present
,
470 .get
= param_get_battery_present
,
473 static const struct kernel_param_ops param_ops_battery_technology
= {
474 .set
= param_set_battery_technology
,
475 .get
= param_get_battery_technology
,
478 static const struct kernel_param_ops param_ops_battery_health
= {
479 .set
= param_set_battery_health
,
480 .get
= param_get_battery_health
,
483 static const struct kernel_param_ops param_ops_battery_capacity
= {
484 .set
= param_set_battery_capacity
,
485 .get
= param_get_battery_capacity
,
488 static const struct kernel_param_ops param_ops_battery_voltage
= {
489 .set
= param_set_battery_voltage
,
490 .get
= param_get_battery_voltage
,
493 #define param_check_ac_online(name, p) __param_check(name, p, void);
494 #define param_check_usb_online(name, p) __param_check(name, p, void);
495 #define param_check_battery_status(name, p) __param_check(name, p, void);
496 #define param_check_battery_present(name, p) __param_check(name, p, void);
497 #define param_check_battery_technology(name, p) __param_check(name, p, void);
498 #define param_check_battery_health(name, p) __param_check(name, p, void);
499 #define param_check_battery_capacity(name, p) __param_check(name, p, void);
500 #define param_check_battery_voltage(name, p) __param_check(name, p, void);
503 module_param(ac_online
, ac_online
, 0644);
504 MODULE_PARM_DESC(ac_online
, "AC charging state <on|off>");
506 module_param(usb_online
, usb_online
, 0644);
507 MODULE_PARM_DESC(usb_online
, "USB charging state <on|off>");
509 module_param(battery_status
, battery_status
, 0644);
510 MODULE_PARM_DESC(battery_status
,
511 "battery status <charging|discharging|not-charging|full>");
513 module_param(battery_present
, battery_present
, 0644);
514 MODULE_PARM_DESC(battery_present
,
515 "battery presence state <good|overheat|dead|overvoltage|failure>");
517 module_param(battery_technology
, battery_technology
, 0644);
518 MODULE_PARM_DESC(battery_technology
,
519 "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>");
521 module_param(battery_health
, battery_health
, 0644);
522 MODULE_PARM_DESC(battery_health
,
523 "battery health state <good|overheat|dead|overvoltage|failure>");
525 module_param(battery_capacity
, battery_capacity
, 0644);
526 MODULE_PARM_DESC(battery_capacity
, "battery capacity (percentage)");
528 module_param(battery_voltage
, battery_voltage
, 0644);
529 MODULE_PARM_DESC(battery_voltage
, "battery voltage (millivolts)");
531 MODULE_DESCRIPTION("Power supply driver for testing");
532 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
533 MODULE_LICENSE("GPL");