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
OSDefineMetaClassAndStructors(IOPMPowerSource,IOService)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
init(void)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
free(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
updateStatus(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
setPSProperty(const OSSymbol * key,OSObject * val)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
setExternalConnected(bool b)258 IOPMPowerSource::setExternalConnected(bool b)
259 {
260 setPSProperty(externalConnectedKey,
261 b ? kOSBooleanTrue : kOSBooleanFalse);
262 }
263
264 void
setExternalChargeCapable(bool b)265 IOPMPowerSource::setExternalChargeCapable(bool b)
266 {
267 setPSProperty(externalChargeCapableKey,
268 b ? kOSBooleanTrue : kOSBooleanFalse);
269 }
270
271 void
setBatteryInstalled(bool b)272 IOPMPowerSource::setBatteryInstalled(bool b)
273 {
274 setPSProperty(batteryInstalledKey,
275 b ? kOSBooleanTrue : kOSBooleanFalse);
276 }
277
278 void
setIsCharging(bool b)279 IOPMPowerSource::setIsCharging(bool b)
280 {
281 setPSProperty(chargingKey,
282 b ? kOSBooleanTrue : kOSBooleanFalse);
283 }
284
285 void
setAtWarnLevel(bool b)286 IOPMPowerSource::setAtWarnLevel(bool b)
287 {
288 setPSProperty(warnLevelKey,
289 b ? kOSBooleanTrue : kOSBooleanFalse);
290 }
291
292 void
setAtCriticalLevel(bool b)293 IOPMPowerSource::setAtCriticalLevel(bool b)
294 {
295 setPSProperty(criticalLevelKey,
296 b ? kOSBooleanTrue : kOSBooleanFalse);
297 }
298
299
300 void
setCurrentCapacity(unsigned int val)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
setMaxCapacity(unsigned int val)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
setTimeRemaining(int val)317 IOPMPowerSource::setTimeRemaining(int val)
318 {
319 OSNumber *n = OSNumber::withNumber(val, 32);
320 setPSProperty(timeRemainingKey, n);
321 n->release();
322 }
323
324 void
setAmperage(int val)325 IOPMPowerSource::setAmperage(int val)
326 {
327 OSNumber *n = OSNumber::withNumber(val, 32);
328 setPSProperty(amperageKey, n);
329 n->release();
330 }
331
332 void
setVoltage(unsigned int val)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
setCycleCount(unsigned int val)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
setAdapterInfo(int val)349 IOPMPowerSource::setAdapterInfo(int val)
350 {
351 OSNumber *n = OSNumber::withNumber(val, 32);
352 setPSProperty(adapterInfoKey, n);
353 n->release();
354 }
355
356 void
setLocation(int val)357 IOPMPowerSource::setLocation(int val)
358 {
359 OSNumber *n = OSNumber::withNumber(val, 32);
360 setPSProperty(locationKey, n);
361 n->release();
362 }
363
364 void
setErrorCondition(OSSymbol * s)365 IOPMPowerSource::setErrorCondition(OSSymbol *s)
366 {
367 setPSProperty(errorConditionKey, s);
368 }
369
370 void
setManufacturer(OSSymbol * s)371 IOPMPowerSource::setManufacturer(OSSymbol *s)
372 {
373 setPSProperty(manufacturerKey, s);
374 }
375
376 void
setModel(OSSymbol * s)377 IOPMPowerSource::setModel(OSSymbol *s)
378 {
379 setPSProperty(modelKey, s);
380 }
381
382 void
setSerial(OSSymbol * s)383 IOPMPowerSource::setSerial(OSSymbol *s)
384 {
385 setPSProperty(serialKey, s);
386 }
387
388 void
setLegacyIOBatteryInfo(OSDictionary * d)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 *
getPSProperty(const OSSymbol * symmie)404 IOPMPowerSource::getPSProperty(const OSSymbol *symmie)
405 {
406 if (!symmie) {
407 return NULL;
408 }
409 return properties->getObject(symmie);
410 }
411
412 bool
externalConnected(void)413 IOPMPowerSource::externalConnected(void)
414 {
415 return kOSBooleanTrue == properties->getObject(externalConnectedKey);
416 }
417
418 bool
externalChargeCapable(void)419 IOPMPowerSource::externalChargeCapable(void)
420 {
421 return kOSBooleanTrue == properties->getObject(externalChargeCapableKey);
422 }
423
424 bool
batteryInstalled(void)425 IOPMPowerSource::batteryInstalled(void)
426 {
427 return kOSBooleanTrue == properties->getObject(batteryInstalledKey);
428 }
429
430 bool
isCharging(void)431 IOPMPowerSource::isCharging(void)
432 {
433 return kOSBooleanTrue == properties->getObject(chargingKey);
434 }
435
436 bool
atWarnLevel(void)437 IOPMPowerSource::atWarnLevel(void)
438 {
439 return kOSBooleanTrue == properties->getObject(warnLevelKey);
440 }
441
442 bool
atCriticalLevel(void)443 IOPMPowerSource::atCriticalLevel(void)
444 {
445 return kOSBooleanTrue == properties->getObject(criticalLevelKey);
446 }
447
448 unsigned int
currentCapacity(void)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
maxCapacity(void)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
capacityPercentRemaining(void)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
timeRemaining(void)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
amperage(void)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
voltage(void)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
cycleCount(void)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
adapterInfo(void)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
location(void)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 *
errorCondition(void)557 IOPMPowerSource::errorCondition(void)
558 {
559 return OSDynamicCast(OSSymbol, properties->getObject(errorConditionKey));
560 }
561
562 OSSymbol *
manufacturer(void)563 IOPMPowerSource::manufacturer(void)
564 {
565 return OSDynamicCast(OSSymbol, properties->getObject(manufacturerKey));
566 }
567
568 OSSymbol *
model(void)569 IOPMPowerSource::model(void)
570 {
571 return OSDynamicCast(OSSymbol, properties->getObject(modelKey));
572 }
573
574 OSSymbol *
serial(void)575 IOPMPowerSource::serial(void)
576 {
577 return OSDynamicCast(OSSymbol, properties->getObject(serialKey));
578 }
579
580 OSDictionary *
legacyIOBatteryInfo(void)581 IOPMPowerSource::legacyIOBatteryInfo(void)
582 {
583 return OSDynamicCast(OSDictionary, properties->getObject(batteryInfoKey));
584 }
585