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