GNU Linux-libre 5.10.217-gnu1
[releases.git] / drivers / power / supply / power_supply_sysfs.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Sysfs interface for the universal power supply monitor class
4  *
5  *  Copyright © 2007  David Woodhouse <dwmw2@infradead.org>
6  *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
7  *  Copyright © 2004  Szabolcs Gyurko
8  *  Copyright © 2003  Ian Molton <spyro@f2s.com>
9  *
10  *  Modified: 2004, Oct     Szabolcs Gyurko
11  */
12
13 #include <linux/ctype.h>
14 #include <linux/device.h>
15 #include <linux/power_supply.h>
16 #include <linux/slab.h>
17 #include <linux/stat.h>
18
19 #include "power_supply.h"
20
21 #define MAX_PROP_NAME_LEN 30
22
23 struct power_supply_attr {
24         const char *prop_name;
25         char attr_name[MAX_PROP_NAME_LEN + 1];
26         struct device_attribute dev_attr;
27         const char * const *text_values;
28         int text_values_len;
29 };
30
31 #define _POWER_SUPPLY_ATTR(_name, _text, _len)  \
32 [POWER_SUPPLY_PROP_ ## _name] =                 \
33 {                                               \
34         .prop_name = #_name,                    \
35         .attr_name = #_name "\0",               \
36         .text_values = _text,                   \
37         .text_values_len = _len,                \
38 }
39
40 #define POWER_SUPPLY_ATTR(_name) _POWER_SUPPLY_ATTR(_name, NULL, 0)
41 #define _POWER_SUPPLY_ENUM_ATTR(_name, _text)   \
42         _POWER_SUPPLY_ATTR(_name, _text, ARRAY_SIZE(_text))
43 #define POWER_SUPPLY_ENUM_ATTR(_name)   \
44         _POWER_SUPPLY_ENUM_ATTR(_name, POWER_SUPPLY_ ## _name ## _TEXT)
45
46 static const char * const POWER_SUPPLY_TYPE_TEXT[] = {
47         [POWER_SUPPLY_TYPE_UNKNOWN]             = "Unknown",
48         [POWER_SUPPLY_TYPE_BATTERY]             = "Battery",
49         [POWER_SUPPLY_TYPE_UPS]                 = "UPS",
50         [POWER_SUPPLY_TYPE_MAINS]               = "Mains",
51         [POWER_SUPPLY_TYPE_USB]                 = "USB",
52         [POWER_SUPPLY_TYPE_USB_DCP]             = "USB_DCP",
53         [POWER_SUPPLY_TYPE_USB_CDP]             = "USB_CDP",
54         [POWER_SUPPLY_TYPE_USB_ACA]             = "USB_ACA",
55         [POWER_SUPPLY_TYPE_USB_TYPE_C]          = "USB_C",
56         [POWER_SUPPLY_TYPE_USB_PD]              = "USB_PD",
57         [POWER_SUPPLY_TYPE_USB_PD_DRP]          = "USB_PD_DRP",
58         [POWER_SUPPLY_TYPE_APPLE_BRICK_ID]      = "BrickID",
59         [POWER_SUPPLY_TYPE_WIRELESS]            = "Wireless",
60 };
61
62 static const char * const POWER_SUPPLY_USB_TYPE_TEXT[] = {
63         [POWER_SUPPLY_USB_TYPE_UNKNOWN]         = "Unknown",
64         [POWER_SUPPLY_USB_TYPE_SDP]             = "SDP",
65         [POWER_SUPPLY_USB_TYPE_DCP]             = "DCP",
66         [POWER_SUPPLY_USB_TYPE_CDP]             = "CDP",
67         [POWER_SUPPLY_USB_TYPE_ACA]             = "ACA",
68         [POWER_SUPPLY_USB_TYPE_C]               = "C",
69         [POWER_SUPPLY_USB_TYPE_PD]              = "PD",
70         [POWER_SUPPLY_USB_TYPE_PD_DRP]          = "PD_DRP",
71         [POWER_SUPPLY_USB_TYPE_PD_PPS]          = "PD_PPS",
72         [POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID]  = "BrickID",
73 };
74
75 static const char * const POWER_SUPPLY_STATUS_TEXT[] = {
76         [POWER_SUPPLY_STATUS_UNKNOWN]           = "Unknown",
77         [POWER_SUPPLY_STATUS_CHARGING]          = "Charging",
78         [POWER_SUPPLY_STATUS_DISCHARGING]       = "Discharging",
79         [POWER_SUPPLY_STATUS_NOT_CHARGING]      = "Not charging",
80         [POWER_SUPPLY_STATUS_FULL]              = "Full",
81 };
82
83 static const char * const POWER_SUPPLY_CHARGE_TYPE_TEXT[] = {
84         [POWER_SUPPLY_CHARGE_TYPE_UNKNOWN]      = "Unknown",
85         [POWER_SUPPLY_CHARGE_TYPE_NONE]         = "N/A",
86         [POWER_SUPPLY_CHARGE_TYPE_TRICKLE]      = "Trickle",
87         [POWER_SUPPLY_CHARGE_TYPE_FAST]         = "Fast",
88         [POWER_SUPPLY_CHARGE_TYPE_STANDARD]     = "Standard",
89         [POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE]     = "Adaptive",
90         [POWER_SUPPLY_CHARGE_TYPE_CUSTOM]       = "Custom",
91         [POWER_SUPPLY_CHARGE_TYPE_LONGLIFE]     = "Long Life",
92 };
93
94 static const char * const POWER_SUPPLY_HEALTH_TEXT[] = {
95         [POWER_SUPPLY_HEALTH_UNKNOWN]               = "Unknown",
96         [POWER_SUPPLY_HEALTH_GOOD]                  = "Good",
97         [POWER_SUPPLY_HEALTH_OVERHEAT]              = "Overheat",
98         [POWER_SUPPLY_HEALTH_DEAD]                  = "Dead",
99         [POWER_SUPPLY_HEALTH_OVERVOLTAGE]           = "Over voltage",
100         [POWER_SUPPLY_HEALTH_UNSPEC_FAILURE]        = "Unspecified failure",
101         [POWER_SUPPLY_HEALTH_COLD]                  = "Cold",
102         [POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE] = "Watchdog timer expire",
103         [POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE]   = "Safety timer expire",
104         [POWER_SUPPLY_HEALTH_OVERCURRENT]           = "Over current",
105         [POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED]  = "Calibration required",
106         [POWER_SUPPLY_HEALTH_WARM]                  = "Warm",
107         [POWER_SUPPLY_HEALTH_COOL]                  = "Cool",
108         [POWER_SUPPLY_HEALTH_HOT]                   = "Hot",
109 };
110
111 static const char * const POWER_SUPPLY_TECHNOLOGY_TEXT[] = {
112         [POWER_SUPPLY_TECHNOLOGY_UNKNOWN]       = "Unknown",
113         [POWER_SUPPLY_TECHNOLOGY_NiMH]          = "NiMH",
114         [POWER_SUPPLY_TECHNOLOGY_LION]          = "Li-ion",
115         [POWER_SUPPLY_TECHNOLOGY_LIPO]          = "Li-poly",
116         [POWER_SUPPLY_TECHNOLOGY_LiFe]          = "LiFe",
117         [POWER_SUPPLY_TECHNOLOGY_NiCd]          = "NiCd",
118         [POWER_SUPPLY_TECHNOLOGY_LiMn]          = "LiMn",
119 };
120
121 static const char * const POWER_SUPPLY_CAPACITY_LEVEL_TEXT[] = {
122         [POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN]   = "Unknown",
123         [POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL]  = "Critical",
124         [POWER_SUPPLY_CAPACITY_LEVEL_LOW]       = "Low",
125         [POWER_SUPPLY_CAPACITY_LEVEL_NORMAL]    = "Normal",
126         [POWER_SUPPLY_CAPACITY_LEVEL_HIGH]      = "High",
127         [POWER_SUPPLY_CAPACITY_LEVEL_FULL]      = "Full",
128 };
129
130 static const char * const POWER_SUPPLY_SCOPE_TEXT[] = {
131         [POWER_SUPPLY_SCOPE_UNKNOWN]    = "Unknown",
132         [POWER_SUPPLY_SCOPE_SYSTEM]     = "System",
133         [POWER_SUPPLY_SCOPE_DEVICE]     = "Device",
134 };
135
136 static struct power_supply_attr power_supply_attrs[] = {
137         /* Properties of type `int' */
138         POWER_SUPPLY_ENUM_ATTR(STATUS),
139         POWER_SUPPLY_ENUM_ATTR(CHARGE_TYPE),
140         POWER_SUPPLY_ENUM_ATTR(HEALTH),
141         POWER_SUPPLY_ATTR(PRESENT),
142         POWER_SUPPLY_ATTR(ONLINE),
143         POWER_SUPPLY_ATTR(AUTHENTIC),
144         POWER_SUPPLY_ENUM_ATTR(TECHNOLOGY),
145         POWER_SUPPLY_ATTR(CYCLE_COUNT),
146         POWER_SUPPLY_ATTR(VOLTAGE_MAX),
147         POWER_SUPPLY_ATTR(VOLTAGE_MIN),
148         POWER_SUPPLY_ATTR(VOLTAGE_MAX_DESIGN),
149         POWER_SUPPLY_ATTR(VOLTAGE_MIN_DESIGN),
150         POWER_SUPPLY_ATTR(VOLTAGE_NOW),
151         POWER_SUPPLY_ATTR(VOLTAGE_AVG),
152         POWER_SUPPLY_ATTR(VOLTAGE_OCV),
153         POWER_SUPPLY_ATTR(VOLTAGE_BOOT),
154         POWER_SUPPLY_ATTR(CURRENT_MAX),
155         POWER_SUPPLY_ATTR(CURRENT_NOW),
156         POWER_SUPPLY_ATTR(CURRENT_AVG),
157         POWER_SUPPLY_ATTR(CURRENT_BOOT),
158         POWER_SUPPLY_ATTR(POWER_NOW),
159         POWER_SUPPLY_ATTR(POWER_AVG),
160         POWER_SUPPLY_ATTR(CHARGE_FULL_DESIGN),
161         POWER_SUPPLY_ATTR(CHARGE_EMPTY_DESIGN),
162         POWER_SUPPLY_ATTR(CHARGE_FULL),
163         POWER_SUPPLY_ATTR(CHARGE_EMPTY),
164         POWER_SUPPLY_ATTR(CHARGE_NOW),
165         POWER_SUPPLY_ATTR(CHARGE_AVG),
166         POWER_SUPPLY_ATTR(CHARGE_COUNTER),
167         POWER_SUPPLY_ATTR(CONSTANT_CHARGE_CURRENT),
168         POWER_SUPPLY_ATTR(CONSTANT_CHARGE_CURRENT_MAX),
169         POWER_SUPPLY_ATTR(CONSTANT_CHARGE_VOLTAGE),
170         POWER_SUPPLY_ATTR(CONSTANT_CHARGE_VOLTAGE_MAX),
171         POWER_SUPPLY_ATTR(CHARGE_CONTROL_LIMIT),
172         POWER_SUPPLY_ATTR(CHARGE_CONTROL_LIMIT_MAX),
173         POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD),
174         POWER_SUPPLY_ATTR(CHARGE_CONTROL_END_THRESHOLD),
175         POWER_SUPPLY_ATTR(INPUT_CURRENT_LIMIT),
176         POWER_SUPPLY_ATTR(INPUT_VOLTAGE_LIMIT),
177         POWER_SUPPLY_ATTR(INPUT_POWER_LIMIT),
178         POWER_SUPPLY_ATTR(ENERGY_FULL_DESIGN),
179         POWER_SUPPLY_ATTR(ENERGY_EMPTY_DESIGN),
180         POWER_SUPPLY_ATTR(ENERGY_FULL),
181         POWER_SUPPLY_ATTR(ENERGY_EMPTY),
182         POWER_SUPPLY_ATTR(ENERGY_NOW),
183         POWER_SUPPLY_ATTR(ENERGY_AVG),
184         POWER_SUPPLY_ATTR(CAPACITY),
185         POWER_SUPPLY_ATTR(CAPACITY_ALERT_MIN),
186         POWER_SUPPLY_ATTR(CAPACITY_ALERT_MAX),
187         POWER_SUPPLY_ATTR(CAPACITY_ERROR_MARGIN),
188         POWER_SUPPLY_ENUM_ATTR(CAPACITY_LEVEL),
189         POWER_SUPPLY_ATTR(TEMP),
190         POWER_SUPPLY_ATTR(TEMP_MAX),
191         POWER_SUPPLY_ATTR(TEMP_MIN),
192         POWER_SUPPLY_ATTR(TEMP_ALERT_MIN),
193         POWER_SUPPLY_ATTR(TEMP_ALERT_MAX),
194         POWER_SUPPLY_ATTR(TEMP_AMBIENT),
195         POWER_SUPPLY_ATTR(TEMP_AMBIENT_ALERT_MIN),
196         POWER_SUPPLY_ATTR(TEMP_AMBIENT_ALERT_MAX),
197         POWER_SUPPLY_ATTR(TIME_TO_EMPTY_NOW),
198         POWER_SUPPLY_ATTR(TIME_TO_EMPTY_AVG),
199         POWER_SUPPLY_ATTR(TIME_TO_FULL_NOW),
200         POWER_SUPPLY_ATTR(TIME_TO_FULL_AVG),
201         POWER_SUPPLY_ENUM_ATTR(TYPE),
202         POWER_SUPPLY_ATTR(USB_TYPE),
203         POWER_SUPPLY_ENUM_ATTR(SCOPE),
204         POWER_SUPPLY_ATTR(PRECHARGE_CURRENT),
205         POWER_SUPPLY_ATTR(CHARGE_TERM_CURRENT),
206         POWER_SUPPLY_ATTR(CALIBRATE),
207         POWER_SUPPLY_ATTR(MANUFACTURE_YEAR),
208         POWER_SUPPLY_ATTR(MANUFACTURE_MONTH),
209         POWER_SUPPLY_ATTR(MANUFACTURE_DAY),
210         /* Properties of type `const char *' */
211         POWER_SUPPLY_ATTR(MODEL_NAME),
212         POWER_SUPPLY_ATTR(MANUFACTURER),
213         POWER_SUPPLY_ATTR(SERIAL_NUMBER),
214 };
215
216 static struct attribute *
217 __power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1];
218
219 static struct power_supply_attr *to_ps_attr(struct device_attribute *attr)
220 {
221         return container_of(attr, struct power_supply_attr, dev_attr);
222 }
223
224 static enum power_supply_property dev_attr_psp(struct device_attribute *attr)
225 {
226         return  to_ps_attr(attr) - power_supply_attrs;
227 }
228
229 static ssize_t power_supply_show_usb_type(struct device *dev,
230                                           const struct power_supply_desc *desc,
231                                           union power_supply_propval *value,
232                                           char *buf)
233 {
234         enum power_supply_usb_type usb_type;
235         ssize_t count = 0;
236         bool match = false;
237         int i;
238
239         for (i = 0; i < desc->num_usb_types; ++i) {
240                 usb_type = desc->usb_types[i];
241
242                 if (value->intval == usb_type) {
243                         count += sprintf(buf + count, "[%s] ",
244                                          POWER_SUPPLY_USB_TYPE_TEXT[usb_type]);
245                         match = true;
246                 } else {
247                         count += sprintf(buf + count, "%s ",
248                                          POWER_SUPPLY_USB_TYPE_TEXT[usb_type]);
249                 }
250         }
251
252         if (!match) {
253                 dev_warn(dev, "driver reporting unsupported connected type\n");
254                 return -EINVAL;
255         }
256
257         if (count)
258                 buf[count - 1] = '\n';
259
260         return count;
261 }
262
263 static ssize_t power_supply_show_property(struct device *dev,
264                                           struct device_attribute *attr,
265                                           char *buf) {
266         ssize_t ret;
267         struct power_supply *psy = dev_get_drvdata(dev);
268         struct power_supply_attr *ps_attr = to_ps_attr(attr);
269         enum power_supply_property psp = dev_attr_psp(attr);
270         union power_supply_propval value;
271
272         if (psp == POWER_SUPPLY_PROP_TYPE) {
273                 value.intval = psy->desc->type;
274         } else {
275                 ret = power_supply_get_property(psy, psp, &value);
276
277                 if (ret < 0) {
278                         if (ret == -ENODATA)
279                                 dev_dbg_ratelimited(dev,
280                                         "driver has no data for `%s' property\n",
281                                         attr->attr.name);
282                         else if (ret != -ENODEV && ret != -EAGAIN)
283                                 dev_err_ratelimited(dev,
284                                         "driver failed to report `%s' property: %zd\n",
285                                         attr->attr.name, ret);
286                         return ret;
287                 }
288         }
289
290         if (ps_attr->text_values_len > 0 &&
291             value.intval < ps_attr->text_values_len && value.intval >= 0) {
292                 return sprintf(buf, "%s\n", ps_attr->text_values[value.intval]);
293         }
294
295         switch (psp) {
296         case POWER_SUPPLY_PROP_USB_TYPE:
297                 ret = power_supply_show_usb_type(dev, psy->desc,
298                                                 &value, buf);
299                 break;
300         case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER:
301                 ret = sprintf(buf, "%s\n", value.strval);
302                 break;
303         default:
304                 ret = sprintf(buf, "%d\n", value.intval);
305         }
306
307         return ret;
308 }
309
310 static ssize_t power_supply_store_property(struct device *dev,
311                                            struct device_attribute *attr,
312                                            const char *buf, size_t count) {
313         ssize_t ret;
314         struct power_supply *psy = dev_get_drvdata(dev);
315         struct power_supply_attr *ps_attr = to_ps_attr(attr);
316         enum power_supply_property psp = dev_attr_psp(attr);
317         union power_supply_propval value;
318
319         ret = -EINVAL;
320         if (ps_attr->text_values_len > 0) {
321                 ret = __sysfs_match_string(ps_attr->text_values,
322                                            ps_attr->text_values_len, buf);
323         }
324
325         /*
326          * If no match was found, then check to see if it is an integer.
327          * Integer values are valid for enums in addition to the text value.
328          */
329         if (ret < 0) {
330                 long long_val;
331
332                 ret = kstrtol(buf, 10, &long_val);
333                 if (ret < 0)
334                         return ret;
335
336                 ret = long_val;
337         }
338
339         value.intval = ret;
340
341         ret = power_supply_set_property(psy, psp, &value);
342         if (ret < 0)
343                 return ret;
344
345         return count;
346 }
347
348 static umode_t power_supply_attr_is_visible(struct kobject *kobj,
349                                            struct attribute *attr,
350                                            int attrno)
351 {
352         struct device *dev = kobj_to_dev(kobj);
353         struct power_supply *psy = dev_get_drvdata(dev);
354         umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
355         int i;
356
357         if (!power_supply_attrs[attrno].prop_name)
358                 return 0;
359
360         if (attrno == POWER_SUPPLY_PROP_TYPE)
361                 return mode;
362
363         for (i = 0; i < psy->desc->num_properties; i++) {
364                 int property = psy->desc->properties[i];
365
366                 if (property == attrno) {
367                         if (psy->desc->property_is_writeable &&
368                             psy->desc->property_is_writeable(psy, property) > 0)
369                                 mode |= S_IWUSR;
370
371                         return mode;
372                 }
373         }
374
375         return 0;
376 }
377
378 static struct attribute_group power_supply_attr_group = {
379         .attrs = __power_supply_attrs,
380         .is_visible = power_supply_attr_is_visible,
381 };
382
383 static const struct attribute_group *power_supply_attr_groups[] = {
384         &power_supply_attr_group,
385         NULL,
386 };
387
388 static void str_to_lower(char *str)
389 {
390         while (*str) {
391                 *str = tolower(*str);
392                 str++;
393         }
394 }
395
396 void power_supply_init_attrs(struct device_type *dev_type)
397 {
398         int i;
399
400         dev_type->groups = power_supply_attr_groups;
401
402         for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) {
403                 struct device_attribute *attr;
404
405                 if (!power_supply_attrs[i].prop_name) {
406                         pr_warn("%s: Property %d skipped because is is missing from power_supply_attrs\n",
407                                 __func__, i);
408                         sprintf(power_supply_attrs[i].attr_name, "_err_%d", i);
409                 } else {
410                         str_to_lower(power_supply_attrs[i].attr_name);
411                 }
412
413                 attr = &power_supply_attrs[i].dev_attr;
414
415                 attr->attr.name = power_supply_attrs[i].attr_name;
416                 attr->show = power_supply_show_property;
417                 attr->store = power_supply_store_property;
418                 __power_supply_attrs[i] = &attr->attr;
419         }
420 }
421
422 static int add_prop_uevent(struct device *dev, struct kobj_uevent_env *env,
423                            enum power_supply_property prop, char *prop_buf)
424 {
425         int ret = 0;
426         struct power_supply_attr *pwr_attr;
427         struct device_attribute *dev_attr;
428         char *line;
429
430         pwr_attr = &power_supply_attrs[prop];
431         dev_attr = &pwr_attr->dev_attr;
432
433         ret = power_supply_show_property(dev, dev_attr, prop_buf);
434         if (ret == -ENODEV || ret == -ENODATA) {
435                 /*
436                  * When a battery is absent, we expect -ENODEV. Don't abort;
437                  * send the uevent with at least the the PRESENT=0 property
438                  */
439                 return 0;
440         }
441
442         if (ret < 0)
443                 return ret;
444
445         line = strchr(prop_buf, '\n');
446         if (line)
447                 *line = 0;
448
449         return add_uevent_var(env, "POWER_SUPPLY_%s=%s",
450                               pwr_attr->prop_name, prop_buf);
451 }
452
453 int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
454 {
455         struct power_supply *psy = dev_get_drvdata(dev);
456         int ret = 0, j;
457         char *prop_buf;
458
459         if (!psy || !psy->desc) {
460                 dev_dbg(dev, "No power supply yet\n");
461                 return ret;
462         }
463
464         ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->desc->name);
465         if (ret)
466                 return ret;
467
468         prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
469         if (!prop_buf)
470                 return -ENOMEM;
471
472         ret = add_prop_uevent(dev, env, POWER_SUPPLY_PROP_TYPE, prop_buf);
473         if (ret)
474                 goto out;
475
476         for (j = 0; j < psy->desc->num_properties; j++) {
477                 ret = add_prop_uevent(dev, env, psy->desc->properties[j],
478                                       prop_buf);
479                 if (ret)
480                         goto out;
481         }
482
483 out:
484         free_page((unsigned long)prop_buf);
485
486         return ret;
487 }