/************************************************************************** * Copyright (C) 2006-2007 by Danny Kukawka * * , * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of version 2 of the GNU General Public License * * as published by the Free Software Foundation. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ /*! * \file hardware.cpp * \brief In this file can be found the hardware information related code. * \author Danny Kukawka, , * \date 2006-2007 */ // include global header #include // include QT header #include #include // keycode definitions #include // include own header #include "hardware.h" #include "tdepowersave_debug.h" #include "privileges.h" // #define USE_EVENT_DEVICES_DIRECTLY 1 /*! The default constructor of the class HardwareInfo */ HardwareInfo::HardwareInfo() { kdDebugFuncIn(trace); // init members acadapter = true; lidclose = false; laptop = false; brightness = false; brightness_in_hardware = false; schedPowerSavings = false; sessionIsActive = true; // assume as first we are active // initialize connection to the TDE hardware library m_hwdevices = TDEGlobal::hardwareDevices(); connect(m_hwdevices, TQT_SIGNAL(hardwareUpdated(TDEGenericDevice*)), this, TQT_SLOT(processHardwareChangedEvent(TDEGenericDevice*))); #ifdef USE_EVENT_DEVICES_DIRECTLY connect(m_hwdevices, TQT_SIGNAL(eventDeviceKeyPressed(unsigned int, TDEEventDevice*)), this, TQT_SLOT(processKeyPressEvent(unsigned int, TDEEventDevice*))); #endif // update everything the first time update_info_ac_changed = true; update_info_cpufreq_policy_changed = true; update_info_primBattery_changed = true; currentCPUFreqPolicy = UNKNOWN_CPUFREQ; primaryBatteriesWarnLevel = 12; primaryBatteriesLowLevel = 7; primaryBatteriesCriticalLevel = 2; allUDIs = TQStringList(); consoleKitSession = TQString(); BatteryList.setAutoDelete( true ); // the list owns the objects primaryBatteries = new BatteryCollection(BAT_PRIMARY); setPrimaryBatteriesWarningLevel(); // force default settings // connect to D-Bus and HAL dbus_HAL = new dbusInterface(); if (dbus_HAL->isConnectedToDBUS()) { dbus_terminated = false; } else { kdError() << "Could not connect to D-Bus & HAL" << endl; } checkConsoleKitSession(); checkPowermanagement(); checkIsLaptop(); checkBrightness(); checkCPUFreq(); // getSchedPowerSavings(); checkSuspend(); intialiseHWInfo(); updatePrimaryBatteries(); kdDebugFuncOut(trace); } /*! The default desctuctor of the class HardwareInfo */ HardwareInfo::~HardwareInfo() { kdDebugFuncIn(trace); kdDebugFuncOut(trace); } /*! * This funtion is used to reinit all hardware information. * \return Boolean with result of the call * \retval true if reinit HW infos correct * \retval false if not */ bool HardwareInfo::reinitHardwareInfos () { kdDebugFuncIn(trace); /* first cleanup */ acadapter = true; lidclose = false; laptop = false; brightness = false; has_APM = false; has_ACPI = false; update_info_ac_changed = true; update_info_cpufreq_policy_changed = true; update_info_primBattery_changed = true; allUDIs = TQStringList(); BatteryList.clear(); primaryBatteries = new BatteryCollection(BAT_PRIMARY); /* reinit hardware data */ checkPowermanagement(); checkIsLaptop(); checkBrightness(); checkCPUFreq(); checkSuspend(); intialiseHWInfo(); // getSchedPowerSavings(); updatePrimaryBatteries(); kdDebugFuncOut(trace); return true; } /*! * This funtion is used to parse changed hardware nofifications from the TDE hardware library * \param device a \ref TDEGenericDevice* which should be processed */ void HardwareInfo::processHardwareChangedEvent (TDEGenericDevice* device) { kdDebugFuncIn(trace); if (allUDIs.contains( device->uniqueID() )) { if (device->type() == TDEGenericDeviceType::PowerSupply) { TQTimer::singleShot(50, this, TQT_SLOT(checkACAdapterState())); } else if (device->type() == TDEGenericDeviceType::Battery) { // this is a battery event updateBatteryValues(device); } else if (device->type() == TDEGenericDeviceType::Event) { TDEEventDevice* edevice = dynamic_cast(device); if (edevice) { if (edevice->eventType() == TDEEventDeviceType::ACPILidSwitch) { TQTimer::singleShot(50, this, TQT_SLOT(checkLidcloseState())); } } } else if (device->type() == TDEGenericDeviceType::Backlight) { TQTimer::singleShot(50, this, TQT_SLOT(checkBrightness())); } // TODO: add needed code } else { kdDebug() << "unmonitored device changed: " << device->uniqueID() << endl; } kdDebugFuncOut(trace); } /*! * This funtion is used to parse changed hardware nofifications from the TDE hardware library * \param keycode a keycode which should be processed * \param edevice the \ref TDEEventDevice* from whence the keypress originated */ void HardwareInfo::processKeyPressEvent(unsigned int keycode, TDEEventDevice* edevice) { kdDebugFuncIn(trace); // FIXME // How can I get specific button press/release information (instead of just "something happened to the button") from the TDE hardware library? // TODO: Check if we really need to monitor this events. We get maybe also // HAL_PROPERTY_CHANGED event for the key // if (message.startsWith("ButtonPressed")) { kdDebug() << "ButtonPressed event from TDE HW library " << endl; if (((edevice->eventType() == TDEEventDeviceType::ACPIPowerButton) || (edevice->eventType() == TDEEventDeviceType::ACPIOtherInput)) && (keycode == KEY_POWER)) { TQTimer::singleShot(50, this, TQT_SLOT(emitPowerButtonPressed())); } else if (((edevice->eventType() == TDEEventDeviceType::ACPISleepButton) || (edevice->eventType() == TDEEventDeviceType::ACPIOtherInput)) && (keycode == KEY_SLEEP)) { TQTimer::singleShot(50, this, TQT_SLOT(emitSleepButtonPressed())); } else if (((edevice->eventType() == TDEEventDeviceType::ACPISuspendButton) || (edevice->eventType() == TDEEventDeviceType::ACPIOtherInput)) && (keycode == KEY_SUSPEND)) { TQTimer::singleShot(50, this, TQT_SLOT(emitS2diskButtonPressed())); // } else if (value.startsWith("brightness-")) { // if (!brightness_in_hardware && value.endsWith("-up")) // TQTimer::singleShot(50, this, TQT_SLOT(brightnessUpPressed())); // else if (!brightness_in_hardware && value.endsWith("-down")) // TQTimer::singleShot(50, this, TQT_SLOT(brightnessDownPressed())); } // } else { // kdDebug() << "Unmonitored HAL_CONDITION: " << message << " : " << value << endl; // } kdDebugFuncOut(trace); } /*! * This funtion is used to parse a message from D-Bus for the different * messagetypes and events. * \param type a \ref msg_type which should be parse/processed * \param message the message * \param value an optional message value as e.g. message string */ void HardwareInfo::processMessage (msg_type type, TQString message, TQString value) { kdDebugFuncIn(trace); switch(type) { case ACPI_EVENT: // we don't handle acpi events here atm break; case HAL_DEVICE: // --> we can maybe ignore these events except for batteries, not shure atm int _type; if (message.startsWith("DeviceAdded")) { if (checkIfHandleDevice(value, &_type)) { switch (_type) { case BATTERY: case AC_ADAPTER: case BUTTON_SLEEP: case BUTTON_POWER: case LID: // TODO: handle code if needed actually not break; case LAPTOP_PANEL: checkBrightness(); break; default: kdDebug() << "New device added Device udi: " << value << "type: " << _type << endl; break; } } } else if (message.startsWith("DeviceRemoved")) { if (allUDIs.contains(value)) { if (checkIfHandleDevice(value, &_type)) { switch (_type) { case BATTERY: case AC_ADAPTER: case BUTTON_SLEEP: case BUTTON_POWER: case LID: // TODO: handle code if needed break; case LAPTOP_PANEL: checkBrightness(); break; default: kdDebug() << "Couldn't handle unknown device" << endl; break; } } } else { kdDebug() << "Not monitored device removed: " << value << endl; } } else { kdDebug() << "Unknown HAL_DEVICE message: " << message << endl; } break; case CONSOLEKIT_SESSION_ACTIVE: if (!message.isEmpty() && !value.isEmpty()) { if (message == consoleKitSession) { if (value == "1") { sessionIsActive = true; } else { sessionIsActive = false; } TQTimer::singleShot(50, this, TQT_SLOT(emitSessionActiveState())); } else { if (trace) kdDebug() << "CONSOLEKIT_SESSION_ACTIVE: not our session" << endl; } } break; case POLICY_POWER_OWNER_CHANGED: if (message.startsWith("NOW_OWNER")) { // TODO: add code } else if (message.startsWith("OTHER_OWNER")){ // TODO: add code } break; default: kdDebug() << "Recieved unknown package type: " << type << endl; break; } kdDebugFuncOut(trace); } /*! * This TQT_SLOT is used to fetch the resume signal and multiplex. If needed some * actions after resume, do this here. * \param result integer with the result of the resume/suspend */ void HardwareInfo::handleResumeSignal (int result) { if (trace) kdDebug() << funcinfo << "IN: " << "(int result: " << result << ")"<< endl; if (result == -1) { // check if time since suspend is higher than 6 hours, // the magic D-Bus timeout for pending calls if (calledSuspend.elapsed() > 21600000) { emit resumed(INT_MAX); } } else { emit resumed(result); } calledSuspend = TQTime(); kdDebugFuncOut(trace); } /*! * This function checks the session for the running TDEPowersave instance * \return Boolean with result of operation * \retval true if the query/check could get finished * \retval false on every error */ bool HardwareInfo::checkConsoleKitSession () { kdDebugFuncIn(trace); bool retval = false; if (dbus_HAL->isConnectedToDBUS()) { char *reply; char *cookie = getenv("XDG_SESSION_COOKIE"); if (cookie == NULL) { kdDebug() << "Could not get XDG_SESSION_COOKIE from environment" << endl; sessionIsActive = true; } else { if (dbus_HAL->dbusSystemMethodCall( CK_SERVICE, CK_MANAGER_OBJECT, CK_MANAGER_IFACE, "GetSessionForCookie", &reply, DBUS_TYPE_OBJECT_PATH, DBUS_TYPE_STRING, &cookie, DBUS_TYPE_INVALID)) { if (trace) kdDebug() << "GetSessionForCookie returned: " << reply << endl; if (reply != NULL) { dbus_bool_t i_reply; consoleKitSession = reply; if (dbus_HAL->dbusSystemMethodCall( CK_SERVICE, consoleKitSession, CK_SESSION_IFACE, "IsActive", &i_reply, DBUS_TYPE_BOOLEAN, DBUS_TYPE_INVALID)) { sessionIsActive = ((i_reply != 0) ? true: false); if (trace) kdDebug() << "IsActive returned: " << sessionIsActive << endl; retval = true; } else { kdError() << "Could get session cookie and session name, but not " << "but not the status of the session. Assume for now " << "the Session is inactive!" << endl; sessionIsActive = false; } } } } } kdDebugFuncOut(trace); return retval; } /*! * This function check for a given UDI, if we should handle a device * \param _udi TQString with the UDI of the device * \param *type pointer to a integer to return the type of the device, see \ref device_type * \return Boolean with info if we should handle the device. * \retval true if we should handle * \retval false if not */ bool HardwareInfo::checkIfHandleDevice ( TQString _udi, int *type) { kdDebugFuncIn(trace); TQStringList _cap; bool ret = true; TDEGenericDevice* hwdevice = m_hwdevices->findByUniqueID(_udi); if (hwdevice) { TDEGenericDeviceType::TDEGenericDeviceType devtype = hwdevice->type(); if (devtype == TDEGenericDeviceType::PowerSupply) { *type = BATTERY; } else if (devtype == TDEGenericDeviceType::Event) { TDEEventDevice* edevice = dynamic_cast(hwdevice); if (edevice) { if (edevice->eventType() == TDEEventDeviceType::ACPILidSwitch) { *type = LID; } else if (edevice->eventType() == TDEEventDeviceType::ACPIPowerButton) { *type = BUTTON_POWER; } else if (edevice->eventType() == TDEEventDeviceType::ACPISleepButton) { *type = BUTTON_SLEEP; } else { ret = false; } } else { ret = false; } } else if (devtype == TDEGenericDeviceType::Battery) { *type = BATTERY; } else if (devtype == TDEGenericDeviceType::Backlight) { *type = LAPTOP_PANEL; } else { ret = false; kdDebug() << "Device with type " << devtype << " unhandled" << endl; } } else { ret = false; } if (!ret) *type = UNKNOWN_DEVICE; kdDebugFuncOut(trace); return ret; } // --> set some values for devices /*! * This function set the warning level for the primary battery collection * If all give param are -1 or not set this function force the current * settings to the primary battery collection. * \param _warn value for the state BAT_WARN or -1 * \param _low value for the state BAT_LOW or -1 * \param _crit value for the state BAT_CRIT or -1 */ void HardwareInfo::setPrimaryBatteriesWarningLevel (int _warn, int _low, int _crit ) { if (trace) kdDebug() << funcinfo << "IN: " << "warn: " << _warn << " low: " << _low << " crit: " << _crit << endl; if (_warn > -1 && _low > -1 && _crit > -1 ){ primaryBatteriesWarnLevel = _warn; primaryBatteriesLowLevel = _low; primaryBatteriesCriticalLevel = _crit; } if (primaryBatteries) { primaryBatteries->setWarnLevel( primaryBatteriesWarnLevel ); primaryBatteries->setLowLevel( primaryBatteriesLowLevel ); primaryBatteries->setCritLevel( primaryBatteriesCriticalLevel ); if (!BatteryList.isEmpty()) { primaryBatteries->refreshInfo( BatteryList, true ); } } kdDebugFuncOut(trace); } // --> init HW information section -- START <--- /*! * The function checks if the machine is a laptop. */ void HardwareInfo::checkIsLaptop () { kdDebugFuncIn(trace); TQString ret; TDERootSystemDevice* rdevice = m_hwdevices->rootSystemDevice(); if (rdevice->formFactor() == TDESystemFormFactor::Laptop) { laptop = true; } else { laptop = false; } kdDebugFuncOut(trace); } /*! * The function checks whether the machine support ACPI/APM/PMU or not. */ void HardwareInfo::checkPowermanagement() { kdDebugFuncIn(trace); TQString ret; has_APM = false; has_ACPI = false; has_PMU = false; TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::OtherACPI); if (hwlist.count() > 0) { has_ACPI = true; } // FIXME // Do we even need to detect APM and PMU devices in the year 2012?!? kdDebugFuncOut(trace); } /*! * The function checks whether the machine can suspend/standby. */ void HardwareInfo::checkSuspend() { kdDebugFuncIn(trace); suspend_states = SuspendStates(); suspend_states.suspend2ram = false; suspend_states.suspend2ram_can = false; suspend_states.suspend2ram_allowed = -1; suspend_states.suspend2disk = false; suspend_states.suspend2disk_can = false; suspend_states.suspend2disk_allowed = -1; suspend_states.standby = false; suspend_states.standby_can = false; suspend_states.standby_allowed = -1; TDERootSystemDevice* rdevice = m_hwdevices->rootSystemDevice(); TDESystemPowerStateList powerStates = rdevice->powerStates(); if (powerStates.count() > 0) { TDESystemPowerStateList::iterator it; for (it = powerStates.begin(); it != powerStates.end(); ++it) { if ((*it) == TDESystemPowerState::Active) { // } if ((*it) == TDESystemPowerState::Standby) { suspend_states.standby = true; suspend_states.standby_allowed = rdevice->canStandby(); suspend_states.standby_can = suspend_states.standby_allowed & suspend_states.standby; } if ((*it) == TDESystemPowerState::Suspend) { suspend_states.suspend2ram = true; suspend_states.suspend2ram_allowed = rdevice->canSuspend(); suspend_states.suspend2ram_can = suspend_states.suspend2ram_allowed & suspend_states.suspend2ram; } if ((*it) == TDESystemPowerState::Hibernate) { suspend_states.suspend2disk = true; suspend_states.suspend2disk_allowed = rdevice->canHibernate(); suspend_states.suspend2disk_can = suspend_states.suspend2disk_allowed & suspend_states.suspend2disk; } if ((*it) == TDESystemPowerState::PowerOff) { // } } } kdDebugFuncOut(trace); } /*! * The function checks whether the machine support CPU frequency changes */ void HardwareInfo::checkCPUFreq() { kdDebugFuncIn(trace); // Use the first CPU in the list; permissions are probably the same across all CPUs TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::CPU); TDEGenericDevice *hwdevice; hwdevice = hwlist.first(); TDECPUDevice *cpudevice = static_cast(hwdevice); if (!cpudevice->scalingDriver().isNull()) { cpuFreq = true; cpuFreqAllowed = cpudevice->canSetGovernor(); checkCurrentCPUFreqPolicy(); } else { cpuFreq = false; } kdDebugFuncOut(trace); } /*! * The function check the currently selected CPU Frequency policy * \return the current policy */ cpufreq_type HardwareInfo::checkCurrentCPUFreqPolicy() { kdDebugFuncIn(trace); // Use the first CPU in the list; permissions are probably the same across all CPUs TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::CPU); TDEGenericDevice *hwdevice; hwdevice = hwlist.first(); TDECPUDevice *cpudevice = static_cast(hwdevice); TQString gov = cpudevice->governor(); cpufreq_type _current = UNKNOWN_CPUFREQ; if (cpuFreq) { if (!gov.isNull()) { kdDebug() << "got CPU Freq gov: " << gov << endl; if ((gov == "ondemand") || (gov == "userspace") || (gov == "conservative")) { _current = DYNAMIC; } else if (gov == "powersave") { _current = POWERSAVE; } else if (gov =="performance") { _current = PERFORMANCE; } else { kdError() << "Got unknown CPUFreq Policy back: " << gov << endl; } cpuFreqGovernor = gov; } else { kdWarning() << "Could not get information about current governor" << endl; } } else { kdWarning() << "CPU Frequency interface not supported by machine or HAL" << endl; } if (_current != currentCPUFreqPolicy) { currentCPUFreqPolicy = _current; update_info_cpufreq_policy_changed = true; emit currentCPUFreqPolicyChanged(); } else { update_info_cpufreq_policy_changed = false; } kdDebugFuncOut(trace); return currentCPUFreqPolicy; } /*! * The function checks whether the machine provide a brightness interface and init * (if needed) brightness information. */ void HardwareInfo::checkBrightness() { kdDebugFuncIn(trace); TQStringList devices; brightness = false; currentBrightnessLevel = -1; availableBrightnessLevels = -1; // Use the first backlight in the list TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::Backlight); TDEGenericDevice *hwdevice; hwdevice = hwlist.first(); TDEBacklightDevice *backlightdevice = static_cast(hwdevice); if (backlightdevice) { udis.insert("laptop_panel", new TQString( hwdevice->uniqueID() )); if (!allUDIs.contains( hwdevice->uniqueID() )) { allUDIs.append( hwdevice->uniqueID() ); } availableBrightnessLevels = backlightdevice->brightnessSteps(); if (availableBrightnessLevels > 1) { brightnessAllowed = backlightdevice->canSetBrightness(); brightness = true; // get the current level via GetBrightness checkCurrentBrightness(); } else { availableBrightnessLevels = -1; } } else { udis.remove("laptop_panel"); kdDebug() << "no device with category laptop_panel found" << endl; kdDebugFuncOut(trace); return; } kdDebugFuncOut(trace); } /*! * The function check the current brigthness */ void HardwareInfo::checkCurrentBrightness() { kdDebugFuncIn(trace); if (brightness) { // Use the first backlight in the list TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::Backlight); TDEGenericDevice *hwdevice; hwdevice = hwlist.first(); TDEBacklightDevice *backlightdevice = static_cast(hwdevice); if (backlightdevice) { currentBrightnessLevel = backlightdevice->rawBrightness(); } } kdDebugFuncOut(trace); } /*! * The function initialise the hardware information and collect all * initial information from HAL. * \return boolean with result of the operation * \retval true if successful * \retval false else, if a error occurs */ bool HardwareInfo::intialiseHWInfo() { kdDebugFuncIn(trace); TDEGenericDevice *hwdevice; TDEGenericHardwareList hwlist; hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::PowerSupply); for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) { udis.insert("acadapter", new TQString( hwdevice->uniqueID() )); if (!allUDIs.contains( hwdevice->uniqueID() )) { allUDIs.append( hwdevice->uniqueID() ); } checkACAdapterState(); } hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::Event); for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) { TDEEventDevice* edevice = dynamic_cast(hwdevice); if (edevice->eventType() == TDEEventDeviceType::ACPILidSwitch) { udis.insert("lidclose", new TQString( hwdevice->uniqueID() )); if (!allUDIs.contains( hwdevice->uniqueID() )) { allUDIs.append( hwdevice->uniqueID() ); } checkLidcloseState(); } } // find batteries and fill battery information hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::Battery); for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) { if (!allUDIs.contains( hwdevice->uniqueID() )) { allUDIs.append( hwdevice->uniqueID() ); } BatteryList.append( new Battery( hwdevice->uniqueID() ) ); } // connect to signals for primary batteries: Battery *bat; for (bat = BatteryList.first(); bat; bat = BatteryList.next() ) { if (bat->getType() == BAT_PRIMARY) { connect(bat, TQT_SIGNAL(changedBattery()),this, TQT_SLOT(updatePrimaryBatteries())); } } kdDebugFuncOut(trace); return true; } /*! * The function/TQT_SLOT checks the state of the AC adapter. */ void HardwareInfo::checkACAdapterState() { kdDebugFuncIn(trace); if ( udis["acadapter"] ) { bool _state; TDEMainsPowerDevice* mdevice = dynamic_cast(m_hwdevices->findByUniqueID(*udis["acadapter"])); if (mdevice) { _state = mdevice->online(); if (_state != acadapter) { acadapter = _state; update_info_ac_changed = true; emit ACStatus( acadapter ); } else { update_info_ac_changed = false; } } else { // we use true as default e.g. for workstations acadapter = true; } } kdDebugFuncOut(trace); } /*! * The function checks the state of the Lidclose button. */ void HardwareInfo::checkLidcloseState() { kdDebugFuncIn(trace); if ( udis["lidclose"] ) { bool _state; TDEEventDevice* edevice = dynamic_cast(m_hwdevices->findByUniqueID(*udis["lidclose"])); if (edevice) { _state = (edevice->activeSwitches() & TDESwitchType::Lid); if (_state != lidclose) { lidclose = _state; emit lidclosetStatus( lidclose ); } } else { lidclose = false; } } kdDebugFuncOut(trace); } /*! * This funtion is used to call a update of a battery value for a given * UDI and the given changed property * \param udi TQString with the UDI of the battery * \param property TQString with the changed property */ void HardwareInfo::updateBatteryValues (TDEGenericDevice* device) { kdDebugFuncIn(trace); if (device && allUDIs.contains( device->uniqueID() )) { // find effected battery object Battery *bat; for (bat = BatteryList.first(); bat; bat = BatteryList.next() ) { if (device->uniqueID().startsWith( bat->getUdi())) { TDEBatteryDevice* bdevice = dynamic_cast(device); if (bdevice) { // found a battery with udi bat->updateProperty(bdevice); } } } } else { kdDebug() << "UDI is empty or not in the list of monitored devices " << endl; } kdDebugFuncOut(trace); return; } /*! * This function refresh the information for the primary battery collection. */ void HardwareInfo::updatePrimaryBatteries () { kdDebugFuncIn(trace); if (!BatteryList.isEmpty()) { if (primaryBatteries->getNumBatteries() < 1) { setPrimaryBatteriesWarningLevel(); primaryBatteries->refreshInfo( BatteryList ); connect(primaryBatteries, TQT_SIGNAL(batteryChanged()), this, TQT_SLOT(setPrimaryBatteriesChanges())); connect(primaryBatteries, TQT_SIGNAL(batteryWarnState(int,int)), this, TQT_SLOT(emitBatteryWARNState(int,int))); } else { setPrimaryBatteriesWarningLevel(); primaryBatteries->refreshInfo( BatteryList ); } } else { primaryBatteries = new BatteryCollection(BAT_PRIMARY); } kdDebugFuncOut(trace); } /*! * This function set the change status for the primary battery collection */ void HardwareInfo::setPrimaryBatteriesChanges () { kdDebugFuncIn(trace); update_info_primBattery_changed = true; emit primaryBatteryChanged(); kdDebugFuncOut(trace); } /*! * This slot emit a signal if a warning state of a battery reached */ void HardwareInfo::emitBatteryWARNState (int type, int state) { kdDebugFuncIn(trace); if (type == BAT_PRIMARY) emit primaryBatteryChanged(); else emit generalDataChanged(); emit batteryWARNState(type, state); kdDebugFuncOut(trace); } // --> init HW information section -- END <--- // --> HAL method call (trigger actions) section -- START <--- /*! * Function to trigger a suspend via HAL * \param suspend enum of suspend_type with the requested suspend * \return boolean with result of the operation * \retval true if successful * \retval false else, if a error occurs */ bool HardwareInfo::suspend( suspend_type suspend ) { kdDebugFuncIn(trace); calledSuspend = TQTime(); TDERootSystemDevice* rdevice = m_hwdevices->rootSystemDevice(); if (rdevice) { switch (suspend) { case SUSPEND2DISK: if (suspend_states.suspend2disk && (suspend_states.suspend2disk_allowed != 0)) { if (rdevice->setPowerState(TDESystemPowerState::Hibernate)) { calledSuspend.start(); handleResumeSignal(0); return true; } else { handleResumeSignal(-1); return false; } } else { if ( !suspend_states.suspend2disk ) kdDebug() << "The machine does not support suspend to disk." << endl; else kdWarning() << "Policy forbid user to trigger suspend to disk" << endl; return false; } break; case SUSPEND2RAM: if (suspend_states.suspend2ram && (suspend_states.suspend2ram_allowed != 0)) { if (rdevice->setPowerState(TDESystemPowerState::Suspend)) { calledSuspend.start(); handleResumeSignal(0); return true; } else { handleResumeSignal(-1); return false; } } else { if ( !suspend_states.suspend2ram ) kdDebug() << "The machine does not support suspend to ram." << endl; else kdWarning() << "Policy forbid user to trigger suspend to ram" << endl; return false; } break; case STANDBY: if (suspend_states.standby && (suspend_states.standby_allowed != 0)) { if (rdevice->setPowerState(TDESystemPowerState::Standby)) { calledSuspend.start(); handleResumeSignal(0); return true; } else { handleResumeSignal(-1); return false; } } else { if ( !suspend_states.standby ) kdDebug() << "The machine does not support standby." << endl; else kdWarning() << "Policy forbid user to trigger standby" << endl; return false; } break; default: return false; } } kdDebugFuncOut(trace); return false; } /*! * Function to set brightness via HAL (if supported by hardware) * \param level Integer with the level to set, (range: 0 - \ref availableBrightnessLevels ) * \param percent Integer with the brightness percentage to set * \return boolean with result of the operation * \retval true if successful * \retval false else, if a error occurs */ bool HardwareInfo::setBrightness ( int level, int percent ){ if (trace) kdDebug() << funcinfo << "IN: " << "level: " << level << " percent: " << percent << endl; bool retval = false; if ((level == -1) && (percent >= 0)) { if (percent == 0) { level = 0; } else if (percent >= 98) { level = (availableBrightnessLevels - 1); } else { level = (int)((float)availableBrightnessLevels * ((float)percent/100.0)); if (level > (availableBrightnessLevels -1)) level = availableBrightnessLevels -1; kdDebug() << "percentage mapped to new level: " << level << endl; } } // Use the first backlight in the list TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::Backlight); TDEGenericDevice *hwdevice; hwdevice = hwlist.first(); TDEBacklightDevice *backlightdevice = static_cast(hwdevice); if (backlightdevice) { if (!brightness) { checkBrightness(); } if (!brightness || (level < 0 ) || (level >= availableBrightnessLevels)) { kdError() << "Change brightness or requested level not supported " << endl; } else { if (currentBrightnessLevel == level) { kdDebug() << "Brightness level not changed, requested level == current level" << endl; retval = true; } else { backlightdevice->setRawBrightness(level); retval = true; } } } // check for actual brightness level to be sure everything was set correct checkCurrentBrightness(); kdDebugFuncOut(trace); return retval; } /*! * Function to set the CPU frequency policy via HAL. * \param cpufreq enum of cpufreq_type with the policy to set * \param limit integer with range 0 - 100 (only if cpufreq == DYNAMIC) * \return boolean with result of the operation * \retval true if successful * \retval false else, if a error occurs */ bool HardwareInfo::setCPUFreq ( cpufreq_type cpufreq, int limit ) { if (trace) kdDebug() << funcinfo << "IN: " << "cpufreq_type: " << cpufreq << " limit: " << limit << endl; if (!cpuFreq) { kdError() << "This machine does not support change the CPU Freq via HAL" << endl; return false; } if (cpuFreqAllowed == 0) { kdError() << "Could not set CPU Freq, this not the needed privileges." << endl; return false; } TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::CPU); if (hwlist.count() > 0) { dbus_bool_t consider = (dbus_bool_t) getAcAdapter(); TQStringList dynamic; if (checkCurrentCPUFreqPolicy() == cpufreq) { if (cpufreq == DYNAMIC && !cpuFreqGovernor.startsWith("ondemand")) { kdDebug() << "CPU Freq Policy is already DYNAMIC, but not governor is currently " << "not 'ondemand'. Try to set ondemand governor." << endl; } else { kdDebug() << "Didn't change Policy, was already set." << endl; return true; } } switch (cpufreq) { case PERFORMANCE: if (!setCPUFreqGovernor("performance")) { kdError() << "Could not set CPU Freq to performance policy" << endl; return false; } break; case DYNAMIC: dynamic << "ondemand" << "userspace" << "conservative"; for (TQStringList::Iterator it = dynamic.begin(); it != dynamic.end(); it++){ kdDebug() << "Try to set dynamic CPUFreq to: " << *it << endl; if (setCPUFreqGovernor((*it).latin1())) { kdDebug() << "Set dynamic successful to: " << *it << endl; break; } } #if 0 // FIXME // What does "SetCPUFreqConsiderNice" actually do??!?! // correct set ondemand if (!dbus_HAL->dbusSystemMethodCall( HAL_SERVICE, HAL_COMPUTER_UDI, HAL_CPUFREQ_IFACE, "SetCPUFreqConsiderNice", DBUS_TYPE_BOOLEAN, &consider, DBUS_TYPE_INVALID)) { kdError() << "Couldn't set SetCPUFreqConsiderNice for DYNAMIC" << endl; } #endif // Set performance limits on all CPUs TDEGenericDevice *hwdevice; TDECPUDevice *cpudevice; for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) { cpudevice = static_cast(hwdevice); // set dynamic performance limit // scale the desired limit so that when limit==0 the minFrequency() is used, and when limit==100 the maxFrequency() is used double cpuLimit = cpudevice->maxFrequency() - cpudevice->minFrequency(); cpuLimit = (cpuLimit * limit) / 100.0; cpuLimit = cpudevice->maxFrequency() + cpuLimit; cpudevice->setMaximumScalingFrequency(cpuLimit); } break; case POWERSAVE: if (!setCPUFreqGovernor("powersave")) { kdError() << "Could not set CPU Freq to powersave policy" << endl; return false; } break; default: kdWarning() << "Unknown cpufreq_type: " << cpufreq << endl; return false; } // check if the policy was really set (and emit signal) if (checkCurrentCPUFreqPolicy() == cpufreq) { // update_info_cpufreq_policy_changed = true; // emit currentCPUFreqPolicyChanged(); return true; } else { return false; } } else { return false; } } /*! * Function to set the CPU governor via HAL. * \param governor char * with the name of the governor * \return boolean with result of the operation * \retval true if successful * \retval false else, if a error occurs */ bool HardwareInfo::setCPUFreqGovernor( const char *governor ) { kdDebugFuncIn(trace); int reply; bool ret = true; TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::CPU); TDEGenericDevice *hwdevice; TDECPUDevice *cpudevice; // Set governor on all CPUs for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) { cpudevice = static_cast(hwdevice); cpudevice->setGovernor(governor); if (cpudevice->governor() != governor) { ret = false; } } kdDebugFuncOut(trace); return ret; } /*! * Function to set the powersave mode (incl. e.g. disk settings) via HAL. * \param on boolean which tell if enable/disable powersave mode * \return boolean with result of the operation * \retval true if successful * \retval false else, if a error occurs */ bool HardwareInfo::setPowerSave( bool on ) { kdDebugFuncIn(trace); bool retval = false; // FIXME // Set up power saving to the best of our ability using "raw" functions printf("[FIXME] HardwareInfo::setPowerSave unimplemented!\n\r"); fflush(stdout); kdDebugFuncOut(trace); return retval; } /*! * Function to call GetSchedPowerSavings() via HAL. * \return boolean with result of the operation * \retval true if successful * \retval false else, if a error occurs */ bool HardwareInfo::getSchedPowerSavings() { kdDebugFuncIn(trace); bool returnval = false; // What does the HAL method GetSchedPowerSavings actually do?!?!? kdDebugFuncOut(trace); return returnval; } /*! * Function to call SetSchedPowerSavings() via HAL. Note: this would only work on * Multiprocessor/-core machines. * \return boolean with result of the operation * \retval true if successful * \retval false else, if a error occurs */ bool HardwareInfo::setSchedPowerSavings( bool enable ) { kdDebugFuncIn(trace); bool retval = false; // What does the HAL method SetCPUFreqPerformance actually do?!?!? kdDebugFuncOut(trace); return retval; } // --> HAL method call (trigger actions) section -- END <--- // --> private helper functions/slots to forward/handle events -- START <-- // need this functions to make events from HAL/D-Bus independent // from QT event loop and to allow QT3 D-Bus bindings to get not // blocked by normal KDE/QT (GUI) calls /*! * Function to emit the signal for the Power button. */ void HardwareInfo::emitPowerButtonPressed() { if (sessionIsActive) { emit powerButtonPressed(); } else { kdWarning() << "Session is not active, don't react on power button event!" << endl; } } /*! * Function to emit the signal for the Sleep button. */ void HardwareInfo::emitSleepButtonPressed() { if (sessionIsActive) { emit sleepButtonPressed(); } else { kdWarning() << "Session is not active, don't react on sleep button event!" << endl; } } /*! * Function to emit the signal for the s2disk button. */ void HardwareInfo::emitS2diskButtonPressed() { if (sessionIsActive) { emit s2diskButtonPressed(); } else { kdWarning() << "Session is not active, don't react on suspend2disk button event!" << endl; } } /*! * Function to emit the signal about changes in the session state */ void HardwareInfo::emitSessionActiveState() { if (sessionIsActive) { if (!dbus_HAL->acquiredPolicyPowerInterface()) { dbus_HAL->acquirePolicyPowerIface(); } } else { if (dbus_HAL->acquiredPolicyPowerInterface()) { dbus_HAL->releasePolicyPowerIface(); } } emit desktopSessionIsActive(sessionIsActive); } /*! * Function to set the brightess a step up. * \param percentageStep Integer of next step should get set * \return result of the operation * \retval true if could get set * \retval false else */ bool HardwareInfo::setBrightnessUp(int percentageStep) { kdDebugFuncIn(trace); bool retval = false; checkCurrentBrightness(); if (supportBrightness() && (getCurrentBrightnessLevel() >= 0) && (getCurrentBrightnessLevel() != (getMaxBrightnessLevel()-1))) { int setTo = 0; int minPercStep = 10; int currentPerc = (int)(((float)getCurrentBrightnessLevel()/(float)(getMaxBrightnessLevel()-1))*100.0); if (percentageStep > 0 && (percentageStep <= (100-currentPerc))) { minPercStep = percentageStep; } if ((currentPerc + minPercStep) > 100) { // set to 100 % setTo = getMaxBrightnessLevel() -1; } else { setTo = (int)(((float)(getMaxBrightnessLevel()-1))*(((float)(currentPerc + minPercStep))/100.0)); if ((setTo == getCurrentBrightnessLevel()) && (setTo < (getMaxBrightnessLevel() -1))) { setTo++; } } if (trace) { kdDebug() << "Max: " << getMaxBrightnessLevel() << " Current: " << getCurrentBrightnessLevel() << " minPercStep: " << minPercStep << " currentPerc: " << currentPerc << " setTo: " << setTo << endl; } retval = setBrightness(setTo, -1); } kdDebugFuncOut(trace); return retval; } /*! * Function to set the brightess a step up. * \param percentageStep Integer of next step should get set * \return result of the operation * \retval true if could get set * \retval false else */ bool HardwareInfo::setBrightnessDown(int percentageStep) { kdDebugFuncIn(trace); bool retval = false; checkCurrentBrightness(); if (supportBrightness() && (getCurrentBrightnessLevel() > 0)) { int setTo = 0; int minPercStep = 10; int currentPerc = (int)(((float)getCurrentBrightnessLevel()/(float)(getMaxBrightnessLevel()-1))*100.0); if (percentageStep > 0 && (percentageStep < currentPerc)) { minPercStep = percentageStep; } if ((currentPerc - minPercStep) < 0) { setTo = 0; } else { setTo = (int)(((float)(getMaxBrightnessLevel()-1))*(((float)(currentPerc - minPercStep))/100.0)); if ((setTo == getCurrentBrightnessLevel()) && (setTo > 0)) { setTo--; } } if (trace) { kdDebug() << "Max: " << getMaxBrightnessLevel() << " Current: " << getCurrentBrightnessLevel() << " minPercStep: " << minPercStep << " currentPerc: " << currentPerc << " setTo: " << setTo << endl; } retval = setBrightness(setTo, -1); } kdDebugFuncOut(trace); return retval; } /*! * Function to handle the signal for the brightness up button/key */ void HardwareInfo::brightnessUpPressed() { kdDebugFuncIn(trace); if (brightness) { if (!sessionIsActive) { kdWarning() << "Session is not active, don't react on brightness up key event!" << endl; } else { if (currentBrightnessLevel < availableBrightnessLevels) { setBrightnessUp(); } else { kdWarning() << "Could not set brightness to higher level, it's already set to max." << endl; } } } kdDebugFuncOut(trace); } /*! * Function to handle the signal for the brightness down button/key */ void HardwareInfo::brightnessDownPressed() { kdDebugFuncIn(trace); if (brightness) { if (!sessionIsActive) { kdWarning() << "Session is not active, don't react on brightness down key event!" << endl; } else { if (currentBrightnessLevel > 0) { setBrightnessDown(); } else { kdWarning() << "Could not set brightness to lower level, it's already set to min." << endl; } } } } // --> private helper slots to forward/handle events -- END <-- // --> get private members section -- START <--- /*! * The function return the current state of the ac adapter. * \return boolean with the current state * \retval true if adapter is present/connected or unknown * \retval false if not */ bool HardwareInfo::getAcAdapter() const { return acadapter; } /*! * The function return the current state of the lidclose button. * \return boolean with the current state * \retval true if the lid is closed * \retval false if the lid is opend */ bool HardwareInfo::getLidclose() const { return lidclose; } /*! * The function return the maximal available brightness level * \return Integer with max level or -1 if not supported */ int HardwareInfo::getMaxBrightnessLevel() const { if (brightness) return availableBrightnessLevels; else return -1; } /*! * The function return the current brightness level * \return Integer with max level or -1 if not supported or unkown */ int HardwareInfo::getCurrentBrightnessLevel() const { if (brightness) return currentBrightnessLevel; else return -1; } /*! * The function return the current set CPU Frequency Policy * \return Integer with currently set Policy or -1 if not supported or unkown */ int HardwareInfo::getCurrentCPUFreqPolicy() const { return currentCPUFreqPolicy; } /*! * The function return information if the system support the different * suspend/standby methodes and if the user can call them. * \return struct with information from \ref suspend_states * TODO: check if we maybe should replace this by more different functions */ SuspendStates HardwareInfo::getSuspendSupport() const { return suspend_states; } /*! * The function return a pointer to the battery collection of primary batteries. * \return BatteryCollection with type == PRIMARY */ BatteryCollection* HardwareInfo::getPrimaryBatteries() const { return primaryBatteries; } /*! * The function return all batteries * \return TQPtrList */ TQPtrList HardwareInfo::getAllBatteries() const { return BatteryList; } /*! * The function return the status of \ref laptop. * \return boolean with info if machine is a laptop * \retval true if a laptop * \retval false else/if not a laptop */ bool HardwareInfo::isLaptop() const { return laptop; } /*! * The function return info if there is a working connection to D-Bus and HAL. * This mean if we get hardwareinformation * \return boolean with info if D-Bus and HAL work * \retval true if connected * \retval false if not connected */ bool HardwareInfo::isOnline() const { // FIXME // Is there ANY case where the TDE hardware library would not function? return true; } /*! * The function return the status of \ref has_ACPI. * \return boolean with info if machine support ACPI * \retval true if support ACPI * \retval false else */ bool HardwareInfo::hasACPI() const { return has_ACPI; } /*! * The function return the status of \ref has_APM. * \return boolean with info if machine support APM * \retval true if support APM * \retval false else */ bool HardwareInfo::hasAPM() const { return has_APM; } /*! * The function return the status of \ref has_PMU. * \return boolean with info if machine support PMU * \retval true if support PMU * \retval false else */ bool HardwareInfo::hasPMU() const { return has_PMU; } /*! * The function return the status of \ref brightness. * \return boolean with info if machine support brightness changes via HAL * \retval true if support brightness changes * \retval false else */ bool HardwareInfo::supportBrightness() const { return brightness; } /*! * The function return the status of \ref cpuFreq. * \return boolean with info if machine support change the CPU frequency via HAL * \retval true if support brightness changes * \retval false else */ bool HardwareInfo::supportCPUFreq() const { return cpuFreq; } /*! * The function return the status of \ref sessionIsActive. * \return boolean with info if current desktop session is marked in ConsoleKit as activ * \retval true if the current session is active * \retval false else */ bool HardwareInfo::currentSessionIsActive() const { return sessionIsActive; } /*! * The function return \ref cpuFreqAllowed and tell by this if the user is allowed * to change the CPU Freq. * \return \ref cpuFreqAllowed * \retval 0 allowed * \retval 1 not allowed * \retval -1 unknown */ int HardwareInfo::isCpuFreqAllowed () { // Use the first CPU in the list; permissions are probably the same across all CPUs TDEGenericHardwareList hwlist = m_hwdevices->listByDeviceClass(TDEGenericDeviceType::CPU); TDEGenericDevice *hwdevice; hwdevice = hwlist.first(); TDECPUDevice *cpudevice = static_cast(hwdevice); cpuFreqAllowed = cpudevice->canSetGovernor(); return cpuFreqAllowed; } /*! check if the org.freedesktop.Policy.Power interface has an owner * \return boolean with info if org.freedesktop.Policy.Power interface has an owner or not * \retval true if there is a owner * \retval false else */ bool HardwareInfo::isPolicyPowerIfaceOwned () { return dbus_HAL->isPolicyPowerIfaceOwned(); } // --> get private members section -- END <--- #include "hardware.moc"