/* * Copyright (c) 1998-2010 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /*! * @header IOAudioDevice */ #ifndef _IOKIT_IOAUDIODEVICE_H #define _IOKIT_IOAUDIODEVICE_H #include #ifndef IOAUDIOFAMILY_SELF_BUILD #include #include #else #include "IOAudioTypes.h" #include "IOAudioStream.h" #endif class IOAudioEngine; class IOAudioStream; class IOAudioPort; class IOAudioControl; class OSDictionary; class OSSet; class OSArray; class IOTimerEventSource; class IOCommandGate; /*! * enum IOAudioDevicePowerState * @abstract Identifies the power state of the audio device * @discussion A newly created IOAudioDevices defaults to the idle state. * @constant kIOAudioDeviceSleep State set when the system is going to sleep * @constant kIOAudioDeviceIdle State when the system is awake but none of the IOAudioEngines are in use * @constant kIOAudioDeviceActive State when one ore more IOAudioEngines are in use. This state transition must complete before the system will begin playing audio. */ typedef enum _IOAudioDevicePowerState { kIOAudioDeviceSleep = 0, // When sleeping kIOAudioDeviceIdle = 1, // When no audio engines running kIOAudioDeviceActive = 2 // audio engines running } IOAudioDevicePowerState; /*! * @class IOAudioDevice * @abstract Abstract base class for a single piece of audio hardware. The IOAudioDevice provides * the central coordination point for an audio driver. * @discussion An audio driver is required to subclass IOAudioDevice in order to provide * working audio to the system. A single driver instance will contain a single instance of the * driver's IOAudioDevice subclass. The subclass is responsible for mapping all hardware device * resources from the service provider nub. It must control access to the hardware so that the * hardware doesn't get into an inconsistent state. It is possible that different threads may make * requests of the hardware at the same time. The IOAudioDevice superclass provides an IOWorkLoop * and IOCommandGate on the IOWorkLoop through which all hardware accesses may be synchronized. * All entry points to all parts of the driver controlled by the IOAudioFamily will be synchronized * through this one IOWorkLoop. * * The IOAudioDevice subclass is responsible for creating the rest of the pieces of the driver. * It must identify and create all IOAudioEngines that are not automatically created by the system * (i.e. those that are not matched and instantiated by IOKit directly). * * The IOAudioDevice subclass must enumerate and create all IOAudioControls to match * the device capabilities. * * It must also execute control value chages when requested by the system (i.e. volume adjustments). * * In order to allow sleep and wake to work on the system, the IOAudioDevice subclass is responsible * for performing the necessary actions to sleep and wake its hardware (and restore necessary state * on wake). * * The IOAudioDevice class provides timer services that allow different elements in the audio driver * to receive timer notifications as needed. These services were designed with the idea that most * timed events in a typical audio driver need to be done at least as often as a certain interval. * Further, it is designed with the idea that being called more often than the specified interval * doesn't hurt anything - and in fact may help. With this in mind, the timer services provided * by the IOAudioDevice class allow different targets to register for timer callbacks at least as * often as the specified interval. The actual interval will be the smallest of the intervals of * all of the callbacks. This way, we avoid the overhead of having many timers in a single audio * device. As an example, each output IOAudioEngine has a timer to run the erase head. It doesn't hurt * to have the erase head run more often. Also, a typical IOAudioDevice subclass may need to run a timer * to check for device state changes (e.g. jack insertions). * * There are a number of strings passed from the driver to the CoreAudio.framework and then into * applications. All of those strings should be localized by the driver. In order to do that * the kext bundle should have localized string files following the Mac OS X localization * instructions. The IOAudioDevice should contain a property with the name of the bundle/kext * that contains the localized string resources. To do that, the driver's personality in * the bundle resources could have a property named 'IOAudioDeviceLocalizedBundle' with the path * of the bundle/kext relative to '/System/Library/Extensions'. It could also be set by the * IOAudioDevice subclass in its initHardware() function. To do so, call * setProperty(kIOAudioDeviceLocalizedBundleKey, "Driver.kext"). * * In a typical driver, the IOAudioDevice subclass will implement initHardware() to perform the * hardware initialization and driver construction. Within that initialization it must create at * least one IOAudioEngine instance and activate it. In order to activate a new IOAudioEngine * activateAudioEngine() should be called for each one. It must create the IOAudioControls * matching the hardware capabilities to allow the system to set volume, mute and input selection. * To add those controls to the driver, each control should be attached to the IOAudioEngine to * which it applies by calling addDefaultAudioControl() on the IOAudioEngine. * During initialization it should also call setDeviceName(), setDeviceShortName() and * setManufacturerName() with localized strings representing each of the attributes. * * If the driver is to work properly after sleep/wake, it must implement performPowerStateChange() * and deal with the sleep and wake transitions. It may also deal with the idle state transitions * to turn off device power when it isn't in use (especially useful for devices attached to a * portable running on battery power). */ class IOAudioDevice : public IOService { friend class IOAudioEngine; OSDeclareDefaultStructors(IOAudioDevice) protected: /*! @var workLoop The IOWorkLoop for the driver - this is shared with the other objects in the driver */ IOWorkLoop *workLoop; /*! @var commandGate The IOCommandGate for this IOAudioDevice. It is attached to workLoop */ IOCommandGate *commandGate; /*! @var timerEventSource An IOTimerEventSource attached to workLoop used for the timer services */ IOTimerEventSource *timerEventSource; /*! @var duringStartup State variable set to true while the driver is starting up and false all other times */ bool duringStartup; /*! @var familyManagePower Set to true if the family is supposed to manage power - this is the default state. It can be changed early in the initialization process with a call to setFamilyManagePower(). */ bool familyManagePower; /*! @var asyncPowerStateChangeInProgress Set to true while an asynchronous power change is pending and false all other times. */ bool asyncPowerStateChangeInProgress; /*! @var numRunningAudioEngines The number of running IOAudioEngines. This is used to maintain idle vs active power state. */ UInt32 numRunningAudioEngines; /*! @var currentPowerState Used to track the existing power state - can be fetched by calling getPowerState() */ IOAudioDevicePowerState currentPowerState; /*! @var pendingPowerState If a power state change is in progress, this represents the pending power state. All other times this is the same as the currentPowerState. */ IOAudioDevicePowerState pendingPowerState; /*! @var audioEngines The set of IOAudioEngine objects vended by the IOAudioDevice. */ OSArray * audioEngines; /*! @var timerEvents The set of timer events in use by the device. * @discussion The key for the dictionary is the target of the event. This means that a single target may * have only a single event associated with it. */ OSDictionary * timerEvents; /*! @var audioPorts The set of IOAudioPort objects associated with the IOAudioDevice */ OSSet * audioPorts; /*! @var minimumInterval The smallest timer interval requested by all timer event targets. */ AbsoluteTime minimumInterval; /*! @var previousTimerFire The time of the last timer event. * @discussion This is used to schedule the next timer event. */ AbsoluteTime previousTimerFire; public: /*! @var gIOAudioPlane A static IORegistryPlane representing the new IOAudioPlane that the IOAudioFamily uses * to represent the signal chain of the device. */ static const IORegistryPlane *gIOAudioPlane; protected: struct ExpansionData { unsigned long long idleSleepDelayTime; IOTimerEventSource * idleTimer; }; ExpansionData *reserved; public: static void idleAudioSleepHandlerTimer(OSObject *owner, IOTimerEventSource *sender); virtual IOReturn setAggressiveness(unsigned long type, unsigned long newLevel); // OSMetaClassDeclareReservedUsed(IOAudioDevice, 0); virtual void setDeviceTransportType(const UInt32 transportType); // OSMetaClassDeclareReservedUsed(IOAudioDevice, 1); /*! * @function setIdleAudioSleepTime * @abstract This function is to be called by a driver that doesn't want to be told about the audio * going idle immediately, but at some point in the future. * @discussion This is useful if the device will want to power down its hardware into an idle sleep * state, but doesn't want to do that unless audio hasn't been used for a while. Calling this function * immediately changes the idle sleep timer and queues it up if the idle is different from the previous * idle time. The idle time defaults to 0, which means be called immediately (backwards compatible with * previous versions of IOAudioFamily). A value of 0xffffffffffffffffULL means don't ever tell the * driver about going idle. * @param sleepDelay The amount of time, in nanoseconds, before the hardware should be told to go idle. */ virtual void setIdleAudioSleepTime(unsigned long long sleepDelay); // OSMetaClassDeclareReservedUsed(IOAudioDevice, 2); virtual void scheduleIdleAudioSleep(void); // OSMetaClassDeclareReservedUsed(IOAudioDevice, 3); /*! * @function setConfigurationApplicationBundle * @abstract This function is to be called if an external configuration application is available to set * which application to launch. * @discussion This is useful for device drivers that are too complex to be represented by the Sound Preferences * panel. The bundle ID is a more flexible way of specifying where the application is than a hard coded path. * @param bundleID The bundle ID of the application to be launched by the HAL for configuration of the device and its engine(s). */ virtual void setConfigurationApplicationBundle(const char *bundleID); // OSMetaClassDeclareReservedUsed(IOAudioDevice, 4); /*! * @function setDeviceCanBeDefault * @abstract This function is to be called to tell CoreAudio if this device shouldn't be a default device. * @discussion This is useful for device drivers that don't want to be a default device. Can be called with * kIOAudioDeviceCanBeDefaultNothing to prevent CoreAudio from allowing this device to be any default device, or it * can be called with any combination of kIOAudioDeviceCanBeDefaultInput, kIOAudioDeviceCanBeDefaultOutput, or * kIOAudioDeviceCanBeSystemOutput. The default is * (kIOAudioDeviceCanBeDefaultInput | kIOAudioDeviceCanBeDefaultOutput | kIOAudioDeviceCanBeSystemOutput). * @param defaultsFlags The flags to instruct CoreAudio to allow this device to be only the indicated default devices. */ virtual void setDeviceCanBeDefault(UInt32 defaultsFlags); // OSMetaClassDeclareReservedUsed(IOAudioDevice, 5); virtual void setDeviceModelName(const char * modelName); private: OSMetaClassDeclareReservedUsed(IOAudioDevice, 0); OSMetaClassDeclareReservedUsed(IOAudioDevice, 1); OSMetaClassDeclareReservedUsed(IOAudioDevice, 2); OSMetaClassDeclareReservedUsed(IOAudioDevice, 3); OSMetaClassDeclareReservedUsed(IOAudioDevice, 4); OSMetaClassDeclareReservedUsed(IOAudioDevice, 5); OSMetaClassDeclareReservedUnused(IOAudioDevice, 6); OSMetaClassDeclareReservedUnused(IOAudioDevice, 7); OSMetaClassDeclareReservedUnused(IOAudioDevice, 8); OSMetaClassDeclareReservedUnused(IOAudioDevice, 9); OSMetaClassDeclareReservedUnused(IOAudioDevice, 10); OSMetaClassDeclareReservedUnused(IOAudioDevice, 11); OSMetaClassDeclareReservedUnused(IOAudioDevice, 12); OSMetaClassDeclareReservedUnused(IOAudioDevice, 13); OSMetaClassDeclareReservedUnused(IOAudioDevice, 14); OSMetaClassDeclareReservedUnused(IOAudioDevice, 15); OSMetaClassDeclareReservedUnused(IOAudioDevice, 16); OSMetaClassDeclareReservedUnused(IOAudioDevice, 17); OSMetaClassDeclareReservedUnused(IOAudioDevice, 18); OSMetaClassDeclareReservedUnused(IOAudioDevice, 19); OSMetaClassDeclareReservedUnused(IOAudioDevice, 20); OSMetaClassDeclareReservedUnused(IOAudioDevice, 21); OSMetaClassDeclareReservedUnused(IOAudioDevice, 22); OSMetaClassDeclareReservedUnused(IOAudioDevice, 23); OSMetaClassDeclareReservedUnused(IOAudioDevice, 24); OSMetaClassDeclareReservedUnused(IOAudioDevice, 25); OSMetaClassDeclareReservedUnused(IOAudioDevice, 26); OSMetaClassDeclareReservedUnused(IOAudioDevice, 27); OSMetaClassDeclareReservedUnused(IOAudioDevice, 28); OSMetaClassDeclareReservedUnused(IOAudioDevice, 29); OSMetaClassDeclareReservedUnused(IOAudioDevice, 30); OSMetaClassDeclareReservedUnused(IOAudioDevice, 31); public: // Initialization /*! * @function init * @abstract Initialize a newly created instance of IOAudioDevice. * @discussion This implementation initializes all of the data structures and variables used by the * IOAudioDevice. The currentPowerState and pendingPowerState variables are set to kIOAudioDeviceIdle. * A subclass that overrides this method must call the superclass' implementation. * @param properties An OSDictionary of the device properties that gets passed to super::init and set * in the IORegistry. * @result true if initialization was successful */ virtual bool init(OSDictionary *properties); /*! * @function free * @abstract Frees resources used by the IOAudioDevice instance * @discussion This method will deactivate all audio audio engines and release the audioEngines OSSet. * It will also deactivate all of the audio ports and release the audioPorts OSSet. It will release * the timerEvents OSDictionary as well as cancel any outstanding timer callbacks. It will clean up * all of the event sources and the workLoop. * * Do not call this directly. This is called automatically by the system when the instance's * refcount goes to 0. To decrement the refcount, call release() on the object. */ virtual void free(); /*! * @function start * @abstract This function is called automatically by the system to tell the driver to start vending * services to the rest of the system. * @discussion The start() implementation in IOAudioDevice starts by calling start() on its superclass. * It then calls initHardware() which the subclass should override to properly initialize itself and * the hardware. If that call succeeds, it sets up power management if the family is supposed to * manage power (checking the familyManagePower variable). Then finally it calls registerService() * to make the IOAudioDevice visible in the IORegistry. * @param provider This is the service provider nub that provides access to the hardware resources. * @result Returns true on success */ virtual bool start(IOService *provider); /*! * @function stop * @abstract This is responsible for stopping the device after the system is done with it (or * if the device is removed from the system). * @discussion The IOAudioDevice implentation of stop() disables the timer services, deactivates * all of the audio audio engines and audio ports and stops power management of the device. * The audio engine and port deactivation causes all of the audio engines to get stopped and * all of the audio engine and port resources and objects to be released. A subclass' implementation * may could shut down hardware here if necessary. If this function is overridden by a subclass, * the superclass' implementation must be called. * @param The service provider nub for the device. */ virtual void stop(IOService *provider); virtual bool willTerminate(IOService *provider, IOOptionBits options); /*! * @function initHardware * @abstract This function is called by start() to provide a convenient place for the subclass to * perform its initialization. * @discussion In a typical implementation, a driver would implementation this function and perform * a number of tasks. Those include mapping hardware resources, initializing the hardware to a known * state, creating the IOAudioEngines, IOAudioControls and IOAudioStreams. Additionally it * should also call setDeviceName(), setDeviceShortName(), setManufacturerName(). Upon return of * this function, the device should be ready to begin vending services to the system. * @param provider The service provider nub for the device. * @result This function should return true on a successful initialization. */ virtual bool initHardware(IOService *provider); /*! * @function setDeviceName * @abstract Sets the name of the device * @discussion This method should be called during initialization or startup. It should * be set by the time initHardware() completes. The device name is used by the * CoreAudio.framework to identify the particular piece of hardware. This string should * should be localized by the driver. */ virtual void setDeviceName(const char *deviceName); /*! * @function setDeviceShortName * @abstract Sets the short name of the device * @discussion The short name is a shorter representation of the device name. It may be used * by applications when the device name is too long. It should be set by the time initHardware() * completes. The string should be localized by the driver. */ virtual void setDeviceShortName(const char *shortName); /*! * @function setManufacturerName * @abstract Sets the manufacturer name of the device * @discussion This method should be called during initialization or startup. This should be * called by the time initHardware() completes. The string should be localized by the driver. */ virtual void setManufacturerName(const char *manufacturerName); // IOWorkLoop, IOCommandGate management /*! * @function getWorkLoop * @abstract Returns the IOWorkLoop for the driver * @discussion The IOWorkLoop is used to synchronized all critical aspects of the driver. This * includes all entry points to the driver as well as power management. */ virtual IOWorkLoop *getWorkLoop() const; /*! * @function getCommandGate * @abstract Returns the IOCommandGate for this IOAudioDevice * @discussion This IOCommandGate allows calls into this IOAudioDevice to be synchronized on * the IOWorkLoop. */ virtual IOCommandGate *getCommandGate() const; // IOAudioEngine management /*! * @function activateAudioEngine * @abstract This simply calls activateAudioEngine(IOAudioEngine *audioEngine, * bool shouldStartAudioEngine) with a value of true for shouldStartAudioEngine. * @param audioEngine The IOAudioEngine instance to be activated. It is treated as a newly * allocated instance. * @result Returns true if the audio engine was successfully activated. */ virtual IOReturn activateAudioEngine(IOAudioEngine *audioEngine); /*! * @function activateAudioEngine * @abstract This is called to add a new IOAudioEngine object to the IOAudioDevice. * @discussion Once the IOAudioEngine has been activated by this function, it is ready * to begin moving audio data. This should be called either during the subclass' initHardware() * implementation for each IOAudioEngine the device creates. Or it should be called by * the IOAudioEngine itself if the audio engine was automatically created by IOKit's matching * process. The system won't be able to properly track and control IOAudioEngines if * they are not activated though this function. * This implementation will retain the IOAudioEngine while it maintains control of it. * When the audio engine is deactivated, the IOAudioEngine will be released. If the * IOAudioDevice subclass is passing a newly instantiated IOAudioEngine, it will need to release * the audio engine after it has been activated. This will insure that the refCount on the audio engine * is correct when it gets deactivated when the driver is stopped. That allows the audio engine to be * freed when it is no longer needed. * @param audioEngine The IOAudioEngine instance to be activated. * @param shouldStartAudioEngine If true, the audio engine is treated as a newly allocated IOAudioEngine * instance and is appropriately attached and started according to IOKit convention. If it is false * it is assumed that some other process (possibly the IOKit matching process) has started the * IOAudioEngine and will skip that step. * @result Returns true if the audio engine was successfully activated. */ virtual IOReturn activateAudioEngine(IOAudioEngine *audioEngine, bool shouldStartAudioEngine); /*! * @function deactivateAllAudioEngines * @abstract Deactivates all of the audio engines in the device. * @discussion This is called by the stop() and free() methods in IOAudioDevice to completely * shut down all audio engines as the driver is being shut down. */ virtual void deactivateAllAudioEngines(); // Power management /*! * @function setFamilyManagePower * @abstract Called set whether or not the family should manage the device power throught the * IOService power management APIs. * @discussion The default behavior is for the family to manage power. It is only necessary to * call this function if the driver does not want the family to manage power. It is not * recommended that this function be called because it makes power management much more * difficult for the driver. If this function is to be called, it must be called before * initHardware() completes. Immediately after initHardware() is called by start(), * the power management system is initialized if the family is to manage power. * @param manage Set to false if it is not desired that the family does the power management */ virtual void setFamilyManagePower(bool manage); /*! * @function setPowerState * @abstract Called by the power management system in IOService when the power state of this * service needs to change. * @discussion The default implementation of IOAudioDevice sets up two power states for IOService * to use. State 0 is sleep and state 1 is wake. This function should not be called directly. * It is only supposed to be used by the IOService power management services. * @param powerStateOrdinal The number of the power state as defined by the IOAudioDevice - * 0 for sleep, 1 for wake. * @param device The power management policy maker. * @result Returns kIOPMAckImplied (0) when the power state change is complete. Otherwise the an * upper bound on the number of microseconds until the state change is complete is returned. */ virtual IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *device); /*! * @function setPowerStateAction * @abstract IOCommandGate Action which calls protectedSetPowerState() while holding the IOCommandGate * @discussion This is needed to allow protectedSetPowerState() to be called on the IOWorkLoop * @param owner The owner of the IOCommandGate (the IOAudioDevice in this case) * @param arg1 The powerStateOrdinal to be passed to protectedSetPowerState() * @param arg2 The device to be passed to protectedSetPowerState() * @result Returns the result of protectedSetPowerState() */ static IOReturn setPowerStateAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4); /*! * @function protectedSetPowerState * @abstract Called by setPowerStateAction() to deal with a power state change from the IOService * power management facility. * @discussion This function is responsible for performing the necessary sleep and wake tasks * when the system is sleeping or waking. If an outstanding power state change is in progress, * it will wait until the state changes has completed. While sleeping, all audio engines are * stopped before calling initiatePowerStateChange() to call performPowerStateChange() to let * the driver deal with the sleep request. When waking, it determines if the device should be * idle or active and continues to call initiatePowerStateChange(). If initiatePowerStateChange() * indicates that the power state change is occuring asynchronously, it returns the number of * microseconds. This function must be called on the IOWorkLoop, but should not be called * directly. * @param powerStateOrdinal Param passed to setPowerState() - 0 for sleep, 1 for wake * @param device Param passed to setPowerState - the device initiating the power state change * @result Returns 0 if the power state change is complete - the number of microseconds until * complete if its asynchronous. */ virtual IOReturn protectedSetPowerState(unsigned long powerStateOrdinal, IOService *device); /*! * @function performPowerStateChange * @abstract This function is called by the IOAudioDevice when a power state change is needed. * @discussion In order to deal with power state changes, a subclass must override this function. * Any combination of old and new power states may be passed to this function. If work is to * be performed while transitioning to sleep, check for a newPowerState of kIOAudioDeviceSleep. * If work is to be performed while transitioning from sleep, check for an oldPowerState of * kIOAudioDeviceSleep. A power state of kIOAudioDeviceIdle means the system is awake, but * no clients are currently playing or recording audio (i.e. no IOAudioEngines are active). * A power state of kIOAudioDeviceActive means that at least one IOAudioEngine is active. * It is possible for a power state change to be performed synchronously or asynchronously. * In the case of a synchronous power state change, simple leave microsecondsUntilComplete * alone and return kIOReturnSuccess. If an asynchronous power state change is needed the * driver should do whatever needed to schedule another thread to finish the state change * and set the microsecondsUntilComplete to an upper bound on the amount of time it will * take to complete the power state change. Then when the power state change is complete, * a call must be made to completePowerStateChange(). During an asynchronous power state * change, the current power state will remain the same as before the transition began, * and the pendingPowerState is set to the new power state that will be set when the * change is complete. * @param oldPowerState The power state before the power state change * @param newPowerState The power state being transitioned to * @param microsecondsUntilComplete A pointer to a value representing an upper bound on * the number of microseconds to complete an asynchronous power state change. It points * to a value of zero at the start and if it remains zero, the state change is complete * upon a successful return from the function. * @result Returns kIOReturnSuccess on a successful completion */ virtual IOReturn performPowerStateChange(IOAudioDevicePowerState oldPowerState, IOAudioDevicePowerState newPowerState, UInt32 *microsecondsUntilComplete); /*! * @function completePowerStateChange * @abstract Called when a power state change is complete * @discussion In the case of an asynchronous power state change, a subclass is responsible * for calling this function. It is safe to call this function if not on the IOWorkLoop. * This function calls protectedCompletePowerStateChange() through the IOCommandGate and * completePowerStateChangeAction(). If the call is already on the IOWorkLoop, it is safe * to call protectedCompletePowerStateChange() directly. * @result Returns kIOReturnSuccess on a successful completion */ virtual IOReturn completePowerStateChange(); /*! * @function completePowerStateChangeAction * @abstract IOCommandGate Action which calls protectedCompletePowerStateChange() while holding the * IOCommandGate. * @discussion This is needed to allow protectedCompletePowerStateChange() to be called on the IOWorkLoop. * @param owner The owner of the IOCommandGate (the IOAudioDevice in this case) * @result Returns the result of protectedCompletePowerStateChange() */ static IOReturn completePowerStateChangeAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4); /*! * @function protectedCompletePowerStateChange() * @abstract Called on the IOWorkLoop when a power state change is complete. * @discussion This function does the work to complete a power state change (both synchronous and * asynchronous). If the system is waking from sleep, the timer system is restarted and the * audio engines are resumed. If this was called as a result of an asynchronous power state changed * it makes the IOService power management call acknowledgePowerChange() and resets the * asyncPowerStateChangeInProgress variable. Finally it sets the currentPowerState to the * pendingPowerState. This function must be called on the IOWorkLoop. If a subclass is not * on the IOWorkLoop (e.g. holding the IOCommandGate), call completePowerStateChange() instead. * @result Returns kIOReturnSuccess on success */ virtual IOReturn protectedCompletePowerStateChange(); /*! * @function getPowerState * @abstract Returns the current power state (the old power state if a change is in progress). * @result The current power state */ virtual IOAudioDevicePowerState getPowerState(); /*! * @function getPendingPowerState * @abstract Returns the pending power state if a state change is in progress. Otherwise it * returns the current power state change. * @result The pending power state */ virtual IOAudioDevicePowerState getPendingPowerState(); /*! * @function waitForPendingPowerStateChange * @abstract Called internally to wait until a pending power state change is complete. * @discussion This is only used by internal functions to wait during pending power * state changes. It is used to prevent multiple power state changes at the same time. * This function must be called while holding the IOCommandGate. If an asynchronous * power state change is in progress this function will block until the state change * if complete. Once complete, it will return while still holding the IOCommandGate. */ virtual void waitForPendingPowerStateChange(); /*! * @function initiatePowerStateChange * @abstract Called internally to execute a power state change * @discussion This function must be called on the IOWorkLoop. It calls performPowerStateChange() * to let the driver process the state change. If the state change is completed synchronously * by the driver (subclass) it calls protectedCompletePowerStateChange(). If done asynchronously * it returns the microsecondsUntilComplete that was set by performPowerStateChange(). This * function should not be called directly. * @param microsecondsUntilComplete Pointer to the microsecondsUntilComplete that should be set * by performPowerStateChange if an asynchronous power state change was started. * @result Returns kIOReturnSuccess on success */ virtual IOReturn initiatePowerStateChange(UInt32 *microsecondsUntilComplete = NULL); // IOAudioControl management /*! * @function flushAudioControls * @abstract Forces each IOAudioControl in the driver to have its value flushed out to the hardware. * That will cause either the IOAudioControl's ValueChangeHandler to be called. * @discussion This can be used to force the hardware to get updated with the current value * of each control. It may be useful during wake for example. */ virtual void flushAudioControls(); // Timer services /*! * @typedef TimerEvent * @abstract Generic timer event callback for IOAudioDevice timer targets * @discussion TimerEvent callback function takes two arguments; the target of * the timer event and the IOAudioDevice sending the event. * @param target The target of the timer event - passed in when the timer event was registered * @param audioDevice The IOAudioDevice sending the event */ typedef void (*TimerEvent)(OSObject *target, IOAudioDevice *audioDevice); /*! * @function addTimerEvent * @abstract Adds a TimerEvent callback for the given target called at least as often * as specified in interval. * @discussion The frequency of the timer event callbacks will be the smallest interval * specified by all targets. Only one interval and callback may be specified per target. * If a addTimerEvent is called twice with the same target, the second one overrides the * first. There is currently a bug triggered if the first call had the smallest interval. * In that case, that smallest interval would still be used. * @param target This parameter is the target object of the TimerEvent. * @param event The callback function called each time the timer fires. * @param interval The callback will be called at least this often. * @result Returns kIOReturnSuccess if the timer event was successfully added. */ virtual IOReturn addTimerEvent(OSObject *target, TimerEvent event, AbsoluteTime interval); /*! * @function removeTimerEvent * @abstract Removes the timer event for the given target. * @discussion If the interval for the target to be removed is the smallest interval, * the timer interval is recalculated based on the remaining targets. The next fire * time is readjusted based on the new interval compared to the last fire time. * @param target The target whose timer event will be removed. */ virtual void removeTimerEvent(OSObject *target); /*! * @function removeAllTimerEvents * @abstract Removes all timer events and stops the timer * @discussion Called during teardown of the driver */ virtual void removeAllTimerEvents(); // IOAudioPort management /*! * @function attachAudioPort * @abstract Adds the port to the IOAudioDevice's list of ports and attaches the port to its parent * and attaches the child to the port. * @discussion This function provides the functionality to represent the device's signal chain in the * IOAudioPlane in the IORegistry. An IOAudioPort's parent(s) are before it in the signal chain * and its children are after it. This method may be called multiple times for a single IOAudioPort. * This is necessary when there are many children or parents. Once a relationship is made, it is not * necessary to make the reverse relationship. A NULL value may be passed in for either the parent * or child or both. * The IOAudioPort passed in should be a newly allocated IOAudioPort instance. This function will * appropriately attach and start the port object. NOTE: It is not necessary to use IOAudioPorts * in a fully functional audio driver. * @param port The newly created IOAudioPort instance to be activated. * @param parent A parent IOAudioPort or IOAudioEngine of the given port. * @param child A child IOAudioPort or IOAudioEngine of the given port. * @result Returns true when the port has been successfully added and attached. */ virtual IOReturn attachAudioPort(IOAudioPort *port, IORegistryEntry *parent, IORegistryEntry *child); /*! * @function detachAllAudioPorts * @abstract Deactivates all of the ports in the device. * @discussion This is called by the stop() and free() methods in IOAudioDevice to completely * shut down all ports as the driver is being shut down. */ virtual void detachAllAudioPorts(); protected: /*! * @function timerFired * @abstract Internal static function called when the timer fires. * @discussion This function simply calls dispatchTimerEvents() on the IOAudioDevice to do just that. * @param target The IOAudioDevice instance that initiated the timer callback. * @param sender The IOTimerEventSources calling this callback */ static void timerFired(OSObject *target, IOTimerEventSource *sender); /*! * @function dispatchTimerEvents * @abstract Called by timerFired() to cause the timer event callbacks to be called. * @discussion This method iterates through all of the timer event targets and calls * the callback on each. Unless the force flag is set to true, the timer events will * only be dispatched if the power state is not kIOAudioDeviceSleep. This prevents * unexpected timer firings while making wake->sleep->wake transitions. This function must * be called on the IOWorkLoop. * @function force A bool param to allow the timer events to be dispatched even if the * device is in the kIOAudioDeviceSleep power state. */ virtual void dispatchTimerEvents(bool force); /*! * @function audioEngineStarting * @abstract Called by IOAudioEngine when it is starting up * @discussion This should only be called while on the IOWorkLoop. It is not intended to be called * directly. It is called when an IOAudioEngine is starting up to allow the IOAudioDevice * to keep track of running audio engines and change the power state from kIOAudioDeviceIdle to * kIOAudioDeviceActive when the first audio engine starts up. If the state change is done * asynchronously, it waits for the state change to complete. This is to ensure that the * system doesn't start playing audio until the IOAudioDevice has completed its transition * to kIOAudioDeviceActive. */ virtual void audioEngineStarting(); /*! * @function audioEngineStopped * @abstract Called by IOAudioEngine when it has stopped * @discussion This should only be called while on the IOWorkLoop. It is not intended to be called * directly. It is called when an IOAudioEngine has stopped to allow the IOAudioDevice * to keep track of running audio engines and change the power state from kIOAudioDeviceActive * to kIOAudioDeviceIdle when the last audio engine stops. If the state change is done * asynchronously, it waits for the state change to complete. */ virtual void audioEngineStopped(); }; #endif /* _IOKIT_IOAUDIODEVICE_H */