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
36OSDefineMetaClassAndStructors(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
45IOPMPowerSource *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// *****************************************************************************
60bool 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// *****************************************************************************
99void 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// *****************************************************************************
129void 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
165void 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
194void IOPMPowerSource::setExternalConnected(bool b) {
195 setPSProperty(externalConnectedKey,
196 b ? kOSBooleanTrue : kOSBooleanFalse);
197}
198
199void IOPMPowerSource::setExternalChargeCapable(bool b) {
200 setPSProperty(externalChargeCapableKey,
201 b ? kOSBooleanTrue : kOSBooleanFalse);
202}
203
204void IOPMPowerSource::setBatteryInstalled(bool b) {
205 setPSProperty(batteryInstalledKey,
206 b ? kOSBooleanTrue : kOSBooleanFalse);
207}
208
209void IOPMPowerSource::setIsCharging(bool b) {
210 setPSProperty(chargingKey,
211 b ? kOSBooleanTrue : kOSBooleanFalse);
212}
213
214void IOPMPowerSource::setAtWarnLevel(bool b) {
215 setPSProperty(warnLevelKey,
216 b ? kOSBooleanTrue : kOSBooleanFalse);
217}
218
219void IOPMPowerSource::setAtCriticalLevel(bool b) {
220 setPSProperty(criticalLevelKey,
221 b ? kOSBooleanTrue : kOSBooleanFalse);
222}
223
224
225void IOPMPowerSource::setCurrentCapacity(unsigned int val) {
226 OSNumber *n = OSNumber::withNumber(val, 32);
227 setPSProperty(currentCapacityKey, n);
228 n->release();
229}
230
231void IOPMPowerSource::setMaxCapacity(unsigned int val) {
232 OSNumber *n = OSNumber::withNumber(val, 32);
233 setPSProperty(maxCapacityKey, n);
234 n->release();
235}
236
237void IOPMPowerSource::setTimeRemaining(int val) {
238 OSNumber *n = OSNumber::withNumber(val, 32);
239 setPSProperty(timeRemainingKey, n);
240 n->release();
241}
242
243void IOPMPowerSource::setAmperage(int val) {
244 OSNumber *n = OSNumber::withNumber(val, 32);
245 setPSProperty(amperageKey, n);
246 n->release();
247}
248
249void IOPMPowerSource::setVoltage(unsigned int val) {
250 OSNumber *n = OSNumber::withNumber(val, 32);
251 setPSProperty(voltageKey, n);
252 n->release();
253}
254
255void IOPMPowerSource::setCycleCount(unsigned int val) {
256 OSNumber *n = OSNumber::withNumber(val, 32);
257 setPSProperty(cycleCountKey, n);
258 n->release();
259}
260
261void IOPMPowerSource::setAdapterInfo(int val) {
262 OSNumber *n = OSNumber::withNumber(val, 32);
263 setPSProperty(adapterInfoKey, n);
264 n->release();
265}
266
267void IOPMPowerSource::setLocation(int val) {
268 OSNumber *n = OSNumber::withNumber(val, 32);
269 setPSProperty(locationKey, n);
270 n->release();
271}
272
273void IOPMPowerSource::setErrorCondition(OSSymbol *s) {
274 setPSProperty(errorConditionKey, s);
275}
276
277void IOPMPowerSource::setManufacturer(OSSymbol *s) {
278 setPSProperty(manufacturerKey, s);
279}
280
281void IOPMPowerSource::setModel(OSSymbol *s) {
282 setPSProperty(modelKey, s);
283}
284
285void IOPMPowerSource::setSerial(OSSymbol *s) {
286 setPSProperty(serialKey, s);
287}
288
289void 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
302OSObject *IOPMPowerSource::getPSProperty(const OSSymbol *symmie) {
303 if(!symmie) return NULL;
304 return properties->getObject(symmie);
305}
306
307bool IOPMPowerSource::externalConnected(void) {
308 return (kOSBooleanTrue == properties->getObject(externalConnectedKey));
309}
310
311bool IOPMPowerSource::externalChargeCapable(void) {
312 return (kOSBooleanTrue == properties->getObject(externalChargeCapableKey));
313}
314
315bool IOPMPowerSource::batteryInstalled(void) {
316 return (kOSBooleanTrue == properties->getObject(batteryInstalledKey));
317}
318
319bool IOPMPowerSource::isCharging(void) {
320 return (kOSBooleanTrue == properties->getObject(chargingKey));
321}
322
323bool IOPMPowerSource::atWarnLevel(void) {
324 return (kOSBooleanTrue == properties->getObject(warnLevelKey));
325}
326
327bool IOPMPowerSource::atCriticalLevel(void) {
328 return (kOSBooleanTrue == properties->getObject(criticalLevelKey));
329}
330
331unsigned 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
338unsigned 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
345unsigned 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
356int 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
363int 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
370unsigned 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
377unsigned 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
384int 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
391int 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
398OSSymbol *IOPMPowerSource::errorCondition(void) {
399 return OSDynamicCast(OSSymbol, properties->getObject(errorConditionKey));
400}
401
402OSSymbol *IOPMPowerSource::manufacturer(void) {
403 return OSDynamicCast(OSSymbol, properties->getObject(manufacturerKey));
404}
405
406OSSymbol *IOPMPowerSource::model(void) {
407 return OSDynamicCast(OSSymbol, properties->getObject(modelKey));
408}
409
410OSSymbol *IOPMPowerSource::serial(void) {
411 return OSDynamicCast(OSSymbol, properties->getObject(serialKey));
412}
413
414OSDictionary *IOPMPowerSource::legacyIOBatteryInfo(void) {
415 return OSDynamicCast(OSDictionary, properties->getObject(batteryInfoKey));
416}
417