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