[Desire HD Android Development] snq-:
people on irc have asked for my opinion on the overclocking daemon

since i couldn't find any details on it, i made a little research

in case anyone else was wondering how it exactly works:

/*
decompiled source code of the
virtuous "overclocking daemon" /rmk40 (rmk@roobix.net)

compiles to the _exact_same_ binary as the original
(md5: c3f8b96dd8933cf50ba36be98a67fef4)
(the goal was not to rewrite/improve/correct it)

the original was built using the
froyo sdk (generic/eng) / gcc440

snq-^xda

-------- snip beg [Android.mk]
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := virtuous_oc
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := eng
LOCAL_SRC_FILES := virtuous_oc.c
LOCAL_SHARED_LIBRARIES := liblog libcutils
include $(BUILD_EXECUTABLE)
-------- snip end [Android.mk]
*/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <android/log.h>

#define LOG(level, ...) __android_log_write(level, "Virtuous_OC", __VA_ARGS__)
#define LOGI(...) LOG(ANDROID_LOG_INFO, __VA_ARGS__)
#define LOGE(...) LOG(ANDROID_LOG_ERROR, __VA_ARGS__)

#define RET_OK	(0)
#define RET_FAIL	(-1)

#define CITEM_LEN	(30)

typedef char pconfitem[CITEM_LEN];

typedef struct
{
pconfitem min_freq;
pconfitem max_freq;
pconfitem governor;
} pconf;

typedef struct
{
pconf wake;
pconf sleep;
} pconfs;

void remove_crlf(char *str)
{
int p = 0;
while(str[p] != '\0')
{
if ((str[p] == '\n') ||(str[p] == '\r'))
str[p]= '\0';
p++;
}
}

int write_iface(const char *iface, const char *val)
{
FILE *f;
int ret;

f = fopen(iface, "w");
if (f == NULL)
return RET_FAIL;

ret = (fputs(val, f) < 0) ? RET_FAIL : RET_OK;
fclose(f);

return ret;
}

int set_values(char *governor, char *min_freq, char *max_freq)
{
char logb[256];

if (write_iface("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", governor) != RET_OK)
return RET_FAIL;
if (write_iface("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", max_freq) != RET_OK)
return RET_FAIL;
if (write_iface("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", min_freq) != RET_OK)
return RET_FAIL;

logb[0] = '\0';

strcat(logb, "Setting CPU Params: Governor=");
remove_crlf(governor);
strcat(logb, governor);

strcat(logb, " min_freq=");
remove_crlf(min_freq);
strcat(logb, min_freq);

strcat(logb, " max_freq=");
remove_crlf(max_freq);
strcat(logb, max_freq);

LOGI(logb);

return RET_OK;
}

int read_file(const char *fname, int count, char *str)
{
FILE *f;
int ret;

f = fopen(fname, "r");
if (f == NULL)
return RET_FAIL;

ret = (fgets(str, count, f) != NULL) ? RET_OK : RET_FAIL;
fclose(f);

return ret;
}

int load_pconfitem(const char *name, pconfitem ci)
{
char fname[60];
strcpy(fname, "/system/etc/virtuous_oc/");
strcat(fname, name);
return read_file(fname, CITEM_LEN, ci);
}

int load_pconfs(pconfs *config)
{
if (config == NULL)
return RET_FAIL;

if (load_pconfitem("wake_min_freq", config->wake.min_freq) == RET_FAIL)
return RET_FAIL;
if (load_pconfitem("wake_max_freq", config->wake.max_freq) == RET_FAIL)
return RET_FAIL;
if (load_pconfitem("wake_governor", config->wake.governor) == RET_FAIL)
return RET_FAIL;
if (load_pconfitem("sleep_min_freq", config->sleep.min_freq) == RET_FAIL)
return RET_FAIL;
if (load_pconfitem("sleep_max_freq", config->sleep.max_freq) == RET_FAIL)
return RET_FAIL;
if (load_pconfitem("sleep_governor", config->sleep.governor) == RET_FAIL)
return RET_FAIL;

return RET_OK;
}

int main(int argc, char *argv[])
{
pconfs config;
char fbstatus[12];

LOGI("Starting service.");

if (load_pconfs(&config) == RET_FAIL)
{
LOGE("Unable to load configuration. Stopping.");
return 1;
}

fbstatus[0] = '\0';

pid_t pid = fork();
if (pid < 0)
exit(2);
else if (pid > 0)
exit(0);

umask(0);
if (setsid() < 0)
exit(2);

if (chdir("/") < 0)
exit(2);

close(0);
close(1);
close(2);

while (1)
{
if (read_file("/sys/power/wait_for_fb_wake", sizeof("awake") /* 5+1 */, fbstatus) == RET_FAIL)
{
LOGE("Unable to get data from file. Cannot continue.");
return 1;
}

if (strcmp(fbstatus, "awake") == 0)
{
LOGI("Setting awake profile.");
set_values(config.wake.governor, config.wake.min_freq, config.wake.max_freq);
}

fbstatus[0] = '\0';

if (read_file("/sys/power/wait_for_fb_sleep", sizeof("sleeping") /* 8+1 */, fbstatus) == RET_FAIL)
{
LOGE("Unable to get data from file. Cannot continue.");
return 1;
}

if (strcmp(fbstatus, "sleeping") == 0)
{
LOGI("Setting sleep profile.");
set_values(config.sleep.governor, config.sleep.min_freq, config.sleep.max_freq);
}

fbstatus[0] = '\0';
}
}