blob: 6ff3a227efdbf77f06a49d44ddf1b69f27fdaeb4 [file] [log] [blame]
/*
* 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 "../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;
strcpy(current_path, path);
while (iter++ < 10) {
char test_path[PATH_MAX + 1];
sprintf(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_joules_consumed();
if (pw > 0.0001) {
char buf[32];
wprintw(win, _("The battery reports a discharge rate of %sW\n"),
fmt_prefix(pw, 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;
double pw;
show_power = global_power_valid();
sort(all_devices.begin(), all_devices.end(), power_device_sort);
report.begin_section(SECTION_DEVPOWER);
report.add_header("Device Power Report");
pw = global_joules_consumed();
if (pw > 0.0001) {
char buf[32];
report.begin_paragraph();
report.addf("The battery reports a discharge rate of %sW",
fmt_prefix(pw, buf));
}
if (show_power) {
char buf[32];
report.begin_paragraph();
report.addf("System baseline power is estimated at %sW",
fmt_prefix(get_parameter_value("base power"), buf));
}
report.begin_table(TABLE_WIDE);
report.begin_row();
if (show_power) {
report.begin_cell(CELL_DEVPOWER_HEADER);
report.add("Power est.");
}
report.begin_cell(CELL_DEVPOWER_HEADER);
report.add("Usage");
report.begin_cell(CELL_DEVPOWER_DEV_NAME);
report.add("Device name");
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, " ");
report.begin_row(ROW_DEVPOWER);
if (show_power) {
report.begin_cell(CELL_DEVPOWER_POWER);
report.add(power);
}
report.begin_cell(CELL_DEVPOWER_UTIL);
report.add(util);
report.begin_cell();
report.add(all_devices[i]->human_name());
}
}
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();
}