| /* |
| * Copyright 2007, 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 |
| * |
| * Authors: |
| * Arjan van de Ven <arjan@linux.intel.com> |
| */ |
| |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdint.h> |
| #include <sys/types.h> |
| #include <dirent.h> |
| #include <ncurses.h> |
| #include <time.h> |
| #include <wchar.h> |
| |
| #include "powertop.h" |
| |
| static WINDOW *title_bar_window; |
| static WINDOW *cstate_window; |
| static WINDOW *wakeup_window; |
| static WINDOW *battery_power_window; |
| static WINDOW *timerstat_window; |
| static WINDOW *suggestion_window; |
| static WINDOW *status_bar_window; |
| |
| #define print(win, y, x, fmt, args...) do { if (dump) printf(fmt, ## args); else mvwprintw(win, y, x, fmt, ## args); } while (0) |
| |
| char status_bar_slots[10][40]; |
| |
| static void cleanup_curses(void) { |
| endwin(); |
| } |
| |
| static void zap_windows(void) |
| { |
| if (title_bar_window) { |
| delwin(title_bar_window); |
| title_bar_window = NULL; |
| } |
| if (cstate_window) { |
| delwin(cstate_window); |
| cstate_window = NULL; |
| } |
| if (wakeup_window) { |
| delwin(wakeup_window); |
| wakeup_window = NULL; |
| } |
| if (battery_power_window) { |
| delwin(battery_power_window); |
| battery_power_window = NULL; |
| } |
| if (timerstat_window) { |
| delwin(timerstat_window); |
| timerstat_window = NULL; |
| } |
| if (suggestion_window) { |
| delwin(suggestion_window); |
| suggestion_window = NULL; |
| } |
| if (status_bar_window) { |
| delwin(status_bar_window); |
| status_bar_window = NULL; |
| } |
| } |
| |
| |
| int maxx, maxy; |
| |
| int maxtimerstats = 50; |
| int maxwidth = 200; |
| |
| void setup_windows(void) |
| { |
| getmaxyx(stdscr, maxy, maxx); |
| |
| zap_windows(); |
| |
| title_bar_window = subwin(stdscr, 1, maxx, 0, 0); |
| cstate_window = subwin(stdscr, 7, maxx, 2, 0); |
| wakeup_window = subwin(stdscr, 1, maxx, 9, 0); |
| battery_power_window = subwin(stdscr, 2, maxx, 10, 0); |
| timerstat_window = subwin(stdscr, maxy-16, maxx, 12, 0); |
| maxtimerstats = maxy-16 -2; |
| maxwidth = maxx - 18; |
| suggestion_window = subwin(stdscr, 3, maxx, maxy-4, 0); |
| status_bar_window = subwin(stdscr, 1, maxx, maxy-1, 0); |
| |
| strcpy(status_bar_slots[0], _(" Q - Quit ")); |
| strcpy(status_bar_slots[1], _(" R - Refresh ")); |
| |
| werase(stdscr); |
| refresh(); |
| } |
| |
| void initialize_curses(void) |
| { |
| initscr(); |
| start_color(); |
| keypad(stdscr, TRUE); /* enable keyboard mapping */ |
| nonl(); /* tell curses not to do NL->CR/NL on output */ |
| cbreak(); /* take input chars one at a time, no wait for \n */ |
| noecho(); /* dont echo input */ |
| curs_set(0); /* turn off cursor */ |
| use_default_colors(); |
| |
| init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK); |
| init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE); |
| init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED); |
| init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED); |
| init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW); |
| init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN); |
| init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE); |
| init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK); |
| |
| atexit(cleanup_curses); |
| } |
| |
| void show_title_bar(void) |
| { |
| int i; |
| int x; |
| wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR)); |
| wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR)); |
| werase(title_bar_window); |
| |
| print(title_bar_window, 0, 0, " PowerTOP version 1.11 (C) 2007 Intel Corporation"); |
| |
| wrefresh(title_bar_window); |
| |
| werase(status_bar_window); |
| |
| x = 0; |
| for (i=0; i<10; i++) { |
| if (strlen(status_bar_slots[i])==0) |
| continue; |
| wattron(status_bar_window, A_REVERSE); |
| print(status_bar_window, 0, x, status_bar_slots[i]); |
| wattroff(status_bar_window, A_REVERSE); |
| x+= strlen(status_bar_slots[i])+1; |
| } |
| wrefresh(status_bar_window); |
| } |
| |
| void show_cstates(void) |
| { |
| int i, count = 0; |
| werase(cstate_window); |
| |
| for (i=0; i < 10; i++) { |
| if (i == topcstate+1) |
| wattron(cstate_window, A_BOLD); |
| else |
| wattroff(cstate_window, A_BOLD); |
| if (strlen(cstate_lines[i]) && count <= 6) { |
| print(cstate_window, count, 0, "%s", cstate_lines[i]); |
| count++; |
| } |
| } |
| |
| for (i=0; i<6; i++) { |
| if (i == topfreq+1) |
| wattron(cstate_window, A_BOLD); |
| else |
| wattroff(cstate_window, A_BOLD); |
| print(cstate_window, i, 38, "%s", cpufreqstrings[i]); |
| } |
| |
| wrefresh(cstate_window); |
| } |
| |
| |
| void show_acpi_power_line(double rate, double cap, double capdelta, time_t ti) |
| { |
| char buffer[1024]; |
| |
| sprintf(buffer, _("no ACPI power usage estimate available") ); |
| |
| werase(battery_power_window); |
| if (rate > 0.001) { |
| char *c; |
| sprintf(buffer, _("Power usage (ACPI estimate): %3.1fW (%3.1f hours)"), rate, cap/rate); |
| strcat(buffer, " "); |
| c = &buffer[strlen(buffer)]; |
| if (ti>180 && capdelta > 0) |
| sprintf(c, _("(long term: %3.1fW,/%3.1fh)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01)); |
| } |
| else if (ti>120 && capdelta > 0.001) |
| sprintf(buffer, _("Power usage (5 minute ACPI estimate) : %5.1f W (%3.1f hours left)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01)); |
| |
| print(battery_power_window, 0, 0, "%s\n", buffer); |
| wrefresh(battery_power_window); |
| } |
| |
| void show_pmu_power_line(unsigned sum_voltage_mV, |
| unsigned sum_charge_mAh, unsigned sum_max_charge_mAh, |
| int sum_discharge_mA) |
| { |
| char buffer[1024]; |
| |
| if (sum_discharge_mA != 0) |
| { |
| unsigned remaining_charge_mAh; |
| |
| if (sum_discharge_mA < 0) |
| { |
| /* we are currently discharging */ |
| sum_discharge_mA = -sum_discharge_mA; |
| remaining_charge_mAh = sum_charge_mAh; |
| } |
| else |
| { |
| /* we are currently charging */ |
| remaining_charge_mAh = (sum_max_charge_mAh |
| - sum_charge_mAh); |
| } |
| |
| snprintf(buffer, sizeof(buffer), |
| _("Power usage: %3.1fW (%3.1f hours)"), |
| sum_voltage_mV * sum_discharge_mA / 1e6, |
| (double)remaining_charge_mAh / sum_discharge_mA); |
| } |
| else |
| snprintf(buffer, sizeof(buffer), |
| _("no power usage estimate available") ); |
| |
| werase(battery_power_window); |
| print(battery_power_window, 0, 0, "%s\n", buffer); |
| wrefresh(battery_power_window); |
| } |
| |
| |
| void show_wakeups(double d, double interval, double C0time) |
| { |
| werase(wakeup_window); |
| |
| wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED)); |
| if (d <= 25.0) |
| wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_YELLOW)); |
| if (d <= 10.0) |
| wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_GREEN)); |
| |
| /* |
| * if the cpu is really busy.... then make it blue to indicate |
| * that it's not the primary power consumer anymore |
| */ |
| if (C0time > 25.0) |
| wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_BLUE)); |
| |
| wattron(wakeup_window, A_BOLD); |
| print(wakeup_window, 0, 0, _("Wakeups-from-idle per second : %4.1f\tinterval: %0.1fs\n"), d, interval); |
| wrefresh(wakeup_window); |
| } |
| |
| void show_timerstats(int nostats, int ticktime) |
| { |
| int i; |
| werase(timerstat_window); |
| |
| if (!nostats) { |
| int counter = 0; |
| print(timerstat_window, 0, 0, _("Top causes for wakeups:\n")); |
| for (i = 0; i < linehead; i++) |
| if (lines[i].count > 0 && counter++ < maxtimerstats) { |
| if ((lines[i].count * 1.0 / ticktime) >= 10.0) |
| wattron(timerstat_window, A_BOLD); |
| else |
| wattroff(timerstat_window, A_BOLD); |
| if (showpids) |
| print(timerstat_window, i+1, 0," %5.1f%% (%5.1f) [%6s] %s \n", lines[i].count * 100.0 / linectotal, |
| lines[i].count * 1.0 / ticktime, |
| lines[i].pid, lines[i].string); |
| else |
| print(timerstat_window, i+1, 0," %5.1f%% (%5.1f) %s \n", lines[i].count * 100.0 / linectotal, |
| lines[i].count * 1.0 / ticktime, |
| lines[i].string); |
| } |
| } else { |
| if (geteuid() == 0) { |
| print(timerstat_window, 0, 0, _("No detailed statistics available; please enable the CONFIG_TIMER_STATS kernel option\n")); |
| print(timerstat_window, 1, 0, _("This option is located in the Kernel Debugging section of menuconfig\n")); |
| print(timerstat_window, 2, 0, _("(which is CONFIG_DEBUG_KERNEL=y in the config file)\n")); |
| print(timerstat_window, 3, 0, _("Note: this is only available in 2.6.21 and later kernels\n")); |
| } else |
| print(timerstat_window, 0, 0, _("No detailed statistics available; PowerTOP needs root privileges for that\n")); |
| } |
| |
| |
| wrefresh(timerstat_window); |
| } |
| |
| void show_suggestion(char *sug) |
| { |
| werase(suggestion_window); |
| print(suggestion_window, 0, 0, "%s", sug); |
| wrefresh(suggestion_window); |
| } |