/* * 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 */ #include "device.h" #include #include #include #include #include #include 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 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 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(); }