19338Srafael.vanoni@sun.com /*
29338Srafael.vanoni@sun.com * Copyright 2009, Intel Corporation
39338Srafael.vanoni@sun.com * Copyright 2009, Sun Microsystems, Inc
49338Srafael.vanoni@sun.com *
59338Srafael.vanoni@sun.com * This file is part of PowerTOP
69338Srafael.vanoni@sun.com *
79338Srafael.vanoni@sun.com * This program file is free software; you can redistribute it and/or modify it
89338Srafael.vanoni@sun.com * under the terms of the GNU General Public License as published by the
99338Srafael.vanoni@sun.com * Free Software Foundation; version 2 of the License.
109338Srafael.vanoni@sun.com *
119338Srafael.vanoni@sun.com * This program is distributed in the hope that it will be useful, but WITHOUT
129338Srafael.vanoni@sun.com * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
139338Srafael.vanoni@sun.com * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
149338Srafael.vanoni@sun.com * for more details.
159338Srafael.vanoni@sun.com *
169338Srafael.vanoni@sun.com * You should have received a copy of the GNU General Public License
179338Srafael.vanoni@sun.com * along with this program in a file named COPYING; if not, write to the
189338Srafael.vanoni@sun.com * Free Software Foundation, Inc.,
199338Srafael.vanoni@sun.com * 51 Franklin Street, Fifth Floor,
209338Srafael.vanoni@sun.com * Boston, MA 02110-1301 USA
219338Srafael.vanoni@sun.com *
229338Srafael.vanoni@sun.com * Authors:
239338Srafael.vanoni@sun.com * Arjan van de Ven <arjan@linux.intel.com>
249338Srafael.vanoni@sun.com * Eric C Saxe <eric.saxe@sun.com>
259338Srafael.vanoni@sun.com * Aubrey Li <aubrey.li@intel.com>
269338Srafael.vanoni@sun.com */
279338Srafael.vanoni@sun.com
289338Srafael.vanoni@sun.com /*
299338Srafael.vanoni@sun.com * GPL Disclaimer
309338Srafael.vanoni@sun.com *
319338Srafael.vanoni@sun.com * For the avoidance of doubt, except that if any license choice other
329338Srafael.vanoni@sun.com * than GPL or LGPL is available it will apply instead, Sun elects to
339338Srafael.vanoni@sun.com * use only the General Public License version 2 (GPLv2) at this time
349338Srafael.vanoni@sun.com * for any software where a choice of GPL license versions is made
359338Srafael.vanoni@sun.com * available with the language indicating that GPLv2 or any later
369338Srafael.vanoni@sun.com * version may be used, or where a choice of which version of the GPL
379338Srafael.vanoni@sun.com * is applied is otherwise unspecified.
389338Srafael.vanoni@sun.com */
399338Srafael.vanoni@sun.com
409338Srafael.vanoni@sun.com #include <unistd.h>
419338Srafael.vanoni@sun.com #include <stdio.h>
429338Srafael.vanoni@sun.com #include <stdlib.h>
439338Srafael.vanoni@sun.com #include <string.h>
449338Srafael.vanoni@sun.com #include "powertop.h"
459338Srafael.vanoni@sun.com
469908Srafael.vanoni@sun.com /*
479908Srafael.vanoni@sun.com * Default number of intervals we display a suggestion before moving
489908Srafael.vanoni@sun.com * to the next.
499908Srafael.vanoni@sun.com */
509908Srafael.vanoni@sun.com #define PT_SUGG_DEF_SLICE 3
519908Srafael.vanoni@sun.com
529908Srafael.vanoni@sun.com /*
539908Srafael.vanoni@sun.com * Global pointer to the current suggestion.
549908Srafael.vanoni@sun.com */
559908Srafael.vanoni@sun.com sugg_t *g_curr_sugg;
569908Srafael.vanoni@sun.com
579908Srafael.vanoni@sun.com /*
589908Srafael.vanoni@sun.com * Head of the list of suggestions.
599908Srafael.vanoni@sun.com */
609908Srafael.vanoni@sun.com static sugg_t *sugg;
619338Srafael.vanoni@sun.com
629908Srafael.vanoni@sun.com /*
639908Srafael.vanoni@sun.com * Add a new suggestion. Only one suggestion per text allowed.
649908Srafael.vanoni@sun.com */
659908Srafael.vanoni@sun.com void
pt_sugg_add(char * text,int weight,char key,char * sb_msg,sugg_func_t * func)669908Srafael.vanoni@sun.com pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func)
679908Srafael.vanoni@sun.com {
689908Srafael.vanoni@sun.com sugg_t *new, *n, *pos = NULL;
699908Srafael.vanoni@sun.com
709908Srafael.vanoni@sun.com /*
719908Srafael.vanoni@sun.com * Text is a required field for suggestions
729908Srafael.vanoni@sun.com */
739908Srafael.vanoni@sun.com if (text == NULL)
749908Srafael.vanoni@sun.com return;
759908Srafael.vanoni@sun.com
769908Srafael.vanoni@sun.com if (sugg == NULL) {
779908Srafael.vanoni@sun.com /*
789908Srafael.vanoni@sun.com * Creating first element
799908Srafael.vanoni@sun.com */
809908Srafael.vanoni@sun.com if ((new = calloc(1, sizeof (sugg_t))) == NULL)
819908Srafael.vanoni@sun.com return;
829338Srafael.vanoni@sun.com
839908Srafael.vanoni@sun.com if (sb_msg != NULL)
849908Srafael.vanoni@sun.com new->sb_msg = strdup(sb_msg);
859908Srafael.vanoni@sun.com
869908Srafael.vanoni@sun.com if (text != NULL)
879908Srafael.vanoni@sun.com new->text = strdup(text);
889908Srafael.vanoni@sun.com
899908Srafael.vanoni@sun.com new->weight = weight;
909908Srafael.vanoni@sun.com new->key = key;
919908Srafael.vanoni@sun.com new->func = func;
929908Srafael.vanoni@sun.com new->slice = 0;
939908Srafael.vanoni@sun.com
949908Srafael.vanoni@sun.com sugg = new;
959908Srafael.vanoni@sun.com new->prev = NULL;
969908Srafael.vanoni@sun.com new->next = NULL;
979908Srafael.vanoni@sun.com } else {
989908Srafael.vanoni@sun.com for (n = sugg; n != NULL; n = n->next) {
999908Srafael.vanoni@sun.com if (strcmp(n->text, text) == 0)
1009908Srafael.vanoni@sun.com return;
1019338Srafael.vanoni@sun.com
1029908Srafael.vanoni@sun.com if (weight > n->weight && pos == NULL)
1039908Srafael.vanoni@sun.com pos = n;
1049908Srafael.vanoni@sun.com }
1059908Srafael.vanoni@sun.com /*
1069908Srafael.vanoni@sun.com * Create a new element
1079908Srafael.vanoni@sun.com */
1089908Srafael.vanoni@sun.com if ((new = calloc(1, sizeof (sugg_t))) == NULL)
1099908Srafael.vanoni@sun.com return;
1109338Srafael.vanoni@sun.com
1119908Srafael.vanoni@sun.com if (sb_msg != NULL)
1129908Srafael.vanoni@sun.com new->sb_msg = strdup(sb_msg);
1139908Srafael.vanoni@sun.com
1149908Srafael.vanoni@sun.com new->text = strdup(text);
1159908Srafael.vanoni@sun.com
1169908Srafael.vanoni@sun.com new->weight = weight;
1179908Srafael.vanoni@sun.com new->key = key;
1189908Srafael.vanoni@sun.com new->func = func;
1199908Srafael.vanoni@sun.com new->slice = 0;
1209338Srafael.vanoni@sun.com
1219908Srafael.vanoni@sun.com if (pos == NULL) {
1229908Srafael.vanoni@sun.com /*
1239908Srafael.vanoni@sun.com * Ordering placed the new element at the end
1249908Srafael.vanoni@sun.com */
1259908Srafael.vanoni@sun.com for (n = sugg; n->next != NULL; n = n->next)
1269908Srafael.vanoni@sun.com ;
1279338Srafael.vanoni@sun.com
1289908Srafael.vanoni@sun.com n->next = new;
1299908Srafael.vanoni@sun.com new->prev = n;
1309908Srafael.vanoni@sun.com new->next = NULL;
1319908Srafael.vanoni@sun.com } else {
1329908Srafael.vanoni@sun.com if (pos == sugg) {
1339908Srafael.vanoni@sun.com /*
1349908Srafael.vanoni@sun.com * Ordering placed the new element at the start
1359908Srafael.vanoni@sun.com */
1369908Srafael.vanoni@sun.com new->next = sugg;
1379908Srafael.vanoni@sun.com new->prev = sugg;
1389908Srafael.vanoni@sun.com sugg->prev = new;
1399908Srafael.vanoni@sun.com sugg = new;
1409908Srafael.vanoni@sun.com } else {
1419908Srafael.vanoni@sun.com /*
1429908Srafael.vanoni@sun.com * Ordering placed the new element somewhere in
1439908Srafael.vanoni@sun.com * the middle
1449908Srafael.vanoni@sun.com */
1459908Srafael.vanoni@sun.com new->next = pos;
1469908Srafael.vanoni@sun.com new->prev = pos->prev;
1479908Srafael.vanoni@sun.com pos->prev->next = new;
1489908Srafael.vanoni@sun.com pos->prev = new;
1499908Srafael.vanoni@sun.com }
1509908Srafael.vanoni@sun.com }
1519908Srafael.vanoni@sun.com }
1529908Srafael.vanoni@sun.com }
1539338Srafael.vanoni@sun.com
1549908Srafael.vanoni@sun.com /*
1559908Srafael.vanoni@sun.com * Removes a suggestion, returning 0 if not found and 1 if so.
1569908Srafael.vanoni@sun.com */
1579908Srafael.vanoni@sun.com int
pt_sugg_remove(sugg_func_t * func)1589908Srafael.vanoni@sun.com pt_sugg_remove(sugg_func_t *func)
1599908Srafael.vanoni@sun.com {
1609908Srafael.vanoni@sun.com sugg_t *n;
1619908Srafael.vanoni@sun.com int ret = 0;
1629338Srafael.vanoni@sun.com
1639908Srafael.vanoni@sun.com for (n = sugg; n != NULL; n = n->next) {
1649908Srafael.vanoni@sun.com if (n->func == func) {
1659908Srafael.vanoni@sun.com /* Removing the first element */
1669908Srafael.vanoni@sun.com if (n == sugg) {
1679908Srafael.vanoni@sun.com if (sugg->next == NULL) {
1689908Srafael.vanoni@sun.com /* Removing the only element */
1699908Srafael.vanoni@sun.com sugg = NULL;
1709908Srafael.vanoni@sun.com } else {
1719908Srafael.vanoni@sun.com sugg = n->next;
1729908Srafael.vanoni@sun.com sugg->prev = NULL;
1739908Srafael.vanoni@sun.com }
1749908Srafael.vanoni@sun.com } else {
1759908Srafael.vanoni@sun.com if (n->next == NULL) {
1769908Srafael.vanoni@sun.com /* Removing the last element */
1779908Srafael.vanoni@sun.com n->prev->next = NULL;
1789908Srafael.vanoni@sun.com } else {
1799908Srafael.vanoni@sun.com /* Removing an intermediate element */
1809908Srafael.vanoni@sun.com n->prev->next = n->next;
1819908Srafael.vanoni@sun.com n->next->prev = n->prev;
1829908Srafael.vanoni@sun.com }
1839908Srafael.vanoni@sun.com }
1849908Srafael.vanoni@sun.com
1859908Srafael.vanoni@sun.com /*
1869908Srafael.vanoni@sun.com * If this suggestions is currently being suggested,
1879908Srafael.vanoni@sun.com * remove it and update the screen.
1889908Srafael.vanoni@sun.com */
1899908Srafael.vanoni@sun.com if (n == g_curr_sugg) {
1909908Srafael.vanoni@sun.com if (n->sb_msg != NULL) {
1919908Srafael.vanoni@sun.com pt_display_mod_status_bar(n->sb_msg);
1929908Srafael.vanoni@sun.com pt_display_status_bar();
1939908Srafael.vanoni@sun.com }
1949908Srafael.vanoni@sun.com if (n->text != NULL)
1959908Srafael.vanoni@sun.com pt_display_suggestions(NULL);
1969908Srafael.vanoni@sun.com }
1979908Srafael.vanoni@sun.com
1989908Srafael.vanoni@sun.com free(n);
1999908Srafael.vanoni@sun.com ret = 1;
2009908Srafael.vanoni@sun.com }
2019338Srafael.vanoni@sun.com }
2029338Srafael.vanoni@sun.com
2039908Srafael.vanoni@sun.com return (ret);
2049908Srafael.vanoni@sun.com }
2059908Srafael.vanoni@sun.com
2069908Srafael.vanoni@sun.com /*
2079908Srafael.vanoni@sun.com * Chose a suggestion to display. The list of suggestions is ordered by weight,
2089908Srafael.vanoni@sun.com * so we only worry about fariness here. Each suggestion, starting with the
2099908Srafael.vanoni@sun.com * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals.
2109908Srafael.vanoni@sun.com */
2119908Srafael.vanoni@sun.com void
pt_sugg_pick(void)2129908Srafael.vanoni@sun.com pt_sugg_pick(void)
2139908Srafael.vanoni@sun.com {
2149908Srafael.vanoni@sun.com sugg_t *n;
2159908Srafael.vanoni@sun.com
2169908Srafael.vanoni@sun.com if (sugg == NULL) {
2179908Srafael.vanoni@sun.com g_curr_sugg = NULL;
2189908Srafael.vanoni@sun.com return;
2199908Srafael.vanoni@sun.com }
2209908Srafael.vanoni@sun.com
2219908Srafael.vanoni@sun.com search:
2229908Srafael.vanoni@sun.com for (n = sugg; n != NULL; n = n->next) {
2239908Srafael.vanoni@sun.com
2249908Srafael.vanoni@sun.com if (n->slice++ < PT_SUGG_DEF_SLICE) {
2259908Srafael.vanoni@sun.com
2269908Srafael.vanoni@sun.com /*
2279908Srafael.vanoni@sun.com * Don't need to re-suggest the current suggestion.
2289908Srafael.vanoni@sun.com */
229*11122Srafael.vanoni@sun.com if (g_curr_sugg == n && !g_sig_resize)
2309908Srafael.vanoni@sun.com return;
2319338Srafael.vanoni@sun.com
2329908Srafael.vanoni@sun.com /*
2339908Srafael.vanoni@sun.com * Remove the current suggestion from screen.
2349908Srafael.vanoni@sun.com */
2359908Srafael.vanoni@sun.com if (g_curr_sugg != NULL) {
2369908Srafael.vanoni@sun.com if (g_curr_sugg->sb_msg != NULL) {
2379908Srafael.vanoni@sun.com pt_display_mod_status_bar(
2389908Srafael.vanoni@sun.com g_curr_sugg->sb_msg);
2399908Srafael.vanoni@sun.com pt_display_status_bar();
2409908Srafael.vanoni@sun.com }
2419908Srafael.vanoni@sun.com if (g_curr_sugg->text != NULL)
2429908Srafael.vanoni@sun.com pt_display_suggestions(NULL);
2439908Srafael.vanoni@sun.com }
2449908Srafael.vanoni@sun.com
2459908Srafael.vanoni@sun.com if (n->sb_msg != NULL) {
2469908Srafael.vanoni@sun.com pt_display_mod_status_bar(n->sb_msg);
2479908Srafael.vanoni@sun.com pt_display_status_bar();
2489908Srafael.vanoni@sun.com }
2499908Srafael.vanoni@sun.com
2509908Srafael.vanoni@sun.com pt_display_suggestions(n->text);
2519908Srafael.vanoni@sun.com
2529908Srafael.vanoni@sun.com g_curr_sugg = n;
2539908Srafael.vanoni@sun.com
2549908Srafael.vanoni@sun.com return;
2559908Srafael.vanoni@sun.com }
2569908Srafael.vanoni@sun.com }
2579908Srafael.vanoni@sun.com
2589908Srafael.vanoni@sun.com /*
2599908Srafael.vanoni@sun.com * All suggestions have run out of slice quotas, so we restart.
2609908Srafael.vanoni@sun.com */
2619908Srafael.vanoni@sun.com for (n = sugg; n != NULL; n = n->next)
2629908Srafael.vanoni@sun.com n->slice = 0;
2639908Srafael.vanoni@sun.com
2649908Srafael.vanoni@sun.com goto search;
2659338Srafael.vanoni@sun.com }
2669338Srafael.vanoni@sun.com
2679338Srafael.vanoni@sun.com void
pt_sugg_as_root(void)2689908Srafael.vanoni@sun.com pt_sugg_as_root(void)
2699338Srafael.vanoni@sun.com {
2709908Srafael.vanoni@sun.com pt_sugg_add("Suggestion: run as root to get suggestions"
2719908Srafael.vanoni@sun.com " for reducing system power consumption", 40, NULL, NULL,
2729908Srafael.vanoni@sun.com NULL);
2739338Srafael.vanoni@sun.com }
274