1/* 2 * Copyright (c) 1998-2010 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include "IOAudioDebug.h" 24#include "IOAudioDevice.h" 25#include "IOAudioEngine.h" 26#include "IOAudioPort.h" 27#include "IOAudioTypes.h" 28#include "IOAudioDefines.h" 29#include "IOAudioLevelControl.h" 30#include "IOAudioToggleControl.h" 31#include <IOKit/IOWorkLoop.h> 32#include <IOKit/IOCommandGate.h> 33#include <IOKit/IOTimerEventSource.h> 34#include <IOKit/IOKitKeys.h> 35#include <libkern/c++/OSDictionary.h> 36#include <libkern/c++/OSSet.h> 37#include <libkern/c++/OSCollectionIterator.h> 38 39#define NUM_POWER_STATES 2 40 41class IOAudioTimerEvent : public OSObject 42{ 43 friend class IOAudioDevice; 44 45 OSDeclareDefaultStructors(IOAudioTimerEvent) 46 47protected: 48 OSObject * target; 49 IOAudioDevice::TimerEvent event; 50 AbsoluteTime interval; 51}; 52 53OSDefineMetaClassAndStructors(IOAudioTimerEvent, OSObject) 54 55class IOAudioEngineEntry : public OSObject 56{ 57 friend class IOAudioDevice; 58 59 OSDeclareDefaultStructors(IOAudioEngineEntry); 60 61protected: 62 IOAudioEngine *audioEngine; 63 bool shouldStopAudioEngine; 64}; 65 66OSDefineMetaClassAndStructors(IOAudioEngineEntry, OSObject) 67 68#define super IOService 69OSDefineMetaClassAndStructors(IOAudioDevice, IOService) 70OSMetaClassDefineReservedUsed(IOAudioDevice, 0); 71OSMetaClassDefineReservedUsed(IOAudioDevice, 1); 72OSMetaClassDefineReservedUsed(IOAudioDevice, 2); 73OSMetaClassDefineReservedUsed(IOAudioDevice, 3); 74OSMetaClassDefineReservedUsed(IOAudioDevice, 4); 75OSMetaClassDefineReservedUsed(IOAudioDevice, 5); 76 77OSMetaClassDefineReservedUnused(IOAudioDevice, 6); 78OSMetaClassDefineReservedUnused(IOAudioDevice, 7); 79OSMetaClassDefineReservedUnused(IOAudioDevice, 8); 80OSMetaClassDefineReservedUnused(IOAudioDevice, 9); 81OSMetaClassDefineReservedUnused(IOAudioDevice, 10); 82OSMetaClassDefineReservedUnused(IOAudioDevice, 11); 83OSMetaClassDefineReservedUnused(IOAudioDevice, 12); 84OSMetaClassDefineReservedUnused(IOAudioDevice, 13); 85OSMetaClassDefineReservedUnused(IOAudioDevice, 14); 86OSMetaClassDefineReservedUnused(IOAudioDevice, 15); 87OSMetaClassDefineReservedUnused(IOAudioDevice, 16); 88OSMetaClassDefineReservedUnused(IOAudioDevice, 17); 89OSMetaClassDefineReservedUnused(IOAudioDevice, 18); 90OSMetaClassDefineReservedUnused(IOAudioDevice, 19); 91OSMetaClassDefineReservedUnused(IOAudioDevice, 20); 92OSMetaClassDefineReservedUnused(IOAudioDevice, 21); 93OSMetaClassDefineReservedUnused(IOAudioDevice, 22); 94OSMetaClassDefineReservedUnused(IOAudioDevice, 23); 95OSMetaClassDefineReservedUnused(IOAudioDevice, 24); 96OSMetaClassDefineReservedUnused(IOAudioDevice, 25); 97OSMetaClassDefineReservedUnused(IOAudioDevice, 26); 98OSMetaClassDefineReservedUnused(IOAudioDevice, 27); 99OSMetaClassDefineReservedUnused(IOAudioDevice, 28); 100OSMetaClassDefineReservedUnused(IOAudioDevice, 29); 101OSMetaClassDefineReservedUnused(IOAudioDevice, 30); 102OSMetaClassDefineReservedUnused(IOAudioDevice, 31); 103 104// New code added here 105void IOAudioDevice::setDeviceModelName(const char *modelName) 106{ 107 audioDebugIOLog(3, "+ IOAudioDevice[%p]::setDeviceModelName(%p)\n", this, modelName); 108 109 if (modelName) { 110 setProperty(kIOAudioDeviceModelIDKey, modelName); 111 } 112 audioDebugIOLog(3, "- IOAudioDevice[%p]::setDeviceModelName(%p)\n", this, modelName); 113} 114 115void IOAudioDevice::setDeviceTransportType(const UInt32 transportType) 116{ 117 if (transportType) { 118 setProperty(kIOAudioDeviceTransportTypeKey, transportType, 32); 119 } 120} 121 122// This needs to be overridden by driver if it wants to know about power manager changes. 123// If overridden, be sure to still call super::setAggressiveness() so we can call our parent. 124IOReturn IOAudioDevice::setAggressiveness(unsigned long type, unsigned long newLevel) 125{ 126 return super::setAggressiveness(type, newLevel); 127} 128 129// This was modified for <rdar://problem/3942297> 130void IOAudioDevice::setIdleAudioSleepTime(unsigned long long sleepDelay) 131{ 132 assert(reserved); 133 134 audioDebugIOLog(3, "+ IOAudioDevice[%p]::setIdleAudioSleepTime: sleepDelay = %lx%lx\n", this, (long unsigned int)(sleepDelay >> 32), (long unsigned int)sleepDelay); 135 136 if ( reserved->idleTimer ) { 137 reserved->idleTimer->cancelTimeout(); 138 } 139 140 if (reserved->idleSleepDelayTime != sleepDelay) { // <rdar://problem/6601320> 141 reserved->idleSleepDelayTime = sleepDelay; 142 } 143 144 if ( kNoIdleAudioPowerDown != sleepDelay ) { 145 scheduleIdleAudioSleep(); 146 } 147 audioDebugIOLog(3, "- IOAudioDevice[%p]::setIdleAudioSleepTime: sleepDelay = %lx%lx\n", this, (long unsigned int)(sleepDelay >> 32), (long unsigned int)sleepDelay); 148} 149 150// Set up a timer to power down the hardware if we haven't used it in a while. 151// <rdar://8121989> Restructured for single point of entry and single point of exit so that 152// the indentifier post processing tool can properly insert scope when post processing a log file 153// obtained via fwkpfv. 154 155void IOAudioDevice::scheduleIdleAudioSleep(void) 156{ 157 AbsoluteTime fireTime; 158 UInt64 nanos; 159 bool exit = false; 160 161 assert(reserved); 162 163 audioDebugIOLog(3, "+ IOAudioDevice[%p]::scheduleIdleAudioSleep: idleSleepDelayTime = %lx%lx\n", this, (long unsigned int)(reserved->idleSleepDelayTime >> 32), (long unsigned int)reserved->idleSleepDelayTime); 164 if ( 0 == reserved->idleSleepDelayTime ) 165 { 166 // For backwards compatibility, or drivers that don't care, tell them about idle right away. 167 initiatePowerStateChange (); 168 } 169 else 170 { 171 if ( !reserved->idleTimer && ( kNoIdleAudioPowerDown != reserved->idleSleepDelayTime ) ) 172 { 173 reserved->idleTimer = IOTimerEventSource::timerEventSource ( this, idleAudioSleepHandlerTimer ); 174 if ( !reserved->idleTimer ) 175 { 176 exit = true; 177 } 178 else 179 { 180 workLoop->addEventSource ( reserved->idleTimer ); 181 } 182 } 183 184 if ( !exit && ( kNoIdleAudioPowerDown != reserved->idleSleepDelayTime ) ) 185 { 186 // If the driver wants to know about idle sleep after a specific amount of time, then set the timer to tell them at that time. 187 // If idleSleepDelayTime == 0xffffffff then don't ever tell the driver about going idle 188 clock_get_uptime ( &fireTime ); 189 absolutetime_to_nanoseconds ( fireTime, &nanos ); 190 nanos += reserved->idleSleepDelayTime; 191 nanoseconds_to_absolutetime ( nanos, &fireTime ); 192 reserved->idleTimer->wakeAtTime ( fireTime ); // will call idleAudioSleepHandlerTimer 193 } 194 } 195 196 audioDebugIOLog(3, "- IOAudioDevice[%p]::scheduleIdleAudioSleep: idleSleepDelayTime = %lx%lx\n", this, (long unsigned int)(reserved->idleSleepDelayTime >> 32), (long unsigned int)reserved->idleSleepDelayTime); 197 return; 198} 199 200void IOAudioDevice::idleAudioSleepHandlerTimer(OSObject *owner, IOTimerEventSource *sender) 201{ 202 IOAudioDevice * audioDevice; 203 204 audioDevice = OSDynamicCast(IOAudioDevice, owner); 205 assert(audioDevice); 206 207 audioDebugIOLog(3, "+ IOAudioDevice[%p]idleAudioSleepHandlerTimer: pendingPowerState = %d, idleSleepDelayTime = %lx%lx\n", audioDevice, audioDevice->pendingPowerState, (long unsigned int)(audioDevice->reserved->idleSleepDelayTime >> 32), (long unsigned int)audioDevice->reserved->idleSleepDelayTime); 208 if (audioDevice->reserved->idleSleepDelayTime != kNoIdleAudioPowerDown && 209 audioDevice->getPendingPowerState () == kIOAudioDeviceIdle) { 210 // If we're still idle, tell the device to go idle now that the requested amount of time has elapsed. 211 audioDevice->initiatePowerStateChange(); 212 } 213 214 audioDebugIOLog(3, "- IOAudioDevice[%p]idleAudioSleepHandlerTimer: pendingPowerState = %d, idleSleepDelayTime = %lx%lx\n", audioDevice, audioDevice->pendingPowerState, (long unsigned int)(audioDevice->reserved->idleSleepDelayTime >> 32), (long unsigned int)audioDevice->reserved->idleSleepDelayTime); 215 return; 216} 217 218void IOAudioDevice::setConfigurationApplicationBundle(const char *bundleID) 219{ 220 audioDebugIOLog(3, "+ IOAudioDevice[%p]::setConfigurationApplicationBundle(%p)\n", this, bundleID); 221 222 if (bundleID) { 223 setProperty(kIOAudioDeviceConfigurationAppKey, bundleID); 224 } 225 audioDebugIOLog(3, "- IOAudioDevice[%p]::setConfigurationApplicationBundle(%p)\n", this, bundleID); 226} 227 228// OSMetaClassDefineReservedUsed(IOAudioDevice, 4); 229void IOAudioDevice::setDeviceCanBeDefault(UInt32 defaultsFlags) 230{ 231 setProperty(kIOAudioDeviceCanBeDefaults, defaultsFlags, sizeof(UInt32) * 8); 232} 233 234// <rdar://8121989> Restructured for single point of entry and single point of exit so that 235// the indentifier post processing tool can properly insert scope when post processing a log file 236// obtained via fwkpfv. 237 238bool IOAudioDevice::init(OSDictionary *properties) 239{ 240 bool result = false; 241 242 audioDebugIOLog(3, "+ IOAudioDevice[%p]::init(%p)\n", this, properties); 243 244 if ( super::init ( properties ) ) 245 { 246 reserved = (ExpansionData *)IOMalloc (sizeof(struct ExpansionData)); 247 if ( 0 != reserved ) 248 { 249 reserved->idleSleepDelayTime = 0; 250 reserved->idleTimer = NULL; 251 252 audioEngines = OSArray::withCapacity ( 2 ); 253 if ( 0 != audioEngines ) 254 { 255 audioPorts = OSSet::withCapacity ( 1 ); 256 if ( 0 != audioPorts ) 257 { 258 workLoop = IOWorkLoop::workLoop (); 259 if ( 0 != workLoop ) 260 { 261 familyManagePower = true; 262 asyncPowerStateChangeInProgress = false; 263 264 currentPowerState = kIOAudioDeviceIdle; 265 pendingPowerState = kIOAudioDeviceIdle; 266 267 numRunningAudioEngines = 0; 268 duringStartup = true; 269 result = true; 270 } 271 } 272 } 273 } 274 } 275 276 audioDebugIOLog(3, "- IOAudioDevice[%p]::init(%p) returns %d\n", this, properties, result); 277 return result; 278} 279 280void IOAudioDevice::free() 281{ 282 audioDebugIOLog(3, "+ IOAudioDevice[%p]::free()\n", this); 283 284 if (audioEngines) { 285 deactivateAllAudioEngines(); 286 audioEngines->release(); 287 audioEngines = 0; 288 } 289 290 audioDebugIOLog ( 3, " did deactiveateAllAudioEngines ()\n" ); 291 292 if (audioPorts) { 293 detachAllAudioPorts(); 294 audioPorts->release(); 295 audioPorts = 0; 296 } 297 298 audioDebugIOLog ( 3, " did detachAllAudioPorts ()\n" ); 299 300 if (timerEvents) { 301 timerEvents->release(); 302 timerEvents = 0; 303 } 304 305 audioDebugIOLog ( 3, " did timerEvents->release ()\n" ); 306 307 if (timerEventSource) { 308 if (workLoop) { 309 timerEventSource->cancelTimeout(); // <rdar://problem/7493627,8426296> 310 workLoop->removeEventSource(timerEventSource); 311 } 312 313 timerEventSource->release(); 314 timerEventSource = NULL; 315 } 316 317 audioDebugIOLog ( 3, " did workLoop->removeEventSource ( timerEventSource )\n" ); 318 319 if (reserved->idleTimer) { 320 if (workLoop) { 321 reserved->idleTimer->cancelTimeout(); // <rdar://problem/7493627,8426296> 322 workLoop->removeEventSource(reserved->idleTimer); 323 } 324 325 reserved->idleTimer->release(); 326 reserved->idleTimer = NULL; 327 } 328 329 audioDebugIOLog ( 3, " did workLoop->removeEventSource ( reserved->idleTimer )\n" ); 330 331 if (commandGate) { 332 if (workLoop) { 333 workLoop->removeEventSource(commandGate); 334 } 335 336 commandGate->release(); 337 commandGate = NULL; 338 } 339 340 audioDebugIOLog ( 3, " did workLoop->removeEventSource ( commandGate )\n" ); 341 342 if (workLoop) { 343 workLoop->release(); 344 workLoop = NULL; 345 } 346 347 audioDebugIOLog ( 3, " did workLoop->release ()\n" ); 348 349 if (reserved) { 350 IOFree (reserved, sizeof(struct ExpansionData)); 351 } 352 353 audioDebugIOLog ( 3, " did IOFree ()\n" ); 354 355 super::free(); 356 357 audioDebugIOLog(3, "- IOAudioDevice[%p]::free()\n", this); 358} 359 360bool IOAudioDevice::initHardware(IOService *provider) 361{ 362 audioDebugIOLog(3, "+-IOAudioDevice[%p]::initHardware(%p)\n", this, provider); 363 364 return true; 365} 366 367// <rdar://8121989> Restructured for single point of entry and single point of exit so that 368// the indentifier post processing tool can properly insert scope when post processing a log file 369// obtained via fwkpfv. 370 371bool IOAudioDevice::start(IOService *provider) 372{ 373 bool result = false; 374 375 static IOPMPowerState powerStates[2] = { 376 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 377 {1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0} 378 }; 379 380 audioDebugIOLog(3, "+ IOAudioDevice[%p]::start(%p)\n", this, provider); 381 382 if ( super::start ( provider ) ) 383 { 384 if ( 0 != provider->getProperty("preserveIODeviceTree\n") ) // <rdar://3206968> 385 { 386 provider->callPlatformFunction("mac-io-publishChildren\n", 0, (void*)this, (void*)0, (void*)0, (void*)0); 387 } 388 389 assert(workLoop); 390 391 commandGate = IOCommandGate::commandGate(this); 392 if ( 0 != commandGate) 393 { 394 workLoop->addEventSource(commandGate); 395 396 setDeviceCanBeDefault (kIOAudioDeviceCanBeDefaultInput | kIOAudioDeviceCanBeDefaultOutput | kIOAudioDeviceCanBeSystemOutput); 397 398 if ( initHardware ( provider ) ) 399 { 400 if ( familyManagePower ) { 401 PMinit (); 402 provider->joinPMtree ( this ); 403 404 if ( NULL != pm_vars ) { 405 // duringStartup = true; 406 registerPowerDriver ( this, powerStates, NUM_POWER_STATES ); 407 changePowerStateTo ( 1 ); 408 // duringStartup = false; 409 } 410 } 411 412 registerService(); 413 result = true; 414 } 415 } 416 } 417 418 audioDebugIOLog(3, "- IOAudioDevice[%p]::start(%p)\n", this, provider); 419 return result; 420} 421 422void IOAudioDevice::stop(IOService *provider) 423{ 424 audioDebugIOLog(3, "+ IOAudioDevice[%p]::stop(%p)\n", this, provider); 425 426 removeAllTimerEvents(); // <rdar://problem/7493627,8426296> 427 428 if (timerEventSource) { 429 if (workLoop) { 430 timerEventSource->cancelTimeout(); // <rdar://problem/7493627,8426296> 431 workLoop->removeEventSource(timerEventSource); 432 } 433 434 timerEventSource->release(); 435 timerEventSource = NULL; 436 } 437 438 if (reserved->idleTimer) { 439 if (workLoop) { 440 reserved->idleTimer->cancelTimeout(); // <rdar://problem/7493627,8426296> 441 workLoop->removeEventSource(reserved->idleTimer); 442 } 443 444 reserved->idleTimer->release(); 445 reserved->idleTimer = NULL; 446 } 447 448 deactivateAllAudioEngines(); 449 detachAllAudioPorts(); 450 451 if (familyManagePower) { 452 if (pm_vars != NULL) { 453 PMstop(); 454 } 455 } 456 457 if (commandGate) { 458 if (workLoop) { 459 workLoop->removeEventSource(commandGate); 460 } 461 462 commandGate->release(); 463 commandGate = NULL; 464 } 465 466 super::stop(provider); 467 audioDebugIOLog(3, "- IOAudioDevice[%p]::stop(%p)\n", this, provider); 468} 469 470bool IOAudioDevice::willTerminate(IOService *provider, IOOptionBits options) 471{ 472 bool result = false; 473 474 audioDebugIOLog(3, "+ IOAudioDevice[%p]::willTerminate(%p, %lx)\n", this, provider, (long unsigned int)options); 475 476 OSCollectionIterator *engineIterator; 477 478 engineIterator = OSCollectionIterator::withCollection(audioEngines); 479 if (engineIterator) { 480 IOAudioEngine *audioEngine; 481 482 while ( (audioEngine = OSDynamicCast(IOAudioEngine, engineIterator->getNextObject())) ) { 483 audioEngine->setState(kIOAudioEngineStopped); 484 } 485 engineIterator->release(); 486 } 487 488 result = super::willTerminate(provider, options); 489 audioDebugIOLog(3, "- IOAudioDevice[%p]::willTerminate(%p, %lx) returns %d\n", this, provider, (long unsigned int)options, result ); 490 return result; 491} 492 493void IOAudioDevice::setFamilyManagePower(bool manage) 494{ 495 familyManagePower = manage; 496} 497 498IOReturn IOAudioDevice::setPowerState(unsigned long powerStateOrdinal, IOService *device) 499{ 500 IOReturn result = IOPMAckImplied; 501 502 audioDebugIOLog(3, "+ IOAudioDevice[%p]::setPowerState(%lu, %p)\n", this, powerStateOrdinal, device); 503 if (!duringStartup) 504 { 505 if (powerStateOrdinal >= NUM_POWER_STATES) 506 { 507 result = IOPMNoSuchState; 508 } else 509 { 510 if (workLoop) { // <rdar://8508064> 511 workLoop->runAction(_setPowerStateAction, this, (void *)powerStateOrdinal, (void *)device); // <rdar://8508064> 512 } 513 } 514 } 515 duringStartup = false; 516 audioDebugIOLog(3, "- IOAudioDevice[%p]::setPowerState(%lu, %p) returns 0x%lX\n", this, powerStateOrdinal, device, (long unsigned int)result ); 517 return result; 518} 519 520// <rdar://8508064> 521IOReturn IOAudioDevice::_setPowerStateAction(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3) 522{ 523 IOReturn result = IOPMAckImplied; 524 525 if (target) { 526 IOAudioDevice *audioDevice = OSDynamicCast(IOAudioDevice, target); 527 if (audioDevice) { 528 IOCommandGate *cg; 529 530 cg = audioDevice->getCommandGate(); 531 532 if (cg) { 533 result = cg->runAction(setPowerStateAction, arg0, arg1, arg2, arg3); 534 } 535 } 536 } 537 538 return result; 539} 540 541IOReturn IOAudioDevice::setPowerStateAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) 542{ 543 IOReturn result = IOPMAckImplied; 544 545 if (owner) { 546 IOAudioDevice *audioDevice = OSDynamicCast(IOAudioDevice, owner); 547 548 if (audioDevice) { 549 result = audioDevice->protectedSetPowerState((unsigned long)arg1, (IOService *)arg2); 550 } 551 } 552 553 return result; 554} 555 556IOReturn IOAudioDevice::protectedSetPowerState(unsigned long powerStateOrdinal, IOService *device) 557{ 558 IOReturn result = IOPMAckImplied; 559 560 audioDebugIOLog(3, "+ IOAudioDevice[%p]::protectedSetPowerState(%lu, %p)\n", this, powerStateOrdinal, device); 561 562 if (asyncPowerStateChangeInProgress) { 563 waitForPendingPowerStateChange(); 564 } 565 566 if (powerStateOrdinal == 0) { // Sleep 567 if (getPowerState() != kIOAudioDeviceSleep) { 568 pendingPowerState = kIOAudioDeviceSleep; 569 570 // Stop all audio engines 571 if (audioEngines && (numRunningAudioEngines > 0)) { 572 OSCollectionIterator *audioEngineIterator; 573 574 audioEngineIterator = OSCollectionIterator::withCollection(audioEngines); 575 576 if (audioEngineIterator) { 577 IOAudioEngine *audioEngine; 578 579 while ( (audioEngine = (IOAudioEngine *)audioEngineIterator->getNextObject()) ) { 580 if (audioEngine->getState() == kIOAudioEngineRunning) { 581 audioEngine->pauseAudioEngine(); 582 } 583 } 584 585 audioEngineIterator->release(); 586 } 587 } 588 } 589 } else if (powerStateOrdinal == 1) { // Wake 590 if (getPowerState() == kIOAudioDeviceSleep) { // Need to change state if sleeping 591 if (numRunningAudioEngines == 0) { 592 pendingPowerState = kIOAudioDeviceIdle; 593 } else { 594 pendingPowerState = kIOAudioDeviceActive; 595 } 596 } 597 } 598 599 if (currentPowerState != pendingPowerState) { 600 UInt32 microsecondsUntilComplete = 0; 601 602 result = initiatePowerStateChange(µsecondsUntilComplete); 603 if (result == kIOReturnSuccess) { 604 result = microsecondsUntilComplete; 605 } 606 } 607 608 audioDebugIOLog(3, "- IOAudioDevice[%p]::protectedSetPowerState(%lu, %p) returns 0x%lX\n", this, powerStateOrdinal, device, (long unsigned int)result ); 609 return result; 610} 611 612void IOAudioDevice::waitForPendingPowerStateChange() 613{ 614 audioDebugIOLog(3, "+ IOAudioDevice[%p]::waitForPendingPowerStateChange()\n", this); 615 616 if (asyncPowerStateChangeInProgress) { 617 IOCommandGate *cg; 618 619 cg = getCommandGate(); 620 621 if (cg) { 622 cg->commandSleep((void *)&asyncPowerStateChangeInProgress); 623 assert(!asyncPowerStateChangeInProgress); 624 } else { 625 IOLog("IOAudioDevice[%p]::waitForPendingPowerStateChange() - internal error - unable to get the command gate.\n", this); 626 } 627 } 628 audioDebugIOLog(3, "- IOAudioDevice[%p]::waitForPendingPowerStateChange()\n", this); 629 return; 630} 631 632IOReturn IOAudioDevice::initiatePowerStateChange(UInt32 *microsecondsUntilComplete) 633{ 634 IOReturn result = kIOReturnSuccess; 635 636 audioDebugIOLog(3, "+ IOAudioDevice[%p]::initiatePowerStateChange(%p) - current = %d - pending = %d\n", this, microsecondsUntilComplete, currentPowerState, pendingPowerState); 637 638 if (currentPowerState != pendingPowerState) { 639 UInt32 localMicsUntilComplete, *micsUntilComplete = NULL; 640 641 if (microsecondsUntilComplete != NULL) { 642 micsUntilComplete = microsecondsUntilComplete; 643 } else { 644 micsUntilComplete = &localMicsUntilComplete; 645 } 646 647 *micsUntilComplete = 0; 648 649 asyncPowerStateChangeInProgress = true; 650 651 result = performPowerStateChange(currentPowerState, pendingPowerState, micsUntilComplete); 652 653 if (result == kIOReturnSuccess) { 654 if (*micsUntilComplete == 0) { 655 asyncPowerStateChangeInProgress = false; 656 protectedCompletePowerStateChange(); 657 } 658 } else { 659 asyncPowerStateChangeInProgress = false; 660 } 661 } 662 663 audioDebugIOLog(3, "- IOAudioDevice[%p]::initiatePowerStateChange(%p) - current = %d - pending = %d returns 0x%lX\n", this, microsecondsUntilComplete, currentPowerState, pendingPowerState, (long unsigned int)result ); 664 return result; 665} 666 667IOReturn IOAudioDevice::completePowerStateChange() 668{ 669 IOReturn result = kIOReturnError; 670 IOCommandGate *cg; 671 672 cg = getCommandGate(); 673 674 if (cg) { 675 result = cg->runAction(completePowerStateChangeAction); 676 } 677 678 return result; 679} 680 681IOReturn IOAudioDevice::completePowerStateChangeAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) 682{ 683 IOReturn result = kIOReturnBadArgument; 684 685 if (owner) { 686 IOAudioDevice *audioDevice = OSDynamicCast(IOAudioDevice, owner); 687 688 if (audioDevice) { 689 result = audioDevice->protectedCompletePowerStateChange(); 690 } 691 } 692 693 return result; 694} 695 696IOReturn IOAudioDevice::protectedCompletePowerStateChange() 697{ 698 IOReturn result = kIOReturnSuccess; 699 700 audioDebugIOLog(3, "+ IOAudioDevice[%p]::protectedCompletePowerStateChange() - current = %d - pending = %d\n", this, currentPowerState, pendingPowerState); 701 702 if (currentPowerState != pendingPowerState) { 703 IOCommandGate *cg; 704 705 cg = getCommandGate(); 706 // If we're waking, we fire off the timers and resync them 707 // Then restart the audio engines that were running before the sleep 708 if (currentPowerState == kIOAudioDeviceSleep) { 709 clock_get_uptime(&previousTimerFire); 710 SUB_ABSOLUTETIME(&previousTimerFire, &minimumInterval); 711 712 if (timerEvents && (timerEvents->getCount() > 0)) { 713 dispatchTimerEvents(true); 714 } 715 716 if (audioEngines && (numRunningAudioEngines > 0)) { 717 OSCollectionIterator *audioEngineIterator; 718 719 audioEngineIterator = OSCollectionIterator::withCollection(audioEngines); 720 721 if (audioEngineIterator) { 722 IOAudioEngine *audioEngine; 723 724 while ( (audioEngine = (IOAudioEngine *)audioEngineIterator->getNextObject()) ) { 725 if (audioEngine->getState() == kIOAudioEnginePaused) { 726 audioEngine->resumeAudioEngine(); 727 } 728 } 729 730 audioEngineIterator->release(); 731 } 732 } 733 } 734 735 if (asyncPowerStateChangeInProgress) { 736 acknowledgeSetPowerState(); 737 asyncPowerStateChangeInProgress = false; 738 739 if (cg) { 740 cg->commandWakeup((void *)&asyncPowerStateChangeInProgress); 741 } 742 } 743 744 currentPowerState = pendingPowerState; 745 746 if (cg) { 747 cg->commandWakeup(¤tPowerState); 748 } 749 } 750 751 audioDebugIOLog(3, "- IOAudioDevice[%p]::protectedCompletePowerStateChange() - current = %d - pending = %d returns 0x%lX\n", this, currentPowerState, pendingPowerState, (long unsigned int)result ); 752 return result; 753} 754 755IOReturn IOAudioDevice::performPowerStateChange(IOAudioDevicePowerState oldPowerState, 756 IOAudioDevicePowerState newPowerState, 757 UInt32 *microsecondsUntilComplete) 758{ 759 return kIOReturnSuccess; 760} 761 762IOAudioDevicePowerState IOAudioDevice::getPowerState() 763{ 764 return currentPowerState; 765} 766 767IOAudioDevicePowerState IOAudioDevice::getPendingPowerState() 768{ 769 return pendingPowerState; 770} 771 772void IOAudioDevice::audioEngineStarting() 773{ 774 audioDebugIOLog(3, "+ IOAudioDevice[%p]::audioEngineStarting() - numRunningAudioEngines = %ld\n", this, (long int)( numRunningAudioEngines + 1 ) ); 775 776 numRunningAudioEngines++; 777 778 if (numRunningAudioEngines == 1) { // First audio engine starting - need to be in active state 779 if (getPowerState() == kIOAudioDeviceIdle) { // Go active 780 if (asyncPowerStateChangeInProgress) { // Sleep if there is a transition in progress 781 waitForPendingPowerStateChange(); 782 } 783 784 pendingPowerState = kIOAudioDeviceActive; 785 786 initiatePowerStateChange(); 787 788 if (asyncPowerStateChangeInProgress) { // Sleep if there is a transition in progress 789 waitForPendingPowerStateChange(); 790 } 791 } else if (getPendingPowerState () != kIOAudioDeviceSleep) { 792 // Make sure that when the idle timer fires that we won't go to sleep. 793 pendingPowerState = kIOAudioDeviceActive; 794 } 795 } 796 audioDebugIOLog(3, "- IOAudioDevice[%p]::audioEngineStarting() - numRunningAudioEngines = %ld\n", this, (long int)( numRunningAudioEngines + 1 ) ); 797} 798 799void IOAudioDevice::audioEngineStopped() 800{ 801 audioDebugIOLog(3, "+ IOAudioDevice[%p]::audioEngineStopped() - numRunningAudioEngines = %ld\n", this, (long int)( numRunningAudioEngines - 1 ) ); 802 803 numRunningAudioEngines--; 804 805 if (numRunningAudioEngines == 0) { // Last audio engine stopping - need to be idle 806 if (getPowerState() == kIOAudioDeviceActive) { // Go idle 807 if (asyncPowerStateChangeInProgress) { // Sleep if there is a transition in progress 808 waitForPendingPowerStateChange(); 809 } 810 811 pendingPowerState = kIOAudioDeviceIdle; 812 813 scheduleIdleAudioSleep(); 814 } 815 } 816 audioDebugIOLog(3, "- IOAudioDevice[%p]::audioEngineStopped() - numRunningAudioEngines = %ld\n", this, (long int)( numRunningAudioEngines - 1 ) ); 817} 818 819IOWorkLoop *IOAudioDevice::getWorkLoop() const 820{ 821 return workLoop; 822} 823 824IOCommandGate *IOAudioDevice::getCommandGate() const 825{ 826 return commandGate; 827} 828 829void IOAudioDevice::setDeviceName(const char *deviceName) 830{ 831 audioDebugIOLog(3, "+ IOAudioDevice[%p]::setDeviceName(%p)\n", this, deviceName); 832 833 if (deviceName) { 834 setProperty(kIOAudioDeviceNameKey, deviceName); 835 if (NULL == getProperty (kIOAudioDeviceModelIDKey)) { 836 int stringLen, tempLength; 837 char * string; 838 839 stringLen = 1; 840 stringLen += strlen (deviceName) + 1; 841 stringLen += strlen (getName ()); 842 string = (char *)IOMalloc (stringLen); 843 if ( string ) // we should not panic for this 844 { 845 strncpy (string, getName (), stringLen); 846 tempLength = strlen ("."); // <rdar://problem/6411827> 847 strncat (string, ":", tempLength); 848 tempLength = strlen (deviceName); // <rdar://problem/6411827> 849 strncat (string, deviceName, tempLength); 850 setDeviceModelName (string); 851 IOFree (string, stringLen); 852 } 853 } 854 } 855 audioDebugIOLog(3, "- IOAudioDevice[%p]::setDeviceName(%p)\n", this, deviceName); 856} 857 858void IOAudioDevice::setDeviceShortName(const char *shortName) 859{ 860 audioDebugIOLog(3, "+ IOAudioDevice[%p]::setDeviceShortName(%p)\n", this, shortName); 861 862 if (shortName) { 863 setProperty(kIOAudioDeviceShortNameKey, shortName); 864 } 865 audioDebugIOLog(3, "- IOAudioDevice[%p]::setDeviceShortName(%p)\n", this, shortName); 866} 867 868void IOAudioDevice::setManufacturerName(const char *manufacturerName) 869{ 870 audioDebugIOLog(3, "+ IOAudioDevice[%p]::setManufacturerName(%p)\n", this, manufacturerName); 871 872 if (manufacturerName) { 873 setProperty(kIOAudioDeviceManufacturerNameKey, manufacturerName); 874 } 875 audioDebugIOLog(3, "- IOAudioDevice[%p]::setManufacturerName(%p)\n", this, manufacturerName); 876} 877 878IOReturn IOAudioDevice::activateAudioEngine(IOAudioEngine *audioEngine) 879{ 880 return activateAudioEngine(audioEngine, true); 881} 882 883// <rdar://8121989> Restructured for single point of entry and single point of exit so that 884// the indentifier post processing tool can properly insert scope when post processing a log file 885// obtained via fwkpfv. 886 887IOReturn IOAudioDevice::activateAudioEngine(IOAudioEngine *audioEngine, bool shouldStartAudioEngine) 888{ 889 IOReturn result = kIOReturnBadArgument; 890 891 audioDebugIOLog(3, "+ IOAudioDevice[%p]::activateAudioEngine(%p, %d)\n", this, audioEngine, shouldStartAudioEngine); 892 893 if ( audioEngine && audioEngines ) 894 { 895 if ( !audioEngine->attach ( this ) ) 896 { 897 result = kIOReturnError; 898 } 899 else 900 { 901 if ( shouldStartAudioEngine ) 902 { 903 if (!audioEngine->start ( this ) ) 904 { 905 audioEngine->detach ( this ); 906 result = kIOReturnError; 907 } 908 else 909 { 910 result = kIOReturnSuccess; 911 } 912 } 913 else // <rdar://8681286> 914 { 915 result = kIOReturnSuccess; 916 } 917 918 if ( kIOReturnSuccess == result ) // <rdar://8681286> 919 { 920 audioEngine->deviceStartedAudioEngine = shouldStartAudioEngine; 921 922 audioEngines->setObject ( audioEngine ); 923 audioEngine->setIndex ( audioEngines->getCount() - 1 ); 924 925 audioEngine->registerService (); 926 } 927 } 928 } 929 930 audioDebugIOLog(3, "- IOAudioDevice[%p]::activateAudioEngine(%p, %d) returns 0x%lX\n", this, audioEngine, shouldStartAudioEngine, (long unsigned int)result ); 931 return result; 932} 933 934// <rdar://8121989> Restructured for single point of entry and single point of exit so that 935// the indentifier post processing tool can properly insert scope when post processing a log file 936// obtained via fwkpfv. 937 938void IOAudioDevice::deactivateAllAudioEngines() 939{ 940 OSCollectionIterator *engineIterator; 941 942 audioDebugIOLog(3, "+ IOAudioDevice[%p]::deactivateAllAudioEngines()\n", this); 943 944 if ( audioEngines ) 945 { 946 engineIterator = OSCollectionIterator::withCollection ( audioEngines ); 947 if ( engineIterator ) 948 { 949 IOAudioEngine *audioEngine; 950 951 while ( (audioEngine = OSDynamicCast ( IOAudioEngine, engineIterator->getNextObject ()) ) ) 952 { 953 audioEngine->stopAudioEngine (); 954 if ( !isInactive () ) 955 { 956 audioEngine->terminate (); 957 } 958 } 959 engineIterator->release (); 960 } 961 962 audioEngines->flushCollection (); 963 } 964 965 audioDebugIOLog(3, "- IOAudioDevice[%p]::deactivateAllAudioEngines()\n", this); 966 return; 967} 968 969IOReturn IOAudioDevice::attachAudioPort(IOAudioPort *port, IORegistryEntry *parent, IORegistryEntry *child) 970{ 971 return kIOReturnSuccess; 972} 973 974void IOAudioDevice::detachAllAudioPorts() 975{ 976} 977 978void IOAudioDevice::flushAudioControls() 979{ 980 audioDebugIOLog(3, "+ IOAudioDevice[%p]::flushAudioControls()\n", this); 981 982 if (audioPorts) { 983 OSCollectionIterator *portIterator; 984 985 portIterator = OSCollectionIterator::withCollection(audioPorts); 986 if (portIterator) { 987 IOAudioPort *audioPort; 988 989 while ( (audioPort = (IOAudioPort *)portIterator->getNextObject()) ) { 990 if (OSDynamicCast(IOAudioPort, audioPort)) { 991 if (audioPort->audioControls) { 992 OSCollectionIterator *controlIterator; 993 994 controlIterator = OSCollectionIterator::withCollection(audioPort->audioControls); 995 996 if (controlIterator) { 997 IOAudioControl *audioControl; 998 999 while ( (audioControl = (IOAudioControl *)controlIterator->getNextObject()) ) { 1000 audioControl->flushValue(); 1001 } 1002 controlIterator->release(); 1003 } 1004 } 1005 } 1006 } 1007 portIterator->release(); 1008 } 1009 } 1010 1011 // This code will flush controls attached to an IOAudioPort and a default on a audio engine 1012 // more than once 1013 // We need to update this to create a single master list of controls and use that to flush 1014 // each only once 1015 if (audioEngines) { 1016 OSCollectionIterator *audioEngineIterator; 1017 1018 audioEngineIterator = OSCollectionIterator::withCollection(audioEngines); 1019 if (audioEngineIterator) { 1020 IOAudioEngine *audioEngine; 1021 1022 while ( (audioEngine = (IOAudioEngine *)audioEngineIterator->getNextObject()) ) { 1023 if (audioEngine->defaultAudioControls) { 1024 OSCollectionIterator *controlIterator; 1025 1026 controlIterator = OSCollectionIterator::withCollection(audioEngine->defaultAudioControls); 1027 if (controlIterator) { 1028 IOAudioControl *audioControl; 1029 1030 while ( (audioControl = (IOAudioControl *)controlIterator->getNextObject()) ) { 1031 audioControl->flushValue(); 1032 } 1033 controlIterator->release(); 1034 } 1035 } 1036 } 1037 1038 audioEngineIterator->release(); 1039 } 1040 } 1041 audioDebugIOLog(3, "- IOAudioDevice[%p]::flushAudioControls()\n", this); 1042} 1043 1044// <rdar://8121989> Restructured for single point of entry and single point of exit so that 1045// the indentifier post processing tool can properly insert scope when post processing a log file 1046// obtained via fwkpfv. 1047 1048IOReturn IOAudioDevice::addTimerEvent(OSObject *target, TimerEvent event, AbsoluteTime interval) 1049{ 1050 IOReturn result = kIOReturnSuccess; 1051 IOAudioTimerEvent * newEvent; 1052 1053#ifdef DEBUG 1054 UInt64 newInt; 1055 absolutetime_to_nanoseconds(interval, &newInt); 1056 audioDebugIOLog(3, "+ IOAudioDevice::addTimerEvent(%p, %p, %lums)\n", target, event, (long unsigned int)(newInt/1000000)); 1057#endif 1058 1059 if ( !event ) 1060 { 1061 result = kIOReturnBadArgument; 1062 } 1063 else 1064 { 1065 newEvent = new IOAudioTimerEvent; 1066 newEvent->target = target; 1067 newEvent->event = event; 1068 newEvent->interval = interval; 1069 1070 if (!timerEvents) { 1071 IOWorkLoop *wl; 1072 1073 timerEvents = OSDictionary::withObjects((const OSObject **)&newEvent, (const OSSymbol **)&target, 1, 1); 1074 1075 timerEventSource = IOTimerEventSource::timerEventSource(this, timerFired); 1076 wl = getWorkLoop(); 1077 if ( !timerEventSource || !wl || ( kIOReturnSuccess != wl->addEventSource ( timerEventSource ) ) ) 1078 { 1079 result = kIOReturnError; 1080 } 1081 else 1082 { 1083 timerEventSource->enable (); 1084 } 1085 } 1086 else 1087 { 1088 timerEvents->setObject((OSSymbol *)target, newEvent); 1089 } 1090 1091 if ( kIOReturnSuccess == result ) 1092 { 1093 newEvent->release(); 1094 1095 assert(timerEvents); 1096 1097 if (timerEvents->getCount() == 1) { 1098 AbsoluteTime nextTimerFire; 1099 1100 minimumInterval = interval; 1101 1102 assert(timerEventSource); 1103 1104 clock_get_uptime(&previousTimerFire); 1105 1106 nextTimerFire = previousTimerFire; 1107 ADD_ABSOLUTETIME(&nextTimerFire, &minimumInterval); 1108 1109 result = timerEventSource->wakeAtTime(nextTimerFire); 1110 1111#ifdef DEBUG 1112 { 1113 UInt64 nanos; 1114 absolutetime_to_nanoseconds(minimumInterval, &nanos); 1115#ifdef __LP64__ 1116 audioDebugIOLog(5, " scheduling timer to fire in %lums - previousTimerFire = {%llu}\n", (long unsigned int) (nanos / 1000000), previousTimerFire); 1117#else /* __LP64__ */ 1118 audioDebugIOLog(5, " scheduling timer to fire in %lums - previousTimerFire = {%ld,%lu}\n", (long unsigned int) (nanos / 1000000), previousTimerFire.hi, previousTimerFire.lo); 1119#endif /* __LP64__ */ 1120 } 1121#endif 1122 1123 if (result != kIOReturnSuccess) { 1124 IOLog("IOAudioDevice::addTimerEvent() - error 0x%x setting timer wake time - timer events will be disabled.\n", result); 1125 } 1126 } else if (CMP_ABSOLUTETIME(&interval, &minimumInterval) < 0) { 1127 AbsoluteTime currentNextFire, desiredNextFire; 1128 1129 clock_get_uptime(&desiredNextFire); 1130 ADD_ABSOLUTETIME(&desiredNextFire, &interval); 1131 1132 currentNextFire = previousTimerFire; 1133 ADD_ABSOLUTETIME(¤tNextFire, &minimumInterval); 1134 1135 minimumInterval = interval; 1136 1137 if (CMP_ABSOLUTETIME(&desiredNextFire, ¤tNextFire) < 0) { 1138 assert(timerEventSource); 1139 1140#ifdef DEBUG 1141 { 1142 UInt64 nanos; 1143 absolutetime_to_nanoseconds(interval, &nanos); 1144#ifdef __LP64__ 1145 audioDebugIOLog(5, " scheduling timer to fire in %lums at {%llu} - previousTimerFire = {%llu}\n", (long unsigned int) (nanos / 1000000), desiredNextFire, previousTimerFire); 1146#else /* __LP64__ */ 1147 audioDebugIOLog(5, " scheduling timer to fire in %lums at {%ld,%lu} - previousTimerFire = {%ld,%lu}\n", (long unsigned int) (nanos / 1000000), desiredNextFire.hi, desiredNextFire.lo, previousTimerFire.hi, previousTimerFire.lo); 1148#endif /* __LP64__ */ 1149 } 1150#endif 1151 1152 result = timerEventSource->wakeAtTime(desiredNextFire); 1153 if (result != kIOReturnSuccess) { 1154 IOLog("IOAudioDevice::addTimerEvent() - error 0x%x setting timer wake time - timer events will be disabled.\n", result); 1155 } 1156 } 1157 } 1158 } 1159 } 1160 1161#ifdef DEBUG 1162 audioDebugIOLog(3, "- IOAudioDevice::addTimerEvent(%p, %p, %lums) returns 0x%lX\n", target, event, (long unsigned int)(newInt/1000000), (long unsigned int)result ); 1163#endif 1164 return result; 1165} 1166 1167// <rdar://8121989> Restructured for single point of entry and single point of exit so that 1168// the indentifier post processing tool can properly insert scope when post processing a log file 1169// obtained via fwkpfv. 1170 1171void IOAudioDevice::removeTimerEvent(OSObject *target) 1172{ 1173 IOAudioTimerEvent *removedTimerEvent; 1174 1175 audioDebugIOLog(3, "+ IOAudioDevice::removeTimerEvent(%p)\n", target); 1176 1177 if ( timerEvents ) 1178 { 1179 removedTimerEvent = (IOAudioTimerEvent *)timerEvents->getObject((const OSSymbol *)target); 1180 if (removedTimerEvent) { 1181 removedTimerEvent->retain(); 1182 timerEvents->removeObject((const OSSymbol *)target); 1183 if (timerEvents->getCount() == 0) { 1184 assert(timerEventSource); 1185 timerEventSource->cancelTimeout(); 1186 } else if (CMP_ABSOLUTETIME(&removedTimerEvent->interval, &minimumInterval) <= 0) { // Need to find a new minimum interval 1187 OSCollectionIterator *iterator; 1188 IOAudioTimerEvent *timerEvent; 1189 AbsoluteTime nextTimerFire; 1190 OSSymbol *obj; 1191 1192 iterator = OSCollectionIterator::withCollection(timerEvents); 1193 1194 if (iterator) { 1195 obj = (OSSymbol *)iterator->getNextObject(); 1196 timerEvent = (IOAudioTimerEvent *)timerEvents->getObject(obj); 1197 1198 if (timerEvent) { 1199 minimumInterval = timerEvent->interval; 1200 1201 while ((obj = (OSSymbol *)iterator->getNextObject()) && (timerEvent = (IOAudioTimerEvent *)timerEvents->getObject(obj))) { 1202 if (CMP_ABSOLUTETIME(&timerEvent->interval, &minimumInterval) < 0) { 1203 minimumInterval = timerEvent->interval; 1204 } 1205 } 1206 } 1207 1208 iterator->release(); 1209 } 1210 1211 assert(timerEventSource); 1212 1213 nextTimerFire = previousTimerFire; 1214 ADD_ABSOLUTETIME(&nextTimerFire, &minimumInterval); 1215 1216#ifdef DEBUG 1217 { 1218 AbsoluteTime now, then; 1219 UInt64 nanos, mi; 1220 clock_get_uptime(&now); 1221 then = nextTimerFire; 1222 absolutetime_to_nanoseconds(minimumInterval, &mi); 1223 if (CMP_ABSOLUTETIME(&then, &now)) { 1224 SUB_ABSOLUTETIME(&then, &now); 1225 absolutetime_to_nanoseconds(then, &nanos); 1226#ifdef __LP64__ 1227 audioDebugIOLog(5, "IOAudioDevice::removeTimerEvent() - scheduling timer to fire in %lums at {%llu} - previousTimerFire = {%llu} - interval=%lums\n", (long unsigned int) (nanos / 1000000), nextTimerFire, previousTimerFire, (long unsigned int)(mi/1000000)); 1228#else /* __LP64__ */ 1229 audioDebugIOLog(5, "IOAudioDevice::removeTimerEvent() - scheduling timer to fire in %lums at {%ld,%lu} - previousTimerFire = {%ld,%lu} - interval=%lums\n", (long unsigned int) (nanos / 1000000), nextTimerFire.hi, nextTimerFire.lo, previousTimerFire.hi, previousTimerFire.lo, (long unsigned int)(mi/1000000)); 1230#endif /* __LP64__ */ 1231 1232 1233 } else { 1234 SUB_ABSOLUTETIME(&now, &then); 1235 absolutetime_to_nanoseconds(now, &nanos); 1236#ifdef __LP64__ 1237 audioDebugIOLog(5, "IOAudioDevice::removeTimerEvent() - scheduling timer to fire in -%lums - previousTimerFire = {%llu}\n", (long unsigned int) (nanos / 1000000), previousTimerFire); 1238#else /* __LP64__ */ 1239 audioDebugIOLog(5, "IOAudioDevice::removeTimerEvent() - scheduling timer to fire in -%lums - previousTimerFire = {%ld,%lu}\n", (long unsigned int) (nanos / 1000000), previousTimerFire.hi, previousTimerFire.lo); 1240#endif /* __LP64__ */ 1241 1242 } 1243 } 1244#endif 1245 1246 timerEventSource->wakeAtTime(nextTimerFire); 1247 } 1248 1249 removedTimerEvent->release(); 1250 } 1251 } 1252 audioDebugIOLog(3, "- IOAudioDevice::removeTimerEvent(%p)\n", target); 1253 return; 1254} 1255 1256void IOAudioDevice::removeAllTimerEvents() 1257{ 1258 audioDebugIOLog(3, "+ IOAudioDevice[%p]::removeAllTimerEvents()\n", this); 1259 1260 if (timerEventSource) { 1261 timerEventSource->cancelTimeout(); 1262 } 1263 1264 if (timerEvents) { 1265 timerEvents->flushCollection(); 1266 } 1267 audioDebugIOLog(3, "- IOAudioDevice[%p]::removeAllTimerEvents()\n", this); 1268} 1269 1270void IOAudioDevice::timerFired(OSObject *target, IOTimerEventSource *sender) 1271{ 1272 if (target) { 1273 IOAudioDevice *audioDevice = OSDynamicCast(IOAudioDevice, target); 1274 1275 if (audioDevice) { 1276 audioDevice->dispatchTimerEvents(false); 1277 } 1278 } 1279} 1280 1281void IOAudioDevice::dispatchTimerEvents(bool force) 1282{ 1283 audioDebugIOLog(5, "+ IOAudioDevice::dispatchTimerEvents( %d )\n", force ); 1284 1285 if (timerEvents) { 1286#ifdef DEBUG 1287 AbsoluteTime now, delta; 1288 UInt64 nanos; 1289 1290 clock_get_uptime(&now); 1291 delta = now; 1292 SUB_ABSOLUTETIME(&delta, &previousTimerFire); 1293 absolutetime_to_nanoseconds(delta, &nanos); 1294#ifdef __LP64__ 1295 audioDebugIOLog(5, " woke up %lums after last fire - now = {%llu} - previousFire = {%llu}\n", (long unsigned int)(nanos / 1000000), now, previousTimerFire); 1296#else /* __LP64__ */ 1297 audioDebugIOLog(5, " woke up %lums after last fire - now = {%ld,%lu} - previousFire = {%ld,%lu}\n", (UInt32)(nanos / 1000000), now.hi, now.lo, previousTimerFire.hi, previousTimerFire.lo); 1298#endif /* __LP64__ */ 1299#endif /* DEBUG */ 1300 1301 if (force || (getPowerState() != kIOAudioDeviceSleep)) { 1302 OSIterator *iterator; 1303 OSSymbol *target; 1304 AbsoluteTime nextTimerFire, currentInterval; 1305 1306 currentInterval = minimumInterval; 1307 1308 assert(timerEvents); 1309 1310 iterator = OSCollectionIterator::withCollection(timerEvents); 1311 1312 if (iterator) { 1313 while ( (target = (OSSymbol *)iterator->getNextObject()) ) { 1314 IOAudioTimerEvent *timerEvent; 1315 timerEvent = (IOAudioTimerEvent *)timerEvents->getObject(target); 1316 1317 if (timerEvent) { 1318 (*timerEvent->event)(timerEvent->target, this); 1319 } 1320 } 1321 1322 iterator->release(); 1323 } 1324 1325 if (timerEvents->getCount() > 0) { 1326 ADD_ABSOLUTETIME(&previousTimerFire, ¤tInterval); 1327 nextTimerFire = previousTimerFire; 1328 ADD_ABSOLUTETIME(&nextTimerFire, &minimumInterval); 1329 1330 assert(timerEventSource); 1331 1332#ifdef DEBUG 1333 { 1334 AbsoluteTime later; 1335 UInt64 mi; 1336 later = nextTimerFire; 1337 absolutetime_to_nanoseconds(minimumInterval, &mi); 1338 if (CMP_ABSOLUTETIME(&later, &now)) { 1339 SUB_ABSOLUTETIME(&later, &now); 1340 absolutetime_to_nanoseconds(later, &nanos); 1341#ifdef __LP64__ 1342 audioDebugIOLog(5, " scheduling timer to fire in %lums at {%llu} - previousTimerFire = {%llu} - interval=%lums\n", (long unsigned int) (nanos / 1000000), nextTimerFire, previousTimerFire, (long unsigned int)(mi/1000000)); 1343#else /* __LP64__ */ 1344 audioDebugIOLog(5, " scheduling timer to fire in %lums at {%ld,%lu} - previousTimerFire = {%ld,%lu} - interval=%lums\n", (UInt32) (nanos / 1000000), nextTimerFire.hi, nextTimerFire.lo, previousTimerFire.hi, previousTimerFire.lo, (UInt32)(mi/1000000)); 1345#endif /* __LP64__*/ 1346 } 1347 else 1348 { 1349 SUB_ABSOLUTETIME(&now, &later); 1350 absolutetime_to_nanoseconds(now, &nanos); 1351#ifdef __LP64__ 1352 audioDebugIOLog(5, " scheduling timer to fire in -%lums - previousTimerFire = {%llu}\n", (long unsigned int) (nanos / 1000000), previousTimerFire); 1353#else /* __LP64__ */ 1354 audioDebugIOLog(5, " scheduling timer to fire in -%lums - previousTimerFire = {%ld,%lu}\n", (UInt32) (nanos / 1000000), previousTimerFire.hi, previousTimerFire.lo); 1355#endif /* __LP64__*/ 1356 } 1357 } 1358#endif /* DEBUG */ 1359 1360 timerEventSource->wakeAtTime(nextTimerFire); 1361 } 1362 } 1363 } 1364 audioDebugIOLog(5, "- IOAudioDevice::dispatchTimerEvents()\n" ); 1365 return; 1366} 1367 1368