1bcde4861SRafael Vanoni Polanczyk /*
2b47b5b34SRafael Vanoni * Copyright 2009, Intel Corporation
3b47b5b34SRafael Vanoni * Copyright 2009, Sun Microsystems, Inc
4bcde4861SRafael Vanoni Polanczyk *
5bcde4861SRafael Vanoni Polanczyk * This file is part of PowerTOP
6bcde4861SRafael Vanoni Polanczyk *
7bcde4861SRafael Vanoni Polanczyk * This program file is free software; you can redistribute it and/or modify it
8bcde4861SRafael Vanoni Polanczyk * under the terms of the GNU General Public License as published by the
9bcde4861SRafael Vanoni Polanczyk * Free Software Foundation; version 2 of the License.
10bcde4861SRafael Vanoni Polanczyk *
11bcde4861SRafael Vanoni Polanczyk * This program is distributed in the hope that it will be useful, but WITHOUT
12bcde4861SRafael Vanoni Polanczyk * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13bcde4861SRafael Vanoni Polanczyk * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14bcde4861SRafael Vanoni Polanczyk * for more details.
15bcde4861SRafael Vanoni Polanczyk *
16bcde4861SRafael Vanoni Polanczyk * You should have received a copy of the GNU General Public License
17bcde4861SRafael Vanoni Polanczyk * along with this program in a file named COPYING; if not, write to the
18bcde4861SRafael Vanoni Polanczyk * Free Software Foundation, Inc.,
19bcde4861SRafael Vanoni Polanczyk * 51 Franklin Street, Fifth Floor,
20bcde4861SRafael Vanoni Polanczyk * Boston, MA 02110-1301 USA
21bcde4861SRafael Vanoni Polanczyk *
22bcde4861SRafael Vanoni Polanczyk * Authors:
23bcde4861SRafael Vanoni Polanczyk * Arjan van de Ven <arjan@linux.intel.com>
24bcde4861SRafael Vanoni Polanczyk * Eric C Saxe <eric.saxe@sun.com>
25bcde4861SRafael Vanoni Polanczyk * Aubrey Li <aubrey.li@intel.com>
26bcde4861SRafael Vanoni Polanczyk */
27bcde4861SRafael Vanoni Polanczyk
28bcde4861SRafael Vanoni Polanczyk /*
29bcde4861SRafael Vanoni Polanczyk * GPL Disclaimer
30bcde4861SRafael Vanoni Polanczyk *
31bcde4861SRafael Vanoni Polanczyk * For the avoidance of doubt, except that if any license choice other
32bcde4861SRafael Vanoni Polanczyk * than GPL or LGPL is available it will apply instead, Sun elects to
33bcde4861SRafael Vanoni Polanczyk * use only the General Public License version 2 (GPLv2) at this time
34bcde4861SRafael Vanoni Polanczyk * for any software where a choice of GPL license versions is made
35bcde4861SRafael Vanoni Polanczyk * available with the language indicating that GPLv2 or any later
36bcde4861SRafael Vanoni Polanczyk * version may be used, or where a choice of which version of the GPL
37bcde4861SRafael Vanoni Polanczyk * is applied is otherwise unspecified.
38bcde4861SRafael Vanoni Polanczyk */
39bcde4861SRafael Vanoni Polanczyk
40bcde4861SRafael Vanoni Polanczyk #include <unistd.h>
41bcde4861SRafael Vanoni Polanczyk #include <stdio.h>
42bcde4861SRafael Vanoni Polanczyk #include <stdlib.h>
43bcde4861SRafael Vanoni Polanczyk #include <string.h>
44bcde4861SRafael Vanoni Polanczyk #include "powertop.h"
45bcde4861SRafael Vanoni Polanczyk
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
51bcde4861SRafael Vanoni Polanczyk
529bbf5ba1SRafael Vanoni /*
539bbf5ba1SRafael Vanoni * Global pointer to the current suggestion.
549bbf5ba1SRafael Vanoni */
559bbf5ba1SRafael Vanoni sugg_t *g_curr_sugg;
56bcde4861SRafael Vanoni Polanczyk
579bbf5ba1SRafael Vanoni /*
589bbf5ba1SRafael Vanoni * Head of the list of suggestions.
599bbf5ba1SRafael Vanoni */
609bbf5ba1SRafael Vanoni static sugg_t *sugg;
61bcde4861SRafael Vanoni Polanczyk
629bbf5ba1SRafael Vanoni /*
639bbf5ba1SRafael Vanoni * Add a new suggestion. Only one suggestion per text allowed.
649bbf5ba1SRafael Vanoni */
65bcde4861SRafael Vanoni Polanczyk 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)
67bcde4861SRafael Vanoni Polanczyk {
689bbf5ba1SRafael Vanoni sugg_t *new, *n, *pos = NULL;
69bcde4861SRafael Vanoni Polanczyk
709bbf5ba1SRafael Vanoni /*
719bbf5ba1SRafael Vanoni * Text is a required field for suggestions
729bbf5ba1SRafael Vanoni */
739bbf5ba1SRafael Vanoni if (text == NULL)
749bbf5ba1SRafael Vanoni return;
75bcde4861SRafael Vanoni Polanczyk
769bbf5ba1SRafael Vanoni if (sugg == NULL) {
779bbf5ba1SRafael Vanoni /*
789bbf5ba1SRafael Vanoni * Creating first element
799bbf5ba1SRafael Vanoni */
809bbf5ba1SRafael Vanoni if ((new = calloc(1, sizeof (sugg_t))) == NULL)
819bbf5ba1SRafael Vanoni return;
82bcde4861SRafael Vanoni Polanczyk
839bbf5ba1SRafael Vanoni if (sb_msg != NULL)
849bbf5ba1SRafael Vanoni new->sb_msg = strdup(sb_msg);
85bcde4861SRafael Vanoni Polanczyk
869bbf5ba1SRafael Vanoni if (text != NULL)
879bbf5ba1SRafael Vanoni new->text = strdup(text);
88bcde4861SRafael Vanoni Polanczyk
899bbf5ba1SRafael Vanoni new->weight = weight;
909bbf5ba1SRafael Vanoni new->key = key;
919bbf5ba1SRafael Vanoni new->func = func;
929bbf5ba1SRafael Vanoni new->slice = 0;
93bcde4861SRafael Vanoni Polanczyk
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;
101bcde4861SRafael Vanoni Polanczyk
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;
110bcde4861SRafael Vanoni Polanczyk
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 }
1529bbf5ba1SRafael Vanoni }
153bcde4861SRafael Vanoni Polanczyk
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)
1599bbf5ba1SRafael Vanoni {
1609bbf5ba1SRafael Vanoni sugg_t *n;
1619bbf5ba1SRafael Vanoni int ret = 0;
1629bbf5ba1SRafael 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 }
184bcde4861SRafael Vanoni Polanczyk
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 }
197bcde4861SRafael Vanoni Polanczyk
1989bbf5ba1SRafael Vanoni free(n);
1999bbf5ba1SRafael Vanoni ret = 1;
2009bbf5ba1SRafael Vanoni }
2019bbf5ba1SRafael Vanoni }
202bcde4861SRafael Vanoni Polanczyk
2039bbf5ba1SRafael Vanoni return (ret);
204bcde4861SRafael Vanoni Polanczyk }
205bcde4861SRafael Vanoni Polanczyk
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 */
211bcde4861SRafael Vanoni Polanczyk void
pt_sugg_pick(void)2129bbf5ba1SRafael Vanoni pt_sugg_pick(void)
213bcde4861SRafael Vanoni Polanczyk {
2149bbf5ba1SRafael Vanoni sugg_t *n;
215bcde4861SRafael Vanoni Polanczyk
2169bbf5ba1SRafael Vanoni if (sugg == NULL) {
2179bbf5ba1SRafael Vanoni g_curr_sugg = NULL;
218bcde4861SRafael Vanoni Polanczyk return;
219bcde4861SRafael Vanoni Polanczyk }
220bcde4861SRafael Vanoni Polanczyk
2219bbf5ba1SRafael Vanoni search:
2229bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) {
2239bbf5ba1SRafael Vanoni
2249bbf5ba1SRafael Vanoni if (n->slice++ < PT_SUGG_DEF_SLICE) {
2259bbf5ba1SRafael Vanoni
2269bbf5ba1SRafael Vanoni /*
2279bbf5ba1SRafael Vanoni * Don't need to re-suggest the current suggestion.
2289bbf5ba1SRafael Vanoni */
2292d83778aSRafael Vanoni if (g_curr_sugg == n && !g_sig_resize)
2309bbf5ba1SRafael Vanoni return;
2319bbf5ba1SRafael 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();
2409bbf5ba1SRafael Vanoni }
2419bbf5ba1SRafael Vanoni if (g_curr_sugg->text != NULL)
2429bbf5ba1SRafael Vanoni pt_display_suggestions(NULL);
2439bbf5ba1SRafael Vanoni }
244bcde4861SRafael Vanoni Polanczyk
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 }
249bcde4861SRafael Vanoni Polanczyk
2509bbf5ba1SRafael Vanoni pt_display_suggestions(n->text);
251bcde4861SRafael Vanoni Polanczyk
2529bbf5ba1SRafael Vanoni g_curr_sugg = n;
253bcde4861SRafael Vanoni Polanczyk
254bcde4861SRafael Vanoni Polanczyk return;
255bcde4861SRafael Vanoni Polanczyk }
256bcde4861SRafael Vanoni Polanczyk }
257bcde4861SRafael Vanoni Polanczyk
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;
265bcde4861SRafael Vanoni Polanczyk }
266bcde4861SRafael Vanoni Polanczyk
267bcde4861SRafael Vanoni Polanczyk void
pt_sugg_as_root(void)2689bbf5ba1SRafael Vanoni pt_sugg_as_root(void)
269bcde4861SRafael Vanoni Polanczyk {
2709bbf5ba1SRafael Vanoni pt_sugg_add("Suggestion: run as root to get suggestions"
271*f795e601SToomas Soome " for reducing system power consumption", 40, 0, NULL,
2729bbf5ba1SRafael Vanoni NULL);
273bcde4861SRafael Vanoni Polanczyk }
274