diff options
author | Perberos <[email protected]> | 2011-11-14 18:24:48 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-11-14 18:24:48 -0300 |
commit | 312ba610a1e98fc656fb58178227d7d45a64494e (patch) | |
tree | 54a3c2b6084c80e63fb0526c6e7b8e01627acbd7 /cpufreq/src/cpufreq-selector | |
download | mate-applets-312ba610a1e98fc656fb58178227d7d45a64494e.tar.bz2 mate-applets-312ba610a1e98fc656fb58178227d7d45a64494e.tar.xz |
initial
Diffstat (limited to 'cpufreq/src/cpufreq-selector')
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> |