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.
This commit is contained in:
parent
74f7623716
commit
bf29cdd777
@ -10,4 +10,4 @@ Server power_daemon :
|
||||
power_button_monitor.cpp
|
||||
;
|
||||
|
||||
LinkAgainst power_daemon : be [ TargetLibsupc++ ] ;
|
||||
LinkAgainst power_daemon : be [ TargetLibstdc++ TargetLibsupc++ ] ;
|
||||
|
@ -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<int>::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");
|
||||
}
|
||||
}
|
||||
|
@ -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<int>&
|
||||
FDs() const { return fFDs; }
|
||||
private:
|
||||
int fFD;
|
||||
std::set<int> fFDs;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 <string.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <Messenger.h>
|
||||
#include <Roster.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <RosterPrivate.h>
|
||||
|
||||
|
||||
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<int>::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;
|
||||
|
@ -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<int>&
|
||||
FDs() const { return fFDs; }
|
||||
private:
|
||||
int fFD;
|
||||
std::set<int> fFDs;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 <Application.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
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<int, PowerMonitor*> 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<int>& fds = fPowerMonitors[i]->FDs();
|
||||
for (std::set<int>::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;
|
||||
}
|
||||
|
@ -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 <set>
|
||||
|
||||
|
||||
class PowerMonitor {
|
||||
public:
|
||||
virtual ~PowerMonitor() {};
|
||||
|
||||
virtual void HandleEvent() = 0;
|
||||
virtual void HandleEvent(int fd) = 0;
|
||||
|
||||
virtual int FD() const = 0;
|
||||
virtual const std::set<int>&
|
||||
FDs() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user