Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright 2007, Intel Corporation
      3  *
      4  * This file is part of PowerTOP
      5  *
      6  * This program file is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License as published by the
      8  * Free Software Foundation; version 2 of the License.
      9  *
     10  * This program is distributed in the hope that it will be useful, but WITHOUT
     11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     13  * for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program in a file named COPYING; if not, write to the
     17  * Free Software Foundation, Inc.,
     18  * 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301 USA
     20  *
     21  * Authors:
     22  * 	Arjan van de Ven <arjan (at) linux.intel.com>
     23  */
     24 
     25 #include <unistd.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <stdint.h>
     30 #include <sys/types.h>
     31 #include <dirent.h>
     32 #include <ncurses.h>
     33 #include <time.h>
     34 #include <wchar.h>
     35 
     36 #include "powertop.h"
     37 
     38 static WINDOW *title_bar_window;
     39 static WINDOW *cstate_window;
     40 static WINDOW *wakeup_window;
     41 static WINDOW *battery_power_window;
     42 static WINDOW *timerstat_window;
     43 static WINDOW *suggestion_window;
     44 static WINDOW *status_bar_window;
     45 
     46 #define print(win, y, x, fmt, args...) do { if (dump) printf(fmt, ## args); else mvwprintw(win, y, x, fmt, ## args); } while (0)
     47 
     48 char status_bar_slots[10][40];
     49 
     50 static void cleanup_curses(void) {
     51 	endwin();
     52 }
     53 
     54 static void zap_windows(void)
     55 {
     56 	if (title_bar_window) {
     57 		delwin(title_bar_window);
     58 		title_bar_window = NULL;
     59 	}
     60 	if (cstate_window) {
     61 		delwin(cstate_window);
     62 		cstate_window = NULL;
     63 	}
     64 	if (wakeup_window) {
     65 		delwin(wakeup_window);
     66 		wakeup_window = NULL;
     67 	}
     68 	if (battery_power_window) {
     69 		delwin(battery_power_window);
     70 		battery_power_window = NULL;
     71 	}
     72 	if (timerstat_window) {
     73 		delwin(timerstat_window);
     74 		timerstat_window = NULL;
     75 	}
     76 	if (suggestion_window) {
     77 		delwin(suggestion_window);
     78 		suggestion_window = NULL;
     79 	}
     80 	if (status_bar_window) {
     81 		delwin(status_bar_window);
     82 		status_bar_window = NULL;
     83 	}
     84 }
     85 
     86 
     87 int maxx, maxy;
     88 
     89 int maxtimerstats = 50;
     90 int maxwidth = 200;
     91 
     92 void setup_windows(void)
     93 {
     94 	getmaxyx(stdscr, maxy, maxx);
     95 
     96 	zap_windows();
     97 
     98 	title_bar_window = subwin(stdscr, 1, maxx, 0, 0);
     99 	cstate_window = subwin(stdscr, 7, maxx, 2, 0);
    100 	wakeup_window = subwin(stdscr, 1, maxx, 9, 0);
    101 	battery_power_window = subwin(stdscr, 2, maxx, 10, 0);
    102 	timerstat_window = subwin(stdscr, maxy-16, maxx, 12, 0);
    103 	maxtimerstats = maxy-16  -2;
    104 	maxwidth = maxx - 18;
    105 	suggestion_window = subwin(stdscr, 3, maxx, maxy-4, 0);
    106 	status_bar_window = subwin(stdscr, 1, maxx, maxy-1, 0);
    107 
    108 	strcpy(status_bar_slots[0], _(" Q - Quit "));
    109 	strcpy(status_bar_slots[1], _(" R - Refresh "));
    110 
    111 	werase(stdscr);
    112 	refresh();
    113 }
    114 
    115 void initialize_curses(void)
    116 {
    117 	initscr();
    118 	start_color();
    119 	keypad(stdscr, TRUE);	/* enable keyboard mapping */
    120 	nonl();			/* tell curses not to do NL->CR/NL on output */
    121 	cbreak();		/* take input chars one at a time, no wait for \n */
    122 	noecho();		/* dont echo input */
    123 	curs_set(0);		/* turn off cursor */
    124 	use_default_colors();
    125 
    126 	init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
    127 	init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE);
    128 	init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED);
    129 	init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED);
    130 	init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW);
    131 	init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN);
    132 	init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE);
    133 	init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK);
    134 
    135 	atexit(cleanup_curses);
    136 }
    137 
    138 void show_title_bar(void)
    139 {
    140 	int i;
    141 	int x;
    142 	wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
    143 	wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
    144 	werase(title_bar_window);
    145 
    146 	print(title_bar_window, 0, 0,  "     PowerTOP version 1.11      (C) 2007 Intel Corporation");
    147 
    148 	wrefresh(title_bar_window);
    149 
    150 	werase(status_bar_window);
    151 
    152 	x = 0;
    153 	for (i=0; i<10; i++) {
    154 		if (strlen(status_bar_slots[i])==0)
    155 			continue;
    156 		wattron(status_bar_window, A_REVERSE);
    157 		print(status_bar_window, 0, x, status_bar_slots[i]);
    158 		wattroff(status_bar_window, A_REVERSE);
    159 		x+= strlen(status_bar_slots[i])+1;
    160 	}
    161 	wrefresh(status_bar_window);
    162 }
    163 
    164 void show_cstates(void)
    165 {
    166 	int i, count = 0;
    167 	werase(cstate_window);
    168 
    169 	for (i=0; i < 10; i++) {
    170 		if (i == topcstate+1)
    171 			wattron(cstate_window, A_BOLD);
    172 		else
    173 			wattroff(cstate_window, A_BOLD);
    174 		if (strlen(cstate_lines[i]) && count <= 6) {
    175 			print(cstate_window, count, 0, "%s", cstate_lines[i]);
    176 			count++;
    177 		}
    178 	}
    179 
    180 	for (i=0; i<6; i++) {
    181 		if (i == topfreq+1)
    182 			wattron(cstate_window, A_BOLD);
    183 		else
    184 			wattroff(cstate_window, A_BOLD);
    185 		print(cstate_window, i, 38, "%s", cpufreqstrings[i]);
    186 	}
    187 
    188 	wrefresh(cstate_window);
    189 }
    190 
    191 
    192 void show_acpi_power_line(double rate, double cap, double capdelta, time_t ti)
    193 {
    194 	char buffer[1024];
    195 
    196 	sprintf(buffer,  _("no ACPI power usage estimate available") );
    197 
    198 	werase(battery_power_window);
    199 	if (rate > 0.001) {
    200 		char *c;
    201 		sprintf(buffer, _("Power usage (ACPI estimate): %3.1fW (%3.1f hours)"), rate, cap/rate);
    202 		strcat(buffer, " ");
    203 		c = &buffer[strlen(buffer)];
    204 		if (ti>180 && capdelta > 0)
    205 			sprintf(c, _("(long term: %3.1fW,/%3.1fh)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01));
    206 	}
    207 	else if (ti>120 && capdelta > 0.001)
    208 		sprintf(buffer, _("Power usage (5 minute ACPI estimate) : %5.1f W (%3.1f hours left)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01));
    209 
    210 	print(battery_power_window, 0, 0, "%s\n", buffer);
    211 	wrefresh(battery_power_window);
    212 }
    213 
    214 void show_pmu_power_line(unsigned sum_voltage_mV,
    215                          unsigned sum_charge_mAh, unsigned sum_max_charge_mAh,
    216                          int sum_discharge_mA)
    217 {
    218 	char buffer[1024];
    219 
    220 	if (sum_discharge_mA != 0)
    221 	{
    222 		unsigned remaining_charge_mAh;
    223 
    224 		if (sum_discharge_mA < 0)
    225 		{
    226 			/* we are currently discharging */
    227 			sum_discharge_mA = -sum_discharge_mA;
    228 			remaining_charge_mAh = sum_charge_mAh;
    229 		}
    230 		else
    231 		{
    232 			/* we are currently charging */
    233 			remaining_charge_mAh = (sum_max_charge_mAh
    234 						- sum_charge_mAh);
    235 		}
    236 
    237 		snprintf(buffer, sizeof(buffer),
    238 			 _("Power usage: %3.1fW (%3.1f hours)"),
    239 			 sum_voltage_mV * sum_discharge_mA / 1e6,
    240 			 (double)remaining_charge_mAh / sum_discharge_mA);
    241 	}
    242 	else
    243 		snprintf(buffer, sizeof(buffer),
    244 			 _("no power usage estimate available") );
    245 
    246 	werase(battery_power_window);
    247 	print(battery_power_window, 0, 0, "%s\n", buffer);
    248 	wrefresh(battery_power_window);
    249 }
    250 
    251 
    252 void show_wakeups(double d, double interval, double C0time)
    253 {
    254 	werase(wakeup_window);
    255 
    256 	wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED));
    257 	if (d <= 25.0)
    258 		wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_YELLOW));
    259 	if (d <= 10.0)
    260 		wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_GREEN));
    261 
    262 	/*
    263 	 * if the cpu is really busy.... then make it blue to indicate
    264 	 * that it's not the primary power consumer anymore
    265 	 */
    266 	if (C0time > 25.0)
    267 		wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_BLUE));
    268 
    269 	wattron(wakeup_window, A_BOLD);
    270 	print(wakeup_window, 0, 0, _("Wakeups-from-idle per second : %4.1f\tinterval: %0.1fs\n"), d, interval);
    271 	wrefresh(wakeup_window);
    272 }
    273 
    274 void show_timerstats(int nostats, int ticktime)
    275 {
    276 	int i;
    277 	werase(timerstat_window);
    278 
    279 	if (!nostats) {
    280 		int counter = 0;
    281 		print(timerstat_window, 0, 0, _("Top causes for wakeups:\n"));
    282 		for (i = 0; i < linehead; i++)
    283 			if (lines[i].count > 0 && counter++ < maxtimerstats) {
    284 				if ((lines[i].count * 1.0 / ticktime) >= 10.0)
    285 					wattron(timerstat_window, A_BOLD);
    286 				else
    287 					wattroff(timerstat_window, A_BOLD);
    288 				if (showpids)
    289 					print(timerstat_window, i+1, 0," %5.1f%% (%5.1f)   [%6s] %s \n", lines[i].count * 100.0 / linectotal,
    290 						lines[i].count * 1.0 / ticktime,
    291 						lines[i].pid, lines[i].string);
    292 				else
    293 					print(timerstat_window, i+1, 0," %5.1f%% (%5.1f)   %s \n", lines[i].count * 100.0 / linectotal,
    294 						lines[i].count * 1.0 / ticktime,
    295 						lines[i].string);
    296 				}
    297 	} else {
    298 		if (geteuid() == 0) {
    299 			print(timerstat_window, 0, 0, _("No detailed statistics available; please enable the CONFIG_TIMER_STATS kernel option\n"));
    300 			print(timerstat_window, 1, 0, _("This option is located in the Kernel Debugging section of menuconfig\n"));
    301 			print(timerstat_window, 2, 0, _("(which is CONFIG_DEBUG_KERNEL=y in the config file)\n"));
    302 			print(timerstat_window, 3, 0, _("Note: this is only available in 2.6.21 and later kernels\n"));
    303 		} else
    304 			print(timerstat_window, 0, 0, _("No detailed statistics available; PowerTOP needs root privileges for that\n"));
    305 	}
    306 
    307 
    308 	wrefresh(timerstat_window);
    309 }
    310 
    311 void show_suggestion(char *sug)
    312 {
    313 	werase(suggestion_window);
    314 	print(suggestion_window, 0, 0, "%s", sug);
    315 	wrefresh(suggestion_window);
    316 }
    317