Blame view
drivers/power/power_supply_sysfs.c
9.1 KB
4a11b59d8 [BATTERY] Univers... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* * Sysfs interface for the universal power supply monitor class * * Copyright © 2007 David Woodhouse <dwmw2@infradead.org> * Copyright © 2007 Anton Vorontsov <cbou@mail.ru> * Copyright © 2004 Szabolcs Gyurko * Copyright © 2003 Ian Molton <spyro@f2s.com> * * Modified: 2004, Oct Szabolcs Gyurko * * You may use this code as per GPL version 2 */ #include <linux/ctype.h> |
51990e825 device.h: cleanup... |
15 |
#include <linux/device.h> |
4a11b59d8 [BATTERY] Univers... |
16 |
#include <linux/power_supply.h> |
5a0e3ad6a include cleanup: ... |
17 |
#include <linux/slab.h> |
778f523dd drivers: power_su... |
18 |
#include <linux/stat.h> |
4a11b59d8 [BATTERY] Univers... |
19 |
|
25f12141e [BATTERY] Every f... |
20 |
#include "power_supply.h" |
4a11b59d8 [BATTERY] Univers... |
21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/* * 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) \ { \ |
5f487cd34 power_supply: Use... |
35 |
.attr = { .name = #_name }, \ |
4a11b59d8 [BATTERY] Univers... |
36 |
.show = power_supply_show_property, \ |
0011d2d4a power_supply: Add... |
37 |
.store = power_supply_store_property, \ |
4a11b59d8 [BATTERY] Univers... |
38 39 40 41 42 43 44 |
} static struct device_attribute power_supply_attrs[]; static ssize_t power_supply_show_property(struct device *dev, struct device_attribute *attr, char *buf) { |
5f487cd34 power_supply: Use... |
45 |
static char *type_text[] = { |
9b8872273 power_supply: Add... |
46 |
"Unknown", "Battery", "UPS", "Mains", "USB", |
6659b55da power_supply: Add... |
47 48 |
"USB_DCP", "USB_CDP", "USB_ACA", "USB_C", "USB_PD", "USB_PD_DRP" |
5f487cd34 power_supply: Use... |
49 |
}; |
4a11b59d8 [BATTERY] Univers... |
50 51 52 |
static char *status_text[] = { "Unknown", "Charging", "Discharging", "Not charging", "Full" }; |
ee8076ed3 power_supply: Add... |
53 54 55 |
static char *charge_type[] = { "Unknown", "N/A", "Trickle", "Fast" }; |
4a11b59d8 [BATTERY] Univers... |
56 57 |
static char *health_text[] = { "Unknown", "Good", "Overheat", "Dead", "Over voltage", |
a05be9917 power_supply: Add... |
58 59 |
"Unspecified failure", "Cold", "Watchdog timer expire", "Safety timer expire" |
4a11b59d8 [BATTERY] Univers... |
60 61 |
}; static char *technology_text[] = { |
c7cc930f9 power_supply: add... |
62 63 |
"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", "LiMn" |
4a11b59d8 [BATTERY] Univers... |
64 |
}; |
b294a290d Revert "power: re... |
65 66 67 |
static char *capacity_level_text[] = { "Unknown", "Critical", "Low", "Normal", "High", "Full" }; |
25a0bc2df power_supply: add... |
68 69 70 |
static char *scope_text[] = { "Unknown", "System", "Device" }; |
5f487cd34 power_supply: Use... |
71 |
ssize_t ret = 0; |
4a11b59d8 [BATTERY] Univers... |
72 73 74 |
struct power_supply *psy = dev_get_drvdata(dev); const ptrdiff_t off = attr - power_supply_attrs; union power_supply_propval value; |
73b4a087b power-supply: Che... |
75 |
if (off == POWER_SUPPLY_PROP_TYPE) { |
297d716f6 power_supply: Cha... |
76 |
value.intval = psy->desc->type; |
73b4a087b power-supply: Che... |
77 |
} else { |
ee8f334a9 power_supply: sys... |
78 |
ret = power_supply_get_property(psy, off, &value); |
4a11b59d8 [BATTERY] Univers... |
79 |
|
73b4a087b power-supply: Che... |
80 81 82 83 84 |
if (ret < 0) { if (ret == -ENODATA) dev_dbg(dev, "driver has no data for `%s' property ", attr->attr.name); |
e38053852 power_supply: fix... |
85 |
else if (ret != -ENODEV && ret != -EAGAIN) |
73b4a087b power-supply: Che... |
86 87 88 89 90 |
dev_err(dev, "driver failed to report `%s' property: %zd ", attr->attr.name, ret); return ret; } |
4a11b59d8 [BATTERY] Univers... |
91 92 93 94 95 |
} if (off == POWER_SUPPLY_PROP_STATUS) return sprintf(buf, "%s ", status_text[value.intval]); |
ee8076ed3 power_supply: Add... |
96 97 98 |
else if (off == POWER_SUPPLY_PROP_CHARGE_TYPE) return sprintf(buf, "%s ", charge_type[value.intval]); |
4a11b59d8 [BATTERY] Univers... |
99 100 101 102 103 104 |
else if (off == POWER_SUPPLY_PROP_HEALTH) return sprintf(buf, "%s ", health_text[value.intval]); else if (off == POWER_SUPPLY_PROP_TECHNOLOGY) return sprintf(buf, "%s ", technology_text[value.intval]); |
b294a290d Revert "power: re... |
105 106 107 |
else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL) return sprintf(buf, "%s ", capacity_level_text[value.intval]); |
5f487cd34 power_supply: Use... |
108 109 110 |
else if (off == POWER_SUPPLY_PROP_TYPE) return sprintf(buf, "%s ", type_text[value.intval]); |
25a0bc2df power_supply: add... |
111 112 113 |
else if (off == POWER_SUPPLY_PROP_SCOPE) return sprintf(buf, "%s ", scope_text[value.intval]); |
4a11b59d8 [BATTERY] Univers... |
114 115 116 117 118 119 120 |
else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) return sprintf(buf, "%s ", value.strval); return sprintf(buf, "%d ", value.intval); } |
0011d2d4a power_supply: Add... |
121 122 123 124 125 126 127 128 129 130 |
static ssize_t power_supply_store_property(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { ssize_t ret; struct power_supply *psy = dev_get_drvdata(dev); const ptrdiff_t off = attr - power_supply_attrs; union power_supply_propval value; long long_val; /* TODO: support other types than int */ |
f107ae11f power_supply: Rep... |
131 |
ret = kstrtol(buf, 10, &long_val); |
0011d2d4a power_supply: Add... |
132 133 134 135 |
if (ret < 0) return ret; value.intval = long_val; |
a9f6a19b5 power_supply: Use... |
136 |
ret = power_supply_set_property(psy, off, &value); |
0011d2d4a power_supply: Add... |
137 138 139 140 141 |
if (ret < 0) return ret; return count; } |
4a11b59d8 [BATTERY] Univers... |
142 143 144 145 |
/* 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), |
ee8076ed3 power_supply: Add... |
146 |
POWER_SUPPLY_ATTR(charge_type), |
4a11b59d8 [BATTERY] Univers... |
147 148 149 |
POWER_SUPPLY_ATTR(health), POWER_SUPPLY_ATTR(present), POWER_SUPPLY_ATTR(online), |
b1b56872b power_supply: Add... |
150 |
POWER_SUPPLY_ATTR(authentic), |
4a11b59d8 [BATTERY] Univers... |
151 |
POWER_SUPPLY_ATTR(technology), |
c955fe8e0 POWER: Add suppor... |
152 |
POWER_SUPPLY_ATTR(cycle_count), |
c7cc930f9 power_supply: add... |
153 154 |
POWER_SUPPLY_ATTR(voltage_max), POWER_SUPPLY_ATTR(voltage_min), |
4a11b59d8 [BATTERY] Univers... |
155 156 157 158 |
POWER_SUPPLY_ATTR(voltage_max_design), POWER_SUPPLY_ATTR(voltage_min_design), POWER_SUPPLY_ATTR(voltage_now), POWER_SUPPLY_ATTR(voltage_avg), |
a2ebfe2fc power_supply: Add... |
159 |
POWER_SUPPLY_ATTR(voltage_ocv), |
a8adcc901 power_supply: Add... |
160 |
POWER_SUPPLY_ATTR(voltage_boot), |
fe3f6d097 power_supply: Int... |
161 |
POWER_SUPPLY_ATTR(current_max), |
4a11b59d8 [BATTERY] Univers... |
162 163 |
POWER_SUPPLY_ATTR(current_now), POWER_SUPPLY_ATTR(current_avg), |
a8adcc901 power_supply: Add... |
164 |
POWER_SUPPLY_ATTR(current_boot), |
7faa144a5 ACPI: battery: ad... |
165 166 |
POWER_SUPPLY_ATTR(power_now), POWER_SUPPLY_ATTR(power_avg), |
4a11b59d8 [BATTERY] Univers... |
167 168 169 170 171 172 |
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), |
8e552c36d power_supply: add... |
173 |
POWER_SUPPLY_ATTR(charge_counter), |
3824c4771 power_supply: Add... |
174 |
POWER_SUPPLY_ATTR(constant_charge_current), |
2815b786c power_supply: Add... |
175 |
POWER_SUPPLY_ATTR(constant_charge_current_max), |
3824c4771 power_supply: Add... |
176 |
POWER_SUPPLY_ATTR(constant_charge_voltage), |
2815b786c power_supply: Add... |
177 |
POWER_SUPPLY_ATTR(constant_charge_voltage_max), |
ea2ce92e4 power_supply: Add... |
178 179 |
POWER_SUPPLY_ATTR(charge_control_limit), POWER_SUPPLY_ATTR(charge_control_limit_max), |
6bb1d272d power_supply: Add... |
180 |
POWER_SUPPLY_ATTR(input_current_limit), |
4a11b59d8 [BATTERY] Univers... |
181 182 183 184 185 186 187 |
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), |
e908c4180 power_supply: Add... |
188 189 |
POWER_SUPPLY_ATTR(capacity_alert_min), POWER_SUPPLY_ATTR(capacity_alert_max), |
b294a290d Revert "power: re... |
190 |
POWER_SUPPLY_ATTR(capacity_level), |
4a11b59d8 [BATTERY] Univers... |
191 |
POWER_SUPPLY_ATTR(temp), |
6bb1d272d power_supply: Add... |
192 193 |
POWER_SUPPLY_ATTR(temp_max), POWER_SUPPLY_ATTR(temp_min), |
e908c4180 power_supply: Add... |
194 195 |
POWER_SUPPLY_ATTR(temp_alert_min), POWER_SUPPLY_ATTR(temp_alert_max), |
4a11b59d8 [BATTERY] Univers... |
196 |
POWER_SUPPLY_ATTR(temp_ambient), |
e908c4180 power_supply: Add... |
197 198 |
POWER_SUPPLY_ATTR(temp_ambient_alert_min), POWER_SUPPLY_ATTR(temp_ambient_alert_max), |
4a11b59d8 [BATTERY] Univers... |
199 200 201 202 |
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), |
5f487cd34 power_supply: Use... |
203 |
POWER_SUPPLY_ATTR(type), |
25a0bc2df power_supply: add... |
204 |
POWER_SUPPLY_ATTR(scope), |
6bb1d272d power_supply: Add... |
205 |
POWER_SUPPLY_ATTR(charge_term_current), |
a8adcc901 power_supply: Add... |
206 |
POWER_SUPPLY_ATTR(calibrate), |
4a11b59d8 [BATTERY] Univers... |
207 208 209 |
/* Properties of type `const char *' */ POWER_SUPPLY_ATTR(model_name), POWER_SUPPLY_ATTR(manufacturer), |
7c2670bbb ACPI: battery: ad... |
210 |
POWER_SUPPLY_ATTR(serial_number), |
4a11b59d8 [BATTERY] Univers... |
211 |
}; |
5f487cd34 power_supply: Use... |
212 213 |
static struct attribute * __power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1]; |
4a11b59d8 [BATTERY] Univers... |
214 |
|
587a1f165 switch ->is_visib... |
215 |
static umode_t power_supply_attr_is_visible(struct kobject *kobj, |
5f487cd34 power_supply: Use... |
216 217 |
struct attribute *attr, int attrno) |
4a11b59d8 [BATTERY] Univers... |
218 |
{ |
5f487cd34 power_supply: Use... |
219 220 |
struct device *dev = container_of(kobj, struct device, kobj); struct power_supply *psy = dev_get_drvdata(dev); |
587a1f165 switch ->is_visib... |
221 |
umode_t mode = S_IRUSR | S_IRGRP | S_IROTH; |
5f487cd34 power_supply: Use... |
222 |
int i; |
4a11b59d8 [BATTERY] Univers... |
223 |
|
bbabb158f power_supply: Fix... |
224 225 |
if (attrno == POWER_SUPPLY_PROP_TYPE) return mode; |
297d716f6 power_supply: Cha... |
226 227 |
for (i = 0; i < psy->desc->num_properties; i++) { int property = psy->desc->properties[i]; |
0011d2d4a power_supply: Add... |
228 229 |
if (property == attrno) { |
297d716f6 power_supply: Cha... |
230 |
if (psy->desc->property_is_writeable && |
5c6e3a97e power_supply: sys... |
231 |
psy->desc->property_is_writeable(psy, property) > 0) |
0011d2d4a power_supply: Add... |
232 233 234 235 |
mode |= S_IWUSR; return mode; } |
4a11b59d8 [BATTERY] Univers... |
236 |
} |
5f487cd34 power_supply: Use... |
237 |
return 0; |
4a11b59d8 [BATTERY] Univers... |
238 |
} |
5f487cd34 power_supply: Use... |
239 240 241 242 243 244 245 246 247 248 249 |
static struct attribute_group power_supply_attr_group = { .attrs = __power_supply_attrs, .is_visible = power_supply_attr_is_visible, }; static const struct attribute_group *power_supply_attr_groups[] = { &power_supply_attr_group, NULL, }; void power_supply_init_attrs(struct device_type *dev_type) |
4a11b59d8 [BATTERY] Univers... |
250 251 |
{ int i; |
5f487cd34 power_supply: Use... |
252 |
dev_type->groups = power_supply_attr_groups; |
4a11b59d8 [BATTERY] Univers... |
253 |
|
5f487cd34 power_supply: Use... |
254 255 |
for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) __power_supply_attrs[i] = &power_supply_attrs[i].attr; |
4a11b59d8 [BATTERY] Univers... |
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
} static char *kstruprdup(const char *str, gfp_t gfp) { char *ret, *ustr; ustr = ret = kmalloc(strlen(str) + 1, gfp); if (!ret) return NULL; while (*str) *ustr++ = toupper(*str++); *ustr = 0; return ret; } |
7eff2e7a8 Driver core: chan... |
274 |
int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) |
4a11b59d8 [BATTERY] Univers... |
275 276 |
{ struct power_supply *psy = dev_get_drvdata(dev); |
7eff2e7a8 Driver core: chan... |
277 |
int ret = 0, j; |
4a11b59d8 [BATTERY] Univers... |
278 279 280 281 282 |
char *prop_buf; char *attrname; dev_dbg(dev, "uevent "); |
297d716f6 power_supply: Cha... |
283 |
if (!psy || !psy->desc) { |
4a11b59d8 [BATTERY] Univers... |
284 285 286 287 |
dev_dbg(dev, "No power supply yet "); return ret; } |
297d716f6 power_supply: Cha... |
288 289 |
dev_dbg(dev, "POWER_SUPPLY_NAME=%s ", psy->desc->name); |
4a11b59d8 [BATTERY] Univers... |
290 |
|
297d716f6 power_supply: Cha... |
291 |
ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->desc->name); |
4a11b59d8 [BATTERY] Univers... |
292 293 294 295 296 297 |
if (ret) return ret; prop_buf = (char *)get_zeroed_page(GFP_KERNEL); if (!prop_buf) return -ENOMEM; |
297d716f6 power_supply: Cha... |
298 |
for (j = 0; j < psy->desc->num_properties; j++) { |
4a11b59d8 [BATTERY] Univers... |
299 300 |
struct device_attribute *attr; char *line; |
297d716f6 power_supply: Cha... |
301 |
attr = &power_supply_attrs[psy->desc->properties[j]]; |
4a11b59d8 [BATTERY] Univers... |
302 303 |
ret = power_supply_show_property(dev, attr, prop_buf); |
f722e17fd power_supply: Ign... |
304 |
if (ret == -ENODEV || ret == -ENODATA) { |
4a11b59d8 [BATTERY] Univers... |
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
/* When a battery is absent, we expect -ENODEV. Don't abort; send the uevent with at least the the PRESENT=0 property */ ret = 0; continue; } if (ret < 0) goto out; line = strchr(prop_buf, ' '); if (line) *line = 0; attrname = kstruprdup(attr->attr.name, GFP_KERNEL); if (!attrname) { ret = -ENOMEM; goto out; } dev_dbg(dev, "prop %s=%s ", attrname, prop_buf); |
7eff2e7a8 Driver core: chan... |
327 |
ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); |
4a11b59d8 [BATTERY] Univers... |
328 329 330 331 332 333 334 335 336 337 |
kfree(attrname); if (ret) goto out; } out: free_page((unsigned long)prop_buf); return ret; } |