1b47b5b34SRafael Vanoni /*
2b47b5b34SRafael Vanoni * Copyright 2009, Intel Corporation
3b47b5b34SRafael Vanoni * Copyright 2009, Sun Microsystems, Inc
4b47b5b34SRafael Vanoni *
5b47b5b34SRafael Vanoni * This file is part of PowerTOP
6b47b5b34SRafael Vanoni *
7b47b5b34SRafael Vanoni * This program file is free software; you can redistribute it and/or modify it
8b47b5b34SRafael Vanoni * under the terms of the GNU General Public License as published by the
9b47b5b34SRafael Vanoni * Free Software Foundation; version 2 of the License.
10b47b5b34SRafael Vanoni *
11b47b5b34SRafael Vanoni * This program is distributed in the hope that it will be useful, but WITHOUT
12b47b5b34SRafael Vanoni * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13b47b5b34SRafael Vanoni * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14b47b5b34SRafael Vanoni * for more details.
15b47b5b34SRafael Vanoni *
16b47b5b34SRafael Vanoni * You should have received a copy of the GNU General Public License
17b47b5b34SRafael Vanoni * along with this program in a file named COPYING; if not, write to the
18b47b5b34SRafael Vanoni * Free Software Foundation, Inc.,
19b47b5b34SRafael Vanoni * 51 Franklin Street, Fifth Floor,
20b47b5b34SRafael Vanoni * Boston, MA 02110-1301 USA
21b47b5b34SRafael Vanoni *
22b47b5b34SRafael Vanoni * Authors:
23b47b5b34SRafael Vanoni * Arjan van de Ven <arjan@linux.intel.com>
24b47b5b34SRafael Vanoni * Eric C Saxe <eric.saxe@sun.com>
25b47b5b34SRafael Vanoni * Aubrey Li <aubrey.li@intel.com>
26b47b5b34SRafael Vanoni */
27b47b5b34SRafael Vanoni
28b47b5b34SRafael Vanoni /*
29b47b5b34SRafael Vanoni * GPL Disclaimer
30b47b5b34SRafael Vanoni *
31b47b5b34SRafael Vanoni * For the avoidance of doubt, except that if any license choice other
32b47b5b34SRafael Vanoni * than GPL or LGPL is available it will apply instead, Sun elects to
33b47b5b34SRafael Vanoni * use only the General Public License version 2 (GPLv2) at this time
34b47b5b34SRafael Vanoni * for any software where a choice of GPL license versions is made
35b47b5b34SRafael Vanoni * available with the language indicating that GPLv2 or any later
36b47b5b34SRafael Vanoni * version may be used, or where a choice of which version of the GPL
37b47b5b34SRafael Vanoni * is applied is otherwise unspecified.
38b47b5b34SRafael Vanoni */
39b47b5b34SRafael Vanoni
40b47b5b34SRafael Vanoni #include <unistd.h>
41b47b5b34SRafael Vanoni #include <stdio.h>
42b47b5b34SRafael Vanoni #include <stdlib.h>
43b47b5b34SRafael Vanoni #include <string.h>
44b47b5b34SRafael Vanoni #include "powertop.h"
45b47b5b34SRafael Vanoni
469bbf5ba1SRafael Vanoni /*
479bbf5ba1SRafael Vanoni * Default number of intervals we display a suggestion before moving
489bbf5ba1SRafael Vanoni * to the next.
499bbf5ba1SRafael Vanoni */
509bbf5ba1SRafael Vanoni #define PT_SUGG_DEF_SLICE 3
51b47b5b34SRafael Vanoni
529bbf5ba1SRafael Vanoni /*
539bbf5ba1SRafael Vanoni * Global pointer to the current suggestion.
549bbf5ba1SRafael Vanoni */
559bbf5ba1SRafael Vanoni sugg_t *g_curr_sugg;
56b47b5b34SRafael Vanoni
579bbf5ba1SRafael Vanoni /*
589bbf5ba1SRafael Vanoni * Head of the list of suggestions.
599bbf5ba1SRafael Vanoni */
609bbf5ba1SRafael Vanoni static sugg_t *sugg;
61b47b5b34SRafael Vanoni
629bbf5ba1SRafael Vanoni /*
639bbf5ba1SRafael Vanoni * Add a new suggestion. Only one suggestion per text allowed.
649bbf5ba1SRafael Vanoni */
65b47b5b34SRafael Vanoni void
pt_sugg_add(char * text,int weight,char key,char * sb_msg,sugg_func_t * func)669bbf5ba1SRafael Vanoni pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func)
67b47b5b34SRafael Vanoni {
689bbf5ba1SRafael Vanoni sugg_t *new, *n, *pos = NULL;
69b47b5b34SRafael Vanoni
709bbf5ba1SRafael Vanoni /*
719bbf5ba1SRafael Vanoni * Text is a required field for suggestions
729bbf5ba1SRafael Vanoni */
739bbf5ba1SRafael Vanoni if (text == NULL)
74b47b5b34SRafael Vanoni return;
75b47b5b34SRafael Vanoni
769bbf5ba1SRafael Vanoni if (sugg == NULL) {
779bbf5ba1SRafael Vanoni /*
789bbf5ba1SRafael Vanoni * Creating first element
799bbf5ba1SRafael Vanoni */
809bbf5ba1SRafael Vanoni if ((new = calloc(1, sizeof (sugg_t))) == NULL)
81b47b5b34SRafael Vanoni return;
82b47b5b34SRafael Vanoni
839bbf5ba1SRafael Vanoni if (sb_msg != NULL)
849bbf5ba1SRafael Vanoni new->sb_msg = strdup(sb_msg);
85b47b5b34SRafael Vanoni
869bbf5ba1SRafael Vanoni if (text != NULL)
879bbf5ba1SRafael Vanoni new->text = strdup(text);
889bbf5ba1SRafael Vanoni
89b47b5b34SRafael Vanoni new->weight = weight;
90b47b5b34SRafael Vanoni new->key = key;
91b47b5b34SRafael Vanoni new->func = func;
929bbf5ba1SRafael Vanoni new->slice = 0;
939bbf5ba1SRafael Vanoni
949bbf5ba1SRafael Vanoni sugg = new;
959bbf5ba1SRafael Vanoni new->prev = NULL;
969bbf5ba1SRafael Vanoni new->next = NULL;
979bbf5ba1SRafael Vanoni } else {
989bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) {
999bbf5ba1SRafael Vanoni if (strcmp(n->text, text) == 0)
1009bbf5ba1SRafael Vanoni return;
1019bbf5ba1SRafael Vanoni
1029bbf5ba1SRafael Vanoni if (weight > n->weight && pos == NULL)
1039bbf5ba1SRafael Vanoni pos = n;
1049bbf5ba1SRafael Vanoni }
1059bbf5ba1SRafael Vanoni /*
1069bbf5ba1SRafael Vanoni * Create a new element
1079bbf5ba1SRafael Vanoni */
1089bbf5ba1SRafael Vanoni if ((new = calloc(1, sizeof (sugg_t))) == NULL)
1099bbf5ba1SRafael Vanoni return;
1109bbf5ba1SRafael Vanoni
1119bbf5ba1SRafael Vanoni if (sb_msg != NULL)
1129bbf5ba1SRafael Vanoni new->sb_msg = strdup(sb_msg);
1139bbf5ba1SRafael Vanoni
1149bbf5ba1SRafael Vanoni new->text = strdup(text);
1159bbf5ba1SRafael Vanoni
1169bbf5ba1SRafael Vanoni new->weight = weight;
1179bbf5ba1SRafael Vanoni new->key = key;
1189bbf5ba1SRafael Vanoni new->func = func;
1199bbf5ba1SRafael Vanoni new->slice = 0;
1209bbf5ba1SRafael Vanoni
1219bbf5ba1SRafael Vanoni if (pos == NULL) {
1229bbf5ba1SRafael Vanoni /*
1239bbf5ba1SRafael Vanoni * Ordering placed the new element at the end
1249bbf5ba1SRafael Vanoni */
1259bbf5ba1SRafael Vanoni for (n = sugg; n->next != NULL; n = n->next)
1269bbf5ba1SRafael Vanoni ;
1279bbf5ba1SRafael Vanoni
1289bbf5ba1SRafael Vanoni n->next = new;
1299bbf5ba1SRafael Vanoni new->prev = n;
1309bbf5ba1SRafael Vanoni new->next = NULL;
1319bbf5ba1SRafael Vanoni } else {
1329bbf5ba1SRafael Vanoni if (pos == sugg) {
1339bbf5ba1SRafael Vanoni /*
1349bbf5ba1SRafael Vanoni * Ordering placed the new element at the start
1359bbf5ba1SRafael Vanoni */
1369bbf5ba1SRafael Vanoni new->next = sugg;
1379bbf5ba1SRafael Vanoni new->prev = sugg;
1389bbf5ba1SRafael Vanoni sugg->prev = new;
1399bbf5ba1SRafael Vanoni sugg = new;
1409bbf5ba1SRafael Vanoni } else {
1419bbf5ba1SRafael Vanoni /*
1429bbf5ba1SRafael Vanoni * Ordering placed the new element somewhere in
1439bbf5ba1SRafael Vanoni * the middle
1449bbf5ba1SRafael Vanoni */
1459bbf5ba1SRafael Vanoni new->next = pos;
1469bbf5ba1SRafael Vanoni new->prev = pos->prev;
1479bbf5ba1SRafael Vanoni pos->prev->next = new;
1489bbf5ba1SRafael Vanoni pos->prev = new;
1499bbf5ba1SRafael Vanoni }
1509bbf5ba1SRafael Vanoni }
1519bbf5ba1SRafael Vanoni }
152b47b5b34SRafael Vanoni }
153b47b5b34SRafael Vanoni
1549bbf5ba1SRafael Vanoni /*
1559bbf5ba1SRafael Vanoni * Removes a suggestion, returning 0 if not found and 1 if so.
1569bbf5ba1SRafael Vanoni */
1579bbf5ba1SRafael Vanoni int
pt_sugg_remove(sugg_func_t * func)1589bbf5ba1SRafael Vanoni pt_sugg_remove(sugg_func_t *func)
159b47b5b34SRafael Vanoni {
1609bbf5ba1SRafael Vanoni sugg_t *n;
1619bbf5ba1SRafael Vanoni int ret = 0;
162b47b5b34SRafael Vanoni
1639bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) {
1649bbf5ba1SRafael Vanoni if (n->func == func) {
1659bbf5ba1SRafael Vanoni /* Removing the first element */
1669bbf5ba1SRafael Vanoni if (n == sugg) {
1679bbf5ba1SRafael Vanoni if (sugg->next == NULL) {
1689bbf5ba1SRafael Vanoni /* Removing the only element */
1699bbf5ba1SRafael Vanoni sugg = NULL;
1709bbf5ba1SRafael Vanoni } else {
1719bbf5ba1SRafael Vanoni sugg = n->next;
1729bbf5ba1SRafael Vanoni sugg->prev = NULL;
1739bbf5ba1SRafael Vanoni }
1749bbf5ba1SRafael Vanoni } else {
1759bbf5ba1SRafael Vanoni if (n->next == NULL) {
1769bbf5ba1SRafael Vanoni /* Removing the last element */
1779bbf5ba1SRafael Vanoni n->prev->next = NULL;
1789bbf5ba1SRafael Vanoni } else {
1799bbf5ba1SRafael Vanoni /* Removing an intermediate element */
1809bbf5ba1SRafael Vanoni n->prev->next = n->next;
1819bbf5ba1SRafael Vanoni n->next->prev = n->prev;
1829bbf5ba1SRafael Vanoni }
1839bbf5ba1SRafael Vanoni }
184b47b5b34SRafael Vanoni
1859bbf5ba1SRafael Vanoni /*
1869bbf5ba1SRafael Vanoni * If this suggestions is currently being suggested,
1879bbf5ba1SRafael Vanoni * remove it and update the screen.
1889bbf5ba1SRafael Vanoni */
1899bbf5ba1SRafael Vanoni if (n == g_curr_sugg) {
1909bbf5ba1SRafael Vanoni if (n->sb_msg != NULL) {
1919bbf5ba1SRafael Vanoni pt_display_mod_status_bar(n->sb_msg);
1929bbf5ba1SRafael Vanoni pt_display_status_bar();
1939bbf5ba1SRafael Vanoni }
1949bbf5ba1SRafael Vanoni if (n->text != NULL)
1959bbf5ba1SRafael Vanoni pt_display_suggestions(NULL);
1969bbf5ba1SRafael Vanoni }
1979bbf5ba1SRafael Vanoni
1989bbf5ba1SRafael Vanoni free(n);
1999bbf5ba1SRafael Vanoni ret = 1;
2009bbf5ba1SRafael Vanoni }
2019bbf5ba1SRafael Vanoni }
2029bbf5ba1SRafael Vanoni
2039bbf5ba1SRafael Vanoni return (ret);
2049bbf5ba1SRafael Vanoni }
2059bbf5ba1SRafael Vanoni
2069bbf5ba1SRafael Vanoni /*
2079bbf5ba1SRafael Vanoni * Chose a suggestion to display. The list of suggestions is ordered by weight,
2089bbf5ba1SRafael Vanoni * so we only worry about fariness here. Each suggestion, starting with the
2099bbf5ba1SRafael Vanoni * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals.
2109bbf5ba1SRafael Vanoni */
2119bbf5ba1SRafael Vanoni void
pt_sugg_pick(void)2129bbf5ba1SRafael Vanoni pt_sugg_pick(void)
2139bbf5ba1SRafael Vanoni {
2149bbf5ba1SRafael Vanoni sugg_t *n;
2159bbf5ba1SRafael Vanoni
2169bbf5ba1SRafael Vanoni if (sugg == NULL) {
2179bbf5ba1SRafael Vanoni g_curr_sugg = NULL;
218b47b5b34SRafael Vanoni return;
219b47b5b34SRafael Vanoni }
220b47b5b34SRafael Vanoni
2219bbf5ba1SRafael Vanoni search:
2229bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) {
223b47b5b34SRafael Vanoni
2249bbf5ba1SRafael Vanoni if (n->slice++ < PT_SUGG_DEF_SLICE) {
225b47b5b34SRafael Vanoni
2269bbf5ba1SRafael Vanoni /*
2279bbf5ba1SRafael Vanoni * Don't need to re-suggest the current suggestion.
2289bbf5ba1SRafael Vanoni */
229*2d83778aSRafael Vanoni if (g_curr_sugg == n && !g_sig_resize)
2309bbf5ba1SRafael Vanoni return;
231b47b5b34SRafael Vanoni
2329bbf5ba1SRafael Vanoni /*
2339bbf5ba1SRafael Vanoni * Remove the current suggestion from screen.
2349bbf5ba1SRafael Vanoni */
2359bbf5ba1SRafael Vanoni if (g_curr_sugg != NULL) {
2369bbf5ba1SRafael Vanoni if (g_curr_sugg->sb_msg != NULL) {
2379bbf5ba1SRafael Vanoni pt_display_mod_status_bar(
2389bbf5ba1SRafael Vanoni g_curr_sugg->sb_msg);
2399bbf5ba1SRafael Vanoni pt_display_status_bar();
240b47b5b34SRafael Vanoni }
2419bbf5ba1SRafael Vanoni if (g_curr_sugg->text != NULL)
2429bbf5ba1SRafael Vanoni pt_display_suggestions(NULL);
2439bbf5ba1SRafael Vanoni }
2449bbf5ba1SRafael Vanoni
2459bbf5ba1SRafael Vanoni if (n->sb_msg != NULL) {
2469bbf5ba1SRafael Vanoni pt_display_mod_status_bar(n->sb_msg);
2479bbf5ba1SRafael Vanoni pt_display_status_bar();
2489bbf5ba1SRafael Vanoni }
2499bbf5ba1SRafael Vanoni
2509bbf5ba1SRafael Vanoni pt_display_suggestions(n->text);
2519bbf5ba1SRafael Vanoni
2529bbf5ba1SRafael Vanoni g_curr_sugg = n;
2539bbf5ba1SRafael Vanoni
254b47b5b34SRafael Vanoni return;
255b47b5b34SRafael Vanoni }
256b47b5b34SRafael Vanoni }
257b47b5b34SRafael Vanoni
2589bbf5ba1SRafael Vanoni /*
2599bbf5ba1SRafael Vanoni * All suggestions have run out of slice quotas, so we restart.
2609bbf5ba1SRafael Vanoni */
2619bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next)
2629bbf5ba1SRafael Vanoni n->slice = 0;
2639bbf5ba1SRafael Vanoni
2649bbf5ba1SRafael Vanoni goto search;
265b47b5b34SRafael Vanoni }
266b47b5b34SRafael Vanoni
267b47b5b34SRafael Vanoni void
pt_sugg_as_root(void)2689bbf5ba1SRafael Vanoni pt_sugg_as_root(void)
269b47b5b34SRafael Vanoni {
2709bbf5ba1SRafael Vanoni pt_sugg_add("Suggestion: run as root to get suggestions"
2719bbf5ba1SRafael Vanoni " for reducing system power consumption", 40, NULL, NULL,
2729bbf5ba1SRafael Vanoni NULL);
273b47b5b34SRafael Vanoni }
274