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 IOPMPowerSource::init (void)
61 {
62     if (!super::init()) {
63         return false;
64     }
65 
66     nextInList = NULL;
67 
68     properties = OSDictionary::withCapacity(10);
69     if(!properties) return false;
70     properties->setCapacityIncrement(1);
71 
72     externalConnectedKey = OSSymbol::withCString(kIOPMPSExternalConnectedKey);
73     externalChargeCapableKey = OSSymbol::withCString(kIOPMPSExternalChargeCapableKey);
74     batteryInstalledKey = OSSymbol::withCString(kIOPMPSBatteryInstalledKey);
75     chargingKey = OSSymbol::withCString(kIOPMPSIsChargingKey);
76     warnLevelKey = OSSymbol::withCString(kIOPMPSAtWarnLevelKey);
77     criticalLevelKey = OSSymbol::withCString(kIOPMPSAtCriticalLevelKey);
78     currentCapacityKey = OSSymbol::withCString(kIOPMPSCurrentCapacityKey);
79     maxCapacityKey = OSSymbol::withCString(kIOPMPSMaxCapacityKey);
80     timeRemainingKey = OSSymbol::withCString(kIOPMPSTimeRemainingKey);
81     amperageKey = OSSymbol::withCString(kIOPMPSAmperageKey);
82     voltageKey = OSSymbol::withCString(kIOPMPSVoltageKey);
83     cycleCountKey = OSSymbol::withCString(kIOPMPSCycleCountKey);
84     adapterInfoKey = OSSymbol::withCString(kIOPMPSAdapterInfoKey);
85     locationKey = OSSymbol::withCString(kIOPMPSLocationKey);
86     errorConditionKey = OSSymbol::withCString(kIOPMPSErrorConditionKey);
87     manufacturerKey = OSSymbol::withCString(kIOPMPSManufacturerKey);
88     modelKey = OSSymbol::withCString(kIOPMPSModelKey);
89     serialKey = OSSymbol::withCString(kIOPMPSSerialKey);
90     batteryInfoKey = OSSymbol::withCString(kIOPMPSLegacyBatteryInfoKey);
91 
92     return true;
93 }
94 
95 // *****************************************************************************
96 // free
97 //
98 // *****************************************************************************
99 void IOPMPowerSource::free(void)
100 {
101     if(properties) properties->release();
102     if(externalConnectedKey) externalConnectedKey->release();
103     if(externalChargeCapableKey) externalChargeCapableKey->release();
104     if(batteryInstalledKey) batteryInstalledKey->release();
105     if(chargingKey) chargingKey->release();
106     if(warnLevelKey) warnLevelKey->release();
107     if(criticalLevelKey) criticalLevelKey->release();
108     if(currentCapacityKey) currentCapacityKey->release();
109     if(maxCapacityKey) maxCapacityKey->release();
110     if(timeRemainingKey) timeRemainingKey->release();
111     if(amperageKey) amperageKey->release();
112     if(voltageKey) voltageKey->release();
113     if(cycleCountKey) cycleCountKey->release();
114     if(adapterInfoKey) adapterInfoKey->release();
115     if(errorConditionKey) errorConditionKey->release();
116     if(manufacturerKey) manufacturerKey->release();
117     if(modelKey) modelKey->release();
118     if(serialKey) serialKey->release();
119     if(locationKey) locationKey->release();
120     if(batteryInfoKey) batteryInfoKey->release();
121 }
122 
123 // *****************************************************************************
124 // updateStatus
125 //
126 // Update power source state in IORegistry and message interested clients
127 // notifying them of our change.
128 // *****************************************************************************
129 void IOPMPowerSource::updateStatus (void)
130 {
131     OSCollectionIterator            *iterator;
132     OSObject                        *iteratorKey;
133     OSObject                        *obj;
134 
135     // do nothing if settings haven't changed
136     if(!settingsChangedSinceUpdate) return;
137 
138     iterator = OSCollectionIterator::withCollection(properties);
139     if(!iterator) return;
140 
141     while ((iteratorKey = iterator->getNextObject())) {
142         OSSymbol *key;
143 
144         key = OSDynamicCast(OSSymbol, iteratorKey);
145         if (!key) continue;
146         obj = properties->getObject(key);
147         if(!obj) continue;
148         setProperty(key, obj);
149     }
150     iterator->release();
151 
152     settingsChangedSinceUpdate = false;
153 
154     // And up goes the flare
155     messageClients(kIOPMMessageBatteryStatusHasChanged);
156 }
157 
158 
159 /*******************************************************************************
160  *
161  * PROTECTED Accessors. All the setters! Yay!
162  *
163  ******************************************************************************/
164 
165 void IOPMPowerSource::setPSProperty(const OSSymbol *key, OSObject *val)
166 {
167     OSObject    *lastVal;
168 
169     if(!key || !val) return;
170 
171     // Compare new setting with existing setting; update
172     // 'settingsChangedSinceUpdate' if the setting has changed.
173     // If values are OSNumbers, do equality comparison.
174     // Otherwise, just compare pointers.
175 
176     if( (lastVal = properties->getObject(key)) ) {
177 	if(val->isEqualTo(lastVal)) {
178 	    // settings didn't change
179 	} else {
180 	    // num val is not equal to last val
181 	    settingsChangedSinceUpdate = true;
182 	}
183     } else {
184         // new setting; no last value
185         settingsChangedSinceUpdate = true;
186     }
187 
188     // here's the part where we go crazy.
189     properties->setObject(key, val);
190 }
191 
192 
193 
194 void IOPMPowerSource::setExternalConnected(bool b) {
195     setPSProperty(externalConnectedKey,
196             b ? kOSBooleanTrue : kOSBooleanFalse);
197 }
198 
199 void IOPMPowerSource::setExternalChargeCapable(bool b) {
200     setPSProperty(externalChargeCapableKey,
201             b ? kOSBooleanTrue : kOSBooleanFalse);
202 }
203 
204 void IOPMPowerSource::setBatteryInstalled(bool b) {
205     setPSProperty(batteryInstalledKey,
206             b ? kOSBooleanTrue : kOSBooleanFalse);
207 }
208 
209 void IOPMPowerSource::setIsCharging(bool b) {
210     setPSProperty(chargingKey,
211             b ? kOSBooleanTrue : kOSBooleanFalse);
212 }
213 
214 void IOPMPowerSource::setAtWarnLevel(bool b) {
215     setPSProperty(warnLevelKey,
216             b ? kOSBooleanTrue : kOSBooleanFalse);
217 }
218 
219 void IOPMPowerSource::setAtCriticalLevel(bool b) {
220     setPSProperty(criticalLevelKey,
221             b ? kOSBooleanTrue : kOSBooleanFalse);
222 }
223 
224 
225 void IOPMPowerSource::setCurrentCapacity(unsigned int val) {
226     OSNumber *n = OSNumber::withNumber(val, 32);
227     setPSProperty(currentCapacityKey, n);
228     n->release();
229 }
230 
231 void IOPMPowerSource::setMaxCapacity(unsigned int val) {
232     OSNumber *n = OSNumber::withNumber(val, 32);
233     setPSProperty(maxCapacityKey, n);
234     n->release();
235 }
236 
237 void IOPMPowerSource::setTimeRemaining(int val) {
238     OSNumber *n = OSNumber::withNumber(val, 32);
239     setPSProperty(timeRemainingKey, n);
240     n->release();
241 }
242 
243 void IOPMPowerSource::setAmperage(int val) {
244     OSNumber *n = OSNumber::withNumber(val, 32);
245     setPSProperty(amperageKey, n);
246     n->release();
247 }
248 
249 void IOPMPowerSource::setVoltage(unsigned int val) {
250     OSNumber *n = OSNumber::withNumber(val, 32);
251     setPSProperty(voltageKey, n);
252     n->release();
253 }
254 
255 void IOPMPowerSource::setCycleCount(unsigned int val) {
256     OSNumber *n = OSNumber::withNumber(val, 32);
257     setPSProperty(cycleCountKey, n);
258     n->release();
259 }
260 
261 void IOPMPowerSource::setAdapterInfo(int val) {
262     OSNumber *n = OSNumber::withNumber(val, 32);
263     setPSProperty(adapterInfoKey, n);
264     n->release();
265 }
266 
267 void IOPMPowerSource::setLocation(int val) {
268     OSNumber *n = OSNumber::withNumber(val, 32);
269     setPSProperty(locationKey, n);
270     n->release();
271 }
272 
273 void IOPMPowerSource::setErrorCondition(OSSymbol *s) {
274     setPSProperty(errorConditionKey, s);
275 }
276 
277 void IOPMPowerSource::setManufacturer(OSSymbol *s) {
278     setPSProperty(manufacturerKey, s);
279 }
280 
281 void IOPMPowerSource::setModel(OSSymbol *s) {
282     setPSProperty(modelKey, s);
283 }
284 
285 void IOPMPowerSource::setSerial(OSSymbol *s) {
286     setPSProperty(serialKey, s);
287 }
288 
289 void IOPMPowerSource::setLegacyIOBatteryInfo(OSDictionary *d) {
290     setPSProperty(batteryInfoKey, d);
291 }
292 
293 
294 
295 
296 /*******************************************************************************
297  *
298  * PUBLIC Accessors. All the getters! Boo!
299  *
300  ******************************************************************************/
301 
302 OSObject *IOPMPowerSource::getPSProperty(const OSSymbol *symmie) {
303     if(!symmie) return NULL;
304     return properties->getObject(symmie);
305 }
306 
307 bool IOPMPowerSource::externalConnected(void) {
308     return (kOSBooleanTrue == properties->getObject(externalConnectedKey));
309 }
310 
311 bool IOPMPowerSource::externalChargeCapable(void) {
312     return (kOSBooleanTrue == properties->getObject(externalChargeCapableKey));
313 }
314 
315 bool IOPMPowerSource::batteryInstalled(void) {
316     return (kOSBooleanTrue == properties->getObject(batteryInstalledKey));
317 }
318 
319 bool IOPMPowerSource::isCharging(void) {
320     return (kOSBooleanTrue == properties->getObject(chargingKey));
321 }
322 
323 bool IOPMPowerSource::atWarnLevel(void) {
324     return (kOSBooleanTrue == properties->getObject(warnLevelKey));
325 }
326 
327 bool IOPMPowerSource::atCriticalLevel(void) {
328     return (kOSBooleanTrue == properties->getObject(criticalLevelKey));
329 }
330 
331 unsigned int IOPMPowerSource::currentCapacity(void) {
332     OSNumber        *n;
333     n = OSDynamicCast(OSNumber, properties->getObject(currentCapacityKey));
334     if(!n) return 0;
335     else return (unsigned int)n->unsigned32BitValue();
336 }
337 
338 unsigned int IOPMPowerSource::maxCapacity(void) {
339     OSNumber        *n;
340     n = OSDynamicCast(OSNumber, properties->getObject(maxCapacityKey));
341     if(!n) return 0;
342     else return (unsigned int)n->unsigned32BitValue();
343 }
344 
345 unsigned int IOPMPowerSource::capacityPercentRemaining(void)
346 {
347     unsigned int _currentCapacity = currentCapacity();
348     unsigned int _maxCapacity = maxCapacity();
349     if(0 == _maxCapacity) {
350         return 0;
351     } else {
352         return ((100*_currentCapacity) / _maxCapacity);
353     }
354 }
355 
356 int IOPMPowerSource::timeRemaining(void) {
357     OSNumber        *n;
358     n = OSDynamicCast(OSNumber, properties->getObject(timeRemainingKey));
359     if(!n) return 0;
360     else return (int)n->unsigned32BitValue();
361 }
362 
363 int IOPMPowerSource::amperage(void) {
364     OSNumber        *n;
365     n = OSDynamicCast(OSNumber, properties->getObject(amperageKey));
366     if(!n) return 0;
367     else return (int)n->unsigned32BitValue();
368 }
369 
370 unsigned int IOPMPowerSource::voltage(void) {
371     OSNumber        *n;
372     n = OSDynamicCast(OSNumber, properties->getObject(voltageKey));
373     if(!n) return 0;
374     else return (unsigned int)n->unsigned32BitValue();
375 }
376 
377 unsigned int IOPMPowerSource::cycleCount(void) {
378     OSNumber        *n;
379     n = OSDynamicCast(OSNumber, properties->getObject(cycleCountKey));
380     if(!n) return 0;
381     else return (unsigned int)n->unsigned32BitValue();
382 }
383 
384 int IOPMPowerSource::adapterInfo(void) {
385     OSNumber        *n;
386     n = OSDynamicCast(OSNumber, properties->getObject(adapterInfoKey));
387     if(!n) return 0;
388     else return (int)n->unsigned32BitValue();
389 }
390 
391 int IOPMPowerSource::location(void) {
392     OSNumber        *n;
393     n = OSDynamicCast(OSNumber, properties->getObject(locationKey));
394     if(!n) return 0;
395     else return (unsigned int)n->unsigned32BitValue();
396 }
397 
398 OSSymbol *IOPMPowerSource::errorCondition(void) {
399     return OSDynamicCast(OSSymbol, properties->getObject(errorConditionKey));
400 }
401 
402 OSSymbol *IOPMPowerSource::manufacturer(void) {
403     return OSDynamicCast(OSSymbol, properties->getObject(manufacturerKey));
404 }
405 
406 OSSymbol *IOPMPowerSource::model(void) {
407     return OSDynamicCast(OSSymbol, properties->getObject(modelKey));
408 }
409 
410 OSSymbol *IOPMPowerSource::serial(void) {
411     return OSDynamicCast(OSSymbol, properties->getObject(serialKey));
412 }
413 
414 OSDictionary *IOPMPowerSource::legacyIOBatteryInfo(void) {
415     return OSDynamicCast(OSDictionary, properties->getObject(batteryInfoKey));
416 }
417