1/*
2 * Copyright 2013, J��r��me Duval, korli@users.berlios.de.
3 * Copyright 2014, Rene Gollent, rene@gollent.com.
4 * Copyright 2005, Nathan Whitehorn.
5 *
6 * Distributed under the terms of the MIT License.
7 */
8
9
10#include "lid_monitor.h"
11#include "power_button_monitor.h"
12
13#include <Server.h>
14
15#include <map>
16
17
18class PowerManagementDaemon : public BServer {
19public:
20								PowerManagementDaemon();
21	virtual 					~PowerManagementDaemon();
22private:
23			void				_EventLoop();
24	static	status_t			_EventLooper(void *arg);
25
26			thread_id			fEventThread;
27			PowerMonitor*		fPowerMonitors[2];
28			uint32				fMonitorCount;
29
30			bool				fQuitRequested;
31};
32
33
34int
35main(void)
36{
37	new PowerManagementDaemon();
38	be_app->Run();
39	delete be_app;
40	return 0;
41}
42
43
44PowerManagementDaemon::PowerManagementDaemon()
45	:
46	BServer("application/x-vnd.Haiku-powermanagement", false, NULL),
47	fMonitorCount(0),
48	fQuitRequested(false)
49{
50	PowerMonitor* powerButtonMonitor = new PowerButtonMonitor;
51	if (powerButtonMonitor->FDs().size() > 0)
52		fPowerMonitors[fMonitorCount++] = powerButtonMonitor;
53	else
54		delete powerButtonMonitor;
55
56	PowerMonitor* lidMonitor = new LidMonitor;
57	if (lidMonitor->FDs().size() > 0)
58		fPowerMonitors[fMonitorCount++] = lidMonitor;
59	else
60		delete lidMonitor;
61
62	fEventThread = spawn_thread(_EventLooper, "_power_daemon_event_loop_",
63		B_NORMAL_PRIORITY, this);
64	if (fEventThread < B_OK)
65		return;
66	if (resume_thread(fEventThread) < B_OK) {
67		kill_thread(fEventThread);
68		fEventThread = -1;
69		return;
70	}
71}
72
73
74PowerManagementDaemon::~PowerManagementDaemon()
75{
76	fQuitRequested = true;
77	for (uint32 i = 0; i < fMonitorCount; i++)
78		delete fPowerMonitors[i];
79	status_t status;
80	wait_for_thread(fEventThread, &status);
81}
82
83
84status_t
85PowerManagementDaemon::_EventLooper(void* arg)
86{
87	PowerManagementDaemon* self = (PowerManagementDaemon*)arg;
88	self->_EventLoop();
89	return B_OK;
90}
91
92
93void
94PowerManagementDaemon::_EventLoop()
95{
96	if (fMonitorCount == 0)
97		return;
98
99	std::map<int, PowerMonitor*> descriptorMap;
100
101	size_t fdCount = 0;
102	for (uint32 i = 0; i < fMonitorCount; i++)
103		fdCount += fPowerMonitors[i]->FDs().size();
104
105	object_wait_info info[fdCount];
106	uint32 index = 0;
107	for (uint32 i = 0; i < fMonitorCount; i++) {
108		const std::set<int>& fds = fPowerMonitors[i]->FDs();
109		for (std::set<int>::iterator it = fds.begin(); it != fds.end(); ++it) {
110			info[index].object = *it;
111			info[index].type = B_OBJECT_TYPE_FD;
112			info[index].events = B_EVENT_READ;
113			descriptorMap[*it] = fPowerMonitors[i];
114			++index;
115		}
116	}
117	while (!fQuitRequested) {
118		if (wait_for_objects(info, fdCount) < B_OK)
119			continue;
120		// handle events and reset events
121		for (uint32 i = 0; i < fdCount; i++) {
122			if (info[i].events & B_EVENT_READ)
123				descriptorMap[info[i].object]->HandleEvent(info[i].object);
124			else
125				info[i].events = B_EVENT_READ;
126		}
127	}
128}
129