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
37OSDefineMetaClassAndStructors(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
46IOPMPowerSource *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// *****************************************************************************
61bool
62IOPMPowerSource::init(void)
63{
64 if (!super::init()) {
65 return false;
66 }
67
68 nextInList = NULL;
69
70 properties = OSDictionary::withCapacity(capacity: 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// *****************************************************************************
103void
104IOPMPowerSource::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// *****************************************************************************
176void
177IOPMPowerSource::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(inColl: 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(aKey: key);
201 if (!obj) {
202 continue;
203 }
204 setProperty(aKey: key, anObject: 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(type: notifyMessage);
216}
217
218
219/*******************************************************************************
220 *
221 * PROTECTED Accessors. All the setters! Yay!
222 *
223 ******************************************************************************/
224
225void
226IOPMPowerSource::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(aKey: key))) {
240 if (val->isEqualTo(anObject: 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(aKey: key, anObject: val);
253}
254
255
256
257void
258IOPMPowerSource::setExternalConnected(bool b)
259{
260 setPSProperty(key: externalConnectedKey,
261 val: b ? kOSBooleanTrue : kOSBooleanFalse);
262}
263
264void
265IOPMPowerSource::setExternalChargeCapable(bool b)
266{
267 setPSProperty(key: externalChargeCapableKey,
268 val: b ? kOSBooleanTrue : kOSBooleanFalse);
269}
270
271void
272IOPMPowerSource::setBatteryInstalled(bool b)
273{
274 setPSProperty(key: batteryInstalledKey,
275 val: b ? kOSBooleanTrue : kOSBooleanFalse);
276}
277
278void
279IOPMPowerSource::setIsCharging(bool b)
280{
281 setPSProperty(key: chargingKey,
282 val: b ? kOSBooleanTrue : kOSBooleanFalse);
283}
284
285void
286IOPMPowerSource::setAtWarnLevel(bool b)
287{
288 setPSProperty(key: warnLevelKey,
289 val: b ? kOSBooleanTrue : kOSBooleanFalse);
290}
291
292void
293IOPMPowerSource::setAtCriticalLevel(bool b)
294{
295 setPSProperty(key: criticalLevelKey,
296 val: b ? kOSBooleanTrue : kOSBooleanFalse);
297}
298
299
300void
301IOPMPowerSource::setCurrentCapacity(unsigned int val)
302{
303 OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32);
304 setPSProperty(key: currentCapacityKey, val: n);
305 n->release();
306}
307
308void
309IOPMPowerSource::setMaxCapacity(unsigned int val)
310{
311 OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32);
312 setPSProperty(key: maxCapacityKey, val: n);
313 n->release();
314}
315
316void
317IOPMPowerSource::setTimeRemaining(int val)
318{
319 OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32);
320 setPSProperty(key: timeRemainingKey, val: n);
321 n->release();
322}
323
324void
325IOPMPowerSource::setAmperage(int val)
326{
327 OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32);
328 setPSProperty(key: amperageKey, val: n);
329 n->release();
330}
331
332void
333IOPMPowerSource::setVoltage(unsigned int val)
334{
335 OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32);
336 setPSProperty(key: voltageKey, val: n);
337 n->release();
338}
339
340void
341IOPMPowerSource::setCycleCount(unsigned int val)
342{
343 OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32);
344 setPSProperty(key: cycleCountKey, val: n);
345 n->release();
346}
347
348void
349IOPMPowerSource::setAdapterInfo(int val)
350{
351 OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32);
352 setPSProperty(key: adapterInfoKey, val: n);
353 n->release();
354}
355
356void
357IOPMPowerSource::setLocation(int val)
358{
359 OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32);
360 setPSProperty(key: locationKey, val: n);
361 n->release();
362}
363
364void
365IOPMPowerSource::setErrorCondition(OSSymbol *s)
366{
367 setPSProperty(key: errorConditionKey, val: s);
368}
369
370void
371IOPMPowerSource::setManufacturer(OSSymbol *s)
372{
373 setPSProperty(key: manufacturerKey, val: s);
374}
375
376void
377IOPMPowerSource::setModel(OSSymbol *s)
378{
379 setPSProperty(key: modelKey, val: s);
380}
381
382void
383IOPMPowerSource::setSerial(OSSymbol *s)
384{
385 setPSProperty(key: serialKey, val: s);
386}
387
388void
389IOPMPowerSource::setLegacyIOBatteryInfo(OSDictionary *d)
390{
391 setPSProperty(key: batteryInfoKey, val: d);
392}
393
394
395
396
397/*******************************************************************************
398 *
399 * PUBLIC Accessors. All the getters! Boo!
400 *
401 ******************************************************************************/
402
403OSObject *
404IOPMPowerSource::getPSProperty(const OSSymbol *symmie)
405{
406 if (!symmie) {
407 return NULL;
408 }
409 return properties->getObject(aKey: symmie);
410}
411
412bool
413IOPMPowerSource::externalConnected(void)
414{
415 return kOSBooleanTrue == properties->getObject(aKey: externalConnectedKey);
416}
417
418bool
419IOPMPowerSource::externalChargeCapable(void)
420{
421 return kOSBooleanTrue == properties->getObject(aKey: externalChargeCapableKey);
422}
423
424bool
425IOPMPowerSource::batteryInstalled(void)
426{
427 return kOSBooleanTrue == properties->getObject(aKey: batteryInstalledKey);
428}
429
430bool
431IOPMPowerSource::isCharging(void)
432{
433 return kOSBooleanTrue == properties->getObject(aKey: chargingKey);
434}
435
436bool
437IOPMPowerSource::atWarnLevel(void)
438{
439 return kOSBooleanTrue == properties->getObject(aKey: warnLevelKey);
440}
441
442bool
443IOPMPowerSource::atCriticalLevel(void)
444{
445 return kOSBooleanTrue == properties->getObject(aKey: criticalLevelKey);
446}
447
448unsigned int
449IOPMPowerSource::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
460unsigned int
461IOPMPowerSource::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
472unsigned int
473IOPMPowerSource::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
484int
485IOPMPowerSource::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
496int
497IOPMPowerSource::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
508unsigned int
509IOPMPowerSource::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
520unsigned int
521IOPMPowerSource::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
532int
533IOPMPowerSource::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
544int
545IOPMPowerSource::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
556OSSymbol *
557IOPMPowerSource::errorCondition(void)
558{
559 return OSDynamicCast(OSSymbol, properties->getObject(errorConditionKey));
560}
561
562OSSymbol *
563IOPMPowerSource::manufacturer(void)
564{
565 return OSDynamicCast(OSSymbol, properties->getObject(manufacturerKey));
566}
567
568OSSymbol *
569IOPMPowerSource::model(void)
570{
571 return OSDynamicCast(OSSymbol, properties->getObject(modelKey));
572}
573
574OSSymbol *
575IOPMPowerSource::serial(void)
576{
577 return OSDynamicCast(OSSymbol, properties->getObject(serialKey));
578}
579
580OSDictionary *
581IOPMPowerSource::legacyIOBatteryInfo(void)
582{
583 return OSDynamicCast(OSDictionary, properties->getObject(batteryInfoKey));
584}
585