]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
0c530ab8 | 2 | * Copyright (c) 1998-2005 Apple Computer, Inc. All rights reserved. |
1c79356b | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
0a7de745 | 5 | * |
2d21ac55 A |
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. | |
0a7de745 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
0a7de745 | 17 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
0a7de745 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
27 | */ |
28 | ||
29 | #include <IOKit/pwr_mgt/IOPMPowerSource.h> | |
0c530ab8 A |
30 | #include <IOKit/pwr_mgt/IOPM.h> |
31 | #include <IOKit/IOMessage.h> | |
32 | #include <IOKit/IOLib.h> | |
1c79356b | 33 | |
0c530ab8 | 34 | #define super IOService |
1c79356b | 35 | |
0c530ab8 | 36 | OSDefineMetaClassAndStructors(IOPMPowerSource, IOService) |
1c79356b | 37 | |
0c530ab8 A |
38 | // ***************************************************************************** |
39 | // powerSource | |
1c79356b | 40 | // |
0c530ab8 A |
41 | // Static initializer for IOPMPowerSource. Returns a new instance of the class |
42 | // which the caller must attach to the power plane. | |
43 | // ***************************************************************************** | |
8ad349bb | 44 | |
0c530ab8 A |
45 | IOPMPowerSource *IOPMPowerSource::powerSource(void) |
46 | { | |
0a7de745 | 47 | IOPMPowerSource *ps = new IOPMPowerSource; |
6601e61a | 48 | |
0a7de745 A |
49 | if (ps) { |
50 | ps->init(); | |
51 | return ps; | |
52 | } | |
53 | return NULL; | |
1c79356b A |
54 | } |
55 | ||
0c530ab8 A |
56 | // ***************************************************************************** |
57 | // init | |
1c79356b | 58 | // |
0c530ab8 | 59 | // ***************************************************************************** |
0a7de745 A |
60 | bool |
61 | IOPMPowerSource::init(void) | |
62 | { | |
63 | if (!super::init()) { | |
64 | return false; | |
65 | } | |
66 | ||
67 | nextInList = NULL; | |
68 | ||
69 | properties = OSDictionary::withCapacity(10); | |
70 | if (!properties) { | |
71 | return false; | |
72 | } | |
73 | properties->setCapacityIncrement(1); | |
74 | ||
75 | externalConnectedKey = OSSymbol::withCString(kIOPMPSExternalConnectedKey); | |
76 | externalChargeCapableKey = OSSymbol::withCString(kIOPMPSExternalChargeCapableKey); | |
77 | batteryInstalledKey = OSSymbol::withCString(kIOPMPSBatteryInstalledKey); | |
78 | chargingKey = OSSymbol::withCString(kIOPMPSIsChargingKey); | |
79 | warnLevelKey = OSSymbol::withCString(kIOPMPSAtWarnLevelKey); | |
80 | criticalLevelKey = OSSymbol::withCString(kIOPMPSAtCriticalLevelKey); | |
81 | currentCapacityKey = OSSymbol::withCString(kIOPMPSCurrentCapacityKey); | |
82 | maxCapacityKey = OSSymbol::withCString(kIOPMPSMaxCapacityKey); | |
83 | timeRemainingKey = OSSymbol::withCString(kIOPMPSTimeRemainingKey); | |
84 | amperageKey = OSSymbol::withCString(kIOPMPSAmperageKey); | |
85 | voltageKey = OSSymbol::withCString(kIOPMPSVoltageKey); | |
86 | cycleCountKey = OSSymbol::withCString(kIOPMPSCycleCountKey); | |
87 | adapterInfoKey = OSSymbol::withCString(kIOPMPSAdapterInfoKey); | |
88 | locationKey = OSSymbol::withCString(kIOPMPSLocationKey); | |
89 | errorConditionKey = OSSymbol::withCString(kIOPMPSErrorConditionKey); | |
90 | manufacturerKey = OSSymbol::withCString(kIOPMPSManufacturerKey); | |
91 | modelKey = OSSymbol::withCString(kIOPMPSModelKey); | |
92 | serialKey = OSSymbol::withCString(kIOPMPSSerialKey); | |
93 | batteryInfoKey = OSSymbol::withCString(kIOPMPSLegacyBatteryInfoKey); | |
94 | ||
95 | return true; | |
1c79356b A |
96 | } |
97 | ||
0c530ab8 A |
98 | // ***************************************************************************** |
99 | // free | |
1c79356b | 100 | // |
0c530ab8 | 101 | // ***************************************************************************** |
0a7de745 A |
102 | void |
103 | IOPMPowerSource::free(void) | |
104 | { | |
105 | if (properties) { | |
106 | properties->release(); | |
107 | } | |
108 | if (externalConnectedKey) { | |
109 | externalConnectedKey->release(); | |
110 | } | |
111 | if (externalChargeCapableKey) { | |
112 | externalChargeCapableKey->release(); | |
113 | } | |
114 | if (batteryInstalledKey) { | |
115 | batteryInstalledKey->release(); | |
116 | } | |
117 | if (chargingKey) { | |
118 | chargingKey->release(); | |
119 | } | |
120 | if (warnLevelKey) { | |
121 | warnLevelKey->release(); | |
122 | } | |
123 | if (criticalLevelKey) { | |
124 | criticalLevelKey->release(); | |
125 | } | |
126 | if (currentCapacityKey) { | |
127 | currentCapacityKey->release(); | |
128 | } | |
129 | if (maxCapacityKey) { | |
130 | maxCapacityKey->release(); | |
131 | } | |
132 | if (timeRemainingKey) { | |
133 | timeRemainingKey->release(); | |
134 | } | |
135 | if (amperageKey) { | |
136 | amperageKey->release(); | |
137 | } | |
138 | if (voltageKey) { | |
139 | voltageKey->release(); | |
140 | } | |
141 | if (cycleCountKey) { | |
142 | cycleCountKey->release(); | |
143 | } | |
144 | if (adapterInfoKey) { | |
145 | adapterInfoKey->release(); | |
146 | } | |
147 | if (errorConditionKey) { | |
148 | errorConditionKey->release(); | |
149 | } | |
150 | if (manufacturerKey) { | |
151 | manufacturerKey->release(); | |
152 | } | |
153 | if (modelKey) { | |
154 | modelKey->release(); | |
155 | } | |
156 | if (serialKey) { | |
157 | serialKey->release(); | |
158 | } | |
159 | if (locationKey) { | |
160 | locationKey->release(); | |
161 | } | |
162 | if (batteryInfoKey) { | |
163 | batteryInfoKey->release(); | |
164 | } | |
cb323159 A |
165 | |
166 | super::free(); | |
1c79356b A |
167 | } |
168 | ||
0c530ab8 A |
169 | // ***************************************************************************** |
170 | // updateStatus | |
1c79356b | 171 | // |
0c530ab8 A |
172 | // Update power source state in IORegistry and message interested clients |
173 | // notifying them of our change. | |
174 | // ***************************************************************************** | |
0a7de745 A |
175 | void |
176 | IOPMPowerSource::updateStatus(void) | |
1c79356b | 177 | { |
0a7de745 A |
178 | OSCollectionIterator *iterator; |
179 | OSObject *iteratorKey; | |
180 | OSObject *obj; | |
0c530ab8 | 181 | |
0a7de745 A |
182 | // do nothing if settings haven't changed |
183 | if (!settingsChangedSinceUpdate) { | |
184 | return; | |
185 | } | |
2d21ac55 | 186 | |
0a7de745 A |
187 | iterator = OSCollectionIterator::withCollection(properties); |
188 | if (!iterator) { | |
189 | return; | |
190 | } | |
0c530ab8 | 191 | |
0a7de745 A |
192 | while ((iteratorKey = iterator->getNextObject())) { |
193 | OSSymbol *key; | |
194 | ||
195 | key = OSDynamicCast(OSSymbol, iteratorKey); | |
196 | if (!key) { | |
197 | continue; | |
198 | } | |
199 | obj = properties->getObject(key); | |
200 | if (!obj) { | |
201 | continue; | |
202 | } | |
203 | setProperty(key, obj); | |
204 | } | |
205 | iterator->release(); | |
0c530ab8 | 206 | |
0a7de745 | 207 | settingsChangedSinceUpdate = false; |
2d21ac55 | 208 | |
0a7de745 A |
209 | // And up goes the flare |
210 | messageClients(kIOPMMessageBatteryStatusHasChanged); | |
4452a7af A |
211 | } |
212 | ||
0c530ab8 A |
213 | |
214 | /******************************************************************************* | |
215 | * | |
216 | * PROTECTED Accessors. All the setters! Yay! | |
217 | * | |
218 | ******************************************************************************/ | |
0a7de745 A |
219 | |
220 | void | |
221 | IOPMPowerSource::setPSProperty(const OSSymbol *key, OSObject *val) | |
2d21ac55 | 222 | { |
0a7de745 | 223 | OSObject *lastVal; |
2d21ac55 | 224 | |
0a7de745 A |
225 | if (!key || !val) { |
226 | return; | |
227 | } | |
2d21ac55 | 228 | |
0a7de745 A |
229 | // Compare new setting with existing setting; update |
230 | // 'settingsChangedSinceUpdate' if the setting has changed. | |
231 | // If values are OSNumbers, do equality comparison. | |
232 | // Otherwise, just compare pointers. | |
233 | ||
234 | if ((lastVal = properties->getObject(key))) { | |
235 | if (val->isEqualTo(lastVal)) { | |
236 | // settings didn't change | |
237 | } else { | |
238 | // num val is not equal to last val | |
239 | settingsChangedSinceUpdate = true; | |
240 | } | |
6d2010ae | 241 | } else { |
0a7de745 A |
242 | // new setting; no last value |
243 | settingsChangedSinceUpdate = true; | |
6d2010ae | 244 | } |
0a7de745 A |
245 | |
246 | // here's the part where we go crazy. | |
247 | properties->setObject(key, val); | |
2d21ac55 A |
248 | } |
249 | ||
250 | ||
0a7de745 A |
251 | |
252 | void | |
253 | IOPMPowerSource::setExternalConnected(bool b) | |
254 | { | |
255 | setPSProperty(externalConnectedKey, | |
256 | b ? kOSBooleanTrue : kOSBooleanFalse); | |
4452a7af A |
257 | } |
258 | ||
0a7de745 A |
259 | void |
260 | IOPMPowerSource::setExternalChargeCapable(bool b) | |
261 | { | |
262 | setPSProperty(externalChargeCapableKey, | |
263 | b ? kOSBooleanTrue : kOSBooleanFalse); | |
4452a7af A |
264 | } |
265 | ||
0a7de745 A |
266 | void |
267 | IOPMPowerSource::setBatteryInstalled(bool b) | |
268 | { | |
269 | setPSProperty(batteryInstalledKey, | |
270 | b ? kOSBooleanTrue : kOSBooleanFalse); | |
4452a7af A |
271 | } |
272 | ||
0a7de745 A |
273 | void |
274 | IOPMPowerSource::setIsCharging(bool b) | |
275 | { | |
276 | setPSProperty(chargingKey, | |
277 | b ? kOSBooleanTrue : kOSBooleanFalse); | |
4452a7af A |
278 | } |
279 | ||
0a7de745 A |
280 | void |
281 | IOPMPowerSource::setAtWarnLevel(bool b) | |
282 | { | |
283 | setPSProperty(warnLevelKey, | |
284 | b ? kOSBooleanTrue : kOSBooleanFalse); | |
4452a7af A |
285 | } |
286 | ||
0a7de745 A |
287 | void |
288 | IOPMPowerSource::setAtCriticalLevel(bool b) | |
289 | { | |
290 | setPSProperty(criticalLevelKey, | |
291 | b ? kOSBooleanTrue : kOSBooleanFalse); | |
4452a7af | 292 | } |
5d5c5d0d | 293 | |
0c530ab8 | 294 | |
0a7de745 A |
295 | void |
296 | IOPMPowerSource::setCurrentCapacity(unsigned int val) | |
297 | { | |
298 | OSNumber *n = OSNumber::withNumber(val, 32); | |
299 | setPSProperty(currentCapacityKey, n); | |
300 | n->release(); | |
89b3af67 A |
301 | } |
302 | ||
0a7de745 A |
303 | void |
304 | IOPMPowerSource::setMaxCapacity(unsigned int val) | |
305 | { | |
306 | OSNumber *n = OSNumber::withNumber(val, 32); | |
307 | setPSProperty(maxCapacityKey, n); | |
308 | n->release(); | |
0c530ab8 | 309 | } |
89b3af67 | 310 | |
0a7de745 A |
311 | void |
312 | IOPMPowerSource::setTimeRemaining(int val) | |
313 | { | |
314 | OSNumber *n = OSNumber::withNumber(val, 32); | |
315 | setPSProperty(timeRemainingKey, n); | |
316 | n->release(); | |
4452a7af | 317 | } |
89b3af67 | 318 | |
0a7de745 A |
319 | void |
320 | IOPMPowerSource::setAmperage(int val) | |
321 | { | |
322 | OSNumber *n = OSNumber::withNumber(val, 32); | |
323 | setPSProperty(amperageKey, n); | |
324 | n->release(); | |
0c530ab8 | 325 | } |
89b3af67 | 326 | |
0a7de745 A |
327 | void |
328 | IOPMPowerSource::setVoltage(unsigned int val) | |
329 | { | |
330 | OSNumber *n = OSNumber::withNumber(val, 32); | |
331 | setPSProperty(voltageKey, n); | |
332 | n->release(); | |
0c530ab8 A |
333 | } |
334 | ||
0a7de745 A |
335 | void |
336 | IOPMPowerSource::setCycleCount(unsigned int val) | |
337 | { | |
338 | OSNumber *n = OSNumber::withNumber(val, 32); | |
339 | setPSProperty(cycleCountKey, n); | |
340 | n->release(); | |
0c530ab8 A |
341 | } |
342 | ||
0a7de745 A |
343 | void |
344 | IOPMPowerSource::setAdapterInfo(int val) | |
345 | { | |
346 | OSNumber *n = OSNumber::withNumber(val, 32); | |
347 | setPSProperty(adapterInfoKey, n); | |
348 | n->release(); | |
0c530ab8 A |
349 | } |
350 | ||
0a7de745 A |
351 | void |
352 | IOPMPowerSource::setLocation(int val) | |
353 | { | |
354 | OSNumber *n = OSNumber::withNumber(val, 32); | |
355 | setPSProperty(locationKey, n); | |
356 | n->release(); | |
0c530ab8 A |
357 | } |
358 | ||
0a7de745 A |
359 | void |
360 | IOPMPowerSource::setErrorCondition(OSSymbol *s) | |
361 | { | |
362 | setPSProperty(errorConditionKey, s); | |
0c530ab8 A |
363 | } |
364 | ||
0a7de745 A |
365 | void |
366 | IOPMPowerSource::setManufacturer(OSSymbol *s) | |
367 | { | |
368 | setPSProperty(manufacturerKey, s); | |
0c530ab8 A |
369 | } |
370 | ||
0a7de745 A |
371 | void |
372 | IOPMPowerSource::setModel(OSSymbol *s) | |
373 | { | |
374 | setPSProperty(modelKey, s); | |
0c530ab8 A |
375 | } |
376 | ||
0a7de745 A |
377 | void |
378 | IOPMPowerSource::setSerial(OSSymbol *s) | |
379 | { | |
380 | setPSProperty(serialKey, s); | |
0c530ab8 A |
381 | } |
382 | ||
0a7de745 A |
383 | void |
384 | IOPMPowerSource::setLegacyIOBatteryInfo(OSDictionary *d) | |
385 | { | |
386 | setPSProperty(batteryInfoKey, d); | |
0c530ab8 A |
387 | } |
388 | ||
389 | ||
390 | ||
391 | ||
392 | /******************************************************************************* | |
393 | * | |
394 | * PUBLIC Accessors. All the getters! Boo! | |
395 | * | |
396 | ******************************************************************************/ | |
397 | ||
0a7de745 A |
398 | OSObject * |
399 | IOPMPowerSource::getPSProperty(const OSSymbol *symmie) | |
400 | { | |
401 | if (!symmie) { | |
402 | return NULL; | |
403 | } | |
404 | return properties->getObject(symmie); | |
2d21ac55 A |
405 | } |
406 | ||
0a7de745 A |
407 | bool |
408 | IOPMPowerSource::externalConnected(void) | |
409 | { | |
410 | return kOSBooleanTrue == properties->getObject(externalConnectedKey); | |
0c530ab8 A |
411 | } |
412 | ||
0a7de745 A |
413 | bool |
414 | IOPMPowerSource::externalChargeCapable(void) | |
415 | { | |
416 | return kOSBooleanTrue == properties->getObject(externalChargeCapableKey); | |
0c530ab8 A |
417 | } |
418 | ||
0a7de745 A |
419 | bool |
420 | IOPMPowerSource::batteryInstalled(void) | |
421 | { | |
422 | return kOSBooleanTrue == properties->getObject(batteryInstalledKey); | |
0c530ab8 A |
423 | } |
424 | ||
0a7de745 A |
425 | bool |
426 | IOPMPowerSource::isCharging(void) | |
427 | { | |
428 | return kOSBooleanTrue == properties->getObject(chargingKey); | |
0c530ab8 A |
429 | } |
430 | ||
0a7de745 A |
431 | bool |
432 | IOPMPowerSource::atWarnLevel(void) | |
433 | { | |
434 | return kOSBooleanTrue == properties->getObject(warnLevelKey); | |
0c530ab8 A |
435 | } |
436 | ||
0a7de745 A |
437 | bool |
438 | IOPMPowerSource::atCriticalLevel(void) | |
439 | { | |
440 | return kOSBooleanTrue == properties->getObject(criticalLevelKey); | |
0c530ab8 A |
441 | } |
442 | ||
0a7de745 A |
443 | unsigned int |
444 | IOPMPowerSource::currentCapacity(void) | |
445 | { | |
446 | OSNumber *n; | |
447 | n = OSDynamicCast(OSNumber, properties->getObject(currentCapacityKey)); | |
448 | if (!n) { | |
449 | return 0; | |
450 | } else { | |
451 | return (unsigned int)n->unsigned32BitValue(); | |
452 | } | |
0c530ab8 A |
453 | } |
454 | ||
0a7de745 A |
455 | unsigned int |
456 | IOPMPowerSource::maxCapacity(void) | |
457 | { | |
458 | OSNumber *n; | |
459 | n = OSDynamicCast(OSNumber, properties->getObject(maxCapacityKey)); | |
460 | if (!n) { | |
461 | return 0; | |
462 | } else { | |
463 | return (unsigned int)n->unsigned32BitValue(); | |
464 | } | |
0c530ab8 A |
465 | } |
466 | ||
0a7de745 A |
467 | unsigned int |
468 | IOPMPowerSource::capacityPercentRemaining(void) | |
6601e61a | 469 | { |
0a7de745 A |
470 | unsigned int _currentCapacity = currentCapacity(); |
471 | unsigned int _maxCapacity = maxCapacity(); | |
472 | if (0 == _maxCapacity) { | |
473 | return 0; | |
474 | } else { | |
475 | return (100 * _currentCapacity) / _maxCapacity; | |
476 | } | |
0c530ab8 | 477 | } |
89b3af67 | 478 | |
0a7de745 A |
479 | int |
480 | IOPMPowerSource::timeRemaining(void) | |
481 | { | |
482 | OSNumber *n; | |
483 | n = OSDynamicCast(OSNumber, properties->getObject(timeRemainingKey)); | |
484 | if (!n) { | |
485 | return 0; | |
486 | } else { | |
487 | return (int)n->unsigned32BitValue(); | |
488 | } | |
4452a7af A |
489 | } |
490 | ||
0a7de745 A |
491 | int |
492 | IOPMPowerSource::amperage(void) | |
493 | { | |
494 | OSNumber *n; | |
495 | n = OSDynamicCast(OSNumber, properties->getObject(amperageKey)); | |
496 | if (!n) { | |
497 | return 0; | |
498 | } else { | |
499 | return (int)n->unsigned32BitValue(); | |
500 | } | |
0c530ab8 | 501 | } |
4452a7af | 502 | |
0a7de745 A |
503 | unsigned int |
504 | IOPMPowerSource::voltage(void) | |
505 | { | |
506 | OSNumber *n; | |
507 | n = OSDynamicCast(OSNumber, properties->getObject(voltageKey)); | |
508 | if (!n) { | |
509 | return 0; | |
510 | } else { | |
511 | return (unsigned int)n->unsigned32BitValue(); | |
512 | } | |
0c530ab8 | 513 | } |
4452a7af | 514 | |
0a7de745 A |
515 | unsigned int |
516 | IOPMPowerSource::cycleCount(void) | |
517 | { | |
518 | OSNumber *n; | |
519 | n = OSDynamicCast(OSNumber, properties->getObject(cycleCountKey)); | |
520 | if (!n) { | |
521 | return 0; | |
522 | } else { | |
523 | return (unsigned int)n->unsigned32BitValue(); | |
524 | } | |
0c530ab8 | 525 | } |
4452a7af | 526 | |
0a7de745 A |
527 | int |
528 | IOPMPowerSource::adapterInfo(void) | |
529 | { | |
530 | OSNumber *n; | |
531 | n = OSDynamicCast(OSNumber, properties->getObject(adapterInfoKey)); | |
532 | if (!n) { | |
533 | return 0; | |
534 | } else { | |
535 | return (int)n->unsigned32BitValue(); | |
536 | } | |
0c530ab8 | 537 | } |
4452a7af | 538 | |
0a7de745 A |
539 | int |
540 | IOPMPowerSource::location(void) | |
541 | { | |
542 | OSNumber *n; | |
543 | n = OSDynamicCast(OSNumber, properties->getObject(locationKey)); | |
544 | if (!n) { | |
545 | return 0; | |
546 | } else { | |
547 | return (unsigned int)n->unsigned32BitValue(); | |
548 | } | |
0c530ab8 A |
549 | } |
550 | ||
0a7de745 A |
551 | OSSymbol * |
552 | IOPMPowerSource::errorCondition(void) | |
553 | { | |
554 | return OSDynamicCast(OSSymbol, properties->getObject(errorConditionKey)); | |
0c530ab8 A |
555 | } |
556 | ||
0a7de745 A |
557 | OSSymbol * |
558 | IOPMPowerSource::manufacturer(void) | |
559 | { | |
560 | return OSDynamicCast(OSSymbol, properties->getObject(manufacturerKey)); | |
0c530ab8 A |
561 | } |
562 | ||
0a7de745 A |
563 | OSSymbol * |
564 | IOPMPowerSource::model(void) | |
565 | { | |
566 | return OSDynamicCast(OSSymbol, properties->getObject(modelKey)); | |
0c530ab8 A |
567 | } |
568 | ||
0a7de745 A |
569 | OSSymbol * |
570 | IOPMPowerSource::serial(void) | |
571 | { | |
572 | return OSDynamicCast(OSSymbol, properties->getObject(serialKey)); | |
0c530ab8 A |
573 | } |
574 | ||
0a7de745 A |
575 | OSDictionary * |
576 | IOPMPowerSource::legacyIOBatteryInfo(void) | |
577 | { | |
578 | return OSDynamicCast(OSDictionary, properties->getObject(batteryInfoKey)); | |
0c530ab8 | 579 | } |