public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/7] [RFC] Battery monitoring class
@ 2007-04-11 23:25 Anton Vorontsov
  2007-04-12  2:53 ` Randy Dunlap
                   ` (6 more replies)
  0 siblings, 7 replies; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-11 23:25 UTC (permalink / raw)
  To: linux-kernel; +Cc: kernel-discuss, dwmw2

Here is battery monitor class. According to first copyright string, we're
maintaining it since 2003. I've took few days and cleaned it up to be
more suitable for mainline inclusion.

It differs from battery class at git://git.infradead.org/battery-2.6.git:

* It's using external power kernel interface, i.e. does not fake external
  powers as batteries. (Same thing David Woodhouse planed last year).

* It have predefined set of attributes, this eliminates code duplication
  by battery drivers. And also gives opportunity to write emulation drivers
  for legacy stuff (APM emulation driver follow).

  If driver can't afford some attribute, it will not appear in sysfs.

* It insists on reusing its predefined attributes *and* their units.
  So, userspace getting expected values for any battery.
  
  Also common units is required for APM/ACPI emulation.
  
  Though our battery class insisting on re-usage, but not forces it. If some
  battery driver can't convert its own raw values (can't imagine why), then
  driver is free to implement its own attributes *and* additional _units
  attribute. Though, this scheme is discouraged.

* LEDs support. Each battery register its trigger, and gadgets with LEDs
  can quickly bind to battery-charging / battery-full triggers.

Here how it looks like from user space:

# ls /sys/class/battery/main-battery/
capacity  max_capacity  max_voltage   min_current  power   subsystem  uevent
current   max_current   min_capacity  min_voltage  status  temp       voltage
# cat /sys/class/battery/main-battery/status
Full
# cat /sys/class/leds/h5400\:green-right/trigger
none h5400-radio timer hwtimer main-battery-charging [main-battery-full]
# cat /sys/class/leds/h5400\:green-right/brightness
255

