mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
power: supply: core: Cleanup power supply sysfs attribute list
Make the device attribute list used to create sysfs attributes more robust by decoupling the list order from order of the enum defined in power_supply.h. This is done by using a designated initializer in the POWER_SUPPLY_ATTR macro. Signed-off-by: Mathew King <mathewk@chromium.org> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
This commit is contained in:
parent
72d9cd9cdc
commit
2cabeaf151
1 changed files with 132 additions and 128 deletions
|
@ -18,27 +18,21 @@
|
||||||
|
|
||||||
#include "power_supply.h"
|
#include "power_supply.h"
|
||||||
|
|
||||||
/*
|
#define MAX_PROP_NAME_LEN 30
|
||||||
* This is because the name "current" breaks the device attr macro.
|
|
||||||
* The "current" word resolves to "(get_current())" so instead of
|
|
||||||
* "current" "(get_current())" appears in the sysfs.
|
|
||||||
*
|
|
||||||
* The source of this definition is the device.h which calls __ATTR
|
|
||||||
* macro in sysfs.h which calls the __stringify macro.
|
|
||||||
*
|
|
||||||
* Only modification that the name is not tried to be resolved
|
|
||||||
* (as a macro let's say).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define POWER_SUPPLY_ATTR(_name) \
|
struct power_supply_attr {
|
||||||
{ \
|
const char *prop_name;
|
||||||
.attr = { .name = #_name }, \
|
char attr_name[MAX_PROP_NAME_LEN + 1];
|
||||||
.show = power_supply_show_property, \
|
struct device_attribute dev_attr;
|
||||||
.store = power_supply_store_property, \
|
};
|
||||||
|
|
||||||
|
#define POWER_SUPPLY_ATTR(_name) \
|
||||||
|
[POWER_SUPPLY_PROP_ ## _name] = \
|
||||||
|
{ \
|
||||||
|
.prop_name = #_name, \
|
||||||
|
.attr_name = #_name "\0", \
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct device_attribute power_supply_attrs[];
|
|
||||||
|
|
||||||
static const char * const power_supply_type_text[] = {
|
static const char * const power_supply_type_text[] = {
|
||||||
"Unknown", "Battery", "UPS", "Mains", "USB",
|
"Unknown", "Battery", "UPS", "Mains", "USB",
|
||||||
"USB_DCP", "USB_CDP", "USB_ACA", "USB_C",
|
"USB_DCP", "USB_CDP", "USB_ACA", "USB_C",
|
||||||
|
@ -77,6 +71,91 @@ static const char * const power_supply_scope_text[] = {
|
||||||
"Unknown", "System", "Device"
|
"Unknown", "System", "Device"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct power_supply_attr power_supply_attrs[] = {
|
||||||
|
/* Properties of type `int' */
|
||||||
|
POWER_SUPPLY_ATTR(STATUS),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_TYPE),
|
||||||
|
POWER_SUPPLY_ATTR(HEALTH),
|
||||||
|
POWER_SUPPLY_ATTR(PRESENT),
|
||||||
|
POWER_SUPPLY_ATTR(ONLINE),
|
||||||
|
POWER_SUPPLY_ATTR(AUTHENTIC),
|
||||||
|
POWER_SUPPLY_ATTR(TECHNOLOGY),
|
||||||
|
POWER_SUPPLY_ATTR(CYCLE_COUNT),
|
||||||
|
POWER_SUPPLY_ATTR(VOLTAGE_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(VOLTAGE_MIN),
|
||||||
|
POWER_SUPPLY_ATTR(VOLTAGE_MAX_DESIGN),
|
||||||
|
POWER_SUPPLY_ATTR(VOLTAGE_MIN_DESIGN),
|
||||||
|
POWER_SUPPLY_ATTR(VOLTAGE_NOW),
|
||||||
|
POWER_SUPPLY_ATTR(VOLTAGE_AVG),
|
||||||
|
POWER_SUPPLY_ATTR(VOLTAGE_OCV),
|
||||||
|
POWER_SUPPLY_ATTR(VOLTAGE_BOOT),
|
||||||
|
POWER_SUPPLY_ATTR(CURRENT_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(CURRENT_NOW),
|
||||||
|
POWER_SUPPLY_ATTR(CURRENT_AVG),
|
||||||
|
POWER_SUPPLY_ATTR(CURRENT_BOOT),
|
||||||
|
POWER_SUPPLY_ATTR(POWER_NOW),
|
||||||
|
POWER_SUPPLY_ATTR(POWER_AVG),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_FULL_DESIGN),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_EMPTY_DESIGN),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_FULL),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_EMPTY),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_NOW),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_AVG),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_COUNTER),
|
||||||
|
POWER_SUPPLY_ATTR(CONSTANT_CHARGE_CURRENT),
|
||||||
|
POWER_SUPPLY_ATTR(CONSTANT_CHARGE_CURRENT_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(CONSTANT_CHARGE_VOLTAGE),
|
||||||
|
POWER_SUPPLY_ATTR(CONSTANT_CHARGE_VOLTAGE_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_CONTROL_LIMIT),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_CONTROL_LIMIT_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_CONTROL_END_THRESHOLD),
|
||||||
|
POWER_SUPPLY_ATTR(INPUT_CURRENT_LIMIT),
|
||||||
|
POWER_SUPPLY_ATTR(INPUT_VOLTAGE_LIMIT),
|
||||||
|
POWER_SUPPLY_ATTR(INPUT_POWER_LIMIT),
|
||||||
|
POWER_SUPPLY_ATTR(ENERGY_FULL_DESIGN),
|
||||||
|
POWER_SUPPLY_ATTR(ENERGY_EMPTY_DESIGN),
|
||||||
|
POWER_SUPPLY_ATTR(ENERGY_FULL),
|
||||||
|
POWER_SUPPLY_ATTR(ENERGY_EMPTY),
|
||||||
|
POWER_SUPPLY_ATTR(ENERGY_NOW),
|
||||||
|
POWER_SUPPLY_ATTR(ENERGY_AVG),
|
||||||
|
POWER_SUPPLY_ATTR(CAPACITY),
|
||||||
|
POWER_SUPPLY_ATTR(CAPACITY_ALERT_MIN),
|
||||||
|
POWER_SUPPLY_ATTR(CAPACITY_ALERT_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(CAPACITY_LEVEL),
|
||||||
|
POWER_SUPPLY_ATTR(TEMP),
|
||||||
|
POWER_SUPPLY_ATTR(TEMP_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(TEMP_MIN),
|
||||||
|
POWER_SUPPLY_ATTR(TEMP_ALERT_MIN),
|
||||||
|
POWER_SUPPLY_ATTR(TEMP_ALERT_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(TEMP_AMBIENT),
|
||||||
|
POWER_SUPPLY_ATTR(TEMP_AMBIENT_ALERT_MIN),
|
||||||
|
POWER_SUPPLY_ATTR(TEMP_AMBIENT_ALERT_MAX),
|
||||||
|
POWER_SUPPLY_ATTR(TIME_TO_EMPTY_NOW),
|
||||||
|
POWER_SUPPLY_ATTR(TIME_TO_EMPTY_AVG),
|
||||||
|
POWER_SUPPLY_ATTR(TIME_TO_FULL_NOW),
|
||||||
|
POWER_SUPPLY_ATTR(TIME_TO_FULL_AVG),
|
||||||
|
POWER_SUPPLY_ATTR(TYPE),
|
||||||
|
POWER_SUPPLY_ATTR(USB_TYPE),
|
||||||
|
POWER_SUPPLY_ATTR(SCOPE),
|
||||||
|
POWER_SUPPLY_ATTR(PRECHARGE_CURRENT),
|
||||||
|
POWER_SUPPLY_ATTR(CHARGE_TERM_CURRENT),
|
||||||
|
POWER_SUPPLY_ATTR(CALIBRATE),
|
||||||
|
/* Properties of type `const char *' */
|
||||||
|
POWER_SUPPLY_ATTR(MODEL_NAME),
|
||||||
|
POWER_SUPPLY_ATTR(MANUFACTURER),
|
||||||
|
POWER_SUPPLY_ATTR(SERIAL_NUMBER),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute *
|
||||||
|
__power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1];
|
||||||
|
|
||||||
|
static enum power_supply_property dev_attr_psp(struct device_attribute *attr)
|
||||||
|
{
|
||||||
|
return container_of(attr, struct power_supply_attr, dev_attr) -
|
||||||
|
power_supply_attrs;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t power_supply_show_usb_type(struct device *dev,
|
static ssize_t power_supply_show_usb_type(struct device *dev,
|
||||||
const struct power_supply_desc *desc,
|
const struct power_supply_desc *desc,
|
||||||
union power_supply_propval *value,
|
union power_supply_propval *value,
|
||||||
|
@ -116,7 +195,7 @@ static ssize_t power_supply_show_property(struct device *dev,
|
||||||
char *buf) {
|
char *buf) {
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
struct power_supply *psy = dev_get_drvdata(dev);
|
struct power_supply *psy = dev_get_drvdata(dev);
|
||||||
enum power_supply_property psp = attr - power_supply_attrs;
|
enum power_supply_property psp = dev_attr_psp(attr);
|
||||||
union power_supply_propval value;
|
union power_supply_propval value;
|
||||||
|
|
||||||
if (psp == POWER_SUPPLY_PROP_TYPE) {
|
if (psp == POWER_SUPPLY_PROP_TYPE) {
|
||||||
|
@ -184,7 +263,7 @@ static ssize_t power_supply_store_property(struct device *dev,
|
||||||
const char *buf, size_t count) {
|
const char *buf, size_t count) {
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
struct power_supply *psy = dev_get_drvdata(dev);
|
struct power_supply *psy = dev_get_drvdata(dev);
|
||||||
enum power_supply_property psp = attr - power_supply_attrs;
|
enum power_supply_property psp = dev_attr_psp(attr);
|
||||||
union power_supply_propval value;
|
union power_supply_propval value;
|
||||||
|
|
||||||
switch (psp) {
|
switch (psp) {
|
||||||
|
@ -233,86 +312,6 @@ static ssize_t power_supply_store_property(struct device *dev,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be in the same order as POWER_SUPPLY_PROP_* */
|
|
||||||
static struct device_attribute power_supply_attrs[] = {
|
|
||||||
/* Properties of type `int' */
|
|
||||||
POWER_SUPPLY_ATTR(status),
|
|
||||||
POWER_SUPPLY_ATTR(charge_type),
|
|
||||||
POWER_SUPPLY_ATTR(health),
|
|
||||||
POWER_SUPPLY_ATTR(present),
|
|
||||||
POWER_SUPPLY_ATTR(online),
|
|
||||||
POWER_SUPPLY_ATTR(authentic),
|
|
||||||
POWER_SUPPLY_ATTR(technology),
|
|
||||||
POWER_SUPPLY_ATTR(cycle_count),
|
|
||||||
POWER_SUPPLY_ATTR(voltage_max),
|
|
||||||
POWER_SUPPLY_ATTR(voltage_min),
|
|
||||||
POWER_SUPPLY_ATTR(voltage_max_design),
|
|
||||||
POWER_SUPPLY_ATTR(voltage_min_design),
|
|
||||||
POWER_SUPPLY_ATTR(voltage_now),
|
|
||||||
POWER_SUPPLY_ATTR(voltage_avg),
|
|
||||||
POWER_SUPPLY_ATTR(voltage_ocv),
|
|
||||||
POWER_SUPPLY_ATTR(voltage_boot),
|
|
||||||
POWER_SUPPLY_ATTR(current_max),
|
|
||||||
POWER_SUPPLY_ATTR(current_now),
|
|
||||||
POWER_SUPPLY_ATTR(current_avg),
|
|
||||||
POWER_SUPPLY_ATTR(current_boot),
|
|
||||||
POWER_SUPPLY_ATTR(power_now),
|
|
||||||
POWER_SUPPLY_ATTR(power_avg),
|
|
||||||
POWER_SUPPLY_ATTR(charge_full_design),
|
|
||||||
POWER_SUPPLY_ATTR(charge_empty_design),
|
|
||||||
POWER_SUPPLY_ATTR(charge_full),
|
|
||||||
POWER_SUPPLY_ATTR(charge_empty),
|
|
||||||
POWER_SUPPLY_ATTR(charge_now),
|
|
||||||
POWER_SUPPLY_ATTR(charge_avg),
|
|
||||||
POWER_SUPPLY_ATTR(charge_counter),
|
|
||||||
POWER_SUPPLY_ATTR(constant_charge_current),
|
|
||||||
POWER_SUPPLY_ATTR(constant_charge_current_max),
|
|
||||||
POWER_SUPPLY_ATTR(constant_charge_voltage),
|
|
||||||
POWER_SUPPLY_ATTR(constant_charge_voltage_max),
|
|
||||||
POWER_SUPPLY_ATTR(charge_control_limit),
|
|
||||||
POWER_SUPPLY_ATTR(charge_control_limit_max),
|
|
||||||
POWER_SUPPLY_ATTR(charge_control_start_threshold),
|
|
||||||
POWER_SUPPLY_ATTR(charge_control_end_threshold),
|
|
||||||
POWER_SUPPLY_ATTR(input_current_limit),
|
|
||||||
POWER_SUPPLY_ATTR(input_voltage_limit),
|
|
||||||
POWER_SUPPLY_ATTR(input_power_limit),
|
|
||||||
POWER_SUPPLY_ATTR(energy_full_design),
|
|
||||||
POWER_SUPPLY_ATTR(energy_empty_design),
|
|
||||||
POWER_SUPPLY_ATTR(energy_full),
|
|
||||||
POWER_SUPPLY_ATTR(energy_empty),
|
|
||||||
POWER_SUPPLY_ATTR(energy_now),
|
|
||||||
POWER_SUPPLY_ATTR(energy_avg),
|
|
||||||
POWER_SUPPLY_ATTR(capacity),
|
|
||||||
POWER_SUPPLY_ATTR(capacity_alert_min),
|
|
||||||
POWER_SUPPLY_ATTR(capacity_alert_max),
|
|
||||||
POWER_SUPPLY_ATTR(capacity_level),
|
|
||||||
POWER_SUPPLY_ATTR(temp),
|
|
||||||
POWER_SUPPLY_ATTR(temp_max),
|
|
||||||
POWER_SUPPLY_ATTR(temp_min),
|
|
||||||
POWER_SUPPLY_ATTR(temp_alert_min),
|
|
||||||
POWER_SUPPLY_ATTR(temp_alert_max),
|
|
||||||
POWER_SUPPLY_ATTR(temp_ambient),
|
|
||||||
POWER_SUPPLY_ATTR(temp_ambient_alert_min),
|
|
||||||
POWER_SUPPLY_ATTR(temp_ambient_alert_max),
|
|
||||||
POWER_SUPPLY_ATTR(time_to_empty_now),
|
|
||||||
POWER_SUPPLY_ATTR(time_to_empty_avg),
|
|
||||||
POWER_SUPPLY_ATTR(time_to_full_now),
|
|
||||||
POWER_SUPPLY_ATTR(time_to_full_avg),
|
|
||||||
POWER_SUPPLY_ATTR(type),
|
|
||||||
POWER_SUPPLY_ATTR(usb_type),
|
|
||||||
POWER_SUPPLY_ATTR(scope),
|
|
||||||
POWER_SUPPLY_ATTR(precharge_current),
|
|
||||||
POWER_SUPPLY_ATTR(charge_term_current),
|
|
||||||
POWER_SUPPLY_ATTR(calibrate),
|
|
||||||
/* Properties of type `const char *' */
|
|
||||||
POWER_SUPPLY_ATTR(model_name),
|
|
||||||
POWER_SUPPLY_ATTR(manufacturer),
|
|
||||||
POWER_SUPPLY_ATTR(serial_number),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct attribute *
|
|
||||||
__power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1];
|
|
||||||
|
|
||||||
static umode_t power_supply_attr_is_visible(struct kobject *kobj,
|
static umode_t power_supply_attr_is_visible(struct kobject *kobj,
|
||||||
struct attribute *attr,
|
struct attribute *attr,
|
||||||
int attrno)
|
int attrno)
|
||||||
|
@ -322,6 +321,9 @@ static umode_t power_supply_attr_is_visible(struct kobject *kobj,
|
||||||
umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
|
umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!power_supply_attrs[attrno].prop_name)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (attrno == POWER_SUPPLY_PROP_TYPE)
|
if (attrno == POWER_SUPPLY_PROP_TYPE)
|
||||||
return mode;
|
return mode;
|
||||||
|
|
||||||
|
@ -350,31 +352,38 @@ static const struct attribute_group *power_supply_attr_groups[] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void str_to_lower(char *str)
|
||||||
|
{
|
||||||
|
while (*str) {
|
||||||
|
*str = tolower(*str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void power_supply_init_attrs(struct device_type *dev_type)
|
void power_supply_init_attrs(struct device_type *dev_type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dev_type->groups = power_supply_attr_groups;
|
dev_type->groups = power_supply_attr_groups;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++)
|
for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) {
|
||||||
__power_supply_attrs[i] = &power_supply_attrs[i].attr;
|
struct device_attribute *attr;
|
||||||
}
|
|
||||||
|
|
||||||
static char *kstruprdup(const char *str, gfp_t gfp)
|
if (!power_supply_attrs[i].prop_name) {
|
||||||
{
|
pr_warn("%s: Property %d skipped because is is missing from power_supply_attrs\n",
|
||||||
char *ret, *ustr;
|
__func__, i);
|
||||||
|
sprintf(power_supply_attrs[i].attr_name, "_err_%d", i);
|
||||||
|
} else {
|
||||||
|
str_to_lower(power_supply_attrs[i].attr_name);
|
||||||
|
}
|
||||||
|
|
||||||
ustr = ret = kmalloc(strlen(str) + 1, gfp);
|
attr = &power_supply_attrs[i].dev_attr;
|
||||||
|
|
||||||
if (!ret)
|
attr->attr.name = power_supply_attrs[i].attr_name;
|
||||||
return NULL;
|
attr->show = power_supply_show_property;
|
||||||
|
attr->store = power_supply_store_property;
|
||||||
while (*str)
|
__power_supply_attrs[i] = &attr->attr;
|
||||||
*ustr++ = toupper(*str++);
|
}
|
||||||
|
|
||||||
*ustr = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
|
int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
|
@ -382,7 +391,6 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
struct power_supply *psy = dev_get_drvdata(dev);
|
struct power_supply *psy = dev_get_drvdata(dev);
|
||||||
int ret = 0, j;
|
int ret = 0, j;
|
||||||
char *prop_buf;
|
char *prop_buf;
|
||||||
char *attrname;
|
|
||||||
|
|
||||||
if (!psy || !psy->desc) {
|
if (!psy || !psy->desc) {
|
||||||
dev_dbg(dev, "No power supply yet\n");
|
dev_dbg(dev, "No power supply yet\n");
|
||||||
|
@ -398,12 +406,14 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (j = 0; j < psy->desc->num_properties; j++) {
|
for (j = 0; j < psy->desc->num_properties; j++) {
|
||||||
struct device_attribute *attr;
|
struct power_supply_attr *pwr_attr;
|
||||||
|
struct device_attribute *dev_attr;
|
||||||
char *line;
|
char *line;
|
||||||
|
|
||||||
attr = &power_supply_attrs[psy->desc->properties[j]];
|
pwr_attr = &power_supply_attrs[psy->desc->properties[j]];
|
||||||
|
dev_attr = &pwr_attr->dev_attr;
|
||||||
|
|
||||||
ret = power_supply_show_property(dev, attr, prop_buf);
|
ret = power_supply_show_property(dev, dev_attr, prop_buf);
|
||||||
if (ret == -ENODEV || ret == -ENODATA) {
|
if (ret == -ENODEV || ret == -ENODATA) {
|
||||||
/* When a battery is absent, we expect -ENODEV. Don't abort;
|
/* When a battery is absent, we expect -ENODEV. Don't abort;
|
||||||
send the uevent with at least the the PRESENT=0 property */
|
send the uevent with at least the the PRESENT=0 property */
|
||||||
|
@ -418,14 +428,8 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
if (line)
|
if (line)
|
||||||
*line = 0;
|
*line = 0;
|
||||||
|
|
||||||
attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
|
ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s",
|
||||||
if (!attrname) {
|
pwr_attr->prop_name, prop_buf);
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf);
|
|
||||||
kfree(attrname);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue