--- /dev/null
+commit a1c28f69847480cc54f36046e96e93a02a2c661d
+Author: John Mathew <johnx.mathew@intel.com>
+Date: Thu Jun 30 09:58:26 2011 +0300
+
+ measurement: add support for universal power supply monitor
+
+ This patch enables powertop to display power estimates on devices that
+ implement power_supply class and donot have acpi battery interface.
+
+ First the acpi/battery interface is checked and if it is not accesible
+ the sysfs/power_class interface is used
+
+diff --git a/Makefile b/Makefile
+index b0b6cb7..f0ebf21 100644
+--- a/Makefile
++++ b/Makefile
+@@ -13,7 +13,7 @@ OBJS += perf/perf.o perf/perf_bundle.o
+ OBJS += process/process.o process/do_process.o process/interrupt.o process/timer.o process/work.o process/powerconsumer.o process/device.o
+ DEVS += devices/device.o devices/backlight.o devices/usb.o devices/ahci.o devices/alsa.o devices/rfkill.o devices/i915-gpu.o devices/thinkpad-fan.o devices/network.o devices/thinkpad-light.o
+ DEVS += devices/runtime_pm.o
+-DEVS += measurement/measurement.o measurement/acpi.o measurement/extech.o
++DEVS += measurement/measurement.o measurement/acpi.o measurement/extech.o measurement/power_supply.o
+ OBJS += $(DEVS)
+ OBJS += parameters/parameters.o parameters/learn.o parameters/persistent.o
+ OBJS += calibrate/calibrate.o
+diff --git a/measurement/measurement.cpp b/measurement/measurement.cpp
+index 3dbaab9..0d679f7 100644
+--- a/measurement/measurement.cpp
++++ b/measurement/measurement.cpp
+@@ -25,11 +25,15 @@
+ #include "measurement.h"
+ #include "acpi.h"
+ #include "extech.h"
++#include "power_supply.h"
+ #include "../parameters/parameters.h"
+ #include "../lib.h"
+
+ #include <sys/types.h>
+ #include <dirent.h>
++#include <unistd.h>
++#include <stdio.h>
++#include <fstream>
+
+ double min_power = 50000.0;
+
+@@ -111,16 +114,45 @@ void power_meters_callback(const char *d_name)
+ power_meters.push_back(meter);
+ }
+
++void power_supply_callback(const char *d_name)
++{
++ char filename[4096];
++ char line[4096];
++ ifstream file;
++ bool discharging = false;
++
++ sprintf(filename, "/sys/class/power_supply/%s/uevent", d_name);
++ file.open(filename, ios::in);
++ if (!file)
++ return;
++
++ while (file) {
++ file.getline(line, 4096);
++
++ if (strstr(line, "POWER_SUPPLY_STATUS") && strstr(line, "POWER_SUPPLY_STATUS"))
++ discharging = true;
++ }
++ file.close();
++
++ if (!discharging)
++ return;
++
++ class power_supply *power;
++ power = new(std::nothrow) class power_supply(d_name);
++ if (power)
++ power_meters.push_back(power);
++}
++
+ void detect_power_meters(void)
+ {
+- process_directory("/proc/acpi/battery", power_meters_callback);
++ if (access("/sys/class/power_supply", R_OK ) == 0)
++ process_directory("/sys/class/power_supply", power_supply_callback);
++ else if (access("/proc/acpi/battery", R_OK ) == 0)
++ process_directory("/proc/acpi/battery", power_meters_callback);
+ }
+
+ void extech_power_meter(const char *devnode)
+ {
+- DIR *dir;
+- struct dirent *entry;
+-
+ class extech_power_meter *meter;
+
+ meter = new class extech_power_meter(devnode);
+diff --git a/measurement/power_supply.cpp b/measurement/power_supply.cpp
+new file mode 100755
+index 0000000..b4fe3af
+--- /dev/null
++++ b/measurement/power_supply.cpp
+@@ -0,0 +1,184 @@
++/*
++ * Copyright 2011, Intel Corporation
++ *
++ * This file is part of PowerTOP
++ *
++ * This program file is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program in a file named COPYING; if not, write to the
++ * Free Software Foundation, Inc,
++ * 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301 USA
++ * or just google for it.
++ *
++ * Authors:
++ * John Mathew <johnx.mathew@intel.com>
++ */
++#include "measurement.h"
++#include "power_supply.h"
++#include <iostream>
++#include <fstream>
++#include <string.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++using namespace std;
++
++power_supply::power_supply(const char *supply_name)
++{
++ rate = 0.0;
++ capacity = 0.0;
++ voltage = 0.0;
++ strncpy(battery_name, supply_name, sizeof(battery_name));
++}
++
++/*
++POWER_SUPPLY_NAME=msic-battery
++POWER_SUPPLY_STATUS=Discharging
++POWER_SUPPLY_HEALTH=Cold
++POWER_SUPPLY_PRESENT=1
++POWER_SUPPLY_TECHNOLOGY=Li-ion
++POWER_SUPPLY_VOLTAGE_MAX_DESIGN=4200000
++POWER_SUPPLY_VOLTAGE_NOW=4119000
++POWER_SUPPLY_CURRENT_NOW=-290000
++POWER_SUPPLY_CHARGE_NOW=1503000
++POWER_SUPPLY_CHARGE_COUNTER=-254923
++POWER_SUPPLY_CHARGE_FULL_DESIGN=1500000
++POWER_SUPPLY_CHARGE_FULL=1500000
++POWER_SUPPLY_CHARGE_AVG=32762000
++POWER_SUPPLY_ENERGY_FULL=6300000
++POWER_SUPPLY_ENERGY_NOW=6235000
++POWER_SUPPLY_CAPACITY_LEVEL=Full
++POWER_SUPPLY_CAPACITY=100
++POWER_SUPPLY_TEMP=-340
++POWER_SUPPLY_MODEL_NAME=CDK0
++POWER_SUPPLY_MANUFACTURER=IN
++
++Quoting include/linux/power_supply.h:
++
++All voltages, currents, charges, energies, time and temperatures in µV,
++µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
++stated. It's driver's job to convert its raw values to units in which
++this class operates.
++*/
++
++void power_supply::measure(void)
++{
++ char filename[4096];
++ char line[4096];
++ ifstream file;
++
++ double _rate = 0;
++ double _capacity = 0;
++ double _voltage = 0;
++
++ char rate_units[16];
++ char capacity_units[16];
++ char voltage_units[16];
++
++ rate_units[0] = 0;
++ capacity_units[0] = 0;
++ voltage_units[0] = 0;
++
++ rate = 0;
++ voltage = 0;
++ capacity = 0;
++
++ sprintf(filename, "/sys/class/power_supply/%s/uevent", battery_name);
++
++ file.open(filename, ios::in);
++ if (!file)
++ return;
++
++ while (file) {
++ char *c;
++ file.getline(line, 4096);
++
++ if (strstr(line, "PRESENT")) {
++ c = strchr(line, '=');
++ c++;
++ if(*c == '0'){
++ printf ("Battery not present");
++ return;
++ }
++ }
++ if (strstr(line, "CURRENT_NOW")) {
++ c = strchr(line, '=');
++ c++;
++ if(*c == '-') c++; // ignoring the negative sign
++ _rate = strtoull(c, NULL, 10);
++ if (c) {
++ //printf ("CURRENT: %f. \n",_rate);
++ } else {
++ _rate = 0;
++ }
++ }
++ if (strstr(line, "CAPACITY=")) {
++ c = strchr(line, '=');
++ c++;
++ _capacity = strtoull(c, NULL, 10);
++ if (c) {
++ //printf ("CAPACITY: %f. \n",_capacity);
++ } else {
++ _capacity = 0;
++ }
++ }
++ if (strstr(line, "VOLTAGE_NOW")) {
++ c = strchr(line, '=');
++ c++;
++ while (*c == ' ') c++;
++ _voltage = strtoull(c, NULL, 10);
++ if (c) {
++ //printf ("VOLTAGE_NOW: %f. \n",_voltage);
++ } else {
++ _voltage = 0;
++ }
++ }
++ }
++ file.close();
++
++ if(_voltage) {
++ _voltage = _voltage / 1000.0;
++ voltage = _voltage;
++ } else {
++ voltage = 0.0;
++ }
++
++ if(_rate) {
++ _rate = _rate / 1000.0;
++ _rate = _rate * _voltage;
++ rate = _rate;
++ } else {
++ rate = 0.0;
++ }
++
++ if(_capacity)
++ capacity = _capacity;
++ else
++ capacity = 0.0;
++}
++
++
++void power_supply::end_measurement(void)
++{
++ measure();
++}
++
++void power_supply::start_measurement(void)
++{
++ /* ACPI battery state is a lagging indication, lets only measure at the end */
++}
++
++
++double power_supply::joules_consumed(void)
++{
++ return rate;
++}
+diff --git a/measurement/power_supply.h b/measurement/power_supply.h
+new file mode 100755
+index 0000000..5ad776e
+--- /dev/null
++++ b/measurement/power_supply.h
+@@ -0,0 +1,46 @@
++/*
++ * Copyright 2011, Intel Corporation
++ *
++ * This file is part of PowerTOP
++ *
++ * This program file is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program in a file named COPYING; if not, write to the
++ * Free Software Foundation, Inc,
++ * 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301 USA
++ * or just google for it.
++ *
++ * Authors:
++ * John Mathew <johnx.mathew@intel.com>
++ */
++#ifndef __INCLUDE_GUARD_POWER_SUPPLY_H
++#define __INCLUDE_GUARD_POWER_SUPPLY_H
++
++#include "measurement.h"
++
++class power_supply:public power_meter {
++ char battery_name[256];
++
++ double capacity;
++ double rate;
++ double voltage;
++ void measure(void);
++public:
++ power_supply(const char *_battery_name);
++ virtual void start_measurement(void);
++ virtual void end_measurement(void);
++
++ virtual double joules_consumed(void);
++ virtual double dev_capacity(void) { return capacity; };
++};
++
++#endif
--- /dev/null
+diff -up powertop-1.98/parameters/persistent.cpp.orig powertop-1.98/parameters/persistent.cpp
+--- powertop-1.98/parameters/persistent.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/parameters/persistent.cpp 2011-12-02 19:48:45.056747667 +0100
+@@ -122,22 +122,23 @@ void save_parameters(const char *filenam
+
+ // printf("result size is %i, #parameters is %i \n", (int)past_results.size(), (int)all_parameters.parameters.size());
+
+- if (!global_power_valid())
+- return;
+
+ file.open(filename, ios::out);
+ if (!file) {
+ cout << _("Cannot save to file ") << filename << "\n";
+ return;
+ }
+-
+- map<string, int>::iterator it;
+
+- for (it = param_index.begin(); it != param_index.end(); it++) {
+- int index;
+- index = it->second;
+- file << it->first << "\t" << setprecision(9) << all_parameters.parameters[index] << "\n";
+- }
++ if (global_power_valid())
++ {
++ map<string, int>::iterator it;
++
++ for (it = param_index.begin(); it != param_index.end(); it++) {
++ int index;
++ index = it->second;
++ file << it->first << "\t" << setprecision(9) << all_parameters.parameters[index] << "\n";
++ }
++ }
+ file.close();
+ }
+
--- /dev/null
+diff -up powertop-1.98/devices/alsa.cpp.orig powertop-1.98/devices/alsa.cpp
+--- powertop-1.98/devices/alsa.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/devices/alsa.cpp 2012-01-11 16:19:53.365786704 +0100
+@@ -28,6 +28,7 @@
+ #include <stdio.h>
+ #include <sys/types.h>
+ #include <dirent.h>
++#include <unistd.h>
+
+
+ using namespace std;
+diff -up powertop-1.98/devices/device.cpp.orig powertop-1.98/devices/device.cpp
+--- powertop-1.98/devices/device.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/devices/device.cpp 2012-01-11 16:13:38.284981557 +0100
+@@ -29,6 +29,7 @@
+ #include <stdio.h>
+ #include <limits.h>
+ #include <stdlib.h>
++#include <unistd.h>
+
+ using namespace std;
+
+diff -up powertop-1.98/html.cpp.orig powertop-1.98/html.cpp
+--- powertop-1.98/html.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/html.cpp 2012-01-11 16:06:58.714989836 +0100
+@@ -29,6 +29,7 @@
+ #include <utility>
+ #include <iostream>
+ #include <fstream>
++#include <unistd.h>
+
+ #include "css.h"
+ #include "lib.h"
+diff -up powertop-1.98/devices/i915-gpu.cpp.orig powertop-1.98/devices/i915-gpu.cpp
+--- powertop-1.98/devices/i915-gpu.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/devices/i915-gpu.cpp 2012-01-11 16:21:46.958008197 +0100
+@@ -28,6 +28,7 @@
+ #include <stdio.h>
+ #include <sys/types.h>
+ #include <dirent.h>
++#include <unistd.h>
+
+
+ using namespace std;
+diff -up powertop-1.98/cpu/intel_cpus.cpp.orig powertop-1.98/cpu/intel_cpus.cpp
+--- powertop-1.98/cpu/intel_cpus.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/cpu/intel_cpus.cpp 2012-01-11 16:11:55.784740852 +0100
+@@ -34,6 +34,7 @@
+ #include <sys/time.h>
+ #include <string.h>
+ #include <errno.h>
++#include <unistd.h>
+
+ #include "../lib.h"
+ #include "../parameters/parameters.h"
+diff -up powertop-1.98/main.cpp.orig powertop-1.98/main.cpp
+--- powertop-1.98/main.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/main.cpp 2012-01-11 16:00:06.445806979 +0100
+@@ -33,6 +33,7 @@
+ #include <time.h>
+ #include <sys/stat.h>
+ #include <getopt.h>
++#include <unistd.h>
+
+ #include "cpu/cpu.h"
+ #include "process/process.h"
+diff -up powertop-1.98/devices/network.cpp.orig powertop-1.98/devices/network.cpp
+--- powertop-1.98/devices/network.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/devices/network.cpp 2012-01-11 16:23:18.176178890 +0100
+@@ -33,6 +33,7 @@
+ #include <dirent.h>
+ #include <libgen.h>
+ #include <stdlib.h>
++#include <unistd.h>
+
+ #include <linux/ethtool.h>
+
+diff -up powertop-1.98/devices/rfkill.cpp.orig powertop-1.98/devices/rfkill.cpp
+--- powertop-1.98/devices/rfkill.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/devices/rfkill.cpp 2012-01-11 16:15:46.003268813 +0100
+@@ -29,6 +29,7 @@
+ #include <sys/types.h>
+ #include <dirent.h>
+ #include <libgen.h>
++#include <unistd.h>
+
+
+ using namespace std;
+diff -up powertop-1.98/devices/thinkpad-fan.cpp.orig powertop-1.98/devices/thinkpad-fan.cpp
+--- powertop-1.98/devices/thinkpad-fan.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/devices/thinkpad-fan.cpp 2012-01-11 16:25:27.550410318 +0100
+@@ -29,6 +29,7 @@
+ #include <sys/types.h>
+ #include <dirent.h>
+ #include <math.h>
++#include <unistd.h>
+
+ #include "../lib.h"
+
+diff -up powertop-1.98/devices/thinkpad-light.cpp.orig powertop-1.98/devices/thinkpad-light.cpp
+--- powertop-1.98/devices/thinkpad-light.cpp.orig 2012-01-11 16:27:38.000000000 +0100
++++ powertop-1.98/devices/thinkpad-light.cpp 2012-01-11 16:27:50.995652724 +0100
+@@ -29,6 +29,7 @@
+ #include <sys/types.h>
+ #include <dirent.h>
+ #include <math.h>
++#include <unistd.h>
+
+ #include "../lib.h"
+
--- /dev/null
+diff --git a/tuning/bluetooth.cpp b/tuning/bluetooth.cpp
+index 3957316..cc98642 100644
+--- a/tuning/bluetooth.cpp
++++ b/tuning/bluetooth.cpp
+@@ -46,6 +46,8 @@
+ bt_tunable::bt_tunable(void) : tunable("", 1.0, "Good", "Bad", "Unknown")
+ {
+ sprintf(desc, _("Bluetooth device interface status"));
++ strcpy(toggle_bad, "/usr/sbin/hciconfig hci0 up &> /dev/null &");
++ strcpy(toggle_good, "/usr/sbin/hciconfig hci0 down &> /dev/null");
+ }
+
+
+@@ -180,6 +182,16 @@ void bt_tunable::toggle(void)
+ system("/usr/sbin/hciconfig hci0 down &> /dev/null");
+ }
+
++const char *bt_tunable::toggle_script(void)
++{
++ int good;
++ good = good_bad();
++
++ if (good == TUNE_GOOD) {
++ return toggle_bad;
++ }
++ return toggle_good;
++}
+
+
+ void add_bt_tunable(void)
+diff --git a/tuning/bluetooth.h b/tuning/bluetooth.h
+index 27e15f1..ecb667d 100644
+--- a/tuning/bluetooth.h
++++ b/tuning/bluetooth.h
+@@ -39,6 +39,8 @@ public:
+
+ virtual void toggle(void);
+
++ virtual const char *toggle_script(void);
++
+ };
+
+ extern void add_bt_tunable(void);
+diff --git a/tuning/cpufreq.cpp b/tuning/cpufreq.cpp
+index bf2b8ae..3d0dbea 100644
+--- a/tuning/cpufreq.cpp
++++ b/tuning/cpufreq.cpp
+@@ -35,6 +35,7 @@
+ #include <unistd.h>
+ #include <dirent.h>
+ #include <errno.h>
++#include <sys/stat.h>
+
+ #include "../lib.h"
+ #include "cpufreq.h"
+@@ -153,6 +154,54 @@ void cpufreq_tunable::toggle(void)
+ closedir(dir);
+ }
+
++const char *cpufreq_tunable::toggle_script(void) {
++ DIR *dir;
++ struct dirent *dirent;
++ FILE *file;
++ char filename[PATH_MAX];
++ char tmp[4096];
++ struct stat statbuf;
++ int good;
++ good = good_bad();
++
++ strcpy(toggle_good, "/sbin/modprobe cpufreq_ondemand > /dev/null 2>&1\n");
++
++ if (good == TUNE_GOOD) {
++ dir = opendir("/sys/devices/system/cpu");
++ if (!dir)
++ return NULL;
++
++ while ((dirent = readdir(dir))) {
++ if (dirent->d_name[0]=='.')
++ continue;
++ sprintf(filename, "/sys/devices/system/cpu/%s/cpufreq/scaling_governor", dirent->d_name);
++ if (stat(filename, &statbuf) == -1)
++ continue;
++ sprintf(tmp, "echo '%s' > '%s';\n", original, filename);
++ strcat(toggle_good, tmp);
++ }
++
++ closedir(dir);
++ return toggle_good;
++ }
++
++ dir = opendir("/sys/devices/system/cpu");
++ if (!dir)
++ return NULL;
++
++ while ((dirent = readdir(dir))) {
++ if (dirent->d_name[0]=='.')
++ continue;
++ sprintf(filename, "/sys/devices/system/cpu/%s/cpufreq/scaling_governor", dirent->d_name);
++ if (stat(filename, &statbuf) == -1)
++ continue;
++ sprintf(tmp, "echo 'ondemand' > '%s';\n", filename);
++ strcat(toggle_good, tmp);
++ }
++
++ closedir(dir);
++ return toggle_good;
++}
+
+
+ void add_cpufreq_tunable(void)
+diff --git a/tuning/cpufreq.h b/tuning/cpufreq.h
+index 55af71f..983f813 100644
+--- a/tuning/cpufreq.h
++++ b/tuning/cpufreq.h
+@@ -40,6 +40,8 @@ public:
+
+ virtual void toggle(void);
+
++ virtual const char *toggle_script(void);
++
+ };
+
+ extern void add_cpufreq_tunable(void);
+diff --git a/tuning/ethernet.cpp b/tuning/ethernet.cpp
+index 4666ac1..7687e38 100644
+--- a/tuning/ethernet.cpp
++++ b/tuning/ethernet.cpp
+@@ -54,6 +54,8 @@ ethernet_tunable::ethernet_tunable(const char *iface) : tunable("", 0.3, _("Good
+ memset(interf, 0, sizeof(interf));
+ strncpy(interf, iface, sizeof(interf));
+ sprintf(desc, _("Wake-on-lan status for device %s"), iface);
++ sprintf(toggle_good, "ethtool -s %s wol d;", iface);
++
+ }
+
+
+@@ -128,6 +130,18 @@ void ethernet_tunable::toggle(void)
+ close(sock);
+ }
+
++const char *ethernet_tunable::toggle_script(void)
++{
++ int good;
++ good = good_bad();
++
++ if (good != TUNE_GOOD) {
++ return toggle_good;
++ }
++
++ return NULL;
++}
++
+
+ void ethtunable_callback(const char *d_name)
+ {
+diff --git a/tuning/ethernet.h b/tuning/ethernet.h
+index eeb6ebb..85810fb 100644
+--- a/tuning/ethernet.h
++++ b/tuning/ethernet.h
+@@ -40,6 +40,8 @@ public:
+
+ virtual void toggle(void);
+
++ virtual const char *toggle_script(void);
++
+ };
+
+ extern void add_ethernet_tunable(void);
+diff --git a/tuning/runtime.cpp b/tuning/runtime.cpp
+index 03cfa0b..3c6dae8 100644
+--- a/tuning/runtime.cpp
++++ b/tuning/runtime.cpp
+@@ -77,6 +77,8 @@ runtime_tunable::runtime_tunable(const char *path, const char *bus, const char *
+
+
+ }
++ sprintf(toggle_good, "echo 'auto' > '%s';", runtime_path);
++ sprintf(toggle_bad, "echo 'on' > '%s';", runtime_path);
+ }
+
+ int runtime_tunable::good_bad(void)
+@@ -105,6 +107,18 @@ void runtime_tunable::toggle(void)
+ write_sysfs(runtime_path, "auto");
+ }
+
++const char *runtime_tunable::toggle_script(void)
++{
++ int good;
++ good = good_bad();
++
++ if (good == TUNE_GOOD) {
++ return toggle_bad;
++ }
++
++ return toggle_good;
++}
++
+
+ void add_runtime_tunables(const char *bus)
+ {
+diff --git a/tuning/runtime.h b/tuning/runtime.h
+index c874241..a3c3e20 100644
+--- a/tuning/runtime.h
++++ b/tuning/runtime.h
+@@ -39,6 +39,8 @@ public:
+
+ virtual void toggle(void);
+
++ virtual const char *toggle_script(void);
++
+ };
+
+ extern void add_runtime_tunables(const char *bus);
+diff --git a/tuning/sysfs.cpp b/tuning/sysfs.cpp
+index e1742a3..ffb2df0 100644
+--- a/tuning/sysfs.cpp
++++ b/tuning/sysfs.cpp
+@@ -39,6 +39,8 @@ sysfs_tunable::sysfs_tunable(const char *str, const char *_sysfs_path, const cha
+ strcpy(sysfs_path, _sysfs_path);
+ strcpy(target_value, _target_content);
+ bad_value[0] = 0;
++ sprintf(toggle_good, "echo '%s' > '%s';", target_value, sysfs_path);
++ sprintf(toggle_bad, "echo '%s' > '%s';", bad_value, sysfs_path);
+ }
+
+ int sysfs_tunable::good_bad(void)
+@@ -77,6 +79,19 @@ void sysfs_tunable::toggle(void)
+ write_sysfs(sysfs_path, target_value);
+ }
+
++const char *sysfs_tunable::toggle_script(void) {
++ int good;
++ good = good_bad();
++
++ if (good == TUNE_GOOD) {
++ if (strlen(bad_value) > 0)
++ return toggle_bad;
++ return NULL;
++ }
++
++ return toggle_good;
++}
++
+
+ void add_sysfs_tunable(const char *str, const char *_sysfs_path, const char *_target_content)
+ {
+diff --git a/tuning/sysfs.h b/tuning/sysfs.h
+index 9fee4c0..ac7938c 100644
+--- a/tuning/sysfs.h
++++ b/tuning/sysfs.h
+@@ -42,6 +42,8 @@ public:
+
+ virtual void toggle(void);
+
++ virtual const char *toggle_script(void);
++
+ };
+
+ extern void add_sysfs_tunable(const char *str, const char *_sysfs_path, const char *_target_content);
+diff --git a/tuning/tunable.h b/tuning/tunable.h
+index a4e994d..dacbd79 100644
+--- a/tuning/tunable.h
++++ b/tuning/tunable.h
+@@ -42,6 +42,9 @@ class tunable {
+ char good_string[128];
+ char bad_string[128];
+ char neutral_string[128];
++protected:
++ char toggle_good[4096];
++ char toggle_bad[4096];
+ public:
+ char desc[4096];
+ double score;
+@@ -67,6 +70,8 @@ public:
+ virtual const char *description(void) { return desc; };
+
+ virtual void toggle(void) { };
++
++ virtual const char *toggle_script(void) { return NULL; }
+ };
+
+ extern vector<class tunable *> all_tunables;
+diff --git a/tuning/tuning.cpp b/tuning/tuning.cpp
+index c63f1e8..dd5b1dc 100644
+--- a/tuning/tuning.cpp
++++ b/tuning/tuning.cpp
+@@ -218,7 +218,7 @@ void html_show_tunables(void)
+ }
+
+ line++;
+- fprintf(htmlout, "<tr class=\"%s\"><td>%s</td></tr>\n", tune_class_bad(line), all_tunables[i]->description());
++ fprintf(htmlout, "<tr class=\"%s\"><td>%s</td><td>%s</td></tr>\n", tune_class_bad(line), all_tunables[i]->description(), all_tunables[i]->toggle_script());
+ }
+
+ if (line > 0)
+diff --git a/tuning/usb.cpp b/tuning/usb.cpp
+index 16e25d4..6bcfb07 100644
+--- a/tuning/usb.cpp
++++ b/tuning/usb.cpp
+@@ -74,6 +74,9 @@ usb_tunable::usb_tunable(const char *path, const char *name) : tunable("", 0.9,
+ sprintf(desc, _("Autosuspend for USB device %s [%s]"), product, name);
+ else if (strlen(vendor))
+ sprintf(desc, _("Autosuspend for USB device %s [%s]"), vendor, name);
++
++ sprintf(toggle_good, "echo 'auto' > '%s';", usb_path);
++ sprintf(toggle_bad, "echo 'on' > '%s';", usb_path);
+ }
+
+ int usb_tunable::good_bad(void)
+@@ -102,6 +105,17 @@ void usb_tunable::toggle(void)
+ write_sysfs(usb_path, "auto");
+ }
+
++const char *usb_tunable::toggle_script(void)
++{
++ int good;
++ good = good_bad();
++
++ if (good == TUNE_GOOD) {
++ return toggle_bad;
++ }
++
++ return toggle_good;
++}
+
+ void add_usb_tunables(void)
+ {
+diff --git a/tuning/usb.h b/tuning/usb.h
+index a6f9557..a257904 100644
+--- a/tuning/usb.h
++++ b/tuning/usb.h
+@@ -40,6 +40,8 @@ public:
+
+ virtual void toggle(void);
+
++ virtual const char *toggle_script(void);
++
+ };
+
+ extern void add_usb_tunables(void);
+diff --git a/tuning/wifi.cpp b/tuning/wifi.cpp
+index 9d64a9f..8b67fc5 100644
+--- a/tuning/wifi.cpp
++++ b/tuning/wifi.cpp
+@@ -46,6 +46,9 @@ wifi_tunable::wifi_tunable(const char *_iface) : tunable("", 1.5, _("Good"), _("
+ {
+ strcpy(iface, _iface);
+ sprintf(desc, _("Wireless Power Saving for interface %s"), iface);
++
++ sprintf(toggle_good, "iw dev %s set power_save off", iface);
++ sprintf(toggle_bad, "iw dev %s set power_save on", iface);
+ }
+
+ int wifi_tunable::good_bad(void)
+@@ -69,6 +72,17 @@ void wifi_tunable::toggle(void)
+ set_wifi_power_saving(iface, 1);
+ }
+
++const char *wifi_tunable::toggle_script(void)
++{
++ int good;
++ good = good_bad();
++
++ if (good == TUNE_GOOD) {
++ return toggle_bad;
++ }
++
++ return toggle_good;
++}
+
+ void add_wifi_tunables(void)
+ {
+diff --git a/tuning/wifi.h b/tuning/wifi.h
+index 347470e..50ca68c 100644
+--- a/tuning/wifi.h
++++ b/tuning/wifi.h
+@@ -40,6 +40,8 @@ public:
+
+ virtual void toggle(void);
+
++ virtual const char *toggle_script(void);
++
+ };
+
+ extern void add_wifi_tunables(void);
--- /dev/null
+From 0dce3803eff9c3919c025ba5534bacdfda471182 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com>
+Date: Fri, 24 Feb 2012 13:55:44 +0100
+Subject: [PATCH] power_supply: Add support for POWER_NOW readings
+
+---
+ measurement/power_supply.cpp | 30 ++++++++++++++++++++++--------
+ 1 files changed, 22 insertions(+), 8 deletions(-)
+
+diff --git a/measurement/power_supply.cpp b/measurement/power_supply.cpp
+index b4fe3af..13d8d34 100755
+--- a/measurement/power_supply.cpp
++++ b/measurement/power_supply.cpp
+@@ -76,7 +76,8 @@ void power_supply::measure(void)
+ char line[4096];
+ ifstream file;
+
+- double _rate = 0;
++ double _power_rate = 0;
++ double _current_rate = 0;
+ double _capacity = 0;
+ double _voltage = 0;
+
+@@ -114,11 +115,21 @@ void power_supply::measure(void)
+ c = strchr(line, '=');
+ c++;
+ if(*c == '-') c++; // ignoring the negative sign
+- _rate = strtoull(c, NULL, 10);
++ _current_rate = strtoull(c, NULL, 10);
+ if (c) {
+- //printf ("CURRENT: %f. \n",_rate);
++ //printf ("CURRENT: %f. \n",_current_rate);
+ } else {
+- _rate = 0;
++ _current_rate = 0;
++ }
++ }
++ if (strstr(line, "POWER_NOW")) {
++ c = strchr(line, '=');
++ c++;
++ _power_rate = strtoull(c, NULL, 10);
++ if (c) {
++ //printf ("POWER: %f. \n",_power_rate);
++ } else {
++ _power_rate = 0;
+ }
+ }
+ if (strstr(line, "CAPACITY=")) {
+@@ -152,10 +163,13 @@ void power_supply::measure(void)
+ voltage = 0.0;
+ }
+
+- if(_rate) {
+- _rate = _rate / 1000.0;
+- _rate = _rate * _voltage;
+- rate = _rate;
++ if(_power_rate)
++ {
++ rate = _power_rate / 1000000.0;
++ }
++ else if(_current_rate) {
++ _current_rate = _current_rate / 1000.0;
++ rate = _current_rate * _voltage;
+ } else {
+ rate = 0.0;
+ }
+--
+1.7.7.6
+
--- /dev/null
+diff -up powertop-1.98/measurement/power_supply.cpp.orig powertop-1.98/measurement/power_supply.cpp
+--- powertop-1.98/measurement/power_supply.cpp.orig 2012-03-07 15:04:52.592471296 +0100
++++ powertop-1.98/measurement/power_supply.cpp 2012-03-07 15:07:27.743785210 +0100
+@@ -157,7 +157,7 @@ void power_supply::measure(void)
+ file.close();
+
+ if(_voltage) {
+- _voltage = _voltage / 1000.0;
++ _voltage = _voltage / 1e6f;
+ voltage = _voltage;
+ } else {
+ voltage = 0.0;
+@@ -165,10 +165,10 @@ void power_supply::measure(void)
+
+ if(_power_rate)
+ {
+- rate = _power_rate / 1000000.0;
++ rate = _power_rate / 1e6f;
+ }
+ else if(_current_rate) {
+- _current_rate = _current_rate / 1000.0;
++ _current_rate = _current_rate / 1e6f;
+ rate = _current_rate * _voltage;
+ } else {
+ rate = 0.0;
--- /dev/null
+diff -up powertop-1.98/measurement/measurement.cpp.orig powertop-1.98/measurement/measurement.cpp
+--- powertop-1.98/measurement/measurement.cpp.orig 2012-04-17 15:47:59.000000000 +0200
++++ powertop-1.98/measurement/measurement.cpp 2012-04-17 15:49:31.690862740 +0200
+@@ -130,7 +130,7 @@ void power_supply_callback(const char *d
+ while (file) {
+ file.getline(line, 4096);
+
+- if (strstr(line, "POWER_SUPPLY_STATUS") && strstr(line, "POWER_SUPPLY_STATUS"))
++ if (strstr(line, "POWER_SUPPLY_STATUS") && strstr(line, "Discharging"))
+ discharging = true;
+ }
+ file.close();
--- /dev/null
+diff -up powertop-1.98/measurement/acpi.cpp.orig powertop-1.98/measurement/acpi.cpp
+--- powertop-1.98/measurement/acpi.cpp.orig 2011-05-11 06:48:37.000000000 +0200
++++ powertop-1.98/measurement/acpi.cpp 2012-01-10 18:31:21.093799991 +0100
+@@ -108,8 +108,13 @@ void acpi_power_meter::measure(void)
+ while (*c == ' ') c++;
+ _capacity = strtoull(c, NULL, 10);
+ c = strchr(c, ' ');
+- c++;
+- strcpy(capacity_units, c);
++ if (c) {
++ c++;
++ strcpy(capacity_units, c);
++ } else {
++ _capacity = 0;
++ strcpy(capacity_units, "Unknown");
++ }
+ }
+ if (strstr(line, "present voltage:")) {
+ c = strchr(line, ':');
+@@ -117,8 +122,13 @@ void acpi_power_meter::measure(void)
+ while (*c == ' ') c++;
+ _voltage = strtoull(c, NULL, 10);
+ c = strchr(c, ' ');
+- c++;
+- strcpy(voltage_units, c);
++ if (c) {
++ c++;
++ strcpy(voltage_units, c);
++ } else {
++ _voltage = 0;
++ strcpy(voltage_units, "Unknown");
++ }
+ }
+ }
+ file.close();
###############################################################################
name = powertop
-version = 1.13
+version = 1.98
release = 1
groups = Applications/System
computer use more power than necessary while it is idle.
end
-source_dl =
+source_dl = http://www.kernel.org/pub/linux/status/powertop/
build
requires
+ gcc-c++
gettext
+ libnl-devel
ncurses-devel
+ pciutils-devel
+ zlib-devel
end
end