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