ACX device enumeration
This topic discusses ACX device enumeration, startup and shutdown, and device rebalance. For a general overview of ACX, see ACX audio class extensions overview. For information about ACX power management and PnP, see ACX power management.
ACX device enumeration and startup for static audio devices
To learn about how ACX startup works, the following scenario will be described.
- An audio device is represented by a single circuit.
- An audio/circuit lifetime is tied to the PnP device lifetime.
- A single device can create multiple circuits for different audio devices.
- KMDF kernel-mode environment.
The sequence of start up is:
WDM DriverEntry. Driver-scoped. DriverEntry for WDF Drivers routine
- Init tracing.
- Optionally register for unload.
- Create WDFDRIVER.
- Call ACX to do any post driver init.
- Optionally do any post driver init.
WDF DeviceAdd. Device-scoped. EVT_WDF_DRIVER_DEVICE_ADD callback function
- Call ACX to init the device init context -
ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg)
ACX_DEVICEINIT_CONFIG_INIT function - Register WDF PnP Power call backs -
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
- Create device using AcxDeviceInitialize
- Call ACX to do any post device init.
- Optionally do any post device init.
- Call ACX to init the device init context -
WDF PrepareHardware. Device-scoped. EVT_WDF_DEVICE_PREPARE_HARDWARE callback function.
Create and init hardware resources (for interrupts and threads, register them with ACX).
Create one or more circuits (one time creation).
- Create an AcxCircuitInit Context.
- Add callbacks.
- Create an AcxCircuit.
- Optionally do any post circuit init.
- Register the circuit with AcxDeviceAddCircuitDevice.
WDF Device D0 Entry callback. Device-scoped. EVT_WDF_DEVICE_D0_ENTRY callback function.
ACX invokes the EvtAcxCircuitPowerUp callback on all the circuits. Circuit-scoped.
ACX Moves the streams (if any) to their previous state before the device was powered down. Stream Instance-scoped.
WDF Queues are restarted.
EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT callback function. Device-scoped.
EVT_WDF_DEVICE_SELF_MANAGED_IO_RESTART callback function. Device-scoped. - Init after each power up from Dx.
ACX Stream Add
- ACX Stream Add (instance) on ACX Circuit (ACX callback on ACX circuits) – invoked at any time after the WDF self-managed I/O Init or Restart has been invoked and device is in D0. Circuit-scoped.
- Input: AcxStreamInit context, ACXCIRCUIT.
- Add callbacks.
- Create an AcxStream (instance).
- Optionally do any post stream Instance init.
- On return, ACX activates this stream instance, and since in this scenario is the only one on the audio path, it allows stream messages to go through.
ACX device enumeration and startup for dynamic audio devices
In this scenario the following are assumed.
- Dynamic audio support (create/delete audio devices at run-time).
- Device lifetime is not tied to the circuit lifetime.
- A single device can create multiple circuits for different audio devices.
- Piggybacks on the simple static pattern described above by only adding elements specific to dynamic pattern.
- Makes use of child raw PDOs.
- KMDF kernel-mode environment.
The sequence of start up for this scenario is:
WDM DriverEntry. Driver-scoped.
- Init tracing.
- Optionally register for unload.
- Create WDFDRIVER.
- Call ACX to do any post driver init.
- Optionally do any post driver init.
WDF DeviceAdd. Device-scoped.
- Call ACX to init the device init context.
- Create device.
- Call ACX to do any post device init.
- Optionally do any post device init.
WDF PrepareHardware. Device-scoped.
- Create and init hardware resources (for interrupts and threads, register them with ACX).
WDF Device D0 Entry callback. Device-scoped.
WDF Queues are restarted.
WDF DeviceSelfManagedIoInit. Device-scoped.
WDF DeviceSelfManagedIoRestart. Device-scoped.
- Init after each power up from Dx.
Circuit dynamic creation (at any time)
- Driver allocates a WDFDEVICE_INIT structure by calling WdfPdoInitAllocate. The driver is responsible for invoking the WdfDeviceInitFree if it encounters any failures before successfully creating a device.
- Driver specifies any PnP/power callbacks it wants to receive.
- Driver creates a device.
- Driver instantiates the new device/circuit by calling AcxDeviceAddCircuitDevice.
- WDF/PnP takes over and the simple enum/startup pattern described in the previous section takes place.
AcxFactoryCircuit
An ACX driver can also create AcxFactoryCircuit objects (circuit providers) during power up sequence using the AcxFactoryCircuitCreate function and the AcxDeviceAddFactoryCircuit function.
Because the ACX driver registered itself with ACX as circuit factory, the ACX framework uses the registered factory to ask the driver to create a new circuit.
AcxFactoryCircuitCreate(Device, &attributes, &factoryInit, &factory);
AcxDeviceAddFactoryCircuit(Device, factory);
ACX device rebalance
Rebalancing is done when system resource usage requires the operating system to rebalance resources between devices. For general information about rebalance, see Implement PnP Rebalance for PortCls Audio Drivers.
ACX supports device rebalance as follows:
In the power down WDF/ACX sequence, the driver releases all streaming resources (EvtAcxStreamPowerDown, EvtAcxStreamReleaseHardware), circuit resources (EvtAcxCircuitPowerDown, EvtAcxCircuitReleaseHardware) and device resources (EvtDeviceReleaseHardware).
All requests are pended, and handles are left open.
In the power up WDF/ACX sequence, the driver makes sure the new resources are compatible with the current ones, and it makes any allowed adjustments to its settings. If the resources are not compatible with the current device/circuit initialization, the driver must delete the current circuits and create new ones. See below more information.
In the power up sequence, WDF invokes its EvtDevicePrepareHardware and EvtDeviceD0 entry, and ACX invokes the corresponding EvtAcxCircuitPrepareHardware and EvtAcxCircuitPowerUp, and it moves all streams into its pre-existing states.
As soon as the queues move to power up/run state, the I/O flow again.
ACX doesn't allow remove (fails query-remove) or rebalance (fails query-stop) to take place if there are streams in active (RUN) state.
Drivers may also opt to always destroy and recreate audio devices on rebalance. This is the same scenario above when the device detects that the new settings are not compatible with the old ones. The deletion of the circuit must be done in EvtDevicePrepareHardware/EvtDeviceReleaseHardware callbacks, and the new circuit is re-created in EvtDevicePrepareHardware. The driver deletes a circuit by un-registering the circuit (using AcxDeviceRemoveCircuit).
User mode file handles
ACX doesn’t wait for the user mode file handles to be closed before re-creating new circuits. The lifetime of the files system handles is not tied to the lifetime of the hardware resources used by the device/circuits. It is the responsibility of clients to listen for interface arrival/removal and close and re-open file handles.
Old file handles are marked obsolete and ACX fails all the I/O requests associated with them.