---
 drivers/Kconfig           |    2 +
 drivers/Makefile          |    1 +
 drivers/battery/Kconfig   |   11 ++
 drivers/battery/Makefile  |    1 +
 drivers/battery/battery.c |  303 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/battery.h   |   98 +++++++++++++++
 6 files changed, 416 insertions(+), 0 deletions(-)
 create mode 100644 drivers/battery/Kconfig
 create mode 100644 drivers/battery/Makefile
 create mode 100644 drivers/battery/battery.c
 create mode 100644 include/linux/battery.h

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..a2239cb
--- /dev/null
+++ b/drivers/battery/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BATTERY)              += battery.o
diff --git a/drivers/battery/battery.c b/drivers/battery/battery.c
new file mode 100644
index 0000000..32b8288
--- /dev/null
+++ b/drivers/battery/battery.c
@@ -0,0 +1,303 @@
+/*
+ *  Universal battery monitor class
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ *
+ * All voltages, currents, capacities and temperatures in mV, mA, mAh and
+ * tenths of a degree unless otherwise stated. It's driver's job to convert
+ * its raw values to which this class operates. If for some reason driver
+ * can't afford this requirement, then it have to create its own attributes,
+ * plus additional "XYZ_units" for each of them.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/battery.h>
+
+/* If we have hwtimer trigger, then use it to blink charging LED */
+#if defined(CONFIG_LEDS_TRIGGER_HWTIMER) || \
+    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
+
+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)
+{
+	pr_debug("%s\n", __FUNCTION__);
+	#ifdef CONFIG_LEDS_TRIGGERS
+	switch(bat->get_status(bat))
+	{
+		case BATTERY_STATUS_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_trig, LED_FULL);
+			led_trigger_event(bat->full_trig, LED_OFF);
+			break;
+		default:
+			led_trigger_event(bat->charging_trig, LED_OFF);
+			led_trigger_event(bat->full_trig, LED_OFF);
+			break;
+	}
+	#endif /* CONFIG_LEDS_TRIGGERS */
+	return;
+}
+
+static char *status_text[] = {
+	"Unknown", "Charging", "Discharging", "Not charging", "Full"
+};
+
+static ssize_t battery_show_status(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+	struct battery *bat = dev_get_drvdata(dev);
+	int status = 0;
+	if (bat->get_status) {
+		status = bat->get_status(bat);
+		if (status > 4)
+			status = 0;
+		return sprintf(buf, "%s\n", status_text[status]);
+	}
+	return 0;
+}
+
+/*
+ * 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_INT_ATTR(_name)                                         \
+static ssize_t battery_show_##_name(struct device *dev,                 \
+                                   struct device_attribute *attr,       \
+                                   char *buf) {                         \
+	struct battery *bat = dev_get_drvdata(dev);                     \
+	return sprintf(buf, "%d\n", bat->get_##_name(bat));             \
+}                                                                       \
+static struct device_attribute dev_attr_##_name = {                     \
+	.attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE }, \
+	.show = battery_show_##_name,                                   \
+	.store = NULL,                                                  \
+}
+
+static DEVICE_ATTR(status, 0444, battery_show_status, NULL);
+BATTERY_INT_ATTR(min_voltage);
+BATTERY_INT_ATTR(min_current);
+BATTERY_INT_ATTR(min_capacity);
+BATTERY_INT_ATTR(max_voltage);
+BATTERY_INT_ATTR(max_current);
+BATTERY_INT_ATTR(max_capacity);
+BATTERY_INT_ATTR(temp);
+BATTERY_INT_ATTR(voltage);
+BATTERY_INT_ATTR(current);
+BATTERY_INT_ATTR(capacity);
+
+static int battery_create_attrs(struct battery *bat)
+{
+	int rc;
+
+	#define create_bat_attr_conditional(name)                    \
+	if(bat->get_##name) {                                        \
+		rc = device_create_file(bat->dev, &dev_attr_##name); \
+		if (rc) goto name##_failed;                          \
+	}
+
+	create_bat_attr_conditional(status);
+	create_bat_attr_conditional(min_voltage);
+	create_bat_attr_conditional(min_current);
+	create_bat_attr_conditional(min_capacity);
+	create_bat_attr_conditional(max_voltage);
+	create_bat_attr_conditional(max_current);
+	create_bat_attr_conditional(max_capacity);
+	create_bat_attr_conditional(temp);
+	create_bat_attr_conditional(voltage);
+	create_bat_attr_conditional(current);
+	create_bat_attr_conditional(capacity);
+
+	#define remove_bat_attr_conditional(name)               \
+	if(bat->get_##name)                                     \
+		device_remove_file(bat->dev, &dev_attr_##name);
+
+	goto success;
+
+capacity_failed:     remove_bat_attr_conditional(current);
+current_failed:      remove_bat_attr_conditional(voltage);
+voltage_failed:      remove_bat_attr_conditional(temp);
+temp_failed:         remove_bat_attr_conditional(max_capacity);
+max_capacity_failed: remove_bat_attr_conditional(max_current);
+max_current_failed:  remove_bat_attr_conditional(max_voltage);
+max_voltage_failed:  remove_bat_attr_conditional(min_capacity);
+min_capacity_failed: remove_bat_attr_conditional(min_current);
+min_current_failed:  remove_bat_attr_conditional(min_voltage);
+min_voltage_failed:  remove_bat_attr_conditional(status);
+status_failed:
+success:
+	return rc;
+}
+
+static void battery_remove_attrs(struct battery *bat)
+{
+	remove_bat_attr_conditional(capacity);
+	remove_bat_attr_conditional(current);
+	remove_bat_attr_conditional(voltage);
+	remove_bat_attr_conditional(temp);
+	remove_bat_attr_conditional(max_capacity);
+	remove_bat_attr_conditional(max_current);
+	remove_bat_attr_conditional(max_voltage);
+	remove_bat_attr_conditional(min_capacity);
+	remove_bat_attr_conditional(min_current);
+	remove_bat_attr_conditional(min_voltage);
+	remove_bat_attr_conditional(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_bat_attrs_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;
+
+	#ifdef CONFIG_LEDS_TRIGGERS
+	bat->charging_trig_name = kmalloc(strlen(bat->name) +
+	                                  sizeof("-charging"), GFP_KERNEL);
+	if (!bat->charging_trig_name) {
+		rc = -ENOMEM;
+		goto charging_trig_name_failed;
+	}
+
+	bat->full_trig_name = kmalloc(strlen(bat->name) +
+	                              sizeof("-full"), GFP_KERNEL);
+	if (!bat->full_trig_name) {
+		rc = -ENOMEM;
+		goto full_trig_name_failed;
+	}
+
+	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_charging(bat->charging_trig_name,
+	                              &bat->charging_trig);
+	led_trigger_register_simple(bat->full_trig_name,
+	                            &bat->full_trig);
+	#endif /* CONFIG_LEDS_TRIGGERS */
+
+	goto success;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+full_trig_name_failed:
+	kfree(bat->charging_trig_name);
+charging_trig_name_failed:
+#endif
+	power_supplicant_unregister(&bat->pst);
+power_supplicant_failed:
+	battery_remove_attrs(bat);
+create_bat_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_attrs(bat);
+	device_unregister(bat->dev);
+
+	#ifdef CONFIG_LEDS_TRIGGERS
+	led_trigger_unregister_charging(bat->charging_trig);
+	led_trigger_unregister_simple(bat->full_trig);
+	kfree(bat->full_trig_name);
+	kfree(bat->charging_trig_name);
+	#endif
+
+	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@f2s.com>, "
+              "Szabolcs Gyurko, "
+              "Anton Vorontsov <cbou@mail.ru>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/battery.h b/include/linux/battery.h
new file mode 100644
index 0000000..a687781
--- /dev/null
+++ b/include/linux/battery.h
@@ -0,0 +1,98 @@
+/*
+ *  Universal battery monitor class
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ *
+ * All voltages, currents, capacities and temperatures in mV, mA, mAh and
+ * tenths of a degree unless otherwise stated. It's driver's job to convert
+ * its raw values to which this class operates. If for some reason driver
+ * can't afford this requirement, then it have to create its own attributes,
+ * plus additional "XYZ_units" for each of them.
+ */
+
+#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
+
+/* 
+ * 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/uknown fields can be NULL and will not appear in sysfs.
+ */
+
+struct battery {
+	struct device *dev;
+	char *name;
+
+	/* For APM emulation, think legacy userspace. */
+	int main_battery;
+
+	/* executed in userspace, feel free to sleep */
+	int (*get_min_voltage)(struct battery *bat);
+	int (*get_min_current)(struct battery *bat);
+	int (*get_min_capacity)(struct battery *bat);
+	int (*get_max_voltage)(struct battery *bat);
+	int (*get_max_current)(struct battery *bat);
+	int (*get_max_capacity)(struct battery *bat);
+	int (*get_temp)(struct battery *bat);
+	int (*get_voltage)(struct battery *bat);
+	int (*get_current)(struct battery *bat);
+	int (*get_capacity)(struct battery *bat);
+	int (*get_status)(struct battery *bat);
+
+	/* drivers should not sleep inside it, you'll get there from ISRs */
+	void (*external_power_changed)(struct battery *bat);
+
+	/* private */
+	struct power_supplicant pst;
+
+	#ifdef CONFIG_LEDS_TRIGGERS
+	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 device
+ * itself does bot use it, but that's what implementing most drivers,
+ * should try reuse for consistency.
+ */
+
+struct battery_info {
+	char *name;
+	int min_voltage;
+	int max_voltage;
+	int min_current;
+	int max_current;
+	int min_capacity;
+	int max_capacity;
+	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
-- 
1.5.0.5-dirty

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-11 23:25 [PATCH 3/7] [RFC] Battery monitoring class Anton Vorontsov
@ 2007-04-12  2:53 ` Randy Dunlap
  2007-04-12 16:51   ` Anton Vorontsov
  2007-04-12  3:43 ` Greg KH
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 34+ messages in thread
From: Randy Dunlap @ 2007-04-12  2:53 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linux-kernel, kernel-discuss, dwmw2

On Thu, 12 Apr 2007 03:25:03 +0400 Anton Vorontsov wrote:

> Here is battery monitor class. According to first copyright string, we're
> maintaining it since 2003. I've took few days and cleaned it up to be
> more suitable for mainline inclusion.
> 
> ---
>  drivers/Kconfig           |    2 +
>  drivers/Makefile          |    1 +
>  drivers/battery/Kconfig   |   11 ++
>  drivers/battery/Makefile  |    1 +
>  drivers/battery/battery.c |  303 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/battery.h   |   98 +++++++++++++++
>  6 files changed, 416 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/battery/Kconfig
>  create mode 100644 drivers/battery/Makefile
>  create mode 100644 drivers/battery/battery.c
>  create mode 100644 include/linux/battery.h
> 
> diff --git a/drivers/battery/battery.c b/drivers/battery/battery.c
> new file mode 100644
> index 0000000..32b8288
> --- /dev/null
> +++ b/drivers/battery/battery.c
> @@ -0,0 +1,303 @@
> +
> +void battery_status_changed(struct battery *bat)
> +{
> +	pr_debug("%s\n", __FUNCTION__);
> +	#ifdef CONFIG_LEDS_TRIGGERS

Please don't indent preprocessor controls (ifdef/endif etc.).

> +	switch(bat->get_status(bat))
> +	{
> +		case BATTERY_STATUS_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_trig, LED_FULL);
> +			led_trigger_event(bat->full_trig, LED_OFF);
> +			break;
> +		default:
> +			led_trigger_event(bat->charging_trig, LED_OFF);
> +			led_trigger_event(bat->full_trig, LED_OFF);
> +			break;

Place 'switch' and 'case' at the same indent level.  This prevents
the "double-indent" for the code statements.

> +	}
> +	#endif /* CONFIG_LEDS_TRIGGERS */
> +	return;
> +}
> +
> +static char *status_text[] = {
> +	"Unknown", "Charging", "Discharging", "Not charging", "Full"
> +};
> +
> +static ssize_t battery_show_status(struct device *dev,
> +                                   struct device_attribute *attr, char *buf)
> +{
> +	struct battery *bat = dev_get_drvdata(dev);
> +	int status = 0;

We usually try to place a blank line between local data and code.

> +	if (bat->get_status) {
> +		status = bat->get_status(bat);
> +		if (status > 4)
> +			status = 0;
> +		return sprintf(buf, "%s\n", status_text[status]);
> +	}
> +	return 0;
> +}
> +
> +static int battery_create_attrs(struct battery *bat)
> +{
> +	int rc;
> +
> +	#define create_bat_attr_conditional(name)                    \
> +	if(bat->get_##name) {                                        \

	space after "if"

> +		rc = device_create_file(bat->dev, &dev_attr_##name); \
> +		if (rc) goto name##_failed;                          \
> +	}
> +
> +	create_bat_attr_conditional(status);
> +	create_bat_attr_conditional(min_voltage);
> +	create_bat_attr_conditional(min_current);
> +	create_bat_attr_conditional(min_capacity);
> +	create_bat_attr_conditional(max_voltage);
> +	create_bat_attr_conditional(max_current);
> +	create_bat_attr_conditional(max_capacity);
> +	create_bat_attr_conditional(temp);
> +	create_bat_attr_conditional(voltage);
> +	create_bat_attr_conditional(current);
> +	create_bat_attr_conditional(capacity);
> +
> +	#define remove_bat_attr_conditional(name)               \
> +	if(bat->get_##name)                                     \

ditto.

> +		device_remove_file(bat->dev, &dev_attr_##name);
> +
> +	goto success;
> +
> +capacity_failed:     remove_bat_attr_conditional(current);
> +current_failed:      remove_bat_attr_conditional(voltage);
> +voltage_failed:      remove_bat_attr_conditional(temp);
> +temp_failed:         remove_bat_attr_conditional(max_capacity);
> +max_capacity_failed: remove_bat_attr_conditional(max_current);
> +max_current_failed:  remove_bat_attr_conditional(max_voltage);
> +max_voltage_failed:  remove_bat_attr_conditional(min_capacity);
> +min_capacity_failed: remove_bat_attr_conditional(min_current);
> +min_current_failed:  remove_bat_attr_conditional(min_voltage);
> +min_voltage_failed:  remove_bat_attr_conditional(status);

I thought there was a class_remove() or something like that?
but I'm not sure of it.

> +status_failed:
> +success:
> +	return rc;
> +}
> +
> +static void battery_remove_attrs(struct battery *bat)
> +{
> +	remove_bat_attr_conditional(capacity);
> +	remove_bat_attr_conditional(current);
> +	remove_bat_attr_conditional(voltage);
> +	remove_bat_attr_conditional(temp);
> +	remove_bat_attr_conditional(max_capacity);
> +	remove_bat_attr_conditional(max_current);
> +	remove_bat_attr_conditional(max_voltage);
> +	remove_bat_attr_conditional(min_capacity);
> +	remove_bat_attr_conditional(min_current);
> +	remove_bat_attr_conditional(min_voltage);
> +	remove_bat_attr_conditional(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)) {

	space after "if"

> +		rc = PTR_ERR(bat->dev);
> +		goto dev_create_failed;
> +	}
> +
> +	dev_set_drvdata(bat->dev, bat);
> +
> +	rc = battery_create_attrs(bat);
> +	if (rc)
> +		goto create_bat_attrs_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;
> +
> +	#ifdef CONFIG_LEDS_TRIGGERS

Don't indent the preprocessor lines.  It hides them (too much).

> +	bat->charging_trig_name = kmalloc(strlen(bat->name) +
> +	                                  sizeof("-charging"), GFP_KERNEL);
> +	if (!bat->charging_trig_name) {
> +		rc = -ENOMEM;
> +		goto charging_trig_name_failed;
> +	}
> +
> +	bat->full_trig_name = kmalloc(strlen(bat->name) +
> +	                              sizeof("-full"), GFP_KERNEL);
> +	if (!bat->full_trig_name) {
> +		rc = -ENOMEM;
> +		goto full_trig_name_failed;
> +	}
> +
> +	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_charging(bat->charging_trig_name,
> +	                              &bat->charging_trig);
> +	led_trigger_register_simple(bat->full_trig_name,
> +	                            &bat->full_trig);
> +	#endif /* CONFIG_LEDS_TRIGGERS */
> +
> +	goto success;
> +
> +#ifdef CONFIG_LEDS_TRIGGERS
> +full_trig_name_failed:
> +	kfree(bat->charging_trig_name);
> +charging_trig_name_failed:
> +#endif
> +	power_supplicant_unregister(&bat->pst);
> +power_supplicant_failed:
> +	battery_remove_attrs(bat);
> +create_bat_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_attrs(bat);
> +	device_unregister(bat->dev);
> +
> +	#ifdef CONFIG_LEDS_TRIGGERS

ifdef/endif not indented, please.

> +	led_trigger_unregister_charging(bat->charging_trig);
> +	led_trigger_unregister_simple(bat->full_trig);
> +	kfree(bat->full_trig_name);
> +	kfree(bat->charging_trig_name);
> +	#endif
> +
> +	return;
> +}
> +
> diff --git a/include/linux/battery.h b/include/linux/battery.h
> new file mode 100644
> index 0000000..a687781
> --- /dev/null
> +++ b/include/linux/battery.h
> @@ -0,0 +1,98 @@
> +
> +/* 
> + * 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/uknown fields can be NULL and will not appear in sysfs.

                    unknown

> + */
> +
> +struct battery {
> +	struct device *dev;
> +	char *name;
> +
> +	/* For APM emulation, think legacy userspace. */
> +	int main_battery;
> +
> +	/* executed in userspace, feel free to sleep */
> +	int (*get_min_voltage)(struct battery *bat);
> +	int (*get_min_current)(struct battery *bat);
> +	int (*get_min_capacity)(struct battery *bat);
> +	int (*get_max_voltage)(struct battery *bat);
> +	int (*get_max_current)(struct battery *bat);
> +	int (*get_max_capacity)(struct battery *bat);
> +	int (*get_temp)(struct battery *bat);
> +	int (*get_voltage)(struct battery *bat);
> +	int (*get_current)(struct battery *bat);
> +	int (*get_capacity)(struct battery *bat);
> +	int (*get_status)(struct battery *bat);
> +
> +	/* drivers should not sleep inside it, you'll get there from ISRs */
> +	void (*external_power_changed)(struct battery *bat);
> +
> +	/* private */
> +	struct power_supplicant pst;
> +
> +	#ifdef CONFIG_LEDS_TRIGGERS

ifdef/endif not indented.

> +	struct led_trigger *charging_trig;
> +	char *charging_trig_name;
> +	struct led_trigger *full_trig;
> +	char *full_trig_name;
> +	#endif
> +};
> +
> +/* 

Please check all patches for trailing whitespace and correct that.

> + * This is recommended structure to specify static battery parameters.
> + * Generic one, parametrizable for different batteries. Battery device
> + * itself does bot use it, but that's what implementing most drivers,
> + * should try reuse for consistency.
> + */


---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-11 23:25 [PATCH 3/7] [RFC] Battery monitoring class Anton Vorontsov
  2007-04-12  2:53 ` Randy Dunlap
@ 2007-04-12  3:43 ` Greg KH
  2007-04-12 12:25   ` Henrique de Moraes Holschuh
  2007-04-12 13:43   ` Anton Vorontsov
  2007-04-12 13:08 ` Matthew Garrett
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 34+ messages in thread
From: Greg KH @ 2007-04-12  3:43 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linux-kernel, kernel-discuss, dwmw2

On Thu, Apr 12, 2007 at 03:25:03AM +0400, Anton Vorontsov wrote:
> Here is battery monitor class. According to first copyright string, we're
> maintaining it since 2003. I've took few days and cleaned it up to be
> more suitable for mainline inclusion.
> 
> It differs from battery class at git://git.infradead.org/battery-2.6.git:

Why fork from David's work?  Does he not like these changes for some
reason?

> +static int battery_create_attrs(struct battery *bat)
> +{
> +	int rc;
> +
> +	#define create_bat_attr_conditional(name)                    \
> +	if(bat->get_##name) {                                        \
> +		rc = device_create_file(bat->dev, &dev_attr_##name); \
> +		if (rc) goto name##_failed;                          \
> +	}
> +
> +	create_bat_attr_conditional(status);
> +	create_bat_attr_conditional(min_voltage);
> +	create_bat_attr_conditional(min_current);
> +	create_bat_attr_conditional(min_capacity);
> +	create_bat_attr_conditional(max_voltage);
> +	create_bat_attr_conditional(max_current);
> +	create_bat_attr_conditional(max_capacity);
> +	create_bat_attr_conditional(temp);
> +	create_bat_attr_conditional(voltage);
> +	create_bat_attr_conditional(current);
> +	create_bat_attr_conditional(capacity);

Use an attribute group please.  It's much simpler and will be created at
the proper time so your userspace tools don't have to sit and spin in
order to properly wait for them to show up.

Ok, yes, you want a conditional type of attribute group, like the
new firewire code does.  I have no problem adding that if you like.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12  3:43 ` Greg KH
@ 2007-04-12 12:25   ` Henrique de Moraes Holschuh
  2007-04-12 13:43   ` Anton Vorontsov
  1 sibling, 0 replies; 34+ messages in thread
From: Henrique de Moraes Holschuh @ 2007-04-12 12:25 UTC (permalink / raw)
  To: Greg KH; +Cc: Anton Vorontsov, linux-kernel, kernel-discuss, dwmw2

On Wed, 11 Apr 2007, Greg KH wrote:
> Ok, yes, you want a conditional type of attribute group, like the
> new firewire code does.  I have no problem adding that if you like.

Please do.  I want that for ibm-acpi/thinkpad-acpi as well.  Right now I
need to use multiple attribute groups because of that.  Some hwmon drivers
are in the same boat, too.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-11 23:25 [PATCH 3/7] [RFC] Battery monitoring class Anton Vorontsov
  2007-04-12  2:53 ` Randy Dunlap
  2007-04-12  3:43 ` Greg KH
@ 2007-04-12 13:08 ` Matthew Garrett
  2007-04-12 14:15   ` Anton Vorontsov
  2007-04-12 15:00 ` Shem Multinymous
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 34+ messages in thread
From: Matthew Garrett @ 2007-04-12 13:08 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linux-kernel, kernel-discuss, dwmw2

On Thu, Apr 12, 2007 at 03:25:03AM +0400, Anton Vorontsov wrote:
> + * All voltages, currents, capacities and temperatures in mV, mA, mAh and
> + * tenths of a degree unless otherwise stated. It's driver's job to convert
> + * its raw values to which this class operates. If for some reason driver
> + * can't afford this requirement, then it have to create its own attributes,
> + * plus additional "XYZ_units" for each of them.

ACPI batteries can report capacity and rate in either mA or mW. Given 
the lack of a constant voltage, how do you accurately convert between 
the two? Right now, I think this is a loss of functionality over the 
current situation.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12  3:43 ` Greg KH
  2007-04-12 12:25   ` Henrique de Moraes Holschuh
@ 2007-04-12 13:43   ` Anton Vorontsov
  1 sibling, 0 replies; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-12 13:43 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, kernel-discuss, dwmw2

Hello Greg,

On Wed, Apr 11, 2007 at 08:43:23PM -0700, Greg KH wrote:
> On Thu, Apr 12, 2007 at 03:25:03AM +0400, Anton Vorontsov wrote:
> > Here is battery monitor class. According to first copyright string, we're
> > maintaining it since 2003. I've took few days and cleaned it up to be
> > more suitable for mainline inclusion.
> > 
> > It differs from battery class at git://git.infradead.org/battery-2.6.git:
> 
> Why fork from David's work?  Does he not like these changes for some
> reason?

It's not a fork, actually. Ian Molton started battery stuff years before
David's work.

Though ours and David's exported API functions are exactly the same
(don't count functions which are unique for our code), but our
implementation a little intersects with David's.

For me it was no matter if I'll take handhelds.org or David's code as a
start point, except that hh.o code familiar to me, and I can test it on
real devices.

Though, you're right, we're in situation when we've two battery classes
now. :-/ And another pity fact is that we also have 8 Mb of patches in
our CVS. It takes a lot of time to to cleanup code for mainline,
especially with limited man-power resources. But we're working hard.

So, this is brief explanation why it took so long for us to show up.

> > +static int battery_create_attrs(struct battery *bat)
> > +{
> > +	int rc;
> > +
> > +	#define create_bat_attr_conditional(name)                    \
> > +	if(bat->get_##name) {                                        \
> > +		rc = device_create_file(bat->dev, &dev_attr_##name); \
> > +		if (rc) goto name##_failed;                          \
> > +	}
> > +
> > +	create_bat_attr_conditional(status);
> > +	create_bat_attr_conditional(min_voltage);
> > +	create_bat_attr_conditional(min_current);
> > +	create_bat_attr_conditional(min_capacity);
> > +	create_bat_attr_conditional(max_voltage);
> > +	create_bat_attr_conditional(max_current);
> > +	create_bat_attr_conditional(max_capacity);
> > +	create_bat_attr_conditional(temp);
> > +	create_bat_attr_conditional(voltage);
> > +	create_bat_attr_conditional(current);
> > +	create_bat_attr_conditional(capacity);
> 
> Use an attribute group please.  It's much simpler and will be created at
> the proper time so your userspace tools don't have to sit and spin in
> order to properly wait for them to show up.
> 
> Ok, yes, you want a conditional type of attribute group, like the
> new firewire code does.  I have no problem adding that if you like.

I'm not sure if it's possible to create that type of conditional
attribute group. Because the condition is "bat->func != NULL", not
attribute' function. And that condition is battery-specific, not class
specific.

But anyway, I guess you're talking about not yet existent API, so I'd be
glad to take a look.

> thanks,
> 
> greg k-h

Thanks for comments!

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12 13:08 ` Matthew Garrett
@ 2007-04-12 14:15   ` Anton Vorontsov
  2007-04-12 14:24     ` Matthew Garrett
  0 siblings, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-12 14:15 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: linux-kernel, kernel-discuss, dwmw2

On Thu, Apr 12, 2007 at 02:08:18PM +0100, Matthew Garrett wrote:
> On Thu, Apr 12, 2007 at 03:25:03AM +0400, Anton Vorontsov wrote:
> > + * All voltages, currents, capacities and temperatures in mV, mA, mAh and
> > + * tenths of a degree unless otherwise stated. It's driver's job to convert
> > + * its raw values to which this class operates. If for some reason driver
> > + * can't afford this requirement, then it have to create its own attributes,
> > + * plus additional "XYZ_units" for each of them.
> 
> ACPI batteries can report capacity and rate in either mA or mW. Given

You sure, capacity in mA? Then I don't know. But you can safely
fallback and create your own attribute (just as in David's battery class,
where every battery required to create its own attributes), plus create
capacity_units attribute. So, user space will know your driver's specific
units.

> the lack of a constant voltage, how do you accurately convert between 
> the two? Right now, I think this is a loss of functionality over the 
> current situation.


> 
> -- 
> Matthew Garrett | mjg59@srcf.ucam.org

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12 14:15   ` Anton Vorontsov
@ 2007-04-12 14:24     ` Matthew Garrett
  2007-04-12 14:36       ` [Kernel-discuss] " Paul Sokolovsky
  0 siblings, 1 reply; 34+ messages in thread
From: Matthew Garrett @ 2007-04-12 14:24 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linux-kernel, kernel-discuss, dwmw2

On Thu, Apr 12, 2007 at 06:15:05PM +0400, Anton Vorontsov wrote:
> On Thu, Apr 12, 2007 at 02:08:18PM +0100, Matthew Garrett wrote:
> > ACPI batteries can report capacity and rate in either mA or mW. Given
> 
> You sure, capacity in mA? Then I don't know. But you can safely
> fallback and create your own attribute (just as in David's battery class,
> where every battery required to create its own attributes), plus create
> capacity_units attribute. So, user space will know your driver's specific
> units.

Well, mAh, but yes. Clearly it's possible to add extra attributes, but 
speccing standard attributes that don't entirely cover the most common 
non-embedded battery class seems less than ideal. Why not just require
capacity_units and rate_units attributes?

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12 14:24     ` Matthew Garrett
@ 2007-04-12 14:36       ` Paul Sokolovsky
  2007-04-12 18:56         ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 34+ messages in thread
From: Paul Sokolovsky @ 2007-04-12 14:36 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: Anton Vorontsov, dwmw2, linux-kernel, kernel-discuss

Hello Matthew,

Thursday, April 12, 2007, 5:24:30 PM, you wrote:

> On Thu, Apr 12, 2007 at 06:15:05PM +0400, Anton Vorontsov wrote:
>> On Thu, Apr 12, 2007 at 02:08:18PM +0100, Matthew Garrett wrote:
>> > ACPI batteries can report capacity and rate in either mA or mW. Given
>> 
>> You sure, capacity in mA? Then I don't know. But you can safely
>> fallback and create your own attribute (just as in David's battery class,
>> where every battery required to create its own attributes), plus create
>> capacity_units attribute. So, user space will know your driver's specific
>> units.

> Well, mAh, but yes. Clearly it's possible to add extra attributes, but
> speccing standard attributes that don't entirely cover the most common
> non-embedded battery class seems less than ideal. Why not just require
> capacity_units and rate_units attributes?

  Yes, that's apparently the way to go. We just should consider
if mAh and mWh are enough, or we go wider and allow whole collection of
units. Btw, original handhelds.org code used Joules ;-).


-- 
Best regards,
 Paul                            mailto:pmiscml@gmail.com


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-11 23:25 [PATCH 3/7] [RFC] Battery monitoring class Anton Vorontsov
                   ` (2 preceding siblings ...)
  2007-04-12 13:08 ` Matthew Garrett
@ 2007-04-12 15:00 ` Shem Multinymous
  2007-04-12 15:18   ` Anton Vorontsov
  2007-04-13 13:49 ` Anton Vorontsov
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 34+ messages in thread
From: Shem Multinymous @ 2007-04-12 15:00 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linux-kernel, kernel-discuss, dwmw2

Hi Anton,

A few comments on the ever-contentious choice of battery attributes:

On 4/11/07, Anton Vorontsov <cbou@mail.ru> wrote:
> + * All voltages, currents, capacities and temperatures in mV, mA, mAh and
> + * tenths of a degree unless otherwise stated. It's driver's job to convert
> + * its raw values to which this class operates. If for some reason driver
> + * can't afford this requirement, then it have to create its own attributes,
> + * plus additional "XYZ_units" for each of them.
> + */

Many (most, I believe) laptop batteries report capacity in mWh
(energy), not mAh (charge). You can't convert between the two without
a detailed, up-to-date physical model of the battery. This is too
common to relegate to a non-standardized "XYZ_units" extension.


> +BATTERY_INT_ATTR(min_voltage);
> +BATTERY_INT_ATTR(min_current);
> +BATTERY_INT_ATTR(min_capacity);
> +BATTERY_INT_ATTR(max_voltage);
> +BATTERY_INT_ATTR(max_current);
> +BATTERY_INT_ATTR(max_capacity);
> +BATTERY_INT_ATTR(temp);
> +BATTERY_INT_ATTR(voltage);
> +BATTERY_INT_ATTR(current);
> +BATTERY_INT_ATTR(capacity);

I suggest adding "remaining operating time" and "remaining charging
time". You can try deducing these from the above attributes, but in
practice this gives very inaccurate predictions. On laptops (e.g.,
ThinkPad) the BIOS or EC often provides much better estimates, using a
more accurate physical model.

I also see you omitted a host of other common attributes, like design
capacity, cycle count, model string, and temperatures. There was an
extensive LKML discussion of the choice and naming of attributes, in
the context of David Woodhouse's patch; there are futher observations
there. Also, here's the list of attributes in my tp_smapi ThinkPad
driver: http://thinkwiki.org/wiki/tp_smapi#Battery_charge_control_features

Does "max capaxity" correspond to what's usually denoted "last full capacity".

I understand you allow adding custom attributes, but they're of
limited use if generic userspace tools don't know their name and
semantics. It's important to standardize all reasonably common
attributes.

  Shem

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12 15:00 ` Shem Multinymous
@ 2007-04-12 15:18   ` Anton Vorontsov
  2007-04-12 17:23     ` Shem Multinymous
  0 siblings, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-12 15:18 UTC (permalink / raw)
  To: Shem Multinymous; +Cc: linux-kernel, kernel-discuss, dwmw2

Hello Shem,

On Thu, Apr 12, 2007 at 11:00:07AM -0400, Shem Multinymous wrote:
> Hi Anton,
> 
> A few comments on the ever-contentious choice of battery attributes:
> 
> On 4/11/07, Anton Vorontsov <cbou@mail.ru> wrote:
> >+ * All voltages, currents, capacities and temperatures in mV, mA, mAh and
> >+ * tenths of a degree unless otherwise stated. It's driver's job to 
> >convert
> >+ * its raw values to which this class operates. If for some reason driver
> >+ * can't afford this requirement, then it have to create its own 
> >attributes,
> >+ * plus additional "XYZ_units" for each of them.
> >+ */
> 
> Many (most, I believe) laptop batteries report capacity in mWh
> (energy), not mAh (charge). You can't convert between the two without
> a detailed, up-to-date physical model of the battery. This is too
> common to relegate to a non-standardized "XYZ_units" extension.

I see. Okay, I'll try to cook something regarding capacity units.

> >+BATTERY_INT_ATTR(min_voltage);
> >+BATTERY_INT_ATTR(min_current);
> >+BATTERY_INT_ATTR(min_capacity);
> >+BATTERY_INT_ATTR(max_voltage);
> >+BATTERY_INT_ATTR(max_current);
> >+BATTERY_INT_ATTR(max_capacity);
> >+BATTERY_INT_ATTR(temp);
> >+BATTERY_INT_ATTR(voltage);
> >+BATTERY_INT_ATTR(current);
> >+BATTERY_INT_ATTR(capacity);
> 
> I suggest adding "remaining operating time" and "remaining charging
> time". You can try deducing these from the above attributes, but in
> practice this gives very inaccurate predictions. On laptops (e.g.,
> ThinkPad) the BIOS or EC often provides much better estimates, using a
> more accurate physical model.

Yes, sure. Feel free to add these attributes to the "standard" ones,
along with your drivers. See (1).

> 
> I also see you omitted a host of other common attributes, like design
> capacity, cycle count, model string, and temperatures. There was an
> extensive LKML discussion of the choice and naming of attributes, in
> the context of David Woodhouse's patch; there are futher observations
> there. Also, here's the list of attributes in my tp_smapi ThinkPad
> driver: http://thinkwiki.org/wiki/tp_smapi#Battery_charge_control_features
> 
> Does "max capaxity" correspond to what's usually denoted "last full 
> capacity".

Yup.

> I understand you allow adding custom attributes, but they're of
> limited use if generic userspace tools don't know their name and
> semantics. It's important to standardize all reasonably common
> attributes.

(1) You're free to add your attribute to "standard" ones in
include/linux/battery.h if it's proven to widely used. Batteries which
do not have such attribute will not even notice that addition, so you
will not have to grep and modify other drivers.

So, that is plain matter of code duplication. If two or more battery
drivers have same attributes, then we can put it in battery.h.
If only one driver using it, then code duplication impossible, and
driver should keep this attribute private.

In handhelds.org tree we have two battery drivers with attributes you
see currently. Second driver is not ready for mainline inclusion yet
(it depends on ADC framework, which we'll present soon), thus I've not
posted it.


Also, APM emulation driver should learn how to use one attribute, or
another depending on which available/better. But this is only technical
question, like

if (battery have attribute1)
	do precise maths of something, because we have mWh;
else
	do approx maths of something, because we have only mAh.
else
	n/a.

>  Shem

Thanks for comments!

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12  2:53 ` Randy Dunlap
@ 2007-04-12 16:51   ` Anton Vorontsov
  0 siblings, 0 replies; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-12 16:51 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: linux-kernel, kernel-discuss, dwmw2

Hello Randy,

On Wed, Apr 11, 2007 at 07:53:59PM -0700, Randy Dunlap wrote:
> On Thu, 12 Apr 2007 03:25:03 +0400 Anton Vorontsov wrote:
> > +void battery_status_changed(struct battery *bat)
> > +{
> > +	pr_debug("%s\n", __FUNCTION__);
> > +	#ifdef CONFIG_LEDS_TRIGGERS
> 
> Please don't indent preprocessor controls (ifdef/endif etc.).
...
> Place 'switch' and 'case' at the same indent level.  This prevents
> the "double-indent" for the code statements.
...
> We usually try to place a blank line between local data and code.
...
> 	space after "if"
...

Much thanks, will fix.

> > +		device_remove_file(bat->dev, &dev_attr_##name);
> > +
> > +	goto success;
> > +
> > +capacity_failed:     remove_bat_attr_conditional(current);
> > +current_failed:      remove_bat_attr_conditional(voltage);
> > +voltage_failed:      remove_bat_attr_conditional(temp);
> > +temp_failed:         remove_bat_attr_conditional(max_capacity);
> > +max_capacity_failed: remove_bat_attr_conditional(max_current);
> > +max_current_failed:  remove_bat_attr_conditional(max_voltage);
> > +max_voltage_failed:  remove_bat_attr_conditional(min_capacity);
> > +min_capacity_failed: remove_bat_attr_conditional(min_current);
> > +min_current_failed:  remove_bat_attr_conditional(min_voltage);
> > +min_voltage_failed:  remove_bat_attr_conditional(status);
> 
> I thought there was a class_remove() or something like that?
> but I'm not sure of it.

[class_]device_destroy()? Yeah, but it's exactly same thing as
[class_]device_unregister.

But this is really good question. Should I manually clean up attributes,
or sysfs will take care? I.e. whole battery directory removes, and
sysfs removes files in it, or they just leaks?

I've took worst scenario, and done removal manually (I've grep'ed in
drivers/, and almost every driver also doing so).

> ---
> ~Randy
> *** Remember to use Documentation/SubmitChecklist when testing your code ***

Thanks for comments!

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12 15:18   ` Anton Vorontsov
@ 2007-04-12 17:23     ` Shem Multinymous
  0 siblings, 0 replies; 34+ messages in thread
From: Shem Multinymous @ 2007-04-12 17:23 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linux-kernel, kernel-discuss, dwmw2

Hi Anton,

On 4/12/07, Anton Vorontsov <cbou@mail.ru> wrote:
> On Thu, Apr 12, 2007 at 11:00:07AM -0400, Shem Multinymous wrote:
> > I suggest adding "remaining operating time" and "remaining charging
> > time". You can try deducing these from the above attributes, but in
> > practice this gives very inaccurate predictions. On laptops (e.g.,
> > ThinkPad) the BIOS or EC often provides much better estimates, using a
> > more accurate physical model.
>
> Yes, sure. Feel free to add these attributes to the "standard" ones,
> along with your drivers. See (1).

That's a sound way to go around i. We just need to be careful about
naming conventions. For example, "*_charge" rather than "*_capacity,
so that we can later add "*_energy" analogously.

But specifically about {operating,charge} time remaining readouts, it
seems important to have them there from the beginning and have all
drivers implement them. Otherwise, userspace will just go ahead and
implement its own crude computation, so by the time when new
attributes and drivers are introduced, userspace will be full of bad
code. I've seen this happening with the tp_smapi ThinkPad driver -- I
introduced those attributes at a recent version, and then needed to
encourage userspace utility authors to dump their extrapolation
calcultions and use the attribute instead.

The rest of the missing attributes are not as imporant in this
respect, because userspace can't try to estimate them.

  Shem

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12 14:36       ` [Kernel-discuss] " Paul Sokolovsky
@ 2007-04-12 18:56         ` Henrique de Moraes Holschuh
  2007-04-12 20:44           ` Anton Vorontsov
  0 siblings, 1 reply; 34+ messages in thread
From: Henrique de Moraes Holschuh @ 2007-04-12 18:56 UTC (permalink / raw)
  To: Paul Sokolovsky
  Cc: Matthew Garrett, Anton Vorontsov, dwmw2, linux-kernel,
	kernel-discuss

On Thu, 12 Apr 2007, Paul Sokolovsky wrote:
>   Yes, that's apparently the way to go. We just should consider
> if mAh and mWh are enough, or we go wider and allow whole collection of
> units. Btw, original handhelds.org code used Joules ;-).

FWIW, SBS only mentions mAh and mWh.  AFAIK, all other (meaningful) units
should be able to be converted to either Ah or Wh, assuming enough precision
on the math.  I never heard of any other way to fuel-gauge batteries than
these two main modes (current-based or capacity-based), but I don't work on
the battery field.

That said, you may need to use uWh and uAh instead of mAh and mWh, though.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12 18:56         ` Henrique de Moraes Holschuh
@ 2007-04-12 20:44           ` Anton Vorontsov
  2007-04-13  0:51             ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-12 20:44 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh
  Cc: Paul Sokolovsky, Matthew Garrett, dwmw2, linux-kernel,
	kernel-discuss, Shem Multinymous

On Thu, Apr 12, 2007 at 03:56:30PM -0300, Henrique de Moraes Holschuh wrote:
> On Thu, 12 Apr 2007, Paul Sokolovsky wrote:
> >   Yes, that's apparently the way to go. We just should consider
> > if mAh and mWh are enough, or we go wider and allow whole collection of
> > units. Btw, original handhelds.org code used Joules ;-).
> 
> FWIW, SBS only mentions mAh and mWh.  AFAIK, all other (meaningful) units
> should be able to be converted to either Ah or Wh, assuming enough precision
> on the math.  I never heard of any other way to fuel-gauge batteries than
> these two main modes (current-based or capacity-based), but I don't work on
> the battery field.

Okay, I have an idea:

Let's name attributes with mWh units as {min_,max_,design_,}energy,
and attributes with mAh units as {min_,max_,design_,}charge.

Because both energy and charge represents ""capacity"" in some meanings,
and that's why we bothering with _units attribute. So, lets drop
"capacity"* and use more specific terms? I really don't want string
attributes by default (except status).

If we export attributes with predefined units, userspace developers
could just look into include/linux/battery.h and conclude: "Ah, great,
if battery reporting energy, then it's in mWh, and if battery reporting
charge it's always in mAh".

* Yup, I've read last discussion regarding batteries, and I've seen
  objections against "charge" term, quoting Shem Multinymous:

  "And, for the reasons I explained earlier, I strongly suggest not using
  the term "charge" except when referring to the action of charging.
  Hence:
  s/charge_rate/rate/;  s/charge/capacity/"

  But lets think about it once again? We'll make things much cleaner
  if we'll drop "capacity" at all.

> That said, you may need to use uWh and uAh instead of mAh and mWh, though.

Not sure. Is there any existing chip that can report uAh/uWh? That is
great precision.

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-12 20:44           ` Anton Vorontsov
@ 2007-04-13  0:51             ` Henrique de Moraes Holschuh
  2007-04-13  2:15               ` Anton Vorontsov
  2007-04-13  2:34               ` Shem Multinymous
  0 siblings, 2 replies; 34+ messages in thread
From: Henrique de Moraes Holschuh @ 2007-04-13  0:51 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Paul Sokolovsky, Matthew Garrett, dwmw2, linux-kernel,
	kernel-discuss, Shem Multinymous

On Fri, 13 Apr 2007, Anton Vorontsov wrote:
> Let's name attributes with mWh units as {min_,max_,design_,}energy,
> and attributes with mAh units as {min_,max_,design_,}charge.

[...]

> * Yup, I've read last discussion regarding batteries, and I've seen
>   objections against "charge" term, quoting Shem Multinymous:
> 
>   "And, for the reasons I explained earlier, I strongly suggest not using
>   the term "charge" except when referring to the action of charging.
>   Hence:
>   s/charge_rate/rate/;  s/charge/capacity/"
> 
>   But lets think about it once again? We'll make things much cleaner
>   if we'll drop "capacity" at all.

I stand with Shem on this one.  The people behind the SBS specification
seems to agree... that specification is aimed at *engineers* and still
avoids the obvious trap of using "charge" due to its high potential for
confusion.

I don't even want to know how much of a mess the people writing applets
woudl make of it...

> > That said, you may need to use uWh and uAh instead of mAh and mWh, though.
> 
> Not sure. Is there any existing chip that can report uAh/uWh? That is
> great precision.

The way things are going, it should be feasible for small embedded systems
quite soon.  Refer to the previous thread.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-13  0:51             ` Henrique de Moraes Holschuh
@ 2007-04-13  2:15               ` Anton Vorontsov
  2007-04-24 19:36                 ` Pavel Machek
  2007-04-13  2:34               ` Shem Multinymous
  1 sibling, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-13  2:15 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh
  Cc: Matthew Garrett, kernel-discuss, linux-kernel, dwmw2,
	Shem Multinymous

On Thu, Apr 12, 2007 at 09:51:12PM -0300, Henrique de Moraes Holschuh wrote:
> On Fri, 13 Apr 2007, Anton Vorontsov wrote:
> > Let's name attributes with mWh units as {min_,max_,design_,}energy,
> > and attributes with mAh units as {min_,max_,design_,}charge.
> 
> [...]
> 
> > * Yup, I've read last discussion regarding batteries, and I've seen
> >   objections against "charge" term, quoting Shem Multinymous:
> > 
> >   "And, for the reasons I explained earlier, I strongly suggest not using
> >   the term "charge" except when referring to the action of charging.
> >   Hence:
> >   s/charge_rate/rate/;  s/charge/capacity/"
> > 
> >   But lets think about it once again? We'll make things much cleaner
> >   if we'll drop "capacity" at all.
> 
> I stand with Shem on this one.  The people behind the SBS specification
> seems to agree... that specification is aimed at *engineers* and still
> avoids the obvious trap of using "charge" due to its high potential for
> confusion.
> 
> I don't even want to know how much of a mess the people writing applets
> woudl make of it...

:-(

Okay, term "charge" is out of scope, I guess. But can we use "capacity"
for xAh, and "energy" for xWh? I just trying to separate these terms
somehow, and avoid "_units" stuff.

> 
> > > That said, you may need to use uWh and uAh instead of mAh and mWh, though.
> > 
> > Not sure. Is there any existing chip that can report uAh/uWh? That is
> > great precision.
> 
> The way things are going, it should be feasible for small embedded systems
> quite soon.  Refer to the previous thread.

I see... is it also applicable to currents and voltages? I.e. should we
use uA and uV from the start?

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-13  0:51             ` Henrique de Moraes Holschuh
  2007-04-13  2:15               ` Anton Vorontsov
@ 2007-04-13  2:34               ` Shem Multinymous
  2007-04-13  2:36                 ` Anton Vorontsov
  1 sibling, 1 reply; 34+ messages in thread
From: Shem Multinymous @ 2007-04-13  2:34 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh
  Cc: Anton Vorontsov, Paul Sokolovsky, Matthew Garrett, dwmw2,
	linux-kernel, kernel-discuss

Hi,

On 4/12/07, Henrique de Moraes Holschuh <hmh@hmh.eng.br> wrote:
> On Fri, 13 Apr 2007, Anton Vorontsov wrote:
> > * Yup, I've read last discussion regarding batteries, and I've seen
> >   objections against "charge" term, quoting Shem Multinymous:
> >
> >   "And, for the reasons I explained earlier, I strongly suggest not using
> >   the term "charge" except when referring to the action of charging.
> >   Hence:
> >   s/charge_rate/rate/;  s/charge/capacity/"
> >
> >   But lets think about it once again? We'll make things much cleaner
> >   if we'll drop "capacity" at all.
>
> I stand with Shem on this one.  The people behind the SBS specification
> seems to agree... that specification is aimed at *engineers* and still
> avoids the obvious trap of using "charge" due to its high potential for
> confusion.
>
> I don't even want to know how much of a mess the people writing applets
> woudl make of it...

With fixed-units files, having *_energy and *_capacity isn't too clear
either... Nor is it consistent with SBS, since SBS uses "capacity" to
refer to either energy or charge, depending on a units attribute.

As a compromise, how about using "energy" and "charge" for quantities,
and "charging" (i.e., a verb) when referring to the operation?

BTW,  tp_smapi uses "charge" and "charging" interchangeably; that was
a  mistake.

  Shem

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-13  2:34               ` Shem Multinymous
@ 2007-04-13  2:36                 ` Anton Vorontsov
  2007-04-13 13:51                   ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-13  2:36 UTC (permalink / raw)
  To: Shem Multinymous
  Cc: Henrique de Moraes Holschuh, Paul Sokolovsky, Matthew Garrett,
	dwmw2, linux-kernel, kernel-discuss

On Thu, Apr 12, 2007 at 10:34:06PM -0400, Shem Multinymous wrote:
> Hi,
> 
> On 4/12/07, Henrique de Moraes Holschuh <hmh@hmh.eng.br> wrote:
> >On Fri, 13 Apr 2007, Anton Vorontsov wrote:
> >> * Yup, I've read last discussion regarding batteries, and I've seen
> >>   objections against "charge" term, quoting Shem Multinymous:
> >>
> >>   "And, for the reasons I explained earlier, I strongly suggest not using
> >>   the term "charge" except when referring to the action of charging.
> >>   Hence:
> >>   s/charge_rate/rate/;  s/charge/capacity/"
> >>
> >>   But lets think about it once again? We'll make things much cleaner
> >>   if we'll drop "capacity" at all.
> >
> >I stand with Shem on this one.  The people behind the SBS specification
> >seems to agree... that specification is aimed at *engineers* and still
> >avoids the obvious trap of using "charge" due to its high potential for
> >confusion.
> >
> >I don't even want to know how much of a mess the people writing applets
> >woudl make of it...
> 
> With fixed-units files, having *_energy and *_capacity isn't too clear
> either... Nor is it consistent with SBS, since SBS uses "capacity" to
> refer to either energy or charge, depending on a units attribute.
> 
> As a compromise, how about using "energy" and "charge" for quantities,
> and "charging" (i.e., a verb) when referring to the operation?

It would be great compromise! Please please please!

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-11 23:25 [PATCH 3/7] [RFC] Battery monitoring class Anton Vorontsov
                   ` (3 preceding siblings ...)
  2007-04-12 15:00 ` Shem Multinymous
@ 2007-04-13 13:49 ` Anton Vorontsov
  2007-04-15  0:43   ` Anton Vorontsov
  2007-04-15 19:56 ` Pavel Machek
  2007-04-15 22:08 ` Ondrej Zajicek
  6 siblings, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-13 13:49 UTC (permalink / raw)
  To: linux-kernel
  Cc: kernel-discuss, dwmw2, Greg KH, Randy Dunlap, Shem Multinymous,
	Henrique de Moraes Holschuh, Matthew Garrett

On Thu, Apr 12, 2007 at 03:25:03AM +0400, Anton Vorontsov wrote:
> Here is battery monitor class. According to first copyright string, we're
> maintaining it since 2003. I've took few days and cleaned it up to be
> more suitable for mainline inclusion.
> 
> It differs from battery class at git://git.infradead.org/battery-2.6.git:
> 
> * It's using external power kernel interface, i.e. does not fake external
>   powers as batteries. (Same thing David Woodhouse planed last year).
> 
> * It have predefined set of attributes, this eliminates code duplication
>   by battery drivers. And also gives opportunity to write emulation drivers
>   for legacy stuff (APM emulation driver follow).
> 
>   If driver can't afford some attribute, it will not appear in sysfs.
> 
> * It insists on reusing its predefined attributes *and* their units.
>   So, userspace getting expected values for any battery.
>   
>   Also common units is required for APM/ACPI emulation.
>   
>   Though our battery class insisting on re-usage, but not forces it. If some
>   battery driver can't convert its own raw values (can't imagine why), then
>   driver is free to implement its own attributes *and* additional _units
>   attribute. Though, this scheme is discouraged.
> 
> * LEDs support. Each battery register its trigger, and gadgets with LEDs
>   can quickly bind to battery-charging / battery-full triggers.
> 
> Here how it looks like from user space:
> 
> # ls /sys/class/battery/main-battery/
> capacity  max_capacity  max_voltage   min_current  power   subsystem  uevent
> current   max_current   min_capacity  min_voltage  status  temp       voltage
> # cat /sys/class/battery/main-battery/status
> Full
> # cat /sys/class/leds/h5400\:green-right/trigger
> none h5400-radio timer hwtimer main-battery-charging [main-battery-full]
> # cat /sys/class/leds/h5400\:green-right/brightness
> 255
> 

Changes:

- Cleanups based on comments from Randy Dunlap.

- Attribute creation scheme changed drastically. No more tons of

  macro-created functions. Compiled code should be much smaller.
  Also adding new "standard" attributes is trivial task now (matter of
  adding two lines, one in battery.c and another in battery.h).

- charge (as quantity) in mAh, energy in mWh.


I'll convert mXh to uXh a bit later, if there will no further objections
against uXh. Also I'd like to hear if there any objections on
mA/mV -> uA/uV conversion. I think we'd better keep all units at the
same order/precision.


Subject: [PATCH] [take2] Battery monitoring class


Signed-off-by: Anton Vorontsov <cbou@mail.ru>
---
 drivers/Kconfig           |    2 +
 drivers/Makefile          |    1 +
 drivers/battery/Kconfig   |   11 ++
 drivers/battery/Makefile  |    1 +
 drivers/battery/battery.c |  290 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/battery.h   |  113 ++++++++++++++++++
 6 files changed, 418 insertions(+), 0 deletions(-)
 create mode 100644 drivers/battery/Kconfig
 create mode 100644 drivers/battery/Makefile
 create mode 100644 drivers/battery/battery.c
 create mode 100644 include/linux/battery.h

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..a2239cb
--- /dev/null
+++ b/drivers/battery/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BATTERY)              += battery.o
diff --git a/drivers/battery/battery.c b/drivers/battery/battery.c
new file mode 100644
index 0000000..6c87fe3
--- /dev/null
+++ b/drivers/battery/battery.c
@@ -0,0 +1,290 @@
+/*
+ *  Universal battery monitor class
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ *
+ * All voltages, currents, charges, energies and temperatures in mV, mA,
+ * mAh, mWh and tenths of a Celsius degree unless otherwise stated. It's
+ * driver's job to convert its raw values to which this class operates. If
+ * for some reason driver can't afford this requirement, then it have to
+ * create its own attributes, plus additional "XYZ_units" for each of them.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#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
+
+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)
+{
+	void *value;
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	value = bat->get_property(bat, BATTERY_PROP_STATUS);
+	if (!value)
+		return;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+	switch(*(int *)value) {
+	case BATTERY_STATUS_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_trig, LED_FULL);
+		led_trigger_event(bat->full_trig, LED_OFF);
+		break;
+	default:
+		led_trigger_event(bat->charging_trig, LED_OFF);
+		led_trigger_event(bat->full_trig, LED_OFF);
+		break;
+	}
+#endif /* CONFIG_LEDS_TRIGGERS */
+	return;
+}
+
+/*
+ * 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"
+	};
+	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
+		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(min_voltage),
+	BATTERY_ATTR(max_voltage),
+	BATTERY_ATTR(voltage),
+	BATTERY_ATTR(min_current),
+	BATTERY_ATTR(max_current),
+	BATTERY_ATTR(current),
+	BATTERY_ATTR(design_charge),
+	BATTERY_ATTR(min_charge),
+	BATTERY_ATTR(max_charge),
+	BATTERY_ATTR(charge),
+	BATTERY_ATTR(design_energy),
+	BATTERY_ATTR(min_energy),
+	BATTERY_ATTR(max_energy),
+	BATTERY_ATTR(energy),
+	BATTERY_ATTR(temp),
+};
+
+static 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;
+}
+
+static 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;
+}
+
+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_bat_attrs_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;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+	bat->charging_trig_name = kmalloc(strlen(bat->name) +
+	                                  sizeof("-charging"), GFP_KERNEL);
+	if (!bat->charging_trig_name) {
+		rc = -ENOMEM;
+		goto charging_trig_name_failed;
+	}
+
+	bat->full_trig_name = kmalloc(strlen(bat->name) +
+	                              sizeof("-full"), GFP_KERNEL);
+	if (!bat->full_trig_name) {
+		rc = -ENOMEM;
+		goto full_trig_name_failed;
+	}
+
+	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_charging(bat->charging_trig_name,
+	                              &bat->charging_trig);
+	led_trigger_register_simple(bat->full_trig_name,
+	                            &bat->full_trig);
+#endif /* CONFIG_LEDS_TRIGGERS */
+
+	goto success;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+full_trig_name_failed:
+	kfree(bat->charging_trig_name);
+charging_trig_name_failed:
+#endif
+	power_supplicant_unregister(&bat->pst);
+power_supplicant_failed:
+	battery_remove_attrs(bat);
+create_bat_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_attrs(bat);
+	device_unregister(bat->dev);
+
+#ifdef CONFIG_LEDS_TRIGGERS
+	led_trigger_unregister_charging(bat->charging_trig);
+	led_trigger_unregister_simple(bat->full_trig);
+	kfree(bat->full_trig_name);
+	kfree(bat->charging_trig_name);
+#endif
+	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@f2s.com>, "
+              "Szabolcs Gyurko, "
+              "Anton Vorontsov <cbou@mail.ru>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/battery.h b/include/linux/battery.h
new file mode 100644
index 0000000..2dcc8ed
--- /dev/null
+++ b/include/linux/battery.h
@@ -0,0 +1,113 @@
+/*
+ *  Universal battery monitor class
+ *
+ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright (c) 2004  Szabolcs Gyurko
+ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ *
+ * All voltages, currents, charges, energies and temperatures in mV, mA,
+ * mAh, mWh and tenths of a Celsius degree unless otherwise stated. It's
+ * driver's job to convert its raw values to which this class operates. If
+ * for some reason driver can't afford this requirement, then it have to
+ * create its own attributes, plus additional "XYZ_units" for each of them.
+ */
+
+#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
+
+/*
+ * 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 can be NULL and will not appear in sysfs.
+ */
+
+enum battery_property {
+	BATTERY_PROP_STATUS = 0,
+	BATTERY_PROP_MIN_VOLTAGE,
+	BATTERY_PROP_MAX_VOLTAGE,
+	BATTERY_PROP_VOLTAGE,
+	BATTERY_PROP_MIN_CURRENT,
+	BATTERY_PROP_MAX_CURRENT,
+	BATTERY_PROP_CURRENT,
+	BATTERY_PROP_DESIGN_CHARGE,
+	BATTERY_PROP_MIN_CHARGE,
+	BATTERY_PROP_MAX_CHARGE,
+	BATTERY_PROP_CHARGE,
+	BATTERY_PROP_DESIGN_ENERGY,
+	BATTERY_PROP_MIN_ENERGY,
+	BATTERY_PROP_MAX_ENERGY,
+	BATTERY_PROP_ENERGY,
+	BATTERY_PROP_TEMP,
+};
+
+struct battery {
+	struct device *dev;
+	char *name;
+	int *properties;
+	int 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 power_supplicant pst;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+	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 device
+ * itself does bot use it, but that's what implementing most drivers,
+ * should try reuse for consistency.
+ */
+
+struct battery_info {
+	char *name;
+	int min_voltage;
+	int max_voltage;
+	int min_current;
+	int max_current;
+	int design_charge;
+	int min_charge;
+	int max_charge;
+	int design_energy;
+	int min_energy;
+	int max_energy;
+	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
-- 
1.5.0.5-dirty


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-13  2:36                 ` Anton Vorontsov
@ 2007-04-13 13:51                   ` Henrique de Moraes Holschuh
  0 siblings, 0 replies; 34+ messages in thread
From: Henrique de Moraes Holschuh @ 2007-04-13 13:51 UTC (permalink / raw)
  To: linux-kernel

On Fri, 13 Apr 2007, Anton Vorontsov wrote:
> > With fixed-units files, having *_energy and *_capacity isn't too clear
> > either... Nor is it consistent with SBS, since SBS uses "capacity" to
> > refer to either energy or charge, depending on a units attribute.
> > 
> > As a compromise, how about using "energy" and "charge" for quantities,
> > and "charging" (i.e., a verb) when referring to the operation?
> 
> It would be great compromise! Please please please!

I can live with it, although I'd rather just use the units (zero margin of
error or confusion).

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-13 13:49 ` Anton Vorontsov
@ 2007-04-15  0:43   ` Anton Vorontsov
  2007-05-04  9:59     ` Pavel Machek
  0 siblings, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-15  0:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: kernel-discuss, dwmw2, Greg KH, Randy Dunlap, Shem Multinymous,
	Henrique de Moraes Holschuh, Matthew Garrett

On Fri, Apr 13, 2007 at 05:49:39PM +0400, Anton Vorontsov wrote:
> I'll convert mXh to uXh a bit later, if there will no further objections
> against uXh. Also I'd like to hear if there any objections on
> mA/mV -> uA/uV conversion. I think we'd better keep all units at the
> same order/precision.

Okay, would it make sense to use "long" instead of "int" after "milli" to
"micro" conversion? On 32 bit machines int gives +-2147483648 limit. So
2147 volts/amperes/...

Though 2147 amperes is unrealistic for batteries, but if used in
calculations it could be dangerous.

For example:
di->life_sec = -((di->accum_current_uAh - di->empty_uAh) *
                 3600) / di->current_uA;

It can be also solved (and I voting for it) by typecasting to long
in the driver itself.

Would it also make sense to use int64_t instead of long? And how should
it passed to printk in portable way? I guess printk (vsprintf) does not
support PRIx notation as defined in /usr/include/inttypes.h ?

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-11 23:25 [PATCH 3/7] [RFC] Battery monitoring class Anton Vorontsov
                   ` (4 preceding siblings ...)
  2007-04-13 13:49 ` Anton Vorontsov
@ 2007-04-15 19:56 ` Pavel Machek
  2007-04-15 22:10   ` [Kernel-discuss] " Anton Vorontsov
  2007-04-15 22:08 ` Ondrej Zajicek
  6 siblings, 1 reply; 34+ messages in thread
From: Pavel Machek @ 2007-04-15 19:56 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linux-kernel, kernel-discuss, dwmw2

Hi!

> * It insists on reusing its predefined attributes *and* their units.
>   So, userspace getting expected values for any battery.
>   
>   Also common units is required for APM/ACPI emulation.
>   
>   Though our battery class insisting on re-usage, but not forces it. If some
>   battery driver can't convert its own raw values (can't imagine why), then
>   driver is free to implement its own attributes *and* additional _units
>   attribute. Though, this scheme is discouraged.
> 
> * LEDs support. Each battery register its trigger, and gadgets with LEDs
>   can quickly bind to battery-charging / battery-full triggers.
> 
> Here how it looks like from user space:
> 
> # ls /sys/class/battery/main-battery/
> capacity  max_capacity  max_voltage   min_current  power   subsystem  uevent
> current   max_current   min_capacity  min_voltage  status  temp       voltage
> # cat /sys/class/battery/main-battery/status
> Full
> # cat /sys/class/leds/h5400\:green-right/trigger
> none h5400-radio timer hwtimer main-battery-charging [main-battery-full]
> # cat /sys/class/leds/h5400\:green-right/brightness
> 255

