lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20070424203251.GA23688@zarina>
Date:	Wed, 25 Apr 2007 00:32:51 +0400
From:	Anton Vorontsov <cbou@...l.ru>
To:	Pavel Machek <pavel@....cz>
Cc:	linux-kernel@...r.kernel.org, kernel-discuss@...dhelds.org
Subject: Re: [PATCH 3/7] Universal battery class

Hello Pavel,

On Tue, Apr 24, 2007 at 09:28:46PM +0200, Pavel Machek wrote:
> Hi!
> 
> > Signed-off-by: Anton Vorontsov <cbou@...l.ru>
> 
> Yes please. Generic battery support is badly needed.

I'm glad you like it, thanks for the review!

Also I've done some code split. It removes all #ifdefs from battery.c,
and also separates core from sysfs and leds.

If there will no objections, I'll send this version when patch window
will opened.

Here it is...


From: Anton Vorontsov <cbou@...l.ru>
Date: Fri, 20 Apr 2007 14:40:50 +0400
Subject: [PATCH] Universal battery class

Signed-off-by: Anton Vorontsov <cbou@...l.ru>
---
 Documentation/battery-class.txt |  150 +++++++++++++++++++++++++++++++++++++++
 drivers/Kconfig                 |    2 +
 drivers/Makefile                |    1 +
 drivers/battery/Kconfig         |   11 +++
 drivers/battery/Makefile        |    9 +++
 drivers/battery/battery.c       |  137 +++++++++++++++++++++++++++++++++++
 drivers/battery/battery.h       |   37 ++++++++++
 drivers/battery/battery_leds.c  |  106 +++++++++++++++++++++++++++
 drivers/battery/battery_sysfs.c |  122 +++++++++++++++++++++++++++++++
 include/linux/battery.h         |  125 ++++++++++++++++++++++++++++++++
 10 files changed, 700 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/battery-class.txt
 create mode 100644 drivers/battery/Kconfig
 create mode 100644 drivers/battery/Makefile
 create mode 100644 drivers/battery/battery.c
 create mode 100644 drivers/battery/battery.h
 create mode 100644 drivers/battery/battery_leds.c
 create mode 100644 drivers/battery/battery_sysfs.c
 create mode 100644 include/linux/battery.h

