summaryrefslogtreecommitdiffstats
path: root/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.cpp')
-rw-r--r--tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.cpp982
1 files changed, 982 insertions, 0 deletions
diff --git a/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.cpp b/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.cpp
new file mode 100644
index 000000000..8ba765c34
--- /dev/null
+++ b/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.cpp
@@ -0,0 +1,982 @@
+#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>
+#include <fcntl.h>
+
+#include <tqdbusconnection.h>
+#include <tqdbusdata.h>
+#include <tqdbusdatamap.h>
+#include <tqdbuserror.h>
+#include <tqdbusmessage.h>
+#include <tqdbusproxy.h>
+#include <tqdbusvariant.h>
+
+// Input devices
+#include <linux/input.h>
+
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NUM_BITS(x) ((((x) - 1) / BITS_PER_LONG) + 1)
+
+bool checkPolKitAuthorization(DBusMessage* msg, const TQString &action_id)
+{
+ if (!msg) {
+ return false;
+ }
+ TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus);
+ if (!dbusConn.isConnected()) {
+ return false;
+ }
+ TQT_DBusProxy polkitProxy("org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority",
+ "org.freedesktop.PolicyKit1.Authority", dbusConn);
+ if (polkitProxy.canSend()) {
+ // Check whether the requested action is authorized
+ TQString sender(dbus_message_get_sender(msg));
+ TQT_DBusVariant sysname;
+ sysname.value = TQT_DBusData::fromString(sender);
+ sysname.signature = sysname.value.buildDBusSignature();
+ TQT_DBusDataMap<TQString> subjectMap = TQT_DBusDataMap<TQString>();
+ subjectMap.insert(TQString("name"), TQT_DBusData::fromVariant(sysname));
+ TQValueList<TQT_DBusData> subjectStruct;
+ subjectStruct << TQT_DBusData::fromString("system-bus-name");
+ subjectStruct << TQT_DBusData::fromStringKeyMap(subjectMap);
+
+ TQMap<TQString, TQString> detailsMap;
+ detailsMap.insert(TQString(""), TQString(""));
+ TQT_DBusDataMap<TQString> dbusDetailsMap(detailsMap);
+
+ TQValueList<TQT_DBusData> params;
+ params << TQT_DBusData::fromStruct(subjectStruct);
+ params << TQT_DBusData::fromString(action_id);
+ params << TQT_DBusData::fromStringKeyMap(dbusDetailsMap);
+ params << TQT_DBusData::fromUInt32(0); // No user interaction
+ params << TQT_DBusData::fromString(""); // No cancellation
+
+ TQT_DBusMessage reply = polkitProxy.sendWithReply("CheckAuthorization", params);
+ if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1) {
+ return (reply[0].toStruct())[0].toBool();
+ }
+ }
+
+ return false;
+}
+
+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;
+
+ // 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;
+
+ // 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);
+}
+
+bool CanSetPowerState(const char* state, const char* disk, const char* mem) {
+ // check if required files are writable
+ bool files_writable = (access("/sys/power/state", W_OK) == 0);
+ if (disk)
+ {
+ files_writable &= (access("/sys/power/disk", W_OK) == 0);
+ }
+ if (mem)
+ {
+ files_writable &= (access("/sys/power/mem_sleep", W_OK) == 0);
+ }
+ if (!files_writable)
+ {
+ return false;
+ }
+
+ // check if method is supported
+ bool result = false;
+ // state
+ FILE *state_node = fopen("/sys/power/state", "r");
+ if (state_node) {
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t read = getline(&line, &len, state_node);
+ if (read > 0 && line) {
+ result = (strstr(line, state) != NULL);
+ free(line);
+ }
+ fclose(state_node);
+ }
+ if (!result)
+ {
+ return false;
+ }
+
+ // disk
+ if (disk)
+ {
+ FILE *disk_node = fopen("/sys/power/disk", "r");
+ if (disk_node) {
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t read = getline(&line, &len, disk_node);
+ if (read > 0 && line) {
+ result &= (strstr(line, disk) != NULL);
+ free(line);
+ }
+ fclose(disk_node);
+ }
+ }
+ if (!result)
+ {
+ return false;
+ }
+
+ // mem_sleep
+ if (mem)
+ {
+ FILE *mem_node = fopen("/sys/power/mem_sleep", "r");
+ if (mem_node) {
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t read = getline(&line, &len, mem_node);
+ if (read > 0 && line) {
+ result &= (strstr(line, mem) != NULL);
+ free(line);
+ }
+ fclose(mem_node);
+ }
+ }
+ return result;
+}
+
+bool SetPowerState(const char* state, const char* disk, const char* mem) {
+ // check if required files are writable
+ bool files_writable = (access("/sys/power/state", W_OK) == 0);
+ if (disk)
+ {
+ files_writable &= (access("/sys/power/disk", W_OK) == 0);
+ }
+ if (mem)
+ {
+ files_writable &= (access("/sys/power/mem_sleep", W_OK) == 0);
+ }
+
+ // set suspend mode
+ bool result = files_writable;
+ if (files_writable)
+ {
+ // disk
+ if (disk)
+ {
+ FILE *disk_node = fopen("/sys/power/disk", "w");
+ if (disk_node) {
+ result &= (fputs(disk, disk_node) != EOF);
+ fclose(disk_node);
+ }
+ }
+
+ // mem_sleep
+ if (mem)
+ {
+ FILE *mem_node = fopen("/sys/power/mem_sleep", "w");
+ if (mem_node) {
+ result &= (fputs(mem, mem_node) != EOF);
+ fclose(mem_node);
+ }
+ }
+
+ // state
+ FILE *state_node = fopen("/sys/power/state", "w");
+ if (state_node) {
+ result &= (fputs(state, state_node) != EOF);
+ fclose(state_node);
+ }
+ }
+ return result;
+}
+
+void reply_CanSetHibernationMethod(DBusMessage* msg, DBusConnection* conn) {
+ // check if path is writable
+ reply_CanSetGivenPath(msg, conn, "/sys/power/disk");
+}
+
+void reply_SetHibernationMethod(DBusMessage* msg, DBusConnection* conn) {
+ DBusMessageIter args;
+ const char* member = dbus_message_get_member(msg);
+ char* method = NULL;
+
+ // 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: argument not string\n", member);
+ }
+ else {
+ dbus_message_iter_get_basic(&args, &method);
+ }
+
+ // set hibernation method
+ if (method) {
+ reply_SetGivenPath(msg, conn, "/sys/power/disk", method);
+ }
+ else {
+ reply_Bool(msg, conn, false);
+ }
+}
+
+void reply_InputEventsGetSwitches(DBusMessage* msg, DBusConnection* conn, bool active) {
+ DBusMessage* reply;
+ DBusMessageIter args, arrayIter;
+ const char* member = dbus_message_get_member(msg);
+ dbus_uint32_t serial = 0;
+ char* rawpath;
+ char* safepath;
+ int fd, r;
+ unsigned long switches[NUM_BITS(EV_CNT)];
+
+ // 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, "/dev/input/event") == safepath)
+ ) {
+
+ fd = open(safepath, O_RDONLY);
+ if( active ) {
+ r = ioctl(fd, EVIOCGSW(sizeof(switches)), switches);
+ }
+ else {
+ r = ioctl(fd, EVIOCGBIT(EV_SW, EV_CNT), switches);
+ }
+ if( r > 0 ) {
+ dbus_uint32_t dSwitches[NUM_BITS(EV_CNT)];
+ dbus_uint32_t *dSwitchesP = dSwitches;
+ int i;
+
+ // create a reply from the message
+ reply = dbus_message_new_method_return(msg);
+
+ // add the arguments to the reply
+ for( i = 0; i < sizeof(switches)/sizeof(switches[0]); i++ ) {
+ dSwitches[i] = switches[i];
+ }
+ dbus_message_iter_init_append(reply, &args);
+ if (!dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "u", &arrayIter)) {
+ fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_open_container failed\n", member);
+ return;
+ }
+ if( !dbus_message_iter_append_fixed_array(&arrayIter, DBUS_TYPE_UINT32,
+ &dSwitchesP, sizeof(switches)/sizeof(switches[0])) ) {
+ fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_append_fixed_array failed\n", member);
+ return;
+ }
+ if (!dbus_message_iter_close_container(&args, &arrayIter)) {
+ fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_close_container failed\n", member);
+ return;
+ }
+ }
+ else {
+ // create a reply from the message
+ reply = dbus_message_new_error_printf(msg,
+ "org.freedesktop.DBus.Error.NotSupported",
+ "Event device \"%s\" not support EV_SW ioctl",
+ safepath);
+ }
+ close(fd);
+ }
+ else {
+ // create a reply from the message
+ reply = dbus_message_new_error_printf(msg,
+ "org.freedesktop.DBus.Error.InvalidArgs",
+ "Event device \"%s\" is invalid",
+ rawpath);
+ }
+
+ // 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);
+
+ // free safepath
+ free(safepath);
+}
+
+void signal_NameAcquired(DBusMessage* msg) {
+ DBusMessageIter args;
+ char *name = NULL;
+ if(dbus_message_iter_init(msg, &args)) {
+ if(DBUS_TYPE_STRING == dbus_message_iter_get_arg_type(&args)) {
+ dbus_message_iter_get_basic(&args, &name);
+ }
+ }
+ fprintf(stderr, "[tde_dbus_hardwarecontrol] Name acquired: %s\n", name);
+}
+
+void reply_Introspect(DBusMessage* msg, DBusConnection* conn) {
+ DBusMessage* reply;
+ DBusMessageIter args;
+ dbus_uint32_t serial = 0;
+ size_t size = 4096;
+ const char* member = dbus_message_get_member(msg);
+ const char *path = dbus_message_get_path(msg);
+ char *data = new char[size];
+
+ // compose reply
+ strncpy(data,
+ "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
+ " \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n",
+ size);
+ strncat(data, "<node>\n", size-strlen(data));
+ if(strcmp("/", path) == 0) {
+ strncat(data, " <node name=\"org\" />\n", size-strlen(data));
+ }
+ else if(strcmp("/org", path) == 0) {
+ strncat(data, " <node name=\"trinitydesktop\" />\n", size-strlen(data));
+ }
+ else if(strcmp("/org/trinitydesktop", path) == 0) {
+ strncat(data, " <node name=\"hardwarecontrol\" />\n", size-strlen(data));
+ }
+ else if(strcmp("/org/trinitydesktop/hardwarecontrol", path) == 0) {
+ strncat(data,
+ " <interface name=\"org.trinitydesktop.hardwarecontrol.Brightness\">\n"
+ " <method name=\"CanSetBrightness\">\n"
+ " <arg name=\"device\" direction=\"in\" type=\"s\" />\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"SetBrightness\">\n"
+ " <arg name=\"device\" direction=\"in\" type=\"s\" />\n"
+ " <arg name=\"brightness\" direction=\"in\" type=\"s\" />\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " </interface>\n",
+ size-strlen(data));
+ strncat(data,
+ " <interface name=\"org.trinitydesktop.hardwarecontrol.CPUGovernor\">\n"
+ " <method name=\"CanSetCPUGovernor\">\n"
+ " <arg name=\"cpu\" direction=\"in\" type=\"i\" />\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"SetCPUGovernor\">\n"
+ " <arg name=\"cpu\" direction=\"in\" type=\"i\" />\n"
+ " <arg name=\"governor\" direction=\"in\" type=\"s\" />\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " </interface>\n",
+ size-strlen(data));
+ strncat(data,
+ " <interface name=\"org.trinitydesktop.hardwarecontrol.InputEvents\">\n"
+ " <method name=\"GetProvidedSwitches\">\n"
+ " <arg name=\"device\" direction=\"in\" type=\"s\" />\n"
+ " <arg name=\"value\" direction=\"out\" type=\"au\" />\n"
+ " </method>\n"
+ " <method name=\"GetActiveSwitches\">\n"
+ " <arg name=\"device\" direction=\"in\" type=\"s\" />\n"
+ " <arg name=\"value\" direction=\"out\" type=\"au\" />\n"
+ " </method>\n"
+ " </interface>\n",
+ size-strlen(data));
+ strncat(data,
+ " <interface name=\"org.trinitydesktop.hardwarecontrol.Power\">\n"
+ " <method name=\"CanStandby\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"Standby\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"CanFreeze\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"Freeze\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"CanSuspend\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"Suspend\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"CanHibernate\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"Hibernate\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"CanHybridSuspend\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"HybridSuspend\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"CanSetHibernationMethod\">\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " <method name=\"SetHibernationMethod\">\n"
+ " <arg name=\"method\" direction=\"in\" type=\"s\" />\n"
+ " <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
+ " </method>\n"
+ " </interface>\n",
+ size-strlen(data));
+ }
+ strncat(data, "</node>\n", size-strlen(data));
+
+ // 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_STRING, &data)) {
+ 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);
+ delete[] data;
+}
+
+void reply_PropertiesGetAll(DBusMessage* msg, DBusConnection* conn) {
+ DBusMessage* reply;
+ DBusMessageIter args, arrayIter;
+ 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_open_container(&args, DBUS_TYPE_ARRAY, "sv", &arrayIter)) {
+ fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_open_container failed\n", member);
+ return;
+ }
+ if (!dbus_message_iter_close_container(&args, &arrayIter)) {
+ fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_close_container 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 error_UnknownMessage(DBusMessage* msg, DBusConnection* conn) {
+ const char* member = dbus_message_get_member(msg);
+ const char* interface = dbus_message_get_interface(msg);
+ // print message
+ fprintf(stderr, "[tde_dbus_hardwarecontrol] Unknown method '%s' called on interface '%s', ignoring\n", member, interface);
+ if (DBUS_MESSAGE_TYPE_METHOD_CALL != dbus_message_get_type(msg)) {
+ return;
+ }
+
+ // create a reply from the message
+ DBusMessage* reply = dbus_message_new_error_printf(msg,
+ "org.freedesktop.DBus.Error.UnknownMethod",
+ "Method \"%s\" on interface \"%s\" doesn't exist",
+ member, interface);
+
+ // send the reply && flush the connection
+ dbus_uint32_t serial = 0;
+ 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 error_PolkitAccessDenied(DBusMessage* msg, DBusConnection* conn) {
+ // create a reply from the message
+ DBusMessage* reply = dbus_message_new_error(msg,
+ "org.freedesktop.DBus.Error.AccessDenied", "Permission denied.");
+
+ // send the reply && flush the connection
+ dbus_uint32_t serial = 0;
+ if (!dbus_connection_send(conn, reply, &serial)) {
+ fprintf(stderr, "[tde_dbus_hardwarecontrol] error_PolkitAccessDenied: dbus_connection_send failed\n");
+ return;
+ }
+ dbus_connection_flush(conn);
+
+ // free the reply
+ dbus_message_unref(reply);
+}
+
+void listen() {
+ DBusMessage* msg;
+ DBusConnection* conn;
+ DBusError err;
+ int ret;
+
+ 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
+ // block for up to 1 second, exit in case the connection was lost
+ while (dbus_connection_read_write(conn, 1000)) {
+ // non blocking read of the next available message
+ 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 if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanFreeze")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.freeze");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = CanSetPowerState("freeze", NULL, NULL) || CanSetPowerState("mem", NULL, "s2idle");
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "Freeze")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.freeze");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = false;
+ if (CanSetPowerState("freeze", NULL, NULL)) {
+ result = SetPowerState("freeze", NULL, NULL);
+ }
+ else if (CanSetPowerState("mem", NULL, "s2idle")) {
+ result = SetPowerState("mem", NULL, "s2idle");
+ }
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanStandby")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.standby");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = CanSetPowerState("standby", NULL, NULL) || CanSetPowerState("mem", NULL, "shallow");
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "Standby")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.standby");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = false;
+ if (CanSetPowerState("standby", NULL, NULL)) {
+ result = SetPowerState("standby", NULL, NULL);
+ }
+ else if (CanSetPowerState("mem", NULL, "shallow")) {
+ result = SetPowerState("mem", NULL, "shallow");
+ }
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanSuspend")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.suspend");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = (CanSetPowerState("mem", NULL, NULL) && access("/sys/power/mem_sleep", R_OK) != 0) ||
+ CanSetPowerState("mem", NULL, "deep");
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "Suspend")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.suspend");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = false;
+ if (CanSetPowerState("mem", NULL, NULL) && access("/sys/power/mem_sleep", R_OK) != 0) {
+ result = SetPowerState("mem", NULL, NULL);
+ }
+ else if (CanSetPowerState("mem", NULL, "deep")) {
+ result = SetPowerState("mem", NULL, "deep");
+ }
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanHybridSuspend")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.hybridsuspend");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = CanSetPowerState("disk", "suspend", NULL);
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "HybridSuspend")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.hybridsuspend");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = SetPowerState("disk", "suspend", NULL);
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanHibernate")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.hibernate");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = CanSetPowerState("disk", "shutdown", NULL) || CanSetPowerState("disk", "platform", NULL);
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "Hibernate")) {
+ bool result = checkPolKitAuthorization(msg, "org.trinitydesktop.hardwarecontrol.power.hibernate");
+ if (!result) {
+ error_PolkitAccessDenied(msg, conn);
+ }
+ else {
+ result = false;
+ if (CanSetPowerState("disk", "shutdown", NULL)) {
+ result = SetPowerState("disk", "shutdown", NULL);
+ }
+ else if (CanSetPowerState("disk", "platform", NULL)) {
+ result = SetPowerState("disk", "platform", NULL);
+ }
+ reply_Bool(msg, conn, result);
+ }
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanSetHibernationMethod")) {
+ reply_CanSetHibernationMethod(msg, conn);
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "SetHibernationMethod")) {
+ reply_SetHibernationMethod(msg, conn);
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.InputEvents", "GetProvidedSwitches")) {
+ reply_InputEventsGetSwitches(msg, conn, false);
+ }
+ else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.InputEvents", "GetActiveSwitches")) {
+ reply_InputEventsGetSwitches(msg, conn, true);
+ }
+ else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired")) {
+ signal_NameAcquired(msg);
+ }
+ else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+ reply_Introspect(msg, conn);
+ }
+ else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Properties", "GetAll")) {
+ reply_PropertiesGetAll(msg, conn);
+ }
+ else {
+ error_UnknownMessage(msg, conn);
+ }
+
+ // free the message
+ dbus_message_unref(msg);
+ }
+
+ // close the connection
+ dbus_connection_unref(conn);
+}
+
+int main(int argc, char** argv) {
+ listen();
+ return 0;
+}