Hi,

attached patch adds new -s (--script) option to generate shell script with commands to turn every "Bad" item from Tunables tab into "Good" state.

It adds new tunable::toggle_script() method which returns command to switch state of particular tunable item and implements that method for all current classes derived from "tunable".

I'm open to suggestions.

Thanks for your work,
Jan Kaluza
diff --git a/Makefile b/Makefile
index b0b6cb7..d3504a1 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ CPPFLAGS += -Wall -O2 -g -fno-omit-frame-pointer
 CXXFLAGS += -Wall -O2 -g -fno-omit-frame-pointer -fstack-protector -Wshadow -Wformat -D_FORTIFY_SOURCE=2
 PKG_CONFIG ?= pkg-config
 
-OBJS := lib.o main.o display.o html.o devlist.o
+OBJS := lib.o main.o display.o html.o devlist.o shell.o
 OBJS += cpu/cpu.o cpu/abstract_cpu.o cpu/cpu_linux.o cpu/cpu_core.o cpu/cpu_package.o cpu/intel_cpus.o  cpu/cpudevice.cpp
 OBJS += perf/perf.o perf/perf_bundle.o
 OBJS += process/process.o process/do_process.o process/interrupt.o process/timer.o process/work.o process/powerconsumer.o process/device.o
diff --git a/main.cpp b/main.cpp
index fc366b0..f0aabb5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -40,6 +40,7 @@
 #include "perf/perf_bundle.h"
 #include "lib.h"
 #include "html.h"
+#include "shell.h"
 
 #include "devices/device.h"
 #include "devices/usb.h"
@@ -67,6 +68,7 @@ static const struct option long_options[] =
 	{"html", optional_argument, NULL, 'h'},
 	{"extech", optional_argument, NULL, 'e'},
 	{"time", optional_argument, NULL, 't'},
+	{"script", optional_argument, NULL, 's'},
 	{NULL, 0, NULL, 0}
 };
 
@@ -83,6 +85,7 @@ static void print_usage()
 	printf(_("--calibrate \t runs powertop in calibration mode\n"));
 	printf(_("--extech=devnode \t uses an Extech Power Analyzer for measurements\n"));
 	printf(_("--html[=FILENAME]\t\t generate a html report\n"));
+	printf(_("--script[=FILENAME]\t\t generate shell script with tunable commands\n"));
 	printf(_("--time[=secs]\t\t generate a html report for secs\n"));
 	printf(_("--help \t\t print this help menu\n"));
 	printf("\n");
@@ -241,6 +244,30 @@ void html_report(int time, bool file)
 	exit(0);
 }
 
