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