1N/A/*
1N/A * Copyright 2009, Intel Corporation
1N/A * Copyright 2009, Sun Microsystems, Inc
1N/A *
1N/A * This file is part of PowerTOP
1N/A *
1N/A * This program file is free software; you can redistribute it and/or modify it
1N/A * under the terms of the GNU General Public License as published by the
1N/A * Free Software Foundation; version 2 of the License.
1N/A *
1N/A * This program is distributed in the hope that it will be useful, but WITHOUT
1N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1N/A * for more details.
1N/A *
1N/A * You should have received a copy of the GNU General Public License
1N/A * along with this program in a file named COPYING; if not, write to the
1N/A * Free Software Foundation, Inc.,
1N/A * 51 Franklin Street, Fifth Floor,
1N/A * Boston, MA 02110-1301 USA
1N/A *
1N/A * Authors:
1N/A * Arjan van de Ven <arjan@linux.intel.com>
1N/A * Eric C Saxe <eric.saxe@sun.com>
1N/A * Aubrey Li <aubrey.li@intel.com>
1N/A */
1N/A
1N/A/*
1N/A * GPL Disclaimer
1N/A *
1N/A * For the avoidance of doubt, except that if any license choice other
1N/A * than GPL or LGPL is available it will apply instead, Sun elects to
1N/A * use only the General Public License version 2 (GPLv2) at this time
1N/A * for any software where a choice of GPL license versions is made
1N/A * available with the language indicating that GPLv2 or any later
1N/A * version may be used, or where a choice of which version of the GPL
1N/A * is applied is otherwise unspecified.
1N/A */
1N/A
1N/A#include <unistd.h>
1N/A#include <stdio.h>
1N/A#include <stdlib.h>
1N/A#include <string.h>
1N/A#include "powertop.h"
1N/A
1N/A/*
1N/A * Default number of intervals we display a suggestion before moving
1N/A * to the next.
1N/A */
1N/A#define PT_SUGG_DEF_SLICE 3
1N/A
1N/A/*
1N/A * Global pointer to the current suggestion.
1N/A */
1N/Asugg_t *g_curr_sugg;
1N/A
1N/A/*
1N/A * Head of the list of suggestions.
1N/A */
1N/Astatic sugg_t *sugg;
1N/A
1N/A/*
1N/A * Add a new suggestion. Only one suggestion per text allowed.
1N/A */
1N/Avoid
1N/Apt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func)
1N/A{
1N/A sugg_t *new, *n, *pos = NULL;
1N/A
1N/A /*
1N/A * Text is a required field for suggestions
1N/A */
1N/A if (text == NULL)
1N/A return;
1N/A
1N/A if (sugg == NULL) {
1N/A /*
1N/A * Creating first element
1N/A */
1N/A if ((new = calloc(1, sizeof (sugg_t))) == NULL)
1N/A return;
1N/A
1N/A if (sb_msg != NULL)
1N/A new->sb_msg = strdup(sb_msg);
1N/A
1N/A if (text != NULL)
1N/A new->text = strdup(text);
1N/A
1N/A new->weight = weight;
1N/A new->key = key;
1N/A new->func = func;
1N/A new->slice = 0;
1N/A
1N/A sugg = new;
1N/A new->prev = NULL;
1N/A new->next = NULL;
1N/A } else {
1N/A for (n = sugg; n != NULL; n = n->next) {
1N/A if (strcmp(n->text, text) == 0)
1N/A return;
1N/A
1N/A if (weight > n->weight && pos == NULL)
1N/A pos = n;
1N/A }
1N/A /*
1N/A * Create a new element
1N/A */
1N/A if ((new = calloc(1, sizeof (sugg_t))) == NULL)
1N/A return;
1N/A
1N/A if (sb_msg != NULL)
1N/A new->sb_msg = strdup(sb_msg);
1N/A
1N/A new->text = strdup(text);
1N/A
1N/A new->weight = weight;
1N/A new->key = key;
1N/A new->func = func;
1N/A new->slice = 0;
1N/A
1N/A if (pos == NULL) {
1N/A /*
1N/A * Ordering placed the new element at the end
1N/A */
1N/A for (n = sugg; n->next != NULL; n = n->next)
1N/A ;
1N/A
1N/A n->next = new;
1N/A new->prev = n;
1N/A new->next = NULL;
1N/A } else {
1N/A if (pos == sugg) {
1N/A /*
1N/A * Ordering placed the new element at the start
1N/A */
1N/A new->next = sugg;
1N/A new->prev = sugg;
1N/A sugg->prev = new;
1N/A sugg = new;
1N/A } else {
1N/A /*
1N/A * Ordering placed the new element somewhere in
1N/A * the middle
1N/A */
1N/A new->next = pos;
1N/A new->prev = pos->prev;
1N/A pos->prev->next = new;
1N/A pos->prev = new;
1N/A }
1N/A }
1N/A }
1N/A}
1N/A
1N/A/*
1N/A * Removes a suggestion, returning 0 if not found and 1 if so.
1N/A */
1N/Aint
1N/Apt_sugg_remove(sugg_func_t *func)
1N/A{
1N/A sugg_t *n;
1N/A int ret = 0;
1N/A
1N/A for (n = sugg; n != NULL; n = n->next) {
1N/A if (n->func == func) {
1N/A /* Removing the first element */
1N/A if (n == sugg) {
1N/A if (sugg->next == NULL) {
1N/A /* Removing the only element */
1N/A sugg = NULL;
1N/A } else {
1N/A sugg = n->next;
1N/A sugg->prev = NULL;
1N/A }
1N/A } else {
1N/A if (n->next == NULL) {
1N/A /* Removing the last element */
1N/A n->prev->next = NULL;
1N/A } else {
1N/A /* Removing an intermediate element */
1N/A n->prev->next = n->next;
1N/A n->next->prev = n->prev;
1N/A }
1N/A }
1N/A
1N/A /*
1N/A * If this suggestions is currently being suggested,
1N/A * remove it and update the screen.
1N/A */
1N/A if (n == g_curr_sugg) {
1N/A if (n->sb_msg != NULL) {
1N/A pt_display_mod_status_bar(n->sb_msg);
1N/A pt_display_status_bar();
1N/A }
1N/A if (n->text != NULL)
1N/A pt_display_suggestions(NULL);
1N/A }
1N/A
1N/A free(n);
1N/A ret = 1;
1N/A }
1N/A }
1N/A
1N/A return (ret);
1N/A}
1N/A
1N/A/*
1N/A * Chose a suggestion to display. The list of suggestions is ordered by weight,
1N/A * so we only worry about fariness here. Each suggestion, starting with the
1N/A * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals.
1N/A */
1N/Avoid
1N/Apt_sugg_pick(void)
1N/A{
1N/A sugg_t *n;
1N/A
1N/A if (sugg == NULL) {
1N/A g_curr_sugg = NULL;
1N/A return;
1N/A }
1N/A
1N/Asearch:
1N/A for (n = sugg; n != NULL; n = n->next) {
1N/A
1N/A if (n->slice++ < PT_SUGG_DEF_SLICE) {
1N/A
1N/A /*
1N/A * Don't need to re-suggest the current suggestion.
1N/A */
1N/A if (g_curr_sugg == n && !g_sig_resize)
1N/A return;
1N/A
1N/A /*
1N/A * Remove the current suggestion from screen.
1N/A */
1N/A if (g_curr_sugg != NULL) {
1N/A if (g_curr_sugg->sb_msg != NULL) {
1N/A pt_display_mod_status_bar(
1N/A g_curr_sugg->sb_msg);
1N/A pt_display_status_bar();
1N/A }
1N/A if (g_curr_sugg->text != NULL)
1N/A pt_display_suggestions(NULL);
1N/A }
1N/A
1N/A if (n->sb_msg != NULL) {
1N/A pt_display_mod_status_bar(n->sb_msg);
1N/A pt_display_status_bar();
1N/A }
1N/A
1N/A pt_display_suggestions(n->text);
1N/A
1N/A g_curr_sugg = n;
1N/A
1N/A return;
1N/A }
1N/A }
1N/A
1N/A /*
1N/A * All suggestions have run out of slice quotas, so we restart.
1N/A */
1N/A for (n = sugg; n != NULL; n = n->next)
1N/A n->slice = 0;
1N/A
1N/A goto search;
1N/A}
1N/A
1N/Avoid
1N/Apt_sugg_as_root(void)
1N/A{
1N/A pt_sugg_add("Suggestion: run as root to get suggestions"
1N/A " for reducing system power consumption", 40, NULL, NULL,
1N/A NULL);
1N/A}