Add control daemon for CPU governor and display brightness

This allows kpowersave-nohal to function properly as a normal user
pull/16/head
Timothy Pearson 12 years ago
parent 9af7bd1f0b
commit 54928e8635

@ -770,6 +770,19 @@ if( WITH_PCRE )
endif( )
##### set DBUS file locations ##################
if( NOT DEFINED DBUS_SYSTEM_CONF_DIRECTORY )
set (DBUS_SYSTEM_CONF_DIRECTORY "/etc/dbus-1/system.d/" )
message( STATUS "Using " ${DBUS_SYSTEM_CONF_DIRECTORY} " for DBUS configuration files" )
endif( NOT DEFINED DBUS_SYSTEM_CONF_DIRECTORY )
if( NOT DEFINED DBUS_SERVICE_DIRECTORY )
set (DBUS_SERVICE_DIRECTORY "/usr/share/dbus-1/system-services/" )
message( STATUS "Using " ${DBUS_SERVICE_DIRECTORY} " for DBUS service files" )
endif( NOT DEFINED DBUS_SERVICE_DIRECTORY )
if( WITH_NETWORK_MANAGER_BACKEND )
##### check for dbus-1 ###########################
pkg_search_module( DBUS dbus-1 )

@ -13,6 +13,7 @@ add_subdirectory( malloc )
add_subdirectory( network )
add_subdirectory( kconfig_compiler )
add_subdirectory( hwlibdata )
add_subdirectory( hwlibdaemons )
if( NOT DBUS_SYSTEM_BUS )
set( DBUS_SYSTEM_BUS "unix:path=/var/run/dbus/system_bus_socket" CACHE INTERNAL "" FORCE )

@ -0,0 +1,13 @@
#################################################
#
# (C) 2012 Timothy Pearson
# kb9vqf (AT) pearsoncomputing.net
#
# Improvements and feedback are welcome
#
# This file is released under GPL >= 2
#
#################################################
add_subdirectory( dbus )

@ -0,0 +1,37 @@
#################################################
#
# (C) 2012 Timothy Pearson
# kb9vqf (AT) pearsoncomputing.net
#
# Improvements and feedback are welcome
#
# This file is released under GPL >= 2
#
#################################################
include_directories(
${DBUS_INCLUDE_DIRS}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
)
##### tde_dbus_hardwarecontrol ##################
tde_add_executable( tde_dbus_hardwarecontrol
SOURCES tde_dbus_hardwarecontrol.c
LINK ${DBUS_LIBRARIES}
DESTINATION ${BIN_INSTALL_DIR}
)
##### other data ################################
configure_file( org.trinitydesktop.hardwarecontrol.service.cmake org.trinitydesktop.hardwarecontrol.service @ONLY )
install( FILES
org.trinitydesktop.hardwarecontrol.conf
DESTINATION ${DBUS_SYSTEM_CONF_DIRECTORY} )
install( FILES
${CMAKE_CURRENT_BINARY_DIR}/org.trinitydesktop.hardwarecontrol.service
DESTINATION ${DBUS_SERVICE_DIRECTORY} )

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Only root can own the service -->
<policy user="root">
<allow own="org.trinitydesktop.hardwarecontrol"/>
</policy>
<policy at_console="true">
<!-- Users with physical access to the machine are allowed access -->
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol.CPUGovernor"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol.Brightness"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.trinitydesktop.hardwarecontrol"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.trinitydesktop.hardwarecontrol.CPUGovernor"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.trinitydesktop.hardwarecontrol.Brightness"/>
</policy>
<policy context="default">
<!-- Everyone else is denied access -->
<deny own="org.trinitydesktop.hardwarecontrol"/>
<deny send_destination="org.trinitydesktop.hardwarecontrol"/>
</policy>
</busconfig>

@ -0,0 +1,4 @@
[D-BUS Service]
Name=org.trinitydesktop.hardwarecontrol
Exec=@BIN_INSTALL_DIR@/tde_dbus_hardwarecontrol
User=root