+void shell_script(int time, bool file)
+{
+	/* one to warm up everything */
+	utf_ok = 0;
+	one_measurement(1);
+
+	if(file)
+		init_shell_output( (optarg ? optarg : "powertop.sh"));
+	else
+		init_shell_output("powertop.sh");
+
+	initialize_tuning();
+	shell_show_tunables();
+
+	finish_shell_output();
+
+	/* and wrap up */
+	learn_parameters(50, 0);
+	save_all_results("/var/cache/powertop/saved_results.powertop");
+	save_parameters("/var/cache/powertop/saved_parameters.powertop");
+	end_pci_access();
+	exit(0);
+}
+
 int main(int argc, char **argv)
 {
 	int uid;
@@ -285,7 +312,7 @@ int main(int argc, char **argv)
 	load_board_params();
 
 	while (1) { /* parse commandline options */
-		c = getopt_long (argc, argv, "ch:t:uV", long_options, &option_index);
+		c = getopt_long (argc, argv, "ch:t:uVs:", long_options, &option_index);
 
 		/* Detect the end of the options. */
 		if (c == -1)
@@ -317,6 +344,9 @@ int main(int argc, char **argv)
 				html_report((optarg ? atoi(optarg) : 20), FALSE);
 				break;
 
+			case 's':
+				shell_script(20, TRUE);
+				break;
 
 			case '?': /* Unknown option */
 				/* getopt_long already printed an error message. */
diff --git a/shell.cpp b/shell.cpp
new file mode 100644
index 0000000..ba44286
--- /dev/null
+++ b/shell.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010, Intel Corporation
+ * Copyright 2011, Red Hat, Inc.
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ *	Jan Kaluza <[email protected]>
+ *	Arjan van de Ven <[email protected]>
+ */
+
+#include "shell.h"
+#include <errno.h>
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+
+#include "lib.h"
+
+using namespace std;
+
+FILE *shellout;
+
+void init_shell_output(const char *filename)
+{
+	shellout = fopen(filename, "w");
+
+	if (!shellout) {
+		fprintf(stderr, "Cannot open output file %s (%s)\n", filename, strerror(errno));
+	}
+
+	printf("Writing PowerTOP output to file %s\n", filename);
+	fprintf(shellout, "#!/bin/sh\n");
+}
+
+void finish_shell_output(void)
+{
+	if (!shellout)
+		return;
+
+	fflush(shellout);
+	fclose(shellout);
+}
diff --git a/shell.h b/shell.h
new file mode 100644
index 0000000..de891ef
--- /dev/null
+++ b/shell.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010, Intel Corporation
+ * Copyright 2011, Red Hat, Inc.
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ *	Jan Kaluza <[email protected]>
+ *	Arjan van de Ven <[email protected]>
+ */
+
+#ifndef __INCLUDE_GUARD_SHELL_H_
+#define __INCLUDE_GUARD_SHELL_H_
+
+#include <string>
+#include <stdio.h>
+
+using namespace std;
+
+extern FILE *shellout;
+
+extern void init_shell_output(const char *filename);
+extern void finish_shell_output(void);
+
+
+#endif
\ No newline at end of file
diff --git a/tuning/bluetooth.cpp b/tuning/bluetooth.cpp
index 3957316..cc98642 100644
--- a/tuning/bluetooth.cpp
+++ b/tuning/bluetooth.cpp
@@ -46,6 +46,8 @@
 bt_tunable::bt_tunable(void) : tunable("", 1.0, "Good", "Bad", "Unknown")
 {
 	sprintf(desc, _("Bluetooth device interface status"));
+	strcpy(toggle_bad, "/usr/sbin/hciconfig hci0 up &> /dev/null &");
+	strcpy(toggle_good, "/usr/sbin/hciconfig hci0 down &> /dev/null");
 }
 
 
@@ -180,6 +182,16 @@ void bt_tunable::toggle(void)
 	system("/usr/sbin/hciconfig hci0 down &> /dev/null");
 }
 
+const char *bt_tunable::toggle_script(void)
+{
+	int good;
+	good = good_bad();
+
+	if (good == TUNE_GOOD) {
+		return toggle_bad;
+	}
+	return toggle_good;
+}
 
 
 void add_bt_tunable(void)
diff --git a/tuning/bluetooth.h b/tuning/bluetooth.h
index 27e15f1..ecb667d 100644
--- a/tuning/bluetooth.h
+++ b/tuning/bluetooth.h
@@ -39,6 +39,8 @@ public:
 
 	virtual void toggle(void);
 
+	virtual const char *toggle_script(void);
+
 };
 
 extern void add_bt_tunable(void);
diff --git a/tuning/cpufreq.cpp b/tuning/cpufreq.cpp
index bf2b8ae..3d0dbea 100644
--- a/tuning/cpufreq.cpp
+++ b/tuning/cpufreq.cpp
@@ -35,6 +35,7 @@
 #include <unistd.h> 
 #include <dirent.h>
 #include <errno.h>
+#include <sys/stat.h>
 
 #include "../lib.h"
 #include "cpufreq.h"
@@ -153,6 +154,54 @@ void cpufreq_tunable::toggle(void)
 	closedir(dir);
 }
 
