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(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 | // ***************************************************************************** |
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(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 | |
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(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 | |
257 | void |
258 | IOPMPowerSource::setExternalConnected(bool b) |
259 | { |
260 | setPSProperty(key: externalConnectedKey, |
261 | val: b ? kOSBooleanTrue : kOSBooleanFalse); |
262 | } |
263 | |
264 | void |
265 | IOPMPowerSource::setExternalChargeCapable(bool b) |
266 | { |
267 | setPSProperty(key: externalChargeCapableKey, |
268 | val: b ? kOSBooleanTrue : kOSBooleanFalse); |
269 | } |
270 | |
271 | void |
272 | IOPMPowerSource::setBatteryInstalled(bool b) |
273 | { |
274 | setPSProperty(key: batteryInstalledKey, |
275 | val: b ? kOSBooleanTrue : kOSBooleanFalse); |
276 | } |
277 | |
278 | void |
279 | IOPMPowerSource::setIsCharging(bool b) |
280 | { |
281 | setPSProperty(key: chargingKey, |
282 | val: b ? kOSBooleanTrue : kOSBooleanFalse); |
283 | } |
284 | |
285 | void |
286 | IOPMPowerSource::setAtWarnLevel(bool b) |
287 | { |
288 | setPSProperty(key: warnLevelKey, |
289 | val: b ? kOSBooleanTrue : kOSBooleanFalse); |
290 | } |
291 | |
292 | void |
293 | IOPMPowerSource::setAtCriticalLevel(bool b) |
294 | { |
295 | setPSProperty(key: criticalLevelKey, |
296 | val: b ? kOSBooleanTrue : kOSBooleanFalse); |
297 | } |
298 | |
299 | |
300 | void |
301 | IOPMPowerSource::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 | |
308 | void |
309 | IOPMPowerSource::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 | |
316 | void |
317 | IOPMPowerSource::setTimeRemaining(int val) |
318 | { |
319 | OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32); |
320 | setPSProperty(key: timeRemainingKey, val: n); |
321 | n->release(); |
322 | } |
323 | |
324 | void |
325 | IOPMPowerSource::setAmperage(int val) |
326 | { |
327 | OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32); |
328 | setPSProperty(key: amperageKey, val: n); |
329 | n->release(); |
330 | } |
331 | |
332 | void |
333 | IOPMPowerSource::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 | |
340 | void |
341 | IOPMPowerSource::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 | |
348 | void |
349 | IOPMPowerSource::setAdapterInfo(int val) |
350 | { |
351 | OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32); |
352 | setPSProperty(key: adapterInfoKey, val: n); |
353 | n->release(); |
354 | } |
355 | |
356 | void |
357 | IOPMPowerSource::setLocation(int val) |
358 | { |
359 | OSNumber *n = OSNumber::withNumber(value: val, numberOfBits: 32); |
360 | setPSProperty(key: locationKey, val: n); |
361 | n->release(); |
362 | } |
363 | |
364 | void |
365 | IOPMPowerSource::setErrorCondition(OSSymbol *s) |
366 | { |
367 | setPSProperty(key: errorConditionKey, val: s); |
368 | } |
369 | |
370 | void |
371 | IOPMPowerSource::setManufacturer(OSSymbol *s) |
372 | { |
373 | setPSProperty(key: manufacturerKey, val: s); |
374 | } |
375 | |
376 | void |
377 | IOPMPowerSource::setModel(OSSymbol *s) |
378 | { |
379 | setPSProperty(key: modelKey, val: s); |
380 | } |
381 | |
382 | void |
383 | IOPMPowerSource::setSerial(OSSymbol *s) |
384 | { |
385 | setPSProperty(key: serialKey, val: s); |
386 | } |
387 | |
388 | void |
389 | IOPMPowerSource::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 | |
403 | OSObject * |
404 | IOPMPowerSource::getPSProperty(const OSSymbol *symmie) |
405 | { |
406 | if (!symmie) { |
407 | return NULL; |
408 | } |
409 | return properties->getObject(aKey: symmie); |
410 | } |
411 | |
412 | bool |
413 | IOPMPowerSource::externalConnected(void) |
414 | { |
415 | return kOSBooleanTrue == properties->getObject(aKey: externalConnectedKey); |
416 | } |
417 | |
418 | bool |
419 | IOPMPowerSource::externalChargeCapable(void) |
420 | { |
421 | return kOSBooleanTrue == properties->getObject(aKey: externalChargeCapableKey); |
422 | } |
423 | |
424 | bool |
425 | IOPMPowerSource::batteryInstalled(void) |
426 | { |
427 | return kOSBooleanTrue == properties->getObject(aKey: batteryInstalledKey); |
428 | } |
429 | |
430 | bool |
431 | IOPMPowerSource::isCharging(void) |
432 | { |
433 | return kOSBooleanTrue == properties->getObject(aKey: chargingKey); |
434 | } |
435 | |
436 | bool |
437 | IOPMPowerSource::atWarnLevel(void) |
438 | { |
439 | return kOSBooleanTrue == properties->getObject(aKey: warnLevelKey); |
440 | } |
441 | |
442 | bool |
443 | IOPMPowerSource::atCriticalLevel(void) |
444 | { |
445 | return kOSBooleanTrue == properties->getObject(aKey: 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 | |