From bf29cdd77788f6761ca85f6039abec2589c45194 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sun, 24 Aug 2014 14:16:21 -0400 Subject: [PATCH] power_daemon: Refactor to handle multiple exported power devices. - Each PowerMonitor now exports a set of descriptors rather than only a single one. This allows e.g. PowerButtonMonitor to watch multiple possible button event sources rather than one. This gets power button working again on some hardware that exports multiple ACPI power buttons, but offers no obvious way to determine which one is actually active/being used. In the long term though, it'd be nice to have a well-defined kernel power event interface that an app could subscribe to, rather than having to watch individual devfs descriptors. Thanks to tqh and korli for advice/review. --- src/servers/power/Jamfile | 2 +- src/servers/power/lid_monitor.cpp | 19 +++++------ src/servers/power/lid_monitor.h | 7 ++-- src/servers/power/power_button_monitor.cpp | 39 +++++++++++++++++----- src/servers/power/power_button_monitor.h | 10 +++--- src/servers/power/power_daemon.cpp | 34 ++++++++++++++----- src/servers/power/power_monitor.h | 11 ++++-- 7 files changed, 83 insertions(+), 39 deletions(-) diff --git a/src/servers/power/Jamfile b/src/servers/power/Jamfile index 4027cd541b..00d6155bfa 100644 --- a/src/servers/power/Jamfile +++ b/src/servers/power/Jamfile @@ -10,4 +10,4 @@ Server power_daemon : power_button_monitor.cpp ; -LinkAgainst power_daemon : be [ TargetLibsupc++ ] ; +LinkAgainst power_daemon : be [ TargetLibstdc++ TargetLibsupc++ ] ; diff --git a/src/servers/power/lid_monitor.cpp b/src/servers/power/lid_monitor.cpp index 70b5ac3876..308508162f 100644 --- a/src/servers/power/lid_monitor.cpp +++ b/src/servers/power/lid_monitor.cpp @@ -18,27 +18,26 @@ LidMonitor::LidMonitor() { - fFD = open("/dev/power/acpi_lid/0", O_RDONLY); + int fd = open("/dev/power/acpi_lid/0", O_RDONLY); + if (fd > 0) + fFDs.insert(fd); } LidMonitor::~LidMonitor() { - if (fFD > 0) - close(fFD); + for (std::set::iterator it = fFDs.begin(); it != fFDs.end(); ++it) + close(*it); } void -LidMonitor::HandleEvent() +LidMonitor::HandleEvent(int fd) { - if (fFD <= 0) + uint8 status; + if (read(fd, &status, 1) != 1) return; - uint8 status; - read(fFD, &status, 1); - - if (status == 1) { + if (status == 1) printf("lid status 1\n"); - } } diff --git a/src/servers/power/lid_monitor.h b/src/servers/power/lid_monitor.h index da9ac79433..571aed006e 100644 --- a/src/servers/power/lid_monitor.h +++ b/src/servers/power/lid_monitor.h @@ -17,11 +17,12 @@ public: LidMonitor(); virtual ~LidMonitor(); - virtual void HandleEvent(); + virtual void HandleEvent(int fd); - virtual int FD() const { return fFD; } + virtual const std::set& + FDs() const { return fFDs; } private: - int fFD; + std::set fFDs; }; diff --git a/src/servers/power/power_button_monitor.cpp b/src/servers/power/power_button_monitor.cpp index a5da6eb288..fa0e0ab2d3 100644 --- a/src/servers/power/power_button_monitor.cpp +++ b/src/servers/power/power_button_monitor.cpp @@ -1,41 +1,62 @@ /* - * Copyright 2005-2013, Haiku, Inc. + * Copyright 2005-2014, Haiku, Inc. * Distributed under the terms of the MIT license. * * Authors: + * Rene Gollent * Nathan Whitehorn */ #include "power_button_monitor.h" +#include + +#include #include #include +#include #include +static const char* kBasePath = "/dev/power/button"; + + PowerButtonMonitor::PowerButtonMonitor() + : + fFDs() { - fFD = open("/dev/power/button/power", O_RDONLY); + BDirectory dir; + if (dir.SetTo(kBasePath) != B_OK) + return; + + entry_ref ref; + while (dir.GetNextRef(&ref) == B_OK) { + if (strncmp(ref.name, "power", 5) == 0) { + BString path; + path.SetToFormat("%s/%s", kBasePath, ref.name); + int fd = open(path.String(), O_RDONLY); + if (fd > 0) + fFDs.insert(fd); + } + } } PowerButtonMonitor::~PowerButtonMonitor() { - if (fFD > 0) - close(fFD); + for (std::set::iterator it = fFDs.begin(); it != fFDs.end(); ++it) + close(*it); } void -PowerButtonMonitor::HandleEvent() +PowerButtonMonitor::HandleEvent(int fd) { - if (fFD <= 0) - return; - uint8 button_pressed; - read(fFD, &button_pressed, 1); + if (read(fd, &button_pressed, 1) != 1) + return; if (button_pressed) { BRoster roster; diff --git a/src/servers/power/power_button_monitor.h b/src/servers/power/power_button_monitor.h index 65882534f7..0d6443bcf7 100644 --- a/src/servers/power/power_button_monitor.h +++ b/src/servers/power/power_button_monitor.h @@ -1,8 +1,9 @@ /* - * Copyright 2005-2013, Haiku, Inc. + * Copyright 2005-2014, Haiku, Inc. * Distributed under the terms of the MIT license. * * Authors: + * Rene Gollent * Nathan Whitehorn */ #ifndef _POWER_BUTTON_MONITOR_H @@ -17,11 +18,12 @@ public: PowerButtonMonitor(); virtual ~PowerButtonMonitor(); - virtual void HandleEvent(); + virtual void HandleEvent(int fd); - virtual int FD() const { return fFD; } + virtual const std::set& + FDs() const { return fFDs; } private: - int fFD; + std::set fFDs; }; diff --git a/src/servers/power/power_daemon.cpp b/src/servers/power/power_daemon.cpp index 570326f7af..f6d64e3cef 100644 --- a/src/servers/power/power_daemon.cpp +++ b/src/servers/power/power_daemon.cpp @@ -1,5 +1,6 @@ /* * Copyright 2013, Jérôme Duval, korli@users.berlios.de. + * Copyright 2014, Rene Gollent, rene@gollent.com. * Copyright 2005, Nathan Whitehorn. * * Distributed under the terms of the MIT License. @@ -11,6 +12,8 @@ #include +#include + class PowerManagementDaemon : public BApplication { public: @@ -45,13 +48,13 @@ PowerManagementDaemon::PowerManagementDaemon() fQuitRequested(false) { PowerMonitor* powerButtonMonitor = new PowerButtonMonitor; - if (powerButtonMonitor->FD() > 0) + if (powerButtonMonitor->FDs().size() > 0) fPowerMonitors[fMonitorCount++] = powerButtonMonitor; else delete powerButtonMonitor; PowerMonitor* lidMonitor = new LidMonitor; - if (lidMonitor->FD() > 0) + if (lidMonitor->FDs().size() > 0) fPowerMonitors[fMonitorCount++] = lidMonitor; else delete lidMonitor; @@ -92,19 +95,32 @@ PowerManagementDaemon::_EventLoop() { if (fMonitorCount == 0) return; - object_wait_info info[fMonitorCount]; + + std::map descriptorMap; + + size_t fdCount = 0; + for (uint32 i = 0; i < fMonitorCount; i++) + fdCount += fPowerMonitors[i]->FDs().size(); + + object_wait_info info[fdCount]; + uint32 index = 0; for (uint32 i = 0; i < fMonitorCount; i++) { - info[i].object = fPowerMonitors[i]->FD(); - info[i].type = B_OBJECT_TYPE_FD; - info[i].events = B_EVENT_READ; + const std::set& fds = fPowerMonitors[i]->FDs(); + for (std::set::iterator it = fds.begin(); it != fds.end(); ++it) { + info[index].object = *it; + info[index].type = B_OBJECT_TYPE_FD; + info[index].events = B_EVENT_READ; + descriptorMap[*it] = fPowerMonitors[i]; + ++index; + } } while (!fQuitRequested) { - if (wait_for_objects(info, fMonitorCount) < B_OK) + if (wait_for_objects(info, fdCount) < B_OK) continue; // handle events and reset events - for (uint32 i = 0; i < fMonitorCount; i++) { + for (uint32 i = 0; i < fdCount; i++) { if (info[i].events & B_EVENT_READ) - fPowerMonitors[i]->HandleEvent(); + descriptorMap[info[i].object]->HandleEvent(info[i].object); else info[i].events = B_EVENT_READ; } diff --git a/src/servers/power/power_monitor.h b/src/servers/power/power_monitor.h index 3128b17835..6c9c5f31fd 100644 --- a/src/servers/power/power_monitor.h +++ b/src/servers/power/power_monitor.h @@ -1,21 +1,26 @@ /* - * Copyright 2013, Haiku, Inc. + * Copyright 2013-2014, Haiku, Inc. * Distributed under the terms of the MIT license. * * Authors: * Jérôme Duval, korli@users.berlios.de. + * Rene Gollent, rene@gollent.com. */ #ifndef _POWER_MONITOR_H #define _POWER_MONITOR_H +#include + + class PowerMonitor { public: virtual ~PowerMonitor() {}; - virtual void HandleEvent() = 0; + virtual void HandleEvent(int fd) = 0; - virtual int FD() const = 0; + virtual const std::set& + FDs() const = 0; };