+const char *cpufreq_tunable::toggle_script(void) {
+	DIR *dir;
+	struct dirent *dirent;
+	FILE *file;
+	char filename[PATH_MAX];
+	char tmp[4096];
+	struct stat statbuf;
+	int good;
+	good = good_bad();
+
+	strcpy(toggle_good, "/sbin/modprobe cpufreq_ondemand > /dev/null 2>&1\n");
+
+	if (good == TUNE_GOOD) {
+		dir = opendir("/sys/devices/system/cpu");
+		if (!dir)
+			return NULL;
+
+		while ((dirent = readdir(dir))) {
+			if (dirent->d_name[0]=='.')
+				continue;
+			sprintf(filename, "/sys/devices/system/cpu/%s/cpufreq/scaling_governor", dirent->d_name);
+			if (stat(filename, &statbuf) == -1)
+				continue;
+			sprintf(tmp, "echo '%s' > '%s';\n", original, filename);
+			strcat(toggle_good, tmp);
+		}
+
+		closedir(dir);
+		return toggle_good;
+	}
+
+	dir = opendir("/sys/devices/system/cpu");
+	if (!dir)
+		return NULL;
+
+	while ((dirent = readdir(dir))) {
+		if (dirent->d_name[0]=='.')
+			continue;
+		sprintf(filename, "/sys/devices/system/cpu/%s/cpufreq/scaling_governor", dirent->d_name);
+		if (stat(filename, &statbuf) == -1)
+			continue;
+		sprintf(tmp, "echo 'ondemand' > '%s';\n", filename);
+		strcat(toggle_good, tmp);
+	}
+
+	closedir(dir);
+	return toggle_good;
+}
 
 
 void add_cpufreq_tunable(void)
diff --git a/tuning/cpufreq.h b/tuning/cpufreq.h
index 55af71f..983f813 100644
--- a/tuning/cpufreq.h
+++ b/tuning/cpufreq.h
@@ -40,6 +40,8 @@ public:
 
 	virtual void toggle(void);
 
+	virtual const char *toggle_script(void);
+
 };
 
 extern void add_cpufreq_tunable(void);
diff --git a/tuning/ethernet.cpp b/tuning/ethernet.cpp
index 4666ac1..7687e38 100644
--- a/tuning/ethernet.cpp
+++ b/tuning/ethernet.cpp
@@ -54,6 +54,8 @@ ethernet_tunable::ethernet_tunable(const char *iface) : tunable("", 0.3, _("Good
 	memset(interf, 0, sizeof(interf));
 	strncpy(interf, iface, sizeof(interf));
 	sprintf(desc, _("Wake-on-lan status for device %s"), iface);
+	sprintf(toggle_good, "ethtool -s %s wol d;", iface);
+	
 }
 
 
@@ -128,6 +130,18 @@ void ethernet_tunable::toggle(void)
 	close(sock);
 }
 
+const char *ethernet_tunable::toggle_script(void)
+{
+	int good;
+	good = good_bad();
+
+	if (good != TUNE_GOOD) {
+		return toggle_good;
+	}
+
+	return NULL;
+}
+
 
 void ethtunable_callback(const char *d_name)
 {
diff --git a/tuning/ethernet.h b/tuning/ethernet.h
index eeb6ebb..85810fb 100644
--- a/tuning/ethernet.h
+++ b/tuning/ethernet.h
@@ -40,6 +40,8 @@ public:
 
 	virtual void toggle(void);
 
+	virtual const char *toggle_script(void);
+
 };
 
 extern void add_ethernet_tunable(void);
diff --git a/tuning/runtime.cpp b/tuning/runtime.cpp
index 03cfa0b..3c6dae8 100644
--- a/tuning/runtime.cpp
+++ b/tuning/runtime.cpp
@@ -77,6 +77,8 @@ runtime_tunable::runtime_tunable(const char *path, const char *bus, const char *
 
 		
 	}
+	sprintf(toggle_good, "echo 'auto' > '%s';", runtime_path);
+	sprintf(toggle_bad, "echo 'on' > '%s';", runtime_path);
 }
 
 int runtime_tunable::good_bad(void)
