blob: ed26cd3686d87d873e958bc01f5e2076ffa1ca88 [file] [log] [blame]
Arjan van der Venbdedb3c2007-05-22 23:53:28 +00001/*
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@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>
Arjan van der Ven2e74d1d2007-05-26 15:47:40 +000032#include <time.h>
Arjan van der Venbdedb3c2007-05-22 23:53:28 +000033#include "powertop.h"
34
Anurag Singhc5781f82011-10-10 10:44:44 -070035#ifndef NO_NCURSES
36#include <ncurses.h>
37#include <wchar.h>
38#endif
39
40
41#ifdef NO_NCURSES
42#define WINDOW void
43#endif
44
Arjan van der Venbdedb3c2007-05-22 23:53:28 +000045static WINDOW *title_bar_window;
46static WINDOW *cstate_window;
47static WINDOW *wakeup_window;
Auke Kok41e83602008-09-04 19:59:19 +000048static WINDOW *battery_power_window;
Arjan van der Venbdedb3c2007-05-22 23:53:28 +000049static WINDOW *timerstat_window;
50static WINDOW *suggestion_window;
Arjan van der Ven41cc9942007-05-24 20:20:19 +000051static WINDOW *status_bar_window;
52
Anurag Singhc5781f82011-10-10 10:44:44 -070053#ifndef NO_NCURSES
Arjan van der Ven6fe1c572007-08-18 21:52:07 +000054#define print(win, y, x, fmt, args...) do { if (dump) printf(fmt, ## args); else mvwprintw(win, y, x, fmt, ## args); } while (0)
Arjan van der Ven41cc9942007-05-24 20:20:19 +000055
Anurag Singhc5781f82011-10-10 10:44:44 -070056#else
57
58#define print(win, y, x, fmt, args...) do { printf(fmt, ## args); } while (0)
59#define endwin(x)
60#define delwin(x)
61#define werase(x)
62#define wrefresh(x) printf("\n")
63#define wattron(x, y)
64#define wattroff(x, y)
65#define wbkgd(x, y)
66#define wattrset(x, y)
67#define COLOR_PAIR(x)
68
69#endif
70
Arjan van der Ven41cc9942007-05-24 20:20:19 +000071char status_bar_slots[10][40];
Arjan van der Venbdedb3c2007-05-22 23:53:28 +000072
73static void cleanup_curses(void) {
Arjan van der Venbdedb3c2007-05-22 23:53:28 +000074 endwin();
75}
76
77static void zap_windows(void)
78{
79 if (title_bar_window) {
80 delwin(title_bar_window);
81 title_bar_window = NULL;
82 }
83 if (cstate_window) {
84 delwin(cstate_window);
85 cstate_window = NULL;
86 }
87 if (wakeup_window) {
88 delwin(wakeup_window);
89 wakeup_window = NULL;
90 }
Auke Kok41e83602008-09-04 19:59:19 +000091 if (battery_power_window) {
92 delwin(battery_power_window);
93 battery_power_window = NULL;
Arjan van der Venbdedb3c2007-05-22 23:53:28 +000094 }
95 if (timerstat_window) {
96 delwin(timerstat_window);
97 timerstat_window = NULL;
98 }
99 if (suggestion_window) {
100 delwin(suggestion_window);
101 suggestion_window = NULL;
102 }
Arjan van der Ven41cc9942007-05-24 20:20:19 +0000103 if (status_bar_window) {
104 delwin(status_bar_window);
105 status_bar_window = NULL;
106 }
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000107}
108
109
110int maxx, maxy;
111
Arjan van der Ven6fe1c572007-08-18 21:52:07 +0000112int maxtimerstats = 50;
113int maxwidth = 200;
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000114
115void setup_windows(void)
116{
Anurag Singhc5781f82011-10-10 10:44:44 -0700117#ifndef NO_NCURSES
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000118 getmaxyx(stdscr, maxy, maxx);
119
120 zap_windows();
121
122 title_bar_window = subwin(stdscr, 1, maxx, 0, 0);
Arjan van der Venea55fec2007-05-23 14:27:03 +0000123 cstate_window = subwin(stdscr, 7, maxx, 2, 0);
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000124 wakeup_window = subwin(stdscr, 1, maxx, 9, 0);
Auke Kok41e83602008-09-04 19:59:19 +0000125 battery_power_window = subwin(stdscr, 2, maxx, 10, 0);
Arjan van der Ven41cc9942007-05-24 20:20:19 +0000126 timerstat_window = subwin(stdscr, maxy-16, maxx, 12, 0);
127 maxtimerstats = maxy-16 -2;
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000128 maxwidth = maxx - 18;
Arjan van der Ven41cc9942007-05-24 20:20:19 +0000129 suggestion_window = subwin(stdscr, 3, maxx, maxy-4, 0);
130 status_bar_window = subwin(stdscr, 1, maxx, maxy-1, 0);
131
Arjan van der Ven3037a452007-05-24 21:26:27 +0000132 strcpy(status_bar_slots[0], _(" Q - Quit "));
Arjan van der Venadd6b5d2007-06-23 05:50:19 +0000133 strcpy(status_bar_slots[1], _(" R - Refresh "));
Arjan van der Vendcf946e2007-05-26 20:43:17 +0000134
135 werase(stdscr);
136 refresh();
Anurag Singhc5781f82011-10-10 10:44:44 -0700137#endif
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000138}
139
140void initialize_curses(void)
141{
Anurag Singhc5781f82011-10-10 10:44:44 -0700142#ifndef NO_NCURSES
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000143 initscr();
Arjan van der Veneebeeff2007-05-23 02:41:05 +0000144 start_color();
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000145 keypad(stdscr, TRUE); /* enable keyboard mapping */
146 nonl(); /* tell curses not to do NL->CR/NL on output */
147 cbreak(); /* take input chars one at a time, no wait for \n */
148 noecho(); /* dont echo input */
149 curs_set(0); /* turn off cursor */
Arjan van der Ven3a00fcb2007-05-23 03:03:10 +0000150 use_default_colors();
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000151
Arjan van der Venc26d73e2007-05-23 02:23:22 +0000152 init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000153 init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE);
154 init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED);
Arjan van der Veneebeeff2007-05-23 02:41:05 +0000155 init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED);
156 init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW);
157 init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN);
Arjan van der Venb37f85d2007-08-18 19:33:04 +0000158 init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE);
Arjan van der Venc26d73e2007-05-23 02:23:22 +0000159 init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK);
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000160
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000161 atexit(cleanup_curses);
Anurag Singhc5781f82011-10-10 10:44:44 -0700162#endif
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000163}
164
165void show_title_bar(void)
166{
Arjan van der Ven41cc9942007-05-24 20:20:19 +0000167 int i;
168 int x;
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000169 wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
170 wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
171 werase(title_bar_window);
172
Anurag Singhbf459e22011-10-10 10:50:51 -0700173 /*
174 print(title_bar_window, 0, 0, " PowerTOP version 1.11 (C) 2007 Intel Corporation");
175 */
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000176
177 wrefresh(title_bar_window);
Arjan van der Ven41cc9942007-05-24 20:20:19 +0000178
179 werase(status_bar_window);
180
181 x = 0;
182 for (i=0; i<10; i++) {
183 if (strlen(status_bar_slots[i])==0)
184 continue;
185 wattron(status_bar_window, A_REVERSE);
Anurag Singhc5781f82011-10-10 10:44:44 -0700186 print(status_bar_window, 0, x, "%s", status_bar_slots[i]);
Arjan van der Ven41cc9942007-05-24 20:20:19 +0000187 wattroff(status_bar_window, A_REVERSE);
188 x+= strlen(status_bar_slots[i])+1;
189 }
190 wrefresh(status_bar_window);
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000191}
192
193void show_cstates(void)
194{
Arjan van der Ven70551c52008-03-27 03:16:37 +0000195 int i, count = 0;
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000196 werase(cstate_window);
197
Arjan van der Ven70551c52008-03-27 03:16:37 +0000198 for (i=0; i < 10; i++) {
Arjan van der Ven5288ca72007-05-23 16:24:06 +0000199 if (i == topcstate+1)
200 wattron(cstate_window, A_BOLD);
201 else
202 wattroff(cstate_window, A_BOLD);
Arjan van der Ven28e45c62008-03-27 04:37:57 +0000203 if (strlen(cstate_lines[i]) && count <= 6) {
Arjan van der Ven70551c52008-03-27 03:16:37 +0000204 print(cstate_window, count, 0, "%s", cstate_lines[i]);
205 count++;
206 }
Arjan van der Ven5288ca72007-05-23 16:24:06 +0000207 }
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000208
Patrick Caind2a9a4c2014-08-20 12:35:29 -0700209 for (i=0; i<25; i++) {
Arjan van der Ven6fe1c572007-08-18 21:52:07 +0000210 if (i == topfreq+1)
Arjan van der Ven329bb7a2007-06-17 06:27:18 +0000211 wattron(cstate_window, A_BOLD);
212 else
213 wattroff(cstate_window, A_BOLD);
Arjan van der Ven6fe1c572007-08-18 21:52:07 +0000214 print(cstate_window, i, 38, "%s", cpufreqstrings[i]);
Arjan van der Ven329bb7a2007-06-17 06:27:18 +0000215 }
216
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000217 wrefresh(cstate_window);
218}
219
Anurag Singhc5781f82011-10-10 10:44:44 -0700220void show_msm_pm_stats(void)
221{
222 int i = 0;
223 for (i=0; i < 12; i++)
224 print(cstate_window, i, 38, "%s", msm_pm_stat_lines[i]);
225 wrefresh(cstate_window);
226}
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000227
Arjan van der Ven2e74d1d2007-05-26 15:47:40 +0000228void show_acpi_power_line(double rate, double cap, double capdelta, time_t ti)
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000229{
Arjan van der Ven2e74d1d2007-05-26 15:47:40 +0000230 char buffer[1024];
231
Arjan van der Ven020cecf2007-05-26 17:32:15 +0000232 sprintf(buffer, _("no ACPI power usage estimate available") );
Arjan van der Ven2e74d1d2007-05-26 15:47:40 +0000233
Auke Kok41e83602008-09-04 19:59:19 +0000234 werase(battery_power_window);
Arjan van der Ven399ceb52007-05-27 02:15:12 +0000235 if (rate > 0.001) {
Arjan van der Ven2e74d1d2007-05-26 15:47:40 +0000236 char *c;
Arjan van der Venfe775a12007-06-01 07:28:10 +0000237 sprintf(buffer, _("Power usage (ACPI estimate): %3.1fW (%3.1f hours)"), rate, cap/rate);
Arjan van der Ven2e74d1d2007-05-26 15:47:40 +0000238 strcat(buffer, " ");
239 c = &buffer[strlen(buffer)];
Arjan van der Ven013a4db2007-05-26 16:12:07 +0000240 if (ti>180 && capdelta > 0)
Arjan van der Ven9ae8f952007-06-01 07:27:31 +0000241 sprintf(c, _("(long term: %3.1fW,/%3.1fh)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01));
Arjan van der Ven2e74d1d2007-05-26 15:47:40 +0000242 }
Arjan van der Vend6d6b042007-05-26 21:41:46 +0000243 else if (ti>120 && capdelta > 0.001)
Arjan van der Ven2e74d1d2007-05-26 15:47:40 +0000244 sprintf(buffer, _("Power usage (5 minute ACPI estimate) : %5.1f W (%3.1f hours left)"), 3600*capdelta / ti, cap / (3600*capdelta/ti+0.01));
245
Auke Kok41e83602008-09-04 19:59:19 +0000246 print(battery_power_window, 0, 0, "%s\n", buffer);
247 wrefresh(battery_power_window);
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000248}
249
Auke Kok07ed39e2008-09-16 17:22:14 +0000250void show_pmu_power_line(unsigned sum_voltage_mV,
Auke Kok41e83602008-09-04 19:59:19 +0000251 unsigned sum_charge_mAh, unsigned sum_max_charge_mAh,
252 int sum_discharge_mA)
253{
254 char buffer[1024];
255
256 if (sum_discharge_mA != 0)
257 {
258 unsigned remaining_charge_mAh;
259
260 if (sum_discharge_mA < 0)
261 {
262 /* we are currently discharging */
263 sum_discharge_mA = -sum_discharge_mA;
264 remaining_charge_mAh = sum_charge_mAh;
265 }
266 else
267 {
268 /* we are currently charging */
269 remaining_charge_mAh = (sum_max_charge_mAh
270 - sum_charge_mAh);
271 }
272
273 snprintf(buffer, sizeof(buffer),
274 _("Power usage: %3.1fW (%3.1f hours)"),
275 sum_voltage_mV * sum_discharge_mA / 1e6,
276 (double)remaining_charge_mAh / sum_discharge_mA);
277 }
278 else
279 snprintf(buffer, sizeof(buffer),
280 _("no power usage estimate available") );
281
282 werase(battery_power_window);
283 print(battery_power_window, 0, 0, "%s\n", buffer);
284 wrefresh(battery_power_window);
285}
286
287
Arjan van der Venb37f85d2007-08-18 19:33:04 +0000288void show_wakeups(double d, double interval, double C0time)
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000289{
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000290 werase(wakeup_window);
Arjan van der Venc26d73e2007-05-23 02:23:22 +0000291
292 wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_RED));
Arjan van der Ven6c3cd752007-08-18 19:45:44 +0000293 if (d <= 25.0)
Arjan van der Venc26d73e2007-05-23 02:23:22 +0000294 wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_YELLOW));
Arjan van der Ven6c3cd752007-08-18 19:45:44 +0000295 if (d <= 10.0)
Arjan van der Venc26d73e2007-05-23 02:23:22 +0000296 wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_GREEN));
Arjan van der Venb37f85d2007-08-18 19:33:04 +0000297
298 /*
299 * if the cpu is really busy.... then make it blue to indicate
300 * that it's not the primary power consumer anymore
301 */
302 if (C0time > 25.0)
303 wbkgd(wakeup_window, COLOR_PAIR(PT_COLOR_BLUE));
Arjan van der Venc26d73e2007-05-23 02:23:22 +0000304
Arjan van der Veneebeeff2007-05-23 02:41:05 +0000305 wattron(wakeup_window, A_BOLD);
Arjan van der Ven6fe1c572007-08-18 21:52:07 +0000306 print(wakeup_window, 0, 0, _("Wakeups-from-idle per second : %4.1f\tinterval: %0.1fs\n"), d, interval);
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000307 wrefresh(wakeup_window);
308}
309
310void show_timerstats(int nostats, int ticktime)
311{
312 int i;
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000313 werase(timerstat_window);
314
315 if (!nostats) {
316 int counter = 0;
Arjan van der Ven6fe1c572007-08-18 21:52:07 +0000317 print(timerstat_window, 0, 0, _("Top causes for wakeups:\n"));
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000318 for (i = 0; i < linehead; i++)
319 if (lines[i].count > 0 && counter++ < maxtimerstats) {
320 if ((lines[i].count * 1.0 / ticktime) >= 10.0)
Arjan van der Veneebeeff2007-05-23 02:41:05 +0000321 wattron(timerstat_window, A_BOLD);
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000322 else
Arjan van der Veneebeeff2007-05-23 02:41:05 +0000323 wattroff(timerstat_window, A_BOLD);
Anurag Singhbf459e22011-10-10 10:50:51 -0700324#ifdef PLATFORM_NO_INT0
325 if (strstr(lines[i].string, "<interrupt>") == 0) continue;
326#endif
Arjan van der Ven356cd2c2007-12-13 21:52:01 +0000327 if (showpids)
Anurag Singhbf459e22011-10-10 10:50:51 -0700328 print(timerstat_window, i+1, 0," %5.1f%% (%5.1f) [%6s] %s \n", lines[i].count * 100.0 /
329#ifdef PLATFORM_NO_INT0
330 (int) total_interrupt,
331#else
332 (int) linectotal,
333#endif
334 lines[i].count * 1.0 / ticktime,
Arjan van der Ven356cd2c2007-12-13 21:52:01 +0000335 lines[i].pid, lines[i].string);
Anurag Singhbf459e22011-10-10 10:50:51 -0700336 else{
337 print(timerstat_window, i+1, 0," %5.1f%% (%5.1f) %s \n", lines[i].count * 100.0 /
338#ifdef PLATFORM_NO_INT0
339 (int) total_interrupt,
340#else
341 (int) linectotal,
342#endif
343 lines[i].count * 1.0 / ticktime,
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000344 lines[i].string);
345 }
Anurag Singhbf459e22011-10-10 10:50:51 -0700346 }
347#ifdef PLATFORM_NO_INT0
348 print(timerstat_window, i, 0, "\nTimer breakdown (dg_timer or gp_timer):\n");
349 for (i = 0; i < linehead; i++)
350 if (lines[i].count > 0 && counter++ < maxtimerstats) {
351 if ((lines[i].count * 1.0 / ticktime) >= 10.0)
352 wattron(timerstat_window, A_BOLD);
353 else
354 wattroff(timerstat_window, A_BOLD);
355 if (strstr(lines[i].string, "<interrupt>") != 0) continue;
356
357 if (showpids)
358 print(timerstat_window, i+1, 0," %5.1f%% (%5.1f) [%6s] %s \n", lines[i].count * 100.0 / (linectotal - (int) total_interrupt),
359 lines[i].count * 1.0 / ticktime,
360 lines[i].pid, lines[i].string);
361 else
362 print(timerstat_window, i+1, 0," %5.1f%% (%5.1f) %s \n", lines[i].count * 100.0 / (linectotal - (int) total_interrupt),
363 lines[i].count * 1.0 / ticktime,
364 lines[i].string);
365 }
366#endif
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000367 } else {
Arjan van der Ven34640a42007-08-19 17:42:57 +0000368 if (geteuid() == 0) {
Arjan van der Ven6fe1c572007-08-18 21:52:07 +0000369 print(timerstat_window, 0, 0, _("No detailed statistics available; please enable the CONFIG_TIMER_STATS kernel option\n"));
370 print(timerstat_window, 1, 0, _("This option is located in the Kernel Debugging section of menuconfig\n"));
371 print(timerstat_window, 2, 0, _("(which is CONFIG_DEBUG_KERNEL=y in the config file)\n"));
372 print(timerstat_window, 3, 0, _("Note: this is only available in 2.6.21 and later kernels\n"));
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000373 } else
Arjan van der Ven6fe1c572007-08-18 21:52:07 +0000374 print(timerstat_window, 0, 0, _("No detailed statistics available; PowerTOP needs root privileges for that\n"));
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000375 }
376
377
378 wrefresh(timerstat_window);
379}
380
381void show_suggestion(char *sug)
382{
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000383 werase(suggestion_window);
Arjan van der Ven6fe1c572007-08-18 21:52:07 +0000384 print(suggestion_window, 0, 0, "%s", sug);
Arjan van der Venbdedb3c2007-05-22 23:53:28 +0000385 wrefresh(suggestion_window);
386}