1 /* 2 * Copyright (c) 1998-2005 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #include <IOKit/pwr_mgt/IOPMPowerSource.h> 30 #include <IOKit/pwr_mgt/IOPM.h> 31 #include <IOKit/IOMessage.h> 32 #include <IOKit/IOLib.h> 33 34 #define super IOService 35 36 OSDefineMetaClassAndStructors(IOPMPowerSource, IOService) 37 38 // ***************************************************************************** 39 // powerSource 40 // 41 // Static initializer for IOPMPowerSource. Returns a new instance of the class 42 // which the caller must attach to the power plane. 43 // ***************************************************************************** 44 45 IOPMPowerSource *IOPMPowerSource::powerSource(void) 46 { 47 IOPMPowerSource *ps = new IOPMPowerSource; 48 49 if(ps) { 50 ps->init(); 51 return ps; 52 } 53 return NULL; 54 } 55 56 // ***************************************************************************** 57 // init 58 // 59 // ***************************************************************************** 60 bool IOPMPowerSource::init (void) 61 { 62 if (!super::init()) { 63 return false; 64 } 65 66 nextInList = NULL; 67 68 properties = OSDictionary::withCapacity(10); 69 if(!properties) return false; 70 properties->setCapacityIncrement(1); 71 72 externalConnectedKey = OSSymbol::withCString(kIOPMPSExternalConnectedKey); 73 externalChargeCapableKey = OSSymbol::withCString(kIOPMPSExternalChargeCapableKey); 74 batteryInstalledKey = OSSymbol::withCString(kIOPMPSBatteryInstalledKey); 75 chargingKey = OSSymbol::withCString(kIOPMPSIsChargingKey); 76 warnLevelKey = OSSymbol::withCString(kIOPMPSAtWarnLevelKey); 77 criticalLevelKey = OSSymbol::withCString(kIOPMPSAtCriticalLevelKey); 78 currentCapacityKey = OSSymbol::withCString(kIOPMPSCurrentCapacityKey); 79 maxCapacityKey = OSSymbol::withCString(kIOPMPSMaxCapacityKey); 80 timeRemainingKey = OSSymbol::withCString(kIOPMPSTimeRemainingKey); 81 amperageKey = OSSymbol::withCString(kIOPMPSAmperageKey); 82 voltageKey = OSSymbol::withCString(kIOPMPSVoltageKey); 83 cycleCountKey = OSSymbol::withCString(kIOPMPSCycleCountKey); 84 adapterInfoKey = OSSymbol::withCString(kIOPMPSAdapterInfoKey); 85 locationKey = OSSymbol::withCString(kIOPMPSLocationKey); 86 errorConditionKey = OSSymbol::withCString(kIOPMPSErrorConditionKey); 87 manufacturerKey = OSSymbol::withCString(kIOPMPSManufacturerKey); 88 modelKey = OSSymbol::withCString(kIOPMPSModelKey); 89 serialKey = OSSymbol::withCString(kIOPMPSSerialKey); 90 batteryInfoKey = OSSymbol::withCString(kIOPMPSLegacyBatteryInfoKey); 91 92 return true; 93 } 94 95 // ***************************************************************************** 96 // free 97 // 98 // ***************************************************************************** 99 void IOPMPowerSource::free(void) 100 { 101 if(properties) properties->release(); 102 if(externalConnectedKey) externalConnectedKey->release(); 103 if(externalChargeCapableKey) externalChargeCapableKey->release(); 104 if(batteryInstalledKey) batteryInstalledKey->release(); 105 if(chargingKey) chargingKey->release(); 106 if(warnLevelKey) warnLevelKey->release(); 107 if(criticalLevelKey) criticalLevelKey->release(); 108 if(currentCapacityKey) currentCapacityKey->release(); 109 if(maxCapacityKey) maxCapacityKey->release(); 110 if(timeRemainingKey) timeRemainingKey->release(); 111 if(amperageKey) amperageKey->release(); 112 if(voltageKey) voltageKey->release(); 113 if(cycleCountKey) cycleCountKey->release(); 114 if(adapterInfoKey) adapterInfoKey->release(); 115 if(errorConditionKey) errorConditionKey->release(); 116 if(manufacturerKey) manufacturerKey->release(); 117 if(modelKey) modelKey->release(); 118 if(serialKey) serialKey->release(); 119 if(locationKey) locationKey->release(); 120 if(batteryInfoKey) batteryInfoKey->release(); 121 } 122 123 // ***************************************************************************** 124 // updateStatus 125 // 126 // Update power source state in IORegistry and message interested clients 127 // notifying them of our change. 128 // ***************************************************************************** 129 void IOPMPowerSource::updateStatus (void) 130 { 131 OSCollectionIterator *iterator; 132 OSObject *iteratorKey; 133 OSObject *obj; 134 135 // do nothing if settings haven't changed 136 if(!settingsChangedSinceUpdate) return; 137 138 iterator = OSCollectionIterator::withCollection(properties); 139 if(!iterator) return; 140 141 while ((iteratorKey = iterator->getNextObject())) { 142 OSSymbol *key; 143 144 key = OSDynamicCast(OSSymbol, iteratorKey); 145 if (!key) continue; 146 obj = properties->getObject(key); 147 if(!obj) continue; 148 setProperty(key, obj); 149 } 150 iterator->release(); 151 152 settingsChangedSinceUpdate = false; 153 154 // And up goes the flare 155 messageClients(kIOPMMessageBatteryStatusHasChanged); 156 } 157 158 159 /******************************************************************************* 160 * 161 * PROTECTED Accessors. All the setters! Yay! 162 * 163 ******************************************************************************/ 164 165 void IOPMPowerSource::setPSProperty(const OSSymbol *key, OSObject *val) 166 { 167 OSObject *lastVal; 168 OSNumber *newNumVal; 169 170 if(!key || !val) return; 171 172 // Compare new setting with existing setting; update 173 // 'settingsChangedSinceUpdate' if the setting has changed. 174 // If values are OSNumbers, do equality comparison. 175 // Otherwise, just compare pointers. 176 177 if( (lastVal = properties->getObject(key)) ) { 178 newNumVal = OSDynamicCast(OSNumber, val); 179 if(newNumVal) { 180 if(newNumVal->isEqualTo(lastVal)) { 181 // settings didn't change 182 } else { 183 // num val is not equal to last val 184 settingsChangedSinceUpdate = true; 185 } 186 } else { 187 // pointer compare as last resort 188 if(lastVal != val) 189 settingsChangedSinceUpdate = true; 190 } 191 } else { 192 // new setting; no last value 193 settingsChangedSinceUpdate = true; 194 } 195 196 // here's the part where we go crazy. 197 properties->setObject(key, val); 198 } 199 200 201 202 void IOPMPowerSource::setExternalConnected(bool b) { 203 setPSProperty(externalConnectedKey, 204 b ? kOSBooleanTrue : kOSBooleanFalse); 205 } 206 207 void IOPMPowerSource::setExternalChargeCapable(bool b) { 208 setPSProperty(externalChargeCapableKey, 209 b ? kOSBooleanTrue : kOSBooleanFalse); 210 } 211 212 void IOPMPowerSource::setBatteryInstalled(bool b) { 213 setPSProperty(batteryInstalledKey, 214 b ? kOSBooleanTrue : kOSBooleanFalse); 215 } 216 217 void IOPMPowerSource::setIsCharging(bool b) { 218 setPSProperty(chargingKey, 219 b ? kOSBooleanTrue : kOSBooleanFalse); 220 } 221 222 void IOPMPowerSource::setAtWarnLevel(bool b) { 223 setPSProperty(warnLevelKey, 224 b ? kOSBooleanTrue : kOSBooleanFalse); 225 } 226 227 void IOPMPowerSource::setAtCriticalLevel(bool b) { 228 setPSProperty(criticalLevelKey, 229 b ? kOSBooleanTrue : kOSBooleanFalse); 230 } 231 232 233 void IOPMPowerSource::setCurrentCapacity(unsigned int val) { 234 OSNumber *n = OSNumber::withNumber(val, 32); 235 setPSProperty(currentCapacityKey, n); 236 n->release(); 237 } 238 239 void IOPMPowerSource::setMaxCapacity(unsigned int val) { 240 OSNumber *n = OSNumber::withNumber(val, 32); 241 setPSProperty(maxCapacityKey, n); 242 n->release(); 243 } 244 245 void IOPMPowerSource::setTimeRemaining(int val) { 246 OSNumber *n = OSNumber::withNumber(val, 32); 247 setPSProperty(timeRemainingKey, n); 248 n->release(); 249 } 250 251 void IOPMPowerSource::setAmperage(int val) { 252 OSNumber *n = OSNumber::withNumber(val, 32); 253 setPSProperty(amperageKey, n); 254 n->release(); 255 } 256 257 void IOPMPowerSource::setVoltage(unsigned int val) { 258 OSNumber *n = OSNumber::withNumber(val, 32); 259 setPSProperty(voltageKey, n); 260 n->release(); 261 } 262 263 void IOPMPowerSource::setCycleCount(unsigned int val) { 264 OSNumber *n = OSNumber::withNumber(val, 32); 265 setPSProperty(cycleCountKey, n); 266 n->release(); 267 } 268 269 void IOPMPowerSource::setAdapterInfo(int val) { 270 OSNumber *n = OSNumber::withNumber(val, 32); 271 setPSProperty(adapterInfoKey, n); 272 n->release(); 273 } 274 275 void IOPMPowerSource::setLocation(int val) { 276 OSNumber *n = OSNumber::withNumber(val, 32); 277 setPSProperty(locationKey, n); 278 n->release(); 279 } 280 281 void IOPMPowerSource::setErrorCondition(OSSymbol *s) { 282 setPSProperty(errorConditionKey, s); 283 } 284 285 void IOPMPowerSource::setManufacturer(OSSymbol *s) { 286 setPSProperty(manufacturerKey, s); 287 } 288 289 void IOPMPowerSource::setModel(OSSymbol *s) { 290 setPSProperty(modelKey, s); 291 } 292 293 void IOPMPowerSource::setSerial(OSSymbol *s) { 294 setPSProperty(serialKey, s); 295 } 296 297 void IOPMPowerSource::setLegacyIOBatteryInfo(OSDictionary *d) { 298 setPSProperty(batteryInfoKey, d); 299 } 300 301 302 303 304 /******************************************************************************* 305 * 306 * PUBLIC Accessors. All the getters! Boo! 307 * 308 ******************************************************************************/ 309 310 OSObject *IOPMPowerSource::getPSProperty(const OSSymbol *symmie) { 311 if(!symmie) return NULL; 312 return properties->getObject(symmie); 313 } 314 315 bool IOPMPowerSource::externalConnected(void) { 316 return (kOSBooleanTrue == properties->getObject(externalConnectedKey)); 317 } 318 319 bool IOPMPowerSource::externalChargeCapable(void) { 320 return (kOSBooleanTrue == properties->getObject(externalChargeCapableKey)); 321 } 322 323 bool IOPMPowerSource::batteryInstalled(void) { 324 return (kOSBooleanTrue == properties->getObject(batteryInstalledKey)); 325 } 326 327 bool IOPMPowerSource::isCharging(void) { 328 return (kOSBooleanTrue == properties->getObject(chargingKey)); 329 } 330 331 bool IOPMPowerSource::atWarnLevel(void) { 332 return (kOSBooleanTrue == properties->getObject(warnLevelKey)); 333 } 334 335 bool IOPMPowerSource::atCriticalLevel(void) { 336 return (kOSBooleanTrue == properties->getObject(criticalLevelKey)); 337 } 338 339 unsigned int IOPMPowerSource::currentCapacity(void) { 340 OSNumber *n; 341 n = OSDynamicCast(OSNumber, properties->getObject(currentCapacityKey)); 342 if(!n) return 0; 343 else return (unsigned int)n->unsigned32BitValue(); 344 } 345 346 unsigned int IOPMPowerSource::maxCapacity(void) { 347 OSNumber *n; 348 n = OSDynamicCast(OSNumber, properties->getObject(maxCapacityKey)); 349 if(!n) return 0; 350 else return (unsigned int)n->unsigned32BitValue(); 351 } 352 353 unsigned int IOPMPowerSource::capacityPercentRemaining(void) 354 { 355 unsigned int _currentCapacity = currentCapacity(); 356 unsigned int _maxCapacity = maxCapacity(); 357 if(0 == _maxCapacity) { 358 return 0; 359 } else { 360 return ((100*_currentCapacity) / _maxCapacity); 361 } 362 } 363 364 int IOPMPowerSource::timeRemaining(void) { 365 OSNumber *n; 366 n = OSDynamicCast(OSNumber, properties->getObject(timeRemainingKey)); 367 if(!n) return 0; 368 else return (int)n->unsigned32BitValue(); 369 } 370 371 int IOPMPowerSource::amperage(void) { 372 OSNumber *n; 373 n = OSDynamicCast(OSNumber, properties->getObject(amperageKey)); 374 if(!n) return 0; 375 else return (int)n->unsigned32BitValue(); 376 } 377 378 unsigned int IOPMPowerSource::voltage(void) { 379 OSNumber *n; 380 n = OSDynamicCast(OSNumber, properties->getObject(voltageKey)); 381 if(!n) return 0; 382 else return (unsigned int)n->unsigned32BitValue(); 383 } 384 385 unsigned int IOPMPowerSource::cycleCount(void) { 386 OSNumber *n; 387 n = OSDynamicCast(OSNumber, properties->getObject(cycleCountKey)); 388 if(!n) return 0; 389 else return (unsigned int)n->unsigned32BitValue(); 390 } 391 392 int IOPMPowerSource::adapterInfo(void) { 393 OSNumber *n; 394 n = OSDynamicCast(OSNumber, properties->getObject(adapterInfoKey)); 395 if(!n) return 0; 396 else return (int)n->unsigned32BitValue(); 397 } 398 399 int IOPMPowerSource::location(void) { 400 OSNumber *n; 401 n = OSDynamicCast(OSNumber, properties->getObject(locationKey)); 402 if(!n) return 0; 403 else return (unsigned int)n->unsigned32BitValue(); 404 } 405 406 OSSymbol *IOPMPowerSource::errorCondition(void) { 407 return OSDynamicCast(OSSymbol, properties->getObject(errorConditionKey)); 408 } 409 410 OSSymbol *IOPMPowerSource::manufacturer(void) { 411 return OSDynamicCast(OSSymbol, properties->getObject(manufacturerKey)); 412 } 413 414 OSSymbol *IOPMPowerSource::model(void) { 415 return OSDynamicCast(OSSymbol, properties->getObject(modelKey)); 416 } 417 418 OSSymbol *IOPMPowerSource::serial(void) { 419 return OSDynamicCast(OSSymbol, properties->getObject(serialKey)); 420 } 421 422 OSDictionary *IOPMPowerSource::legacyIOBatteryInfo(void) { 423 return OSDynamicCast(OSDictionary, properties->getObject(batteryInfoKey)); 424 } 425