@@ -105,6 +107,18 @@ void runtime_tunable::toggle(void)
 	write_sysfs(runtime_path, "auto");
 }
 
+const char *runtime_tunable::toggle_script(void)
+{
+	int good;
+	good = good_bad();
+
+	if (good == TUNE_GOOD) {
+		return toggle_bad;
+	}
+
+	return toggle_good;
+}
+
 
 void add_runtime_tunables(const char *bus)
 {
diff --git a/tuning/runtime.h b/tuning/runtime.h
index c874241..a3c3e20 100644
--- a/tuning/runtime.h
+++ b/tuning/runtime.h
@@ -39,6 +39,8 @@ public:
 
 	virtual void toggle(void);
 
+	virtual const char *toggle_script(void);
+
 };
 
 extern void add_runtime_tunables(const char *bus);
diff --git a/tuning/sysfs.cpp b/tuning/sysfs.cpp
index e1742a3..ffb2df0 100644
--- a/tuning/sysfs.cpp
+++ b/tuning/sysfs.cpp
@@ -39,6 +39,8 @@ sysfs_tunable::sysfs_tunable(const char *str, const char *_sysfs_path, const cha
 	strcpy(sysfs_path, _sysfs_path);
 	strcpy(target_value, _target_content);
 	bad_value[0] = 0;
+	sprintf(toggle_good, "echo '%s' > '%s';", target_value, sysfs_path);
+	sprintf(toggle_bad, "echo '%s' > '%s';", bad_value, sysfs_path);
 }
 
 int sysfs_tunable::good_bad(void)
@@ -77,6 +79,19 @@ void sysfs_tunable::toggle(void)
 	write_sysfs(sysfs_path, target_value);
 }
 
+const char *sysfs_tunable::toggle_script(void) {
+	int good;
+	good = good_bad();
+
+	if (good == TUNE_GOOD) {
+		if (strlen(bad_value) > 0)
+			return toggle_bad;
+		return NULL;
+	}
+
+	return toggle_good;
+}
+
 
 void add_sysfs_tunable(const char *str, const char *_sysfs_path, const char *_target_content)
 {
diff --git a/tuning/sysfs.h b/tuning/sysfs.h
index 9fee4c0..ac7938c 100644
--- a/tuning/sysfs.h
+++ b/tuning/sysfs.h
@@ -42,6 +42,8 @@ public:
 
 	virtual void toggle(void);
 
+	virtual const char *toggle_script(void);
+
 };
 
 extern void add_sysfs_tunable(const char *str, const char *_sysfs_path, const char *_target_content);
diff --git a/tuning/tunable.h b/tuning/tunable.h
index a4e994d..dacbd79 100644
--- a/tuning/tunable.h
+++ b/tuning/tunable.h
@@ -42,6 +42,9 @@ class tunable {
 	char good_string[128];
 	char bad_string[128];
 	char neutral_string[128];
+protected:
+	char toggle_good[4096];
+	char toggle_bad[4096];
 public:
 	char desc[4096];
 	double score;
@@ -67,6 +70,8 @@ public:
 	virtual const char *description(void) { return desc; };
 
 	virtual void toggle(void) { };
+
+	virtual const char *toggle_script(void) { return NULL; }
 };
 
 extern vector<class tunable *> all_tunables;
diff --git a/tuning/tuning.cpp b/tuning/tuning.cpp
index c63f1e8..8cd505a 100644
--- a/tuning/tuning.cpp
+++ b/tuning/tuning.cpp
@@ -40,6 +40,7 @@
 #include "wifi.h"
 #include "../display.h"
 #include "../html.h"
+#include "../shell.h"
 #include "../lib.h"
 
 static void sort_tunables(void);
@@ -262,3 +263,30 @@ void html_show_tunables(void)
 		fprintf(htmlout, "</table></p>\n");
 
 }
