a9da3307db733eb1739ba859952610bba3d894abnp/***************************************************************************
a9da3307db733eb1739ba859952610bba3d894abnp *
a9da3307db733eb1739ba859952610bba3d894abnp * addon-cpufreq.c : Routines to support CPUFreq interface
a9da3307db733eb1739ba859952610bba3d894abnp *
de7d23d85e06f547e8cd4ed4bce494209d63612aLin Guo - Sun Microsystems * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
a9da3307db733eb1739ba859952610bba3d894abnp * Use is subject to license terms.
a9da3307db733eb1739ba859952610bba3d894abnp *
a9da3307db733eb1739ba859952610bba3d894abnp * Licensed under the Academic Free License version 2.1
a9da3307db733eb1739ba859952610bba3d894abnp *
a9da3307db733eb1739ba859952610bba3d894abnp ***************************************************************************/
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#ifdef HAVE_CONFIG_H
a9da3307db733eb1739ba859952610bba3d894abnp#include <config.h>
a9da3307db733eb1739ba859952610bba3d894abnp#endif
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#include <stdio.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <errno.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <string.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <strings.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <stdarg.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <unistd.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <sys/types.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <sys/wait.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <stdlib.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <fcntl.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <sys/dkio.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <sys/stat.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <sys/types.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <glib.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <dbus/dbus-glib-lowlevel.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <dbus/dbus-glib.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <priv.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <pwd.h>
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#include <syslog.h>
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#include <libhal.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include "../../hald/logger.h"
a9da3307db733eb1739ba859952610bba3d894abnp#include "../../utils/adt_data.h"
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#include <pwd.h>
a9da3307db733eb1739ba859952610bba3d894abnp#ifdef HAVE_POLKIT
a9da3307db733eb1739ba859952610bba3d894abnp#include <libpolkit.h>
a9da3307db733eb1739ba859952610bba3d894abnp#endif
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#ifdef sun
a9da3307db733eb1739ba859952610bba3d894abnp#include <bsm/adt.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <bsm/adt_event.h>
a9da3307db733eb1739ba859952610bba3d894abnp#include <sys/pm.h>
a9da3307db733eb1739ba859952610bba3d894abnp#endif
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#define POWER_CONF_FILE "/etc/power.conf"
a9da3307db733eb1739ba859952610bba3d894abnp#define PMCONFIG "/usr/sbin/pmconfig -f"
a9da3307db733eb1739ba859952610bba3d894abnp#define PM "/dev/pm"
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#define FILE_ARR_SIZE 256
a9da3307db733eb1739ba859952610bba3d894abnp#define EDIT_TYPE_SIZE 64
a9da3307db733eb1739ba859952610bba3d894abnp#define ERR_BUF_SIZE 256
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#define WAIT_TIME 30
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpchar TMP_CONF_FILE[64] = "/tmp/power.conf.XXXXXX";
a9da3307db733eb1739ba859952610bba3d894abnpconst char *sender;
a9da3307db733eb1739ba859952610bba3d894abnpunsigned long uid;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Specify different CPUFreq related HAL activities that can be done
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpenum hal_type {
a9da3307db733eb1739ba859952610bba3d894abnp CPU_GOV,
a9da3307db733eb1739ba859952610bba3d894abnp CPU_PERFORMANCE
a9da3307db733eb1739ba859952610bba3d894abnp};
a9da3307db733eb1739ba859952610bba3d894abnptypedef enum hal_type power_conf_hal_type;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Various CPUFreq related editable parameters in the power.conf file
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnptypedef struct {
a9da3307db733eb1739ba859952610bba3d894abnp char cpu_gov[EDIT_TYPE_SIZE];
a9da3307db733eb1739ba859952610bba3d894abnp int cpu_th;
a9da3307db733eb1739ba859952610bba3d894abnp} pconf_edit_type;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * CPUFreq interospect XML that exports the various CPUFreq HAL interface
a9da3307db733eb1739ba859952610bba3d894abnp * supported methods
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpconst char *cpufreq_introspect_xml = \
a9da3307db733eb1739ba859952610bba3d894abnp " <method name= \"SetCPUFreqGovernor\">\n \
a9da3307db733eb1739ba859952610bba3d894abnp <arg type= \"s\" name= \"governor\" direction= \"in\"/>\n \
a9da3307db733eb1739ba859952610bba3d894abnp </method>\n \
a9da3307db733eb1739ba859952610bba3d894abnp <method name= \"GetCPUFreqGovernor\">\n \
a9da3307db733eb1739ba859952610bba3d894abnp <type= \"s\" direction= \"out\"/>\n \
a9da3307db733eb1739ba859952610bba3d894abnp </method>\n \
a9da3307db733eb1739ba859952610bba3d894abnp <method name= \"SetCPUFreqPerformance\">\n \
a9da3307db733eb1739ba859952610bba3d894abnp <arg type=\"i\" direction=\"in\"/>\n \
a9da3307db733eb1739ba859952610bba3d894abnp </method>\n \
a9da3307db733eb1739ba859952610bba3d894abnp <method name= \"GetCPUFreqPerformance\">\n \
a9da3307db733eb1739ba859952610bba3d894abnp <type=\"i\" direction=\"out\"/>\n \
a9da3307db733eb1739ba859952610bba3d894abnp </method>\n \
a9da3307db733eb1739ba859952610bba3d894abnp <method name= \"GetCPUFreqAvailableGovernors\">\n \
de7d23d85e06f547e8cd4ed4bce494209d63612aLin Guo - Sun Microsystems <type=\"s\" direction=\"out\"/>\n \
a9da3307db733eb1739ba859952610bba3d894abnp </method>\n";
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * List of governors that are currently supported
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpchar *const gov_list[] = {
a9da3307db733eb1739ba859952610bba3d894abnp "ondemand",
a9da3307db733eb1739ba859952610bba3d894abnp "performance",
a9da3307db733eb1739ba859952610bba3d894abnp NULL
a9da3307db733eb1739ba859952610bba3d894abnp};
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic char current_gov[EDIT_TYPE_SIZE];
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Free up the mem allocated to hold the DBusError
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpcheck_and_free_error(DBusError *error)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp if (dbus_error_is_set (error)) {
a9da3307db733eb1739ba859952610bba3d894abnp dbus_error_free (error);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Edit the /etc/power.conf file to update the cpupm and cpupm_threshold values
a9da3307db733eb1739ba859952610bba3d894abnp * Return 0 on success
a9da3307db733eb1739ba859952610bba3d894abnp * 1 if the governor is not available or supported
a9da3307db733eb1739ba859952610bba3d894abnp * -1 all other errors
a9da3307db733eb1739ba859952610bba3d894abnp * NOTE: Before modifying power.conf, it is first copied into a temp file, and
a9da3307db733eb1739ba859952610bba3d894abnp * pmconfig is executed on the temp file with -f option, which uses temp file
a9da3307db733eb1739ba859952610bba3d894abnp * to set the PM config and then replaces power.conf with the temp file.
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpstatic int
a9da3307db733eb1739ba859952610bba3d894abnpedit_power_conf_file(pconf_edit_type pc_edit_type,
a9da3307db733eb1739ba859952610bba3d894abnp power_conf_hal_type pc_hal_type, char *tmp_file)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp FILE *pfile;
a9da3307db733eb1739ba859952610bba3d894abnp char tstr[FILE_ARR_SIZE];
a9da3307db733eb1739ba859952610bba3d894abnp char temp_str[FILE_ARR_SIZE];
a9da3307db733eb1739ba859952610bba3d894abnp long fset = 0;
a9da3307db733eb1739ba859952610bba3d894abnp long next_fset = 0;
a9da3307db733eb1739ba859952610bba3d894abnp char *file_edit_type;
a9da3307db733eb1739ba859952610bba3d894abnp char *file_edit_value;
a9da3307db733eb1739ba859952610bba3d894abnp char file_edit_threshold[FILE_ARR_SIZE];
a9da3307db733eb1739ba859952610bba3d894abnp char file_update_str[FILE_ARR_SIZE];
a9da3307db733eb1739ba859952610bba3d894abnp int res = 0;
a9da3307db733eb1739ba859952610bba3d894abnp char cp_cmd_str[128];
a9da3307db733eb1739ba859952610bba3d894abnp int tmp_fd;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Copy /etc/power.conf to temp file
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (tmp_file == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO ((" Invalid temp file name"));
a9da3307db733eb1739ba859952610bba3d894abnp return (EINVAL);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (cp_cmd_str, "/usr/bin/cp %s %s", POWER_CONF_FILE, tmp_file);
a9da3307db733eb1739ba859952610bba3d894abnp if (system (cp_cmd_str) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR ((" Error in copying %s to %s, %s",
a9da3307db733eb1739ba859952610bba3d894abnp POWER_CONF_FILE, tmp_file, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp return (errno);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp pfile = fopen (tmp_file, "r+");
a9da3307db733eb1739ba859952610bba3d894abnp if (pfile == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Cannot open file %s: %s",
a9da3307db733eb1739ba859952610bba3d894abnp tmp_file, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp return (errno);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp switch (pc_hal_type) {
a9da3307db733eb1739ba859952610bba3d894abnp case CPU_GOV:
a9da3307db733eb1739ba859952610bba3d894abnp if ((pc_edit_type.cpu_gov == NULL) ||
a9da3307db733eb1739ba859952610bba3d894abnp ((strcmp (pc_edit_type.cpu_gov, "ondemand") != 0) &&
a9da3307db733eb1739ba859952610bba3d894abnp (strcmp (pc_edit_type.cpu_gov, "performance") != 0))) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO ((" CPU governor is not available/valid."
a9da3307db733eb1739ba859952610bba3d894abnp " Should be either ondemand or performance"));
a9da3307db733eb1739ba859952610bba3d894abnp res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_type = "cpupm";
a9da3307db733eb1739ba859952610bba3d894abnp if (strcmp (pc_edit_type.cpu_gov, "ondemand") == 0) {
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_value = " enable";
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_value = "disable";
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp break;
a9da3307db733eb1739ba859952610bba3d894abnp case CPU_PERFORMANCE:
a9da3307db733eb1739ba859952610bba3d894abnp if (pc_edit_type.cpu_th == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO ((" CPU Threshold is not valid."));
a9da3307db733eb1739ba859952610bba3d894abnp res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_type = "cpu-threshold";
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (file_edit_threshold, "%d", pc_edit_type.cpu_th);
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_value = file_edit_threshold;
a9da3307db733eb1739ba859952610bba3d894abnp break;
a9da3307db733eb1739ba859952610bba3d894abnp default:
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" Cannot recognize the type of change being"
a9da3307db733eb1739ba859952610bba3d894abnp " made to /etc/power.conf"));
a9da3307db733eb1739ba859952610bba3d894abnp res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp if ((tstr == NULL) || (strlen (tstr) <= 0))
a9da3307db733eb1739ba859952610bba3d894abnp continue;
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Look for line containing "cpupm" or "cpu-threshold"
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (strstr (tstr, file_edit_type) == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp fset = fset + strlen (tstr);
a9da3307db733eb1739ba859952610bba3d894abnp continue;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * If the required value already present. Just
a9da3307db733eb1739ba859952610bba3d894abnp * return
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (strstr (tstr, file_edit_value) != NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp res = 0;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (fseek (pfile, fset, SEEK_SET) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Error in fseek %s: %s",
a9da3307db733eb1739ba859952610bba3d894abnp POWER_CONF_FILE, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp res = errno;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Update the file with new values
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (file_update_str, "%s %s \n",
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_type, file_edit_value);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Check if the currrent line is the last one. If not,
a9da3307db733eb1739ba859952610bba3d894abnp * to avoid overwriting and wasting space, move remaining
a9da3307db733eb1739ba859952610bba3d894abnp * lines upwards and update at the end
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp next_fset = fset + strlen(tstr);
a9da3307db733eb1739ba859952610bba3d894abnp if (fseek (pfile, next_fset, SEEK_SET) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Error in fseek %s: %s",
a9da3307db733eb1739ba859952610bba3d894abnp tmp_file, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp res = errno;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp if (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp do {
a9da3307db733eb1739ba859952610bba3d894abnp snprintf (temp_str, FILE_ARR_SIZE,
a9da3307db733eb1739ba859952610bba3d894abnp "%s\n", tstr);
a9da3307db733eb1739ba859952610bba3d894abnp fseek (pfile, fset, SEEK_SET);
a9da3307db733eb1739ba859952610bba3d894abnp fputs (temp_str, pfile);
a9da3307db733eb1739ba859952610bba3d894abnp fset = fset + strlen(tstr);
a9da3307db733eb1739ba859952610bba3d894abnp next_fset = next_fset + strlen(tstr);
a9da3307db733eb1739ba859952610bba3d894abnp fseek (pfile, next_fset, SEEK_SET);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp } while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp fseek (pfile, fset, SEEK_SET);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (fputs (file_update_str, pfile) == EOF) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Error in writing to"
a9da3307db733eb1739ba859952610bba3d894abnp " %s: %s", POWER_CONF_FILE,
a9da3307db733eb1739ba859952610bba3d894abnp strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp res = errno;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (fflush (pfile) == EOF) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Error in flushing to"
a9da3307db733eb1739ba859952610bba3d894abnp " %s: %s", POWER_CONF_FILE,
a9da3307db733eb1739ba859952610bba3d894abnp strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp res = 0;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * If the pointer comes here, then the property is not already present.
a9da3307db733eb1739ba859952610bba3d894abnp * Have to append to the file
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("\n Passed value not found. Will append to the file"));
a9da3307db733eb1739ba859952610bba3d894abnp if (fseek (pfile, 0, SEEK_END) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Error in fseek to %s: %s",
a9da3307db733eb1739ba859952610bba3d894abnp POWER_CONF_FILE, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp res = errno;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Update the file with new values
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (file_update_str, "%s %s \n", file_edit_type, file_edit_value);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (fputs (file_update_str, pfile) == EOF) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Error in writing to file %s: %s",
a9da3307db733eb1739ba859952610bba3d894abnp POWER_CONF_FILE, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp res = errno;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (fflush (pfile) == EOF) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Error in flushing to %s: %s",
a9da3307db733eb1739ba859952610bba3d894abnp POWER_CONF_FILE, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp res = 0;
a9da3307db733eb1739ba859952610bba3d894abnpout:
a9da3307db733eb1739ba859952610bba3d894abnp fclose (pfile);
a9da3307db733eb1739ba859952610bba3d894abnp return (res);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Depending on the type(cpupm or cpu-threshold) to read, check if they are
a9da3307db733eb1739ba859952610bba3d894abnp * present. If present, return the corresponding value through pc_value arg
a9da3307db733eb1739ba859952610bba3d894abnp * and return 1 from the function. If there is no corresponding entry,return 0.
a9da3307db733eb1739ba859952610bba3d894abnp * Return -1 on error
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic int
a9da3307db733eb1739ba859952610bba3d894abnpread_power_conf_file(pconf_edit_type *pc_value,
a9da3307db733eb1739ba859952610bba3d894abnp power_conf_hal_type pc_hal_type)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp FILE *pfile;
a9da3307db733eb1739ba859952610bba3d894abnp char tstr[FILE_ARR_SIZE];
a9da3307db733eb1739ba859952610bba3d894abnp long fset = 0;
a9da3307db733eb1739ba859952610bba3d894abnp char *file_edit_type;
a9da3307db733eb1739ba859952610bba3d894abnp char *tpstr;
a9da3307db733eb1739ba859952610bba3d894abnp int res = 0;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp pfile = fopen (POWER_CONF_FILE, "r");
a9da3307db733eb1739ba859952610bba3d894abnp if (pfile == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("\n Cannot open the file %s: %s",
a9da3307db733eb1739ba859952610bba3d894abnp POWER_CONF_FILE, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp return (-1);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp switch (pc_hal_type) {
a9da3307db733eb1739ba859952610bba3d894abnp case CPU_GOV:
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_type = "cpupm";
a9da3307db733eb1739ba859952610bba3d894abnp break;
a9da3307db733eb1739ba859952610bba3d894abnp case CPU_PERFORMANCE:
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_type = "cpu-threshold";
a9da3307db733eb1739ba859952610bba3d894abnp break;
a9da3307db733eb1739ba859952610bba3d894abnp default :
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Cannot recognize the HAL type to get value"));
a9da3307db733eb1739ba859952610bba3d894abnp res = -1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp if ((tstr == NULL) || (strlen (tstr) <= 0))
a9da3307db733eb1739ba859952610bba3d894abnp continue;
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Look for line containing "cpupm" or "cpu-threshold"
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (strstr (tstr, file_edit_type) == NULL)
a9da3307db733eb1739ba859952610bba3d894abnp continue;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * If the required value already present. Just
a9da3307db733eb1739ba859952610bba3d894abnp * get the value
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp tpstr = strtok (tstr, " ");
a9da3307db733eb1739ba859952610bba3d894abnp tpstr = strtok (NULL, " ");
a9da3307db733eb1739ba859952610bba3d894abnp if (tpstr == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Value of %s in %s is not valid",
a9da3307db733eb1739ba859952610bba3d894abnp file_edit_type, POWER_CONF_FILE));
a9da3307db733eb1739ba859952610bba3d894abnp res = -1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (pc_hal_type == CPU_GOV) {
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Copy the corresponding governor
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (strcmp (tpstr, "enable") == 0) {
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (pc_value->cpu_gov,
a9da3307db733eb1739ba859952610bba3d894abnp "%s", "ondemand");
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (pc_value->cpu_gov,
a9da3307db733eb1739ba859952610bba3d894abnp "%s", "performance");
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp pc_value->cpu_th = atoi (tpstr);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp res = 1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Entry not found in the file
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" No entry of %s in %s", file_edit_type, POWER_CONF_FILE));
a9da3307db733eb1739ba859952610bba3d894abnp res = 0;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpout:
a9da3307db733eb1739ba859952610bba3d894abnp fclose (pfile);
a9da3307db733eb1739ba859952610bba3d894abnp return (res);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Depending on the type(Governor or Perfromance) to read, get the current
a9da3307db733eb1739ba859952610bba3d894abnp * values through PM ioctls().
a9da3307db733eb1739ba859952610bba3d894abnp * For "Governor", return the cpupm state and for "Performance" return the
a9da3307db733eb1739ba859952610bba3d894abnp * current cpu threshold.
a9da3307db733eb1739ba859952610bba3d894abnp * Return the corresponding value through cur_value and return 1 from the
a9da3307db733eb1739ba859952610bba3d894abnp * function for success. Return -1 on error
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic int
a9da3307db733eb1739ba859952610bba3d894abnpget_cur_val(pconf_edit_type *cur_value,
a9da3307db733eb1739ba859952610bba3d894abnp power_conf_hal_type pc_hal_type)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp int pm_fd;
a9da3307db733eb1739ba859952610bba3d894abnp int res = -1;
a9da3307db733eb1739ba859952610bba3d894abnp int pm_ret;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp pm_fd = open (PM, O_RDONLY);
a9da3307db733eb1739ba859952610bba3d894abnp if (pm_fd == -1) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Error opening %s: %s \n", PM, strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp return (res);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp switch (pc_hal_type) {
a9da3307db733eb1739ba859952610bba3d894abnp case CPU_GOV:
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * First check the PM_GET_CPUPM_STATE. If it is not available
a9da3307db733eb1739ba859952610bba3d894abnp * then check PM_GET_PM_STATE
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp pm_ret = ioctl (pm_fd, PM_GET_CPUPM_STATE);
a9da3307db733eb1739ba859952610bba3d894abnp if (pm_ret < 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Error in ioctl PM_GET_CPUPM_STATE: %s \n",
a9da3307db733eb1739ba859952610bba3d894abnp strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp switch (pm_ret) {
a9da3307db733eb1739ba859952610bba3d894abnp case PM_CPU_PM_ENABLED:
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (cur_value->cpu_gov, "%s", "ondemand");
a9da3307db733eb1739ba859952610bba3d894abnp res = 1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp case PM_CPU_PM_DISABLED:
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (cur_value->cpu_gov, "%s", "performance");
a9da3307db733eb1739ba859952610bba3d894abnp res = 1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp case PM_CPU_PM_NOTSET:
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Check for PM_GET_PM_STATE
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp pm_ret = ioctl (pm_fd, PM_GET_PM_STATE);
a9da3307db733eb1739ba859952610bba3d894abnp if (pm_ret < 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Error in ioctl PM_GET_PM_STATE: "
a9da3307db733eb1739ba859952610bba3d894abnp "%s", strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp switch (pm_ret) {
a9da3307db733eb1739ba859952610bba3d894abnp case PM_SYSTEM_PM_ENABLED:
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (cur_value->cpu_gov, "%s", "ondemand");
a9da3307db733eb1739ba859952610bba3d894abnp res = 1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp case PM_SYSTEM_PM_DISABLED:
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (cur_value->cpu_gov, "%s",
a9da3307db733eb1739ba859952610bba3d894abnp "performance");
a9da3307db733eb1739ba859952610bba3d894abnp res = 1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp default:
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("PM Internal error during ioctl "
a9da3307db733eb1739ba859952610bba3d894abnp "PM_GET_PM_STATE"));
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp default:
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Unknown value ioctl PM_GET_CPUPM_STATE"));
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp case CPU_PERFORMANCE:
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * First check the PM_GET_CPU_THRESHOLD. If it is not available
a9da3307db733eb1739ba859952610bba3d894abnp * then check PM_GET_SYSTEM_THRESHOLD
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp pm_ret = ioctl (pm_fd, PM_GET_CPU_THRESHOLD);
a9da3307db733eb1739ba859952610bba3d894abnp if (pm_ret >= 0) {
a9da3307db733eb1739ba859952610bba3d894abnp cur_value->cpu_th = pm_ret;
a9da3307db733eb1739ba859952610bba3d894abnp res = 1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp } else if ((pm_ret == EINVAL) || (pm_ret == ENOTTY)) {
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * PM_GET_CPU_THRESHOLD is not available
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp pm_ret = ioctl (pm_fd, PM_GET_SYSTEM_THRESHOLD);
a9da3307db733eb1739ba859952610bba3d894abnp if (res >= 0) {
a9da3307db733eb1739ba859952610bba3d894abnp cur_value->cpu_th = pm_ret;
a9da3307db733eb1739ba859952610bba3d894abnp res = 1;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Error in PM_GET_CPU_THRESHOLD: %s",
a9da3307db733eb1739ba859952610bba3d894abnp strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR ((" Error in ioctl PM_GET_CPU_THRESHOLD: %s",
a9da3307db733eb1739ba859952610bba3d894abnp strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp default :
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Cannot recognize the HAL type to get value"));
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnpout:
a9da3307db733eb1739ba859952610bba3d894abnp close (pm_fd);
a9da3307db733eb1739ba859952610bba3d894abnp return (res);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Send an error message as a response to the pending call
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpgenerate_err_msg(DBusConnection *con,
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg,
a9da3307db733eb1739ba859952610bba3d894abnp const char *err_name,
a9da3307db733eb1739ba859952610bba3d894abnp char *fmt, ...)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *err_msg;
a9da3307db733eb1739ba859952610bba3d894abnp char err_buf[ERR_BUF_SIZE];
a9da3307db733eb1739ba859952610bba3d894abnp va_list va_args;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp va_start (va_args, fmt);
a9da3307db733eb1739ba859952610bba3d894abnp vsnprintf (err_buf, ERR_BUF_SIZE, fmt, va_args);
a9da3307db733eb1739ba859952610bba3d894abnp va_end (va_args);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" Sending error message: %s", err_buf));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp err_msg = dbus_message_new_error (msg, err_name, err_buf);
a9da3307db733eb1739ba859952610bba3d894abnp if (err_msg == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("No Memory for DBUS error msg"));
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_connection_send (con, err_msg, NULL)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR ((" Out Of Memory!"));
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp dbus_connection_flush (con);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpgen_unknown_gov_err(DBusConnection *con,
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg,
a9da3307db733eb1739ba859952610bba3d894abnp char *err_str)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp generate_err_msg (con,
a9da3307db733eb1739ba859952610bba3d894abnp msg,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.CPUFreq.UnknownGovernor",
a9da3307db733eb1739ba859952610bba3d894abnp "Unknown CPUFreq Governor: %s",
a9da3307db733eb1739ba859952610bba3d894abnp err_str);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpgen_no_suitable_gov_err(DBusConnection *con,
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg,
a9da3307db733eb1739ba859952610bba3d894abnp char *err_str)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp generate_err_msg (con,
a9da3307db733eb1739ba859952610bba3d894abnp msg,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.CPUFreq.NoSuitableGovernor",
a9da3307db733eb1739ba859952610bba3d894abnp "Could not find a suitable governor: %s",
a9da3307db733eb1739ba859952610bba3d894abnp err_str);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpgen_cpufreq_err(DBusConnection *con,
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg,
a9da3307db733eb1739ba859952610bba3d894abnp char *err_str)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp generate_err_msg (con,
a9da3307db733eb1739ba859952610bba3d894abnp msg,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.CPUFreq.Error",
a9da3307db733eb1739ba859952610bba3d894abnp "%s: Syslog might give more information",
a9da3307db733eb1739ba859952610bba3d894abnp err_str);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Puts the required cpufreq audit data and calls adt_put_event()
a9da3307db733eb1739ba859952610bba3d894abnp * to generate auditing
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpaudit_cpufreq(const adt_export_data_t *imported_state, au_event_t event_id,
a9da3307db733eb1739ba859952610bba3d894abnp int result, const char *auth_used, const int cpu_thr_value)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp adt_session_data_t *ah;
a9da3307db733eb1739ba859952610bba3d894abnp adt_event_data_t *event;
a9da3307db733eb1739ba859952610bba3d894abnp struct passwd *msg_pwd;
a9da3307db733eb1739ba859952610bba3d894abnp uid_t gid;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_start_session (&ah, imported_state, 0) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("adt_start_session failed: %s", strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if ((event = adt_alloc_event (ah, event_id)) == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO(("adt_alloc_event audit_cpufreq failed: %s",
a9da3307db733eb1739ba859952610bba3d894abnp strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp switch (event_id) {
a9da3307db733eb1739ba859952610bba3d894abnp case ADT_cpu_ondemand:
a9da3307db733eb1739ba859952610bba3d894abnp event->adt_cpu_ondemand.auth_used = (char *)auth_used;
a9da3307db733eb1739ba859952610bba3d894abnp break;
a9da3307db733eb1739ba859952610bba3d894abnp case ADT_cpu_performance:
a9da3307db733eb1739ba859952610bba3d894abnp event->adt_cpu_performance.auth_used = (char *)auth_used;
a9da3307db733eb1739ba859952610bba3d894abnp break;
a9da3307db733eb1739ba859952610bba3d894abnp case ADT_cpu_threshold:
a9da3307db733eb1739ba859952610bba3d894abnp event->adt_cpu_threshold.auth_used = (char *)auth_used;
a9da3307db733eb1739ba859952610bba3d894abnp event->adt_cpu_threshold.threshold = cpu_thr_value;
a9da3307db733eb1739ba859952610bba3d894abnp break;
a9da3307db733eb1739ba859952610bba3d894abnp default:
a9da3307db733eb1739ba859952610bba3d894abnp goto clean;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (result == 0) {
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("adt_put_event(%d, ADT_SUCCESS) failed",
a9da3307db733eb1739ba859952610bba3d894abnp event_id));
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_put_event (event, ADT_FAILURE, result) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("adt_put_event(%d, ADT_FAILURE) failed",
a9da3307db733eb1739ba859952610bba3d894abnp event_id));
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpclean:
a9da3307db733eb1739ba859952610bba3d894abnp adt_free_event (event);
a9da3307db733eb1739ba859952610bba3d894abnp (void) adt_end_session (ah);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Check if the cpufreq related operations are authorized
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic int
a9da3307db733eb1739ba859952610bba3d894abnpcheck_authorization(DBusConnection *con, DBusMessage *msg)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp int adt_res = 0;
a9da3307db733eb1739ba859952610bba3d894abnp#ifdef HAVE_POLKIT
a9da3307db733eb1739ba859952610bba3d894abnp char user_id[128];
a9da3307db733eb1739ba859952610bba3d894abnp char *udi;
a9da3307db733eb1739ba859952610bba3d894abnp char *privilege;
a9da3307db733eb1739ba859952610bba3d894abnp DBusError error;
a9da3307db733eb1739ba859952610bba3d894abnp gboolean is_priv_allowed;
a9da3307db733eb1739ba859952610bba3d894abnp gboolean is_priv_temporary;
a9da3307db733eb1739ba859952610bba3d894abnp DBusConnection *system_bus = NULL;
a9da3307db733eb1739ba859952610bba3d894abnp LibPolKitContext *pol_ctx = NULL;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Check for authorization before proceeding
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp udi = getenv ("HAL_PROP_INFO_UDI");
a9da3307db733eb1739ba859952610bba3d894abnp privilege = "hal-power-cpu";
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_error_init (&error);
a9da3307db733eb1739ba859952610bba3d894abnp system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
a9da3307db733eb1739ba859952610bba3d894abnp if (system_bus == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Cannot connect to the system bus"));
a9da3307db733eb1739ba859952610bba3d894abnp LIBHAL_FREE_DBUS_ERROR (&error);
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Cannot connect to the system bus");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp sender = dbus_message_get_sender (msg);
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Auth Sender: %s", sender));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (sender == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Could not get the sender of the message"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Could not get the sender of the message");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ADT_FAIL_VALUE_AUTH;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_error_init (&error);
a9da3307db733eb1739ba859952610bba3d894abnp uid = dbus_bus_get_unix_user (system_bus, sender, &error);
a9da3307db733eb1739ba859952610bba3d894abnp if (dbus_error_is_set (&error)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Could not get the user id of the message"));
a9da3307db733eb1739ba859952610bba3d894abnp LIBHAL_FREE_DBUS_ERROR (&error);
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Could not get the user id of the message sender");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ADT_FAIL_VALUE_AUTH;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp snprintf (user_id, sizeof (user_id), "%d", uid);
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" User id is : %d", uid));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp pol_ctx = libpolkit_new_context (system_bus);
a9da3307db733eb1739ba859952610bba3d894abnp if (pol_ctx == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Cannot get libpolkit context"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Cannot get libpolkit context to check privileges");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ADT_FAIL_VALUE_AUTH;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (libpolkit_is_uid_allowed_for_privilege (pol_ctx,
a9da3307db733eb1739ba859952610bba3d894abnp NULL,
a9da3307db733eb1739ba859952610bba3d894abnp user_id,
a9da3307db733eb1739ba859952610bba3d894abnp privilege,
a9da3307db733eb1739ba859952610bba3d894abnp udi,
a9da3307db733eb1739ba859952610bba3d894abnp &is_priv_allowed,
a9da3307db733eb1739ba859952610bba3d894abnp &is_priv_temporary,
a9da3307db733eb1739ba859952610bba3d894abnp NULL) != LIBPOLKIT_RESULT_OK) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Cannot lookup privilege from PolicyKit"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Error looking up privileges from Policykit");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ADT_FAIL_VALUE_AUTH;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!is_priv_allowed) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Caller doesn't possess required privilege to"
a9da3307db733eb1739ba859952610bba3d894abnp " change the governor"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Caller doesn't possess required "
a9da3307db733eb1739ba859952610bba3d894abnp "privilege to change the governor");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ADT_FAIL_VALUE_AUTH;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" Privilege Succeed"));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#endif
a9da3307db733eb1739ba859952610bba3d894abnpout:
a9da3307db733eb1739ba859952610bba3d894abnp return (adt_res);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Sets the CPU Freq governor. It sets the gov name in the /etc/power.conf
a9da3307db733eb1739ba859952610bba3d894abnp * and executes pmconfig. If governor is "ondemand" then "cpupm" is enabled in
a9da3307db733eb1739ba859952610bba3d894abnp * and if governor is performance, then "cpupm" is disabled
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpset_cpufreq_gov(DBusConnection *con, DBusMessage *msg, void *udata)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessageIter arg_iter;
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg_reply;
a9da3307db733eb1739ba859952610bba3d894abnp char *arg_val;
a9da3307db733eb1739ba859952610bba3d894abnp int arg_type;
a9da3307db733eb1739ba859952610bba3d894abnp int pid;
a9da3307db733eb1739ba859952610bba3d894abnp int done_flag = 0;
a9da3307db733eb1739ba859952610bba3d894abnp int sleep_time = 0;
a9da3307db733eb1739ba859952610bba3d894abnp int status;
a9da3307db733eb1739ba859952610bba3d894abnp int adt_res = 0;
a9da3307db733eb1739ba859952610bba3d894abnp char tmp_conf_file[64] = "/tmp/power.conf.XXXXXX";
a9da3307db733eb1739ba859952610bba3d894abnp int tmp_fd;
a9da3307db733eb1739ba859952610bba3d894abnp char pmconfig_cmd[128];
a9da3307db733eb1739ba859952610bba3d894abnp pconf_edit_type pc_edit_type;
a9da3307db733eb1739ba859952610bba3d894abnp#ifdef sun
a9da3307db733eb1739ba859952610bba3d894abnp adt_export_data_t *adt_data;
a9da3307db733eb1739ba859952610bba3d894abnp size_t adt_data_size;
a9da3307db733eb1739ba859952610bba3d894abnp DBusConnection *system_bus = NULL;
a9da3307db733eb1739ba859952610bba3d894abnp DBusError error;
a9da3307db733eb1739ba859952610bba3d894abnp#endif
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (! dbus_message_iter_init (msg, &arg_iter)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Incoming message has no arguments"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_unknown_gov_err (con, msg, "No governor specified");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp arg_type = dbus_message_iter_get_arg_type (&arg_iter);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (arg_type != DBUS_TYPE_STRING) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Incomming message arg type is not string"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_unknown_gov_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Specified governor is not a string");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp dbus_message_iter_get_basic (&arg_iter, &arg_val);
a9da3307db733eb1739ba859952610bba3d894abnp if (arg_val != NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("SetCPUFreqGov is: %s", arg_val));
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Could not get SetCPUFreqGov from message iter"));
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = check_authorization (con, msg);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_res != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Update the /etc/power.conf file.
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp tmp_fd = mkstemp (tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp if (tmp_fd == -1) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR ((" Error in creating a temp conf file"));
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp strcpy (pc_edit_type.cpu_gov, arg_val);
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = edit_power_conf_file (pc_edit_type, CPU_GOV, tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_res != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Error in edit /etc/power.conf"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Internal Error while setting the governor");
a9da3307db733eb1739ba859952610bba3d894abnp unlink (tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Execute pmconfig
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (pmconfig_cmd, "%s %s", PMCONFIG, tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp if (system (pmconfig_cmd) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR ((" Error in executing pmconfig: %s",
a9da3307db733eb1739ba859952610bba3d894abnp strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = errno;
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Error in executing pmconfig");
a9da3307db733eb1739ba859952610bba3d894abnp unlink (tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp unlink (tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Executed pmconfig"));
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (current_gov, "%s", arg_val);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Just return an empty response, so that if the client
a9da3307db733eb1739ba859952610bba3d894abnp * is waiting for any response will not keep waiting
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp msg_reply = dbus_message_new_method_return (msg);
a9da3307db733eb1739ba859952610bba3d894abnp if (msg_reply == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Out of memory to msg reply"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Out of memory to create a response");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ENOMEM;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_connection_send (con, msg_reply, NULL)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Out of memory to msg reply"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Out of memory to create a response");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ENOMEM;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_connection_flush (con);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpout:
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#ifdef sun
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Audit the new governor change
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp dbus_error_init (&error);
a9da3307db733eb1739ba859952610bba3d894abnp system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
a9da3307db733eb1739ba859952610bba3d894abnp if (system_bus == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Cannot connect to the system bus %s",
a9da3307db733eb1739ba859952610bba3d894abnp error.message));
a9da3307db733eb1739ba859952610bba3d894abnp LIBHAL_FREE_DBUS_ERROR (&error);
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp adt_data = get_audit_export_data (system_bus, sender, &adt_data_size);
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_data != NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp if (strcmp (arg_val, "ondemand") == 0) {
a9da3307db733eb1739ba859952610bba3d894abnp audit_cpufreq (adt_data, ADT_cpu_ondemand, adt_res,
a9da3307db733eb1739ba859952610bba3d894abnp "solaris.system.power.cpu", 0);
a9da3307db733eb1739ba859952610bba3d894abnp } else if (strcmp (arg_val, "performance") == 0) {
a9da3307db733eb1739ba859952610bba3d894abnp audit_cpufreq (adt_data, ADT_cpu_performance, adt_res,
a9da3307db733eb1739ba859952610bba3d894abnp "solaris.system.power.cpu", 0);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp free (adt_data);
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO ((" Could not get audit export data"));
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp#endif /* sun */
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Sets the CPU Freq performance. It sets the cpu-threshold in the
a9da3307db733eb1739ba859952610bba3d894abnp * /etc/power.conf and executes pmconfig. The performnace value should
a9da3307db733eb1739ba859952610bba3d894abnp * be between 1 to 100. The cpu-threshold = ((performance val) * 15) secs.
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpset_cpufreq_performance(DBusConnection *con, DBusMessage *msg, void *udata)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessageIter arg_iter;
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg_reply;
a9da3307db733eb1739ba859952610bba3d894abnp int arg_val;
a9da3307db733eb1739ba859952610bba3d894abnp int arg_type;
a9da3307db733eb1739ba859952610bba3d894abnp int pid;
a9da3307db733eb1739ba859952610bba3d894abnp int done_flag = 0;
a9da3307db733eb1739ba859952610bba3d894abnp int sleep_time = 0;
a9da3307db733eb1739ba859952610bba3d894abnp int adt_res = 0;
a9da3307db733eb1739ba859952610bba3d894abnp char tmp_conf_file[64] = "/tmp/power.conf.XXXXXX";
a9da3307db733eb1739ba859952610bba3d894abnp int tmp_fd;
a9da3307db733eb1739ba859952610bba3d894abnp char pmconfig_cmd[128];
a9da3307db733eb1739ba859952610bba3d894abnp pconf_edit_type pc_edit_type;
a9da3307db733eb1739ba859952610bba3d894abnp#ifdef sun
a9da3307db733eb1739ba859952610bba3d894abnp adt_export_data_t *adt_data;
a9da3307db733eb1739ba859952610bba3d894abnp size_t adt_data_size;
a9da3307db733eb1739ba859952610bba3d894abnp DBusConnection *system_bus = NULL;
a9da3307db733eb1739ba859952610bba3d894abnp DBusError error;
a9da3307db733eb1739ba859952610bba3d894abnp#endif
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = check_authorization (con, msg);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_res != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Performance can only be set to dynamic governors. Currently the
a9da3307db733eb1739ba859952610bba3d894abnp * only supported dynamic governor is ondemand.
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (current_gov[0] == 0) {
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Read the current governor from /etc/power.conf
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (read_power_conf_file (&pc_edit_type, CPU_GOV) != 1) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR ((" Error in reading from /etc/power.conf"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while "
a9da3307db733eb1739ba859952610bba3d894abnp "getting the governor");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (current_gov, "%s", pc_edit_type.cpu_gov);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (strcmp (current_gov, "ondemand") != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("To set performance the current gov should be "
a9da3307db733eb1739ba859952610bba3d894abnp "dynamic like ondemand"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_no_suitable_gov_err (con, msg, "Cannot set performance "
a9da3307db733eb1739ba859952610bba3d894abnp "to the current governor");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (! dbus_message_iter_init (msg, &arg_iter)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Incoming message has no arguments"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_no_suitable_gov_err(con, msg, "No performance specified");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp arg_type = dbus_message_iter_get_arg_type (&arg_iter);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (arg_type != DBUS_TYPE_INT32) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Incomming message arg type is not Integer"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_no_suitable_gov_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Specified performance is not a Integer");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp dbus_message_iter_get_basic (&arg_iter, &arg_val);
a9da3307db733eb1739ba859952610bba3d894abnp if ((arg_val < 1) || (arg_val > 100)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("SetCPUFreqPerformance should be between 1 to 100"
a9da3307db733eb1739ba859952610bba3d894abnp ": %d", arg_val));
a9da3307db733eb1739ba859952610bba3d894abnp gen_no_suitable_gov_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Performance value should be between 1 and 100");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("SetCPUFreqPerformance is: %d", arg_val));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Update the /etc/power.conf file
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp tmp_fd = mkstemp (tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp if (tmp_fd == -1) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR ((" Error in creating a temp conf file"));
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = EINVAL;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp pc_edit_type.cpu_th = arg_val * 15;
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = edit_power_conf_file (pc_edit_type, CPU_PERFORMANCE,
a9da3307db733eb1739ba859952610bba3d894abnp tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_res != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Error while editing /etc/power.conf"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Internal error while setting the performance");
a9da3307db733eb1739ba859952610bba3d894abnp unlink (tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Execute pmconfig
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (pmconfig_cmd, "%s %s", PMCONFIG, tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp if (system (pmconfig_cmd) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR ((" Error in executing pmconfig: %s",
a9da3307db733eb1739ba859952610bba3d894abnp strerror (errno)));
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = errno;
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Internal error while setting the performance");
a9da3307db733eb1739ba859952610bba3d894abnp unlink (tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp unlink (tmp_conf_file);
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Executed pmconfig"));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Just return an empty response, so that if the client
a9da3307db733eb1739ba859952610bba3d894abnp * is waiting for any response will not keep waiting
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp msg_reply = dbus_message_new_method_return (msg);
a9da3307db733eb1739ba859952610bba3d894abnp if (msg_reply == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Out of memory to msg reply"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Out of memory to create a response");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ENOMEM;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_connection_send (con, msg_reply, NULL)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Out of memory to msg reply"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Out of memory to create a response");
a9da3307db733eb1739ba859952610bba3d894abnp adt_res = ENOMEM;
a9da3307db733eb1739ba859952610bba3d894abnp goto out;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_connection_flush (con);
a9da3307db733eb1739ba859952610bba3d894abnpout:
a9da3307db733eb1739ba859952610bba3d894abnp#ifdef sun
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Audit the new performance change
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp dbus_error_init (&error);
a9da3307db733eb1739ba859952610bba3d894abnp system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
a9da3307db733eb1739ba859952610bba3d894abnp if (system_bus == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Cannot connect to the system bus %s",
a9da3307db733eb1739ba859952610bba3d894abnp error.message));
a9da3307db733eb1739ba859952610bba3d894abnp LIBHAL_FREE_DBUS_ERROR (&error);
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp adt_data = get_audit_export_data (system_bus, sender, &adt_data_size);
a9da3307db733eb1739ba859952610bba3d894abnp if (adt_data != NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp audit_cpufreq (adt_data, ADT_cpu_threshold, adt_res,
a9da3307db733eb1739ba859952610bba3d894abnp "solaris.system.power.cpu", arg_val);
a9da3307db733eb1739ba859952610bba3d894abnp free (adt_data);
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO ((" Could not get audit export data"));
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp#endif /* sun */
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Returns in the dbus message the current gov.
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpget_cpufreq_gov(DBusConnection *con, DBusMessage *msg, void *udata)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessageIter rep_iter;
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg_reply;
a9da3307db733eb1739ba859952610bba3d894abnp int res;
a9da3307db733eb1739ba859952610bba3d894abnp pconf_edit_type pc_type;
a9da3307db733eb1739ba859952610bba3d894abnp char *param;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Get the governor type from /etc/power.conf if it is present.
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp res = get_cur_val (&pc_type, CPU_GOV);
a9da3307db733eb1739ba859952610bba3d894abnp if (res != 1) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO ((" Error in getting the current governor"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the governor");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" Current governor is: %s", pc_type.cpu_gov));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp msg_reply = dbus_message_new_method_return (msg);
a9da3307db733eb1739ba859952610bba3d894abnp if (msg_reply == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Out of memory to msg reply"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg,
a9da3307db733eb1739ba859952610bba3d894abnp "Internal error while getting the governor");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Append reply arguments
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp param = (char *) malloc (sizeof (char) * 250);
a9da3307db733eb1739ba859952610bba3d894abnp if (param == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Could not allocate mem to param"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the governor");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp sprintf (param, "%s", pc_type.cpu_gov);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_message_iter_init_append (msg_reply, &rep_iter);
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_message_iter_append_basic (&rep_iter, DBUS_TYPE_STRING,
a9da3307db733eb1739ba859952610bba3d894abnp &param)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Out Of Memory!\n"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the governor");
a9da3307db733eb1739ba859952610bba3d894abnp free (param);
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_connection_send (con, msg_reply, NULL)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Out Of Memory!\n"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the governor");
a9da3307db733eb1739ba859952610bba3d894abnp free (param);
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp dbus_connection_flush (con);
a9da3307db733eb1739ba859952610bba3d894abnp free (param);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Returns in the dbus message the current performance value
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpget_cpufreq_performance(DBusConnection *con, DBusMessage *msg, void *udata)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessageIter rep_iter;
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg_reply;
a9da3307db733eb1739ba859952610bba3d894abnp int res;
a9da3307db733eb1739ba859952610bba3d894abnp pconf_edit_type pc_type;
a9da3307db733eb1739ba859952610bba3d894abnp int param_int;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Get the performance value
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp res = get_cur_val (&pc_type, CPU_PERFORMANCE);
a9da3307db733eb1739ba859952610bba3d894abnp if (res != 1) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO ((" Error in getting current performance"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the performance value");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" The current performance: %d", pc_type.cpu_th));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp msg_reply = dbus_message_new_method_return (msg);
a9da3307db733eb1739ba859952610bba3d894abnp if (msg_reply == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Out of memory to msg reply"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the performance value");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Append reply arguments.pc_type.cpu_th gives the current cputhreshold
a9da3307db733eb1739ba859952610bba3d894abnp * vlaue in seconds. Have to convert it into CPU HAL interface
a9da3307db733eb1739ba859952610bba3d894abnp * performance value
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (pc_type.cpu_th < 15)
a9da3307db733eb1739ba859952610bba3d894abnp param_int = 1;
a9da3307db733eb1739ba859952610bba3d894abnp else
a9da3307db733eb1739ba859952610bba3d894abnp param_int = (pc_type.cpu_th / 15);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Performance: %d \n", param_int));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_message_iter_init_append (msg_reply, &rep_iter);
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_message_iter_append_basic (&rep_iter, DBUS_TYPE_INT32,
a9da3307db733eb1739ba859952610bba3d894abnp &param_int)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Out Of Memory!\n"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the performance value");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_connection_send (con, msg_reply, NULL)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Out Of Memory!\n"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the performance value");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp dbus_connection_flush (con);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp/*
a9da3307db733eb1739ba859952610bba3d894abnp * Returns list of available governors. Currently just two governors are
a9da3307db733eb1739ba859952610bba3d894abnp * supported. They are "ondemand" and "performance"
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpget_cpufreq_avail_gov(DBusConnection *con, DBusMessage *msg, void *udata)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessageIter rep_iter;
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessageIter array_iter;
a9da3307db733eb1739ba859952610bba3d894abnp DBusMessage *msg_reply;
a9da3307db733eb1739ba859952610bba3d894abnp int ngov;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp msg_reply = dbus_message_new_method_return (msg);
a9da3307db733eb1739ba859952610bba3d894abnp if (msg_reply == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("Out of memory to msg reply"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the list of governors");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Append reply arguments
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp dbus_message_iter_init_append (msg_reply, &rep_iter);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_message_iter_open_container (&rep_iter,
a9da3307db733eb1739ba859952610bba3d894abnp DBUS_TYPE_ARRAY,
a9da3307db733eb1739ba859952610bba3d894abnp DBUS_TYPE_STRING_AS_STRING,
a9da3307db733eb1739ba859952610bba3d894abnp &array_iter)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Out of memory to msg reply array"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the list of governors");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp for (ngov = 0; gov_list[ngov] != NULL; ngov++) {
a9da3307db733eb1739ba859952610bba3d894abnp if (gov_list[ngov])
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("\n%d Gov Name: %s", ngov, gov_list[ngov]));
a9da3307db733eb1739ba859952610bba3d894abnp dbus_message_iter_append_basic (&array_iter,
a9da3307db733eb1739ba859952610bba3d894abnp DBUS_TYPE_STRING,
a9da3307db733eb1739ba859952610bba3d894abnp &gov_list[ngov]);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp dbus_message_iter_close_container (&rep_iter, &array_iter);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_connection_send (con, msg_reply, NULL)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("\n Out Of Memory!\n"));
a9da3307db733eb1739ba859952610bba3d894abnp gen_cpufreq_err (con, msg, "Internal error while getting"
a9da3307db733eb1739ba859952610bba3d894abnp " the list of governors");
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp dbus_connection_flush (con);
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic DBusHandlerResult
a9da3307db733eb1739ba859952610bba3d894abnphald_dbus_cpufreq_filter(DBusConnection *con, DBusMessage *msg, void *udata)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" Inside CPUFreq filter:%s", dbus_message_get_path(msg)));
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Check for method types
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_connection_get_is_connected (con))
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("Connection disconnected in cpufreq addon"));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (dbus_message_is_method_call (msg,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.Device.CPUFreq",
a9da3307db733eb1739ba859952610bba3d894abnp "SetCPUFreqGovernor")) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("---- SetCPUFreqGovernor is called "));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp set_cpufreq_gov (con, msg, udata);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp } else if (dbus_message_is_method_call (msg,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.Device.CPUFreq",
a9da3307db733eb1739ba859952610bba3d894abnp "GetCPUFreqGovernor")) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("---- GetCPUFreqGovernor is called "));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp get_cpufreq_gov (con, msg, udata);
a9da3307db733eb1739ba859952610bba3d894abnp } else if (dbus_message_is_method_call (msg,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.Device.CPUFreq",
a9da3307db733eb1739ba859952610bba3d894abnp "GetCPUFreqAvailableGovernors")) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("---- GetCPUFreqAvailableGovernors is called "));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp get_cpufreq_avail_gov (con, msg, udata);
a9da3307db733eb1739ba859952610bba3d894abnp } else if (dbus_message_is_method_call (msg,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.Device.CPUFreq",
a9da3307db733eb1739ba859952610bba3d894abnp "SetCPUFreqPerformance")) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("---- SetCPUFreqPerformance is called "));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp set_cpufreq_performance (con, msg, udata);
a9da3307db733eb1739ba859952610bba3d894abnp } else if (dbus_message_is_method_call (msg,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.Device.CPUFreq",
a9da3307db733eb1739ba859952610bba3d894abnp "GetCPUFreqPerformance")) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("---- GetCPUFreqPerformance is called "));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp get_cpufreq_performance (con, msg, udata);
a9da3307db733eb1739ba859952610bba3d894abnp } else {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("---Not Set/Get cpufreq gov---"));
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp return (DBUS_HANDLER_RESULT_HANDLED);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpstatic void
a9da3307db733eb1739ba859952610bba3d894abnpdrop_privileges()
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp priv_set_t *pPrivSet = NULL;
a9da3307db733eb1739ba859952610bba3d894abnp priv_set_t *lPrivSet = NULL;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Start with the 'basic' privilege set and then add any
a9da3307db733eb1739ba859952610bba3d894abnp * of the privileges that will be required.
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if ((pPrivSet = priv_str_to_set ("basic", ",", NULL)) == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Error in setting the priv"));
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp (void) priv_addset (pPrivSet, PRIV_SYS_DEVICES);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (setppriv (PRIV_SET, PRIV_INHERITABLE, pPrivSet) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Could not set the privileges"));
a9da3307db733eb1739ba859952610bba3d894abnp priv_freeset (pPrivSet);
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp (void) priv_addset (pPrivSet, PRIV_PROC_AUDIT);
a9da3307db733eb1739ba859952610bba3d894abnp (void) priv_addset (pPrivSet, PRIV_SYS_CONFIG);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (setppriv (PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("Could not set the privileges"));
a9da3307db733eb1739ba859952610bba3d894abnp priv_freeset (pPrivSet);
a9da3307db733eb1739ba859952610bba3d894abnp return;
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp priv_freeset (pPrivSet);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp}
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnpint
a9da3307db733eb1739ba859952610bba3d894abnpmain(int argc, char **argv)
a9da3307db733eb1739ba859952610bba3d894abnp{
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp LibHalContext *ctx = NULL;
a9da3307db733eb1739ba859952610bba3d894abnp char *udi;
a9da3307db733eb1739ba859952610bba3d894abnp DBusError error;
a9da3307db733eb1739ba859952610bba3d894abnp DBusConnection *conn;
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp GMainLoop *loop = g_main_loop_new (NULL, FALSE);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp drop_privileges ();
a9da3307db733eb1739ba859952610bba3d894abnp openlog ("hald-addon-cpufreq", LOG_PID, LOG_DAEMON);
a9da3307db733eb1739ba859952610bba3d894abnp setup_logger ();
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp bzero (current_gov, EDIT_TYPE_SIZE-1);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if ((udi = getenv ("UDI")) == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO (("\n Could not get the UDI in addon-cpufreq"));
a9da3307db733eb1739ba859952610bba3d894abnp return (0);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_error_init (&error);
a9da3307db733eb1739ba859952610bba3d894abnp if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_ERROR (("main(): init_direct failed\n"));
a9da3307db733eb1739ba859952610bba3d894abnp return (0);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp dbus_error_init (&error);
a9da3307db733eb1739ba859952610bba3d894abnp if (!libhal_device_addon_is_ready (ctx, getenv ("UDI"), &error)) {
a9da3307db733eb1739ba859952610bba3d894abnp check_and_free_error (&error);
a9da3307db733eb1739ba859952610bba3d894abnp return (0);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Claim the cpufreq interface
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG (("cpufreq Introspect XML: %s", cpufreq_introspect_xml));
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!libhal_device_claim_interface (ctx,
a9da3307db733eb1739ba859952610bba3d894abnp udi,
a9da3307db733eb1739ba859952610bba3d894abnp "org.freedesktop.Hal.Device.CPUFreq",
a9da3307db733eb1739ba859952610bba3d894abnp cpufreq_introspect_xml,
a9da3307db733eb1739ba859952610bba3d894abnp &error)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" Cannot claim the CPUFreq interface"));
a9da3307db733eb1739ba859952610bba3d894abnp check_and_free_error (&error);
a9da3307db733eb1739ba859952610bba3d894abnp return (0);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp conn = libhal_ctx_get_dbus_connection (ctx);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Add the cpufreq capability
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp if (!libhal_device_add_capability (ctx,
a9da3307db733eb1739ba859952610bba3d894abnp udi,
a9da3307db733eb1739ba859952610bba3d894abnp "cpufreq_control",
a9da3307db733eb1739ba859952610bba3d894abnp &error)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_DEBUG ((" Could not add cpufreq_control capability"));
a9da3307db733eb1739ba859952610bba3d894abnp check_and_free_error (&error);
a9da3307db733eb1739ba859952610bba3d894abnp return (0);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Watches and times incoming messages
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_connection_setup_with_g_main (conn, NULL);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp /*
a9da3307db733eb1739ba859952610bba3d894abnp * Add a filter function which gets called when a message comes in
a9da3307db733eb1739ba859952610bba3d894abnp * and processes the message
a9da3307db733eb1739ba859952610bba3d894abnp */
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp if (!dbus_connection_add_filter (conn,
a9da3307db733eb1739ba859952610bba3d894abnp hald_dbus_cpufreq_filter,
a9da3307db733eb1739ba859952610bba3d894abnp NULL,
a9da3307db733eb1739ba859952610bba3d894abnp NULL)) {
a9da3307db733eb1739ba859952610bba3d894abnp HAL_INFO ((" Cannot add the CPUFreq filter function"));
a9da3307db733eb1739ba859952610bba3d894abnp return (0);
a9da3307db733eb1739ba859952610bba3d894abnp }
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp dbus_connection_set_exit_on_disconnect (conn, 0);
a9da3307db733eb1739ba859952610bba3d894abnp
a9da3307db733eb1739ba859952610bba3d894abnp g_main_loop_run (loop);
a9da3307db733eb1739ba859952610bba3d894abnp}