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