+
+void shell_show_tunables(void)
+{
+	unsigned int i;
+	/* three sections; bad, unfixable, good */
+
+	if (!shellout)
+		return;
+
+	sort_tunables();
+
+	for (i = 0; i < all_tunables.size(); i++) {
+		int gb;
+
+		gb = all_tunables[i]->good_bad();
+
+		if (gb != TUNE_BAD)
+			continue;
+
+		const char *script = all_tunables[i]->toggle_script();
+		fprintf(shellout, "# %s\n", all_tunables[i]->description());
+		if (script) {
+			
+			fprintf(shellout, "%s\n\n", script);
+		}
+	}
+}
diff --git a/tuning/tuning.h b/tuning/tuning.h
index e3e9d5c..568ada8 100644
--- a/tuning/tuning.h
+++ b/tuning/tuning.h
@@ -28,6 +28,7 @@
 extern void initialize_tuning(void);
 extern void tuning_update_display(void);
 extern void html_show_tunables(void);
+extern void shell_show_tunables(void);
 
 
 
diff --git a/tuning/usb.cpp b/tuning/usb.cpp
index 16e25d4..6bcfb07 100644
--- a/tuning/usb.cpp
+++ b/tuning/usb.cpp
@@ -74,6 +74,9 @@ usb_tunable::usb_tunable(const char *path, const char *name) : tunable("", 0.9,
 		sprintf(desc, _("Autosuspend for USB device %s [%s]"), product, name);
 	else if (strlen(vendor))
 		sprintf(desc, _("Autosuspend for USB device %s [%s]"), vendor, name);
+
+	sprintf(toggle_good, "echo 'auto' > '%s';", usb_path);
+	sprintf(toggle_bad, "echo 'on' > '%s';", usb_path);
 }
 
 int usb_tunable::good_bad(void)
@@ -102,6 +105,17 @@ void usb_tunable::toggle(void)
 	write_sysfs(usb_path, "auto");
 }
 
+const char *usb_tunable::toggle_script(void)
+{
+	int good;
+	good = good_bad();
+
+	if (good == TUNE_GOOD) {
+		return toggle_bad;
+	}
+
+	return toggle_good;
+}
 
 void add_usb_tunables(void)
 {
diff --git a/tuning/usb.h b/tuning/usb.h
index a6f9557..a257904 100644
--- a/tuning/usb.h
+++ b/tuning/usb.h
@@ -40,6 +40,8 @@ public:
 
 	virtual void toggle(void);
 
+	virtual const char *toggle_script(void);
+
 };
 
 extern void add_usb_tunables(void);
diff --git a/tuning/wifi.cpp b/tuning/wifi.cpp
index 9d64a9f..8b67fc5 100644
--- a/tuning/wifi.cpp
+++ b/tuning/wifi.cpp
@@ -46,6 +46,9 @@ wifi_tunable::wifi_tunable(const char *_iface) : tunable("", 1.5, _("Good"), _("
 {
 	strcpy(iface, _iface);
 	sprintf(desc, _("Wireless Power Saving for interface %s"), iface);
+	
+	sprintf(toggle_good, "iw dev %s set power_save off", iface);
+	sprintf(toggle_bad, "iw dev %s set power_save on", iface);
 }
 
 int wifi_tunable::good_bad(void)
@@ -69,6 +72,17 @@ void wifi_tunable::toggle(void)
 	set_wifi_power_saving(iface, 1);
 }
 
+const char *wifi_tunable::toggle_script(void)
+{
+	int good;
+	good = good_bad();
+
+	if (good == TUNE_GOOD) {
+		return toggle_bad;
+	}
+
+	return toggle_good;
+}
 
 void add_wifi_tunables(void)
 {
diff --git a/tuning/wifi.h b/tuning/wifi.h
index 347470e..50ca68c 100644
--- a/tuning/wifi.h
+++ b/tuning/wifi.h
@@ -40,6 +40,8 @@ public:
 
 	virtual void toggle(void);
 
+	virtual const char *toggle_script(void);
+
 };
 
 extern void add_wifi_tunables(void);
_______________________________________________
Power mailing list
[email protected]
https://bughost.org/mailman/listinfo/power

Reply via email to