xref: /haiku/src/servers/power/power_daemon.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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 
18 class PowerManagementDaemon : public BServer {
19 public:
20 								PowerManagementDaemon();
21 	virtual 					~PowerManagementDaemon();
22 private:
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 
34 int
35 main(void)
36 {
37 	new PowerManagementDaemon();
38 	be_app->Run();
39 	delete be_app;
40 	return 0;
41 }
42 
43 
44 PowerManagementDaemon::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 
74 PowerManagementDaemon::~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 
84 status_t
85 PowerManagementDaemon::_EventLooper(void* arg)
86 {
87 	PowerManagementDaemon* self = (PowerManagementDaemon*)arg;
88 	self->_EventLoop();
89 	return B_OK;
90 }
91 
92 
93 void
94 PowerManagementDaemon::_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