summaryrefslogtreecommitdiff
path: root/cpufreq/src/cpufreq-selector
diff options
context:
space:
mode:
Diffstat (limited to 'cpufreq/src/cpufreq-selector')
-rw-r--r--cpufreq/src/cpufreq-selector/Makefile.am89
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-factory.c47
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-factory.h31
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.c197
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.h61
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.c243
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.h54
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-service.c487
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-service.h71
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-service.xml23
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.c430
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.h58
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector.c173
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector.h74
-rw-r--r--cpufreq/src/cpufreq-selector/main.c233
-rw-r--r--cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.conf20
-rw-r--r--cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.service.in4
-rw-r--r--cpufreq/src/cpufreq-selector/org.mate.cpufreqselector.policy.in22
18 files changed, 2317 insertions, 0 deletions
diff --git a/cpufreq/src/cpufreq-selector/Makefile.am b/cpufreq/src/cpufreq-selector/Makefile.am
new file mode 100644
index 00000000..b2db7a97
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/Makefile.am
@@ -0,0 +1,89 @@
+cpufreqselectordir = $(bindir)
+
+INCLUDES = $(CPUFREQ_SELECTOR_CFLAGS)
+
+if HAVE_POLKIT
+INCLUDES += \
+ $(DBUS_CFLAGS) \
+ $(POLKIT_CFLAGS)
+endif
+
+bin_PROGRAMS = cpufreq-selector
+
+install-exec-hook:
+if CPUFREQ_SELECTOR_SUID
+ chmod 4755 $(DESTDIR)$(bindir)/cpufreq-selector
+endif
+
+
+if HAVE_LIBCPUFREQ
+cpufreq_files=cpufreq-selector-libcpufreq.c cpufreq-selector-libcpufreq.h
+endif
+
+if HAVE_POLKIT
+service_files=cpufreq-selector-service.c cpufreq-selector-service.h
+endif
+
+cpufreq_selector_SOURCES = \
+ cpufreq-selector.c cpufreq-selector.h \
+ cpufreq-selector-sysfs.c cpufreq-selector-sysfs.h \
+ cpufreq-selector-procfs.c cpufreq-selector-procfs.h \
+ $(cpufreq_files) \
+ $(service_files) \
+ cpufreq-selector-factory.c cpufreq-selector-factory.h \
+ $(BUILT_SOURCES) \
+ main.c
+
+cpufreq_selector_LDADD = \
+ $(CPUFREQ_SELECTOR_LIBS) \
+ $(LIBCPUFREQ_LIBS)
+
+if HAVE_POLKIT
+cpufreq_selector_LDADD += \
+ $(DBUS_LIBS) \
+ $(POLKIT_LIBS)
+endif
+
+cpufreq_selector_LDFLAGS = $(LDFLAGS) -Wl,-z,now
+
+dbus_services_in_files = org.mate.CPUFreqSelector.service.in
+polkit_in_files = org.mate.cpufreqselector.policy.in
+
+dbus_servicesdir = $(datadir)/dbus-1/system-services
+dbus_confdir = $(sysconfdir)/dbus-1/system.d
+polkitdir = $(datadir)/polkit-1/actions
+
+if HAVE_POLKIT
+BUILT_SOURCES = cpufreq-selector-service-glue.h
+
+cpufreq-selector-service-glue.h: $(srcdir)/cpufreq-selector-service.xml
+ dbus-binding-tool --prefix=cpufreq_selector_service --mode=glib-server \
+ --output=cpufreq-selector-service-glue.h \
+ $(srcdir)/cpufreq-selector-service.xml
+
+dbus_services_DATA = $(dbus_services_in_files:.service.in=.service)
+$(dbus_services_DATA): $(dbus_services_in_files)
+ sed -e "s|\@BINDIR\@|$(DESTDIR)$(bindir)|" $< > $@
+dbus_conf_DATA = org.mate.CPUFreqSelector.conf
+
+@INTLTOOL_POLICY_RULE@
+polkit_DATA = $(polkit_in_files:.policy.in=.policy)
+
+else
+dbus_services_DATA=
+dbus_conf_DATA=
+polkit_DATA=
+endif
+
+EXTRA_DIST = \
+ cpufreq-selector-service.xml \
+ $(dbus_services_in_files) \
+ org.mate.CPUFreqSelector.conf \
+ $(polkit_in_files)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(dbus_services_DATA) \
+ $(polkit_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.c
new file mode 100644
index 00000000..024b5cb7
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.c
@@ -0,0 +1,47 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cpufreq-selector-factory.h"
+#include "cpufreq-selector-sysfs.h"
+#include "cpufreq-selector-procfs.h"
+#ifdef HAVE_LIBCPUFREQ
+#include "cpufreq-selector-libcpufreq.h"
+#endif
+
+CPUFreqSelector *
+cpufreq_selector_factory_create_selector (guint cpu)
+{
+ CPUFreqSelector *selector = NULL;
+
+#ifdef HAVE_LIBCPUFREQ
+ selector = cpufreq_selector_libcpufreq_new (cpu);
+#else
+ if (g_file_test ("/sys/devices/system/cpu/cpu0/cpufreq", G_FILE_TEST_EXISTS)) { /* 2.6 kernel */
+ selector = cpufreq_selector_sysfs_new (cpu);
+ } else if (g_file_test ("/proc/cpufreq", G_FILE_TEST_EXISTS)) { /* 2.4 kernel */
+ selector = cpufreq_selector_procfs_new (cpu);
+ }
+#endif /* HAVE_LIBCPUFREQ */
+
+ return selector;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.h
new file mode 100644
index 00000000..fba0a8dc
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.h
@@ -0,0 +1,31 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef CPUFREQ_SELECTOR_FACTORY
+#define CPUFREQ_SELECTOR_FACTORY
+
+#include "cpufreq-selector.h"
+
+G_BEGIN_DECLS
+
+CPUFreqSelector *cpufreq_selector_factory_create_selector (guint cpu);
+
+G_END_DECLS
+
+#endif /* CPUFREQ_SELECTOR_FACTORY */
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.c
new file mode 100644
index 00000000..4b9573b3
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.c
@@ -0,0 +1,197 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <cpufreq.h>
+#include <stdlib.h>
+
+#include "cpufreq-selector-libcpufreq.h"
+
+static void cpufreq_selector_libcpufreq_init (CPUFreqSelectorLibcpufreq *selector);
+static void cpufreq_selector_libcpufreq_class_init (CPUFreqSelectorLibcpufreqClass *klass);
+
+static gboolean cpufreq_selector_libcpufreq_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+static gboolean cpufreq_selector_libcpufreq_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+
+G_DEFINE_TYPE (CPUFreqSelectorLibcpufreq, cpufreq_selector_libcpufreq, CPUFREQ_TYPE_SELECTOR)
+
+typedef struct cpufreq_policy CPUFreqPolicy;
+typedef struct cpufreq_available_frequencies CPUFreqFrequencyList;
+typedef struct cpufreq_available_governors CPUFreqGovernorList;
+
+static void
+cpufreq_selector_libcpufreq_init (CPUFreqSelectorLibcpufreq *selector)
+{
+}
+
+static void
+cpufreq_selector_libcpufreq_class_init (CPUFreqSelectorLibcpufreqClass *klass)
+{
+ CPUFreqSelectorClass *selector_class = CPUFREQ_SELECTOR_CLASS (klass);
+
+ selector_class->set_frequency = cpufreq_selector_libcpufreq_set_frequency;
+ selector_class->set_governor = cpufreq_selector_libcpufreq_set_governor;
+}
+
+CPUFreqSelector *
+cpufreq_selector_libcpufreq_new (guint cpu)
+{
+ CPUFreqSelector *selector;
+
+ selector = CPUFREQ_SELECTOR (g_object_new (CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ,
+ "cpu", cpu,
+ NULL));
+
+ return selector;
+}
+
+static guint
+cpufreq_selector_libcpufreq_get_valid_frequency (CPUFreqSelectorLibcpufreq *selector,
+ guint frequency)
+{
+ guint cpu;
+ gint dist = G_MAXINT;
+ guint retval = 0;
+ CPUFreqFrequencyList *freqs, *freq;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ freqs = cpufreq_get_available_frequencies (cpu);
+ if (!freqs)
+ return 0;
+
+ for (freq = freqs; freq; freq = freq->next) {
+ guint current_dist;
+
+ if (freq->frequency == frequency) {
+ cpufreq_put_available_frequencies (freqs);
+
+ return frequency;
+ }
+
+ current_dist = abs (freq->frequency - frequency);
+ if (current_dist < dist) {
+ dist = current_dist;
+ retval = freq->frequency;
+ }
+ }
+
+ return retval;
+}
+
+static gboolean
+cpufreq_selector_libcpufreq_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error)
+{
+ guint freq;
+ guint cpu;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ freq = cpufreq_selector_libcpufreq_get_valid_frequency (CPUFREQ_SELECTOR_LIBCPUFREQ (selector),
+ frequency);
+ if (cpufreq_set_frequency (cpu, freq) != 0) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_SET_FREQUENCY,
+ "Cannot set frequency '%d'",
+ frequency);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+cpufreq_selector_libcpufreq_validate_governor (CPUFreqSelectorLibcpufreq *selector,
+ const gchar *governor)
+{
+ guint cpu;
+ CPUFreqGovernorList *govs, *gov;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ govs = cpufreq_get_available_governors (cpu);
+ if (!govs)
+ return FALSE;
+
+ for (gov = govs; gov; gov = gov->next) {
+ if (g_ascii_strcasecmp (gov->governor, governor) == 0) {
+ cpufreq_put_available_governors (govs);
+
+ return TRUE;
+ }
+ }
+
+ cpufreq_put_available_governors (govs);
+
+ return FALSE;
+}
+
+static gboolean
+cpufreq_selector_libcpufreq_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error)
+{
+ CPUFreqSelectorLibcpufreq *selector_libcpufreq;
+ guint cpu;
+
+ selector_libcpufreq = CPUFREQ_SELECTOR_LIBCPUFREQ (selector);
+
+ if (!cpufreq_selector_libcpufreq_validate_governor (selector_libcpufreq, governor)) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_INVALID_GOVERNOR,
+ "Invalid governor '%s'",
+ governor);
+
+ return FALSE;
+ }
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ if (cpufreq_modify_policy_governor (cpu, (gchar *)governor) != 0) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_INVALID_GOVERNOR,
+ "Invalid governor '%s'",
+ governor);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.h
new file mode 100644
index 00000000..37dcda63
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.h
@@ -0,0 +1,61 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_SELECTOR_LIBCPUFREQ_H__
+#define __CPUFREQ_SELECTOR_LIBCPUFREQ_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-selector.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ \
+ (cpufreq_selector_libcpufreq_get_type ())
+#define CPUFREQ_SELECTOR_LIBCPUFREQ(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ, CPUFreqSelectorLibcpufreq))
+#define CPUFREQ_SELECTOR_LIBCPUFREQ_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ, CPUFreqSelectorLibcpufreqClass))
+#define CPUFREQ_IS_SELECTOR_LIBCPUFREQ(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ))
+#define CPUFREQ_IS_SELECTOR_LIBCPUFREQ_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ))
+#define CPUFREQ_SELECTOR_LIBCPUFREQ_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ, CPUFreqSelectorLibcpufreqClass))
+
+typedef struct _CPUFreqSelectorLibcpufreq CPUFreqSelectorLibcpufreq;
+typedef struct _CPUFreqSelectorLibcpufreqClass CPUFreqSelectorLibcpufreqClass;
+
+struct _CPUFreqSelectorLibcpufreq {
+ CPUFreqSelector parent;
+};
+
+struct _CPUFreqSelectorLibcpufreqClass {
+ CPUFreqSelectorClass parent_class;
+};
+
+
+GType cpufreq_selector_libcpufreq_get_type (void) G_GNUC_CONST;
+CPUFreqSelector *cpufreq_selector_libcpufreq_new (guint cpu);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_SYSFS_H__ */
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.c
new file mode 100644
index 00000000..f08d681d
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.c
@@ -0,0 +1,243 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "cpufreq-selector-procfs.h"
+
+static void cpufreq_selector_procfs_init (CPUFreqSelectorProcfs *selector);
+static void cpufreq_selector_procfs_class_init (CPUFreqSelectorProcfsClass *klass);
+
+static gboolean cpufreq_selector_procfs_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+static gboolean cpufreq_selector_procfs_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+
+G_DEFINE_TYPE (CPUFreqSelectorProcfs, cpufreq_selector_procfs, CPUFREQ_TYPE_SELECTOR)
+
+static void
+cpufreq_selector_procfs_init (CPUFreqSelectorProcfs *selector)
+{
+}
+
+static void
+cpufreq_selector_procfs_class_init (CPUFreqSelectorProcfsClass *klass)
+{
+ CPUFreqSelectorClass *selector_class = CPUFREQ_SELECTOR_CLASS (klass);
+
+ selector_class->set_frequency = cpufreq_selector_procfs_set_frequency;
+ selector_class->set_governor = cpufreq_selector_procfs_set_governor;
+}
+
+CPUFreqSelector *
+cpufreq_selector_procfs_new (guint cpu)
+{
+ CPUFreqSelector *selector;
+
+ selector = CPUFREQ_SELECTOR (g_object_new (CPUFREQ_TYPE_SELECTOR_PROCFS,
+ "cpu", cpu,
+ NULL));
+
+ return selector;
+}
+
+static gboolean
+cpufreq_procfs_read (guint selector_cpu,
+ guint *fmax,
+ guint *pmin,
+ guint *pmax,
+ guint *fmin,
+ gchar *mode,
+ GError **error)
+{
+ gchar **lines;
+ gchar *buffer = NULL;
+ gint i;
+ guint cpu;
+ gboolean found = FALSE;
+
+ if (!g_file_get_contents ("/proc/cpufreq", &buffer, NULL, error)) {
+ return FALSE;
+ }
+
+ lines = g_strsplit (buffer, "\n", -1);
+ for (i = 0; lines[i]; i++) {
+ if (g_ascii_strncasecmp (lines[i], "CPU", 3) == 0) {
+ /* CPU 0 650000 kHz ( 81 %) - 800000 kHz (100 %) - powersave */
+ sscanf (lines[i], "CPU %u %u kHz (%u %%) - %u kHz (%u %%) - %20s",
+ &cpu, fmin, pmin, fmax, pmax, mode);
+
+ if (cpu == selector_cpu) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ g_strfreev (lines);
+ g_free (buffer);
+
+ if (!found) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_INVALID_CPU,
+ "Invalid CPU number '%d'",
+ selector_cpu);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+cpufreq_procfs_write (const gchar *path,
+ const gchar *setting,
+ GError **error)
+{
+ FILE *fd;
+
+ fd = g_fopen (path, "w");
+
+ if (!fd) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Failed to open '%s' for writing: "
+ "g_fopen() failed: %s",
+ path,
+ g_strerror (errno));
+
+ return FALSE;
+ }
+
+ if (g_fprintf (fd, "%s", setting) < 0) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Failed to write '%s': "
+ "g_fprintf() failed: %s",
+ path,
+ g_strerror (errno));
+
+ fclose (fd);
+
+ return FALSE;
+ }
+
+ fclose (fd);
+
+ return TRUE;
+}
+
+static gboolean
+cpufreq_selector_procfs_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error)
+{
+ gchar *str;
+ gchar *path;
+ guint freq;
+ guint cpu;
+ guint pmin, pmax;
+ guint sc_max, sc_min;
+ gchar mode[21];
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ if (!cpufreq_procfs_read (cpu, &sc_max, &pmin, &pmax, &sc_min, mode, error)) {
+ return FALSE;
+ }
+
+ if (g_ascii_strcasecmp (mode, "userspace") != 0) {
+ if (!cpufreq_selector_procfs_set_governor (selector,
+ "userspace",
+ error)) {
+ return FALSE;
+ }
+ }
+
+ if (frequency != sc_max && frequency != sc_min) {
+ if (abs (sc_max - frequency) < abs (frequency - sc_min))
+ freq = sc_max;
+ else
+ freq = sc_min;
+ } else {
+ freq = frequency;
+ }
+
+ path = g_strdup_printf ("/proc/sys/cpu/%u/speed", cpu);
+ str = g_strdup_printf ("%u", freq);
+ if (!cpufreq_procfs_write (path, str, error)) {
+ g_free (path);
+ g_free (str);
+
+ return FALSE;
+ }
+
+ g_free (path);
+ g_free (str);
+
+ return TRUE;
+}
+
+static gboolean
+cpufreq_selector_procfs_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error)
+{
+ gchar *str;
+ guint cpu;
+ guint pmin, pmax;
+ guint sc_max, sc_min;
+ gchar mode[21];
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ if (!cpufreq_procfs_read (cpu, &sc_max, &pmin, &pmax, &sc_min, mode, error)) {
+ return FALSE;
+ }
+
+ if (g_ascii_strcasecmp (governor, mode) == 0)
+ return TRUE;
+
+ str = g_strdup_printf ("%u:%u:%u:%s", cpu, sc_min, sc_max, governor);
+
+ if (!cpufreq_procfs_write ("/proc/cpufreq", str, error)) {
+ g_free (str);
+
+ return FALSE;
+ }
+
+ g_free (str);
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.h
new file mode 100644
index 00000000..55193731
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.h
@@ -0,0 +1,54 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_SELECTOR_PROCFS_H__
+#define __CPUFREQ_SELECTOR_PROCFS_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-selector.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR_PROCFS (cpufreq_selector_procfs_get_type ())
+#define CPUFREQ_SELECTOR_PROCFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR_PROCFS, CPUFreqSelectorProcfs))
+#define CPUFREQ_SELECTOR_PROCFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR_PROCFS, CPUFreqSelectorProcfsClass))
+#define CPUFREQ_IS_SELECTOR_PROCFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR_PROCFS))
+#define CPUFREQ_IS_SELECTOR_PROCFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR_PROCFS))
+#define CPUFREQ_SELECTOR_PROCFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR_PROCFS, CPUFreqSelectorProcfsClass))
+
+typedef struct _CPUFreqSelectorProcfs CPUFreqSelectorProcfs;
+typedef struct _CPUFreqSelectorProcfsClass CPUFreqSelectorProcfsClass;
+
+struct _CPUFreqSelectorProcfs {
+ CPUFreqSelector parent;
+};
+
+struct _CPUFreqSelectorProcfsClass {
+ CPUFreqSelectorClass parent_class;
+};
+
+GType cpufreq_selector_procfs_get_type (void) G_GNUC_CONST;
+CPUFreqSelector *cpufreq_selector_procfs_new (guint cpu);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_PROCFS_H__ */
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-service.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.c
new file mode 100644
index 00000000..696ff220
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.c
@@ -0,0 +1,487 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <polkit/polkit.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "cpufreq-selector.h"
+#include "cpufreq-selector-factory.h"
+#include "cpufreq-selector-service.h"
+
+#include "cpufreq-selector-service-glue.h"
+
+#define MAX_CPUS 255
+
+struct _CPUFreqSelectorService {
+ GObject parent;
+
+ CPUFreqSelector *selectors[MAX_CPUS];
+ gint selectors_max;
+
+ DBusGConnection *system_bus;
+
+ /* PolicyKit */
+ PolkitAuthority *authority;
+};
+
+struct _CPUFreqSelectorServiceClass {
+ GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (CPUFreqSelectorService, cpufreq_selector_service, G_TYPE_OBJECT)
+
+#define BUS_NAME "org.mate.CPUFreqSelector"
+
+GType
+cpufreq_selector_service_error_get_type (void)
+{
+ static GType etype = 0;
+
+ if (G_UNLIKELY (etype == 0)) {
+ static const GEnumValue values[] = {
+ { SERVICE_ERROR_GENERAL, "SERVICE_ERROR_GENERAL", "GeneralError" },
+ { SERVICE_ERROR_DBUS, "SERVICE_ERROR_DBUS", "DBUSError" },
+ { SERVICE_ERROR_ALREADY_REGISTERED, "SERVICE_ERROR_ALREADY_REGISTERED", "AlreadyRegistered" },
+ { SERVICE_ERROR_NOT_AUTHORIZED, "SERVICE_ERROR_NOT_AUTHORIZED", "NotAuthorized"},
+ { 0, NULL, NULL}
+ };
+
+ etype = g_enum_register_static ("CPUFreqSelectorServiceError", values);
+ }
+
+ return etype;
+}
+
+GQuark
+cpufreq_selector_service_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (G_UNLIKELY (error_quark == 0))
+ error_quark =
+ g_quark_from_static_string ("cpufreq-selector-service-error-quark");
+
+ return error_quark;
+}
+
+static void
+cpufreq_selector_service_finalize (GObject *object)
+{
+ CPUFreqSelectorService *service = CPUFREQ_SELECTOR_SERVICE (object);
+ gint i;
+
+ service->system_bus = NULL;
+
+ if (service->selectors_max >= 0) {
+ for (i = 0; i < service->selectors_max; i++) {
+ if (service->selectors[i]) {
+ g_object_unref (service->selectors[i]);
+ service->selectors[i] = NULL;
+ }
+ }
+
+ service->selectors_max = -1;
+ }
+
+ if (service->authority) {
+ g_object_unref (service->authority);
+ service->authority = NULL;
+ }
+
+ G_OBJECT_CLASS (cpufreq_selector_service_parent_class)->finalize (object);
+}
+
+static void
+cpufreq_selector_service_class_init (CPUFreqSelectorServiceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cpufreq_selector_service_finalize;
+}
+
+static void
+cpufreq_selector_service_init (CPUFreqSelectorService *service)
+{
+ service->selectors_max = -1;
+}
+
+CPUFreqSelectorService *
+cpufreq_selector_service_get_instance (void)
+{
+ static CPUFreqSelectorService *service = NULL;
+
+ if (!service)
+ service = CPUFREQ_SELECTOR_SERVICE (g_object_new (CPUFREQ_TYPE_SELECTOR_SERVICE, NULL));
+
+ return service;
+}
+
+static gboolean
+service_shutdown (gpointer user_data)
+{
+ g_object_unref (SELECTOR_SERVICE);
+
+ return FALSE;
+}
+
+static void
+reset_killtimer (void)
+{
+ static guint timer_id = 0;
+
+ if (timer_id > 0)
+ g_source_remove (timer_id);
+
+ timer_id = g_timeout_add_seconds (30,
+ (GSourceFunc) service_shutdown,
+ NULL);
+}
+
+gboolean
+cpufreq_selector_service_register (CPUFreqSelectorService *service,
+ GError **error)
+{
+ DBusGConnection *connection;
+ DBusGProxy *bus_proxy;
+ gboolean res;
+ guint result;
+ GError *err = NULL;
+
+ if (service->system_bus) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_ALREADY_REGISTERED,
+ "Service %s already registered", BUS_NAME);
+ return FALSE;
+ }
+
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+ if (!connection) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Couldn't connect to system bus: %s",
+ err->message);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ bus_proxy = dbus_g_proxy_new_for_name (connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ if (!bus_proxy) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Could not construct bus_proxy object");
+ return FALSE;
+ }
+
+ res = dbus_g_proxy_call (bus_proxy,
+ "RequestName",
+ &err,
+ G_TYPE_STRING, BUS_NAME,
+ G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &result,
+ G_TYPE_INVALID);
+ g_object_unref (bus_proxy);
+
+ if (!res) {
+ if (err) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Failed to acquire %s: %s",
+ BUS_NAME, err->message);
+ g_error_free (err);
+ } else {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Failed to acquire %s", BUS_NAME);
+ }
+
+ return FALSE;
+ }
+
+ if (result == DBUS_REQUEST_NAME_REPLY_EXISTS) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_ALREADY_REGISTERED,
+ "Service %s already registered", BUS_NAME);
+ return FALSE;
+ }
+
+ service->authority = polkit_authority_get ();
+
+ service->system_bus = connection;
+
+ dbus_g_object_type_install_info (CPUFREQ_TYPE_SELECTOR_SERVICE,
+ &dbus_glib_cpufreq_selector_service_object_info);
+ dbus_g_connection_register_g_object (connection,
+ "/org/mate/cpufreq_selector/selector",
+ G_OBJECT (service));
+ dbus_g_error_domain_register (CPUFREQ_SELECTOR_SERVICE_ERROR, NULL,
+ CPUFREQ_TYPE_SELECTOR_SERVICE_ERROR);
+
+ reset_killtimer ();
+
+ return TRUE;
+}
+
+static CPUFreqSelector *
+get_selector_for_cpu (CPUFreqSelectorService *service,
+ guint cpu)
+{
+ if (!service->selectors[cpu]) {
+ service->selectors[cpu] = cpufreq_selector_factory_create_selector (cpu);
+ if (!service->selectors[cpu])
+ return NULL;
+
+ if (service->selectors_max < cpu)
+ service->selectors_max = cpu;
+ }
+
+ return service->selectors[cpu];
+}
+
+/* PolicyKit */
+static gboolean
+cpufreq_selector_service_check_policy (CPUFreqSelectorService *service,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ PolkitSubject *subject;
+ PolkitAuthorizationResult *result;
+ gchar *sender;
+ gboolean ret;
+
+ sender = dbus_g_method_get_sender (context);
+ subject = polkit_system_bus_name_new (sender);
+ g_free (sender);
+
+ result = polkit_authority_check_authorization_sync (service->authority,
+ subject,
+ "org.mate.cpufreqselector",
+ NULL,
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ NULL, error);
+ g_object_unref (subject);
+
+ if (*error) {
+ g_warning ("Check policy: %s", (*error)->message);
+ g_object_unref (result);
+
+ return FALSE;
+ }
+
+ ret = polkit_authorization_result_get_is_authorized (result);
+ if (!ret) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_NOT_AUTHORIZED,
+ "Caller is not authorized");
+ }
+
+ g_object_unref (result);
+
+ return ret;
+}
+
+/* D-BUS interface */
+gboolean
+cpufreq_selector_service_set_frequency (CPUFreqSelectorService *service,
+ guint cpu,
+ guint frequency,
+ DBusGMethodInvocation *context)
+{
+ CPUFreqSelector *selector;
+ GError *error = NULL;
+
+ reset_killtimer ();
+
+ if (!cpufreq_selector_service_check_policy (service, context, &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (cpu > MAX_CPUS) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting frequency on cpu %d: Invalid cpu",
+ cpu);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ selector = get_selector_for_cpu (service, cpu);
+ if (!selector) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting frequency on cpu %d: No cpufreq support",
+ cpu);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ cpufreq_selector_set_frequency (selector, frequency, &error);
+ if (error) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting frequency %d on cpu %d: %s",
+ frequency, cpu, error->message);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ dbus_g_method_return (context);
+
+ return TRUE;
+}
+
+gboolean
+cpufreq_selector_service_set_governor (CPUFreqSelectorService *service,
+ guint cpu,
+ const gchar *governor,
+ DBusGMethodInvocation *context)
+{
+ CPUFreqSelector *selector;
+ GError *error = NULL;
+
+ reset_killtimer ();
+
+ if (!cpufreq_selector_service_check_policy (service, context, &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (cpu > MAX_CPUS) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting governor on cpu %d: Invalid cpu",
+ cpu);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ selector = get_selector_for_cpu (service, cpu);
+ if (!selector) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting governor on cpu %d: No cpufreq support",
+ cpu);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ cpufreq_selector_set_governor (selector, governor, &error);
+ if (error) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting governor %s on cpu %d: %s",
+ governor, cpu, error->message);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ dbus_g_method_return (context);
+
+ return TRUE;
+}
+
+
+gboolean
+cpufreq_selector_service_can_set (CPUFreqSelectorService *service,
+ DBusGMethodInvocation *context)
+{
+ PolkitSubject *subject;
+ PolkitAuthorizationResult *result;
+ gchar *sender;
+ gboolean ret;
+ GError *error = NULL;
+
+ reset_killtimer ();
+
+ sender = dbus_g_method_get_sender (context);
+ subject = polkit_system_bus_name_new (sender);
+ g_free (sender);
+
+ result = polkit_authority_check_authorization_sync (service->authority,
+ subject,
+ "org.mate.cpufreqselector",
+ NULL,
+ 0,
+ NULL,
+ &error);
+ g_object_unref (subject);
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (polkit_authorization_result_get_is_authorized (result)) {
+ ret = TRUE;
+ } else if (polkit_authorization_result_get_is_challenge (result)) {
+ ret = TRUE;
+ } else {
+ ret = FALSE;
+ }
+
+ g_object_unref (result);
+
+ dbus_g_method_return (context, ret);
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-service.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.h
new file mode 100644
index 00000000..a6bcc77b
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.h
@@ -0,0 +1,71 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CPUFREQ_SELECTOR_SERVICE_H__
+#define __CPUFREQ_SELECTOR_SERVICE_H__
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR_SERVICE (cpufreq_selector_service_get_type ())
+#define CPUFREQ_SELECTOR_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR_SERVICE, CPUFreqSelectorService))
+#define CPUFREQ_SELECTOR_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR_SERVICE, CPUFreqSelectorServiceClass))
+#define CPUFREQ_IS_SELECTOR_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR_SERVICE))
+#define CPUFREQ_IS_SELECTOR_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR_SERVICE))
+#define CPUFREQ_SELECTOR_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR_SERVICE, CPUFreqSelectorServiceClass))
+
+#define SELECTOR_SERVICE (cpufreq_selector_service_get_instance ())
+
+#define CPUFREQ_SELECTOR_SERVICE_ERROR (cpufreq_selector_service_error_quark ())
+#define CPUFREQ_TYPE_SELECTOR_SERVICE_ERROR (cpufreq_selector_service_error_get_type ())
+
+enum {
+ SERVICE_ERROR_GENERAL,
+ SERVICE_ERROR_DBUS,
+ SERVICE_ERROR_ALREADY_REGISTERED,
+ SERVICE_ERROR_NOT_AUTHORIZED
+};
+
+typedef struct _CPUFreqSelectorService CPUFreqSelectorService;
+typedef struct _CPUFreqSelectorServiceClass CPUFreqSelectorServiceClass;
+
+GType cpufreq_selector_service_get_type (void) G_GNUC_CONST;
+GType cpufreq_selector_service_error_get_type (void) G_GNUC_CONST;
+GQuark cpufreq_selector_service_error_quark (void) G_GNUC_CONST;
+CPUFreqSelectorService *cpufreq_selector_service_get_instance (void);
+gboolean cpufreq_selector_service_register (CPUFreqSelectorService *service,
+ GError **error);
+
+gboolean cpufreq_selector_service_set_frequency (CPUFreqSelectorService *service,
+ guint cpu,
+ guint frequency,
+ DBusGMethodInvocation *context);
+gboolean cpufreq_selector_service_set_governor (CPUFreqSelectorService *service,
+ guint cpu,
+ const gchar *governor,
+ DBusGMethodInvocation *context);
+gboolean cpufreq_selector_service_can_set (CPUFreqSelectorService *service,
+ DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_SERVICE_H__ */
+
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-service.xml b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.xml
new file mode 100644
index 00000000..798dd5b2
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<node name="/org/mate/CPUFreqSelector">
+ <interface name="org.mate.CPUFreqSelector">
+ <method name="SetFrequency">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cpu" direction="in" type="u"/>
+ <arg name="frequency" direction="in" type="u"/>
+ </method>
+
+ <method name="SetGovernor">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cpu" direction="in" type="u"/>
+ <arg name="governor" direction="in" type="s"/>
+ </method>
+
+ <method name="CanSet">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="result" direction="out" type="b"/>
+ </method>
+
+ </interface>
+</node>
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.c
new file mode 100644
index 00000000..ae790caf
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.c
@@ -0,0 +1,430 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "cpufreq-selector-sysfs.h"
+
+#define CPUFREQ_SELECTOR_SYSFS_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), CPUFREQ_TYPE_SELECTOR_SYSFS, CPUFreqSelectorSysfsPrivate))
+
+struct _CPUFreqSelectorSysfsPrivate {
+ GList *available_freqs;
+ GList *available_govs;
+};
+
+static void cpufreq_selector_sysfs_init (CPUFreqSelectorSysfs *selector);
+static void cpufreq_selector_sysfs_class_init (CPUFreqSelectorSysfsClass *klass);
+static void cpufreq_selector_sysfs_finalize (GObject *object);
+
+static gboolean cpufreq_selector_sysfs_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+static gboolean cpufreq_selector_sysfs_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+
+#define CPUFREQ_SYSFS_BASE_PATH "/sys/devices/system/cpu/cpu%u/cpufreq/%s"
+
+G_DEFINE_TYPE (CPUFreqSelectorSysfs, cpufreq_selector_sysfs, CPUFREQ_TYPE_SELECTOR)
+
+static void
+cpufreq_selector_sysfs_init (CPUFreqSelectorSysfs *selector)
+{
+ selector->priv = CPUFREQ_SELECTOR_SYSFS_GET_PRIVATE (selector);
+
+ selector->priv->available_freqs = NULL;
+ selector->priv->available_govs = NULL;
+}
+
+static void
+cpufreq_selector_sysfs_class_init (CPUFreqSelectorSysfsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CPUFreqSelectorClass *selector_class = CPUFREQ_SELECTOR_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (CPUFreqSelectorSysfsPrivate));
+
+ selector_class->set_frequency = cpufreq_selector_sysfs_set_frequency;
+ selector_class->set_governor = cpufreq_selector_sysfs_set_governor;
+
+ object_class->finalize = cpufreq_selector_sysfs_finalize;
+}
+
+static void
+cpufreq_selector_sysfs_finalize (GObject *object)
+{
+ CPUFreqSelectorSysfs *selector = CPUFREQ_SELECTOR_SYSFS (object);
+
+ if (selector->priv->available_freqs) {
+ g_list_foreach (selector->priv->available_freqs,
+ (GFunc) g_free,
+ NULL);
+ g_list_free (selector->priv->available_freqs);
+ selector->priv->available_freqs = NULL;
+ }
+
+ if (selector->priv->available_govs) {
+ g_list_foreach (selector->priv->available_govs,
+ (GFunc) g_free,
+ NULL);
+ g_list_free (selector->priv->available_govs);
+ selector->priv->available_govs = NULL;
+ }
+
+ G_OBJECT_CLASS (cpufreq_selector_sysfs_parent_class)->finalize (object);
+}
+
+CPUFreqSelector *
+cpufreq_selector_sysfs_new (guint cpu)
+{
+ CPUFreqSelector *selector;
+
+ selector = CPUFREQ_SELECTOR (g_object_new (CPUFREQ_TYPE_SELECTOR_SYSFS,
+ "cpu", cpu,
+ NULL));
+
+ return selector;
+}
+
+static gchar *
+cpufreq_sysfs_read (const gchar *path,
+ GError **error)
+{
+ gchar *buffer = NULL;
+
+ if (!g_file_get_contents (path, &buffer, NULL, error)) {
+ return NULL;
+ }
+
+ return g_strchomp (buffer);
+}
+
+static gboolean
+cpufreq_sysfs_write (const gchar *path,
+ const gchar *setting,
+ GError **error)
+{
+ FILE *fd;
+
+ fd = g_fopen (path, "w");
+
+ if (!fd) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Failed to open '%s' for writing: "
+ "g_fopen() failed: %s",
+ path,
+ g_strerror (errno));
+
+ return FALSE;
+ }
+
+ if (g_fprintf (fd, "%s", setting) < 0) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Failed to write '%s': "
+ "g_fprintf() failed: %s",
+ path,
+ g_strerror (errno));
+
+ fclose (fd);
+
+ return FALSE;
+ }
+
+ fclose (fd);
+
+ return TRUE;
+}
+
+static gint
+compare (gconstpointer a, gconstpointer b)
+{
+ gint aa, bb;
+
+ aa = atoi ((gchar *) a);
+ bb = atoi ((gchar *) b);
+
+ if (aa == bb)
+ return 0;
+ else if (aa > bb)
+ return -1;
+ else
+ return 1;
+}
+
+static GList *
+cpufreq_selector_sysfs_get_freqs (CPUFreqSelectorSysfs *selector)
+{
+ gchar *buffer;
+ GList *list = NULL;
+ gchar **frequencies = NULL;
+ gint i;
+ gchar *path;
+ guint cpu;
+ GError *error = NULL;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_available_frequencies");
+
+ buffer = cpufreq_sysfs_read (path, &error);
+ if (!buffer) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ g_free (path);
+
+ return NULL;
+ }
+
+ g_free (path);
+
+ frequencies = g_strsplit (buffer, " ", -1);
+
+ i = 0;
+ while (frequencies[i]) {
+ if (!g_list_find_custom (list, frequencies[i], compare))
+ list = g_list_prepend (list, g_strdup (frequencies[i]));
+ i++;
+ }
+
+ g_strfreev (frequencies);
+ g_free (buffer);
+
+ return g_list_sort (list, compare);
+}
+
+static const gchar *
+cpufreq_selector_sysfs_get_valid_frequency (CPUFreqSelectorSysfs *selector,
+ guint frequency)
+{
+ GList *list = NULL;
+ GList *l;
+ gint dist = G_MAXINT;
+ const gchar *retval = NULL;
+
+ if (!selector->priv->available_freqs) {
+ list = cpufreq_selector_sysfs_get_freqs (selector);
+ selector->priv->available_freqs = list;
+ } else {
+ list = selector->priv->available_freqs;
+ }
+
+ if (!list)
+ return NULL;
+
+ for (l = list; l && l->data; l = g_list_next (l)) {
+ const gchar *freq;
+ guint f;
+ guint current_dist;
+
+ freq = (const gchar *) l->data;
+ f = atoi (freq);
+
+ if (f == frequency)
+ return freq;
+
+ current_dist = abs (frequency - f);
+ if (current_dist < dist) {
+ dist = current_dist;
+ retval = freq;
+ }
+ }
+
+ return retval;
+}
+
+static gboolean
+cpufreq_selector_sysfs_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error)
+{
+ gchar *governor;
+ gchar *path;
+ const gchar *frequency_text;
+ guint cpu;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_governor");
+
+ governor = cpufreq_sysfs_read (path, error);
+ g_free (path);
+
+ if (!governor)
+ return FALSE;
+
+ if (g_ascii_strcasecmp (governor, "userspace") != 0) {
+ if (!cpufreq_selector_sysfs_set_governor (selector,
+ "userspace",
+ error)) {
+ g_free (governor);
+
+ return FALSE;
+ }
+ }
+
+ g_free (governor);
+
+ frequency_text =
+ cpufreq_selector_sysfs_get_valid_frequency (CPUFREQ_SELECTOR_SYSFS (selector),
+ frequency);
+ if (!frequency_text) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_SET_FREQUENCY,
+ "Cannot set frequency '%d'",
+ frequency);
+
+ return FALSE;
+ }
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_setspeed");
+ if (!cpufreq_sysfs_write (path, frequency_text, error)) {
+ g_free (path);
+
+ return FALSE;
+ }
+
+ g_free (path);
+
+ return TRUE;
+}
+
+static GList *
+cpufreq_selector_sysfs_get_govs (CPUFreqSelectorSysfs *selector)
+{
+ gchar *buffer;
+ GList *list = NULL;
+ gchar **governors = NULL;
+ gint i;
+ gchar *path;
+ guint cpu;
+ GError *error = NULL;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_available_governors");
+
+ buffer = cpufreq_sysfs_read (path, &error);
+ if (!buffer) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ g_free (path);
+
+ return NULL;
+ }
+
+ g_free (path);
+
+ governors = g_strsplit (buffer, " ", -1);
+
+ i = 0;
+ while (governors[i]) {
+ list = g_list_prepend (list, g_strdup (governors[i]));
+ i++;
+ }
+
+ g_strfreev (governors);
+ g_free (buffer);
+
+ return list;
+}
+
+static gboolean
+cpufreq_selector_sysfs_validate_governor (CPUFreqSelectorSysfs *selector,
+ const gchar *governor)
+{
+ GList *list = NULL;
+
+ if (!selector->priv->available_govs) {
+ list = cpufreq_selector_sysfs_get_govs (selector);
+ selector->priv->available_govs = list;
+ } else {
+ list = selector->priv->available_govs;
+ }
+
+ if (!list)
+ return FALSE;
+
+ list = g_list_find_custom (selector->priv->available_govs,
+ governor,
+ (GCompareFunc) g_ascii_strcasecmp);
+
+ return (list != NULL);
+}
+
+static gboolean
+cpufreq_selector_sysfs_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error)
+{
+ CPUFreqSelectorSysfs *selector_sysfs;
+ gchar *path;
+ guint cpu;
+
+ selector_sysfs = CPUFREQ_SELECTOR_SYSFS (selector);
+
+ if (!cpufreq_selector_sysfs_validate_governor (selector_sysfs, governor)) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_INVALID_GOVERNOR,
+ "Invalid governor '%s'",
+ governor);
+
+ return FALSE;
+ }
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_governor");
+
+ if (!cpufreq_sysfs_write (path, governor, error)) {
+ g_free (path);
+
+ return FALSE;
+ }
+
+ g_free (path);
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.h
new file mode 100644
index 00000000..a2608bbc
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.h
@@ -0,0 +1,58 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_SELECTOR_SYSFS_H__
+#define __CPUFREQ_SELECTOR_SYSFS_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-selector.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR_SYSFS (cpufreq_selector_sysfs_get_type ())
+#define CPUFREQ_SELECTOR_SYSFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR_SYSFS, CPUFreqSelectorSysfs))
+#define CPUFREQ_SELECTOR_SYSFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR_SYSFS, CPUFreqSelectorSysfsClass))
+#define CPUFREQ_IS_SELECTOR_SYSFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR_SYSFS))
+#define CPUFREQ_IS_SELECTOR_SYSFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR_SYSFS))
+#define CPUFREQ_SELECTOR_SYSFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR_SYSFS, CPUFreqSelectorSysfsClass))
+
+typedef struct _CPUFreqSelectorSysfs CPUFreqSelectorSysfs;
+typedef struct _CPUFreqSelectorSysfsClass CPUFreqSelectorSysfsClass;
+typedef struct _CPUFreqSelectorSysfsPrivate CPUFreqSelectorSysfsPrivate;
+
+struct _CPUFreqSelectorSysfs {
+ CPUFreqSelector parent;
+
+ CPUFreqSelectorSysfsPrivate *priv;
+};
+
+struct _CPUFreqSelectorSysfsClass {
+ CPUFreqSelectorClass parent_class;
+};
+
+
+GType cpufreq_selector_sysfs_get_type (void) G_GNUC_CONST;
+CPUFreqSelector *cpufreq_selector_sysfs_new (guint cpu);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_SYSFS_H__ */
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector.c b/cpufreq/src/cpufreq-selector/cpufreq-selector.c
new file mode 100644
index 00000000..f019fec3
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector.c
@@ -0,0 +1,173 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include "cpufreq-selector.h"
+
+#define CPUFREQ_SELECTOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), CPUFREQ_TYPE_SELECTOR, CPUFreqSelectorPrivate))
+
+enum {
+ PROP_0,
+ PROP_CPU
+};
+
+struct _CPUFreqSelectorPrivate {
+ guint cpu;
+};
+
+static void cpufreq_selector_init (CPUFreqSelector *selector);
+static void cpufreq_selector_class_init (CPUFreqSelectorClass *klass);
+
+static void cpufreq_selector_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *spec);
+static void cpufreq_selector_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *spec);
+
+G_DEFINE_ABSTRACT_TYPE (CPUFreqSelector, cpufreq_selector, G_TYPE_OBJECT)
+
+GQuark
+cpufreq_selector_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (error_quark == 0)
+ error_quark =
+ g_quark_from_static_string ("cpufreq-selector-error-quark");
+
+ return error_quark;
+}
+
+static void
+cpufreq_selector_init (CPUFreqSelector *selector)
+{
+
+ selector->priv = CPUFREQ_SELECTOR_GET_PRIVATE (selector);
+
+ selector->priv->cpu = 0;
+}
+
+static void
+cpufreq_selector_class_init (CPUFreqSelectorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (CPUFreqSelectorPrivate));
+
+ object_class->set_property = cpufreq_selector_set_property;
+ object_class->get_property = cpufreq_selector_get_property;
+
+ /* Public virtual methods */
+ klass->set_frequency = NULL;
+ klass->set_governor = NULL;
+
+ /* Porperties */
+ g_object_class_install_property (object_class,
+ PROP_CPU,
+ g_param_spec_uint ("cpu",
+ NULL,
+ NULL,
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE));
+}
+
+static void
+cpufreq_selector_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *spec)
+{
+ CPUFreqSelector *selector = CPUFREQ_SELECTOR (object);
+
+ switch (prop_id) {
+ case PROP_CPU:
+ selector->priv->cpu = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
+ break;
+ }
+}
+
+static void
+cpufreq_selector_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *spec)
+{
+ CPUFreqSelector *selector = CPUFREQ_SELECTOR (object);
+
+ switch (prop_id) {
+ case PROP_CPU:
+ g_value_set_uint (value, selector->priv->cpu);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
+ break;
+ }
+}
+
+gboolean
+cpufreq_selector_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error)
+{
+ CPUFreqSelectorClass *class;
+
+ g_return_val_if_fail (CPUFREQ_IS_SELECTOR (selector), FALSE);
+ g_return_val_if_fail (frequency > 0, FALSE);
+
+ class = CPUFREQ_SELECTOR_GET_CLASS (selector);
+
+ if (class->set_frequency) {
+ return class->set_frequency (selector, frequency, error);
+ }
+
+ return FALSE;
+}
+
+gboolean
+cpufreq_selector_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error)
+{
+ CPUFreqSelectorClass *class;
+
+ g_return_val_if_fail (CPUFREQ_IS_SELECTOR (selector), FALSE);
+ g_return_val_if_fail (governor != NULL, FALSE);
+
+ class = CPUFREQ_SELECTOR_GET_CLASS (selector);
+
+ if (class->set_governor) {
+ return class->set_governor (selector, governor, error);
+ }
+
+ return FALSE;
+}
+
+
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector.h b/cpufreq/src/cpufreq-selector/cpufreq-selector.h
new file mode 100644
index 00000000..73e41054
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector.h
@@ -0,0 +1,74 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_SELECTOR_H__
+#define __CPUFREQ_SELECTOR_H__
+
+#include <glib-object.h>
+
+#define CPUFREQ_TYPE_SELECTOR (cpufreq_selector_get_type ())
+#define CPUFREQ_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR, CPUFreqSelector))
+#define CPUFREQ_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR, CPUFreqSelectorClass))
+#define CPUFREQ_IS_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR))
+#define CPUFREQ_IS_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR))
+#define CPUFREQ_SELECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR, CPUFreqSelectorClass))
+
+#define CPUFREQ_SELECTOR_ERROR (cpufreq_selector_error_quark ())
+
+enum {
+ SELECTOR_ERROR_INVALID_CPU,
+ SELECTOR_ERROR_INVALID_GOVERNOR,
+ SELECTOR_ERROR_SET_FREQUENCY
+};
+
+typedef struct _CPUFreqSelector CPUFreqSelector;
+typedef struct _CPUFreqSelectorClass CPUFreqSelectorClass;
+typedef struct _CPUFreqSelectorPrivate CPUFreqSelectorPrivate;
+
+struct _CPUFreqSelector {
+ GObject parent;
+
+ CPUFreqSelectorPrivate *priv;
+};
+
+struct _CPUFreqSelectorClass {
+ GObjectClass parent_class;
+
+ gboolean (* set_frequency) (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+ gboolean (* set_governor) (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+};
+
+
+GType cpufreq_selector_get_type (void) G_GNUC_CONST;
+GQuark cpufreq_selector_error_quark (void) G_GNUC_CONST;
+
+gboolean cpufreq_selector_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+gboolean cpufreq_selector_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+
+#endif /* __CPUFREQ_SELECTOR_H__ */
diff --git a/cpufreq/src/cpufreq-selector/main.c b/cpufreq/src/cpufreq-selector/main.c
new file mode 100644
index 00000000..f0fbb7b1
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/main.c
@@ -0,0 +1,233 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef HAVE_POLKIT
+#include "cpufreq-selector-service.h"
+#endif
+#include "cpufreq-selector-factory.h"
+
+
+static gint cpu = 0;
+static gchar *governor = NULL;
+static gulong frequency = 0;
+
+static const GOptionEntry options[] = {
+ { "cpu", 'c', 0, G_OPTION_ARG_INT, &cpu, "CPU Number", NULL },
+ { "governor", 'g', 0, G_OPTION_ARG_STRING, &governor, "Governor", NULL },
+ { "frequency", 'f', 0, G_OPTION_ARG_INT, &frequency, "Frequency in KHz", NULL },
+ { NULL }
+};
+
+#ifdef HAVE_POLKIT
+static void
+do_exit (GMainLoop *loop,
+ GObject *object)
+{
+ if (g_main_loop_is_running (loop))
+ g_main_loop_quit (loop);
+}
+
+static void
+cpufreq_selector_set_values_dbus (void)
+{
+ DBusGConnection *connection;
+ DBusGProxy *proxy;
+ gboolean res;
+ GError *error = NULL;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (!connection) {
+ g_printerr ("Couldn't connect to system bus: %s\n",
+ error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.mate.CPUFreqSelector",
+ "/org/mate/cpufreq_selector/selector",
+ "org.mate.CPUFreqSelector");
+ if (!proxy) {
+ g_printerr ("Could not construct proxy object\n");
+
+ return;
+ }
+
+ if (governor) {
+ res = dbus_g_proxy_call (proxy, "SetGovernor", &error,
+ G_TYPE_UINT, cpu,
+ G_TYPE_STRING, governor,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res) {
+ if (error) {
+ g_printerr ("Error calling SetGovernor: %s\n", error->message);
+ g_error_free (error);
+ } else {
+ g_printerr ("Error calling SetGovernor\n");
+ }
+
+ g_object_unref (proxy);
+
+ return;
+ }
+ }
+
+ if (frequency != 0) {
+ res = dbus_g_proxy_call (proxy, "SetFrequency", &error,
+ G_TYPE_UINT, cpu,
+ G_TYPE_UINT, frequency,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res) {
+ if (error) {
+ g_printerr ("Error calling SetFrequency: %s\n", error->message);
+ g_error_free (error);
+ } else {
+ g_printerr ("Error calling SetFrequency\n");
+ }
+
+ g_object_unref (proxy);
+
+ return;
+ }
+ }
+
+ g_object_unref (proxy);
+}
+#endif /* HAVE_POLKIT */
+
+static void
+cpufreq_selector_set_values (void)
+{
+ CPUFreqSelector *selector;
+ GError *error = NULL;
+
+ selector = cpufreq_selector_factory_create_selector (cpu);
+ if (!selector) {
+ g_printerr ("No cpufreq support\n");
+
+ return;
+ }
+
+ if (governor) {
+ cpufreq_selector_set_governor (selector, governor, &error);
+
+ if (error) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ }
+
+ if (frequency != 0) {
+ cpufreq_selector_set_frequency (selector, frequency, &error);
+
+ if (error) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ }
+
+ g_object_unref (selector);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+#ifdef HAVE_POLKIT
+ GMainLoop *loop;
+#endif
+ GOptionContext *context;
+ GError *error = NULL;
+
+#ifndef HAVE_POLKIT
+ if (geteuid () != 0) {
+ g_printerr ("You must be root\n");
+
+ return 1;
+ }
+
+ if (argc < 2) {
+ g_printerr ("Missing operand after `cpufreq-selector'\n");
+ g_printerr ("Try `cpufreq-selector --help' for more information.\n");
+
+ return 1;
+ }
+#endif
+
+ g_type_init ();
+
+ context = g_option_context_new ("- CPUFreq Selector");
+ g_option_context_add_main_entries (context, options, NULL);
+
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ if (error) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_option_context_free (context);
+
+ return 1;
+ }
+
+ g_option_context_free (context);
+
+#ifdef HAVE_POLKIT
+ if (!cpufreq_selector_service_register (SELECTOR_SERVICE, &error)) {
+ if (governor || frequency != 0) {
+ cpufreq_selector_set_values_dbus ();
+
+ return 0;
+ }
+
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+
+ return 1;
+ }
+
+ cpufreq_selector_set_values ();
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_object_weak_ref (G_OBJECT (SELECTOR_SERVICE),
+ (GWeakNotify) do_exit,
+ loop);
+
+ g_main_loop_run (loop);
+
+ g_main_loop_unref (loop);
+#else /* !HAVE_POLKIT */
+ cpufreq_selector_set_values ();
+#endif /* HAVE_POLKIT */
+
+ return 0;
+}
diff --git a/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.conf b/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.conf
new file mode 100644
index 00000000..c4b27a23
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.conf
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<busconfig>
+
+ <!-- Only root can own the service -->
+ <policy user="root">
+ <allow own="org.mate.CPUFreqSelector"/>
+ <allow send_interface="org.mate.CPUFreqSelector"/>
+ </policy>
+
+ <policy context="default">
+ <allow send_interface="org.mate.CPUFreqSelector"/>
+ </policy>
+
+</busconfig>
+
diff --git a/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.service.in b/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.service.in
new file mode 100644
index 00000000..e402df2e
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.mate.CPUFreqSelector
+Exec=@BINDIR@/cpufreq-selector
+User=root
diff --git a/cpufreq/src/cpufreq-selector/org.mate.cpufreqselector.policy.in b/cpufreq/src/cpufreq-selector/org.mate.cpufreqselector.policy.in
new file mode 100644
index 00000000..f1249cd2
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/org.mate.cpufreqselector.policy.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<policyconfig>
+
+ <vendor>The MATE Project</vendor>
+ <vendor_url>http://www.mate.org/</vendor_url>
+ <icon_name>mate-cpu-frequency-applet</icon_name>
+
+ <action id="org.mate.cpufreqselector">
+ <_description>Change CPU Frequency scaling</_description>
+ <_message>Privileges are required to change the CPU Frequency scaling.</_message>
+ <defaults>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+</policyconfig>