1
/* This file is part of the KDE project
2
Copyright (C) 2006 Kevin Ottens <ervin@kde.org>
3
Copyright (C) 2008-2010 Dario Freddi <drf@kde.org>
4
Copyright (C) 2010 Alejandro Fiestas <alex@eyeos.org>
5
Copyright (C) 2010 Lukas Tinkl <ltinkl@redhat.com>
7
This library is free software; you can redistribute it and/or
8
modify it under the terms of the GNU Library General Public
9
License version 2 as published by the Free Software Foundation.
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Library General Public License for more details.
16
You should have received a copy of the GNU Library General Public License
17
along with this library; see the file COPYING.LIB. If not, write to
18
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
Boston, MA 02110-1301, USA.
23
#include "powerdevilupowerbackend.h"
25
#include <qtextstream.h>
29
#include <KPluginFactory>
30
#include <KAuth/Action>
32
#include "xrandrbrightness.h"
33
#include "upowersuspendjob.h"
35
#define HELPER_ID "org.kde.powerdevil.backlighthelper"
37
PowerDevilUPowerBackend::PowerDevilUPowerBackend(QObject* parent)
38
: BackendInterface(parent),
39
m_brightNessControl(0),
40
m_lidIsPresent(false), m_lidIsClosed(false), m_onBattery(false)
44
PowerDevilUPowerBackend::~PowerDevilUPowerBackend()
46
delete m_brightNessControl;
49
bool PowerDevilUPowerBackend::isAvailable()
51
if (!QDBusConnection::systemBus().interface()->isServiceRegistered(UPOWER_SERVICE)) {
52
// Is it pending activation?
53
kDebug() << "UPower service, " << UPOWER_SERVICE << ", is not registered on the bus. Trying to find out if it is activated.";
54
QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus",
55
"/org/freedesktop/DBus",
56
"org.freedesktop.DBus",
57
"ListActivatableNames");
59
QDBusPendingReply< QStringList > reply = QDBusConnection::systemBus().asyncCall(message);
60
reply.waitForFinished();
62
if (reply.isValid()) {
63
if (reply.value().contains(UPOWER_SERVICE)) {
64
kDebug() << "UPower was found, activating service...";
65
QDBusConnection::systemBus().interface()->startService(UPOWER_SERVICE);
68
kDebug() << "UPower cannot be found on this system.";
72
kWarning() << "Could not request activatable names to DBus!";
80
void PowerDevilUPowerBackend::init()
83
if (!QDBusConnection::systemBus().interface()->isServiceRegistered(UPOWER_SERVICE)) {
85
QDBusConnection::systemBus().interface()->startService(UPOWER_SERVICE);
88
m_upowerInterface = new OrgFreedesktopUPowerInterface(UPOWER_SERVICE, "/org/freedesktop/UPower", QDBusConnection::systemBus(), this);
89
m_kbdBacklight = new OrgFreedesktopUPowerKbdBacklightInterface(UPOWER_SERVICE, "/org/freedesktop/UPower/KbdBacklight", QDBusConnection::systemBus(), this);
90
m_brightNessControl = new XRandrBrightness();
93
setCapabilities(SignalResumeFromSuspend);
97
connect(m_upowerInterface, SIGNAL(Changed()), this, SLOT(slotPropertyChanged()));
98
connect(m_upowerInterface, SIGNAL(DeviceAdded(const QString &)), this, SLOT(slotDeviceAdded(const QString &)));
99
connect(m_upowerInterface, SIGNAL(DeviceRemoved(const QString &)), this, SLOT(slotDeviceRemoved(const QString &)));
100
connect(m_upowerInterface, SIGNAL(DeviceChanged(const QString &)), this, SLOT(slotDeviceChanged(const QString &)));
102
// Brightness Controls available
103
BrightnessControlsList controls;
104
controls.insert(QLatin1String("LVDS1"), Screen);
106
if (m_kbdBacklight->isValid())
107
controls.insert(QLatin1String("KBD"), Keyboard);
109
if (!controls.isEmpty()) {
110
m_cachedBrightness = brightness(Screen);
111
kDebug() << "current screen brightness: " << m_cachedBrightness;
114
// Supported suspend methods
115
SuspendMethods supported = UnknownSuspendMethod;
117
if (m_upowerInterface->canSuspend()) {
118
kDebug() << "Can suspend";
122
if (m_upowerInterface->canHibernate()) {
123
kDebug() << "Can hibernate";
128
connect(m_upowerInterface, SIGNAL(Resuming()), this, SIGNAL(resumeFromSuspend()));
131
QList<RecallNotice> recallList;
132
foreach(OrgFreedesktopUPowerDeviceInterface * upowerDevice, m_devices) {
133
if (upowerDevice->type() == 2 && upowerDevice->powerSupply()) {
134
QString udi = upowerDevice->path();
135
setCapacityForBattery(udi, qRound(upowerDevice->capacity())); // acknowledge capacity
137
if (upowerDevice->recallNotice()) { // check for recall notices
139
notice.batteryId = udi;
140
notice.url = upowerDevice->recallUrl();
141
notice.vendor = upowerDevice->recallVendor();
143
recallList.append(notice);
147
if (!recallList.isEmpty())
148
setRecallNotices(recallList);
151
setBackendIsReady(controls, supported);
154
void PowerDevilUPowerBackend::brightnessKeyPressed(PowerDevil::BackendInterface::BrightnessKeyType type)
156
BrightnessControlsList controls = brightnessControlsAvailable();
157
QList<QString> screenControls = controls.keys(Screen);
159
if (screenControls.isEmpty()) {
160
return; // ignore as we are not able to determine the brightness level
163
float currentBrightness = brightness(Screen);
165
if (qFuzzyCompare(currentBrightness, m_cachedBrightness)) {
167
if (type == Increase) {
168
newBrightness = qMin(100.0f, currentBrightness + 10);
170
newBrightness = qMax(0.0f, currentBrightness - 10);
173
if (setBrightness(newBrightness, Screen)) {
174
newBrightness = brightness(Screen);
175
if (!qFuzzyCompare(newBrightness, m_cachedBrightness)) {
176
m_cachedBrightness = newBrightness;
177
onBrightnessChanged(Screen, m_cachedBrightness);
181
m_cachedBrightness = currentBrightness;
185
float PowerDevilUPowerBackend::brightness(PowerDevil::BackendInterface::BrightnessControlType type) const
189
if (type == Screen) {
190
if (m_brightNessControl->isSupported()) {
191
//kDebug() << "Calling xrandr brightness";
192
result = m_brightNessControl->brightness();
194
//kDebug() << "Falling back to helper to get brightness";
195
KAuth::Action action("org.kde.powerdevil.backlighthelper.brightness");
196
action.setHelperID(HELPER_ID);
197
KAuth::ActionReply reply = action.execute();
198
if (reply.succeeded()) {
199
result = reply.data()["brightness"].toFloat();
200
//kDebug() << "org.kde.powerdevil.backlighthelper.brightness succeeded: " << reply.data()["brightness"];
203
kWarning() << "org.kde.powerdevil.backlighthelper.brightness failed";
206
kDebug() << "Screen brightness: " << result;
207
} else if (type == Keyboard) {
208
kDebug() << "Kbd backlight brightness: " << m_kbdBacklight->GetBrightness();
209
result = m_kbdBacklight->GetBrightness() / m_kbdBacklight->GetMaxBrightness() * 100;
215
bool PowerDevilUPowerBackend::setBrightness(float brightnessValue, PowerDevil::BackendInterface::BrightnessControlType type)
217
if (type == Screen) {
218
kDebug() << "set screen brightness: " << brightnessValue;
219
if (m_brightNessControl->isSupported()) {
220
m_brightNessControl->setBrightness(brightnessValue);
222
//kDebug() << "Falling back to helper to set brightness";
223
KAuth::Action action("org.kde.powerdevil.backlighthelper.setbrightness");
224
action.setHelperID(HELPER_ID);
225
action.addArgument("brightness", brightnessValue);
226
KAuth::ActionReply reply = action.execute();
227
if (reply.failed()) {
228
kWarning() << "org.kde.powerdevil.backlighthelper.setbrightness failed";
234
} else if (type == Keyboard) {
235
kDebug() << "set kbd backlight: " << brightnessValue;
236
m_kbdBacklight->SetBrightness(brightnessValue / 100 * m_kbdBacklight->GetMaxBrightness());
243
KJob* PowerDevilUPowerBackend::suspend(PowerDevil::BackendInterface::SuspendMethod method)
245
return new UPowerSuspendJob(m_upowerInterface, method, supportedSuspendMethods());
248
void PowerDevilUPowerBackend::enumerateDevices()
250
m_lidIsPresent = m_upowerInterface->lidIsPresent();
251
m_lidIsClosed = m_upowerInterface->lidIsClosed();
252
m_onBattery = m_upowerInterface->onBattery();
254
QList<QDBusObjectPath> deviceList = m_upowerInterface->EnumerateDevices();
255
foreach (const QDBusObjectPath & device, deviceList)
256
slotDeviceAdded(device.path());
259
setAcAdapterState(Unplugged);
261
setAcAdapterState(Plugged);
264
void PowerDevilUPowerBackend::slotDeviceAdded(const QString & device)
266
OrgFreedesktopUPowerDeviceInterface * upowerDevice =
267
new OrgFreedesktopUPowerDeviceInterface(UPOWER_SERVICE, device, QDBusConnection::systemBus(), this);
268
m_devices.insert(device, upowerDevice);
273
void PowerDevilUPowerBackend::slotDeviceRemoved(const QString & device)
275
OrgFreedesktopUPowerDeviceInterface * upowerDevice = m_devices.take(device);
282
void PowerDevilUPowerBackend::slotDeviceChanged(const QString & /*device*/)
287
void PowerDevilUPowerBackend::updateDeviceProps()
289
qlonglong remainingTime = 0;
291
foreach(OrgFreedesktopUPowerDeviceInterface * upowerDevice, m_devices) {
292
if ((upowerDevice->type() == 2 || upowerDevice->type() == 3) && upowerDevice->powerSupply()) {
293
if (upowerDevice->state() == 1) // charging
294
remainingTime += upowerDevice->timeToFull();
295
else if (upowerDevice->state() == 2) //discharging
296
remainingTime += upowerDevice->timeToEmpty();
300
setBatteryRemainingTime(remainingTime * 1000);
303
void PowerDevilUPowerBackend::slotPropertyChanged()
305
// check for lid button changes
306
if (m_lidIsPresent) {
307
bool lidIsClosed = m_upowerInterface->lidIsClosed();
308
if (lidIsClosed != m_lidIsClosed) {
310
setButtonPressed(LidClose);
312
setButtonPressed(LidOpen);
314
m_lidIsClosed = lidIsClosed;
317
// check for AC adapter changes
318
bool onBattery = m_upowerInterface->onBattery();
319
if (m_onBattery != onBattery) {
321
setAcAdapterState(Unplugged);
323
setAcAdapterState(Plugged);
326
m_onBattery = onBattery;
329
#include "powerdevilupowerbackend.moc"