xref: /haiku/src/apps/powerstatus/ACPIDriverInterface.cpp (revision 76e9533e9e9945f62053bf7c737df2f3e1735bbd)
1 /*
2  * Copyright 2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Clemens Zeidler, haiku@clemens-zeidler.de
7  */
8 
9 
10 #include "ACPIDriverInterface.h"
11 
12 #include <stdio.h>
13 
14 #include <Autolock.h>
15 #include <Catalog.h>
16 #include <Directory.h>
17 #include <Entry.h>
18 #include <Path.h>
19 
20 
21 #undef B_TRANSLATE_CONTEXT
22 #define B_TRANSLATE_CONTEXT "PowerStatus"
23 
24 
25 RateBuffer::RateBuffer()
26 	:
27 	fPosition(0),
28 	fSize(kRateBufferSize),
29 	fCurrentSize(0)
30 {
31 
32 }
33 
34 
35 void
36 RateBuffer::AddRate(int32 rate)
37 {
38 	fRateBuffer[fPosition] = rate;
39 	fPosition ++;
40 	if (fPosition >= fSize)
41 		fPosition = 0;
42 
43 	if (fCurrentSize < fSize)
44 		fCurrentSize ++;
45 }
46 
47 
48 int32
49 RateBuffer::GetMeanRate()
50 {
51 	int mean = 0;
52 	for (int i = 0; i < fCurrentSize; i++) {
53 		mean += fRateBuffer[i];
54 	}
55 
56 	if (fCurrentSize == 0)
57 		return -1;
58 
59 	return mean / fCurrentSize;
60 }
61 
62 
63 Battery::Battery(int driverHandler)
64 	:
65 	fDriverHandler(driverHandler)
66 {
67 	_Init();
68 }
69 
70 
71 Battery::~Battery()
72 {
73 	close(fDriverHandler);
74 }
75 
76 
77 status_t
78 Battery::InitCheck()
79 {
80 	return fInitStatus;
81 }
82 
83 
84 status_t
85 Battery::ReadBatteryInfo()
86 {
87 	status_t status;
88 	status = ioctl(fDriverHandler, GET_BATTERY_INFO, &fCachedAcpiInfo,
89 		sizeof(acpi_battery_info));
90 
91 	if (status != B_OK)
92 		return status;
93 
94 	return B_OK;
95 }
96 
97 
98 status_t
99 Battery::GetBatteryInfoCached(battery_info* info)
100 {
101 	info->state = fCachedAcpiInfo.state;
102 	info->current_rate = fCachedAcpiInfo.current_rate;
103 	info->capacity = fCachedAcpiInfo.capacity;
104 	info->full_capacity = fExtendedBatteryInfo.last_full_charge;
105 	fRateBuffer.AddRate(fCachedAcpiInfo.current_rate);
106 	if (fCachedAcpiInfo.current_rate > 0)
107 		info->time_left = 3600 * fCachedAcpiInfo.capacity
108 			/ fRateBuffer.GetMeanRate();
109 	else
110 		info->time_left = -1;
111 
112 	return B_OK;
113 }
114 
115 
116 status_t
117 Battery::GetExtendedBatteryInfo(acpi_extended_battery_info* info)
118 {
119 	status_t status;
120 	status = ioctl(fDriverHandler, GET_EXTENDED_BATTERY_INFO, info,
121 		sizeof(acpi_extended_battery_info));
122 
123 	return status;
124 }
125 
126 
127 void
128 Battery::_Init()
129 {
130 	uint32 magicId = 0;
131 	fInitStatus = ioctl(fDriverHandler, IDENTIFY_DEVICE, &magicId,
132 		sizeof(uint32));
133 	if (fInitStatus != B_OK)
134 		return;
135 
136 	fInitStatus = ioctl(fDriverHandler, GET_EXTENDED_BATTERY_INFO,
137 		&fExtendedBatteryInfo, sizeof(acpi_extended_battery_info));
138 	if (fInitStatus != B_OK)
139 		return;
140 
141 	fInitStatus = ioctl(fDriverHandler, GET_BATTERY_INFO, &fCachedAcpiInfo,
142 		sizeof(acpi_battery_info));
143 	if (fInitStatus != B_OK)
144 		return;
145 
146 	printf(B_TRANSLATE("ACPI driver found\n"));
147 
148 }
149 
150 
151 ACPIDriverInterface::~ACPIDriverInterface()
152 {
153 	for (int i = 0; i < fDriverList.CountItems(); i++)
154 		delete fDriverList.ItemAt(i);
155 
156 }
157 
158 
159 const char* kDriverDir = "/dev/power";
160 
161 
162 status_t
163 ACPIDriverInterface::Connect()
164 {
165 	printf(B_TRANSLATE("ACPI connect\n"));
166 	return _FindDrivers(kDriverDir);
167 }
168 
169 
170 status_t
171 ACPIDriverInterface::GetBatteryInfo(battery_info* info, int32 index)
172 {
173 	BAutolock autolock(fInterfaceLocker);
174 	if (index < 0 || index >= fDriverList.CountItems())
175 		return B_ERROR;
176 
177 	status_t status;
178 	status = fDriverList.ItemAt(index)->GetBatteryInfoCached(info);
179 	return status;
180 }
181 
182 
183 status_t
184 ACPIDriverInterface::GetExtendedBatteryInfo(acpi_extended_battery_info* info,
185 	int32 index)
186 {
187 	BAutolock autolock(fInterfaceLocker);
188 	if (index < 0 || index >= fDriverList.CountItems())
189 		return B_ERROR;
190 
191 	status_t status;
192 	status = fDriverList.ItemAt(index)->GetExtendedBatteryInfo(info);
193 
194 	return status;
195 }
196 
197 
198 int32
199 ACPIDriverInterface::GetBatteryCount()
200 {
201 	return fDriverList.CountItems();
202 }
203 
204 
205 status_t
206 ACPIDriverInterface::_ReadBatteryInfo()
207 {
208 	for (int i = 0; i < fDriverList.CountItems(); i++)
209 		fDriverList.ItemAt(i)->ReadBatteryInfo();
210 
211 	return B_OK;
212 }
213 
214 
215 void
216 ACPIDriverInterface::_WatchPowerStatus()
217 {
218 	const bigtime_t kUpdateInterval = 2000000;
219 		// every two seconds
220 
221 	while (atomic_get(&fIsWatching) > 0) {
222 		_ReadBatteryInfo();
223 		Broadcast(kMsgUpdate);
224 		acquire_sem_etc(fWaitSem, 1, B_RELATIVE_TIMEOUT, kUpdateInterval);
225 	}
226 }
227 
228 
229 status_t
230 ACPIDriverInterface::_FindDrivers(const char* dirpath)
231 {
232 	BDirectory dir(dirpath);
233 	BEntry entry;
234 
235 	status_t status = B_ERROR;
236 
237 	while (dir.GetNextEntry(&entry) == B_OK) {
238 		BPath path;
239 		entry.GetPath(&path);
240 
241 		if (entry.IsDirectory()) {
242 			if (_FindDrivers(path.Path()) == B_OK)
243 				return B_OK;
244 		}
245 		else {
246 			int32 handler = open(path.Path(), O_RDWR);
247 			if (handler >= 0) {
248 				printf(B_TRANSLATE("try %s\n"), path.Path());
249 				Battery* battery = new Battery(handler);
250 				if (battery->InitCheck() == B_OK) {
251 					fDriverList.AddItem(battery);
252 					status = B_OK;
253 				}
254 				else
255 					delete battery;
256 			}
257 		}
258 
259 	}
260 	return status;
261 }
262 
263 
264