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 46*9bbf5ba1SRafael Vanoni /* 47*9bbf5ba1SRafael Vanoni * Default number of intervals we display a suggestion before moving 48*9bbf5ba1SRafael Vanoni * to the next. 49*9bbf5ba1SRafael Vanoni */ 50*9bbf5ba1SRafael Vanoni #define PT_SUGG_DEF_SLICE 3 51b47b5b34SRafael Vanoni 52*9bbf5ba1SRafael Vanoni /* 53*9bbf5ba1SRafael Vanoni * Global pointer to the current suggestion. 54*9bbf5ba1SRafael Vanoni */ 55*9bbf5ba1SRafael Vanoni sugg_t *g_curr_sugg; 56b47b5b34SRafael Vanoni 57*9bbf5ba1SRafael Vanoni /* 58*9bbf5ba1SRafael Vanoni * Head of the list of suggestions. 59*9bbf5ba1SRafael Vanoni */ 60*9bbf5ba1SRafael Vanoni static sugg_t *sugg; 61b47b5b34SRafael Vanoni 62*9bbf5ba1SRafael Vanoni /* 63*9bbf5ba1SRafael Vanoni * Add a new suggestion. Only one suggestion per text allowed. 64*9bbf5ba1SRafael Vanoni */ 65b47b5b34SRafael Vanoni void 66*9bbf5ba1SRafael Vanoni pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func) 67b47b5b34SRafael Vanoni { 68*9bbf5ba1SRafael Vanoni sugg_t *new, *n, *pos = NULL; 69b47b5b34SRafael Vanoni 70*9bbf5ba1SRafael Vanoni /* 71*9bbf5ba1SRafael Vanoni * Text is a required field for suggestions 72*9bbf5ba1SRafael Vanoni */ 73*9bbf5ba1SRafael Vanoni if (text == NULL) 74b47b5b34SRafael Vanoni return; 75b47b5b34SRafael Vanoni 76*9bbf5ba1SRafael Vanoni if (sugg == NULL) { 77*9bbf5ba1SRafael Vanoni /* 78*9bbf5ba1SRafael Vanoni * Creating first element 79*9bbf5ba1SRafael Vanoni */ 80*9bbf5ba1SRafael Vanoni if ((new = calloc(1, sizeof (sugg_t))) == NULL) 81b47b5b34SRafael Vanoni return; 82b47b5b34SRafael Vanoni 83*9bbf5ba1SRafael Vanoni if (sb_msg != NULL) 84*9bbf5ba1SRafael Vanoni new->sb_msg = strdup(sb_msg); 85b47b5b34SRafael Vanoni 86*9bbf5ba1SRafael Vanoni if (text != NULL) 87*9bbf5ba1SRafael Vanoni new->text = strdup(text); 88*9bbf5ba1SRafael Vanoni 89b47b5b34SRafael Vanoni new->weight = weight; 90b47b5b34SRafael Vanoni new->key = key; 91b47b5b34SRafael Vanoni new->func = func; 92*9bbf5ba1SRafael Vanoni new->slice = 0; 93*9bbf5ba1SRafael Vanoni 94*9bbf5ba1SRafael Vanoni sugg = new; 95*9bbf5ba1SRafael Vanoni new->prev = NULL; 96*9bbf5ba1SRafael Vanoni new->next = NULL; 97*9bbf5ba1SRafael Vanoni } else { 98*9bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) { 99*9bbf5ba1SRafael Vanoni if (strcmp(n->text, text) == 0) 100*9bbf5ba1SRafael Vanoni return; 101*9bbf5ba1SRafael Vanoni 102*9bbf5ba1SRafael Vanoni if (weight > n->weight && pos == NULL) 103*9bbf5ba1SRafael Vanoni pos = n; 104*9bbf5ba1SRafael Vanoni } 105*9bbf5ba1SRafael Vanoni /* 106*9bbf5ba1SRafael Vanoni * Create a new element 107*9bbf5ba1SRafael Vanoni */ 108*9bbf5ba1SRafael Vanoni if ((new = calloc(1, sizeof (sugg_t))) == NULL) 109*9bbf5ba1SRafael Vanoni return; 110*9bbf5ba1SRafael Vanoni 111*9bbf5ba1SRafael Vanoni if (sb_msg != NULL) 112*9bbf5ba1SRafael Vanoni new->sb_msg = strdup(sb_msg); 113*9bbf5ba1SRafael Vanoni 114*9bbf5ba1SRafael Vanoni new->text = strdup(text); 115*9bbf5ba1SRafael Vanoni 116*9bbf5ba1SRafael Vanoni new->weight = weight; 117*9bbf5ba1SRafael Vanoni new->key = key; 118*9bbf5ba1SRafael Vanoni new->func = func; 119*9bbf5ba1SRafael Vanoni new->slice = 0; 120*9bbf5ba1SRafael Vanoni 121*9bbf5ba1SRafael Vanoni if (pos == NULL) { 122*9bbf5ba1SRafael Vanoni /* 123*9bbf5ba1SRafael Vanoni * Ordering placed the new element at the end 124*9bbf5ba1SRafael Vanoni */ 125*9bbf5ba1SRafael Vanoni for (n = sugg; n->next != NULL; n = n->next) 126*9bbf5ba1SRafael Vanoni ; 127*9bbf5ba1SRafael Vanoni 128*9bbf5ba1SRafael Vanoni n->next = new; 129*9bbf5ba1SRafael Vanoni new->prev = n; 130*9bbf5ba1SRafael Vanoni new->next = NULL; 131*9bbf5ba1SRafael Vanoni } else { 132*9bbf5ba1SRafael Vanoni if (pos == sugg) { 133*9bbf5ba1SRafael Vanoni /* 134*9bbf5ba1SRafael Vanoni * Ordering placed the new element at the start 135*9bbf5ba1SRafael Vanoni */ 136*9bbf5ba1SRafael Vanoni new->next = sugg; 137*9bbf5ba1SRafael Vanoni new->prev = sugg; 138*9bbf5ba1SRafael Vanoni sugg->prev = new; 139*9bbf5ba1SRafael Vanoni sugg = new; 140*9bbf5ba1SRafael Vanoni } else { 141*9bbf5ba1SRafael Vanoni /* 142*9bbf5ba1SRafael Vanoni * Ordering placed the new element somewhere in 143*9bbf5ba1SRafael Vanoni * the middle 144*9bbf5ba1SRafael Vanoni */ 145*9bbf5ba1SRafael Vanoni new->next = pos; 146*9bbf5ba1SRafael Vanoni new->prev = pos->prev; 147*9bbf5ba1SRafael Vanoni pos->prev->next = new; 148*9bbf5ba1SRafael Vanoni pos->prev = new; 149*9bbf5ba1SRafael Vanoni } 150*9bbf5ba1SRafael Vanoni } 151*9bbf5ba1SRafael Vanoni } 152b47b5b34SRafael Vanoni } 153b47b5b34SRafael Vanoni 154*9bbf5ba1SRafael Vanoni /* 155*9bbf5ba1SRafael Vanoni * Removes a suggestion, returning 0 if not found and 1 if so. 156*9bbf5ba1SRafael Vanoni */ 157*9bbf5ba1SRafael Vanoni int 158*9bbf5ba1SRafael Vanoni pt_sugg_remove(sugg_func_t *func) 159b47b5b34SRafael Vanoni { 160*9bbf5ba1SRafael Vanoni sugg_t *n; 161*9bbf5ba1SRafael Vanoni int ret = 0; 162b47b5b34SRafael Vanoni 163*9bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) { 164*9bbf5ba1SRafael Vanoni if (n->func == func) { 165*9bbf5ba1SRafael Vanoni /* Removing the first element */ 166*9bbf5ba1SRafael Vanoni if (n == sugg) { 167*9bbf5ba1SRafael Vanoni if (sugg->next == NULL) { 168*9bbf5ba1SRafael Vanoni /* Removing the only element */ 169*9bbf5ba1SRafael Vanoni sugg = NULL; 170*9bbf5ba1SRafael Vanoni } else { 171*9bbf5ba1SRafael Vanoni sugg = n->next; 172*9bbf5ba1SRafael Vanoni sugg->prev = NULL; 173*9bbf5ba1SRafael Vanoni } 174*9bbf5ba1SRafael Vanoni } else { 175*9bbf5ba1SRafael Vanoni if (n->next == NULL) { 176*9bbf5ba1SRafael Vanoni /* Removing the last element */ 177*9bbf5ba1SRafael Vanoni n->prev->next = NULL; 178*9bbf5ba1SRafael Vanoni } else { 179*9bbf5ba1SRafael Vanoni /* Removing an intermediate element */ 180*9bbf5ba1SRafael Vanoni n->prev->next = n->next; 181*9bbf5ba1SRafael Vanoni n->next->prev = n->prev; 182*9bbf5ba1SRafael Vanoni } 183*9bbf5ba1SRafael Vanoni } 184b47b5b34SRafael Vanoni 185*9bbf5ba1SRafael Vanoni /* 186*9bbf5ba1SRafael Vanoni * If this suggestions is currently being suggested, 187*9bbf5ba1SRafael Vanoni * remove it and update the screen. 188*9bbf5ba1SRafael Vanoni */ 189*9bbf5ba1SRafael Vanoni if (n == g_curr_sugg) { 190*9bbf5ba1SRafael Vanoni if (n->sb_msg != NULL) { 191*9bbf5ba1SRafael Vanoni pt_display_mod_status_bar(n->sb_msg); 192*9bbf5ba1SRafael Vanoni pt_display_status_bar(); 193*9bbf5ba1SRafael Vanoni } 194*9bbf5ba1SRafael Vanoni if (n->text != NULL) 195*9bbf5ba1SRafael Vanoni pt_display_suggestions(NULL); 196*9bbf5ba1SRafael Vanoni } 197*9bbf5ba1SRafael Vanoni 198*9bbf5ba1SRafael Vanoni free(n); 199*9bbf5ba1SRafael Vanoni ret = 1; 200*9bbf5ba1SRafael Vanoni } 201*9bbf5ba1SRafael Vanoni } 202*9bbf5ba1SRafael Vanoni 203*9bbf5ba1SRafael Vanoni return (ret); 204*9bbf5ba1SRafael Vanoni } 205*9bbf5ba1SRafael Vanoni 206*9bbf5ba1SRafael Vanoni /* 207*9bbf5ba1SRafael Vanoni * Chose a suggestion to display. The list of suggestions is ordered by weight, 208*9bbf5ba1SRafael Vanoni * so we only worry about fariness here. Each suggestion, starting with the 209*9bbf5ba1SRafael Vanoni * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals. 210*9bbf5ba1SRafael Vanoni */ 211*9bbf5ba1SRafael Vanoni void 212*9bbf5ba1SRafael Vanoni pt_sugg_pick(void) 213*9bbf5ba1SRafael Vanoni { 214*9bbf5ba1SRafael Vanoni sugg_t *n; 215*9bbf5ba1SRafael Vanoni 216*9bbf5ba1SRafael Vanoni if (sugg == NULL) { 217*9bbf5ba1SRafael Vanoni g_curr_sugg = NULL; 218b47b5b34SRafael Vanoni return; 219b47b5b34SRafael Vanoni } 220b47b5b34SRafael Vanoni 221*9bbf5ba1SRafael Vanoni search: 222*9bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) { 223b47b5b34SRafael Vanoni 224*9bbf5ba1SRafael Vanoni if (n->slice++ < PT_SUGG_DEF_SLICE) { 225b47b5b34SRafael Vanoni 226*9bbf5ba1SRafael Vanoni /* 227*9bbf5ba1SRafael Vanoni * Don't need to re-suggest the current suggestion. 228*9bbf5ba1SRafael Vanoni */ 229*9bbf5ba1SRafael Vanoni if (g_curr_sugg == n) 230*9bbf5ba1SRafael Vanoni return; 231b47b5b34SRafael Vanoni 232*9bbf5ba1SRafael Vanoni /* 233*9bbf5ba1SRafael Vanoni * Remove the current suggestion from screen. 234*9bbf5ba1SRafael Vanoni */ 235*9bbf5ba1SRafael Vanoni if (g_curr_sugg != NULL) { 236*9bbf5ba1SRafael Vanoni if (g_curr_sugg->sb_msg != NULL) { 237*9bbf5ba1SRafael Vanoni pt_display_mod_status_bar( 238*9bbf5ba1SRafael Vanoni g_curr_sugg->sb_msg); 239*9bbf5ba1SRafael Vanoni pt_display_status_bar(); 240b47b5b34SRafael Vanoni } 241*9bbf5ba1SRafael Vanoni if (g_curr_sugg->text != NULL) 242*9bbf5ba1SRafael Vanoni pt_display_suggestions(NULL); 243*9bbf5ba1SRafael Vanoni } 244*9bbf5ba1SRafael Vanoni 245*9bbf5ba1SRafael Vanoni if (n->sb_msg != NULL) { 246*9bbf5ba1SRafael Vanoni pt_display_mod_status_bar(n->sb_msg); 247*9bbf5ba1SRafael Vanoni pt_display_status_bar(); 248*9bbf5ba1SRafael Vanoni } 249*9bbf5ba1SRafael Vanoni 250*9bbf5ba1SRafael Vanoni pt_display_suggestions(n->text); 251*9bbf5ba1SRafael Vanoni 252*9bbf5ba1SRafael Vanoni g_curr_sugg = n; 253*9bbf5ba1SRafael Vanoni 254b47b5b34SRafael Vanoni return; 255b47b5b34SRafael Vanoni } 256b47b5b34SRafael Vanoni } 257b47b5b34SRafael Vanoni 258*9bbf5ba1SRafael Vanoni /* 259*9bbf5ba1SRafael Vanoni * All suggestions have run out of slice quotas, so we restart. 260*9bbf5ba1SRafael Vanoni */ 261*9bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) 262*9bbf5ba1SRafael Vanoni n->slice = 0; 263*9bbf5ba1SRafael Vanoni 264*9bbf5ba1SRafael Vanoni goto search; 265b47b5b34SRafael Vanoni } 266b47b5b34SRafael Vanoni 267b47b5b34SRafael Vanoni void 268*9bbf5ba1SRafael Vanoni pt_sugg_as_root(void) 269b47b5b34SRafael Vanoni { 270*9bbf5ba1SRafael Vanoni pt_sugg_add("Suggestion: run as root to get suggestions" 271*9bbf5ba1SRafael Vanoni " for reducing system power consumption", 40, NULL, NULL, 272*9bbf5ba1SRafael Vanoni NULL); 273b47b5b34SRafael Vanoni } 274