@ -0,0 +1,327 @@
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reply_Bool(DBusMessage* msg, DBusConnection* conn, int value) {
DBusMessage* reply;
DBusMessageIter args;
const char* member = dbus_message_get_member(msg);
dbus_uint32_t serial = 0;
// create a reply from the message
reply = dbus_message_new_method_return(msg);
// add the arguments to the reply
dbus_message_iter_init_append(reply, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &value)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_append_basic failed\n", member);
return;
}
// send the reply && flush the connection
if (!dbus_connection_send(conn, reply, &serial)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_connection_send failed\n", member);
return;
}
dbus_connection_flush(conn);
// free the reply
dbus_message_unref(reply);
}
void reply_CanSetGivenPath(DBusMessage* msg, DBusConnection* conn, const char* param) {
DBusMessage* reply;
DBusMessageIter args;
const char* member = dbus_message_get_member(msg);
dbus_uint32_t serial = 0;
int writable = false;
// check if path is writable
int rval = access (param, W_OK);
if (rval == 0) {
writable = true;
}
// create a reply from the message
reply = dbus_message_new_method_return(msg);
// add the arguments to the reply
dbus_message_iter_init_append(reply, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &writable)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_append_basic failed\n", member);
return;
}
// send the reply && flush the connection
if (!dbus_connection_send(conn, reply, &serial)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_connection_send failed\n", member);
return;
}
dbus_connection_flush(conn);
// free the reply
dbus_message_unref(reply);
}
void reply_SetGivenPath(DBusMessage* msg, DBusConnection* conn, const char* param, const char* contents) {
DBusMessage* reply;
DBusMessageIter args;
const char* member = dbus_message_get_member(msg);
dbus_uint32_t serial = 0;
int writable = false;
int written = false;
// check if path is writable
int rval = access (param, W_OK);
if (rval == 0) {
writable = true;
}
if (writable) {
FILE *node = fopen(param, "w");
if (node != NULL) {
if (fputs(contents, node) != EOF) {
written = true;
}
if (fclose(node) == EOF) {
// Error!
}
}
}
// create a reply from the message
reply = dbus_message_new_method_return(msg);
// add the arguments to the reply
dbus_message_iter_init_append(reply, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &written)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_append_basic failed\n", member);
return;
}
// send the reply && flush the connection
if (!dbus_connection_send(conn, reply, &serial)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_connection_send failed\n", member);
return;
}
dbus_connection_flush(conn);
// free the reply
dbus_message_unref(reply);
}
void reply_CanSetCPUGovernor(DBusMessage* msg, DBusConnection* conn) {
DBusMessageIter args;
const char* member = dbus_message_get_member(msg);
dbus_int32_t cpunum;
char path[256];
// read the arguments
if (!dbus_message_iter_init(msg, &args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: no argument supplied\n", member);
}
else if (DBUS_TYPE_INT32 != dbus_message_iter_get_arg_type(&args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: argument not 32-bit integer\n", member);
}
else {
dbus_message_iter_get_basic(&args, &cpunum);
}
snprintf(path, 256, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", cpunum);
reply_CanSetGivenPath(msg, conn, path);
}
void reply_SetCPUGovernor(DBusMessage* msg, DBusConnection* conn) {
DBusMessageIter args;
const char* member = dbus_message_get_member(msg);
dbus_int32_t cpunum = -1;
char* governor = NULL;
char path[256];
// read the arguments
if (!dbus_message_iter_init(msg, &args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: no arguments supplied\n", member);
}
else if (DBUS_TYPE_INT32 != dbus_message_iter_get_arg_type(&args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: first argument not 32-bit integer\n", member);
}
else {
dbus_message_iter_get_basic(&args, &cpunum);
}
if (!dbus_message_iter_next(&args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: second argument not supplied\n", member);
}
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: second argument not string\n", member);
}
else {
dbus_message_iter_get_basic(&args, &governor);
}
snprintf(path, 256, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", cpunum);
if ((cpunum>-1) && governor) {
reply_SetGivenPath(msg, conn, path, governor);
}
else {
reply_Bool(msg, conn, false);
}
}
void reply_CanSetBrightness(DBusMessage* msg, DBusConnection* conn) {
DBusMessageIter args;
const char* member = dbus_message_get_member(msg);
char* rawpath;
char* safepath;
char path[256];
// read the arguments
if (!dbus_message_iter_init(msg, &args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: no argument supplied\n", member);
}
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: argument not string\n", member);
}
else {
dbus_message_iter_get_basic(&args, &rawpath);
}
safepath = realpath(rawpath, NULL);
if (safepath &&
(strstr(safepath, "/sys/devices") == safepath) &&
(strstr(safepath, "/brightness") == (safepath+strlen(safepath)-strlen("/brightness")))
) {
reply_CanSetGivenPath(msg, conn, safepath);
}
else {
reply_Bool(msg, conn, false);
}
free(safepath);
}
void reply_SetBrightness(DBusMessage* msg, DBusConnection* conn) {
DBusMessageIter args;
const char* member = dbus_message_get_member(msg);
char* rawpath;
char* safepath;
char* brightness;
char path[256];
// read the arguments
if (!dbus_message_iter_init(msg, &args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: no arguments supplied\n", member);
}
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: first argument not string\n", member);
}
else {
dbus_message_iter_get_basic(&args, &rawpath);
}
if (!dbus_message_iter_next(&args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: second argument not supplied\n", member);
}
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: second argument not string\n", member);
}
else {
dbus_message_iter_get_basic(&args, &brightness);
}
safepath = realpath(rawpath, NULL);
if (safepath && brightness &&
(strstr(safepath, "/sys/devices") == safepath) &&
(strstr(safepath, "/brightness") == (safepath+strlen(safepath)-strlen("/brightness")))
) {
reply_SetGivenPath(msg, conn, safepath, brightness);
}
else {
reply_Bool(msg, conn, false);
}
free(safepath);
}
void listen() {
DBusMessage* msg;
DBusMessage* reply;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
int ret;
char* param;
fprintf(stderr, "[tde_dbus_hardwarecontrol] Listening...\n");
// initialise the error structure
dbus_error_init(&err);
// connect to the bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] Connection failed with error '%s'\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] No connection, exiting!\n");
exit(1);
}
// request our name on the bus and check for errors
ret = dbus_bus_request_name(conn, "org.trinitydesktop.hardwarecontrol", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] Name request failed with error '%s'\n", err.message);
dbus_error_free(&err);
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
fprintf(stderr, "[tde_dbus_hardwarecontrol] Not primary owner (%d), exiting!\n", ret);
exit(1);
}
// loop, testing for new messages
while (true) {
// non blocking read of the next available message
dbus_connection_read_write(conn, 1000); // block for up to 1 second
msg = dbus_connection_pop_message(conn);
// loop again if we haven't got a message
if (NULL == msg) {
continue;
}
// check this is a method call for the right interface & method
if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.CPUGovernor", "CanSetCPUGovernor")) {
reply_CanSetCPUGovernor(msg, conn);
}
else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.CPUGovernor", "SetCPUGovernor")) {
reply_SetCPUGovernor(msg, conn);
}
else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Brightness", "CanSetBrightness")) {
reply_CanSetBrightness(msg, conn);
}
else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Brightness", "SetBrightness")) {
reply_SetBrightness(msg, conn);
}
else {
fprintf(stderr, "[tde_dbus_hardwarecontrol] Unknown method '%s' called on interface '%s', ignoring\n", dbus_message_get_member(msg), dbus_message_get_interface(msg));
}
// free the message
dbus_message_unref(msg);
}
// close the connection
dbus_connection_close(conn);
}
int main(int argc, char** argv) {
listen();
return 0;
}

