xref: /onnv-gate/usr/src/cmd/hal/addons/cpufreq/addon-cpufreq.c (revision 9823:d1a95ad35c68)
16654Snp146283 /***************************************************************************
26654Snp146283  *
36654Snp146283  * addon-cpufreq.c : Routines to support CPUFreq interface
46654Snp146283  *
5*9823SLin.Guo@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
66654Snp146283  * Use is subject to license terms.
76654Snp146283  *
86654Snp146283  * Licensed under the Academic Free License version 2.1
96654Snp146283  *
106654Snp146283  ***************************************************************************/
116654Snp146283 
126654Snp146283 
136654Snp146283 #ifdef HAVE_CONFIG_H
146654Snp146283 #include <config.h>
156654Snp146283 #endif
166654Snp146283 
176654Snp146283 #include <stdio.h>
186654Snp146283 #include <errno.h>
196654Snp146283 #include <string.h>
206654Snp146283 #include <strings.h>
216654Snp146283 #include <stdarg.h>
226654Snp146283 #include <unistd.h>
236654Snp146283 #include <sys/types.h>
246654Snp146283 #include <sys/wait.h>
256654Snp146283 #include <stdlib.h>
266654Snp146283 #include <fcntl.h>
276654Snp146283 #include <sys/dkio.h>
286654Snp146283 #include <sys/stat.h>
296654Snp146283 #include <sys/types.h>
306654Snp146283 #include <glib.h>
316654Snp146283 #include <dbus/dbus-glib-lowlevel.h>
326654Snp146283 #include <dbus/dbus-glib.h>
336654Snp146283 #include <priv.h>
346654Snp146283 #include <pwd.h>
356654Snp146283 
366654Snp146283 #include <syslog.h>
376654Snp146283 
386654Snp146283 #include <libhal.h>
396654Snp146283 #include "../../hald/logger.h"
406654Snp146283 #include "../../utils/adt_data.h"
416654Snp146283 
426654Snp146283 #include <pwd.h>
436654Snp146283 #ifdef HAVE_POLKIT
446654Snp146283 #include <libpolkit.h>
456654Snp146283 #endif
466654Snp146283 
476654Snp146283 #ifdef sun
486654Snp146283 #include <bsm/adt.h>
496654Snp146283 #include <bsm/adt_event.h>
506654Snp146283 #include <sys/pm.h>
516654Snp146283 #endif
526654Snp146283 
536654Snp146283 #define	POWER_CONF_FILE "/etc/power.conf"
546654Snp146283 #define	PMCONFIG "/usr/sbin/pmconfig -f"
556654Snp146283 #define	PM "/dev/pm"
566654Snp146283 
576654Snp146283 #define	FILE_ARR_SIZE 256
586654Snp146283 #define	EDIT_TYPE_SIZE 64
596654Snp146283 #define	ERR_BUF_SIZE 256
606654Snp146283 
616654Snp146283 #define	WAIT_TIME 30
626654Snp146283 
636654Snp146283 char TMP_CONF_FILE[64] = "/tmp/power.conf.XXXXXX";
646654Snp146283 const char *sender;
656654Snp146283 unsigned long 	uid;
666654Snp146283 
676654Snp146283 /*
686654Snp146283  * Specify different CPUFreq related HAL activities that can be done
696654Snp146283  */
706654Snp146283 enum hal_type {
716654Snp146283 	CPU_GOV,
726654Snp146283 	CPU_PERFORMANCE
736654Snp146283 };
746654Snp146283 typedef enum hal_type power_conf_hal_type;
756654Snp146283 
766654Snp146283 /*
776654Snp146283  * Various CPUFreq related editable parameters in the power.conf file
786654Snp146283  */
796654Snp146283 typedef struct {
806654Snp146283 	char	cpu_gov[EDIT_TYPE_SIZE];
816654Snp146283 	int	cpu_th;
826654Snp146283 } pconf_edit_type;
836654Snp146283 
846654Snp146283 /*
856654Snp146283  * CPUFreq interospect XML that exports the various CPUFreq HAL interface
866654Snp146283  * supported methods
876654Snp146283  */
886654Snp146283 const char *cpufreq_introspect_xml = \
896654Snp146283 	"	<method name= \"SetCPUFreqGovernor\">\n \
906654Snp146283 		<arg type= \"s\" name= \"governor\" direction= \"in\"/>\n \
916654Snp146283 	</method>\n \
926654Snp146283 	<method name= \"GetCPUFreqGovernor\">\n \
936654Snp146283 		<type= \"s\" direction= \"out\"/>\n \
946654Snp146283 	</method>\n \
956654Snp146283 	<method name= \"SetCPUFreqPerformance\">\n \
966654Snp146283 		<arg type=\"i\" direction=\"in\"/>\n \
976654Snp146283 	</method>\n \
986654Snp146283 	<method name= \"GetCPUFreqPerformance\">\n \
996654Snp146283 		<type=\"i\" direction=\"out\"/>\n \
1006654Snp146283 	</method>\n \
1016654Snp146283 	<method name= \"GetCPUFreqAvailableGovernors\">\n \
102*9823SLin.Guo@Sun.COM 		<type=\"s\" direction=\"out\"/>\n \
1036654Snp146283 	</method>\n";
1046654Snp146283 
1056654Snp146283 /*
1066654Snp146283  * List of governors that are currently supported
1076654Snp146283  */
1086654Snp146283 char *const gov_list[] = {
1096654Snp146283 	"ondemand",
1106654Snp146283 	"performance",
1116654Snp146283 	NULL
1126654Snp146283 };
1136654Snp146283 
1146654Snp146283 static char current_gov[EDIT_TYPE_SIZE];
1156654Snp146283 
1166654Snp146283 /*
1176654Snp146283  * Free up the mem allocated to hold the DBusError
1186654Snp146283  */
1196654Snp146283 static void
check_and_free_error(DBusError * error)1206654Snp146283 check_and_free_error(DBusError *error)
1216654Snp146283 {
1226654Snp146283 	if (dbus_error_is_set (error)) {
1236654Snp146283 		dbus_error_free (error);
1246654Snp146283 	}
1256654Snp146283 }
1266654Snp146283 
1276654Snp146283 /*
1286654Snp146283  * Edit the /etc/power.conf file to update the cpupm and cpupm_threshold values
1296654Snp146283  * Return 0 on success
1306654Snp146283  *	  1 if the governor is not available or supported
1316654Snp146283  *	 -1 all other errors
1326654Snp146283  * NOTE: Before modifying power.conf, it is first copied into a temp file, and
1336654Snp146283  * pmconfig is executed on the temp file with -f option, which uses temp file
1346654Snp146283  * to set the PM config and then replaces power.conf with the temp file.
1356654Snp146283  */
1366654Snp146283 static int
edit_power_conf_file(pconf_edit_type pc_edit_type,power_conf_hal_type pc_hal_type,char * tmp_file)1376654Snp146283 edit_power_conf_file(pconf_edit_type pc_edit_type,
1386654Snp146283     power_conf_hal_type pc_hal_type, char *tmp_file)
1396654Snp146283 {
1406654Snp146283 	FILE	*pfile;
1416654Snp146283 	char  	tstr[FILE_ARR_SIZE];
1426654Snp146283 	char	temp_str[FILE_ARR_SIZE];
1436654Snp146283 	long	fset = 0;
1446654Snp146283 	long	next_fset = 0;
1456654Snp146283 	char	*file_edit_type;
1466654Snp146283 	char    *file_edit_value;
1476654Snp146283 	char    file_edit_threshold[FILE_ARR_SIZE];
1486654Snp146283 	char	file_update_str[FILE_ARR_SIZE];
1496654Snp146283 	int	res = 0;
1506654Snp146283 	char	cp_cmd_str[128];
1516654Snp146283 	int	tmp_fd;
1526654Snp146283 
1536654Snp146283 	/*
1546654Snp146283 	 * Copy /etc/power.conf to temp file
1556654Snp146283 	 */
1566654Snp146283 	if (tmp_file == NULL) {
1576654Snp146283 		HAL_INFO ((" Invalid temp file name"));
1586654Snp146283 		return (EINVAL);
1596654Snp146283 	}
1606654Snp146283 	sprintf (cp_cmd_str, "/usr/bin/cp %s %s", POWER_CONF_FILE, tmp_file);
1616654Snp146283 	if (system (cp_cmd_str) != 0) {
1626654Snp146283 		HAL_ERROR ((" Error in copying %s to %s, %s",
1636654Snp146283 		    POWER_CONF_FILE, tmp_file, strerror (errno)));
1646654Snp146283 		return (errno);
1656654Snp146283 	}
1666654Snp146283 
1676654Snp146283 	pfile = fopen (tmp_file, "r+");
1686654Snp146283 	if (pfile == NULL) {
1696654Snp146283 		HAL_INFO (("Cannot open file %s: %s",
1706654Snp146283 		    tmp_file, strerror (errno)));
1716654Snp146283 		return (errno);
1726654Snp146283 	}
1736654Snp146283 
1746654Snp146283 	switch (pc_hal_type) {
1756654Snp146283 	case CPU_GOV:
1766654Snp146283 		if ((pc_edit_type.cpu_gov == NULL) ||
1776654Snp146283 		    ((strcmp (pc_edit_type.cpu_gov, "ondemand") != 0) &&
1786654Snp146283 		    (strcmp (pc_edit_type.cpu_gov, "performance") != 0))) {
1796654Snp146283 			HAL_INFO ((" CPU governor is not available/valid."
1806654Snp146283 			    " Should be either ondemand or performance"));
1816654Snp146283 			res = EINVAL;
1826654Snp146283 			goto out;
1836654Snp146283 		}
1846654Snp146283 		file_edit_type = "cpupm";
1856654Snp146283 		if (strcmp (pc_edit_type.cpu_gov, "ondemand") == 0) {
1866654Snp146283 			file_edit_value = " enable";
1876654Snp146283 		} else {
1886654Snp146283 			file_edit_value = "disable";
1896654Snp146283 		}
1906654Snp146283 		break;
1916654Snp146283 	case CPU_PERFORMANCE:
1926654Snp146283 		if (pc_edit_type.cpu_th == NULL) {
1936654Snp146283 			HAL_INFO ((" CPU Threshold is not valid."));
1946654Snp146283 			res = EINVAL;
1956654Snp146283 			goto out;
1966654Snp146283 		}
1976654Snp146283 		file_edit_type = "cpu-threshold";
1986654Snp146283 		sprintf (file_edit_threshold, "%d", pc_edit_type.cpu_th);
1996654Snp146283 		file_edit_value = file_edit_threshold;
2006654Snp146283 		break;
2016654Snp146283 	default:
2026654Snp146283 		HAL_DEBUG ((" Cannot recognize the type of change being"
2036654Snp146283 		    " made to /etc/power.conf"));
2046654Snp146283 			res = EINVAL;
2056654Snp146283 			goto out;
2066654Snp146283 	}
2076654Snp146283 
2086654Snp146283 	while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
2096654Snp146283 		if ((tstr == NULL) || (strlen (tstr) <= 0))
2106654Snp146283 			continue;
2116654Snp146283 		/*
2126654Snp146283 		 * Look for line containing "cpupm" or "cpu-threshold"
2136654Snp146283 		 */
2146654Snp146283 
2156654Snp146283 		if (strstr (tstr, file_edit_type) == NULL) {
2166654Snp146283 			fset = fset + strlen (tstr);
2176654Snp146283 			continue;
2186654Snp146283 		}
2196654Snp146283 		/*
2206654Snp146283 		 * If the required value already present. Just
2216654Snp146283 		 * return
2226654Snp146283 		 */
2236654Snp146283 		if (strstr (tstr, file_edit_value) != NULL) {
2246654Snp146283 			res = 0;
2256654Snp146283 			goto out;
2266654Snp146283 		}
2276654Snp146283 
2286654Snp146283 		if (fseek (pfile, fset, SEEK_SET) != 0) {
2296654Snp146283 			HAL_ERROR (("\n Error in fseek %s: %s",
2306654Snp146283 			    POWER_CONF_FILE, strerror (errno)));
2316654Snp146283 			res = errno;
2326654Snp146283 			goto out;
2336654Snp146283 		}
2346654Snp146283 		/*
2356654Snp146283 		 * Update the file with new values
2366654Snp146283 		 */
2376654Snp146283 		sprintf (file_update_str, "%s %s \n",
2386654Snp146283 		    file_edit_type, file_edit_value);
2396654Snp146283 
2406654Snp146283 		/*
2416654Snp146283 		 * Check if the currrent line is the last one. If not,
2426654Snp146283 		 * to avoid overwriting and wasting space, move remaining
2436654Snp146283 		 * lines upwards and update at the end
2446654Snp146283 		 */
2456654Snp146283 		next_fset = fset + strlen(tstr);
2466654Snp146283 		if (fseek (pfile, next_fset, SEEK_SET) != 0) {
2476654Snp146283 			HAL_ERROR (("\n Error in fseek %s: %s",
2486654Snp146283 			    tmp_file, strerror (errno)));
2496654Snp146283 			res = errno;
2506654Snp146283 			goto out;
2516654Snp146283 		}
2526654Snp146283 		if (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
2536654Snp146283 			do {
2546654Snp146283 				snprintf (temp_str, FILE_ARR_SIZE,
2556654Snp146283 				    "%s\n", tstr);
2566654Snp146283 				fseek (pfile, fset, SEEK_SET);
2576654Snp146283 				fputs (temp_str, pfile);
2586654Snp146283 				fset = fset + strlen(tstr);
2596654Snp146283 				next_fset = next_fset + strlen(tstr);
2606654Snp146283 				fseek (pfile, next_fset, SEEK_SET);
2616654Snp146283 
2626654Snp146283 			} while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL);
2636654Snp146283 		}
2646654Snp146283 
2656654Snp146283 		fseek (pfile, fset, SEEK_SET);
2666654Snp146283 
2676654Snp146283 		if (fputs (file_update_str, pfile) == EOF) {
2686654Snp146283 			HAL_ERROR (("\n Error in writing to"
2696654Snp146283 			    " %s: %s", POWER_CONF_FILE,
2706654Snp146283 			    strerror (errno)));
2716654Snp146283 			res = errno;
2726654Snp146283 			goto out;
2736654Snp146283 		}
2746654Snp146283 
2756654Snp146283 		if (fflush (pfile) == EOF) {
2766654Snp146283 			HAL_ERROR (("\n Error in flushing to"
2776654Snp146283 			    " %s: %s", POWER_CONF_FILE,
2786654Snp146283 			    strerror (errno)));
2796654Snp146283 		}
2806654Snp146283 		res = 0;
2816654Snp146283 		goto out;
2826654Snp146283 	}
2836654Snp146283 
2846654Snp146283 	/*
2856654Snp146283 	 * If the pointer comes here, then the property is not already present.
2866654Snp146283 	 * Have to append to the file
2876654Snp146283 	 */
2886654Snp146283 	HAL_DEBUG (("\n Passed value not found. Will append to the file"));
2896654Snp146283 	if (fseek (pfile, 0, SEEK_END) != 0) {
2906654Snp146283 		HAL_ERROR (("\n Error in fseek to %s: %s",
2916654Snp146283 		    POWER_CONF_FILE, strerror (errno)));
2926654Snp146283 		res = errno;
2936654Snp146283 		goto out;
2946654Snp146283 	}
2956654Snp146283 
2966654Snp146283 	/*
2976654Snp146283 	 * Update the file with new values
2986654Snp146283 	 */
2996654Snp146283 	sprintf (file_update_str, "%s %s \n", file_edit_type, file_edit_value);
3006654Snp146283 
3016654Snp146283 	if (fputs (file_update_str, pfile) == EOF) {
3026654Snp146283 		HAL_ERROR (("Error in writing to file %s: %s",
3036654Snp146283 		    POWER_CONF_FILE, strerror (errno)));
3046654Snp146283 		res = errno;
3056654Snp146283 		goto out;
3066654Snp146283 	}
3076654Snp146283 
3086654Snp146283 	if (fflush (pfile) == EOF) {
3096654Snp146283 		HAL_ERROR (("\n Error in flushing to %s: %s",
3106654Snp146283 		    POWER_CONF_FILE, strerror (errno)));
3116654Snp146283 	}
3126654Snp146283 	res = 0;
3136654Snp146283 out:
3146654Snp146283 	fclose (pfile);
3156654Snp146283 	return (res);
3166654Snp146283 }
3176654Snp146283 
3186654Snp146283 /*
3196654Snp146283  * Depending on the type(cpupm or cpu-threshold) to read, check if they are
3206654Snp146283  * present. If present, return the corresponding value through pc_value arg
3216654Snp146283  * and return 1 from the function. If there is no corresponding entry,return 0.
3226654Snp146283  * Return -1 on error
3236654Snp146283  */
3246654Snp146283 
3256654Snp146283 static int
read_power_conf_file(pconf_edit_type * pc_value,power_conf_hal_type pc_hal_type)3266654Snp146283 read_power_conf_file(pconf_edit_type *pc_value,
3276654Snp146283     power_conf_hal_type pc_hal_type)
3286654Snp146283 {
3296654Snp146283 
3306654Snp146283 	FILE	*pfile;
3316654Snp146283 	char  	tstr[FILE_ARR_SIZE];
3326654Snp146283 	long	fset = 0;
3336654Snp146283 	char	*file_edit_type;
3346654Snp146283 	char	*tpstr;
3356654Snp146283 	int	res = 0;
3366654Snp146283 
3376654Snp146283 	pfile = fopen (POWER_CONF_FILE, "r");
3386654Snp146283 	if (pfile == NULL) {
3396654Snp146283 		HAL_INFO (("\n Cannot open the file %s: %s",
3406654Snp146283 		    POWER_CONF_FILE, strerror (errno)));
3416654Snp146283 		return (-1);
3426654Snp146283 	}
3436654Snp146283 
3446654Snp146283 	switch (pc_hal_type) {
3456654Snp146283 	case CPU_GOV:
3466654Snp146283 		file_edit_type = "cpupm";
3476654Snp146283 		break;
3486654Snp146283 	case CPU_PERFORMANCE:
3496654Snp146283 		file_edit_type = "cpu-threshold";
3506654Snp146283 		break;
3516654Snp146283 	default :
3526654Snp146283 		HAL_DEBUG (("Cannot recognize the HAL type to get value"));
3536654Snp146283 		res = -1;
3546654Snp146283 		goto out;
3556654Snp146283 	}
3566654Snp146283 
3576654Snp146283 	while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
3586654Snp146283 		if ((tstr == NULL) || (strlen (tstr) <= 0))
3596654Snp146283 			continue;
3606654Snp146283 		/*
3616654Snp146283 		 * Look for line containing "cpupm" or "cpu-threshold"
3626654Snp146283 		 */
3636654Snp146283 		if (strstr (tstr, file_edit_type) == NULL)
3646654Snp146283 			continue;
3656654Snp146283 
3666654Snp146283 		/*
3676654Snp146283 		 * If the required value already present. Just
3686654Snp146283 		 * get the value
3696654Snp146283 		 */
3706654Snp146283 		tpstr = strtok (tstr, " ");
3716654Snp146283 		tpstr = strtok (NULL, " ");
3726654Snp146283 		if (tpstr == NULL) {
3736654Snp146283 			HAL_INFO (("Value of %s in %s is not valid",
3746654Snp146283 			    file_edit_type, POWER_CONF_FILE));
3756654Snp146283 			res = -1;
3766654Snp146283 			goto out;
3776654Snp146283 		}
3786654Snp146283 
3796654Snp146283 		if (pc_hal_type == CPU_GOV) {
3806654Snp146283 			/*
3816654Snp146283 			 * Copy the corresponding governor
3826654Snp146283 			 */
3836654Snp146283 			if (strcmp (tpstr, "enable") == 0) {
3846654Snp146283 				sprintf (pc_value->cpu_gov,
3856654Snp146283 				    "%s", "ondemand");
3866654Snp146283 			} else {
3876654Snp146283 				sprintf (pc_value->cpu_gov,
3886654Snp146283 				    "%s", "performance");
3896654Snp146283 			}
3906654Snp146283 		} else {
3916654Snp146283 			pc_value->cpu_th = atoi (tpstr);
3926654Snp146283 		}
3936654Snp146283 		res = 1;
3946654Snp146283 		goto out;
3956654Snp146283 	}
3966654Snp146283 	/*
3976654Snp146283 	 * Entry not found in the file
3986654Snp146283 	 */
3996654Snp146283 	HAL_DEBUG ((" No entry of %s in %s", file_edit_type, POWER_CONF_FILE));
4006654Snp146283 	res = 0;
4016654Snp146283 
4026654Snp146283 out:
4036654Snp146283 	fclose (pfile);
4046654Snp146283 	return (res);
4056654Snp146283 }
4066654Snp146283 
4076654Snp146283 
4086654Snp146283 /*
4096654Snp146283  * Depending on the type(Governor or Perfromance) to read, get the current
4106654Snp146283  * values through PM ioctls().
4116654Snp146283  * For "Governor", return the cpupm state and for "Performance" return the
4126654Snp146283  * current cpu threshold.
4136654Snp146283  * Return the corresponding value through cur_value and return 1 from the
4146654Snp146283  * function for success. Return -1 on error
4156654Snp146283  */
4166654Snp146283 
4176654Snp146283 static int
get_cur_val(pconf_edit_type * cur_value,power_conf_hal_type pc_hal_type)4186654Snp146283 get_cur_val(pconf_edit_type *cur_value,
4196654Snp146283     power_conf_hal_type pc_hal_type)
4206654Snp146283 {
4216654Snp146283 
4226654Snp146283 	int pm_fd;
4236654Snp146283 	int res = -1;
4246654Snp146283 	int pm_ret;
4256654Snp146283 
4266654Snp146283 	pm_fd = open (PM, O_RDONLY);
4276654Snp146283 	if (pm_fd == -1) {
4286654Snp146283 		HAL_ERROR (("Error opening %s: %s \n", PM, strerror (errno)));
4296654Snp146283 		return (res);
4306654Snp146283 	}
4316654Snp146283 
4326654Snp146283 	switch (pc_hal_type) {
4336654Snp146283 	case CPU_GOV:
4346654Snp146283 		/*
4356654Snp146283 		 * First check the PM_GET_CPUPM_STATE. If it is not available
4366654Snp146283 		 * then check PM_GET_PM_STATE
4376654Snp146283 		 */
4386654Snp146283 		pm_ret = ioctl (pm_fd, PM_GET_CPUPM_STATE);
4396654Snp146283 		if (pm_ret < 0) {
4406654Snp146283 			HAL_ERROR (("Error in ioctl PM_GET_CPUPM_STATE: %s \n",
4416654Snp146283 			    strerror (errno)));
4426654Snp146283 			goto out;
4436654Snp146283 		}
4446654Snp146283 		switch (pm_ret) {
4456654Snp146283 		case PM_CPU_PM_ENABLED:
4466654Snp146283 			sprintf (cur_value->cpu_gov, "%s", "ondemand");
4476654Snp146283 			res = 1;
4486654Snp146283 			goto out;
4496654Snp146283 		case PM_CPU_PM_DISABLED:
4506654Snp146283 			sprintf (cur_value->cpu_gov, "%s", "performance");
4516654Snp146283 			res = 1;
4526654Snp146283 			goto out;
4536654Snp146283 		case PM_CPU_PM_NOTSET:
4546654Snp146283 			/*
4556654Snp146283 			 * Check for PM_GET_PM_STATE
4566654Snp146283 			 */
4576654Snp146283 			pm_ret = ioctl (pm_fd, PM_GET_PM_STATE);
4586654Snp146283 			if (pm_ret < 0) {
4596654Snp146283 				HAL_ERROR (("Error in ioctl PM_GET_PM_STATE: "
4606654Snp146283 				    "%s", strerror (errno)));
4616654Snp146283 				goto out;
4626654Snp146283 			}
4636654Snp146283 			switch (pm_ret) {
4646654Snp146283 			case PM_SYSTEM_PM_ENABLED:
4656654Snp146283 				sprintf (cur_value->cpu_gov, "%s", "ondemand");
4666654Snp146283 				res = 1;
4676654Snp146283 				goto out;
4686654Snp146283 			case PM_SYSTEM_PM_DISABLED:
4696654Snp146283 				sprintf (cur_value->cpu_gov, "%s",
4706654Snp146283 				    "performance");
4716654Snp146283 				res = 1;
4726654Snp146283 				goto out;
4736654Snp146283 			default:
4746654Snp146283 				HAL_ERROR (("PM Internal error during ioctl "
4756654Snp146283 				    "PM_GET_PM_STATE"));
4766654Snp146283 				goto out;
4776654Snp146283 			}
4786654Snp146283 		default:
4796654Snp146283 			HAL_ERROR (("Unknown value ioctl PM_GET_CPUPM_STATE"));
4806654Snp146283 			goto out;
4816654Snp146283 		}
4826654Snp146283 	case CPU_PERFORMANCE:
4836654Snp146283 		/*
4846654Snp146283 		 * First check the PM_GET_CPU_THRESHOLD. If it is not available
4856654Snp146283 		 * then check PM_GET_SYSTEM_THRESHOLD
4866654Snp146283 		 */
4876654Snp146283 		pm_ret = ioctl (pm_fd, PM_GET_CPU_THRESHOLD);
4886654Snp146283 		if (pm_ret >= 0) {
4896654Snp146283 			cur_value->cpu_th = pm_ret;
4906654Snp146283 			res = 1;
4916654Snp146283 			goto out;
4926654Snp146283 		} else if ((pm_ret == EINVAL) || (pm_ret == ENOTTY)) {
4936654Snp146283 			/*
4946654Snp146283 			 * PM_GET_CPU_THRESHOLD is not available
4956654Snp146283 			 */
4966654Snp146283 			pm_ret = ioctl (pm_fd, PM_GET_SYSTEM_THRESHOLD);
4976654Snp146283 			if (res >= 0) {
4986654Snp146283 				cur_value->cpu_th = pm_ret;
4996654Snp146283 				res = 1;
5006654Snp146283 				goto out;
5016654Snp146283 			} else {
5026654Snp146283 				HAL_ERROR (("Error in PM_GET_CPU_THRESHOLD: %s",
5036654Snp146283 				    strerror (errno)));
5046654Snp146283 				goto out;
5056654Snp146283 			}
5066654Snp146283 		} else {
5076654Snp146283 			HAL_ERROR ((" Error in ioctl PM_GET_CPU_THRESHOLD: %s",
5086654Snp146283 			    strerror (errno)));
5096654Snp146283 			goto out;
5106654Snp146283 		}
5116654Snp146283 	default :
5126654Snp146283 		HAL_DEBUG (("Cannot recognize the HAL type to get value"));
5136654Snp146283 		goto out;
5146654Snp146283 	}
5156654Snp146283 out:
5166654Snp146283 	close (pm_fd);
5176654Snp146283 	return (res);
5186654Snp146283 }
5196654Snp146283 /*
5206654Snp146283  * Send an error message as a response to the pending call
5216654Snp146283  */
5226654Snp146283 static void
generate_err_msg(DBusConnection * con,DBusMessage * msg,const char * err_name,char * fmt,...)5236654Snp146283 generate_err_msg(DBusConnection *con,
5246654Snp146283     DBusMessage *msg,
5256654Snp146283     const char *err_name,
5266654Snp146283     char *fmt, ...)
5276654Snp146283 {
5286654Snp146283 
5296654Snp146283 	DBusMessage	*err_msg;
5306654Snp146283 	char		err_buf[ERR_BUF_SIZE];
5316654Snp146283 	va_list		va_args;
5326654Snp146283 
5336654Snp146283 	va_start (va_args, fmt);
5346654Snp146283 	vsnprintf (err_buf, ERR_BUF_SIZE, fmt, va_args);
5356654Snp146283 	va_end (va_args);
5366654Snp146283 
5376654Snp146283 	HAL_DEBUG ((" Sending error message: %s", err_buf));
5386654Snp146283 
5396654Snp146283 	err_msg = dbus_message_new_error (msg, err_name, err_buf);
5406654Snp146283 	if (err_msg == NULL) {
5416654Snp146283 		HAL_ERROR (("No Memory for DBUS error msg"));
5426654Snp146283 		return;
5436654Snp146283 	}
5446654Snp146283 
5456654Snp146283 	if (!dbus_connection_send (con, err_msg, NULL)) {
5466654Snp146283 		HAL_ERROR ((" Out Of Memory!"));
5476654Snp146283 	}
5486654Snp146283 	dbus_connection_flush (con);
5496654Snp146283 
5506654Snp146283 }
5516654Snp146283 
5526654Snp146283 static void
gen_unknown_gov_err(DBusConnection * con,DBusMessage * msg,char * err_str)5536654Snp146283 gen_unknown_gov_err(DBusConnection *con,
5546654Snp146283     DBusMessage *msg,
5556654Snp146283     char *err_str)
5566654Snp146283 {
5576654Snp146283 
5586654Snp146283 	generate_err_msg (con,
5596654Snp146283 	    msg,
5606654Snp146283 	    "org.freedesktop.Hal.CPUFreq.UnknownGovernor",
5616654Snp146283 	    "Unknown CPUFreq Governor: %s",
5626654Snp146283 	    err_str);
5636654Snp146283 }
5646654Snp146283 
5656654Snp146283 static void
gen_no_suitable_gov_err(DBusConnection * con,DBusMessage * msg,char * err_str)5666654Snp146283 gen_no_suitable_gov_err(DBusConnection *con,
5676654Snp146283     DBusMessage *msg,
5686654Snp146283     char *err_str)
5696654Snp146283 {
5706654Snp146283 
5716654Snp146283 	generate_err_msg (con,
5726654Snp146283 	    msg,
5736654Snp146283 	    "org.freedesktop.Hal.CPUFreq.NoSuitableGovernor",
5746654Snp146283 	    "Could not find a suitable governor: %s",
5756654Snp146283 	    err_str);
5766654Snp146283 }
5776654Snp146283 
5786654Snp146283 static void
gen_cpufreq_err(DBusConnection * con,DBusMessage * msg,char * err_str)5796654Snp146283 gen_cpufreq_err(DBusConnection *con,
5806654Snp146283     DBusMessage *msg,
5816654Snp146283     char *err_str)
5826654Snp146283 {
5836654Snp146283 	generate_err_msg (con,
5846654Snp146283 	    msg,
5856654Snp146283 	    "org.freedesktop.Hal.CPUFreq.Error",
5866654Snp146283 	    "%s: Syslog might give more information",
5876654Snp146283 	    err_str);
5886654Snp146283 }
5896654Snp146283 
5906654Snp146283 
5916654Snp146283 /*
5926654Snp146283  * Puts the required cpufreq audit data and calls adt_put_event()
5936654Snp146283  * to generate auditing
5946654Snp146283  */
5956654Snp146283 static void
audit_cpufreq(const adt_export_data_t * imported_state,au_event_t event_id,int result,const char * auth_used,const int cpu_thr_value)5966654Snp146283 audit_cpufreq(const adt_export_data_t *imported_state, au_event_t event_id,
5976654Snp146283     int result, const char *auth_used, const int cpu_thr_value)
5986654Snp146283 {
5996654Snp146283 	adt_session_data_t	*ah;
6006654Snp146283 	adt_event_data_t	*event;
6016654Snp146283 	struct passwd		*msg_pwd;
6026654Snp146283 	uid_t			gid;
6036654Snp146283 
6046654Snp146283 	if (adt_start_session (&ah, imported_state, 0) != 0) {
6056654Snp146283 		HAL_INFO (("adt_start_session failed: %s", strerror (errno)));
6066654Snp146283 		return;
6076654Snp146283 	}
6086654Snp146283 
6096654Snp146283 	if ((event = adt_alloc_event (ah, event_id)) == NULL) {
6106654Snp146283 		HAL_INFO(("adt_alloc_event audit_cpufreq failed: %s",
6116654Snp146283 		    strerror (errno)));
6126654Snp146283 		return;
6136654Snp146283 	}
6146654Snp146283 
6156654Snp146283 	switch (event_id) {
6166654Snp146283 	case ADT_cpu_ondemand:
6176654Snp146283 		event->adt_cpu_ondemand.auth_used = (char *)auth_used;
6186654Snp146283 		break;
6196654Snp146283 	case ADT_cpu_performance:
6206654Snp146283 		event->adt_cpu_performance.auth_used = (char *)auth_used;
6216654Snp146283 		break;
6226654Snp146283 	case ADT_cpu_threshold:
6236654Snp146283 		event->adt_cpu_threshold.auth_used = (char *)auth_used;
6246654Snp146283 		event->adt_cpu_threshold.threshold = cpu_thr_value;
6256654Snp146283 		break;
6266654Snp146283 	default:
6276654Snp146283 		goto clean;
6286654Snp146283 	}
6296654Snp146283 
6306654Snp146283 	if (result == 0) {
6316654Snp146283 		if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
6326654Snp146283 			HAL_INFO (("adt_put_event(%d, ADT_SUCCESS) failed",
6336654Snp146283 			    event_id));
6346654Snp146283 		}
6356654Snp146283 	} else {
6366654Snp146283 		if (adt_put_event (event, ADT_FAILURE, result) != 0) {
6376654Snp146283 			HAL_INFO (("adt_put_event(%d, ADT_FAILURE) failed",
6386654Snp146283 			    event_id));
6396654Snp146283 		}
6406654Snp146283 	}
6416654Snp146283 
6426654Snp146283 clean:
6436654Snp146283 	adt_free_event (event);
6446654Snp146283 	(void) adt_end_session (ah);
6456654Snp146283 }
6466654Snp146283 
6476654Snp146283 /*
6486654Snp146283  * Check if the cpufreq related operations are authorized
6496654Snp146283  */
6506654Snp146283 
6516654Snp146283 static int
check_authorization(DBusConnection * con,DBusMessage * msg)6526654Snp146283 check_authorization(DBusConnection *con, DBusMessage *msg)
6536654Snp146283 {
6546654Snp146283 	int		adt_res = 0;
6556654Snp146283 #ifdef HAVE_POLKIT
6566654Snp146283 	char		user_id[128];
6576654Snp146283 	char		*udi;
6586654Snp146283 	char		*privilege;
6596654Snp146283 	DBusError	error;
6606654Snp146283 	gboolean	is_priv_allowed;
6616654Snp146283 	gboolean	is_priv_temporary;
6626654Snp146283 	DBusConnection	*system_bus = NULL;
6636654Snp146283 	LibPolKitContext *pol_ctx = NULL;
6646654Snp146283 
6656654Snp146283 	/*
6666654Snp146283 	 * Check for authorization before proceeding
6676654Snp146283 	 */
6686654Snp146283 	udi = getenv ("HAL_PROP_INFO_UDI");
6696654Snp146283 	privilege = "hal-power-cpu";
6706654Snp146283 
6716654Snp146283 	dbus_error_init (&error);
6726654Snp146283 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
6736654Snp146283 	if (system_bus == NULL) {
6746654Snp146283 		HAL_INFO (("Cannot connect to the system bus"));
6756654Snp146283 		LIBHAL_FREE_DBUS_ERROR (&error);
6766654Snp146283 		gen_cpufreq_err (con, msg, "Cannot connect to the system bus");
6776654Snp146283 		adt_res = EINVAL;
6786654Snp146283 		goto out;
6796654Snp146283 	}
6806654Snp146283 
6816654Snp146283 	sender = dbus_message_get_sender (msg);
6826654Snp146283 	HAL_INFO (("Auth Sender: %s", sender));
6836654Snp146283 
6846654Snp146283 	if (sender == NULL) {
6856654Snp146283 		HAL_INFO (("Could not get the sender of the message"));
6866654Snp146283 		gen_cpufreq_err (con, msg,
6876654Snp146283 		    "Could not get the sender of the message");
6886654Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
6896654Snp146283 		goto out;
6906654Snp146283 	}
6916654Snp146283 
6926654Snp146283 	dbus_error_init (&error);
6936654Snp146283 	uid = dbus_bus_get_unix_user (system_bus, sender, &error);
6946654Snp146283 	if (dbus_error_is_set (&error)) {
6956654Snp146283 		HAL_INFO (("Could not get the user id of the message"));
6966654Snp146283 		LIBHAL_FREE_DBUS_ERROR (&error);
6976654Snp146283 		gen_cpufreq_err (con, msg,
6986654Snp146283 		    "Could not get the user id of the message sender");
6996654Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
7006654Snp146283 		goto out;
7016654Snp146283 	}
7026654Snp146283 
7036654Snp146283 	snprintf (user_id, sizeof (user_id), "%d", uid);
7046654Snp146283 	HAL_DEBUG ((" User id is : %d", uid));
7056654Snp146283 
7066654Snp146283 	pol_ctx = libpolkit_new_context (system_bus);
7076654Snp146283 	if (pol_ctx == NULL) {
7086654Snp146283 		HAL_INFO (("Cannot get libpolkit context"));
7096654Snp146283 		gen_cpufreq_err (con, msg,
7106654Snp146283 		    "Cannot get libpolkit context to check privileges");
7116654Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
7126654Snp146283 		goto out;
7136654Snp146283 	}
7146654Snp146283 
7156654Snp146283 	if (libpolkit_is_uid_allowed_for_privilege (pol_ctx,
7166654Snp146283 	    NULL,
7176654Snp146283 	    user_id,
7186654Snp146283 	    privilege,
7196654Snp146283 	    udi,
7206654Snp146283 	    &is_priv_allowed,
7216654Snp146283 	    &is_priv_temporary,
7226654Snp146283 	    NULL) != LIBPOLKIT_RESULT_OK) {
7236654Snp146283 		HAL_INFO (("Cannot lookup privilege from PolicyKit"));
7246654Snp146283 		gen_cpufreq_err (con, msg,
7256654Snp146283 		    "Error looking up privileges from Policykit");
7266654Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
7276654Snp146283 		goto out;
7286654Snp146283 	}
7296654Snp146283 
7306654Snp146283 	if (!is_priv_allowed) {
7316654Snp146283 		HAL_INFO (("Caller doesn't possess required privilege to"
7326654Snp146283 		    " change the governor"));
7336654Snp146283 		gen_cpufreq_err (con, msg,
7346654Snp146283 		    "Caller doesn't possess required "
7356654Snp146283 		    "privilege to change the governor");
7366654Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
7376654Snp146283 		goto out;
7386654Snp146283 	}
7396654Snp146283 
7406654Snp146283 	HAL_DEBUG ((" Privilege Succeed"));
7416654Snp146283 
7426654Snp146283 #endif
7436654Snp146283 out:
7446654Snp146283 	return (adt_res);
7456654Snp146283 }
7466654Snp146283 
7476654Snp146283 /*
7486654Snp146283  * Sets the CPU Freq governor. It sets the gov name in the /etc/power.conf
7496654Snp146283  * and executes pmconfig. If governor is "ondemand" then "cpupm" is enabled in
7506654Snp146283  * and if governor is performance, then "cpupm" is disabled
7516654Snp146283  */
7526654Snp146283 static void
set_cpufreq_gov(DBusConnection * con,DBusMessage * msg,void * udata)7536654Snp146283 set_cpufreq_gov(DBusConnection *con, DBusMessage *msg, void *udata)
7546654Snp146283 {
7556654Snp146283 	DBusMessageIter arg_iter;
7566654Snp146283 	DBusMessage	*msg_reply;
7576654Snp146283 	char		*arg_val;
7586654Snp146283 	int		arg_type;
7596654Snp146283 	int		pid;
7606654Snp146283 	int		done_flag = 0;
7616654Snp146283 	int		sleep_time = 0;
7626654Snp146283 	int		status;
7636654Snp146283 	int		adt_res = 0;
7646654Snp146283 	char		tmp_conf_file[64] = "/tmp/power.conf.XXXXXX";
7656654Snp146283 	int		tmp_fd;
7666654Snp146283 	char		pmconfig_cmd[128];
7676654Snp146283 	pconf_edit_type pc_edit_type;
7686654Snp146283 #ifdef sun
7696654Snp146283 	adt_export_data_t *adt_data;
7706654Snp146283 	size_t 		adt_data_size;
7716654Snp146283 	DBusConnection 	*system_bus = NULL;
7726654Snp146283 	DBusError 	error;
7736654Snp146283 #endif
7746654Snp146283 
7756654Snp146283 	if (! dbus_message_iter_init (msg, &arg_iter)) {
7766654Snp146283 		HAL_DEBUG (("Incoming message has no arguments"));
7776654Snp146283 		gen_unknown_gov_err (con, msg, "No governor specified");
7786654Snp146283 		adt_res = EINVAL;
7796654Snp146283 		goto out;
7806654Snp146283 	}
7816654Snp146283 	arg_type = dbus_message_iter_get_arg_type (&arg_iter);
7826654Snp146283 
7836654Snp146283 	if (arg_type != DBUS_TYPE_STRING) {
7846654Snp146283 		HAL_DEBUG (("Incomming message arg type is not string"));
7856654Snp146283 		gen_unknown_gov_err (con, msg,
7866654Snp146283 		    "Specified governor is not a string");
7876654Snp146283 		adt_res = EINVAL;
7886654Snp146283 		goto out;
7896654Snp146283 	}
7906654Snp146283 	dbus_message_iter_get_basic (&arg_iter, &arg_val);
7916654Snp146283 	if (arg_val != NULL) {
7926654Snp146283 		HAL_DEBUG (("SetCPUFreqGov is: %s", arg_val));
7936654Snp146283 	} else {
7946654Snp146283 		HAL_DEBUG (("Could not get SetCPUFreqGov from message iter"));
7956654Snp146283 		adt_res = EINVAL;
7966654Snp146283 		goto out;
7976654Snp146283 	}
7986654Snp146283 
7996654Snp146283 	adt_res = check_authorization (con, msg);
8006654Snp146283 
8016654Snp146283 	if (adt_res != 0) {
8026654Snp146283 		goto out;
8036654Snp146283 	}
8046654Snp146283 
8056654Snp146283 	/*
8066654Snp146283 	 * Update the /etc/power.conf file.
8076654Snp146283 	 */
8086654Snp146283 	tmp_fd = mkstemp (tmp_conf_file);
8096654Snp146283 	if (tmp_fd == -1) {
8106654Snp146283 		HAL_ERROR ((" Error in creating a temp conf file"));
8116654Snp146283 		adt_res = EINVAL;
8126654Snp146283 		goto out;
8136654Snp146283 	}
8146654Snp146283 	strcpy (pc_edit_type.cpu_gov, arg_val);
8156654Snp146283 	adt_res = edit_power_conf_file (pc_edit_type, CPU_GOV, tmp_conf_file);
8166654Snp146283 	if (adt_res != 0) {
8176654Snp146283 		HAL_DEBUG (("Error in edit /etc/power.conf"));
8186654Snp146283 		gen_cpufreq_err (con, msg,
8196654Snp146283 		    "Internal Error while setting the governor");
8206654Snp146283 		unlink (tmp_conf_file);
8216654Snp146283 		goto out;
8226654Snp146283 	}
8236654Snp146283 
8246654Snp146283 	/*
8256654Snp146283 	 * Execute pmconfig
8266654Snp146283 	 */
8276654Snp146283 	sprintf (pmconfig_cmd, "%s %s", PMCONFIG, tmp_conf_file);
8286654Snp146283 	if (system (pmconfig_cmd) != 0) {
8296654Snp146283 		HAL_ERROR ((" Error in executing pmconfig: %s",
8306654Snp146283 		    strerror (errno)));
8316654Snp146283 		adt_res = errno;
8326654Snp146283 		gen_cpufreq_err (con, msg, "Error in executing pmconfig");
8336654Snp146283 		unlink (tmp_conf_file);
8346654Snp146283 		goto out;
8356654Snp146283 	}
8366654Snp146283 	unlink (tmp_conf_file);
8376654Snp146283 	HAL_DEBUG (("Executed pmconfig"));
8386654Snp146283 	sprintf (current_gov, "%s", arg_val);
8396654Snp146283 
8406654Snp146283 	/*
8416654Snp146283 	 * Just return an empty response, so that if the client
8426654Snp146283 	 * is waiting for any response will not keep waiting
8436654Snp146283 	 */
8446654Snp146283 	msg_reply = dbus_message_new_method_return (msg);
8456654Snp146283 	if (msg_reply == NULL) {
8466654Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
8476654Snp146283 		gen_cpufreq_err (con, msg,
8486654Snp146283 		    "Out of memory to create a response");
8496654Snp146283 		adt_res = ENOMEM;
8506654Snp146283 		goto out;
8516654Snp146283 	}
8526654Snp146283 
8536654Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
8546654Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
8556654Snp146283 		gen_cpufreq_err (con, msg,
8566654Snp146283 		    "Out of memory to create a response");
8576654Snp146283 		adt_res = ENOMEM;
8586654Snp146283 		goto out;
8596654Snp146283 	}
8606654Snp146283 
8616654Snp146283 	dbus_connection_flush (con);
8626654Snp146283 
8636654Snp146283 out:
8646654Snp146283 
8656654Snp146283 #ifdef sun
8666654Snp146283 	/*
8676654Snp146283 	 * Audit the new governor change
8686654Snp146283 	 */
8696654Snp146283 	dbus_error_init (&error);
8706654Snp146283 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
8716654Snp146283 	if (system_bus == NULL) {
8726654Snp146283 		HAL_INFO (("Cannot connect to the system bus %s",
8736654Snp146283 		    error.message));
8746654Snp146283 		LIBHAL_FREE_DBUS_ERROR (&error);
8756654Snp146283 		return;
8766654Snp146283 	}
8776654Snp146283 
8786654Snp146283 	adt_data = get_audit_export_data (system_bus, sender, &adt_data_size);
8796654Snp146283 	if (adt_data != NULL) {
8806654Snp146283 		if (strcmp (arg_val, "ondemand") == 0) {
8816654Snp146283 			audit_cpufreq (adt_data, ADT_cpu_ondemand, adt_res,
8826654Snp146283 			    "solaris.system.power.cpu", 0);
8836654Snp146283 		} else if (strcmp (arg_val, "performance") == 0) {
8846654Snp146283 			audit_cpufreq (adt_data, ADT_cpu_performance, adt_res,
8856654Snp146283 			    "solaris.system.power.cpu", 0);
8866654Snp146283 		}
8876654Snp146283 		free (adt_data);
8886654Snp146283 	} else {
8896654Snp146283 		HAL_INFO ((" Could not get audit export data"));
8906654Snp146283 	}
8916654Snp146283 #endif /* sun */
8926654Snp146283 }
8936654Snp146283 
8946654Snp146283 /*
8956654Snp146283  * Sets the CPU Freq performance. It sets the cpu-threshold in the
8966654Snp146283  * /etc/power.conf and executes pmconfig. The performnace value should
8976654Snp146283  * be between 1 to 100. The cpu-threshold = ((performance val) * 15) secs.
8986654Snp146283  */
8996654Snp146283 static void
set_cpufreq_performance(DBusConnection * con,DBusMessage * msg,void * udata)9006654Snp146283 set_cpufreq_performance(DBusConnection *con, DBusMessage *msg, void *udata)
9016654Snp146283 {
9026654Snp146283 
9036654Snp146283 	DBusMessageIter arg_iter;
9046654Snp146283 	DBusMessage	*msg_reply;
9056654Snp146283 	int		arg_val;
9066654Snp146283 	int		arg_type;
9076654Snp146283 	int		pid;
9086654Snp146283 	int		done_flag = 0;
9096654Snp146283 	int		sleep_time = 0;
9106654Snp146283 	int		adt_res = 0;
9116654Snp146283 	char		tmp_conf_file[64] = "/tmp/power.conf.XXXXXX";
9126654Snp146283 	int		tmp_fd;
9136654Snp146283 	char		pmconfig_cmd[128];
9146654Snp146283 	pconf_edit_type pc_edit_type;
9156654Snp146283 #ifdef sun
9166654Snp146283 	adt_export_data_t *adt_data;
9176654Snp146283 	size_t 		adt_data_size;
9186654Snp146283 	DBusConnection 	*system_bus = NULL;
9196654Snp146283 	DBusError 	error;
9206654Snp146283 #endif
9216654Snp146283 
9226654Snp146283 	adt_res = check_authorization (con, msg);
9236654Snp146283 
9246654Snp146283 	if (adt_res != 0) {
9256654Snp146283 		goto out;
9266654Snp146283 	}
9276654Snp146283 
9286654Snp146283 	/*
9296654Snp146283 	 * Performance can only be set to dynamic governors. Currently the
9306654Snp146283 	 * only supported dynamic governor is ondemand.
9316654Snp146283 	 */
9326654Snp146283 	if (current_gov[0] == 0) {
9336654Snp146283 		/*
9346654Snp146283 		 * Read the current governor from /etc/power.conf
9356654Snp146283 		 */
9366654Snp146283 		if (read_power_conf_file (&pc_edit_type, CPU_GOV) != 1) {
9376654Snp146283 			HAL_ERROR ((" Error in reading from /etc/power.conf"));
9386654Snp146283 			gen_cpufreq_err (con, msg, "Internal error while "
9396654Snp146283 			    "getting the governor");
9406654Snp146283 			adt_res = EINVAL;
9416654Snp146283 			goto out;
9426654Snp146283 		}
9436654Snp146283 		sprintf (current_gov, "%s", pc_edit_type.cpu_gov);
9446654Snp146283 	}
9456654Snp146283 
9466654Snp146283 	if (strcmp (current_gov, "ondemand") != 0) {
9476654Snp146283 		HAL_DEBUG (("To set performance the current gov should be "
9486654Snp146283 		    "dynamic like ondemand"));
9496654Snp146283 		gen_no_suitable_gov_err (con, msg, "Cannot set performance "
9506654Snp146283 		    "to the current governor");
9516654Snp146283 		adt_res = EINVAL;
9526654Snp146283 		goto out;
9536654Snp146283 	}
9546654Snp146283 
9556654Snp146283 	if (! dbus_message_iter_init (msg, &arg_iter)) {
9566654Snp146283 		HAL_DEBUG (("Incoming message has no arguments"));
9576654Snp146283 		gen_no_suitable_gov_err(con, msg, "No performance specified");
9586654Snp146283 		adt_res = EINVAL;
9596654Snp146283 		goto out;
9606654Snp146283 	}
9616654Snp146283 	arg_type = dbus_message_iter_get_arg_type (&arg_iter);
9626654Snp146283 
9636654Snp146283 	if (arg_type != DBUS_TYPE_INT32) {
9646654Snp146283 		HAL_DEBUG (("Incomming message arg type is not Integer"));
9656654Snp146283 		gen_no_suitable_gov_err (con, msg,
9666654Snp146283 		    "Specified performance is not a Integer");
9676654Snp146283 		adt_res = EINVAL;
9686654Snp146283 		goto out;
9696654Snp146283 	}
9706654Snp146283 	dbus_message_iter_get_basic (&arg_iter, &arg_val);
9716654Snp146283 	if ((arg_val < 1) || (arg_val > 100)) {
9726654Snp146283 		HAL_INFO (("SetCPUFreqPerformance should be between 1 to 100"
9736654Snp146283 		    ": %d", arg_val));
9746654Snp146283 		gen_no_suitable_gov_err (con, msg,
9756654Snp146283 		    "Performance value should be between 1 and 100");
9766654Snp146283 		adt_res = EINVAL;
9776654Snp146283 		goto out;
9786654Snp146283 	}
9796654Snp146283 
9806654Snp146283 	HAL_DEBUG (("SetCPUFreqPerformance is: %d", arg_val));
9816654Snp146283 
9826654Snp146283 	/*
9836654Snp146283 	 * Update the /etc/power.conf file
9846654Snp146283 	 */
9856654Snp146283 	tmp_fd = mkstemp (tmp_conf_file);
9866654Snp146283 	if (tmp_fd == -1) {
9876654Snp146283 		HAL_ERROR ((" Error in creating a temp conf file"));
9886654Snp146283 		adt_res = EINVAL;
9896654Snp146283 		goto out;
9906654Snp146283 	}
9916654Snp146283 	pc_edit_type.cpu_th = arg_val * 15;
9926654Snp146283 	adt_res = edit_power_conf_file (pc_edit_type, CPU_PERFORMANCE,
9936654Snp146283 	    tmp_conf_file);
9946654Snp146283 	if (adt_res != 0) {
9956654Snp146283 		HAL_DEBUG (("Error while editing /etc/power.conf"));
9966654Snp146283 		gen_cpufreq_err (con, msg,
9976654Snp146283 		    "Internal error while setting the performance");
9986654Snp146283 		unlink (tmp_conf_file);
9996654Snp146283 		goto out;
10006654Snp146283 	}
10016654Snp146283 
10026654Snp146283 	/*
10036654Snp146283 	 * Execute pmconfig
10046654Snp146283 	 */
10056654Snp146283 	sprintf (pmconfig_cmd, "%s %s", PMCONFIG, tmp_conf_file);
10066654Snp146283 	if (system (pmconfig_cmd) != 0) {
10076654Snp146283 		HAL_ERROR ((" Error in executing pmconfig: %s",
10086654Snp146283 		    strerror (errno)));
10096654Snp146283 		adt_res = errno;
10106654Snp146283 		gen_cpufreq_err (con, msg,
10116654Snp146283 		    "Internal error while setting the performance");
10126654Snp146283 		unlink (tmp_conf_file);
10136654Snp146283 		goto out;
10146654Snp146283 	}
10156654Snp146283 	unlink (tmp_conf_file);
10166654Snp146283 	HAL_DEBUG (("Executed pmconfig"));
10176654Snp146283 
10186654Snp146283 	/*
10196654Snp146283 	 * Just return an empty response, so that if the client
10206654Snp146283 	 * is waiting for any response will not keep waiting
10216654Snp146283 	 */
10226654Snp146283 
10236654Snp146283 	msg_reply = dbus_message_new_method_return (msg);
10246654Snp146283 	if (msg_reply == NULL) {
10256654Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
10266654Snp146283 		gen_cpufreq_err (con, msg,
10276654Snp146283 		    "Out of memory to create a response");
10286654Snp146283 		adt_res = ENOMEM;
10296654Snp146283 		goto out;
10306654Snp146283 	}
10316654Snp146283 
10326654Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
10336654Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
10346654Snp146283 		gen_cpufreq_err (con, msg,
10356654Snp146283 		    "Out of memory to create a response");
10366654Snp146283 		adt_res = ENOMEM;
10376654Snp146283 		goto out;
10386654Snp146283 	}
10396654Snp146283 
10406654Snp146283 	dbus_connection_flush (con);
10416654Snp146283 out:
10426654Snp146283 #ifdef sun
10436654Snp146283 
10446654Snp146283 	/*
10456654Snp146283 	 * Audit the new performance change
10466654Snp146283 	 */
10476654Snp146283 	dbus_error_init (&error);
10486654Snp146283 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
10496654Snp146283 	if (system_bus == NULL) {
10506654Snp146283 		HAL_INFO (("Cannot connect to the system bus %s",
10516654Snp146283 		    error.message));
10526654Snp146283 		LIBHAL_FREE_DBUS_ERROR (&error);
10536654Snp146283 		return;
10546654Snp146283 	}
10556654Snp146283 
10566654Snp146283 	adt_data = get_audit_export_data (system_bus, sender, &adt_data_size);
10576654Snp146283 	if (adt_data != NULL) {
10586654Snp146283 		audit_cpufreq (adt_data, ADT_cpu_threshold, adt_res,
10596654Snp146283 		    "solaris.system.power.cpu", arg_val);
10606654Snp146283 		free (adt_data);
10616654Snp146283 	} else {
10626654Snp146283 		HAL_INFO ((" Could not get audit export data"));
10636654Snp146283 	}
10646654Snp146283 
10656654Snp146283 #endif /* sun */
10666654Snp146283 }
10676654Snp146283 
10686654Snp146283 /*
10696654Snp146283  * Returns in the dbus message the current gov.
10706654Snp146283  */
10716654Snp146283 static void
get_cpufreq_gov(DBusConnection * con,DBusMessage * msg,void * udata)10726654Snp146283 get_cpufreq_gov(DBusConnection *con, DBusMessage *msg, void *udata)
10736654Snp146283 {
10746654Snp146283 
10756654Snp146283 	DBusMessageIter rep_iter;
10766654Snp146283 	DBusMessage	*msg_reply;
10776654Snp146283 	int 		res;
10786654Snp146283 	pconf_edit_type pc_type;
10796654Snp146283 	char		*param;
10806654Snp146283 
10816654Snp146283 	/*
10826654Snp146283 	 * Get the governor type from /etc/power.conf if it is present.
10836654Snp146283 	 */
10846654Snp146283 	res = get_cur_val (&pc_type, CPU_GOV);
10856654Snp146283 	if (res != 1) {
10866654Snp146283 		HAL_INFO ((" Error in getting the current governor"));
10876654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
10886654Snp146283 		    " the governor");
10896654Snp146283 		return;
10906654Snp146283 	}
10916654Snp146283 
10926654Snp146283 	HAL_DEBUG ((" Current governor is: %s", pc_type.cpu_gov));
10936654Snp146283 
10946654Snp146283 	msg_reply = dbus_message_new_method_return (msg);
10956654Snp146283 	if (msg_reply == NULL) {
10966654Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
10976654Snp146283 		gen_cpufreq_err (con, msg,
10986654Snp146283 		    "Internal error while getting the governor");
10996654Snp146283 		return;
11006654Snp146283 	}
11016654Snp146283 
11026654Snp146283 	/*
11036654Snp146283 	 * Append reply arguments
11046654Snp146283 	 */
11056654Snp146283 	param = (char *) malloc (sizeof (char) * 250);
11066654Snp146283 	if (param == NULL) {
11076654Snp146283 		HAL_ERROR (("\n Could not allocate mem to param"));
11086654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
11096654Snp146283 		    " the governor");
11106654Snp146283 		return;
11116654Snp146283 	}
11126654Snp146283 	sprintf (param, "%s",  pc_type.cpu_gov);
11136654Snp146283 
11146654Snp146283 	dbus_message_iter_init_append (msg_reply, &rep_iter);
11156654Snp146283 	if (!dbus_message_iter_append_basic (&rep_iter, DBUS_TYPE_STRING,
11166654Snp146283 	    &param)) {
11176654Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
11186654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
11196654Snp146283 		    " the governor");
11206654Snp146283 		free (param);
11216654Snp146283 		return;
11226654Snp146283 	}
11236654Snp146283 
11246654Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
11256654Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
11266654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
11276654Snp146283 		    " the governor");
11286654Snp146283 		free (param);
11296654Snp146283 		return;
11306654Snp146283 	}
11316654Snp146283 	dbus_connection_flush (con);
11326654Snp146283 	free (param);
11336654Snp146283 }
11346654Snp146283 
11356654Snp146283 /*
11366654Snp146283  * Returns in the dbus message the current performance value
11376654Snp146283  */
11386654Snp146283 static void
get_cpufreq_performance(DBusConnection * con,DBusMessage * msg,void * udata)11396654Snp146283 get_cpufreq_performance(DBusConnection *con, DBusMessage *msg, void *udata)
11406654Snp146283 {
11416654Snp146283 
11426654Snp146283 	DBusMessageIter rep_iter;
11436654Snp146283 	DBusMessage	*msg_reply;
11446654Snp146283 	int 		res;
11456654Snp146283 	pconf_edit_type pc_type;
11466654Snp146283 	int		param_int;
11476654Snp146283 
11486654Snp146283 	/*
11496654Snp146283 	 * Get the performance value
11506654Snp146283 	 */
11516654Snp146283 	res = get_cur_val (&pc_type, CPU_PERFORMANCE);
11526654Snp146283 	if (res != 1) {
11536654Snp146283 		HAL_INFO ((" Error in getting current performance"));
11546654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
11556654Snp146283 		    " the performance value");
11566654Snp146283 		return;
11576654Snp146283 	}
11586654Snp146283 
11596654Snp146283 	HAL_DEBUG ((" The current performance: %d", pc_type.cpu_th));
11606654Snp146283 
11616654Snp146283 	msg_reply = dbus_message_new_method_return (msg);
11626654Snp146283 	if (msg_reply == NULL) {
11636654Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
11646654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
11656654Snp146283 		    " the performance value");
11666654Snp146283 		return;
11676654Snp146283 	}
11686654Snp146283 
11696654Snp146283 	/*
11706654Snp146283 	 * Append reply arguments.pc_type.cpu_th gives the current cputhreshold
11716654Snp146283 	 * vlaue in seconds. Have to convert it into CPU HAL interface
11726654Snp146283 	 * performance value
11736654Snp146283 	 */
11746654Snp146283 	if (pc_type.cpu_th < 15)
11756654Snp146283 		param_int = 1;
11766654Snp146283 	else
11776654Snp146283 		param_int = (pc_type.cpu_th / 15);
11786654Snp146283 
11796654Snp146283 	HAL_DEBUG (("Performance: %d \n", param_int));
11806654Snp146283 
11816654Snp146283 	dbus_message_iter_init_append (msg_reply, &rep_iter);
11826654Snp146283 	if (!dbus_message_iter_append_basic (&rep_iter, DBUS_TYPE_INT32,
11836654Snp146283 	    &param_int)) {
11846654Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
11856654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
11866654Snp146283 		    " the performance value");
11876654Snp146283 		return;
11886654Snp146283 	}
11896654Snp146283 
11906654Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
11916654Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
11926654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
11936654Snp146283 		    " the performance value");
11946654Snp146283 		return;
11956654Snp146283 	}
11966654Snp146283 	dbus_connection_flush (con);
11976654Snp146283 }
11986654Snp146283 
11996654Snp146283 /*
12006654Snp146283  * Returns list of available governors. Currently just two governors are
12016654Snp146283  * supported. They are "ondemand" and "performance"
12026654Snp146283  */
12036654Snp146283 
12046654Snp146283 static void
get_cpufreq_avail_gov(DBusConnection * con,DBusMessage * msg,void * udata)12056654Snp146283 get_cpufreq_avail_gov(DBusConnection *con, DBusMessage *msg, void *udata)
12066654Snp146283 {
12076654Snp146283 
12086654Snp146283 	DBusMessageIter rep_iter;
12096654Snp146283 	DBusMessageIter array_iter;
12106654Snp146283 	DBusMessage	*msg_reply;
12116654Snp146283 	int		ngov;
12126654Snp146283 
12136654Snp146283 	msg_reply = dbus_message_new_method_return (msg);
12146654Snp146283 	if (msg_reply == NULL) {
12156654Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
12166654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
12176654Snp146283 		    " the list of governors");
12186654Snp146283 		return;
12196654Snp146283 	}
12206654Snp146283 
12216654Snp146283 	/*
12226654Snp146283 	 * Append reply arguments
12236654Snp146283 	 */
12246654Snp146283 	dbus_message_iter_init_append (msg_reply, &rep_iter);
12256654Snp146283 
12266654Snp146283 	if (!dbus_message_iter_open_container (&rep_iter,
12276654Snp146283 	    DBUS_TYPE_ARRAY,
12286654Snp146283 	    DBUS_TYPE_STRING_AS_STRING,
12296654Snp146283 	    &array_iter)) {
12306654Snp146283 		HAL_ERROR (("\n Out of memory to msg reply array"));
12316654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
12326654Snp146283 		    " the list of governors");
12336654Snp146283 		return;
12346654Snp146283 	}
12356654Snp146283 
12366654Snp146283 	for (ngov = 0; gov_list[ngov] != NULL; ngov++) {
12376654Snp146283 		if (gov_list[ngov])
12386654Snp146283 			HAL_DEBUG (("\n%d Gov Name: %s", ngov, gov_list[ngov]));
12396654Snp146283 			dbus_message_iter_append_basic (&array_iter,
12406654Snp146283 			    DBUS_TYPE_STRING,
12416654Snp146283 			    &gov_list[ngov]);
12426654Snp146283 	}
12436654Snp146283 	dbus_message_iter_close_container (&rep_iter, &array_iter);
12446654Snp146283 
12456654Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
12466654Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
12476654Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
12486654Snp146283 		    " the list of governors");
12496654Snp146283 		return;
12506654Snp146283 	}
12516654Snp146283 	dbus_connection_flush (con);
12526654Snp146283 }
12536654Snp146283 
12546654Snp146283 static DBusHandlerResult
hald_dbus_cpufreq_filter(DBusConnection * con,DBusMessage * msg,void * udata)12556654Snp146283 hald_dbus_cpufreq_filter(DBusConnection *con, DBusMessage *msg, void *udata)
12566654Snp146283 {
12576654Snp146283 	HAL_DEBUG ((" Inside CPUFreq filter:%s", dbus_message_get_path(msg)));
12586654Snp146283 	/*
12596654Snp146283 	 * Check for method types
12606654Snp146283 	 */
12616654Snp146283 	if (!dbus_connection_get_is_connected (con))
12626654Snp146283 		HAL_DEBUG (("Connection disconnected in cpufreq addon"));
12636654Snp146283 
12646654Snp146283 	if (dbus_message_is_method_call (msg,
12656654Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
12666654Snp146283 	    "SetCPUFreqGovernor")) {
12676654Snp146283 		HAL_DEBUG (("---- SetCPUFreqGovernor is called "));
12686654Snp146283 
12696654Snp146283 		set_cpufreq_gov (con, msg, udata);
12706654Snp146283 
12716654Snp146283 	} else if (dbus_message_is_method_call (msg,
12726654Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
12736654Snp146283 	    "GetCPUFreqGovernor")) {
12746654Snp146283 		HAL_DEBUG (("---- GetCPUFreqGovernor is called "));
12756654Snp146283 
12766654Snp146283 		get_cpufreq_gov (con, msg, udata);
12776654Snp146283 	} else if (dbus_message_is_method_call (msg,
12786654Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
12796654Snp146283 	    "GetCPUFreqAvailableGovernors")) {
12806654Snp146283 		HAL_DEBUG (("---- GetCPUFreqAvailableGovernors is called "));
12816654Snp146283 
12826654Snp146283 		get_cpufreq_avail_gov (con, msg, udata);
12836654Snp146283 	} else if (dbus_message_is_method_call (msg,
12846654Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
12856654Snp146283 	    "SetCPUFreqPerformance")) {
12866654Snp146283 		HAL_DEBUG (("---- SetCPUFreqPerformance is called "));
12876654Snp146283 
12886654Snp146283 		set_cpufreq_performance (con, msg, udata);
12896654Snp146283 	} else if (dbus_message_is_method_call (msg,
12906654Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
12916654Snp146283 	    "GetCPUFreqPerformance")) {
12926654Snp146283 		HAL_DEBUG (("---- GetCPUFreqPerformance is called "));
12936654Snp146283 
12946654Snp146283 		get_cpufreq_performance (con, msg, udata);
12956654Snp146283 	} else {
12966654Snp146283 		HAL_DEBUG (("---Not Set/Get cpufreq gov---"));
12976654Snp146283 	}
12986654Snp146283 
12996654Snp146283 	return (DBUS_HANDLER_RESULT_HANDLED);
13006654Snp146283 
13016654Snp146283 }
13026654Snp146283 
13036654Snp146283 static void
drop_privileges()13046654Snp146283 drop_privileges()
13056654Snp146283 {
13066654Snp146283 	priv_set_t *pPrivSet = NULL;
13076654Snp146283 	priv_set_t *lPrivSet = NULL;
13086654Snp146283 
13096654Snp146283 	/*
13106654Snp146283 	 * Start with the 'basic' privilege set and then add any
13116654Snp146283 	 * of the privileges that will be required.
13126654Snp146283 	 */
13136654Snp146283 	if ((pPrivSet = priv_str_to_set ("basic", ",", NULL)) == NULL) {
13146654Snp146283 		HAL_INFO (("Error in setting the priv"));
13156654Snp146283 		return;
13166654Snp146283 	}
13176654Snp146283 
13186654Snp146283 	(void) priv_addset (pPrivSet, PRIV_SYS_DEVICES);
13196654Snp146283 
13206654Snp146283 	if (setppriv (PRIV_SET, PRIV_INHERITABLE, pPrivSet) != 0) {
13216654Snp146283 		HAL_INFO (("Could not set the privileges"));
13226654Snp146283 		priv_freeset (pPrivSet);
13236654Snp146283 		return;
13246654Snp146283 	}
13256654Snp146283 
13266654Snp146283 	(void) priv_addset (pPrivSet, PRIV_PROC_AUDIT);
13276654Snp146283 	(void) priv_addset (pPrivSet, PRIV_SYS_CONFIG);
13286654Snp146283 
13296654Snp146283 	if (setppriv (PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
13306654Snp146283 		HAL_INFO (("Could not set the privileges"));
13316654Snp146283 		priv_freeset (pPrivSet);
13326654Snp146283 		return;
13336654Snp146283 	}
13346654Snp146283 
13356654Snp146283 	priv_freeset (pPrivSet);
13366654Snp146283 
13376654Snp146283 }
13386654Snp146283 
13396654Snp146283 int
main(int argc,char ** argv)13406654Snp146283 main(int argc, char **argv)
13416654Snp146283 {
13426654Snp146283 
13436654Snp146283 	LibHalContext *ctx = NULL;
13446654Snp146283 	char *udi;
13456654Snp146283 	DBusError error;
13466654Snp146283 	DBusConnection *conn;
13476654Snp146283 
13486654Snp146283 	GMainLoop *loop = g_main_loop_new (NULL, FALSE);
13496654Snp146283 
13506654Snp146283 	drop_privileges ();
13516654Snp146283 	openlog ("hald-addon-cpufreq", LOG_PID, LOG_DAEMON);
13526654Snp146283 	setup_logger ();
13536654Snp146283 
13546654Snp146283 	bzero (current_gov, EDIT_TYPE_SIZE-1);
13556654Snp146283 
13566654Snp146283 	if ((udi = getenv ("UDI")) == NULL) {
13576654Snp146283 		HAL_INFO (("\n Could not get the UDI in addon-cpufreq"));
13586654Snp146283 		return (0);
13596654Snp146283 	}
13606654Snp146283 
13616654Snp146283 	dbus_error_init (&error);
13626654Snp146283 	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
13636654Snp146283 		HAL_ERROR (("main(): init_direct failed\n"));
13646654Snp146283 		return (0);
13656654Snp146283 	}
13666654Snp146283 	dbus_error_init (&error);
13676654Snp146283 	if (!libhal_device_addon_is_ready (ctx, getenv ("UDI"), &error)) {
13686654Snp146283 		check_and_free_error (&error);
13696654Snp146283 		return (0);
13706654Snp146283 	}
13716654Snp146283 
13726654Snp146283 	/*
13736654Snp146283 	 * Claim the cpufreq interface
13746654Snp146283 	 */
13756654Snp146283 
13766654Snp146283 	HAL_DEBUG (("cpufreq Introspect XML: %s", cpufreq_introspect_xml));
13776654Snp146283 
13786654Snp146283 	if (!libhal_device_claim_interface (ctx,
13796654Snp146283 	    udi,
13806654Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
13816654Snp146283 	    cpufreq_introspect_xml,
13826654Snp146283 	    &error)) {
13836654Snp146283 		HAL_DEBUG ((" Cannot claim the CPUFreq interface"));
13846654Snp146283 		check_and_free_error (&error);
13856654Snp146283 		return (0);
13866654Snp146283 	}
13876654Snp146283 
13886654Snp146283 	conn = libhal_ctx_get_dbus_connection (ctx);
13896654Snp146283 
13906654Snp146283 	/*
13916654Snp146283 	 * Add the cpufreq capability
13926654Snp146283 	 */
13936654Snp146283 	if (!libhal_device_add_capability (ctx,
13946654Snp146283 	    udi,
13956654Snp146283 	    "cpufreq_control",
13966654Snp146283 	    &error)) {
13976654Snp146283 		HAL_DEBUG ((" Could not add cpufreq_control capability"));
13986654Snp146283 		check_and_free_error (&error);
13996654Snp146283 		return (0);
14006654Snp146283 	}
14016654Snp146283 	/*
14026654Snp146283 	 * Watches and times incoming messages
14036654Snp146283 	 */
14046654Snp146283 
14056654Snp146283 	dbus_connection_setup_with_g_main (conn, NULL);
14066654Snp146283 
14076654Snp146283 	/*
14086654Snp146283 	 * Add a filter function which gets called when a message comes in
14096654Snp146283 	 * and processes the message
14106654Snp146283 	 */
14116654Snp146283 
14126654Snp146283 	if (!dbus_connection_add_filter (conn,
14136654Snp146283 	    hald_dbus_cpufreq_filter,
14146654Snp146283 	    NULL,
14156654Snp146283 	    NULL)) {
14166654Snp146283 		HAL_INFO ((" Cannot add the CPUFreq filter function"));
14176654Snp146283 		return (0);
14186654Snp146283 	}
14196654Snp146283 
14206654Snp146283 	dbus_connection_set_exit_on_disconnect (conn, 0);
14216654Snp146283 
14226654Snp146283 	g_main_loop_run (loop);
14236654Snp146283 }
1424