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 61 IOPMPowerSource::init(void) 62 { 63 if (!super::init()) { 64 return false; 65 } 66 67 nextInList = NULL; 68 69 properties = OSDictionary::withCapacity(10); 70 if (!properties) { 71 return false; 72 } 73 properties->setCapacityIncrement(1); 74 75 externalConnectedKey = OSSymbol::withCString(kIOPMPSExternalConnectedKey); 76 externalChargeCapableKey = OSSymbol::withCString(kIOPMPSExternalChargeCapableKey); 77 batteryInstalledKey = OSSymbol::withCString(kIOPMPSBatteryInstalledKey); 78 chargingKey = OSSymbol::withCString(kIOPMPSIsChargingKey); 79 warnLevelKey = OSSymbol::withCString(kIOPMPSAtWarnLevelKey); 80 criticalLevelKey = OSSymbol::withCString(kIOPMPSAtCriticalLevelKey); 81 currentCapacityKey = OSSymbol::withCString(kIOPMPSCurrentCapacityKey); 82 maxCapacityKey = OSSymbol::withCString(kIOPMPSMaxCapacityKey); 83 timeRemainingKey = OSSymbol::withCString(kIOPMPSTimeRemainingKey); 84 amperageKey = OSSymbol::withCString(kIOPMPSAmperageKey); 85 voltageKey = OSSymbol::withCString(kIOPMPSVoltageKey); 86 cycleCountKey = OSSymbol::withCString(kIOPMPSCycleCountKey); 87 adapterInfoKey = OSSymbol::withCString(kIOPMPSAdapterInfoKey); 88 locationKey = OSSymbol::withCString(kIOPMPSLocationKey); 89 errorConditionKey = OSSymbol::withCString(kIOPMPSErrorConditionKey); 90 manufacturerKey = OSSymbol::withCString(kIOPMPSManufacturerKey); 91 modelKey = OSSymbol::withCString(kIOPMPSModelKey); 92 serialKey = OSSymbol::withCString(kIOPMPSSerialKey); 93 batteryInfoKey = OSSymbol::withCString(kIOPMPSLegacyBatteryInfoKey); 94 95 return true; 96 } 97 98 // ***************************************************************************** 99 // free 100 // 101 // ***************************************************************************** 102 void 103 IOPMPowerSource::free(void) 104 { 105 if (properties) { 106 properties->release(); 107 } 108 if (externalConnectedKey) { 109 externalConnectedKey->release(); 110 } 111 if (externalChargeCapableKey) { 112 externalChargeCapableKey->release(); 113 } 114 if (batteryInstalledKey) { 115 batteryInstalledKey->release(); 116 } 117 if (chargingKey) { 118 chargingKey->release(); 119 } 120 if (warnLevelKey) { 121 warnLevelKey->release(); 122 } 123 if (criticalLevelKey) { 124 criticalLevelKey->release(); 125 } 126 if (currentCapacityKey) { 127 currentCapacityKey->release(); 128 } 129 if (maxCapacityKey) { 130 maxCapacityKey->release(); 131 } 132 if (timeRemainingKey) { 133 timeRemainingKey->release(); 134 } 135 if (amperageKey) { 136 amperageKey->release(); 137 } 138 if (voltageKey) { 139 voltageKey->release(); 140 } 141 if (cycleCountKey) { 142 cycleCountKey->release(); 143 } 144 if (adapterInfoKey) { 145 adapterInfoKey->release(); 146 } 147 if (errorConditionKey) { 148 errorConditionKey->release(); 149 } 150 if (manufacturerKey) { 151 manufacturerKey->release(); 152 } 153 if (modelKey) { 154 modelKey->release(); 155 } 156 if (serialKey) { 157 serialKey->release(); 158 } 159 if (locationKey) { 160 locationKey->release(); 161 } 162 if (batteryInfoKey) { 163 batteryInfoKey->release(); 164 } 165 166 super::free(); 167 } 168 169 // ***************************************************************************** 170 // updateStatus 171 // 172 // Update power source state in IORegistry and message interested clients 173 // notifying them of our change. 174 // ***************************************************************************** 175 void 176 IOPMPowerSource::updateStatus(void) 177 { 178 OSCollectionIterator *iterator; 179 OSObject *iteratorKey; 180 OSObject *obj; 181 182 // do nothing if settings haven't changed 183 if (!settingsChangedSinceUpdate) { 184 return; 185 } 186 187 iterator = OSCollectionIterator::withCollection(properties); 188 if (!iterator) { 189 return; 190 } 191 192 while ((iteratorKey = iterator->getNextObject())) { 193 OSSymbol *key; 194 195 key = OSDynamicCast(OSSymbol, iteratorKey); 196 if (!key) { 197 continue; 198 } 199 obj = properties->getObject(key); 200 if (!obj) { 201 continue; 202 } 203 setProperty(key, obj); 204 } 205 iterator->release(); 206 207 settingsChangedSinceUpdate = false; 208 209 // And up goes the flare 210 messageClients(kIOPMMessageBatteryStatusHasChanged); 211 } 212 213 214 /******************************************************************************* 215 * 216 * PROTECTED Accessors. All the setters! Yay! 217 * 218 ******************************************************************************/ 219 220 void 221 IOPMPowerSource::setPSProperty(const OSSymbol *key, OSObject *val) 222 { 223 OSObject *lastVal; 224 225 if (!key || !val) { 226 return; 227 } 228 229 // Compare new setting with existing setting; update 230 // 'settingsChangedSinceUpdate' if the setting has changed. 231 // If values are OSNumbers, do equality comparison. 232 // Otherwise, just compare pointers. 233 234 if ((lastVal = properties->getObject(key))) { 235 if (val->isEqualTo(lastVal)) { 236 // settings didn't change 237 } else { 238 // num val is not equal to last val 239 settingsChangedSinceUpdate = true; 240 } 241 } else { 242 // new setting; no last value 243 settingsChangedSinceUpdate = true; 244 } 245 246 // here's the part where we go crazy. 247 properties->setObject(key, val); 248 } 249 250 251 252 void 253 IOPMPowerSource::setExternalConnected(bool b) 254 { 255 setPSProperty(externalConnectedKey, 256 b ? kOSBooleanTrue : kOSBooleanFalse); 257 } 258 259 void 260 IOPMPowerSource::setExternalChargeCapable(bool b) 261 { 262 setPSProperty(externalChargeCapableKey, 263 b ? kOSBooleanTrue : kOSBooleanFalse); 264 } 265 266 void 267 IOPMPowerSource::setBatteryInstalled(bool b) 268 { 269 setPSProperty(batteryInstalledKey, 270 b ? kOSBooleanTrue : kOSBooleanFalse); 271 } 272 273 void 274 IOPMPowerSource::setIsCharging(bool b) 275 { 276 setPSProperty(chargingKey, 277 b ? kOSBooleanTrue : kOSBooleanFalse); 278 } 279 280 void 281 IOPMPowerSource::setAtWarnLevel(bool b) 282 { 283 setPSProperty(warnLevelKey, 284 b ? kOSBooleanTrue : kOSBooleanFalse); 285 } 286 287 void 288 IOPMPowerSource::setAtCriticalLevel(bool b) 289 { 290 setPSProperty(criticalLevelKey, 291 b ? kOSBooleanTrue : kOSBooleanFalse); 292 } 293 294 295 void 296 IOPMPowerSource::setCurrentCapacity(unsigned int val) 297 { 298 OSNumber *n = OSNumber::withNumber(val, 32); 299 setPSProperty(currentCapacityKey, n); 300 n->release(); 301 } 302 303 void 304 IOPMPowerSource::setMaxCapacity(unsigned int val) 305 { 306 OSNumber *n = OSNumber::withNumber(val, 32); 307 setPSProperty(maxCapacityKey, n); 308 n->release(); 309 } 310 311 void 312 IOPMPowerSource::setTimeRemaining(int val) 313 { 314 OSNumber *n = OSNumber::withNumber(val, 32); 315 setPSProperty(timeRemainingKey, n); 316 n->release(); 317 } 318 319 void 320 IOPMPowerSource::setAmperage(int val) 321 { 322 OSNumber *n = OSNumber::withNumber(val, 32); 323 setPSProperty(amperageKey, n); 324 n->release(); 325 } 326 327 void 328 IOPMPowerSource::setVoltage(unsigned int val) 329 { 330 OSNumber *n = OSNumber::withNumber(val, 32); 331 setPSProperty(voltageKey, n); 332 n->release(); 333 } 334 335 void 336 IOPMPowerSource::setCycleCount(unsigned int val) 337 { 338 OSNumber *n = OSNumber::withNumber(val, 32); 339 setPSProperty(cycleCountKey, n); 340 n->release(); 341 } 342 343 void 344 IOPMPowerSource::setAdapterInfo(int val) 345 { 346 OSNumber *n = OSNumber::withNumber(val, 32); 347 setPSProperty(adapterInfoKey, n); 348 n->release(); 349 } 350 351 void 352 IOPMPowerSource::setLocation(int val) 353 { 354 OSNumber *n = OSNumber::withNumber(val, 32); 355 setPSProperty(locationKey, n); 356 n->release(); 357 } 358 359 void 360 IOPMPowerSource::setErrorCondition(OSSymbol *s) 361 { 362 setPSProperty(errorConditionKey, s); 363 } 364 365 void 366 IOPMPowerSource::setManufacturer(OSSymbol *s) 367 { 368 setPSProperty(manufacturerKey, s); 369 } 370 371 void 372 IOPMPowerSource::setModel(OSSymbol *s) 373 { 374 setPSProperty(modelKey, s); 375 } 376 377 void 378 IOPMPowerSource::setSerial(OSSymbol *s) 379 { 380 setPSProperty(serialKey, s); 381 } 382 383 void 384 IOPMPowerSource::setLegacyIOBatteryInfo(OSDictionary *d) 385 { 386 setPSProperty(batteryInfoKey, d); 387 } 388 389 390 391 392 /******************************************************************************* 393 * 394 * PUBLIC Accessors. All the getters! Boo! 395 * 396 ******************************************************************************/ 397 398 OSObject * 399 IOPMPowerSource::getPSProperty(const OSSymbol *symmie) 400 { 401 if (!symmie) { 402 return NULL; 403 } 404 return properties->getObject(symmie); 405 } 406 407 bool 408 IOPMPowerSource::externalConnected(void) 409 { 410 return kOSBooleanTrue == properties->getObject(externalConnectedKey); 411 } 412 413 bool 414 IOPMPowerSource::externalChargeCapable(void) 415 { 416 return kOSBooleanTrue == properties->getObject(externalChargeCapableKey); 417 } 418 419 bool 420 IOPMPowerSource::batteryInstalled(void) 421 { 422 return kOSBooleanTrue == properties->getObject(batteryInstalledKey); 423 } 424 425 bool 426 IOPMPowerSource::isCharging(void) 427 { 428 return kOSBooleanTrue == properties->getObject(chargingKey); 429 } 430 431 bool 432 IOPMPowerSource::atWarnLevel(void) 433 { 434 return kOSBooleanTrue == properties->getObject(warnLevelKey); 435 } 436 437 bool 438 IOPMPowerSource::atCriticalLevel(void) 439 { 440 return kOSBooleanTrue == properties->getObject(criticalLevelKey); 441 } 442 443 unsigned int 444 IOPMPowerSource::currentCapacity(void) 445 { 446 OSNumber *n; 447 n = OSDynamicCast(OSNumber, properties->getObject(currentCapacityKey)); 448 if (!n) { 449 return 0; 450 } else { 451 return (unsigned int)n->unsigned32BitValue(); 452 } 453 } 454 455 unsigned int 456 IOPMPowerSource::maxCapacity(void) 457 { 458 OSNumber *n; 459 n = OSDynamicCast(OSNumber, properties->getObject(maxCapacityKey)); 460 if (!n) { 461 return 0; 462 } else { 463 return (unsigned int)n->unsigned32BitValue(); 464 } 465 } 466 467 unsigned int 468 IOPMPowerSource::capacityPercentRemaining(void) 469 { 470 unsigned int _currentCapacity = currentCapacity(); 471 unsigned int _maxCapacity = maxCapacity(); 472 if (0 == _maxCapacity) { 473 return 0; 474 } else { 475 return (100 * _currentCapacity) / _maxCapacity; 476 } 477 } 478 479 int 480 IOPMPowerSource::timeRemaining(void) 481 { 482 OSNumber *n; 483 n = OSDynamicCast(OSNumber, properties->getObject(timeRemainingKey)); 484 if (!n) { 485 return 0; 486 } else { 487 return (int)n->unsigned32BitValue(); 488 } 489 } 490 491 int 492 IOPMPowerSource::amperage(void) 493 { 494 OSNumber *n; 495 n = OSDynamicCast(OSNumber, properties->getObject(amperageKey)); 496 if (!n) { 497 return 0; 498 } else { 499 return (int)n->unsigned32BitValue(); 500 } 501 } 502 503 unsigned int 504 IOPMPowerSource::voltage(void) 505 { 506 OSNumber *n; 507 n = OSDynamicCast(OSNumber, properties->getObject(voltageKey)); 508 if (!n) { 509 return 0; 510 } else { 511 return (unsigned int)n->unsigned32BitValue(); 512 } 513 } 514 515 unsigned int 516 IOPMPowerSource::cycleCount(void) 517 { 518 OSNumber *n; 519 n = OSDynamicCast(OSNumber, properties->getObject(cycleCountKey)); 520 if (!n) { 521 return 0; 522 } else { 523 return (unsigned int)n->unsigned32BitValue(); 524 } 525 } 526 527 int 528 IOPMPowerSource::adapterInfo(void) 529 { 530 OSNumber *n; 531 n = OSDynamicCast(OSNumber, properties->getObject(adapterInfoKey)); 532 if (!n) { 533 return 0; 534 } else { 535 return (int)n->unsigned32BitValue(); 536 } 537 } 538 539 int 540 IOPMPowerSource::location(void) 541 { 542 OSNumber *n; 543 n = OSDynamicCast(OSNumber, properties->getObject(locationKey)); 544 if (!n) { 545 return 0; 546 } else { 547 return (unsigned int)n->unsigned32BitValue(); 548 } 549 } 550 551 OSSymbol * 552 IOPMPowerSource::errorCondition(void) 553 { 554 return OSDynamicCast(OSSymbol, properties->getObject(errorConditionKey)); 555 } 556 557 OSSymbol * 558 IOPMPowerSource::manufacturer(void) 559 { 560 return OSDynamicCast(OSSymbol, properties->getObject(manufacturerKey)); 561 } 562 563 OSSymbol * 564 IOPMPowerSource::model(void) 565 { 566 return OSDynamicCast(OSSymbol, properties->getObject(modelKey)); 567 } 568 569 OSSymbol * 570 IOPMPowerSource::serial(void) 571 { 572 return OSDynamicCast(OSSymbol, properties->getObject(serialKey)); 573 } 574 575 OSDictionary * 576 IOPMPowerSource::legacyIOBatteryInfo(void) 577 { 578 return OSDynamicCast(OSDictionary, properties->getObject(batteryInfoKey)); 579 } 580