@ -977,7 +977,25 @@ bool TDECPUDevice::canSetGovernor() {
return TRUE;
}
else {
#ifdef WITH_UPOWER
TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus);
if (dbusConn.isConnected()) {
TQT_DBusProxy hardwareControl("org.trinitydesktop.hardwarecontrol", "/org/trinitydesktop/hardwarecontrol", "org.trinitydesktop.hardwarecontrol,CPUGovernor", dbusConn);
// can set brightness?
TQValueList<TQT_DBusData> params;
params << TQT_DBusData::fromInt32(coreNumber());
TQT_DBusMessage reply = hardwareControl.sendWithReply("CanSetCPUGovernor", params);
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1) {
return reply[0].toVariant().value.toBool();
}
}
else {
return FALSE;
}
#else // WITH_UPOWER
return FALSE;
#endif// WITH_UPOWER
}
}
@ -989,6 +1007,22 @@ void TDECPUDevice::setGovernor(TQString gv) {
stream << gv.lower();
file.close();
}
#ifdef WITH_UPOWER
else {
TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus);
if (dbusConn.isConnected()) {
TQT_DBusProxy hardwareControl("org.trinitydesktop.hardwarecontrol", "/org/trinitydesktop/hardwarecontrol", "org.trinitydesktop.hardwarecontrol.CPUGovernor", dbusConn);
// set brightness
TQValueList<TQT_DBusData> params;
params << TQT_DBusData::fromInt32(coreNumber()) << TQT_DBusData::fromString(gv.lower());
hardwareControl.sendWithReply("SetCPUGovernor", params);
}
else {
return;
}
}
#endif // WITH_UPOWER
// Force update of the device information object
KGlobal::hardwareDevices()->processModifiedCPUs();
@ -1629,7 +1663,25 @@ bool TDEBacklightDevice::canSetBrightness() {
return TRUE;
}
else {
#ifdef WITH_UPOWER
TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus);
if (dbusConn.isConnected()) {
TQT_DBusProxy hardwareControl("org.trinitydesktop.hardwarecontrol", "/org/trinitydesktop/hardwarecontrol", "org.trinitydesktop.hardwarecontrol,Brightness", dbusConn);
// can set brightness?
TQValueList<TQT_DBusData> params;
params << TQT_DBusData::fromString(brightnessnode);
TQT_DBusMessage reply = hardwareControl.sendWithReply("CanSetBrightness", params);
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1) {
return reply[0].toVariant().value.toBool();
}
}
else {
return FALSE;
}
#else // WITH_UPOWER
return FALSE;
#endif// WITH_UPOWER
}
}
@ -1639,14 +1691,29 @@ int TDEBacklightDevice::rawBrightness() {
void TDEBacklightDevice::setRawBrightness(int br) {
TQString brightnessnode = systemPath() + "/brightness";
TQString brightnessCommand = TQString("%1").arg(br);
TQFile file( brightnessnode );
if ( file.open( IO_WriteOnly ) ) {
TQString brightnessCommand;
brightnessCommand = TQString("%1").arg(br);
TQTextStream stream( &file );
stream << brightnessCommand;
file.close();
}
#ifdef WITH_UPOWER
else {
TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus);
if (dbusConn.isConnected()) {
TQT_DBusProxy hardwareControl("org.trinitydesktop.hardwarecontrol", "/org/trinitydesktop/hardwarecontrol", "org.trinitydesktop.hardwarecontrol.Brightness", dbusConn);
// set brightness
TQValueList<TQT_DBusData> params;
params << TQT_DBusData::fromString(brightnessnode) << TQT_DBusData::fromString(brightnessCommand);
hardwareControl.sendWithReply("SetBrightness", params);
}
else {
return;
}
}
#endif // WITH_UPOWER
}
TDEMonitorDevice::TDEMonitorDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn) {

@ -33,7 +33,7 @@
* There is a new signal executed(). It gets connected to either
* TQIconView::clicked() or TQIconView::doubleClicked() depending on the KDE
* wide Single Click/Double Click settings. It is strongly recommended that
* you use this signal instead of the above mentioned. This way you don´t
* you use this signal instead of the above mentioned. This way you don<EFBFBD>t
* need to care about the current settings.
* If you want to get informed when the user selects something connect to the
* TQIconView::selectionChanged() signal.

Loading…
Cancel
Save