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 20RateBuffer::RateBuffer() 21 : 22 fPosition(0), 23 fSize(kRateBufferSize), 24 fCurrentSize(0) 25{ 26 27} 28 29 30void 31RateBuffer::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 43int32 44RateBuffer::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 58Battery::Battery(int driverHandler) 59 : 60 fDriverHandler(driverHandler) 61{ 62 _Init(); 63} 64 65 66Battery::~Battery() 67{ 68 close(fDriverHandler); 69} 70 71 72status_t 73Battery::InitCheck() 74{ 75 return fInitStatus; 76} 77 78 79status_t 80Battery::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 93status_t 94Battery::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 111status_t 112Battery::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 122void 123Battery::_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 146ACPIDriverInterface::~ACPIDriverInterface() 147{ 148 for (int i = 0; i < fDriverList.CountItems(); i++) 149 delete fDriverList.ItemAt(i); 150 151} 152 153 154const char* kDriverDir = "/dev/power"; 155 156 157status_t 158ACPIDriverInterface::Connect() 159{ 160 printf("ACPI connect\n"); 161 return _FindDrivers(kDriverDir); 162} 163 164 165status_t 166ACPIDriverInterface::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 178status_t 179ACPIDriverInterface::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 193int32 194ACPIDriverInterface::GetBatteryCount() 195{ 196 return fDriverList.CountItems(); 197} 198 199 200status_t 201ACPIDriverInterface::_ReadBatteryInfo() 202{ 203 for (int i = 0; i < fDriverList.CountItems(); i++) 204 fDriverList.ItemAt(i)->ReadBatteryInfo(); 205 206 return B_OK; 207} 208 209 210void 211ACPIDriverInterface::_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 224status_t 225ACPIDriverInterface::_FindDrivers(const char* dirpath) 226{ 227 BDirectory dir(dirpath); 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