power_supply_sysfs.c 16 KB

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