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
[] = {
159 .type
= POWER_SUPPLY_TYPE_MAINS
,
160 .supplied_to
= test_power_ac_supplied_to
,
161 .num_supplicants
= ARRAY_SIZE(test_power_ac_supplied_to
),
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 .supplied_to
= test_power_ac_supplied_to
,
177 .num_supplicants
= ARRAY_SIZE(test_power_ac_supplied_to
),
178 .properties
= test_power_ac_props
,
179 .num_properties
= ARRAY_SIZE(test_power_ac_props
),
180 .get_property
= test_power_get_usb_property
,
185 static int __init
test_power_init(void)
190 BUILD_BUG_ON(TEST_POWER_NUM
!= ARRAY_SIZE(test_power_supplies
));
192 for (i
= 0; i
< ARRAY_SIZE(test_power_supplies
); i
++) {
193 ret
= power_supply_register(NULL
, &test_power_supplies
[i
]);
195 pr_err("%s: failed to register %s\n", __func__
,
196 test_power_supplies
[i
].name
);
201 module_initialized
= true;
205 power_supply_unregister(&test_power_supplies
[i
]);
208 module_init(test_power_init
);
210 static void __exit
test_power_exit(void)
214 /* Let's see how we handle changes... */
217 battery_status
= POWER_SUPPLY_STATUS_DISCHARGING
;
218 for (i
= 0; i
< ARRAY_SIZE(test_power_supplies
); i
++)
219 power_supply_changed(&test_power_supplies
[i
]);
220 pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n",
224 for (i
= 0; i
< ARRAY_SIZE(test_power_supplies
); i
++)
225 power_supply_unregister(&test_power_supplies
[i
]);
227 module_initialized
= false;
229 module_exit(test_power_exit
);
233 #define MAX_KEYLENGTH 256
234 struct battery_property_map
{
239 static struct battery_property_map map_ac_online
[] = {
245 static struct battery_property_map map_status
[] = {
246 { POWER_SUPPLY_STATUS_CHARGING
, "charging" },
247 { POWER_SUPPLY_STATUS_DISCHARGING
, "discharging" },
248 { POWER_SUPPLY_STATUS_NOT_CHARGING
, "not-charging" },
249 { POWER_SUPPLY_STATUS_FULL
, "full" },
253 static struct battery_property_map map_health
[] = {
254 { POWER_SUPPLY_HEALTH_GOOD
, "good" },
255 { POWER_SUPPLY_HEALTH_OVERHEAT
, "overheat" },
256 { POWER_SUPPLY_HEALTH_DEAD
, "dead" },
257 { POWER_SUPPLY_HEALTH_OVERVOLTAGE
, "overvoltage" },
258 { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
, "failure" },
262 static struct battery_property_map map_present
[] = {
268 static struct battery_property_map map_technology
[] = {
269 { POWER_SUPPLY_TECHNOLOGY_NiMH
, "NiMH" },
270 { POWER_SUPPLY_TECHNOLOGY_LION
, "LION" },
271 { POWER_SUPPLY_TECHNOLOGY_LIPO
, "LIPO" },
272 { POWER_SUPPLY_TECHNOLOGY_LiFe
, "LiFe" },
273 { POWER_SUPPLY_TECHNOLOGY_NiCd
, "NiCd" },
274 { POWER_SUPPLY_TECHNOLOGY_LiMn
, "LiMn" },
279 static int map_get_value(struct battery_property_map
*map
, const char *key
,
282 char buf
[MAX_KEYLENGTH
];
285 strncpy(buf
, key
, MAX_KEYLENGTH
);
286 buf
[MAX_KEYLENGTH
-1] = '\0';
288 cr
= strnlen(buf
, MAX_KEYLENGTH
) - 1;
293 if (strncasecmp(map
->key
, buf
, MAX_KEYLENGTH
) == 0)
302 static const char *map_get_key(struct battery_property_map
*map
, int value
,
306 if (map
->value
== value
)
314 static inline void signal_power_supply_changed(struct power_supply
*psy
)
316 if (module_initialized
)
317 power_supply_changed(psy
);
320 static int param_set_ac_online(const char *key
, const struct kernel_param
*kp
)
322 ac_online
= map_get_value(map_ac_online
, key
, ac_online
);
323 signal_power_supply_changed(&test_power_supplies
[TEST_AC
]);
327 static int param_get_ac_online(char *buffer
, const struct kernel_param
*kp
)
329 strcpy(buffer
, map_get_key(map_ac_online
, ac_online
, "unknown"));
330 return strlen(buffer
);
333 static int param_set_usb_online(const char *key
, const struct kernel_param
*kp
)
335 usb_online
= map_get_value(map_ac_online
, key
, usb_online
);
336 signal_power_supply_changed(&test_power_supplies
[TEST_USB
]);
340 static int param_get_usb_online(char *buffer
, const struct kernel_param
*kp
)
342 strcpy(buffer
, map_get_key(map_ac_online
, usb_online
, "unknown"));
343 return strlen(buffer
);
346 static int param_set_battery_status(const char *key
,
347 const struct kernel_param
*kp
)
349 battery_status
= map_get_value(map_status
, key
, battery_status
);
350 signal_power_supply_changed(&test_power_supplies
[TEST_BATTERY
]);
354 static int param_get_battery_status(char *buffer
, const struct kernel_param
*kp
)
356 strcpy(buffer
, map_get_key(map_status
, battery_status
, "unknown"));
357 return strlen(buffer
);
360 static int param_set_battery_health(const char *key
,
361 const struct kernel_param
*kp
)
363 battery_health
= map_get_value(map_health
, key
, battery_health
);
364 signal_power_supply_changed(&test_power_supplies
[TEST_BATTERY
]);
368 static int param_get_battery_health(char *buffer
, const struct kernel_param
*kp
)
370 strcpy(buffer
, map_get_key(map_health
, battery_health
, "unknown"));
371 return strlen(buffer
);
374 static int param_set_battery_present(const char *key
,
375 const struct kernel_param
*kp
)
377 battery_present
= map_get_value(map_present
, key
, battery_present
);
378 signal_power_supply_changed(&test_power_supplies
[TEST_AC
]);
382 static int param_get_battery_present(char *buffer
,
383 const struct kernel_param
*kp
)
385 strcpy(buffer
, map_get_key(map_present
, battery_present
, "unknown"));
386 return strlen(buffer
);
389 static int param_set_battery_technology(const char *key
,
390 const struct kernel_param
*kp
)
392 battery_technology
= map_get_value(map_technology
, key
,
394 signal_power_supply_changed(&test_power_supplies
[TEST_BATTERY
]);
398 static int param_get_battery_technology(char *buffer
,
399 const struct kernel_param
*kp
)
402 map_get_key(map_technology
, battery_technology
, "unknown"));
403 return strlen(buffer
);
406 static int param_set_battery_capacity(const char *key
,
407 const struct kernel_param
*kp
)
411 if (1 != sscanf(key
, "%d", &tmp
))
414 battery_capacity
= tmp
;
415 signal_power_supply_changed(&test_power_supplies
[TEST_BATTERY
]);
419 #define param_get_battery_capacity param_get_int
421 static int param_set_battery_voltage(const char *key
,
422 const struct kernel_param
*kp
)
426 if (1 != sscanf(key
, "%d", &tmp
))
429 battery_voltage
= tmp
;
430 signal_power_supply_changed(&test_power_supplies
[TEST_BATTERY
]);
434 #define param_get_battery_voltage param_get_int
436 static struct kernel_param_ops param_ops_ac_online
= {
437 .set
= param_set_ac_online
,
438 .get
= param_get_ac_online
,
441 static struct kernel_param_ops param_ops_usb_online
= {
442 .set
= param_set_usb_online
,
443 .get
= param_get_usb_online
,
446 static struct kernel_param_ops param_ops_battery_status
= {
447 .set
= param_set_battery_status
,
448 .get
= param_get_battery_status
,
451 static struct kernel_param_ops param_ops_battery_present
= {
452 .set
= param_set_battery_present
,
453 .get
= param_get_battery_present
,
456 static struct kernel_param_ops param_ops_battery_technology
= {
457 .set
= param_set_battery_technology
,
458 .get
= param_get_battery_technology
,
461 static struct kernel_param_ops param_ops_battery_health
= {
462 .set
= param_set_battery_health
,
463 .get
= param_get_battery_health
,
466 static struct kernel_param_ops param_ops_battery_capacity
= {
467 .set
= param_set_battery_capacity
,
468 .get
= param_get_battery_capacity
,
471 static struct kernel_param_ops param_ops_battery_voltage
= {
472 .set
= param_set_battery_voltage
,
473 .get
= param_get_battery_voltage
,
476 #define param_check_ac_online(name, p) __param_check(name, p, void);
477 #define param_check_usb_online(name, p) __param_check(name, p, void);
478 #define param_check_battery_status(name, p) __param_check(name, p, void);
479 #define param_check_battery_present(name, p) __param_check(name, p, void);
480 #define param_check_battery_technology(name, p) __param_check(name, p, void);
481 #define param_check_battery_health(name, p) __param_check(name, p, void);
482 #define param_check_battery_capacity(name, p) __param_check(name, p, void);
483 #define param_check_battery_voltage(name, p) __param_check(name, p, void);
486 module_param(ac_online
, ac_online
, 0644);
487 MODULE_PARM_DESC(ac_online
, "AC charging state <on|off>");
489 module_param(usb_online
, usb_online
, 0644);
490 MODULE_PARM_DESC(usb_online
, "USB charging state <on|off>");
492 module_param(battery_status
, battery_status
, 0644);
493 MODULE_PARM_DESC(battery_status
,
494 "battery status <charging|discharging|not-charging|full>");
496 module_param(battery_present
, battery_present
, 0644);
497 MODULE_PARM_DESC(battery_present
,
498 "battery presence state <good|overheat|dead|overvoltage|failure>");
500 module_param(battery_technology
, battery_technology
, 0644);
501 MODULE_PARM_DESC(battery_technology
,
502 "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>");
504 module_param(battery_health
, battery_health
, 0644);
505 MODULE_PARM_DESC(battery_health
,
506 "battery health state <good|overheat|dead|overvoltage|failure>");
508 module_param(battery_capacity
, battery_capacity
, 0644);
509 MODULE_PARM_DESC(battery_capacity
, "battery capacity (percentage)");
511 module_param(battery_voltage
, battery_voltage
, 0644);
512 MODULE_PARM_DESC(battery_voltage
, "battery voltage (millivolts)");
514 MODULE_DESCRIPTION("Power supply driver for testing");
515 MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
516 MODULE_LICENSE("GPL");