diff --git a/Documentation/battery-class.txt b/Documentation/battery-class.txt
new file mode 100644
index 0000000..6a7d591
--- /dev/null
+++ b/Documentation/battery-class.txt
@@ -0,0 +1,150 @@
+Linux battery class
+===================
+
+Synopsis
+~~~~~~~~
+Battery class used to export battery properties to userspace in consistent
+manner.
+
+It defines core set of battery attributes, available via sysfs, which
+should be applicable to (almost) every battery out there. Each attribute
+has well defined meaning, up to unit of measure used. While the attributes
+provided are believed to be universally applicable to any battery,
+specific monitoring hardware may not be able to provide them all, so
+any of them may be skipped.
+
+Battery class is extensible, and allows to define drivers own attributes.
+The core attribute set is subject to the standard Linux evolution (i.e.
+if it will be found that some attribute is applicable to many batteries
+or their drivers, it can be added to the core set).
+
+Battery class integrates with External Power framework, for the purpose of
+notification battery drivers when charging power is available. Note that
+specific charge control is left to the battery drivers.
+
+It also integrates with LED framework, for the purpose of providing
+typically expected (at least for portable devices) feedback of battery
+status (charging/fully charged) via LEDs. (Note that specific details of
+the indication (including whether to use it at all) are fully controllable
+by user and/or specific machine defaults, per design principles of LED
+framework).
+
+
+Attributes/properties
+~~~~~~~~~~~~~~~~~~~~~
+Battery class has predefined set of attributes, this eliminates code
+duplication across battery drivers. Battery class insist on reusing its
+predefined attributes *and* their units.
+
+So, userspace gets expected set of attributes and their units for
+any kind of battery, and can process/present them to a user in consistent
+manner. Results for different batteries and machines are also directly
+comparable.
+
+See drivers/battery/ds2760_battery.c for the example how to declare and
+handle attributes.
+
+
+Units
+~~~~~
+Quoting include/linux/battery.h:
+
+  All voltages, currents, charges, energies, time and temperatures in uV,
+  uA, uAh, uWh, seconds and tenths of degree Celsius unless otherwise
+  stated. It's driver's job to convert its raw values to units in which
+  this class operates.
+
+
+Attributes/properties detailed
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+~ ~ ~ ~ ~ ~ ~  Charge/Energy/Capacity - how to not confuse  ~ ~ ~ ~ ~ ~ ~
+~                                                                       ~
+~ Because both "charge" (uAh) and "energy" (uWh) represents "capacity"  ~
+~ of battery, battery class distinguish these terms. Don't mix them!    ~
+~                                                                       ~
+~ CHARGE_* attributes represents capacity in uAh only.                  ~
+~ ENERGY_* attributes represents capacity in uWh only.                  ~
+~ CAPACITY attribute represents capacity in *percents*, from 0 to 100.  ~
+~                                                                       ~
+~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+Postfixes:
+_AVG - *hardware* averaged value, use it if your hardware is really able to
+report averaged values.
+_NOW - momentary/instantaneous values.
+
+STATUS - this attribute represents operating status (charging, full,
+discharging (i.e. powering a load), etc.). This corresponds to
+BATTERY_STATUS_* values, as defined in battery.h.
+
+HEALTH - represents health of the battery, values corresponds to
+BATTERY_HEALTH_*, defined in battery.h.
+
+VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and
+minimal battery voltages. Maximal/minimal means values of voltages when
+battery considered "full"/"empty" at normal conditions. Yes, there is
+no direct relation between voltage and battery capacity, but some dumb
+batteries use voltage for very approximated calculation of capacity.
+Battery driver also can use this attribute just to inform userspace
+about maximal and minimal voltage thresholds of a given battery.
+
+CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when
+battery considered full/empty.
+
+ENERGY_FULL_DESIGN, ENERGY_EMPTY_DESIGN - same as above but for energy.
+
+CHARGE_FULL, CHARGE_EMPTY - These attributes means "last remembered value
+of charge when battery became full/empty". It also could mean "value of
+charge when battery considered full/empty at given conditions (temperature,
+age)". I.e. these attributes represents real thresholds, not design values.
+
+ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
+
+CAPACITY - capacity in percents.
+
+TEMP - temperature of the battery.
+
+TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
+while battery powers a load)
+TIME_TO_FULL - seconds left for battery to be considered full (i.e.
+while battery is charging)
+
+
+QA
+~~
+Q: Where is BATTERY_PROP_XYZ attribute?
+A: If you cannot find attribute suitable for your battery needs, feel free
+   to add it and send patch along with your battery driver.
+
+   The attributes available currently are the ones currently provided by the
+   drivers written.
+
+   Good candidates to add in future: battery technology, model/part#,
+   cycle_time, manufacturer, etc.
+
+
+Q: I have some very specific attribute (e.g. battery color), should I add
+   this attribute to standard ones?
+A: Most likely, no. Such attribute can be placed in the driver itself, if
+   it is useful. Of course, if the attribute in question applicable to
+   large set of batteries, provided by many drivers, and/or comes from
+   some general battery specification/standard, it may be a candidate to
+   be added to the core attribute set.
+
+
+Q: Suppose, my battery monitoring chip/firmware does not provides capacity
+   in percents, but provides charge_{now,full,empty}. Should I calculate
+   percentage capacity manually, inside the driver, and register CAPACITY
+   attribute? The same question about time_to_empty/time_to_full.
+A: Most likely, no. Battery class is designed to export battery properties
+   which are directly measurable by the specific hardware available.
+   Inferring not available properties using some heuristics or mathematical
+   model is not subject of work for a battery driver. Such functionality
+   should be factored out, and in fact, apm_power, the driver to serve
+   legacy APM API on top of battery class, uses a simple heuristic of
+   approximating remaining battery capacity based on its charge, current,
+   voltage and so on. But full-fledged battery model is likely not subject
+   for kernel at all, as it would require floating point calculation to deal
+   with things like differential equations and Kalman filters. This is
+   better be handled by batteryd/libbattery, yet to be written.
diff --git a/drivers/Kconfig b/drivers/Kconfig
index c546de3..c3a0038 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/w1/Kconfig"
 
 source "drivers/power/Kconfig"
 
+source "drivers/battery/Kconfig"
+
 source "drivers/hwmon/Kconfig"
 
 source "drivers/mfd/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 2bdaae7..7cbfd37 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_RTC_LIB)		+= rtc/
 obj-$(CONFIG_I2C)		+= i2c/
 obj-$(CONFIG_W1)		+= w1/
 obj-$(CONFIG_EXTERNAL_POWER)	+= power/
+obj-$(CONFIG_BATTERY)		+= battery/
 obj-$(CONFIG_HWMON)		+= hwmon/
 obj-$(CONFIG_PHONE)		+= telephony/
 obj-$(CONFIG_MD)		+= md/
diff --git a/drivers/battery/Kconfig b/drivers/battery/Kconfig
new file mode 100644
index 0000000..c386593
--- /dev/null
+++ b/drivers/battery/Kconfig
@@ -0,0 +1,11 @@
+
+menu "Battery support"
+
+config BATTERY
+	tristate "Battery monitoring support"
+	select EXTERNAL_POWER
+	help
+	  Say Y here to enable generic battery status reporting in
+	  the /sys filesystem.
+
+endmenu
diff --git a/drivers/battery/Makefile b/drivers/battery/Makefile
new file mode 100644
index 0000000..1af291b
--- /dev/null
+++ b/drivers/battery/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_BATTERY)              += battery.o
+
+ifeq ($(CONFIG_SYSFS),y)
+obj-$(CONFIG_BATTERY)              += battery_sysfs.o
+endif
+
+ifeq ($(CONFIG_LEDS_TRIGGERS),y)
+obj-$(CONFIG_BATTERY)              += battery_leds.o
+endif
diff --git a/drivers/battery/battery.c b/drivers/battery/battery.c
new file mode 100644
index 0000000..1614c39
--- /dev/null
+++ b/drivers/battery/battery.c
@@ -0,0 +1,137 @@
+/*
+ *  Universal battery monitor class
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@...l.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@....com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/battery.h>
+#include "battery.h"
+
+struct class *battery_class;
+
+static void battery_external_power_changed(struct power_supplicant *pst,
+                                           struct power_supply *psy)
+{
+	struct battery *bat = container_of(pst, struct battery, pst);
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	if (bat->external_power_changed)
+		bat->external_power_changed(bat);
+
+	return;
+}
+
+int battery_is_external_power_supplied(struct battery *bat)
+{
+	pr_debug("%s\n", __FUNCTION__);
+
+	return power_supplicant_am_i_supplied(&bat->pst);
+}
+
+void battery_status_changed(struct battery *bat)
+{
+	int *status;
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	status = bat->get_property(bat, BATTERY_PROP_STATUS);
+	if (!status)
+		return;
+
+	battery_update_leds(bat, *status);
+
+	return;
+}
+
+int battery_register(struct device *parent, struct battery *bat)
+{
+	int rc = 0;
+
+	bat->dev = device_create(battery_class, parent, 0, "%s", bat->name);
+	if (IS_ERR(bat->dev)) {
+		rc = PTR_ERR(bat->dev);
+		goto dev_create_failed;
+	}
+
+	dev_set_drvdata(bat->dev, bat);
+
+	rc = battery_create_attrs(bat);
+	if (rc)
+		goto create_attrs_failed;
+
+	rc = battery_create_triggers(bat);
+	if (rc)
+		goto create_triggers_failed;
+
+	bat->pst.name = bat->name;
+	bat->pst.power_supply_changed = battery_external_power_changed;
+	rc = power_supplicant_register(&bat->pst);
+	if (rc)
+		goto power_supplicant_failed;
+
+	goto success;
+
+power_supplicant_failed:
+	battery_remove_triggers(bat);
+create_triggers_failed:
+	battery_remove_attrs(bat);
+create_attrs_failed:
+	device_unregister(bat->dev);
+dev_create_failed:
+success:
+	return rc;
+}
+
+void battery_unregister(struct battery *bat)
+{
+	power_supplicant_unregister(&bat->pst);
+	battery_remove_triggers(bat);
+	battery_remove_attrs(bat);
+	device_unregister(bat->dev);
+	return;
+}
+
+static int __init battery_class_init(void)
+{
+	battery_class = class_create(THIS_MODULE, "battery");
+
+	if (IS_ERR(battery_class))
+		return PTR_ERR(battery_class);
+
+	return 0;
+}
+
+static void __exit battery_class_exit(void)
+{
+	class_destroy(battery_class);
+	return;
+}
+
+EXPORT_SYMBOL_GPL(battery_register);
+EXPORT_SYMBOL_GPL(battery_unregister);
+EXPORT_SYMBOL_GPL(battery_status_changed);
+EXPORT_SYMBOL_GPL(battery_is_external_power_supplied);
+
+/* exported for the APM Power driver, APM emulation */
+EXPORT_SYMBOL_GPL(battery_class);
+
+subsys_initcall(battery_class_init);
+module_exit(battery_class_exit);
+
+MODULE_DESCRIPTION("Universal battery monitor class");
+MODULE_AUTHOR("Ian Molton <spyro@....com>, "
+              "Szabolcs Gyurko, "
+              "Anton Vorontsov <cbou@...l.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/battery/battery.h b/drivers/battery/battery.h
new file mode 100644
index 0000000..25a98c6
--- /dev/null
+++ b/drivers/battery/battery.h
@@ -0,0 +1,37 @@
+/*
+ *  Functions private to battery.c
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@...l.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@....com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#ifdef CONFIG_SYSFS
+
+extern int battery_create_attrs(struct battery *bat);
+extern void battery_remove_attrs(struct battery *bat);
+
+#else
+
+static inline int battery_create_attrs(struct battery *bat) { return 0; }
+static inline void battery_remove_attrs(struct battery *bat) {}
+
+#endif /* CONFIG_SYSFS */
+
+#ifdef CONFIG_LEDS_TRIGGERS
+
+extern void battery_update_leds(struct battery *bat, int status);
+extern int battery_create_triggers(struct battery *bat);
+extern void battery_remove_triggers(struct battery *bat);
+
+#else
+
+static inline void battery_update_leds(struct battery *bat, int status) {}
+static inline int battery_create_triggers(struct battery *bat) { return 0; }
+static inline void battery_remove_triggers(struct battery *bat) {}
+
+#endif /* CONFIG_LEDS_TRIGGERS */
diff --git a/drivers/battery/battery_leds.c b/drivers/battery/battery_leds.c
new file mode 100644
index 0000000..a149f8d
--- /dev/null
+++ b/drivers/battery/battery_leds.c
@@ -0,0 +1,106 @@
+/*
+ *  LEDs triggers for class batteries
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@...l.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@....com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/battery.h>
+
+/* If we have hwtimer trigger, then use it to blink charging LED */
+#if defined(CONFIG_LEDS_TRIGGER_HWTIMER) ||                  \
+               (defined(CONFIG_BATTERY_MODULE) &&            \
+                defined(CONFIG_LEDS_TRIGGER_HWTIMER_MODULE))
+	#define led_trigger_register_charging led_trigger_register_hwtimer
+	#define led_trigger_unregister_charging led_trigger_unregister_hwtimer
+#else
+	#define led_trigger_register_charging led_trigger_register_simple
+	#define led_trigger_unregister_charging led_trigger_unregister_simple
+#endif
+
+void battery_update_leds(struct battery *bat, int status)
+{
+	pr_debug("%s\n", __FUNCTION__);
+
+	switch(status) {
+	case BATTERY_STATUS_FULL:
+		led_trigger_event(bat->charging_full_trig, LED_FULL);
+		led_trigger_event(bat->charging_trig, LED_OFF);
+		led_trigger_event(bat->full_trig, LED_FULL);
+		break;
+	case BATTERY_STATUS_CHARGING:
+		led_trigger_event(bat->charging_full_trig, LED_FULL);
+		led_trigger_event(bat->charging_trig, LED_FULL);
+		led_trigger_event(bat->full_trig, LED_OFF);
+		break;
+	default:
+		led_trigger_event(bat->charging_full_trig, LED_OFF);
+		led_trigger_event(bat->charging_trig, LED_OFF);
+		led_trigger_event(bat->full_trig, LED_OFF);
+		break;
+	}
+
+	return;
+}
+
+int battery_create_triggers(struct battery *bat)
+{
+	int rc = 0;
+
+	bat->charging_full_trig_name = kmalloc(strlen(bat->name) +
+	                          sizeof("-charging-or-full"), GFP_KERNEL);
+	if (!bat->charging_full_trig_name)
+		goto charging_full_failed;
+
+	bat->charging_trig_name = kmalloc(strlen(bat->name) +
+	                                  sizeof("-charging"), GFP_KERNEL);
+	if (!bat->charging_trig_name)
+		goto charging_failed;
+
+	bat->full_trig_name = kmalloc(strlen(bat->name) +
+	                              sizeof("-full"), GFP_KERNEL);
+	if (!bat->full_trig_name)
+		goto full_failed;
+
+	strcpy(bat->charging_full_trig_name, bat->name);
+	strcat(bat->charging_full_trig_name, "-charging-or-full");
+	strcpy(bat->charging_trig_name, bat->name);
+	strcat(bat->charging_trig_name, "-charging");
+	strcpy(bat->full_trig_name, bat->name);
+	strcat(bat->full_trig_name, "-full");
+
+	led_trigger_register_simple(bat->charging_full_trig_name,
+	                            &bat->charging_full_trig);
+	led_trigger_register_charging(bat->charging_trig_name,
+	                              &bat->charging_trig);
+	led_trigger_register_simple(bat->full_trig_name,
+	                            &bat->full_trig);
+
+	goto success;
+
+full_failed:
+	kfree(bat->charging_trig_name);
+charging_failed:
+	kfree(bat->charging_full_trig_name);
+charging_full_failed:
+	rc = -ENOMEM;
+success:
+	return rc;
+}
+
+void battery_remove_triggers(struct battery *bat)
+{
+	led_trigger_unregister_simple(bat->charging_full_trig);
+	led_trigger_unregister_charging(bat->charging_trig);
+	led_trigger_unregister_simple(bat->full_trig);
+	kfree(bat->full_trig_name);
+	kfree(bat->charging_trig_name);
+	kfree(bat->charging_full_trig_name);
+
+	return;
+}
diff --git a/drivers/battery/battery_sysfs.c b/drivers/battery/battery_sysfs.c
new file mode 100644
index 0000000..7e54d55
--- /dev/null
+++ b/drivers/battery/battery_sysfs.c
@@ -0,0 +1,122 @@
+/*
+ *  Sysfs interface for the universal battery monitor class
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@...l.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@....com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/battery.h>
+
+/*
+ * This is because the name "current" breaks the device attr macro.
+ * The "current" word resolvs 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 BATTERY_ATTR(_name)                                             \
+{                                                                       \
+	.attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE }, \
+	.show = battery_show_property,                                  \
+	.store = NULL,                                                  \
+}
+
+static struct device_attribute battery_attrs[];
+
+static ssize_t battery_show_property(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf) {
+	static char *status_text[] = {
+		"Unknown", "Charging", "Discharging", "Not charging", "Full"
+	};
+	static char *health_text[] = {
+		"Unknown", "Good", "Overheat", "Dead"
+	};
+	struct battery *bat = dev_get_drvdata(dev);
+	const off_t off = attr - battery_attrs;
+	void *value = bat->get_property(bat, off);
+
+	if (!value)
+		return sprintf(buf, "Driver can't report this property, "
+		               "but claimed it can. Fix it.\n");
+
+	if (off == BATTERY_PROP_STATUS)
+		return sprintf(buf, "%s\n", status_text[*(int *)value]);
+	else if (off == BATTERY_PROP_HEALTH)
+		return sprintf(buf, "%s\n", health_text[*(int *)value]);
+	else
+		return sprintf(buf, "%d\n", *(int *)value);
+}
+
+/* Must be in the same order as BATTERY_PROP_*, defined in battery.h */
+static struct device_attribute battery_attrs[] = {
+	BATTERY_ATTR(status),
+	BATTERY_ATTR(health),
+	BATTERY_ATTR(voltage_max_design),
+	BATTERY_ATTR(voltage_min_design),
+	BATTERY_ATTR(voltage_now),
+	BATTERY_ATTR(voltage_avg),
+	BATTERY_ATTR(current_now),
+	BATTERY_ATTR(current_avg),
+	BATTERY_ATTR(charge_full_design),
+	BATTERY_ATTR(charge_empty_design),
+	BATTERY_ATTR(charge_full),
+	BATTERY_ATTR(charge_empty),
+	BATTERY_ATTR(charge_now),
+	BATTERY_ATTR(charge_avg),
+	BATTERY_ATTR(energy_full_design),
+	BATTERY_ATTR(energy_empty_design),
+	BATTERY_ATTR(energy_full),
+	BATTERY_ATTR(energy_empty),
+	BATTERY_ATTR(energy_now),
+	BATTERY_ATTR(energy_avg),
+	BATTERY_ATTR(capacity),
+	BATTERY_ATTR(temp),
+	BATTERY_ATTR(time_to_empty_now),
+	BATTERY_ATTR(time_to_empty_avg),
+	BATTERY_ATTR(time_to_full_now),
+	BATTERY_ATTR(time_to_full_avg),
+};
+
+int battery_create_attrs(struct battery *bat)
+{
+	int rc = 0;
+	int i;
+
+	for (i = 0; i < bat->num_properties; i++) {
+		rc = device_create_file(bat->dev,
+		            &battery_attrs[bat->properties[i]]);
+		if (rc)
+			goto failed;
+	}
+
+	goto succeed;
+
+failed:
+	while (i--)
+		device_remove_file(bat->dev,
+		           &battery_attrs[bat->properties[i]]);
+succeed:
+	return rc;
+}
+
+void battery_remove_attrs(struct battery *bat)
+{
+	int i;
+
+	for (i = 0; i < bat->num_properties; i++)
+		device_remove_file(bat->dev,
+		           &battery_attrs[bat->properties[i]]);
+
+	return;
+}
diff --git a/include/linux/battery.h b/include/linux/battery.h
new file mode 100644
index 0000000..db68549
--- /dev/null
+++ b/include/linux/battery.h
@@ -0,0 +1,125 @@
+/*
+ *  Universal battery monitor class
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@...l.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@....com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ *
+ * All voltages, currents, charges, energies, time and temperatures in uV,
+ * uA, uAh, uWh, seconds and tenths of degree Celsius unless otherwise
+ * stated. It's driver's job to convert its raw values to units in which
+ * this class operates.
+ */
+
+#ifndef __LINUX_BATTERY_H__
+#define __LINUX_BATTERY_H__
+
+#include <linux/device.h>
+#include <linux/external_power.h>
+#include <linux/leds.h>
+
+#define BATTERY_STATUS_UNKNOWN      0
+#define BATTERY_STATUS_CHARGING     1
+#define BATTERY_STATUS_DISCHARGING  2
+#define BATTERY_STATUS_NOT_CHARGING 3
+#define BATTERY_STATUS_FULL         4
+
+#define BATTERY_HEALTH_UNKNOWN  0
+#define BATTERY_HEALTH_GOOD     1
+#define BATTERY_HEALTH_OVERHEAT 2
+#define BATTERY_HEALTH_DEAD     3
+
+/*
+ * For systems where the charger determines the maximum battery capacity
+ * the min and max fields should be used to present these values to user
+ * space. Unused/unknown fields will not appear in sysfs.
+ */
+
+enum battery_property {
+	BATTERY_PROP_STATUS = 0,
+	BATTERY_PROP_HEALTH,
+	BATTERY_PROP_VOLTAGE_MAX_DESIGN,
+	BATTERY_PROP_VOLTAGE_MIN_DESIGN,
+	BATTERY_PROP_VOLTAGE_NOW,
+	BATTERY_PROP_VOLTAGE_AVG,
+	BATTERY_PROP_CURRENT_NOW,
+	BATTERY_PROP_CURRENT_AVG,
+	BATTERY_PROP_CHARGE_FULL_DESIGN,
+	BATTERY_PROP_CHARGE_EMPTY_DESIGN,
+	BATTERY_PROP_CHARGE_FULL,
+	BATTERY_PROP_CHARGE_EMPTY,
+	BATTERY_PROP_CHARGE_NOW,
+	BATTERY_PROP_CHARGE_AVG,
+	BATTERY_PROP_ENERGY_FULL_DESIGN,
+	BATTERY_PROP_ENERGY_EMPTY_DESIGN,
+	BATTERY_PROP_ENERGY_FULL,
+	BATTERY_PROP_ENERGY_EMPTY,
+	BATTERY_PROP_ENERGY_NOW,
+	BATTERY_PROP_ENERGY_AVG,
+	BATTERY_PROP_CAPACITY, /* in percents! */
+	BATTERY_PROP_TEMP,
+	BATTERY_PROP_TIME_TO_EMPTY_NOW,
+	BATTERY_PROP_TIME_TO_EMPTY_AVG,
+	BATTERY_PROP_TIME_TO_FULL_NOW,
+	BATTERY_PROP_TIME_TO_FULL_AVG,
+};
+
+struct battery {
+	char *name;
+	enum battery_property *properties;
+	size_t num_properties;
+
+	/* For APM emulation, think legacy userspace. */
+	int main_battery;
+
+	/* executed in userspace, feel free to sleep */
+	void *(*get_property)(struct battery *bat, enum battery_property);
+
+	/* drivers should not sleep inside it, you'll get there from ISRs */
+	void (*external_power_changed)(struct battery *bat);
+
+	/* private */
+	struct device *dev;
+	struct power_supplicant pst;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+	struct led_trigger *charging_full_trig;
+	char *charging_full_trig_name;
+	struct led_trigger *charging_trig;
+	char *charging_trig_name;
+	struct led_trigger *full_trig;
+	char *full_trig_name;
+#endif
+};
+
+/*
+ * This is recommended structure to specify static battery parameters.
+ * Generic one, parametrizable for different batteries. Battery class
+ * itself does not use it, but that's what implementing most drivers,
+ * should try reuse for consistency.
+ */
+
+struct battery_info {
+	char *name;
+	int voltage_max_design;
+	int voltage_min_design;
+	int charge_full_design;
+	int charge_empty_design;
+	int energy_full_design;
+	int energy_empty_design;
+	int main_battery;
+};
+
+extern void battery_status_changed(struct battery *bat);
+extern int battery_is_external_power_supplied(struct battery *bat);
+extern int battery_register(struct device *parent, struct battery *bat);
+extern void battery_unregister(struct battery *bat);
+
+/* For APM emulation, think legacy userspace. */
+extern struct class *battery_class;
+
+#endif /* __LINUX_BATTERY_H__ */
-- 
1.5.1.1-dirty

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