Can we get few lines in Documentation? I guess min_capacity is
shutdown capacity at current temperature, but its surely non-obvious.

Will min_capacity increase as batery gets old? Or will max_capacity
decrease? (Should we introduce design_capacity for ACPI systems that
know the difference?)

What is min_current? Granularity of amper meter?

And min_voltage is shutdown voltage?

Otherwise it looks good to me. Something like this is really needed.

> + * All voltages, currents, capacities and temperatures in mV, mA, mAh and
> + * tenths of a degree unless otherwise stated. It's driver's job to convert

tenths of degree Celsius?

							Pavel

> +#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

Perhaps we need STATUS_ERROR? At least on some machines it is
different from STATUS_NOT_CHARGING.

> +	/* private */
> +	struct power_supplicant pst;
> +
> +	#ifdef CONFIG_LEDS_TRIGGERS
> +	struct led_trigger *charging_trig;
> +	char *charging_trig_name;
> +	struct led_trigger *full_trig;
> +	char *full_trig_name;
> +	#endif
> +};

#ifdefs need to be at column 0?

> +/* 
> + * This is recommended structure to specify static battery parameters.
> + * Generic one, parametrizable for different batteries. Battery device
> + * itself does bot use it, but that's what implementing most drivers,

'does not'?

							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-11 23:25 [PATCH 3/7] [RFC] Battery monitoring class Anton Vorontsov
                   ` (5 preceding siblings ...)
  2007-04-15 19:56 ` Pavel Machek
@ 2007-04-15 22:08 ` Ondrej Zajicek
  2007-04-15 22:50   ` Anton Vorontsov
  6 siblings, 1 reply; 34+ messages in thread
From: Ondrej Zajicek @ 2007-04-15 22:08 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linux-kernel, kernel-discuss, dwmw2

On Thu, Apr 12, 2007 at 03:25:03AM +0400, Anton Vorontsov wrote:
> Here is battery monitor class. According to first copyright string, we're
> maintaining it since 2003. I've took few days and cleaned it up to be
> more suitable for mainline inclusion.

Just some ideas:

- what about using exponents in values?
For example file "voltage" could contain "123 -3" to represent 123 mV.
Exponents could be hardcoded in drivers according to device's range
(so there is no complication in it), but interface is usable in great
range of values. And it is pretty easy to use from userspace.

- interface should allow to present values which are some monotonic
functions of common physical properties. For example when we know
where are some raw data from sensor, but we don't know where are
calibration tables to be able to compute value in some standard unit
(as V for voltage) - in this case it is better to show raw data 
(or raw data after some transformation which makes them monotonic)
and specify that this is raw data than show nothing. 

- it would be nice to know whether presented value is from some
measurement or it is (inaccurate) estimation.

-- 
Elen sila lumenn' omentielvo

Ondrej 'SanTiago' Zajicek (email: santiago@mail.cz, jabber: santiago@njs.netlab.cz)
OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net)
"To err is human -- to blame it on a computer is even more so."

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-15 19:56 ` Pavel Machek
@ 2007-04-15 22:10   ` Anton Vorontsov
  0 siblings, 0 replies; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-15 22:10 UTC (permalink / raw)
  To: Pavel Machek; +Cc: dwmw2, linux-kernel, kernel-discuss

Hello Pavel,

On Sun, Apr 15, 2007 at 07:56:56PM +0000, Pavel Machek wrote:
> Hi!
> 
> > * It insists on reusing its predefined attributes *and* their units.
> >   So, userspace getting expected values for any battery.
> >   
> >   Also common units is required for APM/ACPI emulation.
> >   
> >   Though our battery class insisting on re-usage, but not forces it. If some
> >   battery driver can't convert its own raw values (can't imagine why), then
> >   driver is free to implement its own attributes *and* additional _units
> >   attribute. Though, this scheme is discouraged.
> > 
> > * LEDs support. Each battery register its trigger, and gadgets with LEDs
> >   can quickly bind to battery-charging / battery-full triggers.
> > 
> > Here how it looks like from user space:
> > 
> > # ls /sys/class/battery/main-battery/
> > capacity  max_capacity  max_voltage   min_current  power   subsystem  uevent
> > current   max_current   min_capacity  min_voltage  status  temp       voltage
> > # cat /sys/class/battery/main-battery/status
> > Full
> > # cat /sys/class/leds/h5400\:green-right/trigger
> > none h5400-radio timer hwtimer main-battery-charging [main-battery-full]
> > # cat /sys/class/leds/h5400\:green-right/brightness
> > 255
> 
> Can we get few lines in Documentation?

Yes, sure.

> I guess min_capacity is
> shutdown capacity at current temperature, but its surely non-obvious.
> 
> Will min_capacity increase as batery gets old? Or will max_capacity
> decrease? 

min_capacity and max_capacity depend on temperature. But some drivers
can/want to interpolate, others can't/don't want. It's driver's matter.

ds2760_battery just remembers last capacity when current was < 10 mA
(i.e. battery charged full at given temperature) as max_capacity, and
takes this as reference for calculations.

> (Should we introduce design_capacity for ACPI systems that
> know the difference?)

Yup, I've introduced it in [take2] (it's in this thread, thus it's hard
to find). Will resend it as separate thread soon, along with few other
changes.

> What is min_current? Granularity of amper meter?
> 
> And min_voltage is shutdown voltage?

Yes, should be. But, for example, ds2760 battery can't remember this
value in its eeprom (iirc), thus this value passed by platform code,
i.e. in our case (iPaqs) it's machine dependent value. Probably we
should not even export this attribute in ds2760_battery driver, as it
does not take any part in calculations. Plus this attribute highly
depend on battery chemistry and temperature. Thus it's hardly anyhow
useful, except if hardware itself reports it (not ds2760 case).

> Otherwise it looks good to me. Something like this is really needed.

Thanks!

> > + * All voltages, currents, capacities and temperatures in mV, mA, mAh and
> > + * tenths of a degree unless otherwise stated. It's driver's job to convert
> 
> tenths of degree Celsius?

Yup, fixed in [take2].

> > +#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
> 
> Perhaps we need STATUS_ERROR? At least on some machines it is
> different from STATUS_NOT_CHARGING.

I'm unsure about this. BATTERY_STATUS_* is mostly about charging process
status (should I rename it to more verbose BATTERY_CHARGING_STATUS_, or just
mention it in Documentation?).

For errors things it might be better to create "health" attribute.

> > +	/* private */
> > +	struct power_supplicant pst;
> > +
> > +	#ifdef CONFIG_LEDS_TRIGGERS
> > +	struct led_trigger *charging_trig;
> > +	char *charging_trig_name;
> > +	struct led_trigger *full_trig;
> > +	char *full_trig_name;
> > +	#endif
> > +};
> 
> #ifdefs need to be at column 0?

