From cebadfa114d50a465f9d04d59da5015fed673b26 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sat, 10 Nov 2018 01:06:57 +0900 Subject: [PATCH] Improved support for suspend modes for both older and newer kernels. Signed-off-by: Michele Calgaro --- .../dbus/tde_dbus_hardwarecontrol.c | 75 +++++--- tdecore/tdehw/tdehardwaredevices.cpp | 35 +++- tdecore/tdehw/tderootsystemdevice.cpp | 161 ++++++++++++++---- 3 files changed, 212 insertions(+), 59 deletions(-) diff --git a/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c b/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c index a0b6870b1..2a10d67c6 100644 --- a/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c +++ b/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c @@ -254,7 +254,7 @@ void reply_SetBrightness(DBusMessage* msg, DBusConnection* conn) { free(safepath); } -void reply_CanSetSuspend(DBusMessage* msg, DBusConnection* conn, char* state, char* disk, char* mem) { +bool check_CanSetSuspend(char* state, char* disk, char* mem) { // check if required files are writable bool files_writable = (access("/sys/power/state", W_OK) == 0); if (disk) @@ -267,7 +267,7 @@ void reply_CanSetSuspend(DBusMessage* msg, DBusConnection* conn, char* state, ch } if (!files_writable) { - reply_Bool(msg, conn, false); // send reply + return false; } // check if method is supported @@ -286,7 +286,7 @@ void reply_CanSetSuspend(DBusMessage* msg, DBusConnection* conn, char* state, ch } if (!result) { - reply_Bool(msg, conn, false); // send reply + return false; } // disk @@ -306,7 +306,7 @@ void reply_CanSetSuspend(DBusMessage* msg, DBusConnection* conn, char* state, ch } if (!result) { - reply_Bool(msg, conn, false); // send reply + return false; } // mem_sleep @@ -324,11 +324,10 @@ void reply_CanSetSuspend(DBusMessage* msg, DBusConnection* conn, char* state, ch fclose(mem_node); } } - - reply_Bool(msg, conn, result); // send reply + return result; } -void reply_SetSuspend(DBusMessage* msg, DBusConnection* conn, char* state, char* disk, char* mem) { +bool do_SetSuspend(char* state, char* disk, char* mem) { // check if required files are writable bool files_writable = (access("/sys/power/state", W_OK) == 0); if (disk) @@ -339,10 +338,6 @@ void reply_SetSuspend(DBusMessage* msg, DBusConnection* conn, char* state, char* { files_writable &= (access("/sys/power/mem_sleep", W_OK) == 0); } - if (!files_writable) - { - reply_Bool(msg, conn, false); // send reply - } // set suspend mode bool result = files_writable; @@ -375,7 +370,10 @@ void reply_SetSuspend(DBusMessage* msg, DBusConnection* conn, char* state, char* fclose(state_node); } } + return result; +} +void reply_SetSuspend(DBusMessage* msg, DBusConnection* conn, bool result) { // create a reply from the message DBusMessage *reply = dbus_message_new_method_return(msg); const char* member = dbus_message_get_member(msg); @@ -781,34 +779,69 @@ void listen() { reply_SetBrightness(msg, conn); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanFreeze")) { - reply_CanSetSuspend(msg, conn, "freeze", NULL, NULL); + bool result = check_CanSetSuspend("freeze", NULL, NULL) || check_CanSetSuspend("mem", NULL, "s2idle"); + reply_Bool(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "Freeze")) { - reply_SetSuspend(msg, conn, "freeze", NULL, NULL); + bool result = false; + if (check_CanSetSuspend("freeze", NULL, NULL)) { + result = do_SetSuspend("freeze", NULL, NULL); + } + else if (check_CanSetSuspend("mem", NULL, "s2idle")) { + result = do_SetSuspend("mem", NULL, "s2idle"); + } + reply_SetSuspend(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanStandby")) { - reply_CanSetSuspend(msg, conn, "standby", NULL, NULL); + bool result = check_CanSetSuspend("standby", NULL, NULL) || check_CanSetSuspend("mem", NULL, "shallow"); + reply_Bool(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "Standby")) { - reply_SetSuspend(msg, conn, "standby", NULL, NULL); + bool result = false; + if (check_CanSetSuspend("standby", NULL, NULL)) { + result = do_SetSuspend("standby", NULL, NULL); + } + else if (check_CanSetSuspend("mem", NULL, "shallow")) { + result = do_SetSuspend("mem", NULL, "shallow"); + } + reply_SetSuspend(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanSuspend")) { - reply_CanSetSuspend(msg, conn, "mem", NULL, "deep"); + bool result = (check_CanSetSuspend("mem", NULL, NULL) && access("/sys/power/mem_sleep", R_OK) != 0) || + check_CanSetSuspend("mem", NULL, "deep"); + reply_Bool(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "Suspend")) { - reply_SetSuspend(msg, conn, "mem", NULL, "deep"); + bool result = false; + if (check_CanSetSuspend("mem", NULL, NULL) && access("/sys/power/mem_sleep", R_OK) != 0) { + result = do_SetSuspend("mem", NULL, NULL); + } + else if (check_CanSetSuspend("mem", NULL, "deep")) { + result = do_SetSuspend("mem", NULL, "deep"); + } + reply_SetSuspend(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanHybridSuspend")) { - reply_CanSetSuspend(msg, conn, "disk", "suspend", NULL); + bool result = check_CanSetSuspend("disk", "suspend", NULL); + reply_Bool(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "HybridSuspend")) { - reply_SetSuspend(msg, conn, "disk", "suspend", NULL); + bool result = do_SetSuspend("disk", "suspend", NULL); + reply_SetSuspend(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanHibernate")) { - reply_CanSetSuspend(msg, conn, "disk", "shutdown", NULL); + bool result = check_CanSetSuspend("disk", "shutdown", NULL) || check_CanSetSuspend("disk", "platform", NULL); + reply_Bool(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "Hibernate")) { - reply_SetSuspend(msg, conn, "disk", "shutdown", NULL); + bool result = false; + if (check_CanSetSuspend("disk", "shutdown", NULL)) { + result = do_SetSuspend("disk", "shutdown", NULL); + } + else if (check_CanSetSuspend("disk", "platform", NULL)) { + result = do_SetSuspend("disk", "platform", NULL); + } + reply_SetSuspend(msg, conn, result); } else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "CanSetHibernationMethod")) { reply_CanSetHibernationMethod(msg, conn); diff --git a/tdecore/tdehw/tdehardwaredevices.cpp b/tdecore/tdehw/tdehardwaredevices.cpp index c636e0888..fb08ae486 100644 --- a/tdecore/tdehw/tdehardwaredevices.cpp +++ b/tdecore/tdehw/tdehardwaredevices.cpp @@ -3366,12 +3366,12 @@ void TDEHardwareDevices::updateExistingDeviceInformation(TDEGenericDevice* exist // Always assume that these two fully on/fully off states are available powerstates.append(TDESystemPowerState::Active); powerstates.append(TDESystemPowerState::PowerOff); - if (line.contains("standby")) { - powerstates.append(TDESystemPowerState::Standby); - } if (line.contains("freeze")) { powerstates.append(TDESystemPowerState::Freeze); } + if (line.contains("standby")) { + powerstates.append(TDESystemPowerState::Standby); + } if (line.contains("mem")) { powerstates.append(TDESystemPowerState::Mem); } @@ -3440,17 +3440,34 @@ void TDEHardwareDevices::updateExistingDeviceInformation(TDEGenericDevice* exist } ++valuesdirit; } - // Suspend-to-RAM requires a combination of 'mem' and 'deep' in two different files - if (powerstates.contains(TDESystemPowerState::Mem) && - suspendmodes.contains(TDESystemSuspendMode::SuspendToRAM)) { - powerstates.append(TDESystemPowerState::Suspend); - powerstates.remove(TDESystemPowerState::Mem); + // Freeze can also be set if /sys/power/mem_sleep exists and contains 's2idle' + if (!powerstates.contains(TDESystemPowerState::Freeze) && + powerstates.contains(TDESystemPowerState::Mem) && + suspendmodes.contains(TDESystemSuspendMode::Standby)) { + powerstates.append(TDESystemPowerState::Freeze); + } + // Standby can also be set if /sys/power/mem_sleep exists and contains 'shallow' + if (!powerstates.contains(TDESystemPowerState::Standby) && + powerstates.contains(TDESystemPowerState::Mem) && + suspendmodes.contains(TDESystemSuspendMode::Standby)) { + powerstates.append(TDESystemPowerState::Standby); + } + // Suspend-to-RAM can be set in various ways (not necessarily all available in the same system) + // 1) if /sys/power/mem_sleep exists and contains 'deep' + // 2) if /sys/power/mem_sleep does not exists, requires support for 'mem' in /sys/power/state + if (!powerstates.contains(TDESystemPowerState::Suspend) && + powerstates.contains(TDESystemPowerState::Mem)) { + if (suspendmodes.contains(TDESystemSuspendMode::SuspendToRAM) || suspendmodes.count() == 0) { + powerstates.append(TDESystemPowerState::Suspend); + } } + powerstates.remove(TDESystemPowerState::Mem); // Hibernation and Hybrid Suspend are not real power states, being just two different // ways of suspending to disk. Since they are very common and it is very convenient to // treat them as power states, we do so, as other power frameworks also do. if (powerstates.contains(TDESystemPowerState::Disk) && - hibernationmethods.contains(TDESystemHibernationMethod::Shutdown)) { + (hibernationmethods.contains(TDESystemHibernationMethod::Shutdown) || + hibernationmethods.contains(TDESystemHibernationMethod::Platform))) { powerstates.append(TDESystemPowerState::Hibernate); } if (powerstates.contains(TDESystemPowerState::Disk) && diff --git a/tdecore/tdehw/tderootsystemdevice.cpp b/tdecore/tdehw/tderootsystemdevice.cpp index bbbd63b10..e53342aee 100644 --- a/tdecore/tdehw/tderootsystemdevice.cpp +++ b/tdecore/tdehw/tderootsystemdevice.cpp @@ -21,6 +21,7 @@ #include "tdestoragedevice.h" #include +#include #include @@ -657,41 +658,143 @@ void TDERootSystemDevice::setHibernationMethod(TDESystemHibernationMethod::TDESy } +bool check_CanSetSuspend(char* state, char* disk, 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 TDERootSystemDevice::setPowerState(TDESystemPowerState::TDESystemPowerState ps) { if ((ps == TDESystemPowerState::Freeze) || (ps == TDESystemPowerState::Standby) || (ps == TDESystemPowerState::Suspend) || (ps == TDESystemPowerState::Hibernate) || (ps == TDESystemPowerState::HybridSuspend)) { TQString statenode = "/sys/power/state"; TQString disknode = "/sys/power/disk"; + TQString memnode = "/sys/power/mem_sleep"; TQFile statefile( statenode ); TQFile diskfile( disknode ); - if ( statefile.open( IO_WriteOnly ) && - ((ps != TDESystemPowerState::Hibernate && ps != TDESystemPowerState::HybridSuspend) || - diskfile.open( IO_WriteOnly )) ) { - TQString powerCommand; - if (ps == TDESystemPowerState::Freeze) { - powerCommand = "freeze"; + TQFile memfile( memnode ); + TQString stateCommand = TQString::null; + TQString diskCommand = TQString::null; + TQString memCommand = TQString::null; + if (ps == TDESystemPowerState::Freeze) { + if (check_CanSetSuspend("freeze", NULL, NULL)) { + stateCommand = "freeze"; } - else if (ps == TDESystemPowerState::Standby) { - powerCommand = "standby"; + else { + stateCommand = "mem"; + diskCommand = "s2idle"; } - else if (ps == TDESystemPowerState::Suspend) { - powerCommand = "mem"; + } + else if (ps == TDESystemPowerState::Standby) { + if (check_CanSetSuspend("standby", NULL, NULL)) { + stateCommand = "standby"; } - else if (ps == TDESystemPowerState::Hibernate) { - powerCommand = "disk"; - TQTextStream diskstream( &diskfile ); - diskstream << "platform"; - diskfile.close(); + else { + stateCommand = "mem"; + diskCommand = "shallow"; } - else if (ps == TDESystemPowerState::HybridSuspend) { - powerCommand = "disk"; - TQTextStream diskstream( &diskfile ); - diskstream << "suspend"; - diskfile.close(); + } + else if (ps == TDESystemPowerState::Suspend) { + stateCommand = "mem"; + if (check_CanSetSuspend("mem", NULL, "deep")) { + diskCommand = "deep"; + } + } + else if (ps == TDESystemPowerState::HybridSuspend) { + stateCommand = "disk"; + diskCommand = "suspend"; + } + else if (ps == TDESystemPowerState::Hibernate) { + stateCommand = "disk"; + if (check_CanSetSuspend("disk", "shutdown", NULL)) { + diskCommand = "shutdown"; + } + else { + diskCommand = "platform"; } + } + + if (memCommand != TQString::null && memfile.open( IO_WriteOnly )) { + TQTextStream memstream( &memfile ); + memstream << memCommand; + memfile.close(); + } + if (diskCommand != TQString::null && diskfile.open( IO_WriteOnly )) { + TQTextStream diskstream( &diskfile ); + diskstream << diskCommand; + diskfile.close(); + } + if (stateCommand != TQString::null && statefile.open( IO_WriteOnly )) { TQTextStream statestream( &statefile ); - statestream << powerCommand; + statestream << stateCommand; statefile.close(); return true; } @@ -855,23 +958,23 @@ bool TDERootSystemDevice::setPowerState(TDESystemPowerState::TDESystemPowerState TQT_DBusConnection dbusConn; dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus); if ( dbusConn.isConnected() ) { - if (ps == TDESystemPowerState::Standby) { + if (ps == TDESystemPowerState::Freeze) { TQT_DBusMessage msg = TQT_DBusMessage::methodCall( "org.trinitydesktop.hardwarecontrol", "/org/trinitydesktop/hardwarecontrol", "org.trinitydesktop.hardwarecontrol.Power", - "Standby"); + "Freeze"); TQT_DBusMessage reply = dbusConn.sendWithReply(msg); if (reply.type() == TQT_DBusMessage::ReplyMessage) { return true; } } - else if (ps == TDESystemPowerState::Freeze) { + else if (ps == TDESystemPowerState::Standby) { TQT_DBusMessage msg = TQT_DBusMessage::methodCall( "org.trinitydesktop.hardwarecontrol", "/org/trinitydesktop/hardwarecontrol", "org.trinitydesktop.hardwarecontrol.Power", - "Freeze"); + "Standby"); TQT_DBusMessage reply = dbusConn.sendWithReply(msg); if (reply.type() == TQT_DBusMessage::ReplyMessage) { return true; @@ -888,23 +991,23 @@ bool TDERootSystemDevice::setPowerState(TDESystemPowerState::TDESystemPowerState return true; } } - else if (ps == TDESystemPowerState::Hibernate) { + else if (ps == TDESystemPowerState::HybridSuspend) { TQT_DBusMessage msg = TQT_DBusMessage::methodCall( "org.trinitydesktop.hardwarecontrol", "/org/trinitydesktop/hardwarecontrol", "org.trinitydesktop.hardwarecontrol.Power", - "Hibernate"); + "HybridSuspend"); TQT_DBusMessage reply = dbusConn.sendWithReply(msg); if (reply.type() == TQT_DBusMessage::ReplyMessage) { return true; } } - else if (ps == TDESystemPowerState::HybridSuspend) { + else if (ps == TDESystemPowerState::Hibernate) { TQT_DBusMessage msg = TQT_DBusMessage::methodCall( "org.trinitydesktop.hardwarecontrol", "/org/trinitydesktop/hardwarecontrol", "org.trinitydesktop.hardwarecontrol.Power", - "HybridSuspend"); + "Hibernate"); TQT_DBusMessage reply = dbusConn.sendWithReply(msg); if (reply.type() == TQT_DBusMessage::ReplyMessage) { return true;