1 /* 2 * Copyright 2009, Intel Corporation 3 * Copyright 2009, Sun Microsystems, Inc 4 * 5 * This file is part of PowerTOP 6 * 7 * This program file is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program in a file named COPYING; if not, write to the 18 * Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301 USA 21 * 22 * Authors: 23 * Arjan van de Ven <arjan@linux.intel.com> 24 * Eric C Saxe <eric.saxe@sun.com> 25 * Aubrey Li <aubrey.li@intel.com> 26 */ 27 28 /* 29 * GPL Disclaimer 30 * 31 * For the avoidance of doubt, except that if any license choice other 32 * than GPL or LGPL is available it will apply instead, Sun elects to 33 * use only the General Public License version 2 (GPLv2) at this time 34 * for any software where a choice of GPL license versions is made 35 * available with the language indicating that GPLv2 or any later 36 * version may be used, or where a choice of which version of the GPL 37 * is applied is otherwise unspecified. 38 */ 39 40 #include <unistd.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include "powertop.h" 45 46 /* 47 * Default number of intervals we display a suggestion before moving 48 * to the next. 49 */ 50 #define PT_SUGG_DEF_SLICE 3 51 52 /* 53 * Global pointer to the current suggestion. 54 */ 55 sugg_t *g_curr_sugg; 56 57 /* 58 * Head of the list of suggestions. 59 */ 60 static sugg_t *sugg; 61 62 /* 63 * Add a new suggestion. Only one suggestion per text allowed. 64 */ 65 void 66 pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func) 67 { 68 sugg_t *new, *n, *pos = NULL; 69 70 /* 71 * Text is a required field for suggestions 72 */ 73 if (text == NULL) 74 return; 75 76 if (sugg == NULL) { 77 /* 78 * Creating first element 79 */ 80 if ((new = calloc(1, sizeof (sugg_t))) == NULL) 81 return; 82 83 if (sb_msg != NULL) 84 new->sb_msg = strdup(sb_msg); 85 86 if (text != NULL) 87 new->text = strdup(text); 88 89 new->weight = weight; 90 new->key = key; 91 new->func = func; 92 new->slice = 0; 93 94 sugg = new; 95 new->prev = NULL; 96 new->next = NULL; 97 } else { 98 for (n = sugg; n != NULL; n = n->next) { 99 if (strcmp(n->text, text) == 0) 100 return; 101 102 if (weight > n->weight && pos == NULL) 103 pos = n; 104 } 105 /* 106 * Create a new element 107 */ 108 if ((new = calloc(1, sizeof (sugg_t))) == NULL) 109 return; 110 111 if (sb_msg != NULL) 112 new->sb_msg = strdup(sb_msg); 113 114 new->text = strdup(text); 115 116 new->weight = weight; 117 new->key = key; 118 new->func = func; 119 new->slice = 0; 120 121 if (pos == NULL) { 122 /* 123 * Ordering placed the new element at the end 124 */ 125 for (n = sugg; n->next != NULL; n = n->next) 126 ; 127 128 n->next = new; 129 new->prev = n; 130 new->next = NULL; 131 } else { 132 if (pos == sugg) { 133 /* 134 * Ordering placed the new element at the start 135 */ 136 new->next = sugg; 137 new->prev = NULL; 138 sugg->prev = new; 139 sugg = new; 140 } else { 141 /* 142 * Ordering placed the new element somewhere in 143 * the middle 144 */ 145 new->next = pos; 146 new->prev = pos->prev; 147 pos->prev->next = new; 148 pos->prev = new; 149 } 150 } 151 } 152 } 153 154 /* 155 * Removes a suggestion, returning 0 if not found and 1 if so. 156 */ 157 int 158 pt_sugg_remove(sugg_func_t *func) 159 { 160 sugg_t *n; 161 162 if (func == NULL) 163 return (0); 164 165 for (n = sugg; n != NULL; n = n->next) { 166 if (n->func == func) { 167 /* Removing the first element */ 168 if (n == sugg) { 169 if (sugg->next == NULL) { 170 /* Removing the only element */ 171 sugg = NULL; 172 } else { 173 sugg = n->next; 174 sugg->prev = NULL; 175 } 176 } else { 177 if (n->next == NULL) { 178 /* Removing the last element */ 179 n->prev->next = NULL; 180 } else { 181 /* Removing an intermediate element */ 182 n->prev->next = n->next; 183 n->next->prev = n->prev; 184 } 185 } 186 break; 187 } 188 } 189 190 if (n == NULL) 191 return (0); 192 193 /* 194 * If this suggestions is currently being suggested, 195 * remove it and update the screen. 196 */ 197 if (n == g_curr_sugg) { 198 g_curr_sugg = NULL; 199 if (n->sb_msg != NULL) { 200 pt_display_mod_status_bar(n->sb_msg); 201 pt_display_status_bar(); 202 } 203 if (n->text != NULL) 204 pt_display_suggestions(NULL); 205 } 206 207 free(n->sb_msg); 208 free(n->text); 209 free(n); 210 211 return (1); 212 } 213 214 /* 215 * Chose a suggestion to display. The list of suggestions is ordered by weight, 216 * so we only worry about fariness here. Each suggestion, starting with the 217 * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals. 218 */ 219 void 220 pt_sugg_pick(void) 221 { 222 sugg_t *n; 223 224 if (sugg == NULL) { 225 g_curr_sugg = NULL; 226 return; 227 } 228 229 search: 230 for (n = sugg; n != NULL; n = n->next) { 231 232 if (n->slice++ < PT_SUGG_DEF_SLICE) { 233 234 /* 235 * Don't need to re-suggest the current suggestion. 236 */ 237 if (g_curr_sugg == n && !g_sig_resize) 238 return; 239 240 /* 241 * Remove the current suggestion from screen. 242 */ 243 if (g_curr_sugg != NULL) { 244 if (g_curr_sugg->sb_msg != NULL) { 245 pt_display_mod_status_bar( 246 g_curr_sugg->sb_msg); 247 pt_display_status_bar(); 248 } 249 if (g_curr_sugg->text != NULL) 250 pt_display_suggestions(NULL); 251 } 252 253 if (n->sb_msg != NULL) { 254 pt_display_mod_status_bar(n->sb_msg); 255 pt_display_status_bar(); 256 } 257 258 pt_display_suggestions(n->text); 259 260 g_curr_sugg = n; 261 262 return; 263 } 264 } 265 266 /* 267 * All suggestions have run out of slice quotas, so we restart. 268 */ 269 for (n = sugg; n != NULL; n = n->next) 270 n->slice = 0; 271 272 goto search; 273 } 274 275 void 276 pt_sugg_as_root(void) 277 { 278 pt_sugg_add("Suggestion: run as root to get suggestions" 279 " for reducing system power consumption", 40, 0, NULL, 280 NULL); 281 } 282