Yup, fixed in [take2].

> > +/* 
> > + * This is recommended structure to specify static battery parameters.
> > + * Generic one, parametrizable for different batteries. Battery device
> > + * itself does bot use it, but that's what implementing most drivers,
> 
> 'does not'?

Thanks, will fix!

> 							Pavel
> -- 
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Thanks,

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-15 22:08 ` Ondrej Zajicek
@ 2007-04-15 22:50   ` Anton Vorontsov
  2007-04-16  0:57     ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-15 22:50 UTC (permalink / raw)
  To: Ondrej Zajicek; +Cc: linux-kernel, kernel-discuss, dwmw2

Hi,

On Mon, Apr 16, 2007 at 12:08:54AM +0200, Ondrej Zajicek wrote:
> On Thu, Apr 12, 2007 at 03:25:03AM +0400, Anton Vorontsov wrote:
> > Here is battery monitor class. According to first copyright string, we're
> > maintaining it since 2003. I've took few days and cleaned it up to be
> > more suitable for mainline inclusion.
> 
> Just some ideas:
> 
> - what about using exponents in values?
> For example file "voltage" could contain "123 -3" to represent 123 mV.
> Exponents could be hardcoded in drivers according to device's range
> (so there is no complication in it), but interface is usable in great
> range of values. And it is pretty easy to use from userspace.

No, sorry. Common units is main goal of that class. If you're saying
"energy" you always know that it's uWh. It's better for both userspace
(don't bother to parse anything from kernel) and kernel itself.

No need to invent new kernel<->userspace protocols, no need to do
useless string manipulations in kernel itself.

> - interface should allow to present values which are some monotonic
> functions of common physical properties. For example when we know
> where are some raw data from sensor, but we don't know where are
> calibration tables to be able to compute value in some standard unit
> (as V for voltage) - in this case it is better to show raw data 
> (or raw data after some transformation which makes them monotonic)
> and specify that this is raw data than show nothing. 
> 
> - it would be nice to know whether presented value is from some
> measurement or it is (inaccurate) estimation.

Current battery class assumes values are not averaged. I.e. momentary
values. In general, it's userspace' job to collect statistics. Though,
if hardware can report only average values, it's just okay to use
usual attributes.

Also, if you your battery can collect and report its approximated values
in additional to momentary values, you're free to add _AVG attributes
to standard ones and use them.

> -- 
> Elen sila lumenn' omentielvo
> 
> Ondrej 'SanTiago' Zajicek (email: santiago@mail.cz, jabber: santiago@njs.netlab.cz)
> OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net)
> "To err is human -- to blame it on a computer is even more so."

Thanks for comments!

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-15 22:50   ` Anton Vorontsov
@ 2007-04-16  0:57     ` Henrique de Moraes Holschuh
  2007-04-16  1:57       ` Anton Vorontsov
  2007-04-16  2:32       ` [Kernel-discuss] " ian
  0 siblings, 2 replies; 34+ messages in thread
From: Henrique de Moraes Holschuh @ 2007-04-16  0:57 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: Ondrej Zajicek, linux-kernel, kernel-discuss, dwmw2

On Mon, 16 Apr 2007, Anton Vorontsov wrote:
> Current battery class assumes values are not averaged. I.e. momentary
> values. In general, it's userspace' job to collect statistics. Though,
> if hardware can report only average values, it's just okay to use
> usual attributes.

What about SBS-style battery firmware, which can report *both* ?  This
includes just about all ThinkPads in the last five years, so we are talking
about a damn big lot of machines...

I'd really appreciate if there is a standard way to communicate both.  And
it is probably a good idea to define what should be averaged, and what
should be instantaneous when that matters, that way userspace actually has a
chance at not doing something braindamaged.

Actually, IMHO, every attribute and alarm from SBS should be somehow
losslessly translatable to standard class attributes from day one, unless it
is something that makes no sense at all (and there is precious little of
that in the latest version of SBS, thankfully...).

> Also, if you your battery can collect and report its approximated values
> in additional to momentary values, you're free to add _AVG attributes
> to standard ones and use them.

No, that won't help much.  IMO, we want the sanest set of standard
attributes we can get, and weird as it might be, average reporting are
common properties of battery control firmware on laptops (maybe because of
SBS, but still...).

We don't have to get it perfect at the first try, but I really think we are
getting a bit too far from "as good as we can make it" at the first attempt
if we don't take the SBS into account properly, given the ammount of
circuits and firmware out there that are shaped along the SBS guidelines.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-16  0:57     ` Henrique de Moraes Holschuh
@ 2007-04-16  1:57       ` Anton Vorontsov
  2007-04-16 14:34         ` Henrique de Moraes Holschuh
  2007-04-16  2:32       ` [Kernel-discuss] " ian
  1 sibling, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-16  1:57 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh
  Cc: Ondrej Zajicek, linux-kernel, kernel-discuss, dwmw2

On Sun, Apr 15, 2007 at 09:57:22PM -0300, Henrique de Moraes Holschuh wrote:
> On Mon, 16 Apr 2007, Anton Vorontsov wrote:
> > Current battery class assumes values are not averaged. I.e. momentary
> > values. In general, it's userspace' job to collect statistics. Though,
> > if hardware can report only average values, it's just okay to use
> > usual attributes.
> 
> What about SBS-style battery firmware, which can report *both* ?  This
> includes just about all ThinkPads in the last five years, so we are talking
> about a damn big lot of machines...

Sure, no problem. I'm taking away my words "if hardware can report
only average values, it's just okay to use usual attributes", and replacing
them by "if hardware can report only average values, it should use _AVG
attributes".

So, this scheme should work now:

1. If userspace (nice GUI app) seeing _avg values, it will use these.
2. If userspace seeing no _avg values, it is using its own statistics
   mechanism, i.e. collecting information from momentary attributes.
3. If userspace seeing both, it can decide, most probably it will decide
   to use hardware averaged values, i.e. _avg.

> I'd really appreciate if there is a standard way to communicate both.  And
> it is probably a good idea to define what should be averaged, and what
> should be instantaneous when that matters, that way userspace actually has a
> chance at not doing something braindamaged.
> 
> Actually, IMHO, every attribute and alarm from SBS should be somehow
> losslessly translatable to standard class attributes from day one, unless it
> is something that makes no sense at all (and there is precious little of
> that in the latest version of SBS, thankfully...).
> 
> > Also, if you your battery can collect and report its approximated values
> > in additional to momentary values, you're free to add _AVG attributes
> > to standard ones and use them.
> 
> No, that won't help much.  IMO, we want the sanest set of standard
> attributes we can get, and weird as it might be, average reporting are
> common properties of battery control firmware on laptops (maybe because of
> SBS, but still...).

Why that won't help? Is there something else besides momentary and
hardware-averaged values?

> We don't have to get it perfect at the first try, but I really think we are
> getting a bit too far from "as good as we can make it" at the first attempt
> if we don't take the SBS into account properly, given the ammount of
> circuits and firmware out there that are shaped along the SBS guidelines.

I guess the only question for you is whether we would use, "attr" as momentary
and "attr_avg" as averaged by hardware value, or will use "attr" as averaged
values, and something alike "attr_now" for momentary? And you voting for
"attr" being averaged and "attr_now" momentary.

Actually, I don't see much difference, except default assumption of "attr"
being averaged/momentary.

Though, if it's real issue for you or SBS conformity, I can surely rename
attrs.

> -- 
>   "One disk to rule them all, One disk to find them. One disk to bring
>   them all and in the darkness grind them. In the Land of Redmond
>   where the shadows lie." -- The Silicon Valley Tarot
>   Henrique Holschuh
> 

And again, much thanks for your comments! They're really helpful.

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-16  0:57     ` Henrique de Moraes Holschuh
  2007-04-16  1:57       ` Anton Vorontsov
@ 2007-04-16  2:32       ` ian
  2007-04-16  3:12         ` Anton Vorontsov
  1 sibling, 1 reply; 34+ messages in thread
From: ian @ 2007-04-16  2:32 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh
  Cc: Anton Vorontsov, Ondrej Zajicek, dwmw2, linux-kernel,
	kernel-discuss

On Sun, 2007-04-15 at 21:57 -0300, Henrique de Moraes Holschuh wrote:
> 
> No, that won't help much.  IMO, we want the sanest set of standard
> attributes we can get, and weird as it might be, average reporting are
> common properties of battery control firmware on laptops (maybe
> because of SBS, but still...).

We need to think very carefully here.

charge, current, capacity, etc. are properties all batteries have, and
the current values can all be sampled instantaneously.

funky values processed by 'black box' firmware are not universal
properties of all batteries.

IOW, battery class should be for 'simple' battery types only.

perhaps rename it to simple battery class to make it distinct?

Userspace is the place to put the complications, in any case, and I see
nothing wrong with having both a simple battery class AND other
proprietary battery class an SBS battery class. (or a
toshiba_proprietary_bios battery class or whatever).

Perhaps we need a 'libbattery.so' so that userspace can have a nice
consistent interface?


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-16  2:32       ` [Kernel-discuss] " ian
@ 2007-04-16  3:12         ` Anton Vorontsov
  2007-04-16  8:28           ` ian
  0 siblings, 1 reply; 34+ messages in thread
From: Anton Vorontsov @ 2007-04-16  3:12 UTC (permalink / raw)
  To: ian
  Cc: Henrique de Moraes Holschuh, Ondrej Zajicek, dwmw2, linux-kernel,
	kernel-discuss

On Mon, Apr 16, 2007 at 03:32:54AM +0100, ian wrote:
> On Sun, 2007-04-15 at 21:57 -0300, Henrique de Moraes Holschuh wrote:
> > 
> > No, that won't help much.  IMO, we want the sanest set of standard
> > attributes we can get, and weird as it might be, average reporting are
> > common properties of battery control firmware on laptops (maybe
> > because of SBS, but still...).
> 
> We need to think very carefully here.
> 
> charge, current, capacity, etc. are properties all batteries have, and
> the current values can all be sampled instantaneously.
> 
> funky values processed by 'black box' firmware are not universal
> properties of all batteries.
> 
> IOW, battery class should be for 'simple' battery types only.
> 
> perhaps rename it to simple battery class to make it distinct?
> 
> Userspace is the place to put the complications, in any case, and I see
> nothing wrong with having both a simple battery class AND other
> proprietary battery class an SBS battery class. (or a
> toshiba_proprietary_bios battery class or whatever).
> 
> Perhaps we need a 'libbattery.so' so that userspace can have a nice
> consistent interface?

Why? With current battery class we can do whatever everyone needs. No
need for wrappers.

Adding new properties is cheap and easy. Simple batteries using only
"simple" properties/attributes, and complicated batteries using
complicated attributes.

Because of your original design, simple batteries are stay simple, and
no noticing that there is some "complicated" attributes exists at all.
That's indeed great characteristic of that *universal* battery class.

For example, ds2760 is not really "simple" monitoring chip. ADC battery
is (it's in -hh tree so far). So, ds2760 is somewhere in between SBS
design, and dumb ADC batteries.

So, my another purposal, which I very like now:
Let's do self-documented properties. current_now, current_avg, e.t.c.
No more just "current", lets remove any ambiguousness!

-- 
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.org/bd2

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-16  3:12         ` Anton Vorontsov
@ 2007-04-16  8:28           ` ian
  0 siblings, 0 replies; 34+ messages in thread
From: ian @ 2007-04-16  8:28 UTC (permalink / raw)
  To: cbou
  Cc: Henrique de Moraes Holschuh, Ondrej Zajicek, dwmw2, linux-kernel,
	kernel-discuss

On Mon, 2007-04-16 at 07:12 +0400, Anton Vorontsov wrote:

> Why? With current battery class we can do whatever everyone needs. No
> need for wrappers.

<cut>

> Because of your original design, simple batteries are stay simple, and
> no noticing that there is some "complicated" attributes exists at all.
> That's indeed great characteristic of that *universal* battery class.

Indeed. Im just trying to make sure we dont bloat an otherwise very
simple class. A word of caution only.


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-16  1:57       ` Anton Vorontsov
@ 2007-04-16 14:34         ` Henrique de Moraes Holschuh
  0 siblings, 0 replies; 34+ messages in thread
From: Henrique de Moraes Holschuh @ 2007-04-16 14:34 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: Ondrej Zajicek, linux-kernel, kernel-discuss, dwmw2

> > > Also, if you your battery can collect and report its approximated values
> > > in additional to momentary values, you're free to add _AVG attributes
> > > to standard ones and use them.
> > 
> > No, that won't help much.  IMO, we want the sanest set of standard
> > attributes we can get, and weird as it might be, average reporting are
> > common properties of battery control firmware on laptops (maybe because of
> > SBS, but still...).
> 
> Why that won't help? Is there something else besides momentary and
> hardware-averaged values?

It wouldn't help much to not have standard generic attributes for the
averaged measurements.

That said, yes, there are relative measurements (percent), and time
measurements (some battery firmware can tell you how much *time* it will
take to stop recharing, empty the battery, etc).

> I guess the only question for you is whether we would use, "attr" as momentary
> and "attr_avg" as averaged by hardware value, or will use "attr" as averaged
> values, and something alike "attr_now" for momentary? And you voting for
> "attr" being averaged and "attr_now" momentary.

I don't care either way, as long as it is *documented* what is averaged, and
what is instantaneous.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Kernel-discuss] Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-13  2:15               ` Anton Vorontsov
@ 2007-04-24 19:36                 ` Pavel Machek
  0 siblings, 0 replies; 34+ messages in thread
From: Pavel Machek @ 2007-04-24 19:36 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Henrique de Moraes Holschuh, Matthew Garrett, kernel-discuss,
	linux-kernel, dwmw2, Shem Multinymous

Hi!

> > > > That said, you may need to use uWh and uAh instead of mAh and mWh, though.
> > > 
> > > Not sure. Is there any existing chip that can report uAh/uWh? That is
> > > great precision.
> > 
> > The way things are going, it should be feasible for small embedded systems
> > quite soon.  Refer to the previous thread.
> 
> I see... is it also applicable to currents and voltages? I.e. should we
> use uA and uV from the start?

AFAICT, mobile phone in standby can eat less than 1000 uW... so uA/uV
would indeed be nice.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 3/7] [RFC] Battery monitoring class
  2007-04-15  0:43   ` Anton Vorontsov
@ 2007-05-04  9:59     ` Pavel Machek
  0 siblings, 0 replies; 34+ messages in thread
From: Pavel Machek @ 2007-05-04  9:59 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: linux-kernel, kernel-discuss, dwmw2, Greg KH, Randy Dunlap,
	Shem Multinymous, Henrique de Moraes Holschuh, Matthew Garrett

Hi!

> > I'll convert mXh to uXh a bit later, if there will no further objections
> > against uXh. Also I'd like to hear if there any objections on
> > mA/mV -> uA/uV conversion. I think we'd better keep all units at the
> > same order/precision.
> 
> Okay, would it make sense to use "long" instead of "int" after "milli" to
> "micro" conversion? On 32 bit machines int gives +-2147483648 limit. So
> 2147 volts/amperes/...

long == int on 32bit machines.

> Though 2147 amperes is unrealistic for batteries, but if used in
> calculations it could be dangerous.

Let the one doing calculations handle that ;-).
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2007-05-04 10:00 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-11 23:25 [PATCH 3/7] [RFC] Battery monitoring class Anton Vorontsov
2007-04-12  2:53 ` Randy Dunlap
2007-04-12 16:51   ` Anton Vorontsov
2007-04-12  3:43 ` Greg KH
2007-04-12 12:25   ` Henrique de Moraes Holschuh
2007-04-12 13:43   ` Anton Vorontsov
2007-04-12 13:08 ` Matthew Garrett
2007-04-12 14:15   ` Anton Vorontsov
2007-04-12 14:24     ` Matthew Garrett
2007-04-12 14:36       ` [Kernel-discuss] " Paul Sokolovsky
2007-04-12 18:56         ` Henrique de Moraes Holschuh
2007-04-12 20:44           ` Anton Vorontsov
2007-04-13  0:51             ` Henrique de Moraes Holschuh
2007-04-13  2:15               ` Anton Vorontsov
2007-04-24 19:36                 ` Pavel Machek
2007-04-13  2:34               ` Shem Multinymous
2007-04-13  2:36                 ` Anton Vorontsov
2007-04-13 13:51                   ` Henrique de Moraes Holschuh
2007-04-12 15:00 ` Shem Multinymous
2007-04-12 15:18   ` Anton Vorontsov
2007-04-12 17:23     ` Shem Multinymous
2007-04-13 13:49 ` Anton Vorontsov
2007-04-15  0:43   ` Anton Vorontsov
2007-05-04  9:59     ` Pavel Machek
2007-04-15 19:56 ` Pavel Machek
2007-04-15 22:10   ` [Kernel-discuss] " Anton Vorontsov
2007-04-15 22:08 ` Ondrej Zajicek
2007-04-15 22:50   ` Anton Vorontsov
2007-04-16  0:57     ` Henrique de Moraes Holschuh
2007-04-16  1:57       ` Anton Vorontsov
2007-04-16 14:34         ` Henrique de Moraes Holschuh
2007-04-16  2:32       ` [Kernel-discuss] " ian
2007-04-16  3:12         ` Anton Vorontsov
2007-04-16  8:28           ` ian

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox