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