summaryrefslogtreecommitdiffstats
path: root/src/devices
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/ahci.cpp428
-rw-r--r--src/devices/ahci.h72
-rw-r--r--src/devices/alsa.cpp207
-rw-r--r--src/devices/alsa.h67
-rw-r--r--src/devices/backlight.cpp225
-rw-r--r--src/devices/backlight.h59
-rw-r--r--src/devices/devfreq.cpp334
-rw-r--r--src/devices/devfreq.h76
-rw-r--r--src/devices/device.cpp345
-rw-r--r--src/devices/device.h85
-rw-r--r--src/devices/gpu_rapl_device.cpp70
-rw-r--r--src/devices/gpu_rapl_device.h57
-rw-r--r--src/devices/i915-gpu.cpp121
-rw-r--r--src/devices/i915-gpu.h58
-rw-r--r--src/devices/network.cpp441
-rw-r--r--src/devices/network.h85
-rw-r--r--src/devices/rfkill.cpp177
-rw-r--r--src/devices/rfkill.h62
-rw-r--r--src/devices/runtime_pm.cpp257
-rw-r--r--src/devices/runtime_pm.h66
-rw-r--r--src/devices/thinkpad-fan.cpp124
-rw-r--r--src/devices/thinkpad-fan.h58
-rw-r--r--src/devices/thinkpad-light.cpp113
-rw-r--r--src/devices/thinkpad-light.h58
-rw-r--r--src/devices/usb.cpp254
-rw-r--r--src/devices/usb.h67
26 files changed, 3966 insertions, 0 deletions
diff --git a/src/devices/ahci.cpp b/src/devices/ahci.cpp
new file mode 100644
index 0000000..efa66b3
--- /dev/null
+++ b/src/devices/ahci.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+
+using namespace std;
+
+#include "device.h"
+#include "report/report.h"
+#include "report/report-maker.h"
+#include "ahci.h"
+#include "../parameters/parameters.h"
+#include "report/report-data-html.h"
+#include <string.h>
+
+vector <class ahci *> links;
+
+static string disk_name(char *path, char *target, char *shortname)
+{
+
+ DIR *dir;
+ struct dirent *dirent;
+ char pathname[PATH_MAX];
+ string diskname = "";
+
+ snprintf(pathname, sizeof(pathname), "%s/%s", path, target);
+ dir = opendir(pathname);
+ if (!dir)
+ return diskname;
+
+ while ((dirent = readdir(dir))) {
+ char line[4096], *c;
+ FILE *file;
+ if (dirent->d_name[0]=='.')
+ continue;
+
+ if (!strchr(dirent->d_name, ':'))
+ continue;
+
+ snprintf(line, sizeof(line), "%s/%s/model", pathname, dirent->d_name);
+ file = fopen(line, "r");
+ if (file) {
+ if (fgets(line, sizeof(line), file) == NULL) {
+ fclose(file);
+ break;
+ }
+ fclose(file);
+ c = strchr(line, '\n');
+ if (c)
+ *c = 0;
+ diskname = line;
+ break;
+ }
+ }
+ closedir(dir);
+
+ return diskname;
+}
+
+static string model_name(char *path, char *shortname)
+{
+
+ DIR *dir;
+ struct dirent *dirent;
+ char pathname[PATH_MAX];
+
+ snprintf(pathname, sizeof(pathname), "%s/device", path);
+
+ dir = opendir(pathname);
+ if (!dir)
+ return strdup(shortname);
+
+ while ((dirent = readdir(dir))) {
+ if (dirent->d_name[0]=='.')
+ continue;
+
+ if (!strchr(dirent->d_name, ':'))
+ continue;
+ if (!strstr(dirent->d_name, "target"))
+ continue;
+ return disk_name(pathname, dirent->d_name, shortname);
+ }
+ closedir(dir);
+
+ return "";
+}
+
+ahci::ahci(char *_name, char *path): device()
+{
+ char buffer[4096];
+ char devname[128];
+ string diskname;
+
+ end_active = 0;
+ end_slumber = 0;
+ end_devslp = 0;
+ end_partial = 0;
+ start_active = 0;
+ start_slumber = 0;
+ start_devslp = 0;
+ start_partial = 0;
+ pt_strcpy(sysfs_path, path);
+
+ register_sysfs_path(sysfs_path);
+
+ snprintf(devname, sizeof(devname), "ahci:%s", _name);
+ pt_strcpy(name, devname);
+ active_index = get_param_index("ahci-link-power-active");
+ partial_index = get_param_index("ahci-link-power-partial");
+
+ snprintf(buffer, sizeof(buffer), "%s-active", name);
+ active_rindex = get_result_index(buffer);
+
+ snprintf(buffer, sizeof(buffer), "%s-partial", name);
+ partial_rindex = get_result_index(buffer);
+
+ snprintf(buffer, sizeof(buffer), "%s-slumber", name);
+ slumber_rindex = get_result_index(buffer);
+
+ snprintf(buffer, sizeof(buffer), "%s-devslp", name);
+ devslp_rindex = get_result_index(buffer);
+
+ diskname = model_name(path, _name);
+
+ if (strlen(diskname.c_str()) == 0)
+ snprintf(humanname, sizeof(humanname), _("SATA link: %s"), _name);
+ else
+ snprintf(humanname, sizeof(humanname), _("SATA disk: %s"), diskname.c_str());
+}
+
+void ahci::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_active", sysfs_path);
+ try {
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_active;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_partial", sysfs_path);
+ file.open(filename, ios::in);
+
+ if (file) {
+ file >> start_partial;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_slumber", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_slumber;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_devslp", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_devslp;
+ }
+ file.close();
+ }
+ catch (std::ios_base::failure &c) {
+ fprintf(stderr, "%s\n", c.what());
+ }
+
+}
+
+void ahci::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ char powername[4096];
+ ifstream file;
+ double p;
+ double total;
+
+ try {
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_active", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_active;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_partial", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_partial;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_slumber", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_slumber;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_devslp", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_devslp;
+ }
+ file.close();
+ }
+ catch (std::ios_base::failure &c) {
+ fprintf(stderr, "%s\n", c.what());
+ }
+ if (end_active < start_active)
+ end_active = start_active;
+ if (end_partial < start_partial)
+ end_partial = start_partial;
+ if (end_slumber < start_slumber)
+ end_slumber = start_slumber;
+
+ total = 0.001 + end_active + end_partial + end_slumber + end_devslp -
+ start_active - start_partial - start_slumber - start_devslp;
+
+ /* percent in active */
+ p = (end_active - start_active) / total * 100.0;
+ if (p < 0)
+ p = 0;
+ snprintf(powername, sizeof(powername), "%s-active", name);
+ report_utilization(powername, p);
+
+ /* percent in partial */
+ p = (end_partial - start_partial) / total * 100.0;
+ if (p < 0)
+ p = 0;
+ snprintf(powername, sizeof(powername), "%s-partial", name);
+ report_utilization(powername, p);
+
+ /* percent in slumber */
+ p = (end_slumber - start_slumber) / total * 100.0;
+ if (p < 0)
+ p = 0;
+ snprintf(powername, sizeof(powername), "%s-slumber", name);
+ report_utilization(powername, p);
+
+ /* percent in devslp */
+ p = (end_devslp - start_devslp) / total * 100.0;
+ if (p < 0)
+ p = 0;
+ snprintf(powername, sizeof(powername), "%s-devslp", name);
+ report_utilization(powername, p);
+}
+
+
+double ahci::utilization(void)
+{
+ double p;
+
+ p = (end_partial - start_partial + end_active - start_active) / (0.001 + end_active + end_partial + end_slumber + end_devslp - start_active - start_partial - start_slumber - start_devslp) * 100.0;
+
+ if (p < 0)
+ p = 0;
+
+ return p;
+}
+
+const char * ahci::device_name(void)
+{
+ return name;
+}
+
+void create_all_ahcis(void)
+{
+ struct dirent *entry;
+ DIR *dir;
+ char filename[PATH_MAX];
+
+ dir = opendir("/sys/class/scsi_host/");
+ if (!dir)
+ return;
+ while (1) {
+ class ahci *bl;
+ ofstream file;
+ ifstream check_file;
+ entry = readdir(dir);
+ if (!entry)
+ break;
+ if (entry->d_name[0] == '.')
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/class/scsi_host/%s/ahci_alpm_accounting", entry->d_name);
+
+ check_file.open(filename, ios::in);
+ check_file.get();
+ check_file.close();
+ if (check_file.bad())
+ continue;
+
+ file.open(filename, ios::in);
+ if (!file)
+ continue;
+ file << 1 ;
+ file.close();
+ snprintf(filename, sizeof(filename), "/sys/class/scsi_host/%s", entry->d_name);
+
+ bl = new class ahci(entry->d_name, filename);
+ all_devices.push_back(bl);
+ register_parameter("ahci-link-power-active", 0.6); /* active sata link takes about 0.6 W */
+ register_parameter("ahci-link-power-partial");
+ links.push_back(bl);
+ }
+ closedir(dir);
+
+}
+
+
+
+double ahci::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ power = 0;
+
+ factor = get_parameter_value(active_index, bundle);
+ util = get_result_value(active_rindex, result);
+ power += util * factor / 100.0;
+
+
+ factor = get_parameter_value(partial_index, bundle);
+ util = get_result_value(partial_rindex, result);
+ power += util * factor / 100.0;
+
+ return power;
+}
+
+void ahci_create_device_stats_table(void)
+{
+ unsigned int i;
+ int cols=0;
+ int rows=0;
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "ahci");
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Add section */
+ report.add_div(&div_attr);
+
+ if (links.size() == 0) {
+ report.add_title(&title_attr, __("AHCI ALPM Residency Statistics - Not supported on this macine"));
+ report.end_div();
+ return;
+ }
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes std_table_css;
+ cols=5;
+ rows=links.size()+1;
+ init_std_side_table_attr(&std_table_css, rows, cols);
+
+
+
+ /* Set array of data in row Major order */
+ string *ahci_data = new string[cols * rows];
+ ahci_data[0]=__("Link");
+ ahci_data[1]=__("Active");
+ ahci_data[2]=__("Partial");
+ ahci_data[3]=__("Slumber");
+ ahci_data[4]=__("Devslp");
+
+ /* traverse list of all devices and put their residency in the table */
+ for (i = 0; i < links.size(); i++){
+ links[i]->report_device_stats(ahci_data, i);
+ }
+ report.add_title(&title_attr, __("AHCI ALPM Residency Statistics"));
+ report.add_table(ahci_data, &std_table_css);
+ report.end_div();
+ delete [] ahci_data;
+}
+
+void ahci::report_device_stats(string *ahci_data, int idx)
+{
+ int offset=(idx*5+5);
+ char util[128];
+ double active_util = get_result_value(active_rindex, &all_results);
+ double partial_util = get_result_value(partial_rindex, &all_results);
+ double slumber_util = get_result_value(slumber_rindex, &all_results);
+ double devslp_util = get_result_value(devslp_rindex, &all_results);
+
+ snprintf(util, sizeof(util), "%5.1f", active_util);
+ ahci_data[offset]= util;
+ offset +=1;
+
+ snprintf(util, sizeof(util), "%5.1f", partial_util);
+ ahci_data[offset]= util;
+ offset +=1;
+
+ snprintf(util, sizeof(util), "%5.1f", slumber_util);
+ ahci_data[offset]= util;
+ offset +=1;
+
+ snprintf(util, sizeof(util), "%5.1f", devslp_util);
+ ahci_data[offset]= util;
+}
diff --git a/src/devices/ahci.h b/src/devices/ahci.h
new file mode 100644
index 0000000..7431fb5
--- /dev/null
+++ b/src/devices/ahci.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_AHCI_H
+#define _INCLUDE_GUARD_AHCI_H
+
+
+#include <string>
+#include <limits.h>
+#include "device.h"
+#include "../parameters/parameters.h"
+#include <stdint.h>
+
+class ahci: public device {
+ uint64_t start_active, end_active;
+ uint64_t start_partial, end_partial;
+ uint64_t start_slumber, end_slumber;
+ uint64_t start_devslp, end_devslp;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ int partial_rindex;
+ int active_rindex;
+ int slumber_rindex;
+ int devslp_rindex;
+ int partial_index;
+ int active_index;
+ char humanname[4096];
+public:
+
+ ahci(char *_name, char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "ahci";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void) { return humanname;};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(partial_rindex) + utilization_power_valid(active_rindex);};
+ virtual int grouping_prio(void) { return 1; };
+ virtual void report_device_stats(string *ahci_data, int idx);
+};
+
+extern void create_all_ahcis(void);
+extern void ahci_create_device_stats_table(void);
+
+
+#endif
diff --git a/src/devices/alsa.cpp b/src/devices/alsa.cpp
new file mode 100644
index 0000000..7e22975
--- /dev/null
+++ b/src/devices/alsa.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+using namespace std;
+
+#include "device.h"
+#include "alsa.h"
+#include "../parameters/parameters.h"
+
+#include "../devlist.h"
+
+#include <string.h>
+#include <unistd.h>
+
+alsa::alsa(const char *_name, const char *path): device()
+{
+ ifstream file;
+
+ char devname[4096];
+ char model[4096];
+ char vendor[4096];
+ end_active = 0;
+ start_active = 0;
+ end_inactive = 0;
+ start_inactive = 0;
+ pt_strcpy(sysfs_path, path);
+
+ snprintf(devname, sizeof(devname), "alsa:%s", _name);
+ snprintf(humanname, sizeof(humanname), "alsa:%s", _name);
+ pt_strcpy(name, devname);
+ rindex = get_result_index(name);
+
+ guilty[0] = 0;
+ model[0] = 0;
+ vendor[0] = 0;
+ snprintf(devname, sizeof(devname), "%s/modelname", path);
+ file.open(devname);
+ if (file) {
+ file.getline(model, sizeof(model));
+ file.close();
+ }
+ snprintf(devname, sizeof(devname), "%s/vendor_name", path);
+ file.open(devname);
+ if (file) {
+ file.getline(vendor, sizeof(vendor));
+ file.close();
+ }
+ if (strlen(model) && strlen(vendor))
+ snprintf(humanname, sizeof(humanname), _("Audio codec %s: %s (%s)"), name, model, vendor);
+ else if (strlen(model))
+ snprintf(humanname, sizeof(humanname), _("Audio codec %s: %s"), _name, model);
+ else if (strlen(vendor))
+ snprintf(humanname, sizeof(humanname), _("Audio codec %s: %s"), _name, vendor);
+}
+
+void alsa::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/power_off_acct", sysfs_path);
+ try {
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_inactive;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/power_on_acct", sysfs_path);
+ file.open(filename, ios::in);
+
+ if (file) {
+ file >> start_active;
+ }
+ file.close();
+ }
+ catch (std::ios_base::failure &c) {
+ fprintf(stderr, "%s\n", c.what());
+ }
+}
+
+void alsa::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+ double p;
+
+ snprintf(filename, sizeof(filename), "%s/power_off_acct", sysfs_path);
+ try {
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_inactive;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/power_on_acct", sysfs_path);
+ file.open(filename, ios::in);
+
+ if (file) {
+ file >> end_active;
+ }
+ file.close();
+ }
+ catch (std::ios_base::failure &c) {
+ fprintf(stderr, "%s\n", c.what());
+ }
+
+ p = (end_active - start_active) / (0.001 + end_active + end_inactive - start_active - start_inactive) * 100.0;
+ report_utilization(name, p);
+}
+
+
+double alsa::utilization(void)
+{
+ double p;
+
+ p = (end_active - start_active) / (0.001 + end_active - start_active + end_inactive - start_inactive) * 100.0;
+
+ return p;
+}
+
+const char * alsa::device_name(void)
+{
+ return name;
+}
+
+static void create_all_alsa_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ class alsa *bl;
+
+ if (strncmp(d_name, "hwC", 3) != 0)
+ return;
+
+ snprintf(filename, sizeof(filename), "/sys/class/sound/%s/power_on_acct", d_name);
+ if (access(filename, R_OK) != 0)
+ return;
+
+ snprintf(filename, sizeof(filename), "/sys/class/sound/%s", d_name);
+ bl = new class alsa(d_name, filename);
+ all_devices.push_back(bl);
+ register_parameter("alsa-codec-power", 0.5);
+}
+
+void create_all_alsa(void)
+{
+ process_directory("/sys/class/sound/", create_all_alsa_callback);
+}
+
+double alsa::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+ static int index = 0;
+
+ power = 0;
+ if (!index)
+ index = get_param_index("alsa-codec-power");
+
+ factor = get_parameter_value(index, bundle);
+
+ util = get_result_value(rindex, result);
+
+ power += util * factor / 100.0;
+
+ return power;
+}
+
+void alsa::register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle)
+{
+ register_devpower(&name[7], power_usage(results, bundle), this);
+}
+
+const char * alsa::human_name(void)
+{
+ pt_strcpy(temp_buf, humanname);
+ if (strlen(guilty) > 0)
+ snprintf(temp_buf, sizeof(temp_buf), "%s (%s)", humanname, guilty);
+ return temp_buf;
+}
diff --git a/src/devices/alsa.h b/src/devices/alsa.h
new file mode 100644
index 0000000..b68203f
--- /dev/null
+++ b/src/devices/alsa.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_ALSA_H
+#define _INCLUDE_GUARD_ALSA_H
+
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+#include <stdint.h>
+#include <limits.h>
+
+class alsa: public device {
+ uint64_t start_active, end_active;
+ uint64_t start_inactive, end_inactive;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char humanname[4096];
+ char temp_buf[4096];
+ int rindex;
+public:
+
+ alsa(const char *_name, const char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "alsa";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void);
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(rindex);};
+
+ virtual void register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle);
+ virtual int grouping_prio(void) { return 0; };
+
+};
+
+extern void create_all_alsa(void);
+
+
+#endif
diff --git a/src/devices/backlight.cpp b/src/devices/backlight.cpp
new file mode 100644
index 0000000..c73e4c9
--- /dev/null
+++ b/src/devices/backlight.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+
+using namespace std;
+
+#include "device.h"
+#include "backlight.h"
+#include "../parameters/parameters.h"
+
+#include <string.h>
+
+
+backlight::backlight(const char *_name, const char *path): device()
+{
+ min_level = 0;
+ max_level = 0;
+ start_level = 0;
+ end_level = 0;
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ snprintf(name, sizeof(name) - 1, "backlight:%s", _name);
+ r_index = get_result_index(name);
+ r_index_power = 0;
+}
+
+void backlight::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/max_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> max_level;
+ }
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/actual_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_level;
+ file.close();
+ }
+}
+
+static int dpms_screen_on(void)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char filename[PATH_MAX];
+ char line[4096];
+ ifstream file;
+
+ dir = opendir("/sys/class/drm/card0");
+ if (!dir)
+ return 1;
+ while (1) {
+ entry = readdir(dir);
+ if (!entry)
+ break;
+
+ if (strncmp(entry->d_name, "card", 4) != 0)
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/class/drm/card0/%s/enabled", entry->d_name);
+ file.open(filename, ios::in);
+ if (!file)
+ continue;
+ file.getline(line, sizeof(line));
+ file.close();
+ if (strcmp(line, "enabled") != 0)
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/class/drm/card0/%s/dpms", entry->d_name);
+ file.open(filename, ios::in);
+ if (!file)
+ continue;
+ file.getline(line, sizeof(line));
+ file.close();
+ if (strcmp(line, "On") == 0) {
+ closedir(dir);
+ return 1;
+ }
+ }
+ closedir(dir);
+ return 0;
+}
+
+void backlight::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ char powername[4096];
+ ifstream file;
+ double p;
+ int _backlight = 0;
+
+ snprintf(filename, sizeof(filename), "%s/actual_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_level;
+ }
+ file.close();
+
+ if (dpms_screen_on()) {
+ p = 100.0 * (end_level + start_level) / 2 / max_level;
+ _backlight = 100;
+ } else {
+ p = 0;
+ }
+
+ report_utilization(name, p);
+ snprintf(powername, sizeof(powername), "%s-power", name);
+ report_utilization(powername, _backlight);
+}
+
+
+double backlight::utilization(void)
+{
+ double p;
+
+ p = 100.0 * (end_level + start_level) / 2 / max_level;
+ return p;
+}
+
+const char * backlight::device_name(void)
+{
+ return name;
+}
+
+static void create_all_backlights_callback(const char *d_name)
+{
+ class backlight *bl;
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof(filename), "/sys/class/backlight/%s", d_name);
+ bl = new class backlight(d_name, filename);
+ all_devices.push_back(bl);
+}
+
+void create_all_backlights(void)
+{
+ process_directory("/sys/class/backlight/", create_all_backlights_callback);
+ register_parameter("backlight");
+ register_parameter("backlight-power");
+ register_parameter("backlight-boost-40", 0, 0.5);
+ register_parameter("backlight-boost-80", 0, 0.5);
+ register_parameter("backlight-boost-100", 0, 0.5);
+}
+
+double backlight::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double _utilization;
+ char powername[4096];
+ static int bl_index = 0, blp_index = 0, bl_boost_index40 = 0, bl_boost_index80, bl_boost_index100;
+
+ if (!bl_index)
+ bl_index = get_param_index("backlight");
+ if (!blp_index)
+ blp_index = get_param_index("backlight-power");
+ if (!bl_boost_index40)
+ bl_boost_index40 = get_param_index("backlight-boost-40");
+ if (!bl_boost_index80)
+ bl_boost_index80 = get_param_index("backlight-boost-80");
+ if (!bl_boost_index100)
+ bl_boost_index100 = get_param_index("backlight-boost-100");
+
+ power = 0;
+ factor = get_parameter_value(bl_index, bundle);
+ _utilization = get_result_value(r_index, result);
+
+ power += _utilization * factor / 100.0;
+
+ /*
+ * most machines have a non-linear backlight scale. to compensate, add a fixed value
+ * once the brightness hits 40% and 80%
+ */
+
+ if (_utilization >=99)
+ power += get_parameter_value(bl_boost_index100, bundle);
+ else if (_utilization >=80)
+ power += get_parameter_value(bl_boost_index80, bundle);
+ else if (_utilization >=40)
+ power += get_parameter_value(bl_boost_index40, bundle);
+
+ factor = get_parameter_value(blp_index, bundle);
+
+ if (!r_index_power) {
+ sprintf(powername, "%s-power", name);
+ r_index_power = get_result_index(powername);
+ }
+ _utilization = get_result_value(r_index_power, result);
+
+ power += _utilization * factor / 100.0;
+
+ return power;
+}
diff --git a/src/devices/backlight.h b/src/devices/backlight.h
new file mode 100644
index 0000000..1dac778
--- /dev/null
+++ b/src/devices/backlight.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_BACKLIGHT_H
+#define _INCLUDE_GUARD_BACKLIGHT_H
+
+#include <limits.h>
+
+#include "device.h"
+
+class backlight: public device {
+ int min_level, max_level;
+ int start_level, end_level;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ int r_index;
+ int r_index_power;
+public:
+
+ backlight(const char *_name, const char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "backlight";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void) { return "Display backlight";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int grouping_prio(void) { return 10; };
+};
+
+extern void create_all_backlights(void);
+
+
+#endif
diff --git a/src/devices/devfreq.cpp b/src/devices/devfreq.cpp
new file mode 100644
index 0000000..b194ac4
--- /dev/null
+++ b/src/devices/devfreq.cpp
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * 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:
+ * Rajagopal Venkat <rajagopal.venkat@linaro.org>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "device.h"
+#include "devfreq.h"
+#include "../display.h"
+#include "../cpu/cpu.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+
+static bool is_enabled = true;
+static DIR *dir = NULL;
+
+static vector<class devfreq *> all_devfreq;
+
+devfreq::devfreq(const char* dpath): device()
+{
+ pt_strcpy(dir_name, dpath);
+}
+
+uint64_t devfreq::parse_freq_time(char* pchr)
+{
+ char *cptr, *pptr = pchr;
+ uint64_t ctime;
+
+ cptr = strtok(pchr, " :");
+ while (cptr != NULL) {
+ cptr = strtok(NULL, " :");
+ if (cptr )
+ pptr = cptr;
+ }
+
+ ctime = strtoull(pptr, NULL, 10);
+ return ctime;
+}
+
+void devfreq::process_time_stamps()
+{
+ unsigned int i;
+ uint64_t active_time = 0;
+
+ sample_time = (1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec))
+ + ((stamp_after.tv_usec - stamp_before.tv_usec) );
+
+ for (i=0; i < dstates.size()-1; i++) {
+ struct frequency *state = dstates[i];
+ state->time_after = 1000 * (state->time_after - state->time_before);
+ active_time += state->time_after;
+ }
+ /* Compute idle time for the device */
+ dstates[i]->time_after = sample_time - active_time;
+}
+
+void devfreq::add_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ struct frequency *state;
+
+ state = new(std::nothrow) struct frequency;
+ if (!state)
+ return;
+
+ memset(state, 0, sizeof(*state));
+ dstates.push_back(state);
+
+ state->freq = freq;
+ if (freq == 0)
+ strcpy(state->human_name, "Idle");
+ else
+ hz_to_human(freq, state->human_name);
+ state->time_before = time;
+}
+
+void devfreq::update_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ unsigned int i;
+ struct frequency *state = NULL;
+
+ for(i=0; i < dstates.size(); i++) {
+ if (freq == dstates[i]->freq)
+ state = dstates[i];
+ }
+
+ if (state == NULL) {
+ add_devfreq_freq_state(freq, time);
+ return;
+ }
+
+ state->time_after = time;
+}
+
+void devfreq::parse_devfreq_trans_stat(char *dname)
+{
+ ifstream file;
+ char filename[256];
+
+ snprintf(filename, sizeof(filename), "/sys/class/devfreq/%s/trans_stat", dir_name);
+ file.open(filename);
+
+ if (!file)
+ return;
+
+ char line[1024];
+ char *c;
+
+ while (file) {
+ uint64_t freq;
+ uint64_t time;
+ char *pchr;
+
+ memset(line, 0, sizeof(line));
+ file.getline(line, sizeof(line));
+
+ pchr = strchr(line, '*');
+ pchr = (pchr != NULL) ? pchr+1 : line;
+
+ freq = strtoull(pchr, &c, 10);
+ if (!freq)
+ continue;
+
+ time = parse_freq_time(pchr);
+ update_devfreq_freq_state(freq, time);
+ }
+ file.close();
+}
+
+void devfreq::start_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i < dstates.size(); i++)
+ delete dstates[i];
+ dstates.resize(0);
+ sample_time = 0;
+
+ gettimeofday(&stamp_before, NULL);
+ parse_devfreq_trans_stat(dir_name);
+ /* add device idle state */
+ update_devfreq_freq_state(0, 0);
+}
+
+void devfreq::end_measurement(void)
+{
+ parse_devfreq_trans_stat(dir_name);
+ gettimeofday(&stamp_after, NULL);
+ process_time_stamps();
+}
+
+double devfreq::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ return 0;
+}
+
+double devfreq::utilization(void)
+{
+ return 0;
+}
+
+void devfreq::fill_freq_utilization(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ struct frequency *state = dstates[idx];
+ sprintf(buf, " %5.1f%% ", percentage(1.0 * state->time_after / sample_time));
+ }
+}
+
+void devfreq::fill_freq_name(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ sprintf(buf, "%-15s", dstates[idx]->human_name);
+ }
+}
+
+void start_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->start_measurement();
+}
+
+void end_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->end_measurement();
+}
+
+static void devfreq_dev_callback(const char *d_name)
+{
+ devfreq *df = new(std::nothrow) class devfreq(d_name);
+ if (df)
+ all_devfreq.push_back(df);
+}
+
+void create_all_devfreq_devices(void)
+{
+ int num = 0;
+
+ std::string p = "/sys/class/devfreq/";
+ dir = opendir(p.c_str());
+ if (dir == NULL) {
+ fprintf(stderr, "Devfreq not enabled\n");
+ is_enabled = false;
+ return;
+ }
+
+ while(readdir(dir) != NULL)
+ num++;
+
+ if (num == 2) {
+ fprintf(stderr, "Devfreq not enabled\n");
+ is_enabled = false;
+ closedir(dir);
+ dir = NULL;
+ return;
+ }
+
+ callback fn = &devfreq_dev_callback;
+ process_directory(p.c_str(), fn);
+}
+
+void initialize_devfreq(void)
+{
+ if (is_enabled)
+ create_tab("Device Freq stats", _("Device Freq stats"));
+}
+
+void display_devfreq_devices(void)
+{
+ unsigned int i, j;
+ WINDOW *win;
+ char fline[1024];
+ char buf[128];
+
+ win = get_ncurses_win("Device Freq stats");
+ if (!win)
+ return;
+
+ wclear(win);
+ wmove(win, 2,0);
+
+ if (!is_enabled) {
+ wprintw(win, _(" Devfreq is not enabled"));
+ return;
+ }
+
+ if (!all_devfreq.size()) {
+ wprintw(win, _(" No devfreq devices available"));
+ return;
+ }
+
+ for (i=0; i<all_devfreq.size(); i++) {
+
+ class devfreq *df = all_devfreq[i];
+ wprintw(win, "\n%s\n", df->device_name());
+
+ for(j=0; j < df->dstates.size(); j++) {
+ memset(fline, 0, sizeof(fline));
+ strcpy(fline, "\t");
+ df->fill_freq_name(j, buf);
+ strcat(fline, buf);
+ df->fill_freq_utilization(j, buf);
+ strcat(fline, buf);
+ strcat(fline, "\n");
+ wprintw(win, "%s", fline);
+ }
+ wprintw(win, "\n");
+ }
+}
+
+void report_devfreq_devices(void)
+{
+ if (!is_enabled) {
+ return;
+ }
+
+/* todo: adapt to new report format */
+
+}
+
+void clear_all_devfreq()
+{
+ unsigned int i, j;
+
+ for (i=0; i < all_devfreq.size(); i++) {
+ class devfreq *df = all_devfreq[i];
+
+ for(j=0; j < df->dstates.size(); j++)
+ delete df->dstates[j];
+
+ delete df;
+ }
+ all_devfreq.clear();
+ /* close /sys/class/devfreq */
+ if (dir != NULL) {
+ closedir(dir);
+ dir = NULL;
+ }
+}
diff --git a/src/devices/devfreq.h b/src/devices/devfreq.h
new file mode 100644
index 0000000..4a8983b
--- /dev/null
+++ b/src/devices/devfreq.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * 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:
+ * Rajagopal Venkat <rajagopal.venkat@linaro.org>
+ */
+#ifndef _INCLUDE_GUARD_DEVFREQ_H
+#define _INCLUDE_GUARD_DEVFREQ_H
+
+#include "device.h"
+#include "../parameters/parameters.h"
+#include <sys/time.h>
+
+struct frequency;
+
+class devfreq: public device {
+ char dir_name[128];
+ struct timeval stamp_before, stamp_after;
+ double sample_time;
+
+ uint64_t parse_freq_time(char *ptr);
+ void add_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void update_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void parse_devfreq_trans_stat(char *dname);
+ void process_time_stamps();
+
+public:
+
+ vector<struct frequency *> dstates;
+
+ devfreq(const char *c);
+ void fill_freq_utilization(unsigned int idx, char *buf);
+ void fill_freq_name(unsigned int idx, char *buf);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "devfreq";};
+
+ virtual const char * device_name(void) { return dir_name;};
+ virtual const char * human_name(void) { return "devfreq";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return " rpm"; };
+ virtual int power_valid(void) { return 0; /*utilization_power_valid(r_index);*/};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_all_devfreq_devices(void);
+extern void clear_all_devfreq(void);
+extern void display_devfreq_devices(void);
+extern void report_devfreq_devices(void);
+extern void initialize_devfreq(void);
+extern void start_devfreq_measurement(void);
+extern void end_devfreq_measurement(void);
+
+#endif
diff --git a/src/devices/device.cpp b/src/devices/device.cpp
new file mode 100644
index 0000000..f191072
--- /dev/null
+++ b/src/devices/device.cpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "device.h"
+#include <vector>
+#include <algorithm>
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+using namespace std;
+
+#include "backlight.h"
+#include "usb.h"
+#include "ahci.h"
+#include "alsa.h"
+#include "rfkill.h"
+#include "i915-gpu.h"
+#include "thinkpad-fan.h"
+#include "thinkpad-light.h"
+#include "network.h"
+#include "runtime_pm.h"
+
+#include "../parameters/parameters.h"
+#include "../display.h"
+#include "../lib.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+#include "../report/report-data-html.h"
+#include "../measurement/measurement.h"
+#include "../devlist.h"
+#include <unistd.h>
+
+device::device(void)
+{
+ cached_valid = 0;
+ hide = 0;
+
+ memset(guilty, 0, sizeof(guilty));
+ memset(real_path, 0, sizeof(real_path));
+}
+
+
+void device::register_sysfs_path(const char *path)
+{
+ char current_path[PATH_MAX + 1];
+ int iter = 0;
+ pt_strcpy(current_path, path);
+
+ while (iter++ < 10) {
+ char test_path[PATH_MAX + 1];
+ snprintf(test_path, sizeof(test_path), "%s/device", current_path);
+ if (access(test_path, R_OK) == 0)
+ strcpy(current_path, test_path);
+ else
+ break;
+ }
+
+ if (!realpath(current_path, real_path))
+ real_path[0] = 0;
+}
+
+void device::start_measurement(void)
+{
+ hide = false;
+}
+
+void device::end_measurement(void)
+{
+}
+
+double device::utilization(void)
+{
+ return 0.0;
+}
+
+
+
+vector<class device *> all_devices;
+
+
+void devices_start_measurement(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++)
+ all_devices[i]->start_measurement();
+}
+
+void devices_end_measurement(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++)
+ all_devices[i]->end_measurement();
+
+ clear_devpower();
+
+ for (i = 0; i < all_devices.size(); i++) {
+ all_devices[i]->hide = false;
+ all_devices[i]->register_power_with_devlist(&all_results, &all_parameters);
+ }
+}
+
+static bool power_device_sort(class device * i, class device * j)
+{
+ double pI, pJ;
+ pI = i->power_usage(&all_results, &all_parameters);
+ pJ = j->power_usage(&all_results, &all_parameters);
+
+ if (equals(pI, pJ)) {
+ int vI, vJ;
+ vI = i->power_valid();
+ vJ = j->power_valid();
+
+ if (vI != vJ)
+ return vI > vJ;
+
+ return i->utilization() > j->utilization();
+ }
+ return pI > pJ;
+}
+
+
+void report_devices(void)
+{
+ WINDOW *win;
+ unsigned int i;
+ int show_power;
+ double pw;
+
+ char util[128];
+ char power[128];
+
+ win = get_ncurses_win("Device stats");
+ if (!win)
+ return;
+
+ show_power = global_power_valid();
+
+ wclear(win);
+ wmove(win, 2,0);
+
+ sort(all_devices.begin(), all_devices.end(), power_device_sort);
+
+
+
+ pw = global_power();
+ if (pw > 0.0001) {
+ char buf[32];
+ wprintw(win, _("The battery reports a discharge rate of %sW\n"),
+ fmt_prefix(pw, buf));
+ wprintw(win, _("The energy consumed was %sJ\n"),
+ fmt_prefix(global_joules(), buf));
+ }
+
+ if (show_power) {
+ char buf[32];
+ wprintw(win, _("System baseline power is estimated at %sW\n"),
+ fmt_prefix(get_parameter_value("base power"), buf));
+ }
+
+ if (pw > 0.0001 || show_power)
+ wprintw(win, "\n");
+ if (show_power)
+ wprintw(win, _("Power est. Usage Device name\n"));
+ else
+ wprintw(win, _(" Usage Device name\n"));
+
+ for (i = 0; i < all_devices.size(); i++) {
+ double P;
+
+ util[0] = 0;
+
+ if (all_devices[i]->util_units()) {
+ if (all_devices[i]->utilization() < 1000)
+ sprintf(util, "%5.1f%s", all_devices[i]->utilization(), all_devices[i]->util_units());
+ else
+ sprintf(util, "%5i%s", (int)all_devices[i]->utilization(), all_devices[i]->util_units());
+ }
+ while (strlen(util) < 13) strcat(util, " ");
+
+ P = all_devices[i]->power_usage(&all_results, &all_parameters);
+
+ format_watts(P, power, 11);
+
+ if (!show_power || !all_devices[i]->power_valid())
+ strcpy(power, " ");
+
+
+ wprintw(win, "%s %s %s\n",
+ power,
+ util,
+ all_devices[i]->human_name()
+ );
+ }
+}
+
+void show_report_devices(void)
+{
+ unsigned int i;
+ int show_power, cols, rows, idx;
+ double pw;
+
+ show_power = global_power_valid();
+ sort(all_devices.begin(), all_devices.end(), power_device_sort);
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "devinfo");
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes std_table_css;
+ cols=2;
+ if (show_power)
+ cols=3;
+
+ idx = cols;
+ rows= all_devices.size() + 1;
+ init_std_side_table_attr(&std_table_css, rows, cols);
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Add section */
+ report.add_div(&div_attr);
+
+ /* Device Summary */
+ int summary_size=2;
+ string *summary = new string[summary_size];
+ pw = global_power();
+ char buf[32];
+ if (pw > 0.0001) {
+ summary[0]= __("The battery reports a discharge rate of: ");
+ summary[1]=string(fmt_prefix(pw, buf));
+ summary[1].append(" W");
+ report.add_summary_list(summary, summary_size);
+
+ summary[0]= __("The energy consumed was : ");
+ summary[1]=string(fmt_prefix(global_joules(), buf));
+ summary[1].append(" J");
+ report.add_summary_list(summary, summary_size);
+ }
+
+ if (show_power) {
+ summary[0]=__("The system baseline power is estimated at: ");
+ summary[1]=string(fmt_prefix(get_parameter_value("base power"), buf));
+ summary[1].append(" W");
+ report.add_summary_list(summary, summary_size);
+ }
+ delete [] summary;
+
+ /* Set array of data in row Major order */
+ string *device_data = new string[cols * rows];
+ device_data[0]= __("Usage");
+ device_data[1]= __("Device Name");
+ if (show_power)
+ device_data[2]= __("PW Estimate");
+
+ for (i = 0; i < all_devices.size(); i++) {
+ double P;
+ char util[128];
+ char power[128];
+
+ util[0] = 0;
+ if (all_devices[i]->util_units()) {
+ if (all_devices[i]->utilization() < 1000)
+ sprintf(util, "%5.1f%s",
+ all_devices[i]->utilization(),
+ all_devices[i]->util_units());
+ else
+ sprintf(util, "%5i%s",
+ (int)all_devices[i]->utilization(),
+ all_devices[i]->util_units());
+ }
+
+ P = all_devices[i]->power_usage(&all_results, &all_parameters);
+ format_watts(P, power, 11);
+
+ if (!show_power || !all_devices[i]->power_valid())
+ strcpy(power, " ");
+
+ device_data[idx]= string(util);
+ idx+=1;
+
+ device_data[idx]= string(all_devices[i]->human_name());
+ idx+=1;
+
+ if (show_power) {
+ device_data[idx]= string(power);
+ idx+=1;
+ }
+ }
+ /* Report Output */
+ report.add_title(&title_attr, __("Device Power Report"));
+ report.add_table(device_data, &std_table_css);
+ delete [] device_data;
+}
+
+
+void create_all_devices(void)
+{
+ create_all_backlights();
+ create_all_usb_devices();
+ create_all_ahcis();
+ create_all_alsa();
+ create_all_rfkills();
+ create_i915_gpu();
+ create_thinkpad_fan();
+ create_thinkpad_light();
+ create_all_nics();
+ create_all_runtime_pm_devices();
+}
+
+
+void clear_all_devices(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++) {
+ delete all_devices[i];
+ }
+ all_devices.clear();
+}
diff --git a/src/devices/device.h b/src/devices/device.h
new file mode 100644
index 0000000..a373875
--- /dev/null
+++ b/src/devices/device.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_DEVICE_H
+#define _INCLUDE_GUARD_DEVICE_H
+
+
+#include <vector>
+#include <limits.h>
+
+struct parameter_bundle;
+struct result_bundle;
+
+class device {
+public:
+ int cached_valid;
+ bool hide;
+
+ char guilty[4096];
+ char real_path[PATH_MAX+1];
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ device(void);
+
+ virtual ~device() {};
+
+ void register_sysfs_path(const char *path);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * util_units(void) { return "%"; };
+
+ virtual const char * class_name(void) { return "abstract device";};
+ virtual const char * device_name(void) { return "abstract device";};
+
+ virtual const char * human_name(void) { return device_name(); };
+
+ virtual double power_usage(struct result_bundle *results, struct parameter_bundle *bundle) { return 0.0; };
+
+ virtual bool show_in_list(void) {return !hide;};
+
+ virtual int power_valid(void) { return 1;};
+
+ virtual void register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle) { ; };
+
+ virtual int grouping_prio(void) { return 0; }; /* priority of this device class if multiple classes match to the same underlying device. 0 is lowest */
+};
+
+using namespace std;
+
+extern vector<class device *> all_devices;
+
+extern void devices_start_measurement(void);
+extern void devices_end_measurement(void);
+extern void show_report_devices(void);
+extern void report_devices(void);
+
+
+extern void create_all_devices(void);
+extern void clear_all_devices(void);
+
+#endif
diff --git a/src/devices/gpu_rapl_device.cpp b/src/devices/gpu_rapl_device.cpp
new file mode 100644
index 0000000..71d71a0
--- /dev/null
+++ b/src/devices/gpu_rapl_device.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010, 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:
+ * Srinivas Pandruvada<Srinivas.Pandruvada@linux.intel.com>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "../parameters/parameters.h"
+#include "gpu_rapl_device.h"
+
+gpu_rapl_device::gpu_rapl_device(i915gpu *parent)
+ : i915gpu(),
+ device_valid(false)
+{
+ last_time = time(NULL);
+ if (rapl.pp1_domain_present()) {
+ device_valid = true;
+ parent->add_child(this);
+ rapl.get_pp1_energy_status(&last_energy);
+ }
+}
+
+void gpu_rapl_device::start_measurement(void)
+{
+ last_time = time(NULL);
+
+ rapl.get_pp1_energy_status(&last_energy);
+}
+
+void gpu_rapl_device::end_measurement(void)
+{
+ time_t curr_time = time(NULL);
+ double energy;
+
+ consumed_power = 0.0;
+ if ((curr_time - last_time) > 0) {
+ rapl.get_pp1_energy_status(&energy);
+ consumed_power = (energy-last_energy)/(curr_time-last_time);
+ last_energy = energy;
+ last_time = curr_time;
+ }
+}
+
+double gpu_rapl_device::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ if (rapl.pp1_domain_present())
+ return consumed_power;
+ else
+ return 0.0;
+}
diff --git a/src/devices/gpu_rapl_device.h b/src/devices/gpu_rapl_device.h
new file mode 100644
index 0000000..fbde246
--- /dev/null
+++ b/src/devices/gpu_rapl_device.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010, 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:
+ * Srinivas Pandruvada <Srinivas.Pandruvada@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_GPU_RAPL_DEVICE_H
+#define _INCLUDE_GUARD_GPU_RAPL_DEVICE_H
+
+#include <vector>
+#include <string>
+
+using namespace std;
+
+#include <sys/time.h>
+#include "i915-gpu.h"
+#include "cpu/rapl/rapl_interface.h"
+
+class gpu_rapl_device: public i915gpu {
+
+ c_rapl_interface rapl;
+ time_t last_time;
+ double last_energy;
+ double consumed_power;
+ bool device_valid;
+
+public:
+ gpu_rapl_device(i915gpu *parent);
+ virtual const char * class_name(void) { return "GPU core";};
+ virtual const char * device_name(void) { return "GPU core";};
+ bool device_present() { return device_valid;}
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+};
+
+
+#endif
diff --git a/src/devices/i915-gpu.cpp b/src/devices/i915-gpu.cpp
new file mode 100644
index 0000000..d0f1d69
--- /dev/null
+++ b/src/devices/i915-gpu.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <limits.h>
+#include "../lib.h"
+
+using namespace std;
+
+#include "device.h"
+#include "i915-gpu.h"
+#include "../parameters/parameters.h"
+#include "../process/powerconsumer.h"
+#include "gpu_rapl_device.h"
+
+#include <string.h>
+#include <unistd.h>
+
+i915gpu::i915gpu(): device()
+{
+ index = get_param_index("gpu-operations");
+ rindex = get_result_index("gpu-operations");
+}
+
+const char * i915gpu::device_name(void)
+{
+ if (child_devices.size())
+ return "GPU misc";
+ else
+ return "GPU";
+}
+
+void i915gpu::start_measurement(void)
+{
+}
+
+void i915gpu::end_measurement(void)
+{
+}
+
+
+double i915gpu::utilization(void)
+{
+ return get_result_value(rindex);
+
+}
+
+void create_i915_gpu(void)
+{
+ char filename[PATH_MAX];
+ class i915gpu *gpu;
+ gpu_rapl_device *rapl_dev;
+
+ pt_strcpy(filename, "/sys/kernel/debug/tracing/events/i915/i915_gem_ring_dispatch/format");
+
+ if (access(filename, R_OK) !=0) {
+ /* try an older tracepoint */
+ pt_strcpy(filename, "/sys/kernel/debug/tracing/events/i915/i915_gem_request_submit/format");
+ if (access(filename, R_OK) != 0)
+ return;
+ }
+
+ register_parameter("gpu-operations");
+
+ gpu = new class i915gpu();
+ all_devices.push_back(gpu);
+
+ rapl_dev = new class gpu_rapl_device(gpu);
+ if (rapl_dev->device_present())
+ all_devices.push_back(rapl_dev);
+}
+
+
+
+double i915gpu::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+ double child_power;
+
+ power = 0;
+ factor = get_parameter_value(index, bundle);
+ util = get_result_value(rindex, result);
+
+ power += util * factor / 100.0;
+ for (unsigned int i = 0; i < child_devices.size(); ++i) {
+ child_power = child_devices[i]->power_usage(result, bundle);
+ if ((power - child_power) > 0.0)
+ power -= child_power;
+ }
+
+ return power;
+}
diff --git a/src/devices/i915-gpu.h b/src/devices/i915-gpu.h
new file mode 100644
index 0000000..7653b94
--- /dev/null
+++ b/src/devices/i915-gpu.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_i915_GPU_H
+#define _INCLUDE_GUARD_i915_GPU_H
+
+
+#include "device.h"
+
+class i915gpu: public device {
+ int index;
+ int rindex;
+ vector<device *>child_devices;
+
+public:
+
+ i915gpu();
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "GPU";};
+
+ virtual const char * device_name(void);
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual bool show_in_list(void) {return false;};
+ virtual const char * util_units(void) { return " ops/s"; };
+
+ virtual void add_child(device *dev_ptr) { child_devices.push_back(dev_ptr);}
+};
+
+extern void create_i915_gpu(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/network.cpp b/src/devices/network.cpp
new file mode 100644
index 0000000..8087b7f
--- /dev/null
+++ b/src/devices/network.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+#include <map>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <linux/ethtool.h>
+
+using namespace std;
+
+#include "device.h"
+#include "network.h"
+#include "../lib.h"
+#include "../parameters/parameters.h"
+#include "../process/process.h"
+extern "C" {
+#include "../tuning/iw.h"
+}
+
+#include <string.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+static map<string, class network *> nics;
+
+#ifdef DISABLE_TRYCATCH
+
+static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
+ __u32 speed)
+{
+
+ ep->speed = (__u16)speed;
+ ep->speed_hi = (__u16)(speed >> 16);
+}
+
+static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep)
+{
+ return (ep->speed_hi << 16) | ep->speed;
+}
+
+#endif
+
+static void do_proc_net_dev(void)
+{
+ static time_t last_time;
+ class network *dev;
+ ifstream file;
+ char line[4096];
+ char *c, *c2;
+
+ if (time(NULL) == last_time)
+ return;
+
+ last_time = time(NULL);
+
+ file.open("/proc/net/dev", ios::in);
+ if (!file)
+ return;
+
+ file.getline(line, 4096);
+ file.getline(line, 4096);
+
+ while (file) {
+ int i = 0;
+ unsigned long val = 0;
+ uint64_t pkt = 0;
+ file.getline(line, 4096);
+ c = strchr(line, ':');
+ if (!c)
+ continue;
+ *c = 0;
+ c2 = c +1;
+ c = line; while (c && *c == ' ') c++;
+ /* c now points to the name of the nic */
+
+ dev = nics[c];
+ if (!dev)
+ continue;
+
+ c = c2++;
+ while (c != c2 && strlen(c) > 0) {
+ c2 = c;
+ val = strtoull(c, &c, 10);
+ i++;
+ if (i == 2 || i == 10)
+ pkt += val;
+
+ }
+ dev->pkts = pkt;
+ }
+ file.close();
+}
+
+
+network::network(const char *_name, const char *path): device()
+{
+ char line[4096];
+ std::string filename(path);
+ char devname[128];
+ start_up = 0;
+ end_up = 0;
+ start_speed = 0;
+ end_speed = 0;
+ start_pkts = 0;
+ end_pkts = 0;
+ pkts = 0;
+ valid_100 = -1;
+ valid_1000 = -1;
+ valid_high = -1;
+ valid_powerunsave = -1;
+
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ pt_strcpy(devname, _name);
+ sprintf(humanname, "nic:%s", _name);
+ pt_strcpy(name, devname);
+
+ snprintf(devname, sizeof(devname), "%s-up", _name);
+ index_up = get_param_index(devname);
+ rindex_up = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-powerunsave", _name);
+ index_powerunsave = get_param_index(devname);
+ rindex_powerunsave = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-100", _name);
+ index_link_100 = get_param_index(devname);
+ rindex_link_100 = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-1000", _name);
+ index_link_1000 = get_param_index(devname);
+ rindex_link_1000 = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-high", _name);
+ index_link_high = get_param_index(devname);
+ rindex_link_high = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-packets", _name);
+ index_pkts = get_param_index(devname);
+ rindex_pkts = get_result_index(devname);
+
+ memset(line, 0, 4096);
+ filename.append("/device/driver");
+ if (readlink(filename.c_str(), line, 4096) > 0) {
+ snprintf(humanname, sizeof(humanname), _("Network interface: %s (%s)"), _name, basename(line));
+ };
+}
+
+static int net_iface_up(const char *iface)
+{
+ int sock;
+ struct ifreq ifr;
+ int ret;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock<0)
+ return 0;
+
+ pt_strcpy(ifr.ifr_name, iface);
+
+ /* Check if the interface is up */
+ ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
+ if (ret<0) {
+ close(sock);
+ return 0;
+ }
+
+ if (ifr.ifr_flags & (IFF_UP | IFF_RUNNING)) {
+ close(sock);
+ return 1;
+ }
+
+ close(sock);
+
+ return 0;
+}
+
+static int iface_link(const char *name)
+{
+ int sock;
+ struct ifreq ifr;
+ struct ethtool_value cmd;
+ int link;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock<0)
+ return 0;
+
+ pt_strcpy(ifr.ifr_name, name);
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.cmd = ETHTOOL_GLINK;
+ ifr.ifr_data = (caddr_t)&cmd;
+ ioctl(sock, SIOCETHTOOL, &ifr);
+ close(sock);
+
+ link = cmd.data;
+
+ return link;
+}
+
+
+static int iface_speed(const char *name)
+{
+ int sock;
+ struct ifreq ifr;
+ struct ethtool_cmd cmd;
+ int speed;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock<0)
+ return 0;
+
+ pt_strcpy(ifr.ifr_name, name);
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.cmd = ETHTOOL_GSET;
+ ifr.ifr_data = (caddr_t)&cmd;
+ ioctl(sock, SIOCETHTOOL, &ifr);
+ close(sock);
+
+ speed = ethtool_cmd_speed(&cmd);
+
+
+ if (speed > 0 && speed <= 100)
+ speed = 100;
+ if (speed > 100 && speed <= 1000)
+ speed = 1000;
+ if (speed == 65535 || !iface_link(name))
+ speed = 0; /* no link */
+
+ return speed;
+}
+
+void network::start_measurement(void)
+{
+ start_up = 1;
+ start_speed = 0;
+ end_up = 1;
+ end_speed = 0;
+
+ start_speed = iface_speed(name);
+
+ start_up = net_iface_up(name);
+
+ do_proc_net_dev();
+ start_pkts = pkts;
+
+ gettimeofday(&before, NULL);
+}
+
+
+void network::end_measurement(void)
+{
+ int u_100, u_1000, u_high, u_powerunsave;
+
+ gettimeofday(&after, NULL);
+
+ end_speed = iface_speed(name);
+ end_up = net_iface_up(name);
+ do_proc_net_dev();
+ end_pkts = pkts;
+
+ duration = (after.tv_sec - before.tv_sec) + (after.tv_usec - before.tv_usec) / 1000000.0;
+
+ u_100 = 0;
+ u_1000 = 0;
+ u_high = 0;
+
+ if (start_speed == 100)
+ u_100 += 50;
+ if (start_speed == 1000)
+ u_1000 += 50;
+ if (start_speed > 1000)
+ u_high += 50;
+ if (end_speed == 100)
+ u_100 += 50;
+ if (end_speed == 1000)
+ u_1000 += 50;
+ if (end_speed > 1000)
+ u_high += 50;
+
+ if (start_pkts > end_pkts)
+ end_pkts = start_pkts;
+
+ u_powerunsave = 100 - 100 * get_wifi_power_saving(name);
+
+ report_utilization(rindex_link_100, u_100);
+ report_utilization(rindex_link_1000, u_1000);
+ report_utilization(rindex_link_high, u_high);
+ report_utilization(rindex_up, (start_up+end_up) / 2.0);
+ report_utilization(rindex_pkts, (end_pkts - start_pkts)/(duration + 0.001));
+ report_utilization(rindex_powerunsave, u_powerunsave);
+}
+
+
+double network::utilization(void)
+{
+ return (end_pkts - start_pkts) / (duration + 0.001);
+}
+
+const char * network::device_name(void)
+{
+ return name;
+}
+
+static void netdev_callback(const char *d_name)
+{
+ char devname[128];
+
+ std::string f_name("/sys/class/net/");
+ if (strcmp(d_name, "lo") == 0)
+ return;
+
+ f_name.append(d_name);
+
+ snprintf(devname, sizeof(devname), "%s-up", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-powerunsave", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-100", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-1000", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-high", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-packets", d_name);
+ register_parameter(devname);
+
+ network *bl = new(std::nothrow) class network(d_name, f_name.c_str());
+ if (bl) {
+ all_devices.push_back(bl);
+ nics[d_name] = bl;
+ }
+}
+
+void create_all_nics(callback fn)
+{
+ if (!fn)
+ fn = &netdev_callback;
+ process_directory("/sys/class/net/", fn);
+}
+
+double network::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ power = 0;
+ factor = get_parameter_value(index_up, bundle);
+ util = get_result_value(rindex_up, result);
+
+ power += util * factor;
+
+ if (valid_100 == -1) {
+ valid_100 = utilization_power_valid(rindex_link_100);
+ valid_1000 = utilization_power_valid(rindex_link_1000);
+ valid_high = utilization_power_valid(rindex_link_high);
+ valid_powerunsave = utilization_power_valid(rindex_powerunsave);
+ }
+
+ if (valid_100 > 0) {
+ factor = get_parameter_value(index_link_100, bundle);
+ util = get_result_value(rindex_link_100, result);
+ power += util * factor / 100;
+ }
+
+
+ if (valid_1000 > 0) {
+ factor = get_parameter_value(index_link_1000, bundle);
+ util = get_result_value(rindex_link_1000, result);
+ power += util * factor / 100;
+ }
+
+ if (valid_high > 0) {
+ factor = get_parameter_value(index_link_high, bundle);
+ util = get_result_value(rindex_link_high, result);
+ power += util * factor / 100;
+ }
+
+ if (valid_powerunsave > 0) {
+ factor = get_parameter_value(index_powerunsave, bundle);
+ util = get_result_value(rindex_powerunsave, result);
+ power += util * factor / 100;
+ }
+
+ factor = get_parameter_value(index_pkts, bundle);
+ util = get_result_value(rindex_pkts, result);
+ if (util > 5000)
+ util = 5000;
+
+ power += util * factor / 100;
+
+ return power;
+}
diff --git a/src/devices/network.h b/src/devices/network.h
new file mode 100644
index 0000000..7fb4cc6
--- /dev/null
+++ b/src/devices/network.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_NETWORK_H
+#define _INCLUDE_GUARD_NETWORK_H
+
+#include <sys/time.h>
+#include <limits.h>
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class network: public device {
+ int start_up, end_up;
+ uint64_t start_pkts, end_pkts;
+ struct timeval before, after;
+
+ int start_speed; /* 0 is "no link" */
+ int end_speed; /* 0 is "no link" */
+
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char humanname[4096];
+ int index_up;
+ int rindex_up;
+ int index_link_100;
+ int rindex_link_100;
+ int index_link_1000;
+ int rindex_link_1000;
+ int index_link_high;
+ int rindex_link_high;
+ int index_pkts;
+ int rindex_pkts;
+ int index_powerunsave;
+ int rindex_powerunsave;
+
+ int valid_100;
+ int valid_1000;
+ int valid_high;
+ int valid_powerunsave;
+public:
+ uint64_t pkts;
+ double duration;
+
+ network(const char *_name, const char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void);
+ virtual const char * util_units(void) { return " pkts/s"; };
+
+ virtual const char * class_name(void) { return "ethernet";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void) { return humanname; };
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(rindex_up) + utilization_power_valid(rindex_link_100) + utilization_power_valid(rindex_link_1000) + utilization_power_valid(rindex_link_high);};
+ virtual int grouping_prio(void) { return 10; };
+};
+
+extern void create_all_nics(callback fn = NULL);
+
+#endif
diff --git a/src/devices/rfkill.cpp b/src/devices/rfkill.cpp
new file mode 100644
index 0000000..99a652f
--- /dev/null
+++ b/src/devices/rfkill.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <limits.h>
+
+
+using namespace std;
+
+#include "device.h"
+#include "rfkill.h"
+#include "../parameters/parameters.h"
+
+#include <string.h>
+#include <unistd.h>
+
+rfkill::rfkill(char *_name, char *path): device()
+{
+ char line[4096];
+ char filename[PATH_MAX];
+ char devname[128];
+ start_soft = 0;
+ start_hard = 0;
+ end_soft = 0;
+ end_hard = 0;
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ snprintf(devname, sizeof(devname), "radio:%s", _name);
+ snprintf(humanname, sizeof(humanname), "radio:%s", _name);
+ pt_strcpy(name, devname);
+ register_parameter(devname);
+ index = get_param_index(devname);
+ rindex = get_result_index(name);
+
+ memset(line, 0, 4096);
+ snprintf(filename, sizeof(filename), "%s/device/driver", path);
+ if (readlink(filename, line, sizeof(line)) > 0) {
+ snprintf(humanname, sizeof(humanname), _("Radio device: %s"), basename(line));
+ }
+ snprintf(filename, sizeof(filename), "%s/device/device/driver", path);
+ if (readlink(filename, line, sizeof(line)) > 0) {
+ snprintf(humanname, sizeof(humanname), _("Radio device: %s"), basename(line));
+ }
+}
+
+void rfkill::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ start_hard = 1;
+ start_soft = 1;
+ end_hard = 1;
+ end_soft = 1;
+
+ snprintf(filename, sizeof(filename), "%s/hard", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_hard;
+ }
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/soft", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_soft;
+ }
+ file.close();
+}
+
+void rfkill::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/hard", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_hard;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/soft", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_soft;
+ }
+ file.close();
+
+ report_utilization(name, utilization());
+}
+
+
+double rfkill::utilization(void)
+{
+ double p;
+ int rfk;
+
+ rfk = start_soft+end_soft;
+ if (rfk < start_hard+end_hard)
+ rfk = start_hard+end_hard;
+
+ p = 100 - 50.0 * rfk;
+
+ return p;
+}
+
+const char * rfkill::device_name(void)
+{
+ return name;
+}
+
+static void create_all_rfkills_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ char name[4096] = {0};
+ class rfkill *bl;
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "/sys/class/rfkill/%s/name", d_name);
+ strncpy(name, d_name, sizeof(name) - 1);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(name, 100);
+ file.close();
+ }
+
+ snprintf(filename, sizeof(filename), "/sys/class/rfkill/%s", d_name);
+ bl = new class rfkill(name, filename);
+ all_devices.push_back(bl);
+}
+
+void create_all_rfkills(void)
+{
+ process_directory("/sys/class/rfkill/", create_all_rfkills_callback);
+}
+
+double rfkill::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ power = 0;
+ factor = get_parameter_value(index, bundle);
+ util = get_result_value(rindex, result);
+
+ power += util * factor / 100.0;
+
+ return power;
+}
diff --git a/src/devices/rfkill.h b/src/devices/rfkill.h
new file mode 100644
index 0000000..429ba18
--- /dev/null
+++ b/src/devices/rfkill.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_RFKILL_H
+#define _INCLUDE_GUARD_RFKILL_H
+
+#include <limits.h>
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class rfkill: public device {
+ int start_soft, end_soft;
+ int start_hard, end_hard;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char humanname[4096];
+ int index;
+ int rindex;
+public:
+
+ rfkill(char *_name, char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "radio";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void) { return humanname; };
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(rindex);};
+ virtual int grouping_prio(void) { return 5; };
+};
+
+extern void create_all_rfkills(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/runtime_pm.cpp b/src/devices/runtime_pm.cpp
new file mode 100644
index 0000000..26f9d32
--- /dev/null
+++ b/src/devices/runtime_pm.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "runtime_pm.h"
+
+#include <string.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+#include "../parameters/parameters.h"
+#include "../lib.h"
+
+#include <iostream>
+#include <fstream>
+
+runtime_pmdevice::runtime_pmdevice(const char *_name, const char *path) : device()
+{
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ pt_strcpy(name, _name);
+ snprintf(humanname, sizeof(humanname), "runtime-%s", _name);
+
+ index = get_param_index(humanname);
+ r_index = get_result_index(humanname);
+
+ before_suspended_time = 0;
+ before_active_time = 0;
+ after_suspended_time = 0;
+ after_active_time = 0;
+
+ register_parameter(humanname);
+}
+
+void runtime_pmdevice::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ before_suspended_time = 0;
+ before_active_time = 0;
+ after_suspended_time = 0;
+ after_active_time = 0;
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_suspended_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file >> before_suspended_time;
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_active_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file >> before_active_time;
+ file.close();
+}
+
+void runtime_pmdevice::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_suspended_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file >> after_suspended_time;
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_active_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file >> after_active_time;
+ file.close();
+}
+
+double runtime_pmdevice::utilization(void) /* percentage */
+{
+ double d;
+ d = 100 * (after_active_time - before_active_time) / (0.0001 + after_active_time - before_active_time + after_suspended_time - before_suspended_time);
+
+ if (d < 0.00)
+ d = 0.0;
+ if (d > 99.9)
+ d = 100.0;
+ return d;
+}
+
+const char * runtime_pmdevice::device_name(void)
+{
+ return name;
+}
+
+const char * runtime_pmdevice::human_name(void)
+{
+ return humanname;
+}
+
+
+double runtime_pmdevice::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ power = 0;
+
+ factor = get_parameter_value(index, bundle);
+ util = get_result_value(r_index, result);
+ power += util * factor / 100.0;
+
+ return power;
+}
+
+void runtime_pmdevice::set_human_name(char *_name)
+{
+ pt_strcpy(humanname, _name);
+}
+
+
+int device_has_runtime_pm(const char *sysfs_path)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+ unsigned long value;
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_suspended_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return 0;
+ file >> value;
+ file.close();
+ if (value)
+ return 1;
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_active_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return 0;
+ file >> value;
+ file.close();
+ if (value)
+ return 1;
+
+ return 0;
+}
+
+static void do_bus(const char *bus)
+{
+ /* /sys/bus/pci/devices/0000\:00\:1f.0/power/runtime_suspended_time */
+
+ struct dirent *entry;
+ DIR *dir;
+ char filename[PATH_MAX];
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/", bus);
+ dir = opendir(filename);
+ if (!dir)
+ return;
+ while (1) {
+ ifstream file;
+ class runtime_pmdevice *dev;
+ entry = readdir(dir);
+
+ if (!entry)
+ break;
+ if (entry->d_name[0] == '.')
+ continue;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s", bus, entry->d_name);
+ dev = new class runtime_pmdevice(entry->d_name, filename);
+
+ if (strcmp(bus, "i2c") == 0) {
+ string devname;
+ char dev_name[4096];
+ bool is_adapter = false;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/new_device", bus, entry->d_name);
+ if (access(filename, W_OK) == 0)
+ is_adapter = true;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/name", bus, entry->d_name);
+ file.open(filename, ios::in);
+ if (file) {
+ getline(file, devname);
+ file.close();
+ }
+
+ snprintf(dev_name, sizeof(dev_name), _("I2C %s (%s): %s"), (is_adapter ? _("Adapter") : _("Device")), entry->d_name, devname.c_str());
+ dev->set_human_name(dev_name);
+ }
+
+ if (strcmp(bus, "pci") == 0) {
+ uint16_t vendor = 0, device = 0;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/vendor", bus, entry->d_name);
+
+ file.open(filename, ios::in);
+ if (file) {
+ file >> hex >> vendor;
+ file.close();
+ }
+
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/device", bus, entry->d_name);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> hex >> device;
+ file.close();
+ }
+
+ if (vendor && device) {
+ char devname[4096];
+ snprintf(devname, sizeof(devname), _("PCI Device: %s"),
+ pci_id_to_name(vendor, device, filename, 4095));
+ dev->set_human_name(devname);
+ }
+ }
+ all_devices.push_back(dev);
+ }
+ closedir(dir);
+}
+
+void create_all_runtime_pm_devices(void)
+{
+ do_bus("pci");
+ do_bus("spi");
+ do_bus("platform");
+ do_bus("i2c");
+}
diff --git a/src/devices/runtime_pm.h b/src/devices/runtime_pm.h
new file mode 100644
index 0000000..77bf398
--- /dev/null
+++ b/src/devices/runtime_pm.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_RUNTIMEPM_H
+#define _INCLUDE_GUARD_RUNTIMEPM_H
+
+#include <limits.h>
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class runtime_pmdevice: public device {
+ uint64_t before_suspended_time, before_active_time;
+ uint64_t after_suspended_time, after_active_time;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char humanname[4096];
+ int index;
+ int r_index;
+public:
+
+ runtime_pmdevice(const char *_name, const char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "runtime_pm";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void);
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(r_index);};
+
+ void set_human_name(char *name);
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_all_runtime_pm_devices(void);
+
+extern int device_has_runtime_pm(const char *sysfs_path);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/thinkpad-fan.cpp b/src/devices/thinkpad-fan.cpp
new file mode 100644
index 0000000..8e2ce53
--- /dev/null
+++ b/src/devices/thinkpad-fan.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <math.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "../lib.h"
+
+
+#include "device.h"
+#include "thinkpad-fan.h"
+#include "../parameters/parameters.h"
+#include "../process/powerconsumer.h"
+
+#include <string.h>
+#include <unistd.h>
+
+thinkpad_fan::thinkpad_fan(): device()
+{
+ start_rate = 0;
+ end_rate = 0;
+ fan_index = get_param_index("thinkpad-fan");
+ fansqr_index = get_param_index("thinkpad-fan-sqr");
+ fancub_index = get_param_index("thinkpad-fan-cub");
+ r_index = get_result_index("thinkpad-fan");
+ register_sysfs_path("/sys/devices/platform/thinkpad_hwmon");
+}
+
+void thinkpad_fan::start_measurement(void)
+{
+ /* read the rpms of the fan */
+ start_rate = read_sysfs("/sys/devices/platform/thinkpad_hwmon/fan1_input");
+}
+
+void thinkpad_fan::end_measurement(void)
+{
+ end_rate = read_sysfs("/sys/devices/platform/thinkpad_hwmon/fan1_input");
+
+ report_utilization("thinkpad-fan", utilization());
+}
+
+
+double thinkpad_fan::utilization(void)
+{
+ return (start_rate+end_rate) / 2;
+}
+
+void create_thinkpad_fan(void)
+{
+ char filename[PATH_MAX];
+ class thinkpad_fan *fan;
+
+ pt_strcpy(filename, "/sys/devices/platform/thinkpad_hwmon/fan1_input");
+
+ if (access(filename, R_OK) !=0)
+ return;
+
+ register_parameter("thinkpad-fan", 10);
+ register_parameter("thinkpad-fan-sqr", 5);
+ register_parameter("thinkpad-fan-cub", 10);
+
+ fan = new class thinkpad_fan();
+ all_devices.push_back(fan);
+}
+
+
+
+double thinkpad_fan::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+
+ power = 0;
+ util = get_result_value(r_index, result);
+
+ if (util < 0)
+ util = 0;
+
+
+ /* physics dictact that fan power goes cubic with the rpms, but there's also a linear component for friction*/
+ factor = get_parameter_value(fancub_index, bundle);
+ power += factor * pow(util / 3600.0, 3);
+
+ factor = get_parameter_value(fansqr_index, bundle) - 5.0;
+ power += factor * pow(util / 3600.0, 2);
+
+ factor = get_parameter_value(fan_index, bundle) - 10.0;
+ power += util / 5000.0 * factor;
+
+ if (power <= 0.0)
+ power = 0.0;
+
+ return power;
+}
diff --git a/src/devices/thinkpad-fan.h b/src/devices/thinkpad-fan.h
new file mode 100644
index 0000000..34c4c43
--- /dev/null
+++ b/src/devices/thinkpad-fan.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_THINKPAD_FAN_H
+#define _INCLUDE_GUARD_THINKPAD_FAN_H
+
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class thinkpad_fan: public device {
+ double start_rate, end_rate;
+ int fan_index, fansqr_index, fancub_index;
+ int r_index;
+public:
+
+ thinkpad_fan();
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "fan";};
+
+ virtual const char * device_name(void) { return "Fan-1";};
+ virtual const char * human_name(void) { return "Laptop fan";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return " rpm"; };
+ virtual int power_valid(void) { return utilization_power_valid(r_index);};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_thinkpad_fan(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/thinkpad-light.cpp b/src/devices/thinkpad-light.cpp
new file mode 100644
index 0000000..d047ab3
--- /dev/null
+++ b/src/devices/thinkpad-light.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <math.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "../lib.h"
+
+
+#include "device.h"
+#include "thinkpad-light.h"
+#include "../parameters/parameters.h"
+#include "../process/powerconsumer.h"
+
+#include <string.h>
+#include <unistd.h>
+
+thinkpad_light::thinkpad_light(): device()
+{
+ start_rate = 0;
+ end_rate = 0;
+ light_index = get_param_index("thinkpad-light");
+ r_index = get_result_index("thinkpad-light");
+ register_sysfs_path("/sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight");
+}
+
+void thinkpad_light::start_measurement(void)
+{
+ /* read the rpms of the light */
+ start_rate = read_sysfs("/sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness");
+}
+
+void thinkpad_light::end_measurement(void)
+{
+ end_rate = read_sysfs("/sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness");
+
+ report_utilization("thinkpad-light", utilization());
+}
+
+
+double thinkpad_light::utilization(void)
+{
+ return (start_rate+end_rate) / 2.55 / 2.0;
+}
+
+void create_thinkpad_light(void)
+{
+ char filename[PATH_MAX];
+ class thinkpad_light *light;
+
+ pt_strcpy(filename, "/sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness");
+
+ if (access(filename, R_OK) !=0)
+ return;
+
+ register_parameter("thinkpad-light", 10);
+
+ light = new class thinkpad_light();
+ all_devices.push_back(light);
+}
+
+
+
+double thinkpad_light::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+
+ power = 0;
+ util = get_result_value(r_index, result);
+
+ if (util < 0)
+ util = 0;
+
+
+ factor = get_parameter_value(light_index, bundle) - 10.0;
+ power += util / 100.0 * factor;
+
+ if (power <= 0.0)
+ power = 0.0;
+
+ return power;
+}
diff --git a/src/devices/thinkpad-light.h b/src/devices/thinkpad-light.h
new file mode 100644
index 0000000..64a1789
--- /dev/null
+++ b/src/devices/thinkpad-light.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_THINKPAD_LIGHT_H
+#define _INCLUDE_GUARD_THINKPAD_LIGHT_H
+
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class thinkpad_light: public device {
+ double start_rate, end_rate;
+ int light_index;
+ int r_index;
+public:
+
+ thinkpad_light();
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "light";};
+
+ virtual const char * device_name(void) { return "Light-1";};
+ virtual const char * human_name(void) { return "Thinkpad light";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return "%"; };
+ virtual int power_valid(void) { return utilization_power_valid(r_index);};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_thinkpad_light(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/usb.cpp b/src/devices/usb.cpp
new file mode 100644
index 0000000..5042699
--- /dev/null
+++ b/src/devices/usb.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "usb.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include "../lib.h"
+#include "../devlist.h"
+#include "../parameters/parameters.h"
+
+#include <iostream>
+#include <fstream>
+
+usbdevice::usbdevice(const char *_name, const char *path, const char *devid): device()
+{
+ ifstream file;
+ char filename[PATH_MAX];
+ char vendor[4096];
+ char product[4096];
+
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ pt_strcpy(name, _name);
+ pt_strcpy(devname, devid);
+ snprintf(humanname, sizeof(humanname), _("USB device: %s"), pretty_print(devid, vendor, 4096));
+ active_before = 0;
+ active_after = 0;
+ connected_before = 0;
+ connected_after = 0;
+ busnum = 0;
+ devnum = 0;
+
+ index = get_param_index(devname);
+ r_index = get_result_index(name);
+ rootport = 0;
+ cached_valid = 0;
+
+
+ /* root ports and hubs should count as 0 power ... their activity is derived */
+ snprintf(filename, sizeof(filename), "%s/bDeviceClass", path);
+ file.open(filename, ios::in);
+ if (file) {
+ int dclass = 0;
+
+ file >> dclass;
+ file.close();
+ if (dclass == 9)
+ rootport = 1;
+ };
+
+ vendor[0] = 0;
+ product[0] = 0;
+ snprintf(filename, sizeof(filename), "%s/manufacturer", path);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(vendor, 2047);
+ if (strstr(vendor, "Linux "))
+ vendor[0] = 0;
+ file.close();
+ };
+ snprintf(filename, sizeof(filename), "%s/product", path);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(product, 2040);
+ file.close();
+ };
+ if (strlen(vendor) && strlen(product))
+ snprintf(humanname, sizeof(humanname), _("USB device: %s (%s)"), product, vendor);
+ else if (strlen(product))
+ snprintf(humanname, sizeof(humanname), _("USB device: %s"), product);
+ else if (strlen(vendor))
+ snprintf(humanname, sizeof(humanname), _("USB device: %s"), vendor);
+
+ /* For usbdevfs we need bus number and device number */
+ snprintf(filename, sizeof(filename), "%s/busnum", path);
+ file.open(filename, ios::in);
+ if (file) {
+
+ file >> busnum;
+ file.close();
+ };
+ snprintf(filename, sizeof(filename), "%s/devnum", path);
+ file.open(filename, ios::in);
+ if (file) {
+
+ file >> devnum;
+ file.close();
+ };
+}
+
+
+
+void usbdevice::start_measurement(void)
+{
+ ifstream file;
+ char fullpath[PATH_MAX];
+
+ active_before = 0;
+ active_after = 0;
+ connected_before = 0;
+ connected_after = 0;
+
+ snprintf(fullpath, sizeof(fullpath), "%s/power/active_duration", sysfs_path);
+ file.open(fullpath, ios::in);
+ if (file) {
+ file >> active_before;
+ }
+ file.close();
+
+ snprintf(fullpath, sizeof(fullpath), "%s/power/connected_duration", sysfs_path);
+ file.open(fullpath, ios::in);
+ if (file) {
+ file >> connected_before;
+ }
+ file.close();
+}
+
+void usbdevice::end_measurement(void)
+{
+ ifstream file;
+ char fullpath[PATH_MAX];
+
+ snprintf(fullpath, sizeof(fullpath), "%s/power/active_duration", sysfs_path);
+ file.open(fullpath, ios::in);
+ if (file) {
+ file >> active_after;
+ }
+ file.close();
+
+ snprintf(fullpath, sizeof(fullpath), "%s/power/connected_duration", sysfs_path);
+ file.open(fullpath, ios::in);
+ if (file) {
+ file >> connected_after;
+ }
+ file.close();
+ report_utilization(name, utilization());
+
+}
+
+double usbdevice::utilization(void) /* percentage */
+{
+ double d;
+ d = 100.0 * (active_after - active_before) / (0.01 + connected_after - connected_before);
+ if (d < 0.0)
+ d = 0.0;
+ if (d > 99.8)
+ d = 100.0;
+ return d;
+}
+
+const char * usbdevice::device_name(void)
+{
+ return name;
+}
+
+const char * usbdevice::human_name(void)
+{
+ return humanname;
+}
+
+void usbdevice::register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle)
+{
+ char devfs_name[1024];
+
+ snprintf(devfs_name, sizeof(devfs_name), "usb/%03d/%03d", busnum,
+ devnum);
+
+ register_devpower(devfs_name, power_usage(results, bundle), this);
+}
+
+double usbdevice::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ if (rootport || !cached_valid)
+ return 0.0;
+
+
+ power = 0;
+ factor = get_parameter_value(index, bundle);
+ util = get_result_value(r_index, result);
+
+ power += util * factor / 100.0;
+
+ return power;
+}
+
+static void create_all_usb_devices_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+ class usbdevice *usb;
+ char device_name[PATH_MAX];
+ char vendorid[64], devid[64];
+ char devid_name[4096];
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s", d_name);
+ snprintf(device_name, sizeof(device_name), "%s/power/active_duration", filename);
+ if (access(device_name, R_OK) != 0)
+ return;
+
+ snprintf(device_name, sizeof(device_name), "%s/idVendor", filename);
+ file.open(device_name, ios::in);
+ if (file)
+ file.getline(vendorid, 64);
+ file.close();
+ snprintf(device_name, sizeof(device_name), "%s/idProduct", filename);
+ file.open(device_name, ios::in);
+ if (file)
+ file.getline(devid, 64);
+ file.close();
+
+ snprintf(devid_name, sizeof(devid_name), "usb-device-%s-%s", vendorid, devid);
+ snprintf(device_name, sizeof(device_name), "usb-device-%s-%s-%s", d_name, vendorid, devid);
+ if (result_device_exists(device_name))
+ return;
+
+ usb = new class usbdevice(device_name, filename, devid_name);
+ all_devices.push_back(usb);
+ register_parameter(devid_name, 0.1);
+}
+
+void create_all_usb_devices(void)
+{
+ process_directory("/sys/bus/usb/devices/", create_all_usb_devices_callback);
+}
diff --git a/src/devices/usb.h b/src/devices/usb.h
new file mode 100644
index 0000000..7e76a55
--- /dev/null
+++ b/src/devices/usb.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010, 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:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_USB_H
+#define _INCLUDE_GUARD_USB_H
+
+#include <limits.h>
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class usbdevice: public device {
+ int active_before, active_after;
+ int connected_before, connected_after;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char devname[4096];
+ char humanname[4096];
+ int index;
+ int r_index;
+ int rootport;
+ int busnum;
+ int devnum;
+public:
+
+ usbdevice(const char *_name, const char *path, const char *devid);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "usb";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void);
+ virtual void register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle);
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(r_index);};
+ virtual int grouping_prio(void) { return 4; };
+};
+
+extern void create_all_usb_devices(void);
+
+
+#endif \ No newline at end of file