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