0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/ctype.h>
0014 #include <linux/device.h>
0015 #include <linux/power_supply.h>
0016 #include <linux/slab.h>
0017 #include <linux/stat.h>
0018
0019 #include "power_supply.h"
0020
0021 #define MAX_PROP_NAME_LEN 30
0022
0023 struct power_supply_attr {
0024 const char *prop_name;
0025 char attr_name[MAX_PROP_NAME_LEN + 1];
0026 struct device_attribute dev_attr;
0027 const char * const *text_values;
0028 int text_values_len;
0029 };
0030
0031 #define _POWER_SUPPLY_ATTR(_name, _text, _len) \
0032 [POWER_SUPPLY_PROP_ ## _name] = \
0033 { \
0034 .prop_name = #_name, \
0035 .attr_name = #_name "\0", \
0036 .text_values = _text, \
0037 .text_values_len = _len, \
0038 }
0039
0040 #define POWER_SUPPLY_ATTR(_name) _POWER_SUPPLY_ATTR(_name, NULL, 0)
0041 #define _POWER_SUPPLY_ENUM_ATTR(_name, _text) \
0042 _POWER_SUPPLY_ATTR(_name, _text, ARRAY_SIZE(_text))
0043 #define POWER_SUPPLY_ENUM_ATTR(_name) \
0044 _POWER_SUPPLY_ENUM_ATTR(_name, POWER_SUPPLY_ ## _name ## _TEXT)
0045
0046 static const char * const POWER_SUPPLY_TYPE_TEXT[] = {
0047 [POWER_SUPPLY_TYPE_UNKNOWN] = "Unknown",
0048 [POWER_SUPPLY_TYPE_BATTERY] = "Battery",
0049 [POWER_SUPPLY_TYPE_UPS] = "UPS",
0050 [POWER_SUPPLY_TYPE_MAINS] = "Mains",
0051 [POWER_SUPPLY_TYPE_USB] = "USB",
0052 [POWER_SUPPLY_TYPE_USB_DCP] = "USB_DCP",
0053 [POWER_SUPPLY_TYPE_USB_CDP] = "USB_CDP",
0054 [POWER_SUPPLY_TYPE_USB_ACA] = "USB_ACA",
0055 [POWER_SUPPLY_TYPE_USB_TYPE_C] = "USB_C",
0056 [POWER_SUPPLY_TYPE_USB_PD] = "USB_PD",
0057 [POWER_SUPPLY_TYPE_USB_PD_DRP] = "USB_PD_DRP",
0058 [POWER_SUPPLY_TYPE_APPLE_BRICK_ID] = "BrickID",
0059 [POWER_SUPPLY_TYPE_WIRELESS] = "Wireless",
0060 };
0061
0062 static const char * const POWER_SUPPLY_USB_TYPE_TEXT[] = {
0063 [POWER_SUPPLY_USB_TYPE_UNKNOWN] = "Unknown",
0064 [POWER_SUPPLY_USB_TYPE_SDP] = "SDP",
0065 [POWER_SUPPLY_USB_TYPE_DCP] = "DCP",
0066 [POWER_SUPPLY_USB_TYPE_CDP] = "CDP",
0067 [POWER_SUPPLY_USB_TYPE_ACA] = "ACA",
0068 [POWER_SUPPLY_USB_TYPE_C] = "C",
0069 [POWER_SUPPLY_USB_TYPE_PD] = "PD",
0070 [POWER_SUPPLY_USB_TYPE_PD_DRP] = "PD_DRP",
0071 [POWER_SUPPLY_USB_TYPE_PD_PPS] = "PD_PPS",
0072 [POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID] = "BrickID",
0073 };
0074
0075 static const char * const POWER_SUPPLY_STATUS_TEXT[] = {
0076 [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown",
0077 [POWER_SUPPLY_STATUS_CHARGING] = "Charging",
0078 [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging",
0079 [POWER_SUPPLY_STATUS_NOT_CHARGING] = "Not charging",
0080 [POWER_SUPPLY_STATUS_FULL] = "Full",
0081 };
0082
0083 static const char * const POWER_SUPPLY_CHARGE_TYPE_TEXT[] = {
0084 [POWER_SUPPLY_CHARGE_TYPE_UNKNOWN] = "Unknown",
0085 [POWER_SUPPLY_CHARGE_TYPE_NONE] = "N/A",
0086 [POWER_SUPPLY_CHARGE_TYPE_TRICKLE] = "Trickle",
0087 [POWER_SUPPLY_CHARGE_TYPE_FAST] = "Fast",
0088 [POWER_SUPPLY_CHARGE_TYPE_STANDARD] = "Standard",
0089 [POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE] = "Adaptive",
0090 [POWER_SUPPLY_CHARGE_TYPE_CUSTOM] = "Custom",
0091 [POWER_SUPPLY_CHARGE_TYPE_LONGLIFE] = "Long Life",
0092 [POWER_SUPPLY_CHARGE_TYPE_BYPASS] = "Bypass",
0093 };
0094
0095 static const char * const POWER_SUPPLY_HEALTH_TEXT[] = {
0096 [POWER_SUPPLY_HEALTH_UNKNOWN] = "Unknown",
0097 [POWER_SUPPLY_HEALTH_GOOD] = "Good",
0098 [POWER_SUPPLY_HEALTH_OVERHEAT] = "Overheat",
0099 [POWER_SUPPLY_HEALTH_DEAD] = "Dead",
0100 [POWER_SUPPLY_HEALTH_OVERVOLTAGE] = "Over voltage",
0101 [POWER_SUPPLY_HEALTH_UNSPEC_FAILURE] = "Unspecified failure",
0102 [POWER_SUPPLY_HEALTH_COLD] = "Cold",
0103 [POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE] = "Watchdog timer expire",
0104 [POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE] = "Safety timer expire",
0105 [POWER_SUPPLY_HEALTH_OVERCURRENT] = "Over current",
0106 [POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED] = "Calibration required",
0107 [POWER_SUPPLY_HEALTH_WARM] = "Warm",
0108 [POWER_SUPPLY_HEALTH_COOL] = "Cool",
0109 [POWER_SUPPLY_HEALTH_HOT] = "Hot",
0110 [POWER_SUPPLY_HEALTH_NO_BATTERY] = "No battery",
0111 };
0112
0113 static const char * const POWER_SUPPLY_TECHNOLOGY_TEXT[] = {
0114 [POWER_SUPPLY_TECHNOLOGY_UNKNOWN] = "Unknown",
0115 [POWER_SUPPLY_TECHNOLOGY_NiMH] = "NiMH",
0116 [POWER_SUPPLY_TECHNOLOGY_LION] = "Li-ion",
0117 [POWER_SUPPLY_TECHNOLOGY_LIPO] = "Li-poly",
0118 [POWER_SUPPLY_TECHNOLOGY_LiFe] = "LiFe",
0119 [POWER_SUPPLY_TECHNOLOGY_NiCd] = "NiCd",
0120 [POWER_SUPPLY_TECHNOLOGY_LiMn] = "LiMn",
0121 };
0122
0123 static const char * const POWER_SUPPLY_CAPACITY_LEVEL_TEXT[] = {
0124 [POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN] = "Unknown",
0125 [POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL] = "Critical",
0126 [POWER_SUPPLY_CAPACITY_LEVEL_LOW] = "Low",
0127 [POWER_SUPPLY_CAPACITY_LEVEL_NORMAL] = "Normal",
0128 [POWER_SUPPLY_CAPACITY_LEVEL_HIGH] = "High",
0129 [POWER_SUPPLY_CAPACITY_LEVEL_FULL] = "Full",
0130 };
0131
0132 static const char * const POWER_SUPPLY_SCOPE_TEXT[] = {
0133 [POWER_SUPPLY_SCOPE_UNKNOWN] = "Unknown",
0134 [POWER_SUPPLY_SCOPE_SYSTEM] = "System",
0135 [POWER_SUPPLY_SCOPE_DEVICE] = "Device",
0136 };
0137
0138 static const char * const POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[] = {
0139 [POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO] = "auto",
0140 [POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE] = "inhibit-charge",
0141 [POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE] = "force-discharge",
0142 };
0143
0144 static struct power_supply_attr power_supply_attrs[] = {
0145
0146 POWER_SUPPLY_ENUM_ATTR(STATUS),
0147 POWER_SUPPLY_ENUM_ATTR(CHARGE_TYPE),
0148 POWER_SUPPLY_ENUM_ATTR(HEALTH),
0149 POWER_SUPPLY_ATTR(PRESENT),
0150 POWER_SUPPLY_ATTR(ONLINE),
0151 POWER_SUPPLY_ATTR(AUTHENTIC),
0152 POWER_SUPPLY_ENUM_ATTR(TECHNOLOGY),
0153 POWER_SUPPLY_ATTR(CYCLE_COUNT),
0154 POWER_SUPPLY_ATTR(VOLTAGE_MAX),
0155 POWER_SUPPLY_ATTR(VOLTAGE_MIN),
0156 POWER_SUPPLY_ATTR(VOLTAGE_MAX_DESIGN),
0157 POWER_SUPPLY_ATTR(VOLTAGE_MIN_DESIGN),
0158 POWER_SUPPLY_ATTR(VOLTAGE_NOW),
0159 POWER_SUPPLY_ATTR(VOLTAGE_AVG),
0160 POWER_SUPPLY_ATTR(VOLTAGE_OCV),
0161 POWER_SUPPLY_ATTR(VOLTAGE_BOOT),
0162 POWER_SUPPLY_ATTR(CURRENT_MAX),
0163 POWER_SUPPLY_ATTR(CURRENT_NOW),
0164 POWER_SUPPLY_ATTR(CURRENT_AVG),
0165 POWER_SUPPLY_ATTR(CURRENT_BOOT),
0166 POWER_SUPPLY_ATTR(POWER_NOW),
0167 POWER_SUPPLY_ATTR(POWER_AVG),
0168 POWER_SUPPLY_ATTR(CHARGE_FULL_DESIGN),
0169 POWER_SUPPLY_ATTR(CHARGE_EMPTY_DESIGN),
0170 POWER_SUPPLY_ATTR(CHARGE_FULL),
0171 POWER_SUPPLY_ATTR(CHARGE_EMPTY),
0172 POWER_SUPPLY_ATTR(CHARGE_NOW),
0173 POWER_SUPPLY_ATTR(CHARGE_AVG),
0174 POWER_SUPPLY_ATTR(CHARGE_COUNTER),
0175 POWER_SUPPLY_ATTR(CONSTANT_CHARGE_CURRENT),
0176 POWER_SUPPLY_ATTR(CONSTANT_CHARGE_CURRENT_MAX),
0177 POWER_SUPPLY_ATTR(CONSTANT_CHARGE_VOLTAGE),
0178 POWER_SUPPLY_ATTR(CONSTANT_CHARGE_VOLTAGE_MAX),
0179 POWER_SUPPLY_ATTR(CHARGE_CONTROL_LIMIT),
0180 POWER_SUPPLY_ATTR(CHARGE_CONTROL_LIMIT_MAX),
0181 POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD),
0182 POWER_SUPPLY_ATTR(CHARGE_CONTROL_END_THRESHOLD),
0183 POWER_SUPPLY_ENUM_ATTR(CHARGE_BEHAVIOUR),
0184 POWER_SUPPLY_ATTR(INPUT_CURRENT_LIMIT),
0185 POWER_SUPPLY_ATTR(INPUT_VOLTAGE_LIMIT),
0186 POWER_SUPPLY_ATTR(INPUT_POWER_LIMIT),
0187 POWER_SUPPLY_ATTR(ENERGY_FULL_DESIGN),
0188 POWER_SUPPLY_ATTR(ENERGY_EMPTY_DESIGN),
0189 POWER_SUPPLY_ATTR(ENERGY_FULL),
0190 POWER_SUPPLY_ATTR(ENERGY_EMPTY),
0191 POWER_SUPPLY_ATTR(ENERGY_NOW),
0192 POWER_SUPPLY_ATTR(ENERGY_AVG),
0193 POWER_SUPPLY_ATTR(CAPACITY),
0194 POWER_SUPPLY_ATTR(CAPACITY_ALERT_MIN),
0195 POWER_SUPPLY_ATTR(CAPACITY_ALERT_MAX),
0196 POWER_SUPPLY_ATTR(CAPACITY_ERROR_MARGIN),
0197 POWER_SUPPLY_ENUM_ATTR(CAPACITY_LEVEL),
0198 POWER_SUPPLY_ATTR(TEMP),
0199 POWER_SUPPLY_ATTR(TEMP_MAX),
0200 POWER_SUPPLY_ATTR(TEMP_MIN),
0201 POWER_SUPPLY_ATTR(TEMP_ALERT_MIN),
0202 POWER_SUPPLY_ATTR(TEMP_ALERT_MAX),
0203 POWER_SUPPLY_ATTR(TEMP_AMBIENT),
0204 POWER_SUPPLY_ATTR(TEMP_AMBIENT_ALERT_MIN),
0205 POWER_SUPPLY_ATTR(TEMP_AMBIENT_ALERT_MAX),
0206 POWER_SUPPLY_ATTR(TIME_TO_EMPTY_NOW),
0207 POWER_SUPPLY_ATTR(TIME_TO_EMPTY_AVG),
0208 POWER_SUPPLY_ATTR(TIME_TO_FULL_NOW),
0209 POWER_SUPPLY_ATTR(TIME_TO_FULL_AVG),
0210 POWER_SUPPLY_ENUM_ATTR(TYPE),
0211 POWER_SUPPLY_ATTR(USB_TYPE),
0212 POWER_SUPPLY_ENUM_ATTR(SCOPE),
0213 POWER_SUPPLY_ATTR(PRECHARGE_CURRENT),
0214 POWER_SUPPLY_ATTR(CHARGE_TERM_CURRENT),
0215 POWER_SUPPLY_ATTR(CALIBRATE),
0216 POWER_SUPPLY_ATTR(MANUFACTURE_YEAR),
0217 POWER_SUPPLY_ATTR(MANUFACTURE_MONTH),
0218 POWER_SUPPLY_ATTR(MANUFACTURE_DAY),
0219
0220 POWER_SUPPLY_ATTR(MODEL_NAME),
0221 POWER_SUPPLY_ATTR(MANUFACTURER),
0222 POWER_SUPPLY_ATTR(SERIAL_NUMBER),
0223 };
0224
0225 static struct attribute *
0226 __power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1];
0227
0228 static struct power_supply_attr *to_ps_attr(struct device_attribute *attr)
0229 {
0230 return container_of(attr, struct power_supply_attr, dev_attr);
0231 }
0232
0233 static enum power_supply_property dev_attr_psp(struct device_attribute *attr)
0234 {
0235 return to_ps_attr(attr) - power_supply_attrs;
0236 }
0237
0238 static ssize_t power_supply_show_usb_type(struct device *dev,
0239 const struct power_supply_desc *desc,
0240 union power_supply_propval *value,
0241 char *buf)
0242 {
0243 enum power_supply_usb_type usb_type;
0244 ssize_t count = 0;
0245 bool match = false;
0246 int i;
0247
0248 for (i = 0; i < desc->num_usb_types; ++i) {
0249 usb_type = desc->usb_types[i];
0250
0251 if (value->intval == usb_type) {
0252 count += sprintf(buf + count, "[%s] ",
0253 POWER_SUPPLY_USB_TYPE_TEXT[usb_type]);
0254 match = true;
0255 } else {
0256 count += sprintf(buf + count, "%s ",
0257 POWER_SUPPLY_USB_TYPE_TEXT[usb_type]);
0258 }
0259 }
0260
0261 if (!match) {
0262 dev_warn(dev, "driver reporting unsupported connected type\n");
0263 return -EINVAL;
0264 }
0265
0266 if (count)
0267 buf[count - 1] = '\n';
0268
0269 return count;
0270 }
0271
0272 static ssize_t power_supply_show_property(struct device *dev,
0273 struct device_attribute *attr,
0274 char *buf) {
0275 ssize_t ret;
0276 struct power_supply *psy = dev_get_drvdata(dev);
0277 struct power_supply_attr *ps_attr = to_ps_attr(attr);
0278 enum power_supply_property psp = dev_attr_psp(attr);
0279 union power_supply_propval value;
0280
0281 if (psp == POWER_SUPPLY_PROP_TYPE) {
0282 value.intval = psy->desc->type;
0283 } else {
0284 ret = power_supply_get_property(psy, psp, &value);
0285
0286 if (ret < 0) {
0287 if (ret == -ENODATA)
0288 dev_dbg(dev, "driver has no data for `%s' property\n",
0289 attr->attr.name);
0290 else if (ret != -ENODEV && ret != -EAGAIN)
0291 dev_err_ratelimited(dev,
0292 "driver failed to report `%s' property: %zd\n",
0293 attr->attr.name, ret);
0294 return ret;
0295 }
0296 }
0297
0298 if (ps_attr->text_values_len > 0 &&
0299 value.intval < ps_attr->text_values_len && value.intval >= 0) {
0300 return sprintf(buf, "%s\n", ps_attr->text_values[value.intval]);
0301 }
0302
0303 switch (psp) {
0304 case POWER_SUPPLY_PROP_USB_TYPE:
0305 ret = power_supply_show_usb_type(dev, psy->desc,
0306 &value, buf);
0307 break;
0308 case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER:
0309 ret = sprintf(buf, "%s\n", value.strval);
0310 break;
0311 default:
0312 ret = sprintf(buf, "%d\n", value.intval);
0313 }
0314
0315 return ret;
0316 }
0317
0318 static ssize_t power_supply_store_property(struct device *dev,
0319 struct device_attribute *attr,
0320 const char *buf, size_t count) {
0321 ssize_t ret;
0322 struct power_supply *psy = dev_get_drvdata(dev);
0323 struct power_supply_attr *ps_attr = to_ps_attr(attr);
0324 enum power_supply_property psp = dev_attr_psp(attr);
0325 union power_supply_propval value;
0326
0327 ret = -EINVAL;
0328 if (ps_attr->text_values_len > 0) {
0329 ret = __sysfs_match_string(ps_attr->text_values,
0330 ps_attr->text_values_len, buf);
0331 }
0332
0333
0334
0335
0336
0337 if (ret < 0) {
0338 long long_val;
0339
0340 ret = kstrtol(buf, 10, &long_val);
0341 if (ret < 0)
0342 return ret;
0343
0344 ret = long_val;
0345 }
0346
0347 value.intval = ret;
0348
0349 ret = power_supply_set_property(psy, psp, &value);
0350 if (ret < 0)
0351 return ret;
0352
0353 return count;
0354 }
0355
0356 static umode_t power_supply_attr_is_visible(struct kobject *kobj,
0357 struct attribute *attr,
0358 int attrno)
0359 {
0360 struct device *dev = kobj_to_dev(kobj);
0361 struct power_supply *psy = dev_get_drvdata(dev);
0362 umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
0363 int i;
0364
0365 if (!power_supply_attrs[attrno].prop_name)
0366 return 0;
0367
0368 if (attrno == POWER_SUPPLY_PROP_TYPE)
0369 return mode;
0370
0371 for (i = 0; i < psy->desc->num_properties; i++) {
0372 int property = psy->desc->properties[i];
0373
0374 if (property == attrno) {
0375 if (psy->desc->property_is_writeable &&
0376 psy->desc->property_is_writeable(psy, property) > 0)
0377 mode |= S_IWUSR;
0378
0379 return mode;
0380 }
0381 }
0382
0383 return 0;
0384 }
0385
0386 static const struct attribute_group power_supply_attr_group = {
0387 .attrs = __power_supply_attrs,
0388 .is_visible = power_supply_attr_is_visible,
0389 };
0390
0391 static const struct attribute_group *power_supply_attr_groups[] = {
0392 &power_supply_attr_group,
0393 NULL,
0394 };
0395
0396 static void str_to_lower(char *str)
0397 {
0398 while (*str) {
0399 *str = tolower(*str);
0400 str++;
0401 }
0402 }
0403
0404 void power_supply_init_attrs(struct device_type *dev_type)
0405 {
0406 int i;
0407
0408 dev_type->groups = power_supply_attr_groups;
0409
0410 for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) {
0411 struct device_attribute *attr;
0412
0413 if (!power_supply_attrs[i].prop_name) {
0414 pr_warn("%s: Property %d skipped because it is missing from power_supply_attrs\n",
0415 __func__, i);
0416 sprintf(power_supply_attrs[i].attr_name, "_err_%d", i);
0417 } else {
0418 str_to_lower(power_supply_attrs[i].attr_name);
0419 }
0420
0421 attr = &power_supply_attrs[i].dev_attr;
0422
0423 attr->attr.name = power_supply_attrs[i].attr_name;
0424 attr->show = power_supply_show_property;
0425 attr->store = power_supply_store_property;
0426 __power_supply_attrs[i] = &attr->attr;
0427 }
0428 }
0429
0430 static int add_prop_uevent(struct device *dev, struct kobj_uevent_env *env,
0431 enum power_supply_property prop, char *prop_buf)
0432 {
0433 int ret = 0;
0434 struct power_supply_attr *pwr_attr;
0435 struct device_attribute *dev_attr;
0436 char *line;
0437
0438 pwr_attr = &power_supply_attrs[prop];
0439 dev_attr = &pwr_attr->dev_attr;
0440
0441 ret = power_supply_show_property(dev, dev_attr, prop_buf);
0442 if (ret == -ENODEV || ret == -ENODATA) {
0443
0444
0445
0446
0447 return 0;
0448 }
0449
0450 if (ret < 0)
0451 return ret;
0452
0453 line = strchr(prop_buf, '\n');
0454 if (line)
0455 *line = 0;
0456
0457 return add_uevent_var(env, "POWER_SUPPLY_%s=%s",
0458 pwr_attr->prop_name, prop_buf);
0459 }
0460
0461 int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
0462 {
0463 struct power_supply *psy = dev_get_drvdata(dev);
0464 int ret = 0, j;
0465 char *prop_buf;
0466
0467 if (!psy || !psy->desc) {
0468 dev_dbg(dev, "No power supply yet\n");
0469 return ret;
0470 }
0471
0472 ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->desc->name);
0473 if (ret)
0474 return ret;
0475
0476 prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
0477 if (!prop_buf)
0478 return -ENOMEM;
0479
0480 ret = add_prop_uevent(dev, env, POWER_SUPPLY_PROP_TYPE, prop_buf);
0481 if (ret)
0482 goto out;
0483
0484 for (j = 0; j < psy->desc->num_properties; j++) {
0485 ret = add_prop_uevent(dev, env, psy->desc->properties[j],
0486 prop_buf);
0487 if (ret)
0488 goto out;
0489 }
0490
0491 out:
0492 free_page((unsigned long)prop_buf);
0493
0494 return ret;
0495 }
0496
0497 ssize_t power_supply_charge_behaviour_show(struct device *dev,
0498 unsigned int available_behaviours,
0499 enum power_supply_charge_behaviour current_behaviour,
0500 char *buf)
0501 {
0502 bool match = false, available, active;
0503 ssize_t count = 0;
0504 int i;
0505
0506 for (i = 0; i < ARRAY_SIZE(POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT); i++) {
0507 available = available_behaviours & BIT(i);
0508 active = i == current_behaviour;
0509
0510 if (available && active) {
0511 count += sysfs_emit_at(buf, count, "[%s] ",
0512 POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[i]);
0513 match = true;
0514 } else if (available) {
0515 count += sysfs_emit_at(buf, count, "%s ",
0516 POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[i]);
0517 }
0518 }
0519
0520 if (!match) {
0521 dev_warn(dev, "driver reporting unsupported charge behaviour\n");
0522 return -EINVAL;
0523 }
0524
0525 if (count)
0526 buf[count - 1] = '\n';
0527
0528 return count;
0529 }
0530 EXPORT_SYMBOL_GPL(power_supply_charge_behaviour_show);
0531
0532 int power_supply_charge_behaviour_parse(unsigned int available_behaviours, const char *buf)
0533 {
0534 int i = sysfs_match_string(POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT, buf);
0535
0536 if (i < 0)
0537 return i;
0538
0539 if (available_behaviours & BIT(i))
0540 return i;
0541
0542 return -EINVAL;
0543 }
0544 EXPORT_SYMBOL_GPL(power_supply_charge_behaviour_parse);