summaryrefslogtreecommitdiff
path: root/drivers/power/supply/test_power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/supply/test_power.c')
-rw-r--r--drivers/power/supply/test_power.c269
1 files changed, 248 insertions, 21 deletions
diff --git a/drivers/power/supply/test_power.c b/drivers/power/supply/test_power.c
index 57246cdbd042..2c0e9ad820c0 100644
--- a/drivers/power/supply/test_power.c
+++ b/drivers/power/supply/test_power.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Power supply driver for testing.
*
@@ -8,10 +9,6 @@
* By: Masashi YOKOTA <yokota@pylone.jp>
* Originally found here:
* http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/kernel.h>
@@ -19,7 +16,7 @@
#include <linux/power_supply.h>
#include <linux/errno.h>
#include <linux/delay.h>
-#include <linux/vermagic.h>
+#include <generated/utsrelease.h>
enum test_power_id {
TEST_AC,
@@ -36,6 +33,13 @@ static int battery_present = 1; /* true */
static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION;
static int battery_capacity = 50;
static int battery_voltage = 3300;
+static int battery_charge_counter = -1000;
+static int battery_current = -1600;
+static enum power_supply_charge_behaviour battery_charge_behaviour =
+ POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
+static enum power_supply_charge_type battery_charge_types =
+ POWER_SUPPLY_CHARGE_TYPE_STANDARD;
+static bool battery_extension;
static bool module_initialized;
@@ -85,7 +89,7 @@ static int test_power_get_battery_property(struct power_supply *psy,
val->intval = battery_status;
break;
case POWER_SUPPLY_PROP_CHARGE_TYPE:
- val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ val->intval = battery_charge_types;
break;
case POWER_SUPPLY_PROP_HEALTH:
val->intval = battery_health;
@@ -103,6 +107,9 @@ static int test_power_get_battery_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_NOW:
val->intval = battery_capacity;
break;
+ case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+ val->intval = battery_charge_counter;
+ break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
case POWER_SUPPLY_PROP_CHARGE_FULL:
val->intval = 100;
@@ -117,6 +124,16 @@ static int test_power_get_battery_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
val->intval = battery_voltage;
break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = battery_current;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
+ val->intval = battery_charge_behaviour;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPES:
+ val->intval = battery_charge_types;
+ break;
default:
pr_info("%s: some properties deliberately report errors.\n",
__func__);
@@ -125,6 +142,39 @@ static int test_power_get_battery_property(struct power_supply *psy,
return 0;
}
+static int test_power_battery_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ return psp == POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR || psp == POWER_SUPPLY_PROP_CHARGE_TYPES;
+}
+
+static int test_power_set_battery_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
+ if (val->intval < 0 ||
+ val->intval >= BITS_PER_TYPE(typeof(psy->desc->charge_behaviours)) ||
+ !(BIT(val->intval) & psy->desc->charge_behaviours)) {
+ return -EINVAL;
+ }
+ battery_charge_behaviour = val->intval;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPES:
+ if (val->intval < 0 ||
+ val->intval >= BITS_PER_TYPE(typeof(psy->desc->charge_types)) ||
+ !(BIT(val->intval) & psy->desc->charge_types)) {
+ return -EINVAL;
+ }
+ battery_charge_types = val->intval;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static enum power_supply_property test_power_ac_props[] = {
POWER_SUPPLY_PROP_ONLINE,
};
@@ -138,6 +188,7 @@ static enum power_supply_property test_power_battery_props[] = {
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@ -147,6 +198,10 @@ static enum power_supply_property test_power_battery_props[] = {
POWER_SUPPLY_PROP_SERIAL_NUMBER,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
+ POWER_SUPPLY_PROP_CHARGE_TYPES,
};
static char *test_power_ac_supplied_to[] = {
@@ -169,6 +224,14 @@ static const struct power_supply_desc test_power_desc[] = {
.properties = test_power_battery_props,
.num_properties = ARRAY_SIZE(test_power_battery_props),
.get_property = test_power_get_battery_property,
+ .set_property = test_power_set_battery_property,
+ .property_is_writeable = test_power_battery_property_is_writeable,
+ .charge_behaviours = BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO)
+ | BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE)
+ | BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE_AWAKE)
+ | BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE),
+ .charge_types = BIT(POWER_SUPPLY_CHARGE_TYPE_STANDARD)
+ | BIT(POWER_SUPPLY_CHARGE_TYPE_LONGLIFE)
},
[TEST_USB] = {
.name = "test_usb",
@@ -193,6 +256,91 @@ static const struct power_supply_config test_power_configs[] = {
},
};
+static int test_power_battery_extmanufacture_year = 1234;
+static int test_power_battery_exttemp_max = 1000;
+static const enum power_supply_property test_power_battery_extprops[] = {
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_MANUFACTURE_YEAR,
+ POWER_SUPPLY_PROP_TEMP_MAX,
+};
+
+static int test_power_battery_extget_property(struct power_supply *psy,
+ const struct power_supply_ext *ext,
+ void *ext_data,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+ return power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ val);
+ case POWER_SUPPLY_PROP_MANUFACTURE_YEAR:
+ val->intval = test_power_battery_extmanufacture_year;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ val->intval = test_power_battery_exttemp_max;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int test_power_battery_extset_property(struct power_supply *psy,
+ const struct power_supply_ext *ext,
+ void *ext_data,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_MANUFACTURE_YEAR:
+ test_power_battery_extmanufacture_year = val->intval;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ test_power_battery_exttemp_max = val->intval;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int test_power_battery_extproperty_is_writeable(struct power_supply *psy,
+ const struct power_supply_ext *ext,
+ void *ext_data,
+ enum power_supply_property psp)
+{
+ return true;
+}
+
+static const struct power_supply_ext test_power_battery_ext = {
+ .name = "test_power",
+ .properties = test_power_battery_extprops,
+ .num_properties = ARRAY_SIZE(test_power_battery_extprops),
+ .get_property = test_power_battery_extget_property,
+ .set_property = test_power_battery_extset_property,
+ .property_is_writeable = test_power_battery_extproperty_is_writeable,
+};
+
+static void test_power_configure_battery_extension(bool enable)
+{
+ struct power_supply *psy;
+
+ psy = test_power_supplies[TEST_BATTERY];
+
+ if (enable) {
+ if (power_supply_register_extension(psy, &test_power_battery_ext, &psy->dev,
+ NULL)) {
+ pr_err("registering battery extension failed\n");
+ return;
+ }
+ } else {
+ power_supply_unregister_extension(psy, &test_power_battery_ext);
+ }
+
+ battery_extension = enable;
+}
+
static int __init test_power_init(void)
{
int i;
@@ -213,6 +361,8 @@ static int __init test_power_init(void)
}
}
+ test_power_configure_battery_extension(true);
+
module_initialized = true;
return 0;
failed:
@@ -297,8 +447,7 @@ static int map_get_value(struct battery_property_map *map, const char *key,
char buf[MAX_KEYLENGTH];
int cr;
- strncpy(buf, key, MAX_KEYLENGTH);
- buf[MAX_KEYLENGTH-1] = '\0';
+ strscpy(buf, key, MAX_KEYLENGTH);
cr = strnlen(buf, MAX_KEYLENGTH) - 1;
if (cr < 0)
@@ -343,8 +492,8 @@ static int param_set_ac_online(const char *key, const struct kernel_param *kp)
static int param_get_ac_online(char *buffer, const struct kernel_param *kp)
{
- strcpy(buffer, map_get_key(map_ac_online, ac_online, "unknown"));
- return strlen(buffer);
+ return sprintf(buffer, "%s\n",
+ map_get_key(map_ac_online, ac_online, "unknown"));
}
static int param_set_usb_online(const char *key, const struct kernel_param *kp)
@@ -356,8 +505,8 @@ static int param_set_usb_online(const char *key, const struct kernel_param *kp)
static int param_get_usb_online(char *buffer, const struct kernel_param *kp)
{
- strcpy(buffer, map_get_key(map_ac_online, usb_online, "unknown"));
- return strlen(buffer);
+ return sprintf(buffer, "%s\n",
+ map_get_key(map_ac_online, usb_online, "unknown"));
}
static int param_set_battery_status(const char *key,
@@ -370,8 +519,8 @@ static int param_set_battery_status(const char *key,
static int param_get_battery_status(char *buffer, const struct kernel_param *kp)
{
- strcpy(buffer, map_get_key(map_status, battery_status, "unknown"));
- return strlen(buffer);
+ return sprintf(buffer, "%s\n",
+ map_get_key(map_ac_online, battery_status, "unknown"));
}
static int param_set_battery_health(const char *key,
@@ -384,8 +533,8 @@ static int param_set_battery_health(const char *key,
static int param_get_battery_health(char *buffer, const struct kernel_param *kp)
{
- strcpy(buffer, map_get_key(map_health, battery_health, "unknown"));
- return strlen(buffer);
+ return sprintf(buffer, "%s\n",
+ map_get_key(map_ac_online, battery_health, "unknown"));
}
static int param_set_battery_present(const char *key,
@@ -399,8 +548,8 @@ static int param_set_battery_present(const char *key,
static int param_get_battery_present(char *buffer,
const struct kernel_param *kp)
{
- strcpy(buffer, map_get_key(map_present, battery_present, "unknown"));
- return strlen(buffer);
+ return sprintf(buffer, "%s\n",
+ map_get_key(map_ac_online, battery_present, "unknown"));
}
static int param_set_battery_technology(const char *key,
@@ -415,9 +564,9 @@ static int param_set_battery_technology(const char *key,
static int param_get_battery_technology(char *buffer,
const struct kernel_param *kp)
{
- strcpy(buffer,
- map_get_key(map_technology, battery_technology, "unknown"));
- return strlen(buffer);
+ return sprintf(buffer, "%s\n",
+ map_get_key(map_ac_online, battery_technology,
+ "unknown"));
}
static int param_set_battery_capacity(const char *key,
@@ -450,6 +599,56 @@ static int param_set_battery_voltage(const char *key,
#define param_get_battery_voltage param_get_int
+static int param_set_battery_charge_counter(const char *key,
+ const struct kernel_param *kp)
+{
+ int tmp;
+
+ if (1 != sscanf(key, "%d", &tmp))
+ return -EINVAL;
+
+ battery_charge_counter = tmp;
+ signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
+ return 0;
+}
+
+#define param_get_battery_charge_counter param_get_int
+
+static int param_set_battery_current(const char *key,
+ const struct kernel_param *kp)
+{
+ int tmp;
+
+ if (1 != sscanf(key, "%d", &tmp))
+ return -EINVAL;
+
+ battery_current = tmp;
+ signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
+ return 0;
+}
+
+#define param_get_battery_current param_get_int
+
+static int param_set_battery_extension(const char *key,
+ const struct kernel_param *kp)
+{
+ bool prev_battery_extension;
+ int ret;
+
+ prev_battery_extension = battery_extension;
+
+ ret = param_set_bool(key, kp);
+ if (ret)
+ return ret;
+
+ if (prev_battery_extension != battery_extension)
+ test_power_configure_battery_extension(battery_extension);
+
+ return 0;
+}
+
+#define param_get_battery_extension param_get_bool
+
static const struct kernel_param_ops param_ops_ac_online = {
.set = param_set_ac_online,
.get = param_get_ac_online,
@@ -490,6 +689,21 @@ static const struct kernel_param_ops param_ops_battery_voltage = {
.get = param_get_battery_voltage,
};
+static const struct kernel_param_ops param_ops_battery_charge_counter = {
+ .set = param_set_battery_charge_counter,
+ .get = param_get_battery_charge_counter,
+};
+
+static const struct kernel_param_ops param_ops_battery_current = {
+ .set = param_set_battery_current,
+ .get = param_get_battery_current,
+};
+
+static const struct kernel_param_ops param_ops_battery_extension = {
+ .set = param_set_battery_extension,
+ .get = param_get_battery_extension,
+};
+
#define param_check_ac_online(name, p) __param_check(name, p, void);
#define param_check_usb_online(name, p) __param_check(name, p, void);
#define param_check_battery_status(name, p) __param_check(name, p, void);
@@ -498,6 +712,9 @@ static const struct kernel_param_ops param_ops_battery_voltage = {
#define param_check_battery_health(name, p) __param_check(name, p, void);
#define param_check_battery_capacity(name, p) __param_check(name, p, void);
#define param_check_battery_voltage(name, p) __param_check(name, p, void);
+#define param_check_battery_charge_counter(name, p) __param_check(name, p, void);
+#define param_check_battery_current(name, p) __param_check(name, p, void);
+#define param_check_battery_extension(name, p) __param_check(name, p, void);
module_param(ac_online, ac_online, 0644);
@@ -528,6 +745,16 @@ MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)");
module_param(battery_voltage, battery_voltage, 0644);
MODULE_PARM_DESC(battery_voltage, "battery voltage (millivolts)");
+module_param(battery_charge_counter, battery_charge_counter, 0644);
+MODULE_PARM_DESC(battery_charge_counter,
+ "battery charge counter (microampere-hours)");
+
+module_param(battery_current, battery_current, 0644);
+MODULE_PARM_DESC(battery_current, "battery current (milliampere)");
+
+module_param(battery_extension, battery_extension, 0644);
+MODULE_PARM_DESC(battery_extension, "battery extension");
+
MODULE_DESCRIPTION("Power supply driver for testing");
MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
MODULE_LICENSE("GPL");