diff options
| author | Adonais Romero González <[email protected]> | 2024-05-06 16:21:31 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-05-06 16:21:31 -0700 |
| commit | a74a241c664c4e1d7c0838287b34076c19d9858a (patch) | |
| tree | 6ff7562612967b122acf8acf8a69c4dcfd5905db /audio | |
| parent | def8e8e34ed2b7b1deb2fc9112ac4255f1a0f2ba (diff) | |
| parent | 15477ce52bbb6b42ca591ecdfb484cac089f89ab (diff) | |
Merge develop changes prior to upcoming WDK release (May 2024)
Diffstat (limited to 'audio')
72 files changed, 12376 insertions, 1672 deletions
diff --git a/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.inf b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.inf Binary files differnew file mode 100644 index 00000000..889f9bdb --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.inf diff --git a/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.sln b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.sln new file mode 100644 index 00000000..1cedca27 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.sln @@ -0,0 +1,60 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31409.214 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SamplesCommon", "SamplesCommon", "{0DF6D5E6-3B78-414B-B37B-85D9CA454487}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AudioCodec", "AudioCodec", "{0D3B6287-146E-4700-B2EE-11D520014FEA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SamplesCommon", "..\..\Common\SamplesCommon.vcxproj", "{6A946D59-6690-4ED0-A77D-7D4C3D4B3241}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AudioCodec", "AudioCodec.vcxproj", "{C575002D-5FDE-43C7-AB19-EE846A20083A}" + ProjectSection(ProjectDependencies) = postProject + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241} = {6A946D59-6690-4ED0-A77D-7D4C3D4B3241} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|ARM64.Build.0 = Debug|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|x64.ActiveCfg = Debug|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|x64.Build.0 = Debug|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|x64.Deploy.0 = Debug|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|ARM64.ActiveCfg = Release|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|ARM64.Build.0 = Release|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|ARM64.Deploy.0 = Release|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|x64.ActiveCfg = Release|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|x64.Build.0 = Release|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|x64.Deploy.0 = Release|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|ARM64.Build.0 = Debug|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|x64.ActiveCfg = Debug|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|x64.Build.0 = Debug|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|x64.Deploy.0 = Debug|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|ARM64.ActiveCfg = Release|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|ARM64.Build.0 = Release|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|ARM64.Deploy.0 = Release|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|x64.ActiveCfg = Release|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|x64.Build.0 = Release|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|x64.Deploy.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241} = {0DF6D5E6-3B78-414B-B37B-85D9CA454487} + {C575002D-5FDE-43C7-AB19-EE846A20083A} = {0D3B6287-146E-4700-B2EE-11D520014FEA} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8E3043F2-1C76-4A4A-9C60-A645BD6CBF24} + EndGlobalSection +EndGlobal diff --git a/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj new file mode 100644 index 00000000..0cdc9e61 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|ARM64"> + <Configuration>Debug</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM64"> + <Configuration>Release</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + </ItemGroup> + <ItemGroup> + <None Include="ReadMe.txt" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Device.cpp" /> + <ClCompile Include="Driver.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Trace.h" /> + </ItemGroup> + <ItemGroup> + <Inf Include="AudioCodec.inf" /> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ACX_VERSION_MAJOR>1</ACX_VERSION_MAJOR> + <ACX_VERSION_MINOR>1</ACX_VERSION_MINOR> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR> + <ProjectGuid>{C575002D-5FDE-43C7-AB19-EE846A20083A}</ProjectGuid> + <TemplateGuid>{497e31cb-056b-4f31-abb8-447fd55ee5a5}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <RootNamespace>AudioCodec</RootNamespace> + <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">..\..\common\trace_macros.h</WppScanConfigurationData> + <WppKernelMode>true</WppKernelMode> + <AdditionalIncludeDirectories>$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\..\common;..\..\inc;..\..\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <Link> + <AdditionalDependencies>$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib;..\..\Common\$(IntDir)\SamplesCommon.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">..\..\common\trace_macros.h</WppScanConfigurationData> + <WppKernelMode>true</WppKernelMode> + <AdditionalIncludeDirectories>$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\..\common;..\..\inc;..\..\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <Link> + <AdditionalDependencies>$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib;..\..\Common\$(IntDir)\SamplesCommon.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">..\..\common\trace_macros.h</WppScanConfigurationData> + <WppKernelMode>true</WppKernelMode> + <AdditionalIncludeDirectories>$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\..\common;..\..\inc;..\..\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <Link> + <AdditionalDependencies>$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib;..\..\Common\$(IntDir)\SamplesCommon.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">..\..\common\trace_macros.h</WppScanConfigurationData> + <WppKernelMode>true</WppKernelMode> + <AdditionalIncludeDirectories>$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\..\common;..\..\inc;..\..\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <Link> + <AdditionalDependencies>$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib;..\..\Common\$(IntDir)\SamplesCommon.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj.Filters b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj.Filters new file mode 100644 index 00000000..0b882019 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj.Filters @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Driver Files"> + <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <None Include="ReadMe.txt" /> + </ItemGroup> + <ItemGroup> + <Inf Include="AudioCodec.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Trace.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Device.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/Acx/Samples/AudioCodec/Driver/Device.cpp b/audio/Acx/Samples/AudioCodec/Driver/Device.cpp new file mode 100644 index 00000000..7e9a0a3c --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/Device.cpp @@ -0,0 +1,439 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + Device.cpp - Device handling events for example driver. + +Abstract: + + This file contains the device entry points and callbacks. + +Environment: + + Kernel-mode Driver Framework + +--*/ + +#include <wdm.h> +#include <windef.h> +#include "public.h" +#include <devguid.h> +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" +#include "DriverSettings.h" + +#ifndef __INTELLISENSE__ +#include "device.tmh" +#endif + +UNICODE_STRING g_RegistryPath = { 0 }; // This is used to store the registry settings path for the driver + +ULONG DeviceDriverTag = DRIVER_TAG; + +ULONG IdleTimeoutMsec = IDLE_TIMEOUT_MSEC; + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +CopyRegistrySettingsPath( + _In_ PUNICODE_STRING RegistryPath +) +/*++ + +Routine Description: + +Copies the following registry path to a global variable. + +\REGISTRY\MACHINE\SYSTEM\ControlSetxxx\Services\<driver>\Parameters + +Arguments: + +RegistryPath - Registry path passed to DriverEntry + +Returns: + +NTSTATUS - SUCCESS if able to configure the framework + +--*/ + +{ + PAGED_CODE(); + + // + // Initializing the unicode string, so that if it is not allocated it will not be deallocated too. + // + RtlInitUnicodeString(&g_RegistryPath, nullptr); + + g_RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR); + + g_RegistryPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, g_RegistryPath.MaximumLength, DRIVER_TAG); + + if (g_RegistryPath.Buffer == nullptr) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlAppendUnicodeToString(&g_RegistryPath, RegistryPath->Buffer); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtBusDeviceAdd( + _In_ WDFDRIVER Driver, + _Inout_ PWDFDEVICE_INIT DeviceInit +) +/*++ + +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent a new instance of the device. All the software resources + should be allocated in this callback. + +Arguments: + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + ACX_DEVICEINIT_CONFIG devInitCfg; + ACX_DEVICE_CONFIG devCfg; + WDFDEVICE device = nullptr; + PCODEC_DEVICE_CONTEXT devCtx; + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); + + // + // The driver calls this DDI in its AddDevice callback before creating the PnP device. + // ACX uses this call to add default/standard settings for the device to be created. + // + ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg); + RETURN_IF_FAILED(AcxDeviceInitInitialize(DeviceInit, &devInitCfg)); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = Codec_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = Codec_EvtDeviceReleaseHardware; + pnpPowerCallbacks.EvtDeviceD0Entry = Codec_EvtDeviceD0Entry; + pnpPowerCallbacks.EvtDeviceD0Exit = Codec_EvtDeviceD0Exit; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = Codec_EvtDeviceContextCleanup; + + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&DeviceInit, &attributes, &device)); + + // + // Init Codec's device context. + // + devCtx = GetCodecDeviceContext(device); + ASSERT(devCtx != nullptr); + + devCtx->Render = nullptr; + devCtx->Capture = nullptr; + devCtx->ExcludeD3Cold = WdfFalse; + + // + // The driver calls this DDI in its AddDevice callback after creating the PnP + // device. ACX uses this call to apply any post device settings. + // + ACX_DEVICE_CONFIG_INIT(&devCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(device, &devCfg)); + + // + // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so + // that you don't get the popup in usermode (on Win2K) when you surprise + // remove the device. + // + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + pnpCaps.SurpriseRemovalOK = WdfTrue; + WdfDeviceSetPnpCapabilities(device, &pnpCaps); + + // + // Create a render circuit and capture circuit and add them to the current + // device context. These circuits will be added to the device when the + // prepare hardware callback is called. + // + RETURN_NTSTATUS_IF_FAILED(CodecR_AddStaticRender(device, &CODEC_RENDER_COMPONENT_GUID, &renderCircuitName)); + + RETURN_NTSTATUS_IF_FAILED(CodecC_AddStaticCapture(device, &CODEC_CAPTURE_COMPONENT_GUID, &MIC_CUSTOM_NAME, &captureCircuitName)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // NOTE: Download firmware here. + + // NOTE: Register streaming h/w resources here. + + // + // Set power policy data. + // + RETURN_NTSTATUS_IF_FAILED(Codec_SetPowerPolicy(Device)); + + // + // Setting up the data saving (CSaveData) and wave file reader (CWaveReader) + // utility classes which will be used by the virtual streaming engine. + // + RETURN_NTSTATUS_IF_FAILED(CSaveData::SetDeviceObject(WdfDeviceWdmGetDeviceObject(Device))); + + RETURN_NTSTATUS_IF_FAILED(CSaveData::InitializeWorkItems(WdfDeviceWdmGetDeviceObject(Device))); + + RETURN_NTSTATUS_IF_FAILED(CWaveReader::InitializeWorkItems(WdfDeviceWdmGetDeviceObject(Device))); + + // + // The driver uses this DDI to associate a circuit to a device. After + // this call the circuit is not visible until the device goes in D0. + // For a real driver there should be a check here to make sure the + // circuit has not been added already (there could be a situation where + // prepareHardware is called multiple times and releaseHardware is only + // called once). + // + + ASSERT(devCtx->Render); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Render)); + + ASSERT(devCtx->Capture); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Capture)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + PCODEC_DEVICE_CONTEXT devCtx; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // The driver uses this DDI to delete a circuit from the current device. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceRemoveCircuit(Device, devCtx->Render)); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceRemoveCircuit(Device, devCtx->Capture)); + + // NOTE: Release streaming h/w resources here. + + CSaveData::DestroyWorkItems(); + CWaveReader::DestroyWorkItems(); + + status = STATUS_SUCCESS; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtDeviceD0Entry( + _In_ WDFDEVICE Device, + _In_ WDF_POWER_DEVICE_STATE PreviousState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(PreviousState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +NTSTATUS +Codec_EvtDeviceD0Exit( + _In_ WDFDEVICE Device, + _In_ WDF_POWER_DEVICE_STATE TargetState +) +{ + NTSTATUS status = STATUS_SUCCESS; + POWER_ACTION powerAction; + + PAGED_CODE(); + + powerAction = WdfDeviceGetSystemPowerAction(Device); + + // + // Update the power policy D3-cold info for Connected Standby. + // + if (TargetState == WdfPowerDeviceD3 && powerAction == PowerActionNone) + { + PCODEC_DEVICE_CONTEXT devCtx; + WDF_TRI_STATE excludeD3Cold = WdfTrue; + ACX_DX_EXIT_LATENCY latency; + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // Get the current exit latency. + // + latency = AcxDeviceGetCurrentDxExitLatency(Device, + WdfDeviceGetSystemPowerAction(Device), + TargetState); + + // + // If the current exit latency for the ACX device is responsive + // (not instant or fast) then D3-cold does not need to be excluded. + // Otherwise, D3-cold should be excluded because if the hardware + // goes into this state it will take too long to go back into D0 + // and respond. + // + if (latency == AcxDxExitLatencyResponsive) + { + excludeD3Cold = WdfFalse; + } + + if (devCtx->ExcludeD3Cold != excludeD3Cold) + { + devCtx->ExcludeD3Cold = excludeD3Cold; + + RETURN_NTSTATUS_IF_FAILED(Codec_SetPowerPolicy(Device)); + } + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_SetPowerPolicy( + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // Init the idle policy structure. + // + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = IDLE_POWER_TIMEOUT; + idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; + idleSettings.ExcludeD3Cold = devCtx->ExcludeD3Cold; + + RETURN_NTSTATUS_IF_FAILED(WdfDeviceAssignS0IdleSettings(Device, &idleSettings)); + + return status; +} + +VOID +Codec_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice +) +/*++ + +Routine Description: + + In this callback, it cleans up device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + nullptr + +--*/ +{ + WDFDEVICE device; + PCODEC_DEVICE_CONTEXT devCtx; + + device = (WDFDEVICE)WdfDevice; + devCtx = GetCodecDeviceContext(device); + ASSERT(devCtx != nullptr); + + if (devCtx->Capture) + { + CodecC_CircuitCleanup(devCtx->Capture); + } +} diff --git a/audio/Acx/Samples/AudioCodec/Driver/Driver.cpp b/audio/Acx/Samples/AudioCodec/Driver/Driver.cpp new file mode 100644 index 00000000..452b0d99 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/Driver.cpp @@ -0,0 +1,129 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + Driver.cpp + +Abstract: + + This file contains the driver entry points and callbacks. + +Environment: + + Kernel-mode Driver Framework + +--*/ + +#include "public.h" +#include "cpp_utils.h" + +#ifndef __INTELLISENSE__ +#include "driver.tmh" +#endif + +_Use_decl_annotations_ +void AudioCodecDriverUnload( + _In_ WDFDRIVER Driver +) +{ + PAGED_CODE(); + + if (!Driver) + { + ASSERT(FALSE); + return; + } + + WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); + + if (g_RegistryPath.Buffer != nullptr) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + + return; +} + +INIT_CODE_SEG +NTSTATUS +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath +) +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. DriverEntry specifies the other entry + points in the function driver, such as EvtDevice and DriverUnload. + +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverEntry must initialize members of DriverObject before it + returns to the caller. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + WDF_DRIVER_CONFIG wdfCfg; + ACX_DRIVER_CONFIG acxCfg; + WDFDRIVER driver; + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + + PAGED_CODE(); + WPP_INIT_TRACING(DriverObject, RegistryPath); + + auto exit = scope_exit([&status, &DriverObject]() { + if (!NT_SUCCESS(status)) + { + WPP_CLEANUP(DriverObject); + + if (g_RegistryPath.Buffer != nullptr) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + } + }); + + RETURN_NTSTATUS_IF_FAILED(CopyRegistrySettingsPath(RegistryPath)); + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + WDF_DRIVER_CONFIG_INIT(&wdfCfg, Codec_EvtBusDeviceAdd); + wdfCfg.EvtDriverUnload = AudioCodecDriverUnload; + + // + // Create a framework driver object to represent our driver. + // + RETURN_NTSTATUS_IF_FAILED(WdfDriverCreate(DriverObject, RegistryPath, &attributes, &wdfCfg, &driver)); + + // + // Initializing the ACX driver configuration struct which contains size and flags + // elements. + // + ACX_DRIVER_CONFIG_INIT(&acxCfg); + + // + // The driver calls this DDI in its DriverEntry callback after creating the WDF driver + // object. ACX uses this call to apply any post driver settings. + // + RETURN_NTSTATUS_IF_FAILED(AcxDriverInitialize(driver, &acxCfg)); + + return status; +} diff --git a/audio/Acx/Samples/AudioCodec/Driver/DriverSettings.h b/audio/Acx/Samples/AudioCodec/Driver/DriverSettings.h new file mode 100644 index 00000000..65aa7f5b --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/DriverSettings.h @@ -0,0 +1,54 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + DriverSettings.h + +Abstract: + + Contains guid definitions and other definitions used by the render and capture circuits + for this specific driver. Driver developers should replace these definitions with their + own. + +Environment: + + Kernel mode + +--*/ + +// Defining the component ID for the capture circuit. This ID uniquely identifies the circuit instance (vendor specific): +DEFINE_GUID(CODEC_CAPTURE_COMPONENT_GUID, 0xc3ee9ec6, 0x8e8c, 0x49e9, 0xaf, 0x4b, 0xa7, 0xfc, 0x28, 0xe9, 0xd2, 0xe7); + +// Defines a custom name for the capture circuit bridge pin: +DEFINE_GUID(MIC_CUSTOM_NAME, 0xd5649dc4, 0x2fa2, 0x418b, 0xb2, 0x78, 0x39, 0x7, 0x64, 0x6b, 0x3, 0xe); + +// Defining the component ID for the render circuit. This ID uniquely identifies the circuit instance (vendor specific): +DEFINE_GUID(CODEC_RENDER_COMPONENT_GUID, 0xd03deb75, 0xe5b2, 0x45f7, 0x91, 0xfa, 0xf7, 0xae, 0x42, 0xdd, 0xf, 0xe0); + +// This is always the definition for the system container guid: +DEFINE_GUID(SYSTEM_CONTAINER_GUID, 0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + +// Driver developers should update this guid if the container is a device rather than a +// system. Otherwise, this GUID should stay the same: +DEFINE_GUID(DEVICE_CONTAINER_GUID, 0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + +// AudioCodec driver tag: +#define DRIVER_TAG (ULONG) 'CduA' + +// The idle timeout in msec for power policy structure: +#define IDLE_TIMEOUT_MSEC (ULONG) 10000 + +// The WPP control GUID defined in Trace.h should also be updated to be unique. + +// This string must match the string defined in AudioCodec.inf for the microphone name: +DECLARE_CONST_UNICODE_STRING(captureCircuitName, L"Microphone0"); + +// This string must match the string defined in AudioCodec.inf for the speaker name: +DECLARE_CONST_UNICODE_STRING(renderCircuitName, L"Speaker0"); diff --git a/audio/Acx/Samples/AudioCodec/Driver/ReadMe.txt b/audio/Acx/Samples/AudioCodec/Driver/ReadMe.txt new file mode 100644 index 00000000..ebc61c6d --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/ReadMe.txt @@ -0,0 +1,42 @@ +======================================================================== + AudioCodec Project Overview +======================================================================== + +This file contains a summary of what you will find in each of the files that make up your project. + +AudioCodec.vcxproj + This is the main project file for projects generated using an Application Wizard. + It contains information about the version of the product that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +AudioCodec.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +Driver.cpp & Driver.h + DriverEntry and WDFDRIVER related functionality and callbacks. Driver developers should + make changes to these files for their specific driver as necessary. + +Device.cpp & Device.h + WDFDEVICE related functionality and callbacks. Driver developers should make changes to + these files for their specific driver as necessary. + +Trace.h + Definitions for WPP tracing. + +DriverSettings.h + Contains guid definitions and other definitions used by the render and capture circuits + for this specific driver. Driver developers should replace these definitions with their + own. + +///////////////////////////////////////////////////////////////////////////// + +Learn more about Kernel Mode Driver Framework here: + +http://msdn.microsoft.com/en-us/library/ff544296(v=VS.85).aspx + +///////////////////////////////////////////////////////////////////////////// diff --git a/audio/Acx/Samples/AudioCodec/Driver/Resources.rc b/audio/Acx/Samples/AudioCodec/Driver/Resources.rc new file mode 100644 index 00000000..788fc416 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/Resources.rc @@ -0,0 +1,12 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Audio Codec Acx Sample Driver" +#define VER_INTERNALNAME_STR "AudioCodec.sys" +#define VER_ORIGINALFILENAME_STR "AudioCodec.sys" + +#include "common.ver" + diff --git a/audio/Acx/Samples/Common/CaptureCircuit.cpp b/audio/Acx/Samples/Common/CaptureCircuit.cpp new file mode 100644 index 00000000..ba205a90 --- /dev/null +++ b/audio/Acx/Samples/Common/CaptureCircuit.cpp @@ -0,0 +1,799 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + CaptureCircuit.cpp + +Abstract: + + Capture Circuit. This file contains routines to create and handle + capture circuit. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "AudioFormats.h" +#include "streamengine.h" +#include "cpp_utils.h" +#include "circuithelper.h" + +#ifndef __INTELLISENSE__ +#include "captureCircuit.tmh" +#endif + +// +// Controls how the custom name of the bridge pin is read. +// +BOOL g_UseCustomInfName = TRUE; + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtAcxPinSetDataFormat( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat +) +/*++ + +Routine Description: + + This ACX pin callback sets the device/mixed format. + +Return Value: + + NTSTATUS + +--*/ +{ + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + PAGED_CODE(); + + // NOTE: update device/mixed format here. + + return STATUS_NOT_SUPPORTED; +} + +/////////////////////////////////////////////////////////// +// +// For more information on volume element see: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/ksnodetype-volume +// +_Use_decl_annotations_ +NTSTATUS +CodecC_EvtVolumeAssignLevelCallback( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _In_ LONG VolumeLevel +) +{ + PAGED_CODE(); + + ASSERT(Volume); + PVOLUME_ELEMENT_CONTEXT volumeCtx = GetVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + volumeCtx->VolumeLevel[Channel] = VolumeLevel; + } + else + { + for (ULONG i = 0; i < MAX_CHANNELS; ++i) + { + volumeCtx->VolumeLevel[i] = VolumeLevel; + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +CodecC_EvtVolumeRetrieveLevelCallback( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _Out_ LONG * VolumeLevel +) +{ + PAGED_CODE(); + + ASSERT(Volume); + PVOLUME_ELEMENT_CONTEXT volumeCtx = GetVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel == ALL_CHANNELS_ID) + { + Channel = 0; + } + + *VolumeLevel = volumeCtx->VolumeLevel[Channel]; + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_CreateVolumeElement( + _In_ ACXCIRCUIT Circuit, + _Out_ ACXVOLUME* Element +) +/*++ + +Routine Description: + + This routine creates a volume element. + +Return Value: + + NT status value +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + ACX_VOLUME_CALLBACKS volumeCallbacks; + ACX_VOLUME_CONFIG volumeCfg; + VOLUME_ELEMENT_CONTEXT * volumeCtx; + + PAGED_CODE(); + + // + // The driver uses this DDI to assign its volume element callbacks. + // + ACX_VOLUME_CALLBACKS_INIT(&volumeCallbacks); + volumeCallbacks.EvtAcxVolumeAssignLevel = CodecC_EvtVolumeAssignLevelCallback; + volumeCallbacks.EvtAcxVolumeRetrieveLevel = CodecC_EvtVolumeRetrieveLevelCallback; + + // + // Create Volume element + // + ACX_VOLUME_CONFIG_INIT(&volumeCfg); + volumeCfg.ChannelsCount = MAX_CHANNELS; + volumeCfg.Minimum = VOLUME_LEVEL_MINIMUM; + volumeCfg.Maximum = VOLUME_LEVEL_MAXIMUM; + volumeCfg.SteppingDelta = VOLUME_STEPPING; + volumeCfg.Callbacks = &volumeCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, VOLUME_ELEMENT_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxVolumeCreate(Circuit, &attributes, &volumeCfg, Element)); + + ASSERT(*Element != nullptr); + volumeCtx = GetVolumeElementContext(*Element); + ASSERT(volumeCtx); + + // + // (max + min)/2 puts it in the middle of the valid range, divide that by the stepping to get the nearest + // valid step, multiply that by stepping to put it back at a level value. + // + volumeCtx->VolumeLevel[0] = (VOLUME_LEVEL_MAXIMUM + VOLUME_LEVEL_MINIMUM) / 2 / VOLUME_STEPPING * VOLUME_STEPPING; + volumeCtx->VolumeLevel[1] = (VOLUME_LEVEL_MAXIMUM + VOLUME_LEVEL_MINIMUM) / 2 / VOLUME_STEPPING * VOLUME_STEPPING; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtAcxPinRetrieveName( + _In_ ACXPIN Pin, + _Out_ PUNICODE_STRING Name +) +/*++ + +Routine Description: + + If g_UseCustomInfName is false then the ACX + pin callback EvtAcxPinRetrieveName calls this + function in order to retrieve the pin name. + +Return Value: + + NTSTATUS + +--*/ +{ + UNREFERENCED_PARAMETER(Pin); + + PAGED_CODE(); + + return RtlUnicodeStringPrintf(Name, L"CustomName2"); +} + +VOID +CodecC_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin +) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + nullptr + +--*/ +{ + UNREFERENCED_PARAMETER(WdfPin); +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_CircuitCleanup( + _In_ ACXCIRCUIT Circuit +) +{ + PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx; + + PAGED_CODE(); + + // + // Remove the static capture circuit. + // + circuitCtx = GetCaptureCircuitContext(Circuit); + ASSERT(circuitCtx != nullptr); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName +) +/*++ + +Routine Description: + + Creates the static capture circuit (pictured below) + and adds it to the device context. This is called + when a new device is detected and the AddDevice + call is made by the pnp manager. + + ****************************************************** + * Capture Circuit * + * * + * +-----------------------+ * + * | | * + * | +-------------+ | * + * Host ------>| | Volume Node | |---> Bridge * + * Pin | +-------------+ | Pin * + * | | * + * +-----------------------+ * + * * + ****************************************************** + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + PCAPTURE_DEVICE_CONTEXT captureDevCtx; + ACXCIRCUIT captureCircuit = nullptr; + WDF_OBJECT_ATTRIBUTES attributes; + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // Alloc audio context to current device. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CAPTURE_DEVICE_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(WdfObjectAllocateContext(Device, &attributes, (PVOID*)&captureDevCtx)); + ASSERT(captureDevCtx); + + // + // Create a capture circuit associated with this child device. + // + RETURN_NTSTATUS_IF_FAILED(CodecC_CreateCaptureCircuit(Device, ComponentGuid, MicCustomName, CircuitName, &captureCircuit)); + + devCtx->Capture = captureCircuit; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Capture_AllocateSupportedFormats( + _In_ WDFDEVICE Device, + _In_reads_bytes_(CodecCapturePinCount) ACXPIN Pin[], + _In_ ACXCIRCUIT Circuit, + _In_ size_t CodecCapturePinCount +) +{ + UNREFERENCED_PARAMETER(CodecCapturePinCount); + + NTSTATUS status = STATUS_SUCCESS; + ACXDATAFORMAT formatPcm44100c1; + ACXDATAFORMAT formatPcm48000c1; + ACXDATAFORMATLIST formatList; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + /////////////////////////////////////////////////////////// + // + // Allocate the formats this circuit supports. + // + + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm44100c1, Circuit, Device, &formatPcm44100c1)); + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm48000c1, Circuit, Device, &formatPcm48000c1)); + + /////////////////////////////////////////////////////////// + // + // Define supported formats for the host pin. + // + + // + // The raw processing mode list is associated with each single circuit + // by ACX. A driver uses this DDI to retrieve the built-in raw + // data-format list. + // + RETURN_NTSTATUS_IF_TRUE(CodecCaptureHostPin >= CodecCapturePinCount, STATUS_INVALID_PARAMETER); + formatList = AcxPinGetRawDataFormatList(Pin[CodecCaptureHostPin]); + RETURN_NTSTATUS_IF_TRUE(formatList == nullptr, STATUS_INSUFFICIENT_RESOURCES); + + // + // The driver uses this DDI to add data formats to the raw + // processing mode list associated with the current circuit. + // + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c1)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm48000c1)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName, + _Out_ ACXCIRCUIT* Circuit +) +/*++ + +Routine Description: + + This routine builds the CODEC capture circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + WDF_OBJECT_ATTRIBUTES attributes; + ACXCIRCUIT circuit; + CODEC_CAPTURE_CIRCUIT_CONTEXT* circuitCtx; + ACXPIN pin[CodecCapturePinCount]; + + PAGED_CODE(); + + // + // Init output value. + // + *Circuit = nullptr; + + /////////////////////////////////////////////////////////// + // + // Create a circuit. + // + { + PACXCIRCUIT_INIT circuitInit = nullptr; + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + + // + // The driver uses this DDI to allocate an ACXCIRCUIT_INIT + // structure. This opaque structure is used when creating + // a standalone audio circuit representing an audio device. + // + circuitInit = AcxCircuitInitAllocate(Device); + + // + // A driver uses this DDI to free the allocated + // ACXCIRCUIT_INIT structure when an error is detected. + // Normally the structures is deleted/cleared by ACX when + // an ACX circuit is created successfully. + // + auto circuitInitScope = scope_exit([&circuitInit]() { + if (circuitInit) { + AcxCircuitInitFree(circuitInit); + } + }); + + // + // The driver uses this DDI to specify the Component ID + // of the ACX circuit. This ID is a guid that uniquely + // identifies the circuit instance (vendor specific). + // + AcxCircuitInitSetComponentId(circuitInit, ComponentGuid); + + // + // The driver uses this DDI to specify the circuit name. + // For standalone circuits, this is the audio device name + // which is used by clients to open handles to the audio devices. + // + (VOID)AcxCircuitInitAssignName(circuitInit, CircuitName); + + // + // The driver uses this DDI to specify the circuit type. The + // circuit type can be AcxCircuitTypeRender, AcxCircuitTypeCapture, + // AcxCircuitTypeOther, or AcxCircuitTypeMaximum (for validation). + // + AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeCapture); + + // + // The driver uses this DDI to assign its (if any) power callbacks. + // + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = CodecC_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = CodecC_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(circuitInit, &powerCallbacks); + + // + // The driver uses this DDI to register for a stream-create callback. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback(circuitInit, CodecC_EvtCircuitCreateStream)); + + // + // The driver uses this DDI to create a new ACX circuit. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_CAPTURE_CIRCUIT_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit)); + + circuitInitScope.release(); + + circuitCtx = GetCaptureCircuitContext(circuit); + ASSERT(circuitCtx); + } + + // + // Post circuit creation initialization. + // + + /////////////////////////////////////////////////////////// + // + // Create volume element. + // + { + ACXELEMENT elements[CaptureElementCount] = { 0 }; + + RETURN_NTSTATUS_IF_FAILED(CodecC_CreateVolumeElement(circuit, (ACXVOLUME*)&elements[CaptureVolumeIndex])); + + // + // Saving the volume element in the circuit context. + // + circuitCtx->VolumeElement = (ACXVOLUME)elements[CaptureVolumeIndex]; + + // + // The driver uses this DDI post circuit creation to add ACXELEMENTs. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + } + + /////////////////////////////////////////////////////////// + // + // Create the pins for the circuit. + // + { + ACX_PIN_CALLBACKS pinCallbacks; + ACX_PIN_CONFIG pinCfg; + CODEC_PIN_CONTEXT* pinCtx; + + /////////////////////////////////////////////////////////// + // + // Create capture streaming pin. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = CodecC_EvtAcxPinSetDataFormat; + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSource; + pinCfg.Communication = AcxPinCommunicationSink; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecC_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + // + // The driver uses this DDI to create one or more pins on the circuits. + // + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &(pin[CodecCaptureHostPin]))); + + ASSERT(pin[CodecCaptureHostPin] != nullptr); + pinCtx = GetCodecPinContext(pin[CodecCaptureHostPin]); + ASSERT(pinCtx); + pinCtx->CodecPinType = CodecPinTypeHost; + + /////////////////////////////////////////////////////////// + // + // Create capture endpoint pin. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + ACX_PIN_CONFIG_INIT(&pinCfg); + + pinCfg.Type = AcxPinTypeSink; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSNODETYPE_MICROPHONE; + pinCfg.PinCallbacks = &pinCallbacks; + + // Specify how to read the custom name. + if (g_UseCustomInfName) + { + pinCfg.Name = MicCustomName; + } + else + { + pinCallbacks.EvtAcxPinRetrieveName = CodecC_EvtAcxPinRetrieveName; + } + g_UseCustomInfName = !g_UseCustomInfName; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = circuit; + + // + // The driver uses this DDI to create one or more pins on the circuits. + // + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &(pin[CodecCaptureBridgePin]))); + + ASSERT(pin[CodecCaptureBridgePin] != nullptr); + } + + /////////////////////////////////////////////////////////// + // + // Add audio jack to bridge pin. + // For more information on audio jack see: https://docs.microsoft.com/en-us/windows/win32/api/devicetopology/ns-devicetopology-ksjack_description + // + { + ACX_JACK_CONFIG jackCfg; + ACXJACK jack; + PJACK_CONTEXT jackCtx; + + ACX_JACK_CONFIG_INIT(&jackCfg); + jackCfg.Description.ChannelMapping = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; + jackCfg.Description.Color = RGB(0, 0, 0); + jackCfg.Description.ConnectionType = AcxConnTypeAtapiInternal; + jackCfg.Description.GeoLocation = AcxGeoLocFront; + jackCfg.Description.GenLocation = AcxGenLocPrimaryBox; + jackCfg.Description.PortConnection = AcxPortConnIntegratedDevice; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, JACK_CONTEXT); + attributes.ParentObject = pin[CodecCaptureBridgePin]; + + RETURN_NTSTATUS_IF_FAILED(AcxJackCreate(pin[CodecCaptureBridgePin], &attributes, &jackCfg, &jack)); + + ASSERT(jack != nullptr); + + jackCtx = GetJackContext(jack); + ASSERT(jackCtx); + jackCtx->Dummy = 0; + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddJacks(pin[CodecCaptureBridgePin], &jack, 1)); + } + + RETURN_NTSTATUS_IF_FAILED(Capture_AllocateSupportedFormats(Device, pin, circuit, CodecCapturePinCount)); + + /////////////////////////////////////////////////////////// + // + // The driver uses this DDI post circuit creation to add ACXPINs. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, pin, CodecCapturePinCount)); + + // + // Set output value. + // + *Circuit = circuit; + + // + // Done. + // + status = STATUS_SUCCESS; + + return status; +} + +_Use_decl_annotations_ +NTSTATUS +CodecC_EvtCircuitPowerUp( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE PreviousState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(PreviousState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +CodecC_EvtCircuitPowerDown( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE TargetState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(TargetState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID * SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine creates a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + PCAPTURE_DEVICE_CONTEXT devCtx; + WDF_OBJECT_ATTRIBUTES attributes; + ACXSTREAM stream; + STREAMENGINE_CONTEXT * streamCtx; + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_RT_STREAM_CALLBACKS rtCallbacks; + CCaptureStreamEngine * streamEngine = nullptr; + CODEC_CAPTURE_CIRCUIT_CONTEXT * circuitCtx; + CODEC_PIN_CONTEXT * pinCtx; + + auto streamEngineScope = scope_exit([&streamEngine]() { + + if (streamEngine) + { + delete streamEngine; + } + + }); + + PAGED_CODE(); + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)); + + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != nullptr); + + circuitCtx = GetCaptureCircuitContext(Circuit); + ASSERT(circuitCtx != nullptr); + + pinCtx = GetCodecPinContext(Pin); + ASSERT(pinCtx != nullptr); + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = EvtStreamPause; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Init RT streaming callbacks. + // + ACX_RT_STREAM_CALLBACKS_INIT(&rtCallbacks); + rtCallbacks.EvtAcxStreamGetHwLatency = EvtStreamGetHwLatency; + rtCallbacks.EvtAcxStreamAllocateRtPackets = EvtStreamAllocateRtPackets; + rtCallbacks.EvtAcxStreamFreeRtPackets = EvtStreamFreeRtPackets; + rtCallbacks.EvtAcxStreamGetCapturePacket = CodecC_EvtStreamGetCapturePacket; + rtCallbacks.EvtAcxStreamGetCurrentPacket = EvtStreamGetCurrentPacket; + rtCallbacks.EvtAcxStreamGetPresentationPosition = EvtStreamGetPresentationPosition; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRtStreamCallbacks(StreamInit, &rtCallbacks)); + + // + // Buffer notifications are supported. + // + AcxStreamInitSetAcxRtStreamSupportsNotifications(StreamInit); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, STREAMENGINE_CONTEXT); + attributes.EvtDestroyCallback = EvtStreamDestroy; + RETURN_NTSTATUS_IF_FAILED(AcxRtStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + streamCtx = GetStreamEngineContext(stream); + ASSERT(streamCtx); + + // + // Create the virtual streaming engine which will control + // streaming logic for the capture circuit. + // + streamEngine = new (POOL_FLAG_NON_PAGED, DeviceDriverTag) CCaptureStreamEngine(stream, StreamFormat); + RETURN_NTSTATUS_IF_TRUE(streamEngine == nullptr, STATUS_INSUFFICIENT_RESOURCES); + + streamCtx->StreamEngine = (PVOID)streamEngine; + + streamEngine = nullptr; + + // + // Done. + // + status = STATUS_SUCCESS; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtStreamGetCapturePacket( + _In_ ACXSTREAM Stream, + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData +) +{ + PSTREAMENGINE_CONTEXT ctx; + CCaptureStreamEngine* streamEngine = nullptr; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = static_cast<CCaptureStreamEngine*>(ctx->StreamEngine); + + return streamEngine->GetCapturePacket(LastCapturePacket, QPCPacketStart, MoreData); +} + + diff --git a/audio/Acx/Samples/Common/CircuitHelper.cpp b/audio/Acx/Samples/Common/CircuitHelper.cpp new file mode 100644 index 00000000..bfff74b2 --- /dev/null +++ b/audio/Acx/Samples/Common/CircuitHelper.cpp @@ -0,0 +1,620 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + CircuitHelper.cpp + +Abstract: + + This module contains helper functions for circuits. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include "CircuitHelper.h" + +#ifndef __INTELLISENSE__ +#include "CircuitHelper.tmh" +#endif + +const ULONG _DSP_STREAM_PROPERTY_UI4_VALUE = 1; + +PAGED_CODE_SEG +NTSTATUS AllocateFormat( + _In_ KSDATAFORMAT_WAVEFORMATEXTENSIBLE WaveFormat, + _In_ ACXCIRCUIT Circuit, + _In_ WDFDEVICE Device, + _Out_ ACXDATAFORMAT* Format +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + ACX_DATAFORMAT_CONFIG formatCfg; + ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &WaveFormat); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FORMAT_CONTEXT); + attributes.ParentObject = Circuit; + + // + // Creates an ACXDATAFORMAT handle for the given wave format. + // + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, Format)); + + ASSERT((*Format) != NULL); + FORMAT_CONTEXT* formatCtx; + formatCtx = GetFormatContext(*Format); + ASSERT(formatCtx); + UNREFERENCED_PARAMETER(formatCtx); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS CreateStreamBridge( + _In_ ACX_STREAM_BRIDGE_CONFIG StreamCfg, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ DSP_PIN_CONTEXT* PinCtx, + _In_ BOOL Render) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + attributes.ParentObject = Pin; + + ACX_OBJECTBAG_CONFIG objBagCfg; + ACXOBJECTBAG objBag = NULL; + ACX_OBJECTBAG_CONFIG_INIT(&objBagCfg); + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Circuit; + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag)); + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(objBag, &TestUI4, _DSP_STREAM_PROPERTY_UI4_VALUE)); + + // + // Add a stream BRIDGE. + // + PCGUID inModes[] = { + &AUDIO_SIGNALPROCESSINGMODE_RAW, + &AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + }; + + if (Render) + { + StreamCfg.InModesCount = SIZEOF_ARRAY(inModes); + StreamCfg.InModes = inModes; + } + + // + // Do not specify InModes for capture - this will prevent the ACX framework from adding created streams to this stream + // bridge automatically. We want to add the stream bridges manually since we don't want KWS streams added. + // + StreamCfg.OutMode = &AUDIO_SIGNALPROCESSINGMODE_RAW; + StreamCfg.OutStreamVarArguments = objBag; + + // + // Uncomment this line to reverse the change-state sequence notifications. + // + // streamCfg.Flags |= AcxStreamBridgeInvertChangeStateSequence; + + ACXSTREAMBRIDGE streamBridge = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxStreamBridgeCreate(Circuit, &attributes, &StreamCfg, &streamBridge)); + + if (!Render) + { + PinCtx->HostStreamBridge = streamBridge; + } + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddStreamBridges(Pin, &streamBridge, 1)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ConnectRenderCircuitElements( + _In_ ACXAUDIOENGINE AudioEngineElement, + _In_ ACXCIRCUIT Circuit +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Explicitly connect the circuit/elements. Note that driver doesn't + // need to perform this step when circuit/elements are connected in the + // same order as they were added to the circuit. By default ACX connects + // the elements starting from the sink circuit pin and ending with the + // source circuit pin for both render and capture devices. + // + // Circuit layout + // ----------------------------------------- + // | | + // | -------------------- | + // Host -0->|-----1->| |-0-------->|-3-> Bridge Pin + // | | Audio Engine | | + // Offload -1->|-----2->| Node |-3--| | + // | |------------------| | | + // | | | + // Loopback <-2-|<------------------------------ | | + // | | + // | | + // |---------------------------------------| + // + + ACX_CONNECTION connections[4]; + + ACX_CONNECTION_INIT(&connections[0], Circuit, AudioEngineElement); + connections[0].FromPin.Id = RenderHostPin; + connections[0].ToPin.Id = 1; + + ACX_CONNECTION_INIT(&connections[1], Circuit, AudioEngineElement); + connections[1].FromPin.Id = RenderOffloadPin; + connections[1].ToPin.Id = 2; + + ACX_CONNECTION_INIT(&connections[2], AudioEngineElement, Circuit); + connections[2].ToPin.Id = RenderLoopbackPin; + connections[2].FromPin.Id = 3; + + ACX_CONNECTION_INIT(&connections[3], AudioEngineElement, Circuit); + connections[3].ToPin.Id = RenderBridgePin; + connections[3].FromPin.Id = 0; + + // + // Add the connections linking circuit to elements. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(Circuit, connections, SIZEOF_ARRAY(connections))); + + return status; + +} + +PAGED_CODE_SEG +NTSTATUS +Codec_GetModeFromAttributeList( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _Out_ GUID * SignalProcessingMode + ) +{ + NTSTATUS status = STATUS_NO_MORE_ENTRIES; + PKSATTRIBUTE attributeHeader = NULL; + PAGED_CODE(); + *SignalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT; + + status = FindKsAttributeById(Attributes, + AttributesSize, + &KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE, + sizeof(KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE), + &attributeHeader); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + ASSERT(attributeHeader->Attribute == KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE); + ASSERT(attributeHeader->Size == sizeof(KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE)); + + KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE* signalProcessingModeAttribute; + signalProcessingModeAttribute = (KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE*)attributeHeader; + *SignalProcessingMode = signalProcessingModeAttribute->SignalProcessingMode; + status = STATUS_SUCCESS; +exit: + return status; +} + +struct AFX_FIND_KSATTRIBUTE_BY_ID +{ + const _GUID * Id; + ULONG Size; + PKSATTRIBUTE Attribute; +}; + +PAGED_CODE_SEG +NTSTATUS +FindKsAttributeByIdVisitor( + _In_ PKSATTRIBUTE AttributeHeader, + _In_ PVOID Context, + _Out_ BOOLEAN * bContinue + ) +{ + NTSTATUS status = STATUS_SUCCESS; + AFX_FIND_KSATTRIBUTE_BY_ID * ctx = (AFX_FIND_KSATTRIBUTE_BY_ID *)Context; + PAGED_CODE(); + // Default: continue searching. + *bContinue = TRUE; + + if (IsEqualGUIDAligned(AttributeHeader->Attribute, *ctx->Id)) + { + // Validate its size. + if (AttributeHeader->Size < ctx->Size) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + ctx->Attribute = AttributeHeader; + *bContinue = FALSE; + } +exit: + return status; +} + +PAGED_CODE_SEG +NTSTATUS +FindKsAttributeById( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _In_ const _GUID * AttributeId, + _In_ ULONG AttributeSize, + _Out_ PKSATTRIBUTE * AttributeHeader + ) +{ + PAGED_CODE(); + NTSTATUS status; + AFX_FIND_KSATTRIBUTE_BY_ID ctx = {0}; + *AttributeHeader = NULL; + ctx.Id = AttributeId; + ctx.Size = AttributeSize; + status = TraverseKsAttributeList(Attributes, AttributesSize, FindKsAttributeByIdVisitor, &ctx); + if (!NT_SUCCESS(status)) + { + goto exit; + } + if (ctx.Attribute == NULL) + { + status = STATUS_NO_MORE_ENTRIES; + goto exit; + } + *AttributeHeader = ctx.Attribute; +exit: + return status; +} + +PAGED_CODE_SEG +NTSTATUS +TraverseKsAttributeList( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _In_ PFN_KSATTRIBUTES_VISITOR Visitor, + _In_ PVOID Context + ) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + ULONG cbRemaining = 0; + PKSATTRIBUTE attributeHeader = NULL; + ASSERT(Visitor); + // + // Note: multiple-item ptr must have a FILE_QUAD_ALIGNMENT only in relation to the Pin's format size. + // I.e., it is not guaranteed that the attributes are FILE_QUAD_ALIGNMENT in memory, unless the caller reallocates + // them before calling this function (which is currently not done by anyone in any driver/sample). + // + //ASSERT((ULONG_PTR)Attributes == (((ULONG_PTR)Attributes + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT)); + if (AttributesSize < sizeof(KSMULTIPLE_ITEM)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + if (Attributes->Size < sizeof(KSMULTIPLE_ITEM)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + if (AttributesSize < Attributes->Size) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + cbRemaining = Attributes->Size; + // + // Init ptr / size of attributes of list. + // + cbRemaining -= sizeof(KSMULTIPLE_ITEM); + attributeHeader = (PKSATTRIBUTE)(Attributes + 1); + for (ULONG i = 0; i < Attributes->Count; i++) + { + BOOLEAN bContinue = TRUE; + size_t cbAttribute = 0; + + if (cbRemaining < sizeof(KSATTRIBUTE)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + if (attributeHeader->Size < sizeof(KSATTRIBUTE)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + if (cbRemaining < attributeHeader->Size) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + // + // Invoke the descriptor enumeration routine. + // + status = Visitor(attributeHeader, Context, &bContinue); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + if (!bContinue) + { + break; + } + // + // Adjust pointer and buffer size to next attribute (QWORD aligned) + // + cbAttribute = CODEC_ALIGN_SIZE_UP_CONSTANT(attributeHeader->Size, FILE_QUAD_ALIGNMENT); + if (cbRemaining < cbAttribute) + { + // + // Out of buffer, check if this was the last attribute. + // + if (i + 1 != Attributes->Count) + { + // + // This was not the last attribute, nevertheless there is no more buffer, error out. + // + status = STATUS_INVALID_PARAMETER; + goto exit; + } + // This was the final attribute. Exit loop with success status. + break; + } + // Check next attribute. + attributeHeader = (PKSATTRIBUTE)(((PBYTE)attributeHeader) + cbAttribute); + cbRemaining -= (ULONG)cbAttribute; + } + // Normalize success code. + status = STATUS_SUCCESS; +exit: + return status; +} + +PAGED_CODE_SEG +NTSTATUS +EvtJackRetrievePresence( + _In_ ACXJACK Jack, + _In_ PBOOLEAN IsConnected +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Jack); + UNREFERENCED_PARAMETER(IsConnected); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Because this is a sample we always return true (jack is present). A real driver should check + // if the device is actually present before returning true. + // + *IsConnected = true; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CreateAudioJack( + _In_ ULONG ChannelMapping, + _In_ ULONG Color, + _In_ ACX_JACK_CONNECTION_TYPE ConnectionType, + _In_ ACX_JACK_GEO_LOCATION GeoLocation, + _In_ ACX_JACK_GEN_LOCATION GenLocation, + _In_ ACX_JACK_PORT_CONNECTION PortConnection, + _In_ ULONG Flags, + _In_ ACXPIN BridgePin + ) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + ACX_JACK_CONFIG jackCfg; + ACXJACK jack; + PJACK_CONTEXT jackCtx; + ACX_JACK_CALLBACKS jackCallbacks; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + ACX_JACK_CONFIG_INIT(&jackCfg); + jackCfg.Description.ChannelMapping = ChannelMapping; + jackCfg.Description.Color = Color; + jackCfg.Description.ConnectionType = ConnectionType; + jackCfg.Description.GeoLocation = GeoLocation; + jackCfg.Description.GenLocation = GenLocation; + jackCfg.Description.PortConnection = PortConnection; + jackCfg.Flags = Flags; + + ACX_JACK_CALLBACKS_INIT(&jackCallbacks); + jackCallbacks.EvtAcxJackRetrievePresenceState = EvtJackRetrievePresence; + jackCfg.Callbacks = &jackCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, JACK_CONTEXT); + attributes.ParentObject = BridgePin; + + status = AcxJackCreate(BridgePin, &attributes, &jackCfg, &jack); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + ASSERT(jack != nullptr); + + jackCtx = GetJackContext(jack); + ASSERT(jackCtx); + jackCtx->Dummy = 0; + + status = AcxPinAddJacks(BridgePin, &jack, 1); + +exit: + return status; +} + +PAGED_CODE_SEG +VOID +CpuResourcesCallbackHelper +( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request, + _In_ ACXELEMENT Element +) +{ + NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; + ULONG_PTR outDataCb = 0; + ACX_REQUEST_PARAMETERS params; + ULONG minSize = sizeof(ULONG); + + PAGED_CODE(); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + if ((params.Type != AcxRequestTypeProperty) || + (params.Parameters.Property.ItemType != AcxItemTypeElement)) + { + // Return to acx + (VOID) AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + Request = NULL; + goto exit; + } + + if (Element == NULL) + { + ntStatus = STATUS_NOT_SUPPORTED; + goto exit; + } + + ULONG elementId = params.Parameters.Property.ItemId; + ULONG currentElementId = AcxElementGetId(Element); + ULONG valueCb = params.Parameters.Property.ValueCb; + + if (valueCb != 0) + { + if (params.Parameters.Property.Value == NULL) + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + } + + // + // Check to see if the current node is the peakmeter node, if not then return the call to ACX + // + if (elementId != currentElementId) + { + (VOID) AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + Request = NULL; + goto exit; + } + + if (params.Parameters.Property.Verb == AcxPropertyVerbGet) + { + + if (valueCb == 0) + { + outDataCb = minSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + goto exit; + } + else if (valueCb < minSize) + { + outDataCb = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + else + { + *((PULONG)params.Parameters.Property.Value) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU; + params.Parameters.Property.ValueCb = sizeof(ULONG); + outDataCb = params.Parameters.Property.ValueCb; + ntStatus = STATUS_SUCCESS; + } + } + else if (params.Parameters.Property.Verb == AcxPropertyVerbBasicSupport) + { + if ((valueCb != sizeof(ULONG)) && (valueCb != sizeof(KSPROPERTY_DESCRIPTION))) + { + outDataCb = minSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + goto exit; + } + + if (valueCb >= sizeof(KSPROPERTY_DESCRIPTION)) + { + // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it + // + PKSPROPERTY_DESCRIPTION PropDesc = (PKSPROPERTY_DESCRIPTION)params.Parameters.Property.Value; + + PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET; + PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); + PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + PropDesc->PropTypeSet.Id = VT_UI4; + PropDesc->PropTypeSet.Flags = 0; + PropDesc->MembersListCount = 0; + PropDesc->Reserved = 0; + outDataCb = sizeof(KSPROPERTY_DESCRIPTION); + ntStatus = STATUS_SUCCESS; + } + else if (valueCb >= sizeof(ULONG)) + { + // if return buffer can hold a ULONG, return the access flags + // + *((PULONG)params.Parameters.Property.Value) = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET; + outDataCb = minSize; + ntStatus = STATUS_SUCCESS; + } + else if (valueCb > 0) + { + outDataCb = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + else + { + outDataCb = minSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + } + else + { + // + // Just give it back to ACX. After this call the request is gone. + // + (VOID) AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + Request = NULL; + goto exit; + } + +exit: + if (Request != NULL) + { + WdfRequestCompleteWithInformation(Request, ntStatus, outDataCb); + } +} // EvtAudioCpuResourcesCallback diff --git a/audio/Acx/Samples/Common/CircuitHelper.h b/audio/Acx/Samples/Common/CircuitHelper.h new file mode 100644 index 00000000..58938153 --- /dev/null +++ b/audio/Acx/Samples/Common/CircuitHelper.h @@ -0,0 +1,135 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + CircuitHelper.h + +Abstract: + + This module contains helper functions for endpoints. + +Environment: + + Kernel mode + +--*/ + +// size_t +// __inline +// CODEC_ALIGN_SIZE_DOWN_CONSTANT( +// IN size_t Length, +// IN size_t AlignTo +// ) +#define CODEC_ALIGN_SIZE_DOWN_CONSTANT(Length, AlignTo) ((Length) & ~((AlignTo)-1)) + +#define CODEC_ALIGN_SIZE_DOWN CODEC_ALIGN_SIZE_DOWN_CONSTANT + +// size_t +// __inline +// CODEC_ALIGN_SIZE_UP_CONSTANT( +// IN size_t Length, +// IN size_t AlignTo +// ) +#define CODEC_ALIGN_SIZE_UP_CONSTANT(Length, AlignTo) CODEC_ALIGN_SIZE_DOWN_CONSTANT((Length) + (AlignTo)-1, (AlignTo)) + +#define CODEC_ALIGN_SIZE_UP CODEC_ALIGN_SIZE_UP_CONSTANT + +PAGED_CODE_SEG +NTSTATUS +Codec_GetModeFromAttributeList( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _Out_ GUID * SignalProcessingMode + ); + +// +// Enumeration visitor callback. +// +typedef +NTSTATUS +(EVT_KSATTRIBUTES_VISITOR)( + _In_ PKSATTRIBUTE AttributeHeader, + _In_ PVOID Context, + _Out_ BOOLEAN * bContinue + ); + +typedef EVT_KSATTRIBUTES_VISITOR *PFN_KSATTRIBUTES_VISITOR; + +static +PAGED_CODE_SEG +EVT_KSATTRIBUTES_VISITOR FindKsAttributeByIdVisitor; + +PAGED_CODE_SEG +NTSTATUS +FindKsAttributeById( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _In_ const _GUID * AttributeId, + _In_ ULONG AttributeSize, + _Out_ PKSATTRIBUTE * AttributeHeader + ); + +PAGED_CODE_SEG +NTSTATUS +TraverseKsAttributeList( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _In_ PFN_KSATTRIBUTES_VISITOR Visitor, + _In_ PVOID Context + ); + +PAGED_CODE_SEG +NTSTATUS AllocateFormat( + _In_ KSDATAFORMAT_WAVEFORMATEXTENSIBLE WaveFormat, + _In_ ACXCIRCUIT Circuit, + _In_ WDFDEVICE Device, + _Out_ ACXDATAFORMAT* Format +); + +PAGED_CODE_SEG +NTSTATUS CreateStreamBridge( + _In_ ACX_STREAM_BRIDGE_CONFIG StreamCfg, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ DSP_PIN_CONTEXT* PinCtx, + _In_ BOOL Render +); + +PAGED_CODE_SEG +NTSTATUS ConnectRenderCircuitElements( + _In_ ACXAUDIOENGINE AudioEngineElement, + _In_ ACXCIRCUIT Circuit +); + +PAGED_CODE_SEG +NTSTATUS CreateAudioJack( + _In_ ULONG ChannelMapping, + _In_ ULONG Color, + _In_ ACX_JACK_CONNECTION_TYPE ConnectionType, + _In_ ACX_JACK_GEO_LOCATION GeoLocation, + _In_ ACX_JACK_GEN_LOCATION GenLocation, + _In_ ACX_JACK_PORT_CONNECTION PortConnection, + _In_ ULONG Flags, + _In_ ACXPIN BridgePin +); + +PAGED_CODE_SEG +NTSTATUS EvtJackRetrievePresence( + _In_ ACXJACK Jack, + _In_ PBOOLEAN IsConnected +); + +PAGED_CODE_SEG +VOID CpuResourcesCallbackHelper( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request, + _In_ ACXELEMENT Element +); + diff --git a/audio/Acx/Samples/Common/KeywordDetector.cpp b/audio/Acx/Samples/Common/KeywordDetector.cpp new file mode 100644 index 00000000..f3476745 --- /dev/null +++ b/audio/Acx/Samples/Common/KeywordDetector.cpp @@ -0,0 +1,484 @@ +/*++ + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + KeywordDetector.cpp + +Abstract: + + Sample keyword detector management. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" +#include "KeywordDetector.h" + +PAGED_CODE_SEG +CKeywordDetector::CKeywordDetector() + : + m_streamRunning(FALSE), + m_qpcStartCapture(0), + m_nLastQueuedPacket(-1), + m_SoundDetectorArmed1(FALSE), + m_SoundDetectorArmed2(FALSE), + m_SoundDetectorData1(0), + m_SoundDetectorData2(0), + m_ullKeywordStartTimestamp(0), + m_ullKeywordStopTimestamp(0) +{ + PAGED_CODE(); + + // Initialize our pool of packets and the list structures + KeInitializeSpinLock(&PacketPoolSpinLock); + KeInitializeSpinLock(&PacketFifoSpinLock); + ResetFifo(); +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() +{ + PAGED_CODE(); + + NTSTATUS ntStatus; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; + + RTL_QUERY_REGISTRY_TABLE paramTable[] = { + // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"KeywordDetectorStartTimestamp", &m_ullKeywordStartTimestamp, (REG_QWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_QWORD, &m_ullKeywordStartTimestamp, sizeof(ULONGLONG) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"KeywordDetectorStopTimestamp", &m_ullKeywordStopTimestamp, (REG_QWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_QWORD, &m_ullKeywordStopTimestamp, sizeof(ULONGLONG) }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); + + if (!NT_SUCCESS(ntStatus)) + { + return ntStatus; + } + + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); + if (DriverKey) + { + ZwClose(DriverKey); + } + + return ntStatus; +} + + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::ResetDetector(_In_ GUID eventId) +{ + PAGED_CODE(); + + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = 0; + m_SoundDetectorArmed1 = FALSE; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = 0; + m_SoundDetectorArmed2 = FALSE; + } + else if(eventId == GUID_NULL) + { + // When DownloadDetectorData is called to set the pattern for multiple keywords + // at once, all keyword detectors must be reset. Also used during keyword detector + // initialization and cleanup to restore it back to initial state and power down. + m_SoundDetectorData1 = 0; + m_SoundDetectorArmed1 = FALSE; + m_SoundDetectorData2 = 0; + m_SoundDetectorArmed2 = FALSE; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data) +{ + PAGED_CODE(); + + // reset the detector for this event Id + ResetDetector(eventId); + + // In this example, the driver supports detection data + // set with a single call for both detectors, or each + // detector set individually. + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = Data; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = Data; + } + else if(eventId == GUID_NULL) + { + // in this simplified example "Data" is set on both detectors, + // however in a real system "Data" could be a data structure which + // contains different values for each detector. + m_SoundDetectorData1 = m_SoundDetectorData2 = Data; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +// The following function is only applicable to single keyword detection systems, +// and assumes keyword detector #1. +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data) +{ + PAGED_CODE(); + + if (eventId == CONTOSO_KEYWORD1) + { + *Data = m_SoundDetectorData1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Data = m_SoundDetectorData2; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +ULONGLONG CKeywordDetector::GetStartTimestamp() +{ + PAGED_CODE(); + + return m_ullKeywordStartTimestamp; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +ULONGLONG CKeywordDetector::GetStopTimestamp() +{ + PAGED_CODE(); + + return m_ullKeywordStopTimestamp; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::ResetFifo() +{ + PAGED_CODE(); + + m_qpcStartCapture = 0; + m_nLastQueuedPacket = (-1); + InitializeListHead(&PacketPoolHead); + InitializeListHead(&PacketFifoHead); + + for (int i = 0; i < ARRAYSIZE(PacketPool); i++) + { + InsertTailList(&PacketPoolHead, &PacketPool[i].ListEntry); + } + return; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::SetArmed(_In_ GUID eventId, _In_ BOOLEAN Arm) +{ + PAGED_CODE(); + + BOOL previousArming = FALSE; + NTSTATUS ntStatus = STATUS_SUCCESS; + + // the previous state is "armed" if either detector is armed. + // this reflects the fact that both detectors are sharing the + // same stream. + previousArming = m_SoundDetectorArmed1 || m_SoundDetectorArmed2; + + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorArmed1 = Arm; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorArmed2 = Arm; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + if (Arm && !previousArming && m_qpcStartCapture == 0) + { + StartBufferingStream(); + } + else if (!Arm && previousArming && !m_streamRunning) + { + // if it's not actively streaming and everything has been disarmed, + // then stop buffering. + ResetFifo(); + } + + return ntStatus; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetArmed(_In_ GUID eventId, _Out_ BOOLEAN *Arm) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (eventId == CONTOSO_KEYWORD1) + { + *Arm = m_SoundDetectorArmed1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Arm = m_SoundDetectorArmed2; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return ntStatus; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::Run() +{ + PAGED_CODE(); + + if (m_qpcStartCapture == 0) + { + StartBufferingStream(); + } + + m_streamRunning = TRUE; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::Stop() +{ + PAGED_CODE(); + + ResetFifo(); + m_streamRunning = FALSE; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::StartBufferingStream() +{ + LARGE_INTEGER qpc; + LARGE_INTEGER qpcFrequency; + + PAGED_CODE(); + + qpc = KeQueryPerformanceCounter(&qpcFrequency); + m_qpcStartCapture = qpc.QuadPart; + m_qpcFrequency = qpcFrequency.QuadPart; + + return; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::NotifyDetection() +{ + PAGED_CODE(); + + // A detection will only happen if armed and the + // stream is already running. If there isn't a client + // running, then set the stream start time to align + // with this detection. + if (!m_streamRunning) + { + StartBufferingStream(); + + // The following code is for testing purposes only. + // m_qpcFrequency is defined to be the number of ticks in 1 second. + // Use the stream start time (the current time retrieved in StartBufferStream) to + // mark when the keyword ended, and the start time minus 1 second worth of ticks + // to mark when the keyword started. Also, adjust the stream start time to align + // to this new keyword start time, so that the simulated stream contains the full keyword. + + m_ullKeywordStopTimestamp = m_qpcStartCapture; // stop time is the current time + m_qpcStartCapture = m_qpcStartCapture - m_qpcFrequency; // buffer start time is 1 second ago + m_ullKeywordStartTimestamp = m_qpcStartCapture; // buffer start time = keyword start time + + } + else + { + // The following code is for testing purposes only. + // If the stream is running, we cannot modify qpcStartCapture to be in + // the past, so instead make the keyword start & stop times fit within the + // time period that the keyword has been running. If it has been running + // for more than 1 second, then set the keyword start time to be 1 second back + // into the stream, as though we just figured out there was a keyword there. + // If it has been running less than one second, then the keyword size ends + // up being however long the stream has been running. + + LARGE_INTEGER qpc; + qpc = KeQueryPerformanceCounter(NULL); + + m_ullKeywordStopTimestamp = qpc.QuadPart; // stop time is the current time + + if (m_qpcStartCapture < (qpc.QuadPart - m_qpcFrequency)) + { + m_ullKeywordStartTimestamp = (qpc.QuadPart - m_qpcFrequency); + } + else + { + m_ullKeywordStartTimestamp = m_qpcStartCapture; + } + + } + + return; +} + +_IRQL_requires_min_(DISPATCH_LEVEL) +VOID CKeywordDetector::DpcRoutine(_In_ LONGLONG PerformanceCounter, _In_ LONGLONG PerformanceFrequency) +{ + LONGLONG currentPacket; + LONGLONG packetsToQueue; + + // TODO: the timer only runs when the stream is open, but really for KWS it should be building up a collection of burst data + // in the queue from 1.5 sec before the trigger happens. Is there some way to simulate that behavior here? Without doing that, + // there isn't really a burst that happens, just a trickle because while the timestamps will be right, the queue won't contain + // anything until the timer fires at the normal rate. + + if (m_qpcStartCapture <= 0) + { + return; + } + + currentPacket = (PerformanceCounter - m_qpcStartCapture) * (SamplesPerSecond / SamplesPerPacket) / PerformanceFrequency; + packetsToQueue = currentPacket - m_nLastQueuedPacket; + + while (packetsToQueue > 0) + { + LIST_ENTRY* packetListEntry; + PACKET_ENTRY* packetEntry; + + do + { + packetListEntry = ExInterlockedRemoveHeadList(&PacketPoolHead, &PacketPoolSpinLock); + if (packetListEntry != NULL) break; + + // Pool is empty, no room to buffer more, an overrun is occurring. Drop and reuse the + // oldest packet from head of fifo. + + // Since the pool is empty, the fifo should be full. However, although unlikely, the + // driver might empty the fifo before this routine removes a packet. In that case, the + // pool should have packets available again. Therefore this is a retry loop. + packetListEntry = ExInterlockedRemoveHeadList(&PacketFifoHead, &PacketFifoSpinLock); + if (packetListEntry != NULL) break; + } while (TRUE); + + packetEntry = CONTAINING_RECORD(packetListEntry, PACKET_ENTRY, ListEntry); + + packetEntry->PacketNumber = ++m_nLastQueuedPacket; + packetEntry->QpcWhenSampled = m_qpcStartCapture + (packetEntry->PacketNumber * PerformanceFrequency * SamplesPerPacket / SamplesPerSecond); + + // TODO: this should really put something real in the buffer. Use the sine tone generator maybe? + RtlZeroMemory(&packetEntry->Samples[0], sizeof(packetEntry->Samples)); + + ExInterlockedInsertTailList(&PacketFifoHead, packetListEntry, &PacketFifoSpinLock); + + packetsToQueue -= 1; + } +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetReadPacket +( + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_writes_(PacketSize) PVOID *Packets, + _Out_ ULONG *PacketNumber, + _Out_ ULONG64 *PerformanceCounterValue, + _Out_ BOOLEAN *MoreData +) +{ + NTSTATUS ntStatus; + BYTE *packetData; + PACKET_ENTRY *packetEntry; + LIST_ENTRY *packetListEntry = NULL; + + packetListEntry = ExInterlockedRemoveHeadList(&PacketFifoHead, &PacketFifoSpinLock); + if (packetListEntry == NULL) + { + ntStatus = STATUS_DEVICE_NOT_READY; + goto Exit; + } + packetEntry = CONTAINING_RECORD(packetListEntry, PACKET_ENTRY, ListEntry); + + ntStatus = RtlLongLongToULong(packetEntry->PacketNumber, PacketNumber); + if (!NT_SUCCESS(ntStatus)) + { + goto Exit; + } + + packetData = (PBYTE) Packets[(*PacketNumber) % PacketCount]; + + *PerformanceCounterValue = packetEntry->QpcWhenSampled; + *MoreData = !IsListEmpty(&PacketFifoHead); + + // TODO: the packet size here needs to line up to the packet size allocated. + // Also, handle the first packet offset + RtlCopyMemory(packetData, packetEntry->Samples, min(sizeof(packetEntry->Samples), PacketSize)); + +Exit: + if (packetListEntry != NULL) + { + ExInterlockedInsertTailList(&PacketPoolHead, packetListEntry, &PacketPoolSpinLock); + } + + return ntStatus; +} diff --git a/audio/Acx/Samples/Common/KeywordDetector.h b/audio/Acx/Samples/Common/KeywordDetector.h new file mode 100644 index 00000000..2d5293b8 --- /dev/null +++ b/audio/Acx/Samples/Common/KeywordDetector.h @@ -0,0 +1,145 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + KeywordDetector.h + +Abstract: + + Sample Keyword Detector. + + +--*/ + +#pragma once + +typedef struct +{ + SOUNDDETECTOR_PATTERNHEADER Header; + LONGLONG ContosoDetectorConfigurationData; +} CONTOSO_KEYWORDCONFIGURATION; + +typedef struct +{ + SOUNDDETECTOR_PATTERNHEADER Header; + LONGLONG ContosoDetectorResultData; + ULONGLONG KeywordStartTimestamp; + ULONGLONG KeywordStopTimestamp; + GUID EventId; +} CONTOSO_KEYWORDDETECTIONRESULT; + +DEFINE_GUID(CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2, +0x207f3d0c, 0x5c79, 0x496f, 0xa9, 0x4c, 0xd3, 0xd2, 0x93, 0x4d, 0xbf, 0xa9); + +// {A537F559-2D67-463B-B10E-BEB750A21F31} +DEFINE_GUID(CONTOSO_KEYWORD1, +0xa537f559, 0x2d67, 0x463b, 0xb1, 0xe, 0xbe, 0xb7, 0x50, 0xa2, 0x1f, 0x31); +// {655E417A-80A5-4A77-B3F1-512EAF67ABCF} +DEFINE_GUID(CONTOSO_KEYWORD2, +0x655e417a, 0x80a5, 0x4a77, 0xb3, 0xf1, 0x51, 0x2e, 0xaf, 0x67, 0xab, 0xcf); + +#define KEYWORDDETECTOR_POOLTAG 'KWS0' + +class CKeywordDetector +{ +public: + PAGED_CODE_SEG + CKeywordDetector(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS ResetDetector(_In_ GUID eventId); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + ULONGLONG GetStartTimestamp(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + ULONGLONG GetStopTimestamp(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS SetArmed(_In_ GUID eventId, _In_ BOOLEAN Arm); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID NotifyDetection(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS GetArmed(_In_ GUID eventId, _Out_ BOOLEAN *Arm); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID Run(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID Stop(); + + _IRQL_requires_min_(DISPATCH_LEVEL) + VOID DpcRoutine(_In_ LONGLONG PerformanceCounter, _In_ LONGLONG PerformanceFrequency); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS GetReadPacket(_In_ ULONG PacketCount, _In_ ULONG PacketSize, _Out_writes_(PacketSize) PVOID *Packets, _Out_ ULONG *PacketNumber, _Out_ ULONGLONG *PerformanceCount, _Out_ BOOLEAN *MoreData); + +private: + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID ResetFifo(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS ReadKeywordTimestampRegistry(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID StartBufferingStream(); + + // The Contoso keyword detector processes 10ms packets of 16KHz 16-bit PCM + // audio samples + static const int SamplesPerSecond = 16000; + static const int SamplesPerPacket = (10 * SamplesPerSecond / 1000); + + typedef struct + { + LIST_ENTRY ListEntry; + LONGLONG PacketNumber; + LONGLONG QpcWhenSampled; + UINT16 Samples[SamplesPerPacket]; + } PACKET_ENTRY; + + BOOLEAN m_streamRunning; + + BOOLEAN m_SoundDetectorArmed1; + BOOLEAN m_SoundDetectorArmed2; + LONGLONG m_SoundDetectorData1; + LONGLONG m_SoundDetectorData2; + + LONGLONG m_qpcStartCapture; + LONGLONG m_qpcFrequency; + LONGLONG m_nLastQueuedPacket; + + ULONGLONG m_ullKeywordStartTimestamp; + ULONGLONG m_ullKeywordStopTimestamp; + + KSPIN_LOCK PacketPoolSpinLock; + LIST_ENTRY PacketPoolHead; + PACKET_ENTRY PacketPool[1 * SamplesPerSecond / SamplesPerPacket]; // Enough storage for 1 second of audio data + + KSPIN_LOCK PacketFifoSpinLock; + LIST_ENTRY PacketFifoHead; + +}; + diff --git a/audio/Acx/Samples/Common/NewDelete.cpp b/audio/Acx/Samples/Common/NewDelete.cpp new file mode 100644 index 00000000..583d36c5 --- /dev/null +++ b/audio/Acx/Samples/Common/NewDelete.cpp @@ -0,0 +1,91 @@ +/*++ + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. +Module Name: + newdelete.cpp +Abstract: + Contains overloaded placement new and delete operators +Environment: + Kernel mode +--*/ + +#include "private.h" +#include "NewDelete.h" + +/***************************************************************************** + * ::new(POOL_FLAGS) + ***************************************************************************** + * New function for creating objects with a specified pool flags. + */ +PVOID operator new( + _In_ size_t size, + _In_ POOL_FLAGS poolFlags +) +{ + PVOID result = ExAllocatePool2(poolFlags, size, 'wNwS'); + + return result; +} + +/***************************************************************************** + * ::new(POOL_FLAGS, TAG) + ***************************************************************************** + * New function for creating objects with specified pool flags and allocation tag. + */ +PVOID operator new( + _In_ size_t size, + _In_ POOL_FLAGS poolFlags, + _In_ ULONG tag +) +{ + PVOID result = ExAllocatePool2(poolFlags, size, tag); + + return result; +} + +void __cdecl operator delete(PVOID buffer) +{ + if (buffer) + { + ExFreePool(buffer); + } +} + +void __cdecl operator delete(PVOID buffer, ULONG tag) +{ + if (buffer) + { + ExFreePoolWithTag(buffer, tag); + } +} + +void __cdecl operator delete(_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer, _In_ size_t cbSize) +{ + UNREFERENCED_PARAMETER(cbSize); + + if (buffer) + { + ExFreePool(buffer); + } +} + +void __cdecl operator delete[](_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer) +{ + if (buffer) + { + ExFreePool(buffer); + } +} + +void __cdecl operator delete[](_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer, _In_ size_t cbSize) +{ + UNREFERENCED_PARAMETER(cbSize); + + if (buffer) + { + ExFreePool(buffer); + } +} + diff --git a/audio/Acx/Samples/Common/NewDelete.h b/audio/Acx/Samples/Common/NewDelete.h new file mode 100644 index 00000000..fb660ff9 --- /dev/null +++ b/audio/Acx/Samples/Common/NewDelete.h @@ -0,0 +1,58 @@ +/*++ +Copyright (c) Microsoft Corporation. All rights reserved. + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. +Module Name: + NewDelete.h +Abstract: + Contains overloaded placement new and delete operators +Environment: + Kernel mode +--*/ + +/***************************************************************************** + * ::new(POOL_FLAGS) + ***************************************************************************** + * New function for creating objects with a specified pool flags. + */ +PVOID operator new( + _In_ size_t size, + _In_ POOL_FLAGS poolFlags +); + +/***************************************************************************** + * ::new(POOL_FLAGS, TAG) + ***************************************************************************** + * New function for creating objects with specified pool flags and allocation tag. + */ +PVOID operator new( + _In_ size_t size, + _In_ POOL_FLAGS poolFlags, + _In_ ULONG tag +); + +/***************************************************************************** + * ::delete() + ***************************************************************************** + * Delete function. + */ +void __cdecl operator delete(PVOID buffer); + +/***************************************************************************** + * ::delete() + ***************************************************************************** + * Delete function. + */ +void __cdecl operator delete(PVOID buffer, ULONG tag); + +void __cdecl operator delete[](PVOID pVoid, _In_ size_t cbSize); + +void __cdecl operator delete(_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer, _In_ size_t cbSize); + +void __cdecl operator delete[](_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer); + +void __cdecl operator delete[](_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer, _In_ size_t cbSize); + + diff --git a/audio/Acx/Samples/Common/Private.h b/audio/Acx/Samples/Common/Private.h new file mode 100644 index 00000000..da89ef78 --- /dev/null +++ b/audio/Acx/Samples/Common/Private.h @@ -0,0 +1,922 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + Private.h + +Abstract: + + Contains structure definitions and function prototypes private to + the Common library. + +Environment: + + Kernel mode + +--*/ + +#ifndef _PRIVATE_H_ +#define _PRIVATE_H_ + + +#include <wdm.h> +#include <windef.h> +#include "cpp_utils.h" +#include <mmsystem.h> +#include <ks.h> +#include <ksmedia.h> +#include "NewDelete.h" + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <initguid.h> +#include <ntddk.h> +#include <ntstrsafe.h> +#include <ntintsafe.h> +#include "Trace.h" + +#include <wdf.h> +#include <acx.h> + +#define PAGED_CODE_SEG __declspec(code_seg("PAGE")) +#define INIT_CODE_SEG __declspec(code_seg("INIT")) + +extern const GUID DSP_CIRCUIT_SPEAKER_GUID; +extern const GUID DSP_CIRCUIT_MICROPHONE_GUID; +extern const GUID DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID; +extern const GUID DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID; + +///////////////////////////////////////////////////////// +// +// Driver wide definitions +// + +// Copied from cfgmgr32.h +#if !defined(MAX_DEVICE_ID_LEN) +#define MAX_DEVICE_ID_LEN 200 +#endif + +// Number of millisecs per sec. +#define MS_PER_SEC 1000 + +// Number of hundred nanosecs per sec. +#define HNS_PER_SEC 10000000 + +#define REQUEST_TIMEOUT_SECONDS 5 + +#undef MIN +#undef MAX +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef SIZEOF_ARRAY +#define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0])) +#endif // !defined(SIZEOF_ARRAY) + +#ifndef RGB +#define RGB(r, g, b) (DWORD)(r << 16 | g << 8 | b) +#endif + +#define ALL_CHANNELS_ID UINT32_MAX +#define MAX_CHANNELS 2 + +// +// Ks support. +// +#define KSPROPERTY_TYPE_ALL KSPROPERTY_TYPE_BASICSUPPORT | \ + KSPROPERTY_TYPE_GET | \ + KSPROPERTY_TYPE_SET + +// +// Define struct to hold signal processing mode and corresponding +// list of supported formats. +// +typedef struct +{ + GUID SignalProcessingMode; + KSDATAFORMAT_WAVEFORMATEXTENSIBLE* FormatList; + ULONG FormatListCount; +} SUPPORTED_FORMATS_LIST; + +// +// Define CAPTURE device context. +// +typedef struct _CAPTURE_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} CAPTURE_DEVICE_CONTEXT, * PCAPTURE_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CAPTURE_DEVICE_CONTEXT, GetCaptureDeviceContext) + +// +// Define RENDER device context. +// +typedef struct _RENDER_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} RENDER_DEVICE_CONTEXT, * PRENDER_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(RENDER_DEVICE_CONTEXT, GetRenderDeviceContext) + +// +// Define circuit/stream element context. +// +typedef struct _ELEMENT_CONTEXT { + BOOLEAN Dummy; +} ELEMENT_CONTEXT, *PELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(ELEMENT_CONTEXT, GetElementContext) + +// +// Define circuit/stream element context. +// +typedef struct _MUTE_ELEMENT_CONTEXT { + BOOL MuteState[MAX_CHANNELS]; +} MUTE_ELEMENT_CONTEXT, *PMUTE_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MUTE_ELEMENT_CONTEXT, GetMuteElementContext) + +// +// Define circuit/stream element context. +// +typedef struct _VOLUME_ELEMENT_CONTEXT { + LONG VolumeLevel[MAX_CHANNELS]; +} VOLUME_ELEMENT_CONTEXT, *PVOLUME_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(VOLUME_ELEMENT_CONTEXT, GetVolumeElementContext) + +#define VOLUME_STEPPING 0x8000 +#define VOLUME_LEVEL_MAXIMUM 0x00000000 +#define VOLUME_LEVEL_MINIMUM (-96 * 0x10000) + +// +// Define mute timer context. +// +typedef struct _MUTE_TIMER_CONTEXT { + ACXELEMENT MuteElement; + ACXEVENT Event; +} MUTE_TIMER_CONTEXT, *PMUTE_TIMER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MUTE_TIMER_CONTEXT, GetMuteTimerContext) + +// +// Define format context. +// +typedef struct _FORMAT_CONTEXT { + BOOLEAN Dummy; +} FORMAT_CONTEXT, *PFORMAT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FORMAT_CONTEXT, GetFormatContext) + +// +// Define jack context. +// +typedef struct _JACK_CONTEXT { + ULONG Dummy; +} JACK_CONTEXT, * PJACK_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(JACK_CONTEXT, GetJackContext) + +// +// Define audio engine context. +// +typedef struct _ENGINE_CONTEXT { + ACXDATAFORMAT MixFormat; +} ENGINE_CONTEXT, * PENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(ENGINE_CONTEXT, GetEngineContext) + +// +// Define stream audio engine context. +// +typedef struct _STREAMAUDIOENGINE_CONTEXT { + BOOLEAN Dummy; +} STREAMAUDIOENGINE_CONTEXT, * PSTREAMAUDIOENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(STREAMAUDIOENGINE_CONTEXT, GetStreamAudioEngineContext) + +// +// Define keyword spotter context +// +typedef struct _KEYWORDSPOTTER_CONTEXT { + ACXPNPEVENT Event; + PVOID KeywordDetector; +} KEYWORDSPOTTER_CONTEXT, * PKEYWORDSPOTTER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(KEYWORDSPOTTER_CONTEXT, GetKeywordSpotterContext) + +// +// Define pnp event context. +// +typedef struct _PNPEVENT_CONTEXT { + BOOLEAN Dummy; +} PNPEVENT_CONTEXT, * PPNPEVENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PNPEVENT_CONTEXT, GetPnpEventContext) + +// +// Define peakmeter element context. +// +typedef struct _PEAKMETER_ELEMENT_CONTEXT { + LONG PeakMeterLevel[MAX_CHANNELS]; +} PEAKMETER_ELEMENT_CONTEXT, * PPEAKMETER_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PEAKMETER_ELEMENT_CONTEXT, GetPeakMeterElementContext) + +// +// Define DSP circuit's peakmeter element context. +// +typedef struct _DSP_PEAKMETER_ELEMENT_CONTEXT +{ + PVOID peakMeter; +} DSP_PEAKMETER_ELEMENT_CONTEXT, *PDSP_PEAKMETER_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_PEAKMETER_ELEMENT_CONTEXT, GetDspPeakMeterElementContext) + +// +// Define stream engine context. +// +typedef struct _STREAMENGINE_CONTEXT { + PVOID StreamEngine; +} STREAMENGINE_CONTEXT, * PSTREAMENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(STREAMENGINE_CONTEXT, GetStreamEngineContext) + +#define PEAKMETER_STEPPING_DELTA 0x1000 +#define PEAKMETER_MAXIMUM LONG_MAX +#define PEAKMETER_MINIMUM LONG_MIN + +///////////////////////////////////////////////////////////// +// Codec driver defintions +// + +typedef enum _CODEC_PIN_TYPE { + CodecPinTypeHost, + CodecPinTypeOffload, + CodecPinTypeLoopback, + CodecPinTypeKeyword, + CodecPinTypeDevice +} CODEC_PIN_TYPE, * PCODEC_PIN_TYPE; + +typedef struct _CODEC_PIN_CONTEXT { + CODEC_PIN_TYPE CodecPinType; +} CODEC_PIN_CONTEXT, * PCODEC_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_PIN_CONTEXT, GetCodecPinContext) + +/////////////////////////////////////////////////////////// +// Dsp driver definitions +// + +typedef enum { + CaptureHostPin = 0, + CaptureBridgePin = 1, + CaptureKWSPin = 2, + CapturePinCount = 3 +} CAPTURE_PIN_TYPE; + +typedef enum { + RenderHostPin = 0, + RenderOffloadPin = 1, + RenderLoopbackPin = 2, + RenderBridgePin = 3, + RenderPinCount = 4 +} RENDER_PIN_TYPE; + +typedef struct _DSP_PIN_CONTEXT { + ACXTARGETCIRCUIT TargetCircuit; + ULONG TargetPinId; + RENDER_PIN_TYPE RenderPinType; + CAPTURE_PIN_TYPE CapturePinType; + + // The stream bridge below will only be valid for the Capture circuit Bridge Pin + + // Host stream bridge will be used to ensure host stream creations are passed + // to the downlevel circuits. Since the HostStreamBridge won't have InModes set, + // the ACX framework will not add streams automatically. We will add streams for + // non KWS pin. + ACXSTREAMBRIDGE HostStreamBridge; +} DSP_PIN_CONTEXT, * PDSP_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_PIN_CONTEXT, GetDspPinContext) + +///////////////////////////////////////////////////////////// +// Multicircuit Dsp driver definitions +// + +// +// Circuit context for multi circuit dsp circuits. +// +typedef struct _DSP_CIRCUIT_CONTEXT +{ + ACXAUDIOENGINE AudioEngineElement; + ACXPEAKMETER PeakMeterElement; + PVOID peakMeter; + ACXKEYWORDSPOTTER KeywordSpotter; + BOOLEAN IsRenderCircuit; +} DSP_CIRCUIT_CONTEXT, *PDSP_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_CIRCUIT_CONTEXT, GetDspCircuitContext) + +typedef struct _DSP_ENGINE_CONTEXT +{ + ACXDATAFORMAT MixFormat; + BOOLEAN GFxEnabled; +} DSP_ENGINE_CONTEXT, *PDSP_ENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_ENGINE_CONTEXT, GetDspEngineContext) + +typedef struct _DSP_STREAMAUDIOENGINE_CONTEXT +{ + BOOLEAN LFxEnabled; +} DSP_STREAMAUDIOENGINE_CONTEXT, *PDSP_STREAMAUDIOENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_STREAMAUDIOENGINE_CONTEXT, GetDspStreamAudioEngineContext) + +///////////////////////////////////////////////////////// +// +// Codec Render (speaker) definitions +// + +// +// Define render circuit context. +// +typedef struct _CODEC_RENDER_CIRCUIT_CONTEXT { + ACXVOLUME VolumeElement; + ACXMUTE MuteElement; + ACXPEAKMETER PeakMeterElement; + ACXAUDIOENGINE AudioEngineElement; +} CODEC_RENDER_CIRCUIT_CONTEXT, * PCODEC_RENDER_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_RENDER_CIRCUIT_CONTEXT, GetRenderCircuitContext) + +typedef enum { + CodecRenderHostPin = 0, + CodecRenderBridgePin = 1, + CodecRenderPinCount = 2 +} CODEC_RENDER_PINS; + +typedef enum { + RenderVolumeIndex = 0, + RenderMuteIndex = 1, + RenderElementCount = 2 +} CODEC_RENDER_ELEMENTS; + +// Render callbacks. + +EVT_ACX_CIRCUIT_CREATE_STREAM CodecR_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CodecR_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CodecR_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET CodecR_EvtStreamSetRenderPacket; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CodecR_EvtStreamGetLoopbackPacket; +EVT_ACX_PIN_SET_DATAFORMAT CodecR_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecR_EvtPinContextCleanup; +EVT_ACX_MUTE_ASSIGN_STATE CodecR_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE CodecR_EvtMuteRetrieveState; +EVT_ACX_VOLUME_ASSIGN_LEVEL CodecR_EvtVolumeAssignLevel; +EVT_ACX_VOLUME_RETRIEVE_LEVEL CodecR_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL CodecR_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL CodecR_EvtRampedVolumeAssignLevel; +EVT_ACX_AUDIOENGINE_RETRIEVE_BUFFER_SIZE_LIMITS CodecR_EvtAcxAudioEngineRetrieveBufferSizeLimits; +EVT_ACX_AUDIOENGINE_RETRIEVE_EFFECTS_STATE CodecR_EvtAcxAudioEngineRetrieveEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_EFFECTS_STATE CodecR_EvtAcxAudioEngineAssignEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_ENGINE_FORMAT CodecR_EvtAcxAudioEngineAssignEngineDeviceFormat; +EVT_ACX_AUDIOENGINE_RETRIEVE_ENGINE_FORMAT CodecR_EvtAcxAudioEngineRetrieveEngineMixFormat; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_EFFECTS_STATE CodecR_EvtAcxStreamAudioEngineRetrieveEffectsState; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_EFFECTS_STATE CodecR_EvtAcxStreamAudioEngineAssignEffectsState; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_PRESENTATION_POSITION CodecR_EvtAcxStreamAudioEngineRetrievePresentationPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_CURRENT_WRITE_POSITION CodecR_EvtAcxStreamAudioEngineAssignCurrentWritePosition; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_LINEAR_BUFFER_POSITION CodecR_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LAST_BUFFER_POSITION CodecR_EvtAcxStreamAudioEngineAssignLastBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LOOPBACK_PROTECTION CodecR_EvtAcxStreamAudioEngineAssignLoopbackProtection; + +PAGED_CODE_SEG +NTSTATUS +CodecR_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// Codec Capture (microphone) definitions +// + +// +// Define capture circuit context. +// +typedef struct _CODEC_CAPTURE_CIRCUIT_CONTEXT { + ACXVOLUME BoostElement; + ACXVOLUME VolumeElement; + ACXKEYWORDSPOTTER KeywordSpotter; +} CODEC_CAPTURE_CIRCUIT_CONTEXT, * PCODEC_CAPTURE_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_CAPTURE_CIRCUIT_CONTEXT, GetCaptureCircuitContext) + +typedef enum { + CodecCaptureHostPin = 0, + CodecCaptureBridgePin = 1, + CodecCapturePinCount = 2 +} CODEC_CAPTURE_PINS; + +typedef enum { + CaptureVolumeIndex = 0, + CaptureElementCount = 1 +} CAPTURE_ELEMENTS; + +// Capture callbacks. + +EVT_ACX_CIRCUIT_CREATE_STREAM CodecC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CodecC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CodecC_EvtCircuitPowerDown; +EVT_ACX_VOLUME_ASSIGN_LEVEL CodecC_EvtVolumeAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL CodecC_EvtVolumeRetrieveLevelCallback; +EVT_ACX_VOLUME_ASSIGN_LEVEL CodecC_EvtBoostAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL CodecC_EvtBoostRetrieveLevelCallback; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CodecC_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT CodecC_EvtAcxPinSetDataFormat; +EVT_ACX_PIN_RETRIEVE_NAME CodecC_EvtAcxPinRetrieveName; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecC_EvtPinContextCleanup; +EVT_ACX_KEYWORDSPOTTER_RETRIEVE_ARM CodecC_EvtAcxKeywordSpotterRetrieveArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_ARM CodecC_EvtAcxKeywordSpotterAssignArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_PATTERNS CodecC_EvtAcxKeywordSpotterAssignPatterns; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_RESET CodecC_EvtAcxKeywordSpotterAssignReset; + +PAGED_CODE_SEG +NTSTATUS +CodecC_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// MicArray definitions +// + +// +// Define MicArray circuit context. +// +typedef struct _MICARRAY_CIRCUIT_CONTEXT { + ACXMUTE MuteElement; + ACXVOLUME VolumeElement; + ACXPEAKMETER PeakMeterElement; + ACXKEYWORDSPOTTER KeywordSpotter; +} MICARRAY_CIRCUIT_CONTEXT, * PMICARRAY_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MICARRAY_CIRCUIT_CONTEXT, GetMicArrayCircuitContext) + +typedef enum { + MicArrayVolumeIndex = 0, + MicArrayMuteIndex = 1, + MicArrayPeakmeterIndex = 2, + MicArrayKWSIndex = 3, + MicArrayElementCount = 4 +} MICARRAY_ELEMENTS; + +// MicArray callbacks. + +EVT_ACX_MUTE_ASSIGN_STATE MicArray_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE MicArray_EvtMuteRetrieveState; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL MicArray_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_CIRCUIT_CREATE_STREAM MicArray_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP MicArray_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN MicArray_EvtCircuitPowerDown; +EVT_ACX_VOLUME_ASSIGN_LEVEL MicArray_EvtVolumeAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL MicArray_EvtVolumeRetrieveLevelCallback; +EVT_ACX_STREAM_GET_CAPTURE_PACKET MicArray_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT MicArray_EvtAcxPinSetDataFormat; +EVT_ACX_PIN_RETRIEVE_NAME MicArray_EvtAcxPinRetrieveName; +EVT_WDF_DEVICE_CONTEXT_CLEANUP MicArray_EvtPinContextCleanup; +EVT_ACX_KEYWORDSPOTTER_RETRIEVE_ARM MicArray_EvtAcxKeywordSpotterRetrieveArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_ARM MicArray_EvtAcxKeywordSpotterAssignArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_PATTERNS MicArray_EvtAcxKeywordSpotterAssignPatterns; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_RESET MicArray_EvtAcxKeywordSpotterAssignReset; +EVT_ACX_PIN_CONNECTED MicArray_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED MicArray_EvtPinDisconnected; +EVT_WDF_DEVICE_CONTEXT_CLEANUP MicArray_EvtDeviceContextCleanup; +EVT_ACX_OBJECT_PROCESS_REQUEST MicArray_EvtPinProposeDataFormat2Callback; +EVT_ACX_OBJECT_PREPROCESS_REQUEST MicArray_EvtAudioCpuResourcesCallback; + +PAGED_CODE_SEG +NTSTATUS +MicArray_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ GUID MicCustomName, + _In_ UNICODE_STRING CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +PAGED_CODE_SEG +NTSTATUS +MicArray_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +///////////////////////////////////////////////////////// +// +// Microphone (external: headphone) definitions +// + +// +// Define MicrophoneHp circuit context. +// +typedef struct _MICROPHONEHP_CIRCUIT_CONTEXT { + ACXMUTE MuteElement; + ACXVOLUME VolumeElement; + ACXPEAKMETER PeakMeterElement; +} MICROPHONEHP_CIRCUIT_CONTEXT, * PMICROPHONEHP_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MICROPHONEHP_CIRCUIT_CONTEXT, GetMicrophoneHpCircuitContext) + +typedef enum { + MicrophoneHpVolumeIndex = 0, + MicrophoneHpMuteIndex = 1, + MicrophoneHpPeakmeterIndex = 2, + MicrophoneHpElementCount = 3 +} MICROPHONEHP_ELEMENTS; + +// MicrophoneHp callbacks. + +EVT_ACX_MUTE_ASSIGN_STATE MicrophoneHp_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE MicrophoneHp_EvtMuteRetrieveState; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL MicrophoneHp_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_CIRCUIT_CREATE_STREAM MicrophoneHp_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP MicrophoneHp_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN MicrophoneHp_EvtCircuitPowerDown; +EVT_ACX_VOLUME_ASSIGN_LEVEL MicrophoneHp_EvtVolumeAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL MicrophoneHp_EvtVolumeRetrieveLevelCallback; +EVT_ACX_STREAM_GET_CAPTURE_PACKET MicrophoneHp_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT MicrophoneHp_EvtAcxPinSetDataFormat; +EVT_ACX_PIN_RETRIEVE_NAME MicrophoneHp_EvtAcxPinRetrieveName; +EVT_WDF_DEVICE_CONTEXT_CLEANUP MicrophoneHp_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED MicrophoneHp_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED MicrophoneHp_EvtPinDisconnected; +EVT_ACX_OBJECT_PREPROCESS_REQUEST MicrophoneHp_EvtAudioCpuResourcesCallback; + +PAGED_CODE_SEG +NTSTATUS +MicrophoneHp_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ GUID MicCustomName, + _In_ UNICODE_STRING CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +PAGED_CODE_SEG +NTSTATUS +MicrophoneHp_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +///////////////////////////////////////////////////////// +// +// Speaker definitions +// + +// +// Define circuit context for Speaker and SpeakerHp. +// +typedef struct _DSP_RENDER_CIRCUIT_CONTEXT { + ACXPEAKMETER PeakMeterElement; + ACXAUDIOENGINE AudioEngineElement; + PVOID PeakMeter; +} DSP_RENDER_CIRCUIT_CONTEXT, * PDSP_RENDER_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_RENDER_CIRCUIT_CONTEXT, GetSpeakerCircuitContext) + +// Speaker callbacks. + +EVT_ACX_CIRCUIT_CREATE_STREAM Speaker_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP Speaker_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN Speaker_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET Speaker_EvtStreamSetRenderPacket; +EVT_ACX_STREAM_GET_CAPTURE_PACKET Speaker_EvtStreamGetLoopbackPacket; +EVT_ACX_PIN_SET_DATAFORMAT Speaker_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Speaker_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED Speaker_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED Speaker_EvtPinDisconnected; + +//Render Audio Engine callbacks. + +EVT_ACX_MUTE_ASSIGN_STATE Speaker_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE Speaker_EvtMuteRetrieveState; +EVT_ACX_VOLUME_RETRIEVE_LEVEL Speaker_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL Speaker_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL Speaker_EvtRampedVolumeAssignLevel; +EVT_ACX_AUDIOENGINE_RETRIEVE_BUFFER_SIZE_LIMITS Speaker_EvtAcxAudioEngineRetrieveBufferSizeLimits; +EVT_ACX_AUDIOENGINE_RETRIEVE_EFFECTS_STATE Speaker_EvtAcxAudioEngineRetrieveEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_EFFECTS_STATE Speaker_EvtAcxAudioEngineAssignEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_ENGINE_FORMAT Speaker_EvtAcxAudioEngineAssignEngineDeviceFormat; +EVT_ACX_AUDIOENGINE_RETRIEVE_ENGINE_FORMAT Speaker_EvtAcxAudioEngineRetrieveEngineMixFormat; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_EFFECTS_STATE Speaker_EvtAcxStreamAudioEngineRetrieveEffectsState; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_EFFECTS_STATE Speaker_EvtAcxStreamAudioEngineAssignEffectsState; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_PRESENTATION_POSITION Speaker_EvtAcxStreamAudioEngineRetrievePresentationPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_CURRENT_WRITE_POSITION Speaker_EvtAcxStreamAudioEngineAssignCurrentWritePosition; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_LINEAR_BUFFER_POSITION Speaker_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LAST_BUFFER_POSITION Speaker_EvtAcxStreamAudioEngineAssignLastBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LOOPBACK_PROTECTION Speaker_EvtAcxStreamAudioEngineAssignLoopbackProtection; + +PAGED_CODE_SEG +NTSTATUS +Speaker_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +Speaker_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName, + _In_ BOOLEAN IsHeadphones, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// HDMI definitions +// + +// +// Define HDMI circuit context. +// +typedef struct _DSP_HDMI_CIRCUIT_CONTEXT { + ACXVOLUME VolumeElement; + ACXMUTE MuteElement; + ACXPEAKMETER PeakmeterElement; +} DSP_HDMI_CIRCUIT_CONTEXT, * PDSP_HDMI_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_HDMI_CIRCUIT_CONTEXT, GetHDMICircuitContext) + +typedef enum { + HDMIVolumeIndex = 0, + HDMIMuteIndex = 1, + HDMIPeakmeterIndex = 2, + HDMIElementCount = 3 +} HDMI_ELEMENTS; + +typedef enum { + HDMIHostPin = 0, + HDMILoopbackPin = 1, + HDMIBridgePin = 2, + HDMIPinCount = 3 +} HDMI_PIN_TYPE; + +typedef struct _HDMI_PIN_CONTEXT { + ACXTARGETCIRCUIT TargetCircuit; + ULONG TargetPinId; + HDMI_PIN_TYPE PinType; + CAPTURE_PIN_TYPE CapturePinType; +} HDMI_PIN_CONTEXT, * PHDMI_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(HDMI_PIN_CONTEXT, GetHDMIPinContext) + +typedef struct _HDMI_STREAM_CONTEXT { + HDMI_PIN_TYPE PinType; + CAPTURE_PIN_TYPE CapturePinType; +} HDMI_STREAM_CONTEXT, * PHDMI_STREAM_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(HDMI_STREAM_CONTEXT, GetHDMIStreamContext) + +// HDMI callbacks. +EVT_ACX_CIRCUIT_CREATE_STREAM HDMI_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP HDMI_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN HDMI_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET HDMI_EvtStreamSetRenderPacket; +EVT_ACX_STREAM_GET_CAPTURE_PACKET HDMI_EvtStreamGetLoopbackPacket; +EVT_ACX_PIN_SET_DATAFORMAT HDMI_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP HDMI_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED HDMI_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED HDMI_EvtPinDisconnected; +EVT_WDF_DEVICE_CONTEXT_CLEANUP HDMI_EvtDeviceContextCleanup; +EVT_ACX_MUTE_ASSIGN_STATE HDMI_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE HDMI_EvtMuteRetrieveState; +EVT_ACX_VOLUME_ASSIGN_LEVEL HDMI_EvtRampedVolumeAssignLevel; +EVT_ACX_VOLUME_RETRIEVE_LEVEL HDMI_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL HDMI_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_OBJECT_PREPROCESS_REQUEST HDMI_EvtAudioCpuResourcesCallback; + +PAGED_CODE_SEG +NTSTATUS +HDMI_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +HDMI_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// Multi circuit codec Render (speaker) definitions +// + +// Uses the same circuit context, render pin, and render element definitions as Codec Render. + +// Render callbacks. +EVT_ACX_CIRCUIT_CREATE_STREAM RenderMC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP RenderMC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN RenderMC_EvtCircuitPowerDown; +EVT_ACX_PIN_SET_DATAFORMAT RenderMC_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP RenderMC_EvtPinContextCleanup; +EVT_ACX_MUTE_ASSIGN_STATE RenderMC_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE RenderMC_EvtMuteRetrieveState; +EVT_ACX_VOLUME_RETRIEVE_LEVEL RenderMC_EvtVolumeRetrieveLevel; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL RenderMC_EvtRampedVolumeAssignLevel; + +PAGED_CODE_SEG +NTSTATUS +RenderMC_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName, + _In_ const UNICODE_STRING * Uri, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// Multi circuit codec Capture (microphone) definitions +// + +// Uses the same circuit context, render pin, and render element definitions as Codec Capture. + +// Capture callbacks. +EVT_ACX_CIRCUIT_CREATE_STREAM CaptureMC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CaptureMC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CaptureMC_EvtCircuitPowerDown; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CaptureMC_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT CaptureMC_EvtAcxPinSetDataFormat; +EVT_ACX_PIN_RETRIEVE_NAME CaptureMC_EvtAcxPinRetrieveName; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CaptureMC_EvtPinContextCleanup; + +PAGED_CODE_SEG +NTSTATUS +CaptureMC_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName, + _In_ const UNICODE_STRING * Uri, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// Multi circuit dsp Render (speaker) definitions +// + +// Uses the same circuit context, render pin, and render element definitions as Codec Render. + +// Render callbacks. +EVT_ACX_CIRCUIT_COMPOSITE_CIRCUIT_INITIALIZE RenderMCDsp_EvtCircuitCompositeCircuitInitialize; +EVT_ACX_CIRCUIT_COMPOSITE_INITIALIZE RenderMCDsp_EvtCircuitCompositeInitialize; +EVT_WDF_DEVICE_CONTEXT_CLEANUP RenderMCDsp_EvtCircuitContextCleanup; +EVT_WDF_DEVICE_PREPARE_HARDWARE RenderMCDsp_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE RenderMCDsp_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT RenderMCDsp_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP RenderMCDsp_EvtDeviceContextCleanup; +EVT_ACX_CIRCUIT_CREATE_STREAM RenderMCDsp_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP RenderMCDsp_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN RenderMCDsp_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET RenderMCDsp_EvtStreamSetRenderPacket; +EVT_ACX_PIN_SET_DATAFORMAT RenderMCDsp_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP RenderMCDsp_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED RenderMCDsp_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED RenderMCDsp_EvtPinDisconnected; + +// Render Audio Engine +EVT_ACX_MUTE_ASSIGN_STATE DspR_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE DspR_EvtMuteRetrieveState; +EVT_ACX_VOLUME_RETRIEVE_LEVEL DspR_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL DspR_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL DspR_EvtRampedVolumeAssignLevel; +EVT_ACX_AUDIOENGINE_RETRIEVE_BUFFER_SIZE_LIMITS DspR_EvtAcxAudioEngineRetrieveBufferSizeLimits; +EVT_ACX_AUDIOENGINE_RETRIEVE_EFFECTS_STATE DspR_EvtAcxAudioEngineRetrieveEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_EFFECTS_STATE DspR_EvtAcxAudioEngineAssignEffectsState; +EVT_ACX_AUDIOENGINE_RETRIEVE_ENGINE_FORMAT DspR_EvtAcxAudioEngineRetrieveEngineMixFormat; +EVT_ACX_AUDIOENGINE_ASSIGN_ENGINE_FORMAT DspR_EvtAcxAudioEngineAssignEngineDeviceFormat; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_EFFECTS_STATE DspR_EvtAcxStreamAudioEngineRetrieveEffectsState; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_EFFECTS_STATE DspR_EvtAcxStreamAudioEngineAssignEffectsState; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_PRESENTATION_POSITION DspR_EvtAcxStreamAudioEngineRetrievePresentationPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_CURRENT_WRITE_POSITION DspR_EvtAcxStreamAudioEngineAssignCurrentWritePosition; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_LINEAR_BUFFER_POSITION DspR_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LAST_BUFFER_POSITION DspR_EvtAcxStreamAudioEngineAssignLastBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LOOPBACK_PROTECTION DspR_EvtAcxStreamAudioEngineAssignLoopbackProtection; + +PAGED_CODE_SEG +NTSTATUS +RenderMCDsp_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS CreateRenderCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +); + +PAGED_CODE_SEG +NTSTATUS CreateRenderMCDspPin( + _In_ ACX_PIN_TYPE PinType, + _In_ ACXCIRCUIT Circuit, + _In_ ACX_PIN_COMMUNICATION Communication, + _In_ const GUID* Category, + _In_ ACX_PIN_CALLBACKS* PinCallbacks, + _In_ bool Mic, + _Out_ ACXPIN* Pin +); + +PAGED_CODE_SEG +NTSTATUS CreateAudioEngine( + _In_ ACXCIRCUIT Circuit, + _In_reads_(PinCount) ACXPIN* Pins, + _In_ ULONG PinCount, + _Out_ ACXAUDIOENGINE* AudioEngineElement +); + +///////////////////////////////////////////////////////// +// +// Multi circuit dsp Capture (microphone) definitions +// + +// Uses the same circuit context, capture pin and capture element definitions as Codec Capture. + +// Capture callbacks. +EVT_ACX_CIRCUIT_COMPOSITE_CIRCUIT_INITIALIZE CaptureMCDsp_EvtCircuitCompositeCircuitInitialize; +EVT_ACX_CIRCUIT_COMPOSITE_INITIALIZE CaptureMCDsp_EvtCircuitCompositeInitialize; +EVT_WDF_DEVICE_PREPARE_HARDWARE CaptureMCDsp_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE CaptureMCDsp_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT CaptureMCDsp_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CaptureMCDsp_EvtDeviceContextCleanup; +EVT_ACX_CIRCUIT_CREATE_STREAM CaptureMCDsp_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CaptureMCDsp_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CaptureMCDsp_EvtCircuitPowerDown; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CaptureMCDsp_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT CaptureMCDsp_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CaptureMCDsp_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED CaptureMCDsp_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED CaptureMCDsp_EvtPinDisconnected; + +PAGED_CODE_SEG +NTSTATUS +CaptureMCDsp_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS CreateCaptureCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +); + +PAGED_CODE_SEG +NTSTATUS CreateCaptureMCDspPin( + _In_ ACX_PIN_TYPE PinType, + _In_ ACXCIRCUIT Circuit, + _In_ ACX_PIN_COMMUNICATION Communication, + _In_ const GUID* Category, + _In_ ACX_PIN_CALLBACKS* PinCallbacks, + _In_ bool Mic, + _Out_ ACXPIN* Pin +); + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + + + +#endif // _PRIVATE_H_ diff --git a/audio/Acx/Samples/Common/RenderCircuit.cpp b/audio/Acx/Samples/Common/RenderCircuit.cpp new file mode 100644 index 00000000..2f5abd13 --- /dev/null +++ b/audio/Acx/Samples/Common/RenderCircuit.cpp @@ -0,0 +1,807 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + RenderCircuit.cpp + +Abstract: + + Render Circuit. This file contains routines to create and handle + render circuit with no offload. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "AudioFormats.h" +#include "streamengine.h" +#include "cpp_utils.h" +#include "circuithelper.h" + +#ifndef __INTELLISENSE__ +#include "renderCircuit.tmh" +#endif + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtAcxPinSetDataFormat( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat +) +/*++ + +Routine Description: + + This ACX pin callback sets the device/mixed format. + +Return Value: + + NTSTATUS + +--*/ +{ + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + PAGED_CODE(); + + // NOTE: update device/mixed format here. + + return STATUS_NOT_SUPPORTED; +} + +/////////////////////////////////////////////////////////// +// +// For more information on mute element see: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/ksnodetype-mute +// +_Use_decl_annotations_ +NTSTATUS +NTAPI +CodecR_EvtMuteAssignState( + _In_ ACXMUTE Mute, + _In_ ULONG Channel, + _In_ ULONG State +) +{ + PMUTE_ELEMENT_CONTEXT muteCtx; + ULONG i; + + PAGED_CODE(); + + muteCtx = GetMuteElementContext(Mute); + ASSERT(muteCtx); + + // + // Use first channel for all channels setting. + // + if (Channel != ALL_CHANNELS_ID) + { + muteCtx->MuteState[Channel] = State; + } + else + { + for (i = 0; i < MAX_CHANNELS; ++i) + { + muteCtx->MuteState[i] = State; + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +NTAPI +CodecR_EvtMuteRetrieveState( + _In_ ACXMUTE Mute, + _In_ ULONG Channel, + _Out_ ULONG * State +) +{ + PMUTE_ELEMENT_CONTEXT muteCtx; + + PAGED_CODE(); + + muteCtx = GetMuteElementContext(Mute); + ASSERT(muteCtx); + + // + // Use first channel for all channels setting. + // + if (Channel != ALL_CHANNELS_ID) + { + *State = muteCtx->MuteState[Channel]; + } + else + { + *State = muteCtx->MuteState[0]; + } + + return STATUS_SUCCESS; +} + +/////////////////////////////////////////////////////////// +// +// For more information on volume element see: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/ksnodetype-volume +// +_Use_decl_annotations_ +NTSTATUS +NTAPI +CodecR_EvtRampedVolumeAssignLevel( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _In_ LONG VolumeLevel, + _In_ ACX_VOLUME_CURVE_TYPE CurveType, + _In_ ULONGLONG CurveDuration +) +{ + PVOLUME_ELEMENT_CONTEXT volumeCtx; + ULONG i; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(CurveType); + UNREFERENCED_PARAMETER(CurveDuration); + + volumeCtx = GetVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + volumeCtx->VolumeLevel[Channel] = VolumeLevel; + } + else + { + for (i = 0; i < MAX_CHANNELS; ++i) + { + volumeCtx->VolumeLevel[i] = VolumeLevel; + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +NTAPI +CodecR_EvtVolumeRetrieveLevel( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _Out_ LONG * VolumeLevel +) +{ + PVOLUME_ELEMENT_CONTEXT volumeCtx; + + PAGED_CODE(); + + volumeCtx = GetVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + *VolumeLevel = volumeCtx->VolumeLevel[Channel]; + } + else + { + *VolumeLevel = volumeCtx->VolumeLevel[0]; + } + + return STATUS_SUCCESS; +} + +VOID +CodecR_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin +) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + nullptr + +--*/ +{ + + UNREFERENCED_PARAMETER(WdfPin); +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName +) +/*++ + +Routine Description: + + Creates the static render circuit (pictured below) and + adds it to the device context. This is called when a + new device is detected and the AddDevice call is made + by the pnp manager. + + *************************************************************************** + * Render Circuit * + * * + * +--------------------------------------------+ * + * | | * + * | +-------------+ +-------------+ | * + * Host ------>| | Volume Node | | Mute Node | |---> Bridge * + * Pin | +-------------+ +-------------+ | Pin * + * | | * + * +--------------------------------------------+ * + * * + *************************************************************************** + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + PRENDER_DEVICE_CONTEXT renderDevCtx; + ACXCIRCUIT renderCircuit = nullptr; + WDF_OBJECT_ATTRIBUTES attributes; + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // Alloc audio context to current device. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RENDER_DEVICE_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(WdfObjectAllocateContext(Device, &attributes, (PVOID*)&renderDevCtx)); + ASSERT(renderDevCtx); + + // + // Create a render circuit associated with this child device. + // + RETURN_NTSTATUS_IF_FAILED(CodecR_CreateRenderCircuit(Device, ComponentGuid, CircuitName, &renderCircuit)); + + devCtx->Render = renderCircuit; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Render_AllocateSupportedFormats( + _In_ WDFDEVICE Device, + _In_reads_bytes_(CodecRenderPinCount) ACXPIN Pin[], + _In_ ACXCIRCUIT Circuit, + _In_ size_t CodecRenderPinCount +) +{ + UNREFERENCED_PARAMETER(CodecRenderPinCount); + + NTSTATUS status = STATUS_SUCCESS; + ACXDATAFORMAT formatPcm44100c2; + ACXDATAFORMAT formatPcm48000c2; + ACXDATAFORMATLIST formatList; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + /////////////////////////////////////////////////////////// + // + // Allocate the formats this circuit supports. + // + + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm44100c2, Circuit, Device, &formatPcm44100c2)); + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm48000c2, Circuit, Device, &formatPcm48000c2)); + + /////////////////////////////////////////////////////////// + // + // Define supported formats for the host pin. + // + + // + // The raw processing mode list is associated with each single circuit + // by ACX. The driver uses this DDI to retrieve the built-in raw + // data-format list. + // + RETURN_NTSTATUS_IF_TRUE(CodecRenderHostPin >= CodecRenderPinCount, STATUS_INVALID_PARAMETER); + formatList = AcxPinGetRawDataFormatList(Pin[CodecRenderHostPin]); + RETURN_NTSTATUS_IF_TRUE(formatList == nullptr, STATUS_INSUFFICIENT_RESOURCES); + + // + // The driver uses this DDI to add data formats to the raw + // processing mode list associated with the current circuit. + // + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm48000c2)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName, + _Out_ ACXCIRCUIT* Circuit +) +/*++ + +Routine Description: + + This routine builds the CODEC render circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + ACXCIRCUIT circuit; + CODEC_RENDER_CIRCUIT_CONTEXT* circuitCtx; + ACXPIN pin[CodecRenderPinCount]; + + PAGED_CODE(); + + // + // Init output value. + // + *Circuit = nullptr; + + /////////////////////////////////////////////////////////// + // + // Create a circuit. + // + { + PACXCIRCUIT_INIT circuitInit = nullptr; + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + + // + // The driver uses this DDI to allocate an ACXCIRCUIT_INIT + // structure. This opaque structure is used when creating + // a standalone audio circuit representing an audio device. + // + circuitInit = AcxCircuitInitAllocate(Device); + + // + // The driver uses this DDI to free the allocated + // ACXCIRCUIT_INIT structure when an error is detected. + // Normally the structures is deleted/cleared by ACX when + // an ACX circuit is created successfully. + // + auto circuitInitScope = scope_exit([&circuitInit]() { + if (circuitInit) { + AcxCircuitInitFree(circuitInit); + } + }); + + // + // The driver uses this DDI to specify the Component ID + // of the ACX circuit. This ID is a guid that uniquely + // identifies the circuit instance (vendor specific). + // + AcxCircuitInitSetComponentId(circuitInit, ComponentGuid); + + // + // The driver uses this DDI to specify the circuit name. + // For standalone circuits, this is the audio device name + // which is used by clients to open handles to the audio devices. + // + (VOID)AcxCircuitInitAssignName(circuitInit, CircuitName); + + // + // The driver uses this DDI to specify the circuit type. The + // circuit type can be AcxCircuitTypeRender, AcxCircuitTypeCapture, + // AcxCircuitTypeOther, or AcxCircuitTypeMaximum (for validation). + // + AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeRender); + + // + // The driver uses this DDI to assign its (if any) power callbacks. + // + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = CodecR_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = CodecR_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(circuitInit, &powerCallbacks); + + // + // The driver uses this DDI to register for a stream-create callback. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback(circuitInit, CodecR_EvtCircuitCreateStream)); + + // + // The driver uses this DDI to create a new ACX circuit. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_CIRCUIT_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit)); + + circuitInitScope.release(); + + circuitCtx = GetRenderCircuitContext(circuit); + ASSERT(circuitCtx); + } + + // + // Post circuit creation initialization. + // + + /////////////////////////////////////////////////////////// + // + // Create mute and volume elements. + // + { + ACXELEMENT elements[RenderElementCount] = { 0 }; + + // + // The driver uses this DDI to assign its volume element callbacks. + // + ACX_VOLUME_CALLBACKS volumeCallbacks; + ACX_VOLUME_CALLBACKS_INIT(&volumeCallbacks); + volumeCallbacks.EvtAcxRampedVolumeAssignLevel = CodecR_EvtRampedVolumeAssignLevel; + volumeCallbacks.EvtAcxVolumeRetrieveLevel = CodecR_EvtVolumeRetrieveLevel; + + // + // Create Volume element + // + ACX_VOLUME_CONFIG volumeCfg; + ACX_VOLUME_CONFIG_INIT(&volumeCfg); + volumeCfg.ChannelsCount = MAX_CHANNELS; + volumeCfg.Minimum = VOLUME_LEVEL_MINIMUM; + volumeCfg.Maximum = VOLUME_LEVEL_MAXIMUM; + volumeCfg.SteppingDelta = VOLUME_STEPPING; + volumeCfg.Name = &KSAUDFNAME_VOLUME_CONTROL; + volumeCfg.Callbacks = &volumeCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, VOLUME_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxVolumeCreate(circuit, &attributes, &volumeCfg, (ACXVOLUME*)&elements[RenderVolumeIndex])); + + // + // The driver uses this DDI to assign its mute element callbacks. + // + ACX_MUTE_CALLBACKS muteCallbacks; + ACX_MUTE_CALLBACKS_INIT(&muteCallbacks); + muteCallbacks.EvtAcxMuteAssignState = CodecR_EvtMuteAssignState; + muteCallbacks.EvtAcxMuteRetrieveState = CodecR_EvtMuteRetrieveState; + + // + // Create Mute element + // + ACX_MUTE_CONFIG muteCfg; + ACX_MUTE_CONFIG_INIT(&muteCfg); + muteCfg.ChannelsCount = MAX_CHANNELS; + muteCfg.Name = &KSAUDFNAME_WAVE_MUTE; + muteCfg.Callbacks = &muteCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, MUTE_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxMuteCreate(circuit, &attributes, &muteCfg, (ACXMUTE*)&elements[RenderMuteIndex])); + + // + // Saving the volume and mute elements in the circuit context. + // + circuitCtx->VolumeElement = (ACXVOLUME)elements[RenderVolumeIndex]; + circuitCtx->MuteElement = (ACXMUTE)elements[RenderMuteIndex]; + + // + // The driver uses this DDI post circuit creation to add ACXELEMENTs. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + } + + /////////////////////////////////////////////////////////// + // + // Create the pins for the circuit. + // + { + ACX_PIN_CONFIG pinCfg; + CODEC_PIN_CONTEXT* pinCtx; + ACX_PIN_CALLBACKS pinCallbacks; + + /////////////////////////////////////////////////////////// + // + // Create Render Pin. + // + + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = CodecR_EvtAcxPinSetDataFormat; + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSink; + pinCfg.Communication = AcxPinCommunicationSink; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + // + // The driver uses this DDI to create one or more pins on the circuits. + // + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin[CodecRenderHostPin])); + + ASSERT(pin[CodecRenderHostPin] != nullptr); + pinCtx = GetCodecPinContext(pin[CodecRenderHostPin]); + ASSERT(pinCtx); + pinCtx->CodecPinType = CodecPinTypeHost; + + /////////////////////////////////////////////////////////// + // + // Create Device Bridge Pin. + // + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSource; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSNODETYPE_SPEAKER; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + // + // The driver uses this DDI to create one or more pins on the circuits. + // + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin[CodecRenderBridgePin])); + + ASSERT(pin[CodecRenderBridgePin] != nullptr); + pinCtx = GetCodecPinContext(pin[CodecRenderBridgePin]); + ASSERT(pinCtx); + pinCtx->CodecPinType = CodecPinTypeDevice; + } + + /////////////////////////////////////////////////////////// + // + // Add audio jack to bridge pin. + // For more information on audio jack see: https://docs.microsoft.com/en-us/windows/win32/api/devicetopology/ns-devicetopology-ksjack_description + // + { + ACX_JACK_CONFIG jackCfg; + ACXJACK jack; + PJACK_CONTEXT jackCtx; + + ACX_JACK_CONFIG_INIT(&jackCfg); + jackCfg.Description.ChannelMapping = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; + jackCfg.Description.Color = RGB(0, 0, 0); + jackCfg.Description.ConnectionType = AcxConnTypeAtapiInternal; + jackCfg.Description.GeoLocation = AcxGeoLocFront; + jackCfg.Description.GenLocation = AcxGenLocPrimaryBox; + jackCfg.Description.PortConnection = AcxPortConnIntegratedDevice; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, JACK_CONTEXT); + attributes.ParentObject = pin[CodecRenderBridgePin]; + + RETURN_NTSTATUS_IF_FAILED(AcxJackCreate(pin[CodecRenderBridgePin], &attributes, &jackCfg, &jack)); + + ASSERT(jack != nullptr); + + jackCtx = GetJackContext(jack); + ASSERT(jackCtx); + jackCtx->Dummy = 0; + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddJacks(pin[CodecRenderBridgePin], &jack, 1)); + } + + RETURN_NTSTATUS_IF_FAILED(Render_AllocateSupportedFormats(Device, pin, circuit, CodecRenderPinCount)); + + /////////////////////////////////////////////////////////// + // + // The driver uses this DDI post circuit creation to add ACXPINs. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, pin, CodecRenderPinCount)); + + // + // Set output value. + // + *Circuit = circuit; + + // + // Done. + // + status = STATUS_SUCCESS; + + return status; +} + +_Use_decl_annotations_ +NTSTATUS +CodecR_EvtCircuitPowerUp( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE PreviousState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(PreviousState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +CodecR_EvtCircuitPowerDown( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE TargetState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(TargetState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID* SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine creates a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + PRENDER_DEVICE_CONTEXT devCtx; + WDF_OBJECT_ATTRIBUTES attributes; + ACXSTREAM stream; + STREAMENGINE_CONTEXT * streamCtx; + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_RT_STREAM_CALLBACKS rtCallbacks; + CRenderStreamEngine* renderStreamEngine = nullptr; + CODEC_PIN_TYPE codecPinType; + PCODEC_PIN_CONTEXT pinCtx; + ACX_PIN_TYPE pinType; + CODEC_RENDER_CIRCUIT_CONTEXT* circuitCtx; + + auto streamEngineScope = scope_exit([&renderStreamEngine]() { + + delete renderStreamEngine; + + }); + + PAGED_CODE(); + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)); + + ASSERT(Circuit != nullptr); + circuitCtx = GetRenderCircuitContext(Circuit); + ASSERT(circuitCtx); + + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != nullptr); + UNREFERENCED_PARAMETER(devCtx); + + pinCtx = GetCodecPinContext(Pin); + codecPinType = pinCtx->CodecPinType; + + pinType = AcxPinGetType(Pin); + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = EvtStreamPause; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Init RT streaming callbacks. + // + ACX_RT_STREAM_CALLBACKS_INIT(&rtCallbacks); + rtCallbacks.EvtAcxStreamGetHwLatency = EvtStreamGetHwLatency; + rtCallbacks.EvtAcxStreamAllocateRtPackets = EvtStreamAllocateRtPackets; + rtCallbacks.EvtAcxStreamFreeRtPackets = EvtStreamFreeRtPackets; + rtCallbacks.EvtAcxStreamSetRenderPacket = CodecR_EvtStreamSetRenderPacket; + rtCallbacks.EvtAcxStreamGetCurrentPacket = EvtStreamGetCurrentPacket; + rtCallbacks.EvtAcxStreamGetPresentationPosition = EvtStreamGetPresentationPosition; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRtStreamCallbacks(StreamInit, &rtCallbacks)); + + // + // Buffer notifications are supported. + // + AcxStreamInitSetAcxRtStreamSupportsNotifications(StreamInit); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, STREAMENGINE_CONTEXT); + attributes.EvtDestroyCallback = EvtStreamDestroy; + RETURN_NTSTATUS_IF_FAILED(AcxRtStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + // + // Create the virtual streaming engine which will control + // streaming logic for the render circuit. + // + renderStreamEngine = new (POOL_FLAG_NON_PAGED, DeviceDriverTag) CRenderStreamEngine(stream, StreamFormat, FALSE, NULL); + RETURN_NTSTATUS_IF_TRUE(renderStreamEngine == nullptr, STATUS_INSUFFICIENT_RESOURCES); + + streamCtx = GetStreamEngineContext(stream); + ASSERT(streamCtx); + streamCtx->StreamEngine = (PVOID)renderStreamEngine; + + renderStreamEngine = nullptr; + + // + // Done. + // + status = STATUS_SUCCESS; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtStreamSetRenderPacket( + _In_ ACXSTREAM Stream, + _In_ ULONG Packet, + _In_ ULONG Flags, + _In_ ULONG EosPacketLength +) +{ + PSTREAMENGINE_CONTEXT ctx; + CRenderStreamEngine* streamEngine = nullptr; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = static_cast<CRenderStreamEngine*>(ctx->StreamEngine); + + return streamEngine->SetRenderPacket(Packet, Flags, EosPacketLength); +} + diff --git a/audio/Acx/Samples/Common/SamplesCommon.vcxproj b/audio/Acx/Samples/Common/SamplesCommon.vcxproj new file mode 100644 index 00000000..0932d59a --- /dev/null +++ b/audio/Acx/Samples/Common/SamplesCommon.vcxproj @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|ARM64"> + <Configuration>Debug</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM64"> + <Configuration>Release</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{6A946D59-6690-4ED0-A77D-7D4C3D4B3241}</ProjectGuid> + <TemplateGuid>{497e31cb-056b-4f31-abb8-447fd55ee5a5}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <RootNamespace>SamplesCommon</RootNamespace> + <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace_macros.h</WppScanConfigurationData> + <WppKernelMode>true</WppKernelMode> + <AdditionalIncludeDirectories>$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\1.1;..\inc;..\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace_macros.h</WppScanConfigurationData> + <WppKernelMode>true</WppKernelMode> + <AdditionalIncludeDirectories>$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\1.1;..\inc;..\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace_macros.h</WppScanConfigurationData> + <WppKernelMode>true</WppKernelMode> + <AdditionalIncludeDirectories>$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\1.1;..\inc;..\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <ClCompile> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace_macros.h</WppScanConfigurationData> + <WppKernelMode>true</WppKernelMode> + <AdditionalIncludeDirectories>$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\1.1;..\inc;..\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="NewDelete.h" /> + <ClInclude Include="CircuitHelper.h" /> + <ClInclude Include="KeywordDetector.h" /> + <ClInclude Include="Private.h" /> + <ClInclude Include="Public.h" /> + <ClInclude Include="SaveData.h" /> + <ClInclude Include="SimPeakMeter.h" /> + <ClInclude Include="StreamEngine.h" /> + <ClInclude Include="ToneGenerator.h" /> + <ClInclude Include="Trace.h" /> + <ClInclude Include="Trace_macros.h" /> + <ClInclude Include="WaveReader.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="NewDelete.cpp" /> + <ClCompile Include="captureCircuit.cpp" /> + <ClCompile Include="CircuitHelper.cpp" /> + <ClCompile Include="KeywordDetector.cpp" /> + <ClCompile Include="renderCircuit.cpp" /> + <ClCompile Include="SaveData.cpp" /> + <ClCompile Include="SimPeakMeter.cpp" /> + <ClCompile Include="StreamEngine.cpp" /> + <ClCompile Include="ToneGenerator.cpp" /> + <ClCompile Include="WaveReader.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/audio/Acx/Samples/Common/SaveData.cpp b/audio/Acx/Samples/Common/SaveData.cpp new file mode 100644 index 00000000..72e98850 --- /dev/null +++ b/audio/Acx/Samples/Common/SaveData.cpp @@ -0,0 +1,1103 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + SaveData.cpp + +Abstract: + + Implementation of data saving class for ACX driver samples. + + To save the playback data to disk, this class maintains a circular data + buffer, associated frame structures and worker items to save frames to + disk. + Each frame structure represents a portion of buffer. When that portion + of frame is full, a workitem is scheduled to save it to disk. + + + +--*/ +#pragma warning (disable : 4127) +#pragma warning (disable : 26165) + + +#include "private.h" +#include <devguid.h> +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "savedata.h" +#include <ntstrsafe.h> // This is for using RtlStringCbPrintf + +#define SAVEDATA_POOLTAG 'TDVS' +#define SAVEDATA_POOLTAG1 '1DVS' +#define SAVEDATA_POOLTAG2 '2DVS' +#define SAVEDATA_POOLTAG3 '3DVS' +#define SAVEDATA_POOLTAG4 '4DVS' +#define SAVEDATA_POOLTAG5 '5DVS' +#define SAVEDATA_POOLTAG6 '6DVS' +#define SAVEDATA_POOLTAG7 '7DVS' + +//============================================================================= +// Defines +//============================================================================= +#define RIFF_TAG 0x46464952; +#define WAVE_TAG 0x45564157; +#define FMT__TAG 0x20746D66; +#define DATA_TAG 0x61746164; + +#define DEFAULT_FRAME_COUNT 4 +#define DEFAULT_FRAME_SIZE PAGE_SIZE * 4 +#define DEFAULT_BUFFER_SIZE DEFAULT_FRAME_SIZE * DEFAULT_FRAME_COUNT + +#define DEFAULT_FILE_FOLDER1 L"\\DriverData\\Audio_Samples" +#define DEFAULT_FILE_FOLDER2 L"\\DriverData\\Audio_Samples\\AudioCodec" +#define DEFAULT_FILE_NAME L"\\DriverData\\Audio_Samples\\AudioCodec\\STREAM" +#define OFFLOAD_FILE_NAME L"OFFLOAD" +#define HOST_FILE_NAME L"HOST" + +#define MAX_WORKER_ITEM_COUNT 15 + + +PSAVEWORKER_PARAM CSaveData::m_pWorkItems = NULL; +PDEVICE_OBJECT CSaveData::m_pDeviceObject = NULL; + +//============================================================================= +// Statics +//============================================================================= +ULONG CSaveData::m_ulStreamId = 0; +ULONG CSaveData::m_ulOffloadStreamId = 0; + +//============================================================================= +// CSaveData +//============================================================================= + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::CSaveData() +: m_pDataBuffer(NULL), + m_FileHandle(NULL), + m_ulFrameCount(DEFAULT_FRAME_COUNT), + m_ulBufferSize(DEFAULT_BUFFER_SIZE), + m_ulFrameSize(DEFAULT_FRAME_SIZE), + m_ulBufferOffset(0), + m_ulFrameIndex(0), + m_fFrameUsed(NULL), + m_waveFormat(NULL), + m_pFilePtr(NULL), + m_fWriteDisabled(FALSE), + m_bInitialized(FALSE) +{ + PAGED_CODE(); + + m_FileHeader.dwRiff = RIFF_TAG; + m_FileHeader.dwFileSize = 0; + m_FileHeader.dwWave = WAVE_TAG; + m_FileHeader.dwFormat = FMT__TAG; + m_FileHeader.dwFormatLength = sizeof(WAVEFORMATEX); + + m_DataHeader.dwData = DATA_TAG; + m_DataHeader.dwDataLength = 0; + + RtlZeroMemory(&m_objectAttributes, sizeof(m_objectAttributes)); +} // CSaveData + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::~CSaveData() +{ + PAGED_CODE(); + Cleanup(); +} // CSaveData + +void +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::Cleanup +( + void +) +{ + PAGED_CODE(); + + // Update the wave header in data file with real file size. + // + if(m_pFilePtr) + { + // RIFF header, whose size is the whole file size minus RIFF header. + m_FileHeader.dwFileSize = + (DWORD)m_pFilePtr->QuadPart - 2 * sizeof(DWORD); + // The data length is the size of all the audio that was written. + // It gets calculated by taking: + m_DataHeader.dwDataLength = (DWORD)m_pFilePtr->QuadPart - // the whole file size, + sizeof(m_FileHeader) - // minus the file header, + m_FileHeader.dwFormatLength - // minus the format, + sizeof(m_DataHeader); // minus the data header itself. + + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + if (NT_SUCCESS(FileOpen(FALSE))) + { + FileWriteHeader(); + + FileClose(); + } + + KeReleaseMutex(&m_FileSync, FALSE); + } + + m_FileHeader.dwRiff = RIFF_TAG; + m_FileHeader.dwFileSize = 0; + m_FileHeader.dwWave = WAVE_TAG; + m_FileHeader.dwFormat = FMT__TAG; + m_FileHeader.dwFormatLength = sizeof(WAVEFORMATEX); + + m_DataHeader.dwData = DATA_TAG; + m_DataHeader.dwDataLength = 0; + m_pFilePtr = NULL; + } + + if (m_waveFormat) + { + ExFreePoolWithTag(m_waveFormat, SAVEDATA_POOLTAG1); + m_waveFormat = NULL; + } + + if (m_fFrameUsed) + { + ExFreePoolWithTag(m_fFrameUsed, SAVEDATA_POOLTAG2); + m_fFrameUsed = NULL; + } + + if (m_FileName.Buffer) + { + ExFreePoolWithTag(m_FileName.Buffer, SAVEDATA_POOLTAG3); + m_FileName.Buffer = NULL; + } + + if (m_pDataBuffer) + { + ExFreePoolWithTag(m_pDataBuffer, SAVEDATA_POOLTAG4); + m_pDataBuffer = NULL; + } +} + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void +CSaveData::DestroyWorkItems +( + void +) +{ + PAGED_CODE(); + + if (m_pWorkItems) + { + for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) + { + if (m_pWorkItems[i].WorkItem!=NULL) + { + IoFreeWorkItem(m_pWorkItems[i].WorkItem); + m_pWorkItems[i].WorkItem = NULL; + } + } + ExFreePoolWithTag(m_pWorkItems, SAVEDATA_POOLTAG); + m_pWorkItems = NULL; + } + +} // DestroyWorkItems + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void +CSaveData::Disable +( + _In_ BOOL fDisable +) +{ + PAGED_CODE(); + + m_fWriteDisabled = fDisable; +} // Disable + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileClose(void) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_FileHandle) + { + ntStatus = ZwClose(m_FileHandle); + m_FileHandle = NULL; + } + + return ntStatus; +} // FileClose + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileOpen +( + _In_ BOOL fOverWrite +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STATUS_BLOCK ioStatusBlock; + + if( FALSE == m_bInitialized ) + { + return STATUS_UNSUCCESSFUL; + } + + if(!m_FileHandle) + { + ntStatus = + ZwCreateFile + ( + &m_FileHandle, + GENERIC_WRITE | SYNCHRONIZE, + &m_objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + fOverWrite ? FILE_OVERWRITE_IF : FILE_OPEN_IF, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0 + ); + } + + return ntStatus; +} // FileOpen + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileWrite +( + _In_reads_bytes_(ulDataSize) PBYTE pData, + _In_ ULONG ulDataSize +) +{ + PAGED_CODE(); + + ASSERT(pData); + ASSERT(m_pFilePtr); + + NTSTATUS ntStatus; + + if (m_FileHandle) + { + IO_STATUS_BLOCK ioStatusBlock; + + ntStatus = ZwWriteFile( m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + pData, + ulDataSize, + m_pFilePtr, + NULL); + + if (NT_SUCCESS(ntStatus)) + { + ASSERT(ioStatusBlock.Information == ulDataSize); + + m_pFilePtr->QuadPart += ulDataSize; + } + } + else + { + ntStatus = STATUS_INVALID_HANDLE; + } + + return ntStatus; +} // FileWrite + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileWriteHeader(void) +{ + PAGED_CODE(); + + NTSTATUS ntStatus; + + if (m_FileHandle && m_waveFormat) + { + IO_STATUS_BLOCK ioStatusBlock; + + m_pFilePtr->QuadPart = 0; + + m_FileHeader.dwFormatLength = (m_waveFormat->wFormatTag == WAVE_FORMAT_PCM) ? + sizeof( PCMWAVEFORMAT ) : + sizeof( WAVEFORMATEX ) + m_waveFormat->cbSize; + + ntStatus = ZwWriteFile( m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + &m_FileHeader, + sizeof(m_FileHeader), + m_pFilePtr, + NULL); + + if (NT_SUCCESS(ntStatus)) + { + m_pFilePtr->QuadPart += sizeof(m_FileHeader); + + ntStatus = ZwWriteFile( m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + m_waveFormat, + m_FileHeader.dwFormatLength, + m_pFilePtr, + NULL); + } + + if (NT_SUCCESS(ntStatus)) + { + m_pFilePtr->QuadPart += m_FileHeader.dwFormatLength; + + ntStatus = ZwWriteFile( m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + &m_DataHeader, + sizeof(m_DataHeader), + m_pFilePtr, + NULL); + } + + if (NT_SUCCESS(ntStatus)) + { + m_pFilePtr->QuadPart += sizeof(m_DataHeader); + } + } + else + { + ntStatus = STATUS_INVALID_HANDLE; + } + + + return ntStatus; +} // FileWriteHeader + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetDeviceObject +( + _In_ PDEVICE_OBJECT DeviceObject +) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + m_pDeviceObject = DeviceObject; + return ntStatus; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +PDEVICE_OBJECT +CSaveData::GetDeviceObject +( + void +) +{ + PAGED_CODE(); + + return m_pDeviceObject; +} + +//============================================================================= +_Use_decl_annotations_ +PSAVEWORKER_PARAM +CSaveData::GetNewWorkItem +( + void +) +{ + LARGE_INTEGER timeOut = { 0 }; + NTSTATUS ntStatus; + + for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) + { + ntStatus = + KeWaitForSingleObject + ( + &m_pWorkItems[i].EventDone, + Executive, + KernelMode, + FALSE, + &timeOut + ); + if (STATUS_SUCCESS == ntStatus) + { + if (m_pWorkItems[i].WorkItem) + return &(m_pWorkItems[i]); + else + return NULL; + } + } + + return NULL; +} // GetNewWorkItem + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::Initialize +( + _In_ BOOL _bOffloaded +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + WCHAR szTemp[MAX_PATH]; + size_t cLen = 0; + IO_STATUS_BLOCK ioStatusBlock = {0}; + HANDLE fileHandle; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING fileName; + + if (_bOffloaded) + { + m_ulOffloadStreamId++; + } + else + { + m_ulStreamId++; + } + + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER1); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, + &objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER2); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, + &objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + } + } + + if (NT_SUCCESS(ntStatus)) + { + // Allocate data file name. + // + RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", DEFAULT_FILE_NAME, _bOffloaded ? OFFLOAD_FILE_NAME : HOST_FILE_NAME, _bOffloaded ? m_ulOffloadStreamId : m_ulStreamId); + m_FileName.Length = 0; + ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); + } + + if (NT_SUCCESS(ntStatus)) + { + m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL + m_FileName.Buffer = (PWSTR) + ExAllocatePool2 + ( + POOL_FLAG_PAGED, + m_FileName.MaximumLength, + SAVEDATA_POOLTAG3 + ); + if (!m_FileName.Buffer) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + + // Allocate memory for data buffer. + // + if (NT_SUCCESS(ntStatus)) + { + RtlStringCbCopyW(m_FileName.Buffer, m_FileName.MaximumLength, szTemp); + m_FileName.Length = (USHORT)wcslen(m_FileName.Buffer) * sizeof(WCHAR); + + m_pDataBuffer = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + m_ulBufferSize, + SAVEDATA_POOLTAG4 + ); + if (!m_pDataBuffer) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + + // Allocate memory for frame usage flags and m_pFilePtr. + // + if (NT_SUCCESS(ntStatus)) + { + m_fFrameUsed = (PBOOL) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + m_ulFrameCount * sizeof(BOOL) + + sizeof(LARGE_INTEGER), + SAVEDATA_POOLTAG2 + ); + if (!m_fFrameUsed) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + + // Initialize the spinlock to synchronize access to the frames + // + KeInitializeSpinLock ( &m_FrameInUseSpinLock ) ; + + // Initialize the file mutex + // + KeInitializeMutex( &m_FileSync, 1 ) ; + + // Open the data file. + // + if (NT_SUCCESS(ntStatus)) + { + // m_fFrameUsed has additional memory to hold m_pFilePtr + // + m_pFilePtr = (PLARGE_INTEGER) + (((PBYTE) m_fFrameUsed) + m_ulFrameCount * sizeof(BOOL)); + + // Create data file. + InitializeObjectAttributes + ( + &m_objectAttributes, + &m_FileName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL + ); + + m_bInitialized = TRUE; + + // Write wave header information to data file. + ntStatus = KeWaitForSingleObject + ( + &m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + ); + + if (STATUS_SUCCESS == ntStatus) + { + ntStatus = FileOpen(TRUE); + if (NT_SUCCESS(ntStatus)) + { + ntStatus = FileWriteHeader(); + + FileClose(); + } + + KeReleaseMutex( &m_FileSync, FALSE ); + } + } + + return ntStatus; +} // Initialize + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::InitializeWorkItems +( + _In_ PDEVICE_OBJECT DeviceObject +) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_pWorkItems != NULL) + { + return ntStatus; + } + + m_pWorkItems = (PSAVEWORKER_PARAM) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + sizeof(SAVEWORKER_PARAM) * MAX_WORKER_ITEM_COUNT, + SAVEDATA_POOLTAG + ); + if (m_pWorkItems) + { + for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) + { + + m_pWorkItems[i].WorkItem = IoAllocateWorkItem(DeviceObject); + if(m_pWorkItems[i].WorkItem == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + KeInitializeEvent + ( + &m_pWorkItems[i].EventDone, + NotificationEvent, + TRUE + ); + } + } + else + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + return ntStatus; +} // InitializeWorkItems + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +SaveFrameWorkerCallback +( + _In_ PDEVICE_OBJECT pDeviceObject, + _In_opt_ PVOID Context +) +{ + UNREFERENCED_PARAMETER(pDeviceObject); + + PAGED_CODE(); + + ASSERT(Context); + + PSAVEWORKER_PARAM pParam = (PSAVEWORKER_PARAM) Context; + PCSaveData pSaveData; + + if (NULL == pParam) + { + // This is completely unexpected, assert here. + // + ASSERT(pParam); + return; + } + + ASSERT(pParam->pSaveData); + ASSERT(pParam->pSaveData->m_fFrameUsed); + + if (pParam->WorkItem) + { + pSaveData = pParam->pSaveData; + + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &pSaveData->m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + if (NT_SUCCESS(pSaveData->FileOpen(FALSE))) + { + pSaveData->FileWrite(pParam->pData, pParam->ulDataSize); + pSaveData->FileClose(); + } + InterlockedExchange( (LONG *)&(pSaveData->m_fFrameUsed[pParam->ulFrameNo]), FALSE ); + + KeReleaseMutex( &pSaveData->m_FileSync, FALSE ); + } + } + + KeSetEvent(&pParam->EventDone, 0, FALSE); +} // SaveFrameWorkerCallback + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetDataFormat +( + _In_ PKSDATAFORMAT pDataFormat +) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + ASSERT(pDataFormat); + + PWAVEFORMATEX pwfx = NULL; + + if (IsEqualGUIDAligned(pDataFormat->Specifier, + KSDATAFORMAT_SPECIFIER_DSOUND)) + { + pwfx = + &(((PKSDATAFORMAT_DSOUND) pDataFormat)->BufferDesc.WaveFormatEx); + } + else if (IsEqualGUIDAligned(pDataFormat->Specifier, + KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) + { + pwfx = &((PKSDATAFORMAT_WAVEFORMATEX) pDataFormat)->WaveFormatEx; + } + + if (pwfx) + { + // Free the previously allocated waveformat + if (m_waveFormat) + { + ExFreePoolWithTag(m_waveFormat, SAVEDATA_POOLTAG1); + } + + m_waveFormat = (PWAVEFORMATEX) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + (pwfx->wFormatTag == WAVE_FORMAT_PCM) ? + sizeof( PCMWAVEFORMAT ) : + sizeof( WAVEFORMATEX ) + pwfx->cbSize, + SAVEDATA_POOLTAG1 + ); + + if(m_waveFormat) + { + RtlCopyMemory( m_waveFormat, + pwfx, + (pwfx->wFormatTag == WAVE_FORMAT_PCM) ? + sizeof( PCMWAVEFORMAT ) : + sizeof( WAVEFORMATEX ) + pwfx->cbSize); + } + else + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + return ntStatus; +} // SetDataFormat + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetMaxWriteSize +( + _In_ ULONG ulMaxWriteSize +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG bufferSize = 0; + PBYTE buffer = NULL; + + // + // Compute new buffer size. + // + ntStatus = RtlULongMult(ulMaxWriteSize, DEFAULT_FRAME_COUNT, &bufferSize); + if (!NT_SUCCESS(ntStatus)) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + // + // Alloc memory for buffer. + // + buffer = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + bufferSize, + SAVEDATA_POOLTAG4 + ); + if (!buffer) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + // + // Free old one. + // + if (m_pDataBuffer) + { + ExFreePoolWithTag(m_pDataBuffer, SAVEDATA_POOLTAG4); + m_pDataBuffer = NULL; + } + + // + // Init new buffer settings. + // + m_pDataBuffer = buffer; + m_ulBufferSize = bufferSize; + m_ulFrameSize = ulMaxWriteSize; + + ntStatus = STATUS_SUCCESS; + +Done: + return ntStatus; +} // SetDataFormat + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void +CSaveData::ReadData +( + _Inout_updates_bytes_all_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount +) +{ + UNREFERENCED_PARAMETER(pBuffer); + UNREFERENCED_PARAMETER(ulByteCount); + + PAGED_CODE(); + + // Not implemented yet. +} // ReadData + +//============================================================================= +_Use_decl_annotations_ +void +CSaveData::SaveFrame +( + _In_ ULONG ulFrameNo, + _In_ ULONG ulDataSize +) +{ + PSAVEWORKER_PARAM pParam = NULL; + + pParam = GetNewWorkItem(); + if (pParam) + { + pParam->pSaveData = this; + pParam->ulFrameNo = ulFrameNo; + pParam->ulDataSize = ulDataSize; + pParam->pData = m_pDataBuffer + ulFrameNo * m_ulFrameSize; + KeResetEvent(&pParam->EventDone); + IoQueueWorkItem(pParam->WorkItem, SaveFrameWorkerCallback, + CriticalWorkQueue, (PVOID)pParam); + } +} // SaveFrame + +//============================================================================= +void +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::WaitAllWorkItems +( + void +) +{ + PAGED_CODE(); + + // Save the last partially-filled frame + if (m_ulBufferOffset > m_ulFrameIndex * m_ulFrameSize) + { + ULONG size; + + size = m_ulBufferOffset - m_ulFrameIndex * m_ulFrameSize; + SaveFrame(m_ulFrameIndex, size); + } + + for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) + { + KeWaitForSingleObject + ( + &(m_pWorkItems[i].EventDone), + Executive, + KernelMode, + FALSE, + NULL + ); + } +} // WaitAllWorkItems + +//============================================================================= +_Use_decl_annotations_ +void +CSaveData::WriteData +( + _In_reads_bytes_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount +) +{ + ASSERT(pBuffer); + + BOOL fSaveFrame = FALSE; + ULONG ulSaveFrameIndex = 0; + KIRQL oldIrql; + + // If stream writing is disabled, then exit. + // + if (m_fWriteDisabled) + { + return; + } + + if( 0 == ulByteCount ) + { + return; + } + + // The logic below assumes that write size is <= than frame size. + if (ulByteCount > m_ulFrameSize) + { + ulByteCount = m_ulFrameSize; + } + + // Check to see if this frame is available. + KeAcquireSpinLock(&m_FrameInUseSpinLock, &oldIrql); + if (!m_fFrameUsed[m_ulFrameIndex]) + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql ); + + ULONG ulWriteBytes = ulByteCount; + + if( (m_ulBufferSize - m_ulBufferOffset) < ulWriteBytes ) + { + ulWriteBytes = m_ulBufferSize - m_ulBufferOffset; + } + + RtlCopyMemory(m_pDataBuffer + m_ulBufferOffset, pBuffer, ulWriteBytes); + m_ulBufferOffset += ulWriteBytes; + + // Check to see if we need to save this frame + if (m_ulBufferOffset >= ((m_ulFrameIndex + 1) * m_ulFrameSize)) + { + fSaveFrame = TRUE; + } + + // Loop the buffer, if we reached the end. + if (m_ulBufferOffset == m_ulBufferSize) + { + fSaveFrame = TRUE; + m_ulBufferOffset = 0; + } + + if (fSaveFrame) + { + InterlockedExchange( (LONG *)&(m_fFrameUsed[m_ulFrameIndex]), TRUE ); + ulSaveFrameIndex = m_ulFrameIndex; + m_ulFrameIndex = (m_ulFrameIndex + 1) % m_ulFrameCount; + } + + // Write the left over if the next frame is available. + if (ulWriteBytes != ulByteCount) + { + KeAcquireSpinLock(&m_FrameInUseSpinLock, &oldIrql ); + if (!m_fFrameUsed[m_ulFrameIndex]) + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql ); + RtlCopyMemory + ( + m_pDataBuffer + m_ulBufferOffset, + pBuffer + ulWriteBytes, + ulByteCount - ulWriteBytes + ); + + m_ulBufferOffset += ulByteCount - ulWriteBytes; + } + else + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql); + } + } + + if (fSaveFrame) + { + SaveFrame(ulSaveFrameIndex, m_ulFrameSize); + } + } + else + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql ); + } + +} // WriteData + + diff --git a/audio/Acx/Samples/Common/SaveData.h b/audio/Acx/Samples/Common/SaveData.h new file mode 100644 index 00000000..9138352f --- /dev/null +++ b/audio/Acx/Samples/Common/SaveData.h @@ -0,0 +1,259 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + SaveData.h + +Abstract: + + Declaration of data saving class for ACX driver samples. This class supplies services +to save data to disk. + + +--*/ + +#pragma once + +//----------------------------------------------------------------------------- +// Forward declaration +//----------------------------------------------------------------------------- +class CSaveData; +typedef CSaveData *PCSaveData; + + +//----------------------------------------------------------------------------- +// Structs +//----------------------------------------------------------------------------- + +// Parameter to workitem. +#include <pshpack1.h> +typedef struct _SAVEWORKER_PARAM { + PIO_WORKITEM WorkItem; + ULONG ulFrameNo; + ULONG ulDataSize; + PBYTE pData; + PCSaveData pSaveData; + KEVENT EventDone; +} SAVEWORKER_PARAM; +typedef SAVEWORKER_PARAM *PSAVEWORKER_PARAM; +#include <poppack.h> + +// wave file header. +#include <pshpack1.h> +typedef struct _OUTPUT_FILE_HEADER +{ + DWORD dwRiff; + DWORD dwFileSize; + DWORD dwWave; + DWORD dwFormat; + DWORD dwFormatLength; +} OUTPUT_FILE_HEADER; +typedef OUTPUT_FILE_HEADER *POUTPUT_FILE_HEADER; + +typedef struct _OUTPUT_DATA_HEADER +{ + DWORD dwData; + DWORD dwDataLength; +} OUTPUT_DATA_HEADER; +typedef OUTPUT_DATA_HEADER *POUTPUT_DATA_HEADER; + +#include <poppack.h> + +//----------------------------------------------------------------------------- +// Classes +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// CSaveData +// Saves the wave data to disk. +// +__drv_maxIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +IO_WORKITEM_ROUTINE SaveFrameWorkerCallback; + +class CSaveData +{ +protected: + UNICODE_STRING m_FileName; // DataFile name. + HANDLE m_FileHandle; // DataFile handle. + PBYTE m_pDataBuffer; // Data buffer. + ULONG m_ulBufferSize; // Total buffer size. + + ULONG m_ulFrameIndex; // Current Frame. + ULONG m_ulFrameCount; // Frame count. + ULONG m_ulFrameSize; + ULONG m_ulBufferOffset; // index in buffer. + PBOOL m_fFrameUsed; // Frame usage table. + KSPIN_LOCK m_FrameInUseSpinLock; // Spinlock for synch. + KMUTEX m_FileSync; // Synchronizes file access + + OBJECT_ATTRIBUTES m_objectAttributes; // Used for opening file. + + OUTPUT_FILE_HEADER m_FileHeader; + PWAVEFORMATEX m_waveFormat; + OUTPUT_DATA_HEADER m_DataHeader; + PLARGE_INTEGER m_pFilePtr; + + static PDEVICE_OBJECT m_pDeviceObject; + static ULONG m_ulStreamId; + static ULONG m_ulOffloadStreamId; + static PSAVEWORKER_PARAM m_pWorkItems; + + BOOL m_fWriteDisabled; + + BOOL m_bInitialized; + +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSaveData(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CSaveData(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + Cleanup( + void + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + InitializeWorkItems( + _In_ PDEVICE_OBJECT DeviceObject + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + DestroyWorkItems( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + Disable( + _In_ BOOL fDisable + ); + + static + __drv_maxIRQL(DISPATCH_LEVEL) + PSAVEWORKER_PARAM + GetNewWorkItem( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Initialize( + _In_ BOOL _bOffloaded + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetDeviceObject( + _In_ PDEVICE_OBJECT DeviceObject + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + PDEVICE_OBJECT + GetDeviceObject( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + ReadData( + _Inout_updates_bytes_all_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetDataFormat( + _In_ PKSDATAFORMAT pDataFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetMaxWriteSize( + _In_ ULONG ulMaxWriteSize + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + WaitAllWorkItems( + void + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + void + WriteData( + _In_reads_bytes_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount + ); + +private: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileClose( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileOpen( + _In_ BOOL fOverWrite + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileWrite( + _In_reads_bytes_(ulDataSize) PBYTE pData, + _In_ ULONG ulDataSize + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileWriteHeader( + void + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + void + SaveFrame( + _In_ ULONG ulFrameNo, + _In_ ULONG ulDataSize + ); + + friend + IO_WORKITEM_ROUTINE SaveFrameWorkerCallback; +}; +typedef CSaveData *PCSaveData; + diff --git a/audio/Acx/Samples/Common/SimPeakMeter.cpp b/audio/Acx/Samples/Common/SimPeakMeter.cpp new file mode 100644 index 00000000..0dfbd4e5 --- /dev/null +++ b/audio/Acx/Samples/Common/SimPeakMeter.cpp @@ -0,0 +1,106 @@ +/*++ + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + SimPeakMeter.cpp + +Abstract: + + Virtual Peakmeter - aggregates all streams + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "SimPeakMeter.h" + +#ifndef __INTELLISENSE__ +#include "SimPeakMeter.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter::CSimPeakMeter() +{ + PAGED_CODE(); + m_NumStreams = 0; + m_PeakMeterIndex = 0; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter::~CSimPeakMeter() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +LONG CSimPeakMeter::GetValue(ULONG Channel) +{ + PAGED_CODE(); + + // Ignore channel + UNREFERENCED_PARAMETER(Channel); + +#define PEAKMETER_VALUE_FULL (PEAKMETER_MAXIMUM / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_HALF (PEAKMETER_MAXIMUM / 2 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_QUARTER (PEAKMETER_MAXIMUM / 4 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_ONE_EIGTH (PEAKMETER_MAXIMUM / 8 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) + + LONG PeakMeterValues[] = { + PEAKMETER_VALUE_ONE_EIGTH, + PEAKMETER_VALUE_QUARTER, + PEAKMETER_VALUE_HALF, + PEAKMETER_VALUE_FULL, + PEAKMETER_VALUE_HALF, + PEAKMETER_VALUE_QUARTER + }; + + if (m_NumStreams) + { + LONG pmi = InterlockedIncrement(&m_PeakMeterIndex); + if (pmi == ARRAYSIZE(PeakMeterValues)) + { + pmi = 0; + InterlockedExchange(&m_PeakMeterIndex, 0); + } + + return PeakMeterValues[pmi]; + } + + // + // No active streams. Peak meter = 0 + // + return 0; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CSimPeakMeter::StartStream() +{ + PAGED_CODE(); + InterlockedIncrement(&m_NumStreams); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CSimPeakMeter::StopStream() +{ + PAGED_CODE(); + + ASSERT(m_NumStreams); + InterlockedDecrement(&m_NumStreams); + + return STATUS_SUCCESS; +} diff --git a/audio/Acx/Samples/Common/SimPeakMeter.h b/audio/Acx/Samples/Common/SimPeakMeter.h new file mode 100644 index 00000000..7203f299 --- /dev/null +++ b/audio/Acx/Samples/Common/SimPeakMeter.h @@ -0,0 +1,51 @@ +/*++ + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + SimPeakMeter.h + +Abstract: + + Virtual Peakmeter - aggregates all streams + +Environment: + + Kernel mode + +--*/ + +#pragma once + +class CSimPeakMeter +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSimPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CSimPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + LONG GetValue(_In_ ULONG Channel); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS StartStream(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS StopStream(); + +private: + LONG m_NumStreams; + LONG m_PeakMeterIndex; +}; + diff --git a/audio/Acx/Samples/Common/StreamEngine.cpp b/audio/Acx/Samples/Common/StreamEngine.cpp new file mode 100644 index 00000000..be90bac6 --- /dev/null +++ b/audio/Acx/Samples/Common/StreamEngine.cpp @@ -0,0 +1,1345 @@ +/*++ + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + StreamEngine.cpp + +Abstract: + + Virtual Streaming Engine - this module controls streaming logic for + the device. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include <devguid.h> +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" + +#ifndef __INTELLISENSE__ +#include "streamengine.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CStreamEngine::CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ BOOL Offload, + _In_opt_ CSimPeakMeter *CircuitPeakmeter +) + : m_PacketsCount(0), + m_PacketSize(0), + m_FirstPacketOffset(0), + m_NotificationTimer(NULL), + m_CurrentState(AcxStreamStateStop), + m_CurrentPacket(0), + m_Position(0), + m_Stream(Stream), + m_StreamFormat(StreamFormat), + m_StartTime(0), + m_StartPosition(0), + m_GlitchAdjust(0), + m_ToneFrequency(DEFAULT_FREQUENCY), + m_Offload(Offload), + m_pCircuitPeakmeter(CircuitPeakmeter) +{ + PAGED_CODE(); + + KeQueryPerformanceCounter(&m_PerformanceCounterFrequency); + RtlZeroMemory(m_Packets, sizeof(m_Packets)); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CStreamEngine::~CStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::AllocateRtPackets( + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET* Packets +) +{ + NTSTATUS status = STATUS_SUCCESS; + PACX_RTPACKET packets = NULL; + PVOID packetBuffer = NULL; + ULONG i; + ULONG packetAllocSizeInPages = 0; + ULONG packetAllocSizeInBytes = 0; + ULONG firstPacketOffset = 0; + size_t packetsSize = 0; + + PAGED_CODE(); + + if (PacketCount > MAX_PACKET_COUNT) + { + ASSERT(FALSE); + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + status = RtlSizeTMult(PacketCount, sizeof(ACX_RTPACKET), &packetsSize); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + packets = (PACX_RTPACKET)ExAllocatePool2(POOL_FLAG_NON_PAGED, packetsSize, DeviceDriverTag); + if (!packets) + { + status = STATUS_NO_MEMORY; + ASSERT(FALSE); + goto exit; + } + + // + // We need to allocate page-aligned buffers, to ensure no kernel memory leaks + // to user space. Round up the packet size to page aligned, then calculate + // the first packet's buffer offset so packet 0 ends on a page boundary and + // packet 1 begins on a page boundary. + // + status = RtlULongAdd(PacketSize, PAGE_SIZE - 1, &packetAllocSizeInPages); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + packetAllocSizeInPages = packetAllocSizeInPages / PAGE_SIZE; + packetAllocSizeInBytes = PAGE_SIZE * packetAllocSizeInPages; + firstPacketOffset = packetAllocSizeInBytes - PacketSize; + + for (i = 0; i < PacketCount; ++i) + { + PMDL pMdl = NULL; + + ACX_RTPACKET_INIT(&packets[i]); + + packetBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, packetAllocSizeInBytes, DeviceDriverTag); + if (packetBuffer == NULL) + { + status = STATUS_NO_MEMORY; + goto exit; + } + + pMdl = IoAllocateMdl(packetBuffer, packetAllocSizeInBytes, FALSE, TRUE, NULL); + if (pMdl == NULL) + { + status = STATUS_NO_MEMORY; + goto exit; + } + + MmBuildMdlForNonPagedPool(pMdl); + + WDF_MEMORY_DESCRIPTOR_INIT_MDL(&((packets)[i].RtPacketBuffer), pMdl, packetAllocSizeInBytes); + + packets[i].RtPacketSize = PacketSize; + if (i == 0) + { + packets[i].RtPacketOffset = firstPacketOffset; + } + else + { + packets[i].RtPacketOffset = 0; + } + m_Packets[i] = packetBuffer; + + packetBuffer = NULL; + } + + *Packets = packets; + packets = NULL; + m_PacketsCount = PacketCount; + m_PacketSize = PacketSize; + m_FirstPacketOffset = firstPacketOffset; + +exit: + if (packetBuffer) + { + ExFreePoolWithTag(packetBuffer, DeviceDriverTag); + } + if (packets) + { + FreeRtPackets(packets, PacketCount); + } + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CStreamEngine::FreeRtPackets( + _Frees_ptr_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount +) +{ + ULONG i; + PVOID buffer; + + PAGED_CODE(); + + for (i = 0; i < PacketCount; ++i) + { + if (Packets[i].RtPacketBuffer.u.MdlType.Mdl) + { + buffer = MmGetMdlVirtualAddress(Packets[i].RtPacketBuffer.u.MdlType.Mdl); + IoFreeMdl(Packets[i].RtPacketBuffer.u.MdlType.Mdl); + ExFreePool(buffer); + } + } + + ExFreePool(Packets); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::PrepareHardware() +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + WDF_TIMER_CONFIG timerConfig; + WDF_OBJECT_ATTRIBUTES timerAttributes; + PSTREAM_TIMER_CONTEXT timerCtx; + + PAGED_CODE(); + + // + // If already in this state, do nothing. + // + if (m_CurrentState == AcxStreamStatePause) + { + // Nothing to do. + status = STATUS_SUCCESS; + goto exit; + } + + if (m_CurrentState != AcxStreamStateStop) + { + // Error out. + status = STATUS_INVALID_STATE_TRANSITION; + goto exit; + } + + // + // Stop to Pause. + // + WDF_TIMER_CONFIG_INIT(&timerConfig, CStreamEngine::s_EvtStreamPassCallback); + timerConfig.AutomaticSerialization = TRUE; + timerConfig.UseHighResolutionTimer = WdfTrue; + timerConfig.Period = 0; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&timerAttributes, STREAM_TIMER_CONTEXT); + timerAttributes.ParentObject = m_Stream; + + status = WdfTimerCreate(&timerConfig, &timerAttributes, &m_NotificationTimer); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + timerCtx = GetStreamTimerContext(m_NotificationTimer); + timerCtx->StreamEngine = this; + + m_CurrentState = AcxStreamStatePause; + status = STATUS_SUCCESS; + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + // + // If already in this state, do nothing. + // + if (m_CurrentState == AcxStreamStateStop) + { + // Nothing to do. + goto exit; + } + + // + // Just assert we are in the correct state. + // On the way down we always want to succeed. + // + ASSERT(m_CurrentState == AcxStreamStatePause); + + // + // Pause to Stop. + // + if (m_NotificationTimer) + { + WdfTimerStop(m_NotificationTimer, TRUE); + WdfObjectDelete(m_NotificationTimer); + m_NotificationTimer = NULL; + } + + KeFlushQueuedDpcs(); + + m_Position = 0; + m_GlitchAdjust = 0; + m_CurrentPacket = 0; + + m_CurrentState = AcxStreamStateStop; + +exit: + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Pause() +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + + PAGED_CODE(); + + if (m_CurrentState == AcxStreamStatePause) + { + // Nothing to do. + status = STATUS_SUCCESS; + goto exit; + } + + if (m_CurrentState != AcxStreamStateRun) + { + // Error out. + status = STATUS_INVALID_STATE_TRANSITION; + goto exit; + } + + m_PeakMeter.StopStream(); + if (m_pCircuitPeakmeter) + { + m_pCircuitPeakmeter->StopStream(); + } + + // + // Run to Pause. + // + WdfTimerStop(m_NotificationTimer, TRUE); + + // Save the position we paused at. + UpdatePosition(); + + m_CurrentState = AcxStreamStatePause; + status = STATUS_SUCCESS; + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Run() +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + + PAGED_CODE(); + + if (m_CurrentState == AcxStreamStateRun) + { + // Nothing to do. + status = STATUS_SUCCESS; + goto exit; + } + + if (m_CurrentState != AcxStreamStatePause) + { + status = STATUS_INVALID_STATE_TRANSITION; + goto exit; + } + + m_PeakMeter.StartStream(); + if (m_pCircuitPeakmeter) + { + m_pCircuitPeakmeter->StartStream(); + } + + // + // Pause to Run. + // + // Save the time and position - if we ran and paused previously, the StartTime and StartPosition will allow + // us to continue scheduling packet completions correctly, while still reporting absolute position from the + // start of the stream. + // + m_StartTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + m_StartPosition = m_Position; + + // Reset time we've lost to glitches + m_GlitchAdjust = 0; + + ScheduleNextPass(); + + m_CurrentState = AcxStreamStateRun; + status = STATUS_SUCCESS; + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetPresentationPosition( + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition +) +{ + ULONG blockAlign; + LARGE_INTEGER qpc; + + PAGED_CODE(); + + blockAlign = AcxDataFormatGetBlockAlign(m_StreamFormat); + + // Update the position based on the current time + UpdatePosition(); + qpc = KeQueryPerformanceCounter(NULL); + + *PositionInBlocks = m_Position / blockAlign; + *QPCPosition = (ULONGLONG)qpc.QuadPart; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetLinearBufferPosition( + _Out_ PULONGLONG Position +) +{ + UNREFERENCED_PARAMETER(Position); + PAGED_CODE(); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::SetCurrentWritePosition( + _In_ ULONG Position +) +{ + UNREFERENCED_PARAMETER(Position); + PAGED_CODE(); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::SetLastBufferPosition( + _In_ ULONG Position +) +{ + UNREFERENCED_PARAMETER(Position); + PAGED_CODE(); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::AssignDrmContentId( + ULONG DrmContentId, + PACXDRMRIGHTS DrmRights +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DrmContentId); + UNREFERENCED_PARAMETER(DrmRights); + + // + // At this point the driver should enforce the new DrmRights. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // + // From MSDN: + // + // This sample doesn't forward protected content, but if your driver uses + // lower layer drivers or a different stack to properly work, please see the + // following info from MSDN: + // + // "Before allowing protected content to flow through a data path, the system + // verifies that the data path is secure. To do so, the system authenticates + // each module in the data path beginning at the upstream end of the data path + // and moving downstream. As each module is authenticated, that module gives + // the system information about the next module in the data path so that it + // can also be authenticated. To be successfully authenticated, a module's + // binary file must be signed as DRM-compliant. + // + // Two adjacent modules in the data path can communicate with each other in + // one of several ways. If the upstream module calls the downstream module + // through IoCallDriver, the downstream module is part of a WDM driver. In + // this case, the upstream module calls the AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetHWLatency( + _Out_ ULONG* FifoSize, + _Out_ ULONG* Delay +) +{ + PAGED_CODE(); + + *FifoSize = 128; + *Delay = 0; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter * +CStreamEngine::GetPeakMeter() +{ + PAGED_CODE(); + + return &m_PeakMeter; +} + +_Use_decl_annotations_ +VOID +CStreamEngine::s_EvtStreamPassCallback( + _In_ WDFTIMER Timer +) +{ + CStreamEngine* This; + PSTREAM_TIMER_CONTEXT timerCtx; + + // Get our stream engine pointer from the timer context + timerCtx = GetStreamTimerContext(Timer); + This = timerCtx->StreamEngine; + + // Call the StreamPassCallback for the engine + This->StreamPassCallback(); +} + +// This is run every time the stream timer fires +_Use_decl_annotations_ +VOID +CStreamEngine::StreamPassCallback() +{ + ULONGLONG completedPacket; + ULONGLONG qpcCompleted; + + // Process the packet (e.g. save render to file/generate capture data) + ProcessPacket(); + + // We've completed a packet! Increment our currently active packet + completedPacket = (ULONG)InterlockedIncrement((LONG*)&m_CurrentPacket) - 1; + // Save the time at which we moved to the next packet + qpcCompleted = (ULONGLONG)KeQueryPerformanceCounter(NULL).QuadPart; + + InterlockedExchange64(&m_LastPacketStart.QuadPart, m_CurrentPacketStart.QuadPart); + InterlockedExchange64(&m_CurrentPacketStart.QuadPart, qpcCompleted); + + // Tell ACX we've completed the packet. + (void)AcxRtStreamNotifyPacketComplete(m_Stream, completedPacket, qpcCompleted); + + // Schedule when our new current packet will finish + ScheduleNextPass(); +} + +_Use_decl_annotations_ +VOID +CStreamEngine::ScheduleNextPass() +{ + LONGLONG delay = 0; + ULONG bytesPerSecond; + ULONGLONG nextPacket = 0; + ULONGLONG nextPacketStartPosition = 0; + ULONGLONG nextPacketPositionFromLastPause = 0; + ULONGLONG nextPacketTimeFromLastPauseHns = 0; + ULONGLONG nextPacketTime = 0; + ULONGLONG currentTime; + BOOLEAN inTimerQueue = FALSE; + + // Get the number of bytes per second from our stored stream format + bytesPerSecond = GetBytesPerSecond(); + + // Calculate the absolute position of the beginning of the next packet from the beginning of the stream + nextPacket = m_CurrentPacket + 1; + nextPacketStartPosition = nextPacket * m_PacketSize; + + // Adjust next packet position to account for the last time we resumed from Pause + nextPacketPositionFromLastPause = nextPacketStartPosition - m_StartPosition; + + // Convert from bytes to HNS (to prevent truncation, multiply first then divide) + nextPacketTimeFromLastPauseHns = nextPacketPositionFromLastPause * HNS_PER_SEC / bytesPerSecond; + + // Next packet time is Time @ resume from Pause, offset for lost time due to glitch, with next packet time added + nextPacketTime = m_StartTime + m_GlitchAdjust + nextPacketTimeFromLastPauseHns; + + currentTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + + // Determine how long we want to wait, in HNS. Negative since it's a relative wait + delay = -(LONGLONG)(nextPacketTime - currentTime); + + // If the delay isn't negative, this means we lost some time (e.g. broken into kernel debugger). Update + // our glitch adjust to account for that lost time, and attempt to schedule again + if (delay >= 0) + { + // Glitch!!! + // Update the glitch adjustment and set the new delay. + m_GlitchAdjust += delay; + + StreamPassCallback(); + + return; + } + + // Start the timer for our next pass! Note the timer isn't periodic. + inTimerQueue = WdfTimerStart(m_NotificationTimer, delay); + + // We shouldn't be scheduling our next pass if the timer was previously still pending + ASSERT(inTimerQueue == FALSE); +} + +_Use_decl_annotations_ +VOID +CStreamEngine::UpdatePosition() +{ + ULONGLONG currentTime; + ULONG bytesPerSecond; + + if (m_CurrentState != AcxStreamStateRun) + { + return; + } + bytesPerSecond = GetBytesPerSecond(); + currentTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + + // Update position + m_Position = m_StartPosition - m_GlitchAdjust + (currentTime - m_StartTime) * bytesPerSecond / HNS_PER_SEC; +} + +_Use_decl_annotations_ +ULONG +CStreamEngine::GetBytesPerSecond() +{ + ULONG bytesPerSecond; + + bytesPerSecond = AcxDataFormatGetAverageBytesPerSec(m_StreamFormat); + + return bytesPerSecond; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetCurrentPacket( + _Out_ PULONG CurrentPacket +) +{ + ULONG currentPacket; + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + *CurrentPacket = currentPacket; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ BOOL Offload, + _In_ CSimPeakMeter * CircuitPeakmeter + +) + : CStreamEngine(Stream, StreamFormat, Offload, CircuitPeakmeter) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::~CRenderStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::PrepareHardware() +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + status = CStreamEngine::PrepareHardware(); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + status = m_SaveData.SetDataFormat((PKSDATAFORMAT)AcxDataFormatGetKsDataFormat(m_StreamFormat)); + if (!NT_SUCCESS(status)) + { + status = STATUS_SUCCESS; + goto exit; + } + + status = m_SaveData.Initialize(m_Offload); + if (!NT_SUCCESS(status)) + { + status = STATUS_SUCCESS; + goto exit; + } + + status = m_SaveData.SetMaxWriteSize(m_PacketSize * m_PacketsCount * 16); + if (!NT_SUCCESS(status)) + { + status = STATUS_SUCCESS; + goto exit; + } + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + m_SaveData.WaitAllWorkItems(); + m_SaveData.Cleanup(); + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::AssignDrmContentId( + ULONG DrmContentId, + PACXDRMRIGHTS DrmRights + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DrmContentId); + + // + // At this point the driver should enforce the new DrmRights. + // The sample driver handles DrmRights per stream basis, and + // stops writing the stream to disk, if CopyProtect = TRUE. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // Loopback: if CopyProtect is true, disable loopback stream. + // + + // + // Sample writes each stream seperately to disk. If the rights for this + // stream indicates that the stream is CopyProtected, stop writing to disk. + // + m_SaveData.Disable(DrmRights->CopyProtect); + + // + // From MSDN: + // + // This sample doesn't forward protected content, but if your driver uses + // lower layer drivers or a different stack to properly work, please see the + // following info from MSDN: + // + // "Before allowing protected content to flow through a data path, the system + // verifies that the data path is secure. To do so, the system authenticates + // each module in the data path beginning at the upstream end of the data path + // and moving downstream. As each module is authenticated, that module gives + // the system information about the next module in the data path so that it + // can also be authenticated. To be successfully authenticated, a module's + // binary file must be signed as DRM-compliant. + // + // Two adjacent modules in the data path can communicate with each other in + // one of several ways. If the upstream module calls the downstream module + // through IoCallDriver, the downstream module is part of a WDM driver. In + // this case, the upstream module calls the AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::SetRenderPacket( + _In_ ULONG Packet, + _In_ ULONG Flags, + _In_ ULONG EosPacketLength +) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG currentPacket; + + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(EosPacketLength); + + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + if (Packet <= currentPacket) + { + //ASSERT(FALSE); + status = STATUS_DATA_LATE_ERROR; + } + else if (Packet > currentPacket + 1) + { + //ASSERT(FALSE); + status = STATUS_DATA_OVERRUN; + } + + return status; +} + +_Use_decl_annotations_ +VOID +CRenderStreamEngine::ProcessPacket() +{ + ULONG currentPacket; + ULONG packetIndex; + PBYTE packetBuffer; + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + packetIndex = currentPacket % m_PacketsCount; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + // Packet 0 starts at an offset if the size isn't a multiple of page_size + if (packetIndex == 0) + { + packetBuffer += m_FirstPacketOffset; + } + + m_SaveData.WriteData(packetBuffer, m_PacketSize); +} + + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat +) + : CStreamEngine(Stream, StreamFormat, FALSE, NULL), + m_EnableWaveCapture(0) +{ + PAGED_CODE(); + + m_CurrentPacketStart.QuadPart = 0; + m_LastPacketStart.QuadPart = 0; + + RtlInitUnicodeString(&m_HostCaptureFileName, NULL); + RtlInitUnicodeString(&m_LoopbackCaptureFileName, NULL); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::~CCaptureStreamEngine() +{ + PAGED_CODE(); + + RtlFreeUnicodeString(&m_HostCaptureFileName); + RtlFreeUnicodeString(&m_LoopbackCaptureFileName); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::PrepareHardware() +{ + NTSTATUS status = STATUS_SUCCESS; + PWAVEFORMATEXTENSIBLE pwfext = NULL; + + PAGED_CODE(); + + status = CStreamEngine::PrepareHardware(); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + (void)ReadRegistrySettings(); + + pwfext = (PWAVEFORMATEXTENSIBLE)AcxDataFormatGetWaveFormatExtensible(m_StreamFormat); + if (pwfext == NULL) + { + // Cannot initialize reader or generator with a format that's not understood + status = STATUS_NO_MATCH; + ASSERT(FALSE); + goto exit; + } + + if (m_EnableWaveCapture) + { + status = m_WaveReader.Init(pwfext, &m_HostCaptureFileName); + if (!NT_SUCCESS(status)) + { + m_EnableWaveCapture = FALSE; + } + } + + if (!m_EnableWaveCapture) + { + status = m_ToneGenerator.Init(m_ToneFrequency, pwfext); + } + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + if (m_EnableWaveCapture) + { + m_WaveReader.WaitAllWorkItems(); + } + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::GetCapturePacket( + _Out_ ULONG* LastCapturePacket, + _Out_ ULONGLONG* QPCPacketStart, + _Out_ BOOLEAN* MoreData +) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG currentPacket; + LONGLONG qpcPacketStart; + + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + qpcPacketStart = InterlockedCompareExchange64(&m_LastPacketStart.QuadPart, -1, -1); + + *LastCapturePacket = currentPacket - 1; + *QPCPacketStart = (ULONGLONG)qpcPacketStart; + *MoreData = FALSE; + + return status; +} + +_Use_decl_annotations_ +VOID +CCaptureStreamEngine::ProcessPacket() +{ + ULONG currentPacket; + ULONG packetIndex; + PBYTE packetBuffer; + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + packetIndex = currentPacket % m_PacketsCount; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + + // Packet 0 starts at an offset if the size isn't a multiple of page_size + if (packetIndex == 0) + { + packetBuffer += m_FirstPacketOffset; + } + + if (m_EnableWaveCapture) + { + m_WaveReader.ReadWaveData(packetBuffer, m_PacketSize); + } + else + { + m_ToneGenerator.GenerateSine(packetBuffer, m_PacketSize); + } +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReadRegistrySettings() +{ + NTSTATUS status; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; + + RTL_QUERY_REGISTRY_TABLE paramTable[] = { + // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"EnableWaveCapture", &m_EnableWaveCapture, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_EnableWaveCapture, sizeof(DWORD) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureFileName", &m_HostCaptureFileName, (REG_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_SZ, &m_HostCaptureFileName, sizeof(UNICODE_STRING) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"LoopbackCaptureFileName", &m_LoopbackCaptureFileName, (REG_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_SZ, &m_LoopbackCaptureFileName, sizeof(UNICODE_STRING) }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + + PAGED_CODE(); + + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + status = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); + + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); + + if (DriverKey) + { + ZwClose(DriverKey); + } + +exit: + if (!NT_SUCCESS(status)) + { + m_EnableWaveCapture = FALSE; + } + + return status; +} +_Use_decl_annotations_ +PAGED_CODE_SEG +CBufferedCaptureStreamEngine::CBufferedCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ CKeywordDetector* KeywordDetector + +) + : CCaptureStreamEngine(Stream, StreamFormat), + m_KeywordDetector(KeywordDetector) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CBufferedCaptureStreamEngine::~CBufferedCaptureStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::Pause() +{ + PAGED_CODE(); + + m_KeywordDetector->Stop(); + return CCaptureStreamEngine::Pause(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::Run() +{ + PAGED_CODE(); + + m_KeywordDetector->Run(); + return CCaptureStreamEngine::Run(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::GetCapturePacket( + _Out_ ULONG* LastCapturePacket, + _Out_ ULONGLONG* QPCPacketStart, + _Out_ BOOLEAN* MoreData +) +{ + PAGED_CODE(); + + // retrieve the packet from the fifo queue + return m_KeywordDetector->GetReadPacket(m_PacketsCount, m_PacketSize, m_Packets, LastCapturePacket, QPCPacketStart, MoreData); +} + +_Use_decl_annotations_ +VOID +CBufferedCaptureStreamEngine::ProcessPacket() +{ + LARGE_INTEGER qpc; + LARGE_INTEGER qpcFrequency; + + qpc = KeQueryPerformanceCounter(&qpcFrequency); + + // Add the next packet to the fifo queue + m_KeywordDetector->DpcRoutine(qpc.QuadPart, qpcFrequency.QuadPart); +} + +//Streamengine callbacks + +VOID +EvtStreamDestroy( + _In_ WDFOBJECT Object +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + ctx = GetStreamEngineContext((ACXSTREAM)Object); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + ctx->StreamEngine = NULL; + delete streamEngine; +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetHwLatency( + _In_ ACXSTREAM Stream, + _Out_ ULONG* FifoSize, + _Out_ ULONG* Delay +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->GetHWLatency(FifoSize, Delay); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamAllocateRtPackets( + _In_ ACXSTREAM Stream, + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET* Packets +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->AllocateRtPackets(PacketCount, PacketSize, Packets); +} + +PAGED_CODE_SEG +VOID +EvtStreamFreeRtPackets( + _In_ ACXSTREAM Stream, + _In_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->FreeRtPackets(Packets, PacketCount); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamPrepareHardware( + _In_ ACXSTREAM Stream +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->PrepareHardware(); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamReleaseHardware( + _In_ ACXSTREAM Stream +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->ReleaseHardware(); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamRun( + _In_ ACXSTREAM Stream +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->Run(); +} + + +PAGED_CODE_SEG +NTSTATUS +EvtStreamPause( + _In_ ACXSTREAM Stream +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->Pause(); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamAssignDrmContentId( + _In_ ACXSTREAM Stream, + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->AssignDrmContentId(DrmContentId, DrmRights); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetCurrentPacket( + _In_ ACXSTREAM Stream, + _Out_ PULONG CurrentPacket +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = static_cast<CStreamEngine*>(ctx->StreamEngine); + + return streamEngine->GetCurrentPacket(CurrentPacket); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetPresentationPosition( + _In_ ACXSTREAM Stream, + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = static_cast<CStreamEngine*>(ctx->StreamEngine); + + return streamEngine->GetPresentationPosition(PositionInBlocks, QPCPosition); +} + diff --git a/audio/Acx/Samples/Common/StreamEngine.h b/audio/Acx/Samples/Common/StreamEngine.h new file mode 100644 index 00000000..deeff95a --- /dev/null +++ b/audio/Acx/Samples/Common/StreamEngine.h @@ -0,0 +1,449 @@ +#pragma once + +#include "savedata.h" +#include "tonegenerator.h" +#include "WaveReader.h" +#include "SimPeakMeter.h" +#include "keyworddetector.h" + +#define HNSTIME_PER_MILLISECOND 10000 + +#define MAX_PACKET_COUNT 2 + +#define DEFAULT_FREQUENCY 220 +#define LOOPBACK_FREQUENCY 500 + +// Stream callbacks shared between Capture and Render + +VOID +EvtStreamDestroy( + _In_ WDFOBJECT Object +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetHwLatency( + _In_ ACXSTREAM Stream, + _Out_ ULONG* FifoSize, + _Out_ ULONG* Delay +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamAllocateRtPackets( + _In_ ACXSTREAM Stream, + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET* Packets +); + +PAGED_CODE_SEG +VOID +EvtStreamFreeRtPackets( + _In_ ACXSTREAM Stream, + _In_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamPrepareHardware( + _In_ ACXSTREAM Stream +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamReleaseHardware( + _In_ ACXSTREAM Stream +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamRun( + _In_ ACXSTREAM Stream +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamPause( + _In_ ACXSTREAM Stream +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamAssignDrmContentId( + _In_ ACXSTREAM Stream, + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetCurrentPacket( + _In_ ACXSTREAM Stream, + _Out_ PULONG CurrentPacket +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetPresentationPosition( + _In_ ACXSTREAM Stream, + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition +); + + +class CStreamEngine +{ +public: + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AllocateRtPackets( + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET * Packets + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID + FreeRtPackets( + _Frees_ptr_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetPresentationPosition( + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetLinearBufferPosition( + _Out_ PULONGLONG Position + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetCurrentWritePosition( + _In_ ULONG Position + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetLastBufferPosition( + _In_ ULONG Position + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCurrentPacket( + _Out_ PULONG CurrentPacket + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetHWLatency( + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSimPeakMeter * + GetPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ BOOL Offload, + _In_opt_ CSimPeakMeter *CircuitPeakmeter + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CStreamEngine(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID + SetFrequency( + _In_ DWORD ToneFrequency + ) + { + PAGED_CODE(); + + m_ToneFrequency = ToneFrequency; + } + +protected: + PVOID m_Packets[MAX_PACKET_COUNT]; + ULONG m_PacketsCount; + ULONG m_PacketSize; + ULONG m_FirstPacketOffset; + WDFTIMER m_NotificationTimer; + ACX_STREAM_STATE m_CurrentState; + ULONG m_CurrentPacket; + ULONGLONG m_Position; + ACXSTREAM m_Stream; + ACXDATAFORMAT m_StreamFormat; + ULONGLONG m_StartTime; + ULONGLONG m_StartPosition; + ULONGLONG m_GlitchAdjust; + LARGE_INTEGER m_PerformanceCounterFrequency; + LARGE_INTEGER m_CurrentPacketStart; + LARGE_INTEGER m_LastPacketStart; + DWORD m_ToneFrequency; + BOOL m_Offload; + CSimPeakMeter m_PeakMeter; + CSimPeakMeter* m_pCircuitPeakmeter; + + static + __drv_maxIRQL(DISPATCH_LEVEL) + _Function_class_(EVT_WDF_TIMER) + VOID s_EvtStreamPassCallback( + _In_ WDFTIMER Timer + ); + + // This is run every time the stream timer fires + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + StreamPassCallback(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ScheduleNextPass(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + UpdatePosition(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + ULONG + GetBytesPerSecond(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ProcessPacket() = 0; +}; + +class CRenderStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ BOOL Offload, + _In_ CSimPeakMeter *CircuitPeakmeter + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CRenderStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetRenderPacket( + _In_ ULONG Packet, + _In_ ULONG Flags, + _In_ ULONG EosPacketLength + ); + +protected: + CSaveData m_SaveData; + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ProcessPacket(); + +}; + +class CCaptureStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CCaptureStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCapturePacket( + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData + ); + +protected: + ToneGenerator m_ToneGenerator; + CWaveReader m_WaveReader; + DWORD m_EnableWaveCapture; + UNICODE_STRING m_HostCaptureFileName; + UNICODE_STRING m_LoopbackCaptureFileName; + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ProcessPacket(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReadRegistrySettings(); +}; + +class CBufferedCaptureStreamEngine : public CCaptureStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CBufferedCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ CKeywordDetector * KeywordDetector + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CBufferedCaptureStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCapturePacket( + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData + ); + +protected: + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ProcessPacket(); + + CKeywordDetector * m_KeywordDetector; +}; + +// Define circuit/stream pin context. +// +typedef struct _STREAM_TIMER_CONTEXT { + CStreamEngine * StreamEngine; +} STREAM_TIMER_CONTEXT, *PSTREAM_TIMER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(STREAM_TIMER_CONTEXT, GetStreamTimerContext) diff --git a/audio/Acx/Samples/Common/ToneGenerator.cpp b/audio/Acx/Samples/Common/ToneGenerator.cpp new file mode 100644 index 00000000..fc30e3b2 --- /dev/null +++ b/audio/Acx/Samples/Common/ToneGenerator.cpp @@ -0,0 +1,297 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + ToneGenerator.cpp + +Abstract: + + Implementation of sine wave generator for ACX driver samples + + +--*/ +#include "private.h" +#include "public.h" +#include <devguid.h> +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "ToneGenerator.h" + +#define TONEGENERATOR_POOLTAG 'rGnT' + +const double TONE_AMPLITUDE = 0.5; // Scalar value, should be between 0.0 - 1.0 +const double TWO_PI = M_PI * 2; + +DWORD g_DisableToneGenerator = 0; // default is to generate tones. + +#define IF_FAILED_JUMP(result, tag) do {if (!NT_SUCCESS(result)) {goto tag;}} while(false) +#define IF_TRUE_JUMP(result, tag) do {if (result) {goto tag;}} while(false) +#define IF_TRUE_ACTION_JUMP(result, action, tag) do {if (result) {action; goto tag;}} while(false) + +// +// Double to short conversion. +// +__drv_maxIRQL(DISPATCH_LEVEL) +short ConvertToShort(double Value) +{ + return (short)(Value * _I16_MAX); +}; + +// +// Double to char conversion. +// +__drv_maxIRQL(DISPATCH_LEVEL) +unsigned char ConvertToUChar(double Value) +{ + const double F_127_5 = 127.5; + return (unsigned char)(Value * F_127_5 + F_127_5); +}; + +// +// Ctor: basic init. +// +_Use_decl_annotations_ +PAGED_CODE_SEG +ToneGenerator::ToneGenerator() +: m_Frequency(0), + m_ChannelCount(0), + m_BitsPerSample(0), + m_SamplesPerSecond(0), + m_Mute(false), + m_PartialFrame(NULL), + m_PartialFrameBytes(0), + m_FrameSize(0) +{ + PAGED_CODE(); + + // Theta (double) and SampleIncrement (double) are init in the Init() method + // after saving the floating point state. +} + +// +// Dtor: free resources. +// +_Use_decl_annotations_ +PAGED_CODE_SEG +ToneGenerator::~ToneGenerator() +{ + PAGED_CODE(); + + if (m_PartialFrame) + { + ExFreePoolWithTag(m_PartialFrame, TONEGENERATOR_POOLTAG); + m_PartialFrame = NULL; + m_PartialFrameBytes = 0; + } +} + +// +// Init a new frame. +// Note: caller will save and restore the floatingpoint state. +// +#pragma warning(push) +// Caller wraps this routine between KeSaveFloatingPointState/KeRestoreFloatingPointState calls. +#pragma warning(disable: 28110) + +_Use_decl_annotations_ +VOID ToneGenerator::InitNewFrame +( + _Out_writes_bytes_(FrameSize) BYTE* Frame, + _In_ DWORD FrameSize +) +{ + double sinValue = TONE_AMPLITUDE * sin( m_Theta ); + + if (FrameSize != (DWORD)m_ChannelCount * m_BitsPerSample/8) + { + ASSERT(FALSE); + RtlZeroMemory(Frame, FrameSize); + return; + } + + for(ULONG i = 0; i < m_ChannelCount; ++i) + { + if (m_BitsPerSample == 8) + { + unsigned char *dataBuffer = reinterpret_cast<unsigned char *>(Frame); + dataBuffer[i] = ConvertToUChar(sinValue); + } + else // 16 bits per sample + { + short *dataBuffer = reinterpret_cast<short *>(Frame); + dataBuffer[i] = ConvertToShort(sinValue); + } + } + + m_Theta += m_SampleIncrement; + if (m_Theta >= TWO_PI) + { + m_Theta -= TWO_PI; + } +} +#pragma warning(pop) + +// +// GenerateSamples() +// +// Generate a sine wave that fits into the specified buffer. +// +// Buffer - Buffer to hold the samples +// BufferLength - Length of the buffer. +// +// Note: this function supports 16bit and 8bit samples only. +// +_Use_decl_annotations_ +void ToneGenerator::GenerateSine +( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ size_t BufferLength +) +{ + NTSTATUS status; + KFLOATING_SAVE saveData; + BYTE * buffer; + size_t length; + size_t copyBytes; + + // if muted, or tone generator disabled via registry, + // we deliver silence. + if (m_Mute || g_DisableToneGenerator) + { + goto ZeroBuffer; + } + + status = KeSaveFloatingPointState(&saveData); + if (!NT_SUCCESS(status)) + { + goto ZeroBuffer; + } + + buffer = Buffer; + length = BufferLength; + + // + // Check if we have any residual frame bytes from the last time. + // + if (m_PartialFrameBytes) + { + ASSERT(m_FrameSize > m_PartialFrameBytes); + DWORD offset = m_FrameSize - m_PartialFrameBytes; + copyBytes = MIN(m_PartialFrameBytes, length); + RtlCopyMemory(buffer, m_PartialFrame + offset, copyBytes); + RtlZeroMemory(m_PartialFrame + offset, copyBytes); + length -= copyBytes; + buffer += copyBytes; + m_PartialFrameBytes = 0; + } + + IF_TRUE_JUMP(length == 0, Done); + + // + // Copy all the aligned frames. + // + + size_t frames = length/m_FrameSize; + + for (size_t i = 0; i < frames; ++i) + { + InitNewFrame(buffer, m_FrameSize); + buffer += m_FrameSize; + length -= m_FrameSize; + } + + IF_TRUE_JUMP(length == 0, Done); + + // + // Copy any partial frame at the end. + // + ASSERT(m_FrameSize > length); + InitNewFrame(m_PartialFrame, m_FrameSize); + RtlCopyMemory(buffer, m_PartialFrame, length); + RtlZeroMemory(m_PartialFrame, length); + m_PartialFrameBytes = m_FrameSize - (DWORD)length; + +Done: + KeRestoreFloatingPointState(&saveData); + return; + +ZeroBuffer: + RtlZeroMemory(Buffer, BufferLength); + return; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS ToneGenerator::Init +( + _In_ DWORD ToneFrequency, + _In_ PWAVEFORMATEXTENSIBLE WfExt +) +{ + NTSTATUS status = STATUS_SUCCESS; + KFLOATING_SAVE saveData; + + PAGED_CODE(); + + // + // This sample supports PCM 16bit formats only. + // + if ((WfExt->Format.wFormatTag != WAVE_FORMAT_PCM && + !(WfExt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && + IsEqualGUIDAligned(WfExt->SubFormat, KSDATAFORMAT_SUBTYPE_PCM))) || + (WfExt->Format.wBitsPerSample != 16 && + WfExt->Format.wBitsPerSample != 8)) + { + status = STATUS_NOT_SUPPORTED; + } + IF_FAILED_JUMP(status, Done); + + // + // Save floating state (just in case). + // + status = KeSaveFloatingPointState(&saveData); + IF_FAILED_JUMP(status, Done); + + // + // Basic init. + // + RtlZeroMemory(&m_Theta, sizeof(m_Theta)); + m_Frequency = ToneFrequency; + m_ChannelCount = WfExt->Format.nChannels; // # channels. + m_BitsPerSample = WfExt->Format.wBitsPerSample; // bits per sample. + m_SamplesPerSecond = WfExt->Format.nSamplesPerSec; // samples per sec. + m_Mute = false; + m_SampleIncrement = (m_Frequency * TWO_PI) / (double)m_SamplesPerSecond; + m_FrameSize = (DWORD)m_ChannelCount * m_BitsPerSample/8; + ASSERT(m_FrameSize == WfExt->Format.nBlockAlign); + + // + // Restore floating state. + // + KeRestoreFloatingPointState(&saveData); + + // + // Allocate a buffer to hold a partial frame. + // + m_PartialFrame = (BYTE*)ExAllocatePool2( + POOL_FLAG_NON_PAGED, + m_FrameSize, + TONEGENERATOR_POOLTAG); + + IF_TRUE_ACTION_JUMP(m_PartialFrame == NULL, status = STATUS_INSUFFICIENT_RESOURCES, Done); + + status = STATUS_SUCCESS; + +Done: + return status; +} + + diff --git a/audio/Acx/Samples/Common/ToneGenerator.h b/audio/Acx/Samples/Common/ToneGenerator.h new file mode 100644 index 00000000..9de138f8 --- /dev/null +++ b/audio/Acx/Samples/Common/ToneGenerator.h @@ -0,0 +1,88 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + ToneGenerator.h + +Abstract: + + Declaration of sine wave generator for ACX driver samples. + + +--*/ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> +#include <limits.h> + +class ToneGenerator +{ +public: + DWORD m_Frequency; + WORD m_ChannelCount; + WORD m_BitsPerSample; + DWORD m_SamplesPerSecond; + double m_Theta; + double m_SampleIncrement; + bool m_Mute; + BYTE* m_PartialFrame; + DWORD m_PartialFrameBytes; + DWORD m_FrameSize; + +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ToneGenerator(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~ToneGenerator(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Init + ( + _In_ DWORD ToneFrequency, + _In_ PWAVEFORMATEXTENSIBLE WfExt + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + GenerateSine + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ size_t BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID + SetMute + ( + _In_ bool Value + ) + { + PAGED_CODE(); + + m_Mute = Value; + } + +private: + __drv_maxIRQL(DISPATCH_LEVEL) + VOID InitNewFrame + ( + _Out_writes_bytes_(FrameSize) BYTE* Frame, + _In_ DWORD FrameSize + ); +}; + + diff --git a/audio/Acx/Samples/Common/Trace_macros.h b/audio/Acx/Samples/Common/Trace_macros.h new file mode 100644 index 00000000..5291b391 --- /dev/null +++ b/audio/Acx/Samples/Common/Trace_macros.h @@ -0,0 +1,470 @@ +#pragma once + +#include <stdarg.h> // for va_start, etc. + +#pragma region Tracing level definitions + +#if !defined(FAILED_NTSTATUS) +#define FAILED_NTSTATUS(status) (((NTSTATUS)(status)) < 0) +#endif + +#if !defined(SUCCEEDED_NTSTATUS) +#define SUCCEEDED_NTSTATUS(status) (((NTSTATUS)(status)) >= 0) +#endif + +//! Define shorter versions of the ETW trace levels +#define LEVEL_CRITICAL TRACE_LEVEL_CRITICAL +#define LEVEL_ERROR TRACE_LEVEL_ERROR +#define LEVEL_WARNING TRACE_LEVEL_WARNING +#define LEVEL_INFO TRACE_LEVEL_INFORMATION +#define LEVEL_VERBOSE TRACE_LEVEL_VERBOSE + +//! This is a special LEVEL that changes the trace macro level from ERROR to VERBOSE +//! depending on whether the return value passed to the macro was non-zero or zero, +//! respectively. +#define LEVEL_COND 0xFF +#pragma endregion + +//! Logger and Enabled that supports both level and flag. +//! \link https://msdn.microsoft.com/en-us/library/windows/hardware/ff542492(v=vs.85).aspx +#define WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) WPP_LEVEL_LOGGER(FLAGS) +#define WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) (WPP_LEVEL_ENABLED(FLAGS) && (WPP_CONTROL(WPP_BIT_ ## FLAGS).Level >= LEVEL)) + +//! This macro is to be used by the WPP custom macros below that want to do conditional +//! logging based on return value. If LEVEL_VERBOSE is specified when calling a macro that +//! uses this, the level will be set to LEVEL_INFO if return code is 0 or +//! LEVEL_ERROR if the return code is not 0. This can be called in any PRE macro. +//! +//! The "LEVEL == LEVEL_COND" check generates a compiler warning that the "conditional +//! expression is constant" so we explicitly disable that. +#define WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) \ + BOOL bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS); \ + __pragma(warning(push)) \ + __pragma(warning(disable: 4127)) \ + if (LEVEL == LEVEL_COND) \ + { \ + if (SUCCEEDED(HR)) \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_VERBOSE, FLAGS); \ + } \ + else \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_ERROR, FLAGS); \ + } \ + } \ + __pragma(warning(pop)) + +#define WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) \ + BOOLEAN bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS); \ + __pragma(warning(push)) \ + __pragma(warning(disable: 4127)) \ + if (LEVEL == LEVEL_COND) \ + { \ + if (SUCCEEDED_NTSTATUS(STATUS)) \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_VERBOSE, FLAGS); \ + } \ + else \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_ERROR, FLAGS); \ + } \ + } \ + __pragma(warning(pop)) + + +#define WPP_LEVEL_FLAGS_IFRLOG_ENABLED(LEVEL, FLAGS, IFRLOG) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_LOGGER(LEVEL, FLAGS, IFRLOG) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) +#define WPP_LEVEL_IFRLOG_FLAGS_ENABLED(LEVEL, IFRLOG, FLAGS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_IFRLOG_FLAGS_LOGGER(LEVEL, IFRLOG, FLAGS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_HR_PRE(LEVEL, FLAGS, HR) { WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) +#define WPP_LEVEL_FLAGS_HR_POST(LEVEL, FLAGS, HR) ;} +#define WPP_LEVEL_FLAGS_HR_ENABLED(LEVEL, FLAGS, HR) bEnabled +#define WPP_LEVEL_FLAGS_HR_LOGGER(LEVEL, FLAGS, HR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETVAL_ENABLED(LEVEL, FLAGS, RETVAL) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETVAL_LOGGER(LEVEL, FLAGS, RETVAL) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_FI_ENABLED(LEVEL, FLAGS, FI) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_FI_LOGGER(LEVEL, FLAGS, FI) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_STATUS_PRE(LEVEL, FLAGS, STATUS) { WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) +#define WPP_LEVEL_FLAGS_STATUS_POST(LEVEL, FLAGS, STATUS) ;} +#define WPP_LEVEL_FLAGS_STATUS_ENABLED(LEVEL, FLAGS, STATUS) bEnabled +#define WPP_LEVEL_FLAGS_STATUS_LOGGER(LEVEL, FLAGS, STATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_PRE(LEVEL, FLAGS, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_POST(LEVEL, FLAGS, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_ENABLED(LEVEL, FLAGS, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_LOGGER(LEVEL, FLAGS, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_PRE(LEVEL, FLAGS, IFRLOG, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_POST(LEVEL, FLAGS, IFRLOG, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_PRE(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) do {\ +NTSTATUS __statusRet = (RETSTATUS);\ +if(__statusRet == ALLOWEDSTATUS)\ +{\ + __statusRet = STATUS_SUCCESS;\ +}\ +if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_POST(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETPTR_PRE(LEVEL, FLAGS, RETPTR) do { if ((RETPTR) == nullptr) { +#define WPP_LEVEL_FLAGS_RETPTR_POST(LEVEL, FLAGS, RETPTR) ; return STATUS_INSUFFICIENT_RESOURCES; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETPTR_ENABLED(LEVEL, FLAGS, RETPTR) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETPTR_LOGGER(LEVEL, FLAGS, RETPTR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_PRE(LEVEL, FLAGS, RETSTATUS, RETPTR) do { NTSTATUS __statusRet = (RETSTATUS); if ((RETPTR) == nullptr) { +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_POST(LEVEL, FLAGS, RETSTATUS, RETPTR) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_ENABLED(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_LOGGER(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_PRE(LEVEL, FLAGS, RETSTATUS, POSCOND) do { NTSTATUS __statusRet = (RETSTATUS); if ((POSCOND)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_POST(LEVEL, FLAGS, RETSTATUS, POSCOND) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_ENABLED(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_LOGGER(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_PRE(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if ((POSCOND)) { +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_POST(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_PRE(LEVEL, FLAGS, RETSTATUS, NEGCOND) do { NTSTATUS __statusRet = (RETSTATUS); if (!(NEGCOND)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_POST(LEVEL, FLAGS, RETSTATUS, NEGCOND) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_ENABLED(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_LOGGER(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#pragma region IFR Enablement Macros + +// Opt-in to a WPP recorder feature that enables independent evaluation of conditions to decide if a +// message needs to be sent to the recorder, an enabled session, or both. +#define ENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER 1 + +// Logger/Enabled macros used to decide if a message that is being sent to a custom recorder should +// also go to an enabled session. These do not depend on the custom recorder itself, so just +// delegate to the default. +#define WPP_IFRLOG_LEVEL_FLAGS_LOGGER(IFRLOG, LEVEL, FLAGS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) +#define WPP_IFRLOG_LEVEL_FLAGS_ENABLED(IFRLOG, LEVEL, FLAGS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) + +#define WPP_RECORDER_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) \ + ((LEVEL == LEVEL_COND) ? \ + (FAILED(HR) ? \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_ERROR, FLAGS) : WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_VERBOSE, FLAGS)) : \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS)) + +#define WPP_RECORDER_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) \ + ((LEVEL == LEVEL_COND) ? \ + (FAILED_NTSTATUS(STATUS) ? \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_ERROR, FLAGS) : WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_VERBOSE, FLAGS)) : \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS)) + +#define WPP_RECORDER_LEVEL_FLAGS_HR_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_HR_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETVAL_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETVAL_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_FI_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_FI_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_STATUS_ARGS(LEVEL, FLAGS, STATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_STATUS_FILTER(LEVEL, FLAGS, STATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_ARGS(LEVEL, FLAGS, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_FILTER(LEVEL, FLAGS, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETPTR_ARGS(LEVEL, FLAGS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETPTR_FILTER(LEVEL, FLAGS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_RETPTR_ARGS(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_RETPTR_FILTER(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_POSCOND_ARGS(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_POSCOND_FILTER(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_NEGCOND_ARGS(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_NEGCOND_FILTER(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) +#pragma endregion + +#pragma region Custom tracing macros + +// begin_wpp config +// USEPREFIX(DrvLogCritical, "%!STDPREFIX!CRIT: "); +// USEPREFIX(DrvLogError, "%!STDPREFIX!ERROR: "); +// USEPREFIX(DrvLogWarning, "%!STDPREFIX!WARN: "); +// USEPREFIX(DrvLogInfo, "%!STDPREFIX!INFO: "); +// USEPREFIX(DrvLogVerbose, "%!STDPREFIX!VERB: "); +// USEPREFIX(DrvLogEnter, "%!STDPREFIX!ENTER"); +// USEPREFIX(DrvLogExit, "%!STDPREFIX!EXIT"); +// end_wpp + +// begin_wpp config +// FUNC DrvLogCritical{LEVEL=TRACE_LEVEL_CRITICAL}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogError{LEVEL=TRACE_LEVEL_ERROR}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogWarning{LEVEL=TRACE_LEVEL_WARNING}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogInfo{LEVEL=TRACE_LEVEL_INFORMATION}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogEnter{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=FLAG_FUNCTION}(IFRLOG,...); +// FUNC DrvLogVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogExit{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=FLAG_FUNCTION}(IFRLOG,...); +// end_wpp + + +#ifdef __INTELLISENSE__ +#define FLAG_DEVICE_ALL 0x01 +#define FLAG_FUNCTION 0x02 +#define FLAG_INFO 0x04 +#define FLAG_PNP 0x08 +#define FLAG_POWER 0x10 +#define FLAG_STREAM 0x20 +#define FLAG_INIT 0x40 +#define FLAG_DDI 0x80 +#define FLAG_GENERIC 0x100 +void DrvLogCritical(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogError(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogWarning(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogInfo(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogEnter(void* log, ...); +void DrvLogVerbose(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogExit(void* log, ...); + +void RETURN_IF_FAILED(NTSTATUS status); +void RETURN_NTSTATUS_IF_FAILED(NTSTATUS status); +void RETURN_NTSTATUS_IF_FAILED_MSG(NTSTATUS status, const WCHAR* fmt, ...); +void RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED(NTSTATUS returnStatus, NTSTATUS allowedStatus); +void RETURN_NTSTATUS_IF_NULL_ALLOC(PVOID ptr); +void RETURN_NTSTATUS_IF_NULL(PVOID ptr); +void RETURN_NTSTATUS_IF_TRUE(BOOL condition, NTSTATUS status); +void RETURN_NTSTATUS_IF_TRUE_MSG(BOOL condition, NTSTATUS status, const WCHAR* fmt, ...); +void RETURN_NTSTATUS_IF_FALSE(BOOL condition, NTSTATUS status); +void RETURN_NTSTATUS(NTSTATUS status); +void RETURN_NTSTATUS_MSG(NTSTATUS status, const WCHAR* fmt, ...); +#endif// __INTELLISENSE__ + +//********************************************************* +// MACRO: TRACE_METHOD_LINE +// +// begin_wpp config +// FUNC TRACE_METHOD_LINE(LEVEL, FLAGS, MSG, ...); +// USESUFFIX (TRACE_METHOD_LINE, ", this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_ENTRY +// +// begin_wpp config +// FUNC TRACE_METHOD_ENTRY(LEVEL, FLAGS); +// USESUFFIX (TRACE_METHOD_ENTRY, "Enter, this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT(LEVEL, FLAGS); +// USESUFFIX (TRACE_METHOD_EXIT, "Exit, this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_HR +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_HR(LEVEL, FLAGS, HR); +// USESUFFIX (TRACE_METHOD_EXIT_HR, "Exit, this=0x%p, hr=%!HRESULT!", this, HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_DWORD +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_DWORD(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_METHOD_EXIT_DWORD, "Exit, this=0x%p, ret=0x%08Ix ", this, RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_PTR +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_PTR(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_METHOD_EXIT_PTR,"Exit, this=0x%p, retptr=0x%p", this, RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_STATUS +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_STATUS(LEVEL, FLAGS, STATUS); +// USESUFFIX (TRACE_METHOD_EXIT_STATUS, "Exit, this=0x%p, status=%!STATUS!", this, STATUS); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_ENTRY +// +// begin_wpp config +// FUNC TRACE_FUNCTION_ENTRY(LEVEL, FLAGS); +// USESUFFIX (TRACE_FUNCTION_ENTRY, "Enter"); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT(LEVEL, FLAGS); +// USESUFFIX (TRACE_FUNCTION_EXIT, "Exit"); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_HR +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_HR(LEVEL, FLAGS, HR); +// USESUFFIX (TRACE_FUNCTION_EXIT_HR, "Exit, hr=%!HRESULT!", HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_DWORD +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_DWORD(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_FUNCTION_EXIT_DWORD, "Exit, ret=0x%08Ix", RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_PTR +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_PTR(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_FUNCTION_EXIT_PTR, "Exit, retptr=0x%p", RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_STATUS +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_STATUS(LEVEL, FLAGS, STATUS); +// USESUFFIX (TRACE_FUNCTION_EXIT_STATUS, "Exit, status=%!STATUS!", STATUS); +// end_wpp + +//********************************************************* +// MACRO: TRACE_LINE +// +// begin_wpp config +// FUNC TRACE_LINE(LEVEL, FLAGS, MSG, ...); +// end_wpp + +//********************************************************* +// MACRO: TRACE_HRESULT +// +// begin_wpp config +// FUNC TRACE_HRESULT(LEVEL, FLAGS, HR, MSG, ...); +// USESUFFIX (TRACE_HRESULT, ", ret=%!HRESULT!", HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FAILURE_INFO (WIL FailureInfo logging) +// see: https://github.com/microsoft/wil/blob/master/include/wil/result_macros.h +// +// begin_wpp config +// FUNC TRACE_FAILURE_INFO(LEVEL, FLAGS, FI); +// USESUFFIX(TRACE_FAILURE_INFO, " [%04X] '%ws', hr=%!HRESULT! ['%s' (%u)]", FI.threadId, FI.pszMessage, FI.hr, FI.pszFile, FI.uLineNumber); +// end_wpp + +// MACRO: RETURN_IF_FAILED +// +// begin_wpp config +// FUNC RETURN_IF_FAILED{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS); +// USEPREFIX(RETURN_IF_FAILED, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_IF_FAILED, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + + +// MACRO: RETURN_NTSTATUS_IF_FAILED +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FAILED_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS, MSG, ...); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED_MSG, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED_MSG, " - status=%!STATUS!",__statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS, ALLOWEDSTATUS); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_NULL_ALLOC +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_NULL_ALLOC{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETPTR); +// USESUFFIX(RETURN_NTSTATUS_IF_NULL, "status=STATUS_INSUFFICIENT_RESOURCES"); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_NULL +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_NULL{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETSTATUS, RETPTR); +// USESUFFIX(RETURN_NTSTATUS_IF_NULL, "status=%!STATUS!", __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_TRUE +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_TRUE{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(POSCOND, RETSTATUS); +// USESUFFIX(RETURN_NTSTATUS_IF_TRUE, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_TRUE_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_TRUE_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(POSCOND, RETSTATUS, MSG, ...); +// USESUFFIX(RETURN_NTSTATUS_IF_TRUE_MSG, " - status=%!STATUS!", __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FALSE +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FALSE{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETSTATUS, NEGCOND); +// USESUFFIX(RETURN_NTSTATUS_IF_FALSE, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS +// +// begin_wpp config +// FUNC RETURN_NTSTATUS{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS); +// USESUFFIX(RETURN_NTSTATUS, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS, MSG, ...); +// USESUFFIX(RETURN_NTSTATUS_MSG, " - status=%!STATUS!", __statusRet); +// end_wpp + +#define W32 +#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings + +#pragma endregion diff --git a/audio/Acx/Samples/Common/WaveReader.cpp b/audio/Acx/Samples/Common/WaveReader.cpp new file mode 100644 index 00000000..4fa6eae9 --- /dev/null +++ b/audio/Acx/Samples/Common/WaveReader.cpp @@ -0,0 +1,769 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + WaveReader.cpp + +Abstract: + Implementation of wave file reader for ACX sample drivers. + + To read data from disk, this class maintains a circular data buffer. This buffer is segmented into multiple chunks of + big buffer (Though we only need two, so it is set to two now). Initially we fill first two chunks and once a chunk gets emptied + by OS, we schedule a workitem to fill the next available chunk. + + +--*/ + +#pragma warning (disable : 4127) +#pragma warning (disable : 26165) + +#include "private.h" +#include <devguid.h> +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "WaveReader.h" + +#define FILE_NAME_BUFFER_TAG 'WRT1' +#define WAVE_DATA_BUFFER_TAG 'WRT2' +#define WORK_ITEM_BUFFER_TAG 'WRT3' + +#define MAX_READ_WORKER_ITEM_COUNT 15 + +#define IF_FAILED_JUMP(result, tag) do {if (!NT_SUCCESS(result)) {goto tag;}} while(false) +#define IF_TRUE_JUMP(result, tag) do {if (result) {goto tag;}} while(false) +#define IF_TRUE_ACTION_JUMP(result, action, tag) do {if (result) {action; goto tag;}} while(false) + +PREADWORKER_PARAM CWaveReader::m_pWorkItems = NULL; +PDEVICE_OBJECT CWaveReader::m_pDeviceObject = NULL; + + +/*++ + +Routine Description: + Ctor: basic init. + +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +CWaveReader::CWaveReader() +: m_ChannelCount(0), + m_BitsPerSample(0), + m_SamplesPerSecond(0), + m_Mute(false), + m_FileHandle(NULL) +{ + PAGED_CODE(); + m_WaveDataQueue.pWavData = NULL; + KeInitializeMutex(&m_FileSync, 0); +} + +/*++ + +Routine Description: + Dtor: free resources. + +--*/ +_Use_decl_annotations_ +PAGED_CODE_SEG +CWaveReader::~CWaveReader() +{ + PAGED_CODE(); + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + if (m_WaveDataQueue.pWavData != NULL) + { + ExFreePoolWithTag(m_WaveDataQueue.pWavData, WAVE_DATA_BUFFER_TAG); + m_WaveDataQueue.pWavData = NULL; + } + + FileClose(); + KeReleaseMutex(&m_FileSync, FALSE); + } + +} + +/*++ + +Routine Description: + - Initializing the workitems. These workitems will be scheduled asynchronously by the OS. + - When these work items will be scheduled the wave file will be read and the data + - will be put inside the big chunks. + +Arguments: + Device object + +Return Value: + NT status code. + +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::InitializeWorkItems(_In_ PDEVICE_OBJECT DeviceObject) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_pWorkItems != NULL) + { + return ntStatus; + } + + m_pWorkItems = (PREADWORKER_PARAM) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + sizeof(READWORKER_PARAM) * MAX_READ_WORKER_ITEM_COUNT, + 'RDPT' + ); + if (m_pWorkItems) + { + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + + m_pWorkItems[i].WorkItem = IoAllocateWorkItem(DeviceObject); + if (m_pWorkItems[i].WorkItem == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + KeInitializeEvent + ( + &m_pWorkItems[i].EventDone, + NotificationEvent, + TRUE + ); + } + } + else + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + return ntStatus; +} + +/*++ + +Routine Description: +- Wait for all the scheduled workitems to finish. + +--*/ + + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void CWaveReader::WaitAllWorkItems() +{ + PAGED_CODE(); + + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + KeWaitForSingleObject + ( + &(m_pWorkItems[i].EventDone), + Executive, + KernelMode, + FALSE, + NULL + ); + } +} + +/*++ + +Routine Description: + - Deallocating the workitems. + +--*/ + + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID CWaveReader::DestroyWorkItems() +{ + PAGED_CODE(); + + if (m_pWorkItems) + { + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + if (m_pWorkItems[i].WorkItem != NULL) + { + IoFreeWorkItem(m_pWorkItems[i].WorkItem); + m_pWorkItems[i].WorkItem = NULL; + } + } + ExFreePoolWithTag(m_pWorkItems, WORK_ITEM_BUFFER_TAG); + m_pWorkItems = NULL; + } +} + +/*++ + +Routine Description: + - Get a free work item to schedule a file read operation. + +--*/ +_Use_decl_annotations_ +PREADWORKER_PARAM CWaveReader::GetNewWorkItem() +{ + LARGE_INTEGER timeOut = { 0 }; + NTSTATUS ntStatus; + + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + ntStatus = + KeWaitForSingleObject + ( + &m_pWorkItems[i].EventDone, + Executive, + KernelMode, + FALSE, + &timeOut + ); + if (STATUS_SUCCESS == ntStatus) + { + if (m_pWorkItems[i].WorkItem) + return &(m_pWorkItems[i]); + else + return NULL; + } + } + + return NULL; +} + +/*++ +Routine Description: +- This routine will enqueue a workitem for reading wave file and putting +- the data into the chunk buffer. + +Arguments: + Chunk descriptor for the chunk to be filled. +--*/ + +_Use_decl_annotations_ +VOID CWaveReader::ReadWavChunk(PCHUNKDESCRIPTOR pChunkDescriptor) +{ + PREADWORKER_PARAM pParam = NULL; + + pParam = GetNewWorkItem(); + if (pParam) + { + pParam->PtrWaveReader = this; + pParam->PtrChunkDescriptor = pChunkDescriptor; + KeResetEvent(&pParam->EventDone); + IoQueueWorkItem(pParam->WorkItem, ReadFrameWorkerCallback, + DelayedWorkQueue, (PVOID)pParam); + } +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; +/* +Routine Description: +- This routine will be called by the OS. It will fill the chunk buffer, defined by the chunk descriptor +- If end of file is reached it will mark the end of file as true. + +Arguments: + pDeviceObject - Device object + Context - pointer to reader worker params +*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID ReadFrameWorkerCallback +( + _In_ PDEVICE_OBJECT pDeviceObject, + _In_opt_ PVOID Context +) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(pDeviceObject); + pWaveReader pWavRd; + PREADWORKER_PARAM pParam = (PREADWORKER_PARAM)Context; + + if (NULL == pParam) + { + // This is completely unexpected, assert here. + // + ASSERT(pParam); + goto exit; + } + + pWavRd = pParam->PtrWaveReader; + + if (pWavRd == NULL) + { + goto exit; + } + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &pWavRd->m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + + NTSTATUS ntStatus = STATUS_SUCCESS; + + ASSERT(Context); + + IO_STATUS_BLOCK ioStatusBlock; + + if (pParam->WorkItem) + { + if (pWavRd->m_WaveDataQueue.bEofReached || pWavRd->m_WaveDataQueue.pWavData == NULL) + { + KeReleaseMutex(&pWavRd->m_FileSync, FALSE); + goto exit; + } + + if (pParam->PtrChunkDescriptor->pStartAddress != NULL) + { + ntStatus = ZwReadFile(pWavRd->m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + pParam->PtrChunkDescriptor->pStartAddress, + pParam->PtrChunkDescriptor->ulChunkLength, + NULL, + NULL); + + pParam->PtrChunkDescriptor->bIsChunkEmpty = false; + + if (ioStatusBlock.Information != pParam->PtrChunkDescriptor->ulChunkLength) + { + pWavRd->m_WaveDataQueue.bEofReached = true; + } + } + } + + KeReleaseMutex(&pWavRd->m_FileSync, FALSE); + } + +exit: + KeSetEvent(&pParam->EventDone, 0, FALSE); +} + +/*++ + +Routine Description: +- If all the chunks are empty this resturn true. + +--*/ + +_Use_decl_annotations_ +bool CWaveReader::IsAllChunkEmpty() +{ + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + if (!m_WaveDataQueue.sChunkDescriptor[i].bIsChunkEmpty) + { + return false; + } + } + return true; +} + +/*++ +Routine Description: + - This routine does the actual copy of data from the chunk buffer to the buffer provided by OS. + - If it empties the current chunk buffer, then it sets it state to empty and then enqueue a workitem + - to read data from the wave file and put it to the next available chunk buffer. + +Arguments: + Buffer - Pointer to the OS buffer + BufferLength - Length of the data to be filled (in bytes) + +--*/ +_Use_decl_annotations_ +VOID CWaveReader::CopyDataFromRingBuffer +( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength +) +{ + if (IsAllChunkEmpty()) + { + RtlZeroMemory(Buffer, BufferLength); + } + else + { + ULONG prevChunk = (m_WaveDataQueue.ulReadPtr*NUM_OF_CHUNK_FOR_FILE_READ )/ m_WaveDataQueue.ulLength; + + ///////////////// + BYTE *currentBuf = Buffer; + ULONG length = BufferLength; + while (length > 0) + { + ULONG runWrite = min(length, m_WaveDataQueue.ulLength - m_WaveDataQueue.ulReadPtr); + + // Copy the wave buffer data to OS buffer + RtlCopyMemory(currentBuf, m_WaveDataQueue.pWavData + m_WaveDataQueue.ulReadPtr, runWrite); + // Zero out the wave buffer, so that if wave end of file is reached we should copy only zeros + RtlZeroMemory(m_WaveDataQueue.pWavData + m_WaveDataQueue.ulReadPtr, runWrite); + // Update the read pointer + m_WaveDataQueue.ulReadPtr = (m_WaveDataQueue.ulReadPtr + runWrite) % m_WaveDataQueue.ulLength; + currentBuf += runWrite; + length = length - runWrite; + } + + ULONG curChunk = (m_WaveDataQueue.ulReadPtr*NUM_OF_CHUNK_FOR_FILE_READ) / m_WaveDataQueue.ulLength; + + if (curChunk != prevChunk) + { + m_WaveDataQueue.currentExecutedChunk++; + // Schedule a workitem to read data from the wave file + ULONG chunkNo = m_WaveDataQueue.currentExecutedChunk % NUM_OF_CHUNK_FOR_FILE_READ; + m_WaveDataQueue.sChunkDescriptor[chunkNo].bIsChunkEmpty = true; + if (!m_WaveDataQueue.bEofReached) + { + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[chunkNo]); + } + } + } +} + +/*++ +Routine Description: + - Just a high level read buffer call. + + Arguments: + Buffer - Pointer to the OS buffer + BufferLength - Length of the data to be filled (in bytes) +--*/ + +_Use_decl_annotations_ +VOID CWaveReader::ReadWaveData +( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength +) +{ + if (m_Mute) + { + RtlZeroMemory(Buffer, BufferLength); + } + else + { + CopyDataFromRingBuffer(Buffer, BufferLength); + } +} + +/*++ +Routine Description: +- initialization for the wavereader member variables, +- Allocating memory for the 1 second buffer +- Preread the one second buffer data, so that when OS comes to read the data we have it available in the memory. + +Arguments: + WfExt - Format which should be used for capture + fileNameString - name of the file to be read + +Return: + NTStatus +--*/ +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::Init +( + _In_ PWAVEFORMATEXTENSIBLE WfExt, + _In_ PUNICODE_STRING puiFileName +) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + KFLOATING_SAVE saveData; + + // Save floating state (just in case). + ntStatus = KeSaveFloatingPointState(&saveData); + if (!NT_SUCCESS(ntStatus)) + { + return ntStatus; + } + + // + // This sample supports PCM 16bit formats only. + // + if ((WfExt->Format.wFormatTag != WAVE_FORMAT_PCM && + !(WfExt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && + IsEqualGUIDAligned(WfExt->SubFormat, KSDATAFORMAT_SUBTYPE_PCM))) || + (WfExt->Format.wBitsPerSample != 16 && + WfExt->Format.wBitsPerSample != 8)) + { + ntStatus = STATUS_NOT_SUPPORTED; + } + IF_FAILED_JUMP(ntStatus, Done); + + // Basic init. + m_ChannelCount = WfExt->Format.nChannels; // # channels. + m_BitsPerSample = WfExt->Format.wBitsPerSample; // bits per sample. + m_SamplesPerSecond = WfExt->Format.nSamplesPerSec; // samples per sec. + m_Mute = false; + + // Wave data queue initialization + m_WaveDataQueue.ulLength = WfExt->Format.nAvgBytesPerSec; + m_WaveDataQueue.bEofReached = false; + m_WaveDataQueue.ulReadPtr = 0; + + // Mark all the chunk empty + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + m_WaveDataQueue.sChunkDescriptor[i].bIsChunkEmpty = true; + } + + ntStatus = OpenWaveFile(puiFileName); + IF_FAILED_JUMP(ntStatus, Done); + + ntStatus = AllocateBigBuffer(); + IF_FAILED_JUMP(ntStatus, Done); + + ntStatus = ReadHeaderAndFillBuffer(); + +Done: + (void)KeRestoreFloatingPointState(&saveData); + return ntStatus; +} + +/*++ +Routine Description: + This function read the wave header file and compare the header info with the + stream info. Currently we are using only number of channel, sampling frequency + and bits per sample as the primary parameters for the wave file to compare against + stream params. If the params don't match we return success but streams zeros. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::ReadHeaderAndFillBuffer() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + ntStatus = FileReadHeader(); + + if(NT_SUCCESS(ntStatus)) + { + if (m_WaveHeader.numChannels != m_ChannelCount || + m_WaveHeader.bitsPerSample != m_BitsPerSample || + m_WaveHeader.sampleRate != m_SamplesPerSecond) + { + // If the wave file format don't match we wont treat this as error + // and we will stream zeros. So we return from here and will not read the + // wave file and wont fill the buffers. + return STATUS_SUCCESS; + } + } + + if (NT_SUCCESS(ntStatus)) + { + // If the wave file format is same as the stream format we will stream the data + // else we will just stream zeros. + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[0]); // Fill the first chunk + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[1]); // Fill the second chunk + // Set the current executed chunk to 1. Once OS finishs the data for the first chunk + // use the currentExecutedChunk to find the next chunk and schedule a workitem to fill the + // data into the next chunk + m_WaveDataQueue.currentExecutedChunk = 1; + } + + return ntStatus; +} + +/*++ +Routine Description: + This function allocates 1 second buffer. + Segments the buffer into multiple (currently two) chunks. Assigns the start pointer and length + for each chunk. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::AllocateBigBuffer() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + m_WaveDataQueue.pWavData = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + m_WaveDataQueue.ulLength, + WAVE_DATA_BUFFER_TAG + ); + if (!m_WaveDataQueue.pWavData) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + ULONG chunklLength = m_WaveDataQueue.ulLength / NUM_OF_CHUNK_FOR_FILE_READ; + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + m_WaveDataQueue.sChunkDescriptor[i].pStartAddress = m_WaveDataQueue.pWavData + chunklLength*i; + m_WaveDataQueue.sChunkDescriptor[i].ulChunkLength = chunklLength; + } + } + return ntStatus; +} + +/*++ +Routine Description: + This function opens wave file. + +Arguments: + fileNameString - Name of the wave file + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::OpenWaveFile(PUNICODE_STRING puiFileName) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (NT_SUCCESS(ntStatus) && puiFileName->Buffer != NULL) + { + // Create data file. + InitializeObjectAttributes + ( + &m_objectAttributes, + puiFileName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL + ); + + // Open Wave File + ntStatus = FileOpen(); + } + + return ntStatus; +} + +/*++ +Routine Description: + This function closes wave file handle. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileClose() +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_FileHandle) + { + ntStatus = ZwClose(m_FileHandle); + m_FileHandle = NULL; + } + + return ntStatus; +} + +/*++ +Routine Description: + Reads the wave file file header information + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileReadHeader() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STATUS_BLOCK ioStatusBlock; + + + ntStatus = ZwReadFile(m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + &m_WaveHeader, + sizeof(WAVEHEADER), + NULL, + NULL); + + return ntStatus; +} + +/*++ +Routine Description: + This function opens wave file. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileOpen() +{ + + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STATUS_BLOCK ioStatusBlock; + + if (!m_FileHandle) + { + ntStatus = + ZwCreateFile + ( + &m_FileHandle, + GENERIC_READ, + &m_objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0 + ); + } + + return ntStatus; +} + diff --git a/audio/Acx/Samples/Common/WaveReader.h b/audio/Acx/Samples/Common/WaveReader.h new file mode 100644 index 00000000..08516be7 --- /dev/null +++ b/audio/Acx/Samples/Common/WaveReader.h @@ -0,0 +1,196 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + WaveReader.h + +Abstract: + + Declaration of wave reader for ACX sample drivers. + + +--*/ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> +#include <limits.h> + +#define NUM_OF_CHUNK_FOR_FILE_READ 2 + +class CWaveReader; + +// Wave header structure decleration +typedef CWaveReader *pWaveReader; +typedef struct _WAVEHEADER +{ + BYTE chunkId[4]; + ULONG chunkSize; + BYTE format[4]; + BYTE subChunkId[4]; + ULONG subChunkSize; + WORD audioFormat; + WORD numChannels; + ULONG sampleRate; + ULONG bytesPerSecond; + WORD blockAlign; + WORD bitsPerSample; + BYTE dataChunkId[4]; + ULONG dataSize; +}WAVEHEADER; + +typedef struct _CHUNKDESCRIPTOR +{ + PBYTE pStartAddress; // Starting address of the chunk + ULONG ulChunkLength; // Length of the chunk + bool bIsChunkEmpty; // If the chunk is empty +}CHUNKDESCRIPTOR; +typedef CHUNKDESCRIPTOR *PCHUNKDESCRIPTOR; + +/* + The idea here is to allocate one second long worth of buffer and divide it into NUM_OF_CHUNK_FOR_FILE_READ chunks. + In one file read operation we read and fill one chunk data . The chunk will be emptied every 10 ms by OS. + Once the OS empties one chunk data we schedule a workitem to read and fill next available chunk. +*/ + +typedef struct _WAVEDATAQUEUE +{ + PBYTE pWavData; // Pointer to the temporary buffer for reading one second worth of data from wave file + ULONG ulLength; // length of pWavData in bytes + ULONG ulReadPtr; // current reading position in pWavData in bytes + bool bEofReached; // This will be set once the eof is reached. + WORD currentExecutedChunk; + CHUNKDESCRIPTOR sChunkDescriptor[NUM_OF_CHUNK_FOR_FILE_READ]; +}WAVEDATAQUEUE; +typedef WAVEDATAQUEUE *PWAVEDATAQUEUE; + +// Parameter to workitem. +#include <pshpack1.h> +typedef struct _READWORKER_PARAM { + PIO_WORKITEM WorkItem; // Pointer to the workitem + KEVENT EventDone; // Used for synchronizing a workitem for scheduling. + pWaveReader PtrWaveReader; // pointer to the wavereader class. + PCHUNKDESCRIPTOR PtrChunkDescriptor; // chunk descriptor for the chunk, which needs to be filled after file read +} READWORKER_PARAM; +typedef READWORKER_PARAM *PREADWORKER_PARAM; +#include <poppack.h> + +__drv_maxIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; + +// Wave Reader class + +class CWaveReader +{ + +public: + HANDLE m_FileHandle; // Wave File handle. + WORD m_ChannelCount; // Number of Channels for the stream during stream init + WORD m_BitsPerSample; // Number of Bits per sample for the stream during stream init + DWORD m_SamplesPerSecond; // Number of Sample per second for the stream during stream init + bool m_Mute; // Capture Zero buffer if mute + OBJECT_ATTRIBUTES m_objectAttributes; // Used for opening file. + WAVEDATAQUEUE m_WaveDataQueue; // Big buffer data object and its current state + KMUTEX m_FileSync; // Synchronizes file access + WAVEHEADER m_WaveHeader; + +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CWaveReader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CWaveReader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS Init + ( + _In_ PWAVEFORMATEXTENSIBLE WfExt, + _In_ PUNICODE_STRING puiFileName + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + VOID ReadWaveData + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID SetMute(_In_ bool Value) + { + PAGED_CODE(); + + m_Mute = Value; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void WaitAllWorkItems(); + + // Static allocation totally related to the workitems for reading data from wavefile and putting it to chunk buffer + static PDEVICE_OBJECT m_pDeviceObject; + static PREADWORKER_PARAM m_pWorkItems; + PAGED_CODE_SEG + static NTSTATUS InitializeWorkItems(_In_ PDEVICE_OBJECT DeviceObject); + + __drv_maxIRQL(DISPATCH_LEVEL) + static PREADWORKER_PARAM GetNewWorkItem(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + static VOID DestroyWorkItems(); + +private: + __drv_maxIRQL(DISPATCH_LEVEL) + VOID ReadWavChunk(PCHUNKDESCRIPTOR PtrChunkDescriptor); + + __drv_maxIRQL(DISPATCH_LEVEL) + bool IsAllChunkEmpty(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS OpenWaveFile(PUNICODE_STRING puiFileName); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileClose(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileReadHeader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileOpen(); + + __drv_maxIRQL(DISPATCH_LEVEL) + VOID CopyDataFromRingBuffer + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS AllocateBigBuffer(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS ReadHeaderAndFillBuffer(); + + friend IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; +}; + + diff --git a/audio/Acx/Samples/Inc/AudioFormats.h b/audio/Acx/Samples/Inc/AudioFormats.h new file mode 100644 index 00000000..8a48b1cf --- /dev/null +++ b/audio/Acx/Samples/Inc/AudioFormats.h @@ -0,0 +1,959 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + AudioFormats.h + +Abstract: + + Contains Audio formats supported for the ACX Sample Drivers + +Environment: + + Kernel mode + +--*/ + +#pragma once + +#define NOBITMAP +#include <mmreg.h> + +// +// Basic-testing formats. +// +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 44100, + 176400, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2_24in32 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 44100, + 352800, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 192000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2_24in32 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 384000, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm192000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 768000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 44100, + 88200, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 48000, + 96000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm16000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 16000, + 32000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm32000c2 = +{ // 14 + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 32000, + 128000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm88200c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 88200, + 352800, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm96000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 96000, + 384000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm24000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 24000, + 96000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm16000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 16000, + 64000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm8000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 8000, + 16000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm11025c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 11025, + 22050, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm22050c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 22050, + 44100, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm24000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 24000, + 48000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm32000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 32000, + 64000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +// +// Definitions of HDMI specific audio formats. +// + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyDigital = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 192000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyDigitalPlus = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 768000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyDigitalPlusAtmos = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS_ATMOS), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 768000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS_ATMOS) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyMlp = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyMlpSurround = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1_SURROUND, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsSurround = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 192000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsHD = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsHDLowBitRate = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsXE1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTSX_E1), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTSX_E1) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsXE2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTSX_E2), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTSX_E2) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyMAT20 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MAT20), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MAT20) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyMAT21 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MAT21), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MAT21) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 44100, + 176400, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +// No Mask version is used for 2ch Capture, where the mask is not meaningful +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 192000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm16000c4nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 4, + 16000, + 128000, + 8, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; diff --git a/audio/Acx/Samples/Inc/cpp_utils.h b/audio/Acx/Samples/Inc/cpp_utils.h new file mode 100644 index 00000000..f4ed6220 --- /dev/null +++ b/audio/Acx/Samples/Inc/cpp_utils.h @@ -0,0 +1,71 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + cpp_utils.h + +Abstract: + + Contains CPP utilities + +Environment: + + Kernel mode + +--*/ + +#pragma once + +// Function scope_exit instantiates scope_exit object +// Constructor accepts lamda as parameter. +// Assign tasks in lamdba to be executed on scope exit. +template <typename F> +auto scope_exit(F f) +{ + class scope_exit + { + public: + scope_exit(F f) : + _f{ f } + { + } + + ~scope_exit() + { + if (_call) + { + _f(); + } + } + + // Ensures the scope_exit lambda will not be called + void release() + { + _call = false; + } + + // Executes the scope_exit lambda immediately if not yet run; ensures it will not run again + void reset() + { + if (_call) + { + _f(); + _call = false; + } + } + + private: + F _f; + bool _call = true; + }; + + return scope_exit{ f }; +}; + diff --git a/audio/Acx/Samples/Shared/Public.h b/audio/Acx/Samples/Shared/Public.h new file mode 100644 index 00000000..f1e9da3b --- /dev/null +++ b/audio/Acx/Samples/Shared/Public.h @@ -0,0 +1,342 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + Public.h + +Abstract: + + Contains structure definitions and function prototypes for the driver + that are public. + +Environment: + + Kernel mode + +--*/ + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <initguid.h> +#include <ntddk.h> +#include <ntstrsafe.h> +#include <ntintsafe.h> +#include "Trace.h" + +#include <wdf.h> +#include <acx.h> + +#define PAGED_CODE_SEG __declspec(code_seg("PAGE")) +#define INIT_CODE_SEG __declspec(code_seg("INIT")) + +// Number of msec for idle timeout. +#define IDLE_POWER_TIMEOUT 5000 + +extern RECORDER_LOG g_AudioDspLog; +extern RECORDER_LOG g_AudioDspMcLog; + +// +// Define CODEC device context. +// +typedef struct _CODEC_DEVICE_CONTEXT { + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + WDF_TRI_STATE ExcludeD3Cold; +} CODEC_DEVICE_CONTEXT, * PCODEC_DEVICE_CONTEXT; + +// +// Codec driver prototypes. +// +EVT_WDF_DRIVER_DEVICE_ADD Codec_EvtBusDeviceAdd; +DRIVER_INITIALIZE DriverEntry; +EVT_WDF_DRIVER_UNLOAD AudioCodecDriverUnload; + +// +// Codec device callbacks. +// +EVT_WDF_DEVICE_PREPARE_HARDWARE Codec_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE Codec_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY Codec_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT Codec_EvtDeviceD0Exit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Codec_EvtDeviceContextCleanup; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_DEVICE_CONTEXT, GetCodecDeviceContext) + +// +// Define DSP device context. +// +typedef struct _DSP_DEVICE_CONTEXT { + ACXCIRCUIT Speaker; + ACXCIRCUIT MicArray; + ACXCIRCUIT SpeakerHp; + ACXCIRCUIT MicrophoneHp; + ACXCIRCUIT HDMI; + WDF_TRI_STATE ExcludeD3Cold; +} DSP_DEVICE_CONTEXT, * PDSP_DEVICE_CONTEXT; + +// +// Dsp driver prototypes. +// +EVT_WDF_DRIVER_DEVICE_ADD Dsp_EvtBusDeviceAdd; +EVT_WDF_DRIVER_UNLOAD AudioDspDriverUnload; + +// +// Dsp device callbacks. +// +EVT_WDF_DEVICE_PREPARE_HARDWARE Dsp_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE Dsp_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY Dsp_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT Dsp_EvtDeviceD0Exit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Dsp_EvtDeviceContextCleanup; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_DEVICE_CONTEXT, GetDspDeviceContext) + +// +// Define CODECMC (multicircuit codec) device context. +// +typedef struct _CODECMC_DEVICE_CONTEXT +{ + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + ACXCOMPOSITETEMPLATE Composite[2]; + ULONG refComposite[2]; + WDF_TRI_STATE ExcludeD3Cold; +} CODECMC_DEVICE_CONTEXT, *PCODECMC_DEVICE_CONTEXT; + +// +// Multicircuit codec driver prototypes. +// +EVT_WDF_DRIVER_DEVICE_ADD CodecMc_EvtBusDeviceAdd; +DRIVER_INITIALIZE DriverEntry; +EVT_WDF_DRIVER_UNLOAD AudioCodecMcDriverUnload; + +// +// Multicircuit codec device callbacks. +// +EVT_WDF_DEVICE_PREPARE_HARDWARE CodecMc_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE CodecMc_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY CodecMc_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT CodecMc_EvtDeviceD0Exit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecMc_EvtDeviceContextCleanup; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODECMC_DEVICE_CONTEXT, GetCodecMcDeviceContext) + +// +// Composite type definition used in multicircuit codec. +// +typedef enum +{ + CompositeType_RENDER, + CompositeType_CAPTURE +} CompositeType; + +// +// Define DSPMC (multicircuit dsp) device context. +// +typedef struct _DSPMC_DEVICE_CONTEXT +{ + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + WDF_TRI_STATE ExcludeD3Cold; +} DSPMC_DEVICE_CONTEXT, *PDSPMC_DEVICE_CONTEXT; + +// +// Multicircuit dsp driver prototypes. +// +EVT_WDF_DRIVER_DEVICE_ADD DspMc_EvtBusDeviceAdd; +EVT_WDF_DRIVER_UNLOAD AudioDspMcDriverUnload; + +// +// Multicircuit dsp device callbacks. +// +EVT_WDF_DEVICE_PREPARE_HARDWARE DspMc_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE DspMc_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY DspMc_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT DspMc_EvtDeviceD0Exit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP DspMc_EvtDeviceContextCleanup; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSPMC_DEVICE_CONTEXT, GetDspMcDeviceContext) + +// Factory circuit callbacks for multicircuit dsp. +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUITDEVICE RenderMCDsp_EvtAcxFactoryCircuitCreateCircuitDevice; +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUIT RenderMCDsp_EvtAcxFactoryCircuitCreateCircuit; + +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUITDEVICE CaptureMCDsp_EvtAcxFactoryCircuitCreateCircuitDevice; +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUIT CaptureMCDsp_EvtAcxFactoryCircuitCreateCircuit; + + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + +// Used to store the registry settings path for the driver: +extern UNICODE_STRING g_RegistryPath; + +// Driver tag name: +extern ULONG DeviceDriverTag; + +// The idle timeout in msec for power policy structure: +extern ULONG IdleTimeoutMsec; + +#define DECLARE_CONST_ACXOBJECTBAG_MULTICIRCUIT_SAMPLE_PROPERTY_NAME(name) \ + DECLARE_CONST_UNICODE_STRING(name, L"mc_" #name) + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +CopyRegistrySettingsPath( + _In_ PUNICODE_STRING RegistryPath +); + +PAGED_CODE_SEG +NTSTATUS +Codec_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +Dsp_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +CodecMc_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +DspMc_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +CodecR_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +CodecC_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +Speaker_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName, + _In_ BOOLEAN IsHeadphones +); + +PAGED_CODE_SEG +NTSTATUS +MicArray_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ GUID MicCustomName, + _In_ UNICODE_STRING CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +MicrophoneHp_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ GUID MicCustomName, + _In_ UNICODE_STRING CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +SpeakerHp_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +HDMI_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +RenderMC_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName, + _In_ const UNICODE_STRING * Uri +); + +PAGED_CODE_SEG +NTSTATUS +CaptureMC_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName, + _In_ const UNICODE_STRING * Uri +); + +PAGED_CODE_SEG +NTSTATUS +CodecC_CircuitCleanup( + _In_ ACXCIRCUIT Device +); + +PAGED_CODE_SEG +NTSTATUS +MicArray_CircuitCleanup( + _In_ ACXCIRCUIT Device +); + +PAGED_CODE_SEG +NTSTATUS +CaptureMCDsp_CircuitCleanup( + _In_ ACXCIRCUIT Device +); + +PAGED_CODE_SEG +NTSTATUS +DspMc_AddFactoryCircuit( + _In_ WDFDRIVER Driver, + _In_ WDFDEVICE Device +); + +NTSTATUS +CodecMc_AddRenderComposites(_In_ WDFDEVICE Device); + +PAGED_CODE_SEG +NTSTATUS +CodecMc_AddCaptureComposites(_In_ WDFDEVICE Device); + +PAGED_CODE_SEG +NTSTATUS +CodecMc_AddComposites(_In_ WDFDEVICE Device, _In_ CompositeType compositeType); + +NTSTATUS +CodecMc_RemoveComposites(_In_ WDFDEVICE Device); diff --git a/audio/Acx/Samples/Shared/Trace.h b/audio/Acx/Samples/Shared/Trace.h new file mode 100644 index 00000000..01478bfc --- /dev/null +++ b/audio/Acx/Samples/Shared/Trace.h @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + +Trace.h + +--*/ + +#pragma once + +#include <WppRecorder.h> +#include <evntrace.h> // For TRACE_LEVEL definitions + +#define WPP_TOTAL_BUFFER_SIZE (PAGE_SIZE) +#define WPP_ERROR_PARTITION_SIZE (WPP_TOTAL_BUFFER_SIZE/4) + +// {1945C417-844C-48C6-9BCE-3AA2113A2B69} +#define WPP_CONTROL_GUIDS \ +WPP_DEFINE_CONTROL_GUID(DrvLogger,(1945C417,844C,48C6,9BCE,3AA2113A2B69), \ + WPP_DEFINE_BIT(FLAG_DEVICE_ALL) /* bit 0 = 0x00000001 */ \ + WPP_DEFINE_BIT(FLAG_FUNCTION) /* bit 1 = 0x00000002 */ \ + WPP_DEFINE_BIT(FLAG_INFO) /* bit 2 = 0x00000004 */ \ + WPP_DEFINE_BIT(FLAG_PNP) /* bit 3 = 0x00000008 */ \ + WPP_DEFINE_BIT(FLAG_POWER) /* bit 4 = 0x00000010 */ \ + WPP_DEFINE_BIT(FLAG_STREAM) /* bit 5 = 0x00000020 */ \ + WPP_DEFINE_BIT(FLAG_INIT) /* bit 6 = 0x00000040 */ \ + WPP_DEFINE_BIT(FLAG_DDI) /* bit 7 = 0x00000080 */ \ + WPP_DEFINE_BIT(FLAG_GENERIC) /* bit 8 = 0x00000100 */ \ + ) + +#include "trace_macros.h" diff --git a/audio/simpleaudiosample/Package/package.VcxProj b/audio/simpleaudiosample/Package/package.VcxProj index a70e4820..7921c8d3 100644 --- a/audio/simpleaudiosample/Package/package.VcxProj +++ b/audio/simpleaudiosample/Package/package.VcxProj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -44,14 +36,6 @@ <SampleGuid>{E9D167E6-E633-4284-8F02-FF86DF3B6D7F}</SampleGuid> <RootNamespace>$(MSBuildProjectName)</RootNamespace> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>true</UseDebugLibraries> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>false</UseDebugLibraries> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>true</UseDebugLibraries> @@ -92,16 +76,6 @@ <VerifyDrivers /> <VerifyFlags>133563</VerifyFlags> </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <DriverSign> <FileDigestAlgorithm>sha256</FileDigestAlgorithm> @@ -125,4 +99,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/simpleaudiosample/SimpleAudioSample.sln b/audio/simpleaudiosample/SimpleAudioSample.sln index 407838ba..8fc1ef17 100644 --- a/audio/simpleaudiosample/SimpleAudioSample.sln +++ b/audio/simpleaudiosample/SimpleAudioSample.sln @@ -29,71 +29,49 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 - Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|ARM64 = Release|ARM64 - Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.ActiveCfg = Debug|ARM64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.Build.0 = Debug|ARM64 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.ActiveCfg = Debug|Win32 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.Build.0 = Debug|Win32 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.ActiveCfg = Debug|x64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.Build.0 = Debug|x64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.ActiveCfg = Release|ARM64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.Build.0 = Release|ARM64 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.ActiveCfg = Release|Win32 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.Build.0 = Release|Win32 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.ActiveCfg = Release|x64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Build.0 = Release|x64 {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|ARM64.ActiveCfg = Debug|ARM64 {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|ARM64.Build.0 = Debug|ARM64 - {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|Win32.ActiveCfg = Debug|Win32 - {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|Win32.Build.0 = Debug|Win32 {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|x64.ActiveCfg = Debug|x64 {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|x64.Build.0 = Debug|x64 {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|ARM64.ActiveCfg = Release|ARM64 {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|ARM64.Build.0 = Release|ARM64 - {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|Win32.ActiveCfg = Release|Win32 - {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|Win32.Build.0 = Release|Win32 {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|x64.ActiveCfg = Release|x64 {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|x64.Build.0 = Release|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.ActiveCfg = Debug|ARM64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.Build.0 = Debug|ARM64 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.ActiveCfg = Debug|Win32 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.Build.0 = Debug|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.ActiveCfg = Debug|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.Build.0 = Debug|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.ActiveCfg = Release|ARM64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.Build.0 = Release|ARM64 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.ActiveCfg = Release|Win32 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.Build.0 = Release|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.ActiveCfg = Release|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.Build.0 = Release|x64 {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|ARM64.ActiveCfg = Debug|ARM64 {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|ARM64.Build.0 = Debug|ARM64 - {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|Win32.Build.0 = Debug|Win32 {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|x64.ActiveCfg = Debug|x64 {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|x64.Build.0 = Debug|x64 {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|ARM64.ActiveCfg = Release|ARM64 {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|ARM64.Build.0 = Release|ARM64 - {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|Win32.ActiveCfg = Release|Win32 - {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|Win32.Build.0 = Release|Win32 {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|x64.ActiveCfg = Release|x64 {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|x64.Build.0 = Release|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.ActiveCfg = Debug|ARM64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.Build.0 = Debug|ARM64 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.ActiveCfg = Debug|Win32 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.Build.0 = Debug|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.ActiveCfg = Debug|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.Build.0 = Debug|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.ActiveCfg = Release|ARM64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.Build.0 = Release|ARM64 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.ActiveCfg = Release|Win32 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.Build.0 = Release|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.ActiveCfg = Release|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.Build.0 = Release|x64 EndGlobalSection diff --git a/audio/simpleaudiosample/Source/Filters/Filters.vcxproj b/audio/simpleaudiosample/Source/Filters/Filters.vcxproj index 82fd07dc..1b343b45 100644 --- a/audio/simpleaudiosample/Source/Filters/Filters.vcxproj +++ b/audio/simpleaudiosample/Source/Filters/Filters.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -31,14 +23,14 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -46,7 +38,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -54,7 +46,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -62,23 +54,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -99,12 +75,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>Filters</TargetName> @@ -118,12 +88,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>Filters</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>Filters</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>Filters</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> @@ -216,52 +180,6 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="micarraytopo.cpp" /> <ClCompile Include="speakertopo.cpp" /> @@ -279,4 +197,4 @@ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/simpleaudiosample/Source/Inc/Inc.vcxproj b/audio/simpleaudiosample/Source/Inc/Inc.vcxproj index ab768d84..46846d71 100644 --- a/audio/simpleaudiosample/Source/Inc/Inc.vcxproj +++ b/audio/simpleaudiosample/Source/Inc/Inc.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -31,14 +23,14 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -46,7 +38,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -54,7 +46,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -62,23 +54,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -99,12 +75,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>Inc</TargetName> @@ -118,12 +88,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>Inc</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>Inc</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>Inc</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> @@ -204,46 +168,6 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> <ItemGroup> <Inf Exclude="@(Inf)" Include="*.inf" /> <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> @@ -257,4 +181,4 @@ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/simpleaudiosample/Source/Main/Main.vcxproj b/audio/simpleaudiosample/Source/Main/Main.vcxproj index a68d0242..b569da4d 100644 --- a/audio/simpleaudiosample/Source/Main/Main.vcxproj +++ b/audio/simpleaudiosample/Source/Main/Main.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -33,14 +25,14 @@ <SupportsPackaging>false</SupportsPackaging> <RequiresPackageProject>true</RequiresPackageProject> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{2A9A946E-F017-4E0D-BF75-AD81E7E97D64}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> @@ -48,7 +40,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> @@ -56,7 +48,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> @@ -64,23 +56,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> @@ -101,12 +77,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> @@ -208,56 +178,6 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>SimpleAudioSample</TargetName> </PropertyGroup> @@ -270,12 +190,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>SimpleAudioSample</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>SimpleAudioSample</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>SimpleAudioSample</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies> @@ -396,62 +310,6 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> </ResourceCompile> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies> - </Link> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies> - </Link> - <ClCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - </ResourceCompile> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies> - </Link> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies> - </Link> - <ClCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - </ResourceCompile> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="adapter.cpp" /> <ClCompile Include="basetopo.cpp" /> @@ -475,4 +333,4 @@ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx b/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx Binary files differindex a63bb0ba..d0835f1f 100644 --- a/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx +++ b/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx diff --git a/audio/simpleaudiosample/Source/Main/adapter.cpp b/audio/simpleaudiosample/Source/Main/adapter.cpp index 105f7fde..a66ee5a2 100644 --- a/audio/simpleaudiosample/Source/Main/adapter.cpp +++ b/audio/simpleaudiosample/Source/Main/adapter.cpp @@ -45,10 +45,10 @@ _Dispatch_type_(IRP_MJ_PNP) DRIVER_DISPATCH PnpHandler; // -// Rendering streams are saved to a file by default. Use the registry value -// DoNotCreateDataFiles (DWORD) > 0 to override this default. +// Rendering streams are not saved to a file by default. Use the registry value +// DoNotCreateDataFiles (DWORD) = 0 to override this default. // -DWORD g_DoNotCreateDataFiles = 0; // default is off. +DWORD g_DoNotCreateDataFiles = 1; // default is off. DWORD g_DisableToneGenerator = 0; // default is to generate tones. UNICODE_STRING g_RegistryPath; // This is used to store the registry settings path for the driver @@ -59,6 +59,8 @@ UNICODE_STRING g_RegistryPath; // This is used to store the registry settin #pragma code_seg("PAGE") void ReleaseRegistryStringBuffer() { + PAGED_CODE(); + if (g_RegistryPath.Buffer != NULL) { ExFreePool(g_RegistryPath.Buffer); @@ -192,7 +194,8 @@ Returns: { NTSTATUS ntStatus; - UNICODE_STRING parametersPath; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DoNotCreateDataFiles", &g_DoNotCreateDataFiles, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DoNotCreateDataFiles, sizeof(ULONG)}, @@ -202,29 +205,27 @@ Returns: DPF(D_TERSE, ("[GetRegistrySettings]")); - PAGED_CODE(); - - RtlInitUnicodeString(¶metersPath, NULL); + PAGED_CODE(); + UNREFERENCED_PARAMETER(RegistryPath); - parametersPath.MaximumLength = - RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(WCHAR); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - parametersPath.Buffer = (PWCH) ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINADAPTER_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, RegistryPath->Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); - - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); if (!NT_SUCCESS(ntStatus)) { @@ -240,10 +241,10 @@ Returns: DPF(D_VERBOSE, ("DoNotCreateDataFiles: %u", g_DoNotCreateDataFiles)); DPF(D_VERBOSE, ("DisableToneGenerator: %u", g_DisableToneGenerator)); - // - // Cleanup. - // - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return STATUS_SUCCESS; } @@ -292,15 +293,6 @@ Return Value: ntStatus, DPF(D_ERROR, ("Registry path copy error 0x%x", ntStatus)), Done); - - // - // Get registry configuration. - // - ntStatus = GetRegistrySettings(RegistryPathName); - IF_FAILED_ACTION_JUMP( - ntStatus, - DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)), - Done); WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK); // @@ -324,6 +316,15 @@ Return Value: Done); // + // Get registry configuration. + // + ntStatus = GetRegistrySettings(RegistryPathName); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)), + Done); + + // // Tell the class driver to initialize the driver. // ntStatus = PcInitializeAdapterDriver(DriverObject, diff --git a/audio/simpleaudiosample/Source/Main/common.cpp b/audio/simpleaudiosample/Source/Main/common.cpp index 8843d3a4..457bdb17 100644 --- a/audio/simpleaudiosample/Source/Main/common.cpp +++ b/audio/simpleaudiosample/Source/Main/common.cpp @@ -2547,6 +2547,7 @@ Exit: return ntStatus; } +#pragma code_seg("PAGE") NTSTATUS CopyRegistryKey(HANDLE _hSourceKey, HANDLE _hDestinationKey, BOOL _bOverwrite = FALSE) /*++ @@ -2686,7 +2687,7 @@ Exit: return ntStatus; } - +#pragma code_seg("PAGE") NTSTATUS CAdapterCommon::MigrateDeviceInterfaceTemplateParameters ( _In_ PUNICODE_STRING SymbolicLinkName, @@ -2729,6 +2730,8 @@ Return Value: UNICODE_STRING TemplateSymbolicLinkName; UNICODE_STRING referenceString; + PAGED_CODE(); + RtlInitUnicodeString(&TemplateSymbolicLinkName, NULL); RtlInitUnicodeString(&referenceString, TemplateReferenceString); diff --git a/audio/simpleaudiosample/Source/Main/minwavertstream.cpp b/audio/simpleaudiosample/Source/Main/minwavertstream.cpp index 27289a0e..c189c939 100644 --- a/audio/simpleaudiosample/Source/Main/minwavertstream.cpp +++ b/audio/simpleaudiosample/Source/Main/minwavertstream.cpp @@ -108,8 +108,8 @@ NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings() PAGED_CODE(); NTSTATUS ntStatus; - UNICODE_STRING parametersPath; - + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureToneFrequency", &m_ulHostCaptureToneFrequency, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_ulHostCaptureToneFrequency, sizeof(DWORD) }, @@ -119,30 +119,37 @@ NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings() { NULL, 0, NULL, NULL, 0, NULL, 0 } }; - RtlInitUnicodeString(¶metersPath, NULL); - - // The sizeof(WCHAR) is added to the maximum length, for allowing a space for null termination of the string. - parametersPath.MaximumLength = - g_RegistryPath.Length + sizeof(L"\\Parameters") + sizeof(WCHAR); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - parametersPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINWAVERT_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, g_RegistryPath.Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_VERBOSE, ("RtlQueryRegistryValues failed, using default values, 0x%x", ntStatus)); + // + // Don't return error because we will operate with default values. + // + } - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return ntStatus; } diff --git a/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj b/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj index 0a71bf42..5efe1068 100644 --- a/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj +++ b/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -31,14 +23,14 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -46,7 +38,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -54,7 +46,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -62,23 +54,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -99,12 +75,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>Utilities</TargetName> @@ -118,12 +88,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>Utilities</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>Utilities</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>Utilities</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> @@ -216,52 +180,6 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="hw.cpp" /> <ClCompile Include="kshelper.cpp" /> @@ -281,4 +199,4 @@ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/simpleaudiosample/Source/Utilities/savedata.cpp b/audio/simpleaudiosample/Source/Utilities/savedata.cpp index 7b2a11e9..02c3f602 100644 --- a/audio/simpleaudiosample/Source/Utilities/savedata.cpp +++ b/audio/simpleaudiosample/Source/Utilities/savedata.cpp @@ -44,8 +44,9 @@ Abstract: #define DEFAULT_FRAME_SIZE PAGE_SIZE * 4 #define DEFAULT_BUFFER_SIZE DEFAULT_FRAME_SIZE * DEFAULT_FRAME_COUNT -#define DEFAULT_FILE_NAME L"\\DosDevices\\C:\\STREAM" -#define OSDATA_FILE_NAME L"\\DosDevices\\O:\\STREAM" +#define DEFAULT_FILE_FOLDER1 L"\\DriverData\\Audio_Samples" +#define DEFAULT_FILE_FOLDER2 L"\\DriverData\\Audio_Samples\\SimpleAudioSample" +#define DEFAULT_FILE_NAME L"\\DriverData\\Audio_Samples\\SimpleAudioSample\\STREAM" #define OFFLOAD_FILE_NAME L"OFFLOAD" #define HOST_FILE_NAME L"HOST" @@ -444,59 +445,86 @@ CSaveData::Initialize { PAGED_CODE(); - NTSTATUS ntStatus = STATUS_SUCCESS; - WCHAR szTemp[MAX_PATH]; - size_t cLen; - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING osDataVolumeString; - HANDLE osDataFileHandle = NULL; - IO_STATUS_BLOCK ioStatusBlock; + NTSTATUS ntStatus = STATUS_SUCCESS; + WCHAR szTemp[MAX_PATH]; + size_t cLen = 0; + IO_STATUS_BLOCK ioStatusBlock = {0}; + HANDLE fileHandle; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING fileName; DPF_ENTER(("[CSaveData::Initialize]")); m_ulStreamId++; - // Probe if OSData volume exists. - // - RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_probe.txt", OSDATA_FILE_NAME); - RtlInitUnicodeString(&osDataVolumeString, szTemp); - InitializeObjectAttributes - ( - &objectAttributes, - &osDataVolumeString, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL - ); + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER1); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); - ntStatus = - ZwCreateFile - ( - &osDataFileHandle, - GENERIC_WRITE | SYNCHRONIZE, + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, - FILE_OVERWRITE_IF, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, - 0 - ); + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER2); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, + &objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + } + } + if (NT_SUCCESS(ntStatus)) { - ZwClose(osDataFileHandle); + // Allocate data file name. + // + RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", DEFAULT_FILE_NAME, HOST_FILE_NAME, m_ulStreamId); + m_FileName.Length = 0; + ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); } - // Allocate data file name. - // - RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", NT_SUCCESS(ntStatus) ? OSDATA_FILE_NAME : DEFAULT_FILE_NAME, HOST_FILE_NAME, m_ulStreamId); - m_FileName.Length = 0; - ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); if (NT_SUCCESS(ntStatus)) { - m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL + m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL m_FileName.Buffer = (PWSTR) ExAllocatePool2 ( @@ -574,7 +602,7 @@ CSaveData::Initialize ( &m_objectAttributes, &m_FileName, - OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); diff --git a/audio/sysvad/APO/AecApo/AecApo.h b/audio/sysvad/APO/AecApo/AecApo.h index a62b69ce..7c96314d 100644 --- a/audio/sysvad/APO/AecApo/AecApo.h +++ b/audio/sysvad/APO/AecApo/AecApo.h @@ -99,13 +99,8 @@ public: ) override; // IAudioSystemEffects3 - STDMETHODIMP GetControllableSystemEffectsList(_Outptr_result_buffer_maybenull_(*numEffects) AUDIO_SYSTEMEFFECT** effects, _Out_ UINT* numEffects, _In_opt_ HANDLE event) override - { - UNREFERENCED_PARAMETER(effects); - UNREFERENCED_PARAMETER(numEffects); - UNREFERENCED_PARAMETER(event); - return S_OK; - } + STDMETHOD(GetControllableSystemEffectsList)( + _Outptr_result_buffer_maybenull_(*numEffects) AUDIO_SYSTEMEFFECT** effects, _Out_ UINT* numEffects, _In_opt_ HANDLE event) override; STDMETHODIMP SetAudioSystemEffectState(GUID, AUDIO_SYSTEMEFFECT_STATE) override {return S_OK;} diff --git a/audio/sysvad/APO/AecApo/AecApo.vcxproj b/audio/sysvad/APO/AecApo/AecApo.vcxproj index f40ce919..7de1a862 100644 --- a/audio/sysvad/APO/AecApo/AecApo.vcxproj +++ b/audio/sysvad/APO/AecApo/AecApo.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -32,14 +24,14 @@ <SupportsPackaging>false</SupportsPackaging> <RequiresPackageProject>true</RequiresPackageProject> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{D5CCDCB1-348E-414E-BB0F-33C773760034}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -48,7 +40,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -57,7 +49,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -66,25 +58,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -106,12 +80,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>AecApo</TargetName> @@ -125,46 +93,24 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>AecApo</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>AecApo</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>AecApo</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -179,12 +125,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <UseOfAtl>Dynamic</UseOfAtl> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> @@ -283,54 +223,6 @@ <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.;..\..\..\..\wil\include</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary /> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> - <ModuleDefinitionFile>AecApoDll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.;..\..\..\..\wil\include</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary /> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> - <ModuleDefinitionFile>AecApoDll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="AecApoDll.cpp" /> <ClCompile Include="AecApoMFX.cpp" /> diff --git a/audio/sysvad/APO/AecApo/AecApoMfx.cpp b/audio/sysvad/APO/AecApo/AecApoMfx.cpp index 21f2c20d..0c16f348 100644 --- a/audio/sysvad/APO/AecApo/AecApoMfx.cpp +++ b/audio/sysvad/APO/AecApo/AecApoMfx.cpp @@ -375,6 +375,39 @@ STDMETHODIMP CAecApoMFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEffe return S_OK; } +STDMETHODIMP CAecApoMFX::GetControllableSystemEffectsList(_Outptr_result_buffer_maybenull_(*numEffects) AUDIO_SYSTEMEFFECT** effects, _Out_ UINT* numEffects, _In_opt_ HANDLE event) +{ + UNREFERENCED_PARAMETER(event); + + RETURN_HR_IF_NULL(E_POINTER, effects); + RETURN_HR_IF_NULL(E_POINTER, numEffects); + + *effects = nullptr; + *numEffects = 0; + + if (m_audioSignalProcessingMode == AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS) + { + // Return the list of effects implemented by this APO for COMMUNICATIONS processing mode + static const GUID effectsList[] = {AUDIO_EFFECT_TYPE_ACOUSTIC_ECHO_CANCELLATION}; + + wil::unique_cotaskmem_array_ptr<AUDIO_SYSTEMEFFECT> audioEffects( + static_cast<AUDIO_SYSTEMEFFECT*>(CoTaskMemAlloc(ARRAYSIZE(effectsList) * sizeof(AUDIO_SYSTEMEFFECT))), ARRAYSIZE(effectsList)); + RETURN_IF_NULL_ALLOC(audioEffects.get()); + + for (UINT i = 0; i < ARRAYSIZE(effectsList); i++) + { + audioEffects[i].id = effectsList[i]; + audioEffects[i].state = AUDIO_SYSTEMEFFECT_STATE_ON; + audioEffects[i].canSetState = FALSE; + } + + *numEffects = (UINT)audioEffects.size(); + *effects = audioEffects.release(); + } + + return S_OK; +} + HRESULT IsInputFormatSupportedForAec(IAudioMediaType* pMediaType, BOOL * pSupported) { ASSERT_NONREALTIME(); diff --git a/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj b/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj index ecdaf321..a5d6ff37 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj +++ b/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -32,14 +24,14 @@ <SupportsPackaging>false</SupportsPackaging> <RequiresPackageProject>true</RequiresPackageProject> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{D5CCDCB1-348E-414E-BB0F-33C773760034}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -48,7 +40,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -57,7 +49,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -66,25 +58,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -106,12 +80,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>DelayAPO</TargetName> @@ -125,46 +93,24 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>DelayAPO</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>DelayAPO</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>DelayAPO</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -179,12 +125,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <UseOfAtl>Dynamic</UseOfAtl> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> @@ -283,58 +223,10 @@ <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary /> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> - <ModuleDefinitionFile>DelayAPODll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary /> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> - <ModuleDefinitionFile>DelayAPODll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="Delay.cpp" /> <ClCompile Include="DelayAPODll.cpp" /> - <ClCompile Include="DelayAPOMFX.cpp " /> + <ClCompile Include="DelayAPOMFX.cpp " /> <ClCompile Include="DelayAPOSFX.cpp" /> <Midl Include="DelayAPODll.idl" /> <Midl Include="DelayAPOInterface.idl" /> @@ -353,4 +245,4 @@ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp b/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp index 8778b252..af67571b 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp +++ b/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp @@ -292,7 +292,7 @@ STDMETHODIMP CDelayAPOMFX::LockForProcess(UINT32 u32NumInputConnections, // // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important - m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); + m_pf32DelayBuffer.Allocate((size_t) GetSamplesPerFrame() * m_nDelayFrames); WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); if (nullptr == m_pf32DelayBuffer) { @@ -430,7 +430,8 @@ HRESULT CDelayAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && - processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE && + processingMode != AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION), hr = E_INVALIDARG, Exit); m_AudioProcessingMode = processingMode; // @@ -1165,4 +1166,4 @@ HRESULT CDelayAPOMFX::CheckCustomFormats(IAudioMediaType *pRequestedFormat) } return hResult; -}
\ No newline at end of file +} diff --git a/audio/sysvad/APO/DelayAPO/DelayAPOSFX.cpp b/audio/sysvad/APO/DelayAPO/DelayAPOSFX.cpp index 81594bb7..67ae2788 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPOSFX.cpp +++ b/audio/sysvad/APO/DelayAPO/DelayAPOSFX.cpp @@ -241,7 +241,7 @@ STDMETHODIMP CDelayAPOSFX::LockForProcess(UINT32 u32NumInputConnections, // // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important - m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); + m_pf32DelayBuffer.Allocate((size_t) GetSamplesPerFrame() * m_nDelayFrames); WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); if (nullptr == m_pf32DelayBuffer) @@ -388,7 +388,8 @@ HRESULT CDelayAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && - processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE && + processingMode != AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION), hr = E_INVALIDARG, Exit); m_AudioProcessingMode = processingMode; // diff --git a/audio/sysvad/APO/KWSApo/KWSApo.vcxproj b/audio/sysvad/APO/KWSApo/KWSApo.vcxproj index b34e03d9..938e5974 100644 --- a/audio/sysvad/APO/KWSApo/KWSApo.vcxproj +++ b/audio/sysvad/APO/KWSApo/KWSApo.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -32,14 +24,14 @@ <SupportsPackaging>false</SupportsPackaging> <RequiresPackageProject>true</RequiresPackageProject> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{D5CCDCB1-348E-414E-BB0F-33C773760034}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -48,7 +40,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -57,7 +49,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -66,25 +58,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -106,12 +80,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>KWSApo</TargetName> @@ -125,46 +93,24 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>KWSApo</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>KWSApo</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>KWSApo</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -179,12 +125,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <UseOfAtl>Dynamic</UseOfAtl> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> @@ -283,54 +223,6 @@ <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.;..\..\..\..\wil\include</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary /> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> - <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.;..\..\..\..\wil\include</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary /> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> - <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="KWSApo.cpp" /> <ClCompile Include="KWSApoDll.cpp" /> diff --git a/audio/sysvad/APO/SwapAPO/SwapAPO.h b/audio/sysvad/APO/SwapAPO/SwapAPO.h index aeb9d259..d169d9db 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPO.h +++ b/audio/sysvad/APO/SwapAPO/SwapAPO.h @@ -195,7 +195,8 @@ public: public: LONG m_fEnableSwapMFX; GUID m_AudioProcessingMode; - wil::com_ptr_nothrow<IMMDevice> m_device; + wil::com_ptr_nothrow<IMMDevice> m_deviceTopologyMMDevice; + wil::com_ptr_nothrow<IMMDevice> m_audioEndpoint; CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties; CComPtr<IMMDeviceEnumerator> m_spEnumerator; static const CRegAPOProperties<1> sm_RegProperties; // registration properties @@ -315,7 +316,8 @@ public: LONG m_fEnableSwapSFX; LONG m_fEnableDelaySFX; GUID m_AudioProcessingMode; - wil::com_ptr_nothrow<IMMDevice> m_device; + wil::com_ptr_nothrow<IMMDevice> m_deviceTopologyMMDevice; + wil::com_ptr_nothrow<IMMDevice> m_audioEndpoint; CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties; CComPtr<IMMDeviceEnumerator> m_spEnumerator; static const CRegAPOProperties<1> sm_RegProperties; // registration properties diff --git a/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj b/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj index 2a26307e..61bea0cb 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj +++ b/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj @@ -5,18 +5,10 @@ <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -32,14 +24,14 @@ <SupportsPackaging>false</SupportsPackaging> <RequiresPackageProject>true</RequiresPackageProject> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{D5CCDCB1-348E-414E-BB0F-33C773760034}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -48,7 +40,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -57,7 +49,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -66,25 +58,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <EmbedManifest>false</EmbedManifest> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> @@ -106,12 +80,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>SwapAPO</TargetName> @@ -125,64 +93,24 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>SwapAPO</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>SwapAPO</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <TargetName>SwapAPO</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>SwapAPO</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <TargetName>SwapAPO</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -197,18 +125,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <UseOfAtl>Dynamic</UseOfAtl> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> @@ -307,104 +223,6 @@ <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.;..\..\..\..\wil\include</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary /> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib;rtworkq.lib</AdditionalDependencies> - <ModuleDefinitionFile>SwapAPODll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary> - </RuntimeLibrary> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib;rtworkq.lib</AdditionalDependencies> - <ModuleDefinitionFile>SwapAPODll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.;..\..\..\..\wil\include</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary /> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib;rtworkq.lib</AdditionalDependencies> - <ModuleDefinitionFile>SwapAPODll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary> - </RuntimeLibrary> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib;rtworkq.lib</AdditionalDependencies> - <ModuleDefinitionFile>SwapAPODll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="Swap.cpp" /> <ClCompile Include="SwapAPODll.cpp" /> diff --git a/audio/sysvad/APO/SwapAPO/swapapomfx.cpp b/audio/sysvad/APO/SwapAPO/swapapomfx.cpp index 7a772a07..b05b1568 100644 --- a/audio/sysvad/APO/SwapAPO/swapapomfx.cpp +++ b/audio/sysvad/APO/SwapAPO/swapapomfx.cpp @@ -458,10 +458,38 @@ HRESULT CSwapAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) // that need to run at a real-time priority. The work queue ID is used with the Rtwq APIs. hr = apoRtQueueService->GetRealTimeWorkQueue(&m_queueId); IF_FAILED_JUMP(hr, Exit); - + // Windows should pass a valid collection. ATLASSERT(papoSysFxInit3->pDeviceCollection != nullptr); IF_TRUE_ACTION_JUMP(papoSysFxInit3->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + + // Use IMMDevice to activate IAudioSystemEffectsPropertyStore that contains the default, user and + // volatile settings. + IMMDeviceCollection* deviceCollection = reinterpret_cast<APOInitSystemEffects3*>(pbyData)->pDeviceCollection; + UINT32 numDevices; + // Get the endpoint on which this APO has been created + // (It is the last device in the device collection) + hr = deviceCollection->GetCount(&numDevices); + IF_FAILED_JUMP(hr, Exit); + + hr = numDevices > 0 ? S_OK : E_UNEXPECTED; + IF_FAILED_JUMP(hr, Exit); + + hr = deviceCollection->Item(numDevices - 1, &m_audioEndpoint); + IF_FAILED_JUMP(hr, Exit); + + wil::unique_prop_variant activationParam; + hr = InitPropVariantFromCLSID(SWAP_APO_SFX_CONTEXT, &activationParam); + IF_FAILED_JUMP(hr, Exit); + + wil::com_ptr_nothrow<IAudioSystemEffectsPropertyStore> effectsPropertyStore; + hr = m_audioEndpoint->Activate(__uuidof(effectsPropertyStore), CLSCTX_ALL, &activationParam, effectsPropertyStore.put_void()); + IF_FAILED_JUMP(hr, Exit); + + // This is where an APO might want to open the volatile or default property stores as well + // Use STGM_READWRITE if IPropertyStore::SetValue is needed. + hr = effectsPropertyStore->OpenUserPropertyStore(STGM_READ, m_userStore.put()); + IF_FAILED_JUMP(hr, Exit); // Save the processing mode being initialized. processingMode = papoSysFxInit3->AudioProcessingMode; @@ -523,7 +551,8 @@ HRESULT CSwapAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && - processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE && + processingMode != AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION), hr = E_INVALIDARG, Exit); m_AudioProcessingMode = processingMode; // @@ -755,7 +784,7 @@ HRESULT CSwapAPOMFX::SetAudioSystemEffectState(GUID effectId, AUDIO_SYSTEMEFFECT if (oldState != effectInfo.state) { SetEvent(m_hEffectsChangedEvent); - m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"SetAudioSystemEffectState - effect: " GUID_FORMAT_STRING L", state: %i", effectInfo.id, effectInfo.state); + m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"CSwapAPOMFX::SetAudioSystemEffectState - effect: " GUID_FORMAT_STRING L", state: %i", effectInfo.id, effectInfo.state); } m_EffectsLock.Leave(); @@ -772,8 +801,6 @@ HRESULT CSwapAPOMFX::GetApoNotificationRegistrationInfo(_Out_writes_(*count) APO *apoNotifications = nullptr; *count = 0; - RETURN_HR_IF_NULL(E_FAIL, m_device); - // Let the OS know what notifications we are interested in by returning an array of // APO_NOTIFICATION_DESCRIPTORs. constexpr DWORD numDescriptors = 1; @@ -785,7 +812,7 @@ HRESULT CSwapAPOMFX::GetApoNotificationRegistrationInfo(_Out_writes_(*count) APO // Our APO wants to get notified when a endpoint property changes on the audio endpoint. apoNotificationDescriptors[0].type = APO_NOTIFICATION_TYPE_ENDPOINT_PROPERTY_CHANGE; - (void)m_device.query_to(&apoNotificationDescriptors[0].audioEndpointPropertyChange.device); + (void)m_audioEndpoint.query_to(&apoNotificationDescriptors[0].audioEndpointPropertyChange.device); *apoNotifications = apoNotificationDescriptors.release(); *count = numDescriptors; @@ -811,7 +838,7 @@ void CSwapAPOMFX::HandleNotification(APO_NOTIFICATION *apoNotification) {PKEY_Endpoint_Enable_Channel_Swap_MFX, &m_fEnableSwapMFX}, }; - m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"HandleNotification - pkey: " GUID_FORMAT_STRING L" %d", GUID_FORMAT_ARGS(apoNotification->audioEndpointPropertyChange.propertyKey.fmtid), apoNotification->audioEndpointPropertyChange.propertyKey.pid); + m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"CSwapAPOMFX::HandleNotification - pkey: " GUID_FORMAT_STRING L" %d", GUID_FORMAT_ARGS(apoNotification->audioEndpointPropertyChange.propertyKey.fmtid), apoNotification->audioEndpointPropertyChange.propertyKey.pid); for (int i = 0; i < ARRAYSIZE(controls); i++) { @@ -847,11 +874,11 @@ HRESULT CSwapAPOMFX::ProprietaryCommunicationWithDriver(IMMDeviceCollection *pDe } // Get the target IMMDevice - hr = pDeviceCollection->Item(nSoftwareIoDeviceInCollection, &m_device); + hr = pDeviceCollection->Item(nSoftwareIoDeviceInCollection, &m_deviceTopologyMMDevice); IF_FAILED_JUMP(hr, Exit); // Instantiate a device topology instance - hr = m_device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + hr = m_deviceTopologyMMDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); IF_FAILED_JUMP(hr, Exit); // retrieve connect instance @@ -859,7 +886,7 @@ HRESULT CSwapAPOMFX::ProprietaryCommunicationWithDriver(IMMDeviceCollection *pDe IF_FAILED_JUMP(hr, Exit); // activate IKsControl on the IMMDevice - hr = m_device->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, NULL, (void**)&spKsControl); + hr = m_deviceTopologyMMDevice->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, NULL, (void**)&spKsControl); IF_FAILED_JUMP(hr, Exit); // get KS pin id diff --git a/audio/sysvad/APO/SwapAPO/swapaposfx.cpp b/audio/sysvad/APO/SwapAPO/swapaposfx.cpp index 8483d8df..ef418f75 100644 --- a/audio/sysvad/APO/SwapAPO/swapaposfx.cpp +++ b/audio/sysvad/APO/SwapAPO/swapaposfx.cpp @@ -297,48 +297,48 @@ HRESULT CSwapAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) hr = papoSysFxInit3->pServiceProvider->QueryService(SID_AudioProcessingObjectLoggingService, IID_PPV_ARGS(&m_apoLoggingService)); IF_FAILED_JUMP(hr, Exit); - // SampleApo supports the new IAudioSystemEffects3 interface so it will receive APOInitSystemEffects3 + // SampleApo supports the new IAudioSystemEffects3 interface so it will receive APOInitSystemEffects3 // in pbyData if the audio driver has declared support for this. + // Windows should pass a valid collection. + ATLASSERT(papoSysFxInit3->pDeviceCollection != nullptr); + IF_TRUE_ACTION_JUMP(papoSysFxInit3->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + // Use IMMDevice to activate IAudioSystemEffectsPropertyStore that contains the default, user and // volatile settings. IMMDeviceCollection* deviceCollection = reinterpret_cast<APOInitSystemEffects3*>(pbyData)->pDeviceCollection; - if (deviceCollection != nullptr) - { - UINT32 numDevices; - wil::com_ptr_nothrow<IMMDevice> endpoint; + UINT32 numDevices; + // Get the endpoint on which this APO has been created + // (It is the last device in the device collection) + hr = deviceCollection->GetCount(&numDevices); + IF_FAILED_JUMP(hr, Exit); - // Get the endpoint on which this APO has been created - // (It is the last device in the device collection) - if (SUCCEEDED(deviceCollection->GetCount(&numDevices)) && numDevices > 0 && - SUCCEEDED(deviceCollection->Item(numDevices - 1, &endpoint))) - { - wil::unique_prop_variant activationParam; - hr = InitPropVariantFromCLSID(SWAP_APO_SFX_CONTEXT, &activationParam); - IF_FAILED_JUMP(hr, Exit); + hr = numDevices > 0 ? S_OK : E_UNEXPECTED; + IF_FAILED_JUMP(hr, Exit); - wil::com_ptr_nothrow<IAudioSystemEffectsPropertyStore> effectsPropertyStore; - hr = endpoint->Activate(__uuidof(effectsPropertyStore), CLSCTX_ALL, &activationParam, effectsPropertyStore.put_void()); - IF_FAILED_JUMP(hr, Exit); + hr = deviceCollection->Item(numDevices - 1, &m_audioEndpoint); + IF_FAILED_JUMP(hr, Exit); - // This is where an APO might want to open the volatile or default property stores as well - // Use STGM_READWRITE if IPropertyStore::SetValue is needed. - hr = effectsPropertyStore->OpenUserPropertyStore(STGM_READ, m_userStore.put()); - IF_FAILED_JUMP(hr, Exit); - } - } + wil::unique_prop_variant activationParam; + hr = InitPropVariantFromCLSID(SWAP_APO_SFX_CONTEXT, &activationParam); + IF_FAILED_JUMP(hr, Exit); - // Windows should pass a valid collection. - ATLASSERT(papoSysFxInit2->pDeviceCollection != nullptr); - IF_TRUE_ACTION_JUMP(papoSysFxInit3->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + wil::com_ptr_nothrow<IAudioSystemEffectsPropertyStore> effectsPropertyStore; + hr = m_audioEndpoint->Activate(__uuidof(effectsPropertyStore), CLSCTX_ALL, &activationParam, effectsPropertyStore.put_void()); + IF_FAILED_JUMP(hr, Exit); + + // This is where an APO might want to open the volatile or default property stores as well + // Use STGM_READWRITE if IPropertyStore::SetValue is needed. + hr = effectsPropertyStore->OpenUserPropertyStore(STGM_READ, m_userStore.put()); + IF_FAILED_JUMP(hr, Exit); // Get the IDeviceTopology and IConnector interfaces to communicate with this // APO's counterpart audio driver. This can be used for any proprietary // communication. - hr = papoSysFxInit3->pDeviceCollection->Item(papoSysFxInit3->nSoftwareIoDeviceInCollection, &m_device); + hr = papoSysFxInit3->pDeviceCollection->Item(papoSysFxInit3->nSoftwareIoDeviceInCollection, &m_deviceTopologyMMDevice); IF_FAILED_JUMP(hr, Exit); - hr = m_device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + hr = m_deviceTopologyMMDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); IF_FAILED_JUMP(hr, Exit); hr = spMyDeviceTopology->GetConnector(papoSysFxInit3->nSoftwareIoConnectorIndex, &spMyConnector); @@ -365,10 +365,10 @@ HRESULT CSwapAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) // Get the IDeviceTopology and IConnector interfaces to communicate with this // APO's counterpart audio driver. This can be used for any proprietary // communication. - hr = papoSysFxInit2->pDeviceCollection->Item(papoSysFxInit2->nSoftwareIoDeviceInCollection, &m_device); + hr = papoSysFxInit2->pDeviceCollection->Item(papoSysFxInit2->nSoftwareIoDeviceInCollection, &m_deviceTopologyMMDevice); IF_FAILED_JUMP(hr, Exit); - hr = m_device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + hr = m_deviceTopologyMMDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); IF_FAILED_JUMP(hr, Exit); hr = spMyDeviceTopology->GetConnector(papoSysFxInit2->nSoftwareIoConnectorIndex, &spMyConnector); @@ -407,7 +407,8 @@ HRESULT CSwapAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && - processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE && + processingMode != AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION), hr = E_INVALIDARG, Exit); m_AudioProcessingMode = processingMode; // @@ -640,7 +641,7 @@ HRESULT CSwapAPOSFX::SetAudioSystemEffectState(GUID effectId, AUDIO_SYSTEMEFFECT if (oldState != effectInfo.state) { SetEvent(m_hEffectsChangedEvent); - m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"SetAudioSystemEffectState - effect: " GUID_FORMAT_STRING L", state: %i", effectInfo.id, effectInfo.state); + m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"CSwapAPOSFX::SetAudioSystemEffectState - effect: " GUID_FORMAT_STRING L", state: %i", effectInfo.id, effectInfo.state); } m_EffectsLock.Leave(); @@ -733,8 +734,6 @@ HRESULT CSwapAPOSFX::GetApoNotificationRegistrationInfo(_Out_writes_(*count) APO *apoNotifications = nullptr; *count = 0; - RETURN_HR_IF_NULL(E_FAIL, m_device); - // Let the OS know what notifications we are interested in by returning an array of // APO_NOTIFICATION_DESCRIPTORs. constexpr DWORD numDescriptors = 1; @@ -746,7 +745,7 @@ HRESULT CSwapAPOSFX::GetApoNotificationRegistrationInfo(_Out_writes_(*count) APO // Our APO wants to get notified when a endpoint property changes on the audio endpoint. apoNotificationDescriptors[0].type = APO_NOTIFICATION_TYPE_ENDPOINT_PROPERTY_CHANGE; - (void)m_device.query_to(&apoNotificationDescriptors[0].audioEndpointPropertyChange.device); + (void)m_audioEndpoint.query_to(&apoNotificationDescriptors[0].audioEndpointPropertyChange.device); *apoNotifications = apoNotificationDescriptors.release(); *count = numDescriptors; @@ -772,7 +771,7 @@ void CSwapAPOSFX::HandleNotification(APO_NOTIFICATION *apoNotification) {PKEY_Endpoint_Enable_Channel_Swap_SFX, &m_fEnableSwapSFX}, }; - m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"HandleNotification - pkey: " GUID_FORMAT_STRING L" %d", GUID_FORMAT_ARGS(apoNotification->audioEndpointPropertyChange.propertyKey.fmtid), apoNotification->audioEndpointPropertyChange.propertyKey.pid); + m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"CSwapAPOSFX::HandleNotification - pkey: " GUID_FORMAT_STRING L" %d", GUID_FORMAT_ARGS(apoNotification->audioEndpointPropertyChange.propertyKey.fmtid), apoNotification->audioEndpointPropertyChange.propertyKey.pid); for (int i = 0; i < ARRAYSIZE(controls); i++) { diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj index 5b819cf3..aa5cc3e2 100644 --- a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj +++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -31,14 +23,14 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -46,7 +38,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -54,7 +46,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -62,23 +54,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>KMDF</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -99,12 +75,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>EndpointsCommon</TargetName> @@ -118,12 +88,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>EndpointsCommon</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>EndpointsCommon</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>EndpointsCommon</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> @@ -204,46 +168,6 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="a2dphpminwavert.cpp" /> <ClCompile Include="a2dphpspeakertopo.cpp" /> @@ -280,4 +204,4 @@ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp b/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp index 34477606..8c3979f2 100644 --- a/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp +++ b/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp @@ -57,9 +57,9 @@ Remarks: } KSAUDIOENGINE_DESCRIPTOR, *PKSAUDIOENGINE_DESCRIPTOR; The fields are defined as: - nHostPinId – The ID of the pin factory connected to the audio engine node that is intended for host processed audio data. This is the pin factory on which a software audio engine will run. - nOffloadPinId – The ID of the pin factory connected to the audio engine node that is intended for offloaded streams. - nLoopbackPinId – The ID of the pin factory connected to the audio engine that is intended for supplying a post-mix loopback or reference stream. + nHostPinId - The ID of the pin factory connected to the audio engine node that is intended for host processed audio data. This is the pin factory on which a software audio engine will run. + nOffloadPinId - The ID of the pin factory connected to the audio engine node that is intended for offloaded streams. + nLoopbackPinId - The ID of the pin factory connected to the audio engine that is intended for supplying a post-mix loopback or reference stream. All pin ids need to be unique for each audio engine node. diff --git a/audio/sysvad/EndpointsCommon/mintopo.cpp b/audio/sysvad/EndpointsCommon/mintopo.cpp index c1e4bc14..9fb2cc21 100644 --- a/audio/sysvad/EndpointsCommon/mintopo.cpp +++ b/audio/sysvad/EndpointsCommon/mintopo.cpp @@ -581,6 +581,100 @@ Return Value: //============================================================================= #pragma code_seg("PAGE") NTSTATUS +CMiniportTopology::PropertyHandlerJackDescription3 +( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions, + _In_ ULONG ConfigId +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION3 ) + +Arguments: + + PropertyRequest - + cJackDescriptions - # of elements in the jack descriptions array. + JackDescriptions - Array of jack descriptions pointers. + ConfigId - Current endpoint config id + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[PropertyHandlerJackDescription3]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + ULONG nPinId = (ULONG)-1; + + if (PropertyRequest->InstanceSize >= sizeof(ULONG)) + { + nPinId = *(PULONG(PropertyRequest->Instance)); + + if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL)) + { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ntStatus = + PropertyHandler_BasicSupport + ( + PropertyRequest, + KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET, + VT_ILLEGAL + ); + } + else + { + ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION3); + + if (PropertyRequest->ValueSize == 0) + { + PropertyRequest->ValueSize = cbNeeded; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (PropertyRequest->ValueSize < cbNeeded) + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + else + { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value; + PKSJACK_DESCRIPTION3 pDesc = (PKSJACK_DESCRIPTION3)(pMI+1); + + pMI->Size = cbNeeded; + pMI->Count = 1; + + RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION3)); + + // + // hardware config id + // + pDesc->ConfigId = ConfigId; + + ntStatus = STATUS_SUCCESS; + } + } + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS CMiniportTopology::PropertyHandlerAudioResourceGroup ( _In_ PPCPROPERTY_REQUEST PropertyRequest diff --git a/audio/sysvad/EndpointsCommon/mintopo.h b/audio/sysvad/EndpointsCommon/mintopo.h index 596e13b1..f0bae44d 100644 --- a/audio/sysvad/EndpointsCommon/mintopo.h +++ b/audio/sysvad/EndpointsCommon/mintopo.h @@ -100,6 +100,14 @@ public: _In_ DWORD JackCapabilities ); + NTSTATUS PropertyHandlerJackDescription3 + ( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions, + _In_ ULONG ConfigId + ); + NTSTATUS PropertyHandlerAudioResourceGroup ( _In_ PPCPROPERTY_REQUEST PropertyRequest diff --git a/audio/sysvad/EndpointsCommon/minwavert.cpp b/audio/sysvad/EndpointsCommon/minwavert.cpp index bd81c110..c6b8e8c3 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.cpp +++ b/audio/sysvad/EndpointsCommon/minwavert.cpp @@ -3452,7 +3452,8 @@ NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() PAGED_CODE(); NTSTATUS ntStatus; - UNICODE_STRING parametersPath; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength @@ -3461,30 +3462,37 @@ NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() { NULL, 0, NULL, NULL, 0, NULL, 0 } }; - RtlInitUnicodeString(¶metersPath, NULL); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - // The sizeof(WCHAR) is added to the maximum length, for allowing a space for null termination of the string. - parametersPath.MaximumLength = - g_RegistryPath.Length + sizeof(L"\\Parameters") + sizeof(WCHAR); - - parametersPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINWAVERT_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, g_RegistryPath.Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_VERBOSE, ("RtlQueryRegistryValues failed, using default values, 0x%x", ntStatus)); + // + // Don't return error because we will operate with default values. + // + } - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return ntStatus; } diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.cpp b/audio/sysvad/EndpointsCommon/minwavertstream.cpp index 08467e05..adea0c82 100644 --- a/audio/sysvad/EndpointsCommon/minwavertstream.cpp +++ b/audio/sysvad/EndpointsCommon/minwavertstream.cpp @@ -121,7 +121,8 @@ NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings() PAGED_CODE(); NTSTATUS ntStatus; - UNICODE_STRING parametersPath; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength @@ -136,30 +137,37 @@ NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings() { NULL, 0, NULL, NULL, 0, NULL, 0 } }; - RtlInitUnicodeString(¶metersPath, NULL); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - // The sizeof(WCHAR) is added to the maximum length, for allowing a space for null termination of the string. - parametersPath.MaximumLength = - g_RegistryPath.Length + sizeof(L"\\Parameters") + sizeof(WCHAR); - - parametersPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINWAVERT_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, g_RegistryPath.Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_VERBOSE, ("RtlQueryRegistryValues failed, using default values, 0x%x", ntStatus)); + // + // Don't return error because we will operate with default values. + // + } - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return ntStatus; } diff --git a/audio/sysvad/EndpointsCommon/speakertopo.cpp b/audio/sysvad/EndpointsCommon/speakertopo.cpp index fba72036..002b1174 100644 --- a/audio/sysvad/EndpointsCommon/speakertopo.cpp +++ b/audio/sysvad/EndpointsCommon/speakertopo.cpp @@ -75,6 +75,15 @@ Return Value: 0 // jack capabilities ); } + else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION3) + { + ntStatus = pMiniport->PropertyHandlerJackDescription3( + PropertyRequest, + ARRAYSIZE(SpeakerJackDescriptions), + SpeakerJackDescriptions, + 42 // jack config id + ); + } } else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioResourceManagement)) { diff --git a/audio/sysvad/EndpointsCommon/speakertoptable.h b/audio/sysvad/EndpointsCommon/speakertoptable.h index 3d31d7a4..ea3890f7 100644 --- a/audio/sysvad/EndpointsCommon/speakertoptable.h +++ b/audio/sysvad/EndpointsCommon/speakertoptable.h @@ -142,6 +142,13 @@ PCPROPERTY_ITEM PropertiesSpeakerTopoFilter[] = PropertyHandler_SpeakerTopoFilter }, { + &KSPROPSETID_Jack, + KSPROPERTY_JACK_DESCRIPTION3, + KSPROPERTY_TYPE_GET | + KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_SpeakerTopoFilter + }, + { &KSPROPSETID_AudioResourceManagement, KSPROPERTY_AUDIORESOURCEMANAGEMENT_RESOURCEGROUP, KSPROPERTY_TYPE_SET, diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj index d1675201..592fefb2 100644 --- a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj +++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj @@ -5,18 +5,10 @@ <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -32,14 +24,14 @@ <SupportsPackaging>false</SupportsPackaging> <RequiresPackageProject>true</RequiresPackageProject> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{C1851F27-BDAA-4DF1-8CA5-9D0176FD2B33}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> @@ -47,7 +39,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> @@ -55,7 +47,7 @@ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> @@ -63,23 +55,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> @@ -100,12 +76,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>KeywordDetectorContosoAdapter</TargetName> @@ -119,46 +89,24 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>KeywordDetectorContosoAdapter</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>KeywordDetectorContosoAdapter</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>KeywordDetectorContosoAdapter</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + <EntryPointSymbol>_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -257,54 +205,6 @@ <ModuleDefinitionFile>KeywordDetectorContosoAdapter.def</ModuleDefinitionFile> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> - <ModuleDefinitionFile>KeywordDetectorContosoAdapter.def</ModuleDefinitionFile> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> - <ModuleDefinitionFile>KeywordDetectorContosoAdapter.def</ModuleDefinitionFile> - </Link> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="dllmain.cpp" /> <ClCompile Include="KeywordDetectorContosoAdapter.cpp" /> @@ -325,4 +225,4 @@ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/Package/package.VcxProj b/audio/sysvad/Package/package.VcxProj index 0d3bb44a..9af11965 100644 --- a/audio/sysvad/Package/package.VcxProj +++ b/audio/sysvad/Package/package.VcxProj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -59,14 +51,6 @@ <SampleGuid>{E9D167E6-E633-4284-8F02-FF86DF3B6D7F}</SampleGuid> <RootNamespace>$(MSBuildProjectName)</RootNamespace> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>true</UseDebugLibraries> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>false</UseDebugLibraries> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>true</UseDebugLibraries> @@ -107,16 +91,6 @@ <VerifyDrivers /> <VerifyFlags>133563</VerifyFlags> </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <DriverSign> <FileDigestAlgorithm>sha256</FileDigestAlgorithm> @@ -127,7 +101,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <DriverSign> <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> @@ -140,4 +114,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj index 6e4e4c44..8e6e6ee4 100644 --- a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj +++ b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj @@ -1,22 +1,14 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -33,7 +25,7 @@ <SupportsPackaging>false</SupportsPackaging> <RequiresPackageProject>true</RequiresPackageProject> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{2A9A946E-F017-4E0D-BF75-AD81E7E97D64}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> @@ -69,22 +61,6 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> <OutDir>$(IntDir)</OutDir> @@ -101,12 +77,6 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> @@ -196,50 +166,6 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </Midl> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </Midl> - </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>TabletAudioSample</TargetName> </PropertyGroup> @@ -252,12 +178,6 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>TabletAudioSample</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>TabletAudioSample</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>TabletAudioSample</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> @@ -354,50 +274,6 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> - </Link> - <ClCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </ResourceCompile> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> - </Link> - <ClCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </ResourceCompile> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="..\A2dpHpDevice.cpp" /> <ClCompile Include="..\adapter.cpp" /> @@ -427,4 +303,4 @@ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/adapter.cpp b/audio/sysvad/adapter.cpp index ef48e5f4..0f44c593 100644 --- a/audio/sysvad/adapter.cpp +++ b/audio/sysvad/adapter.cpp @@ -246,10 +246,10 @@ _Dispatch_type_(IRP_MJ_PNP) DRIVER_DISPATCH PnpHandler; // -// Rendering streams are saved to a file by default. Use the registry value -// DoNotCreateDataFiles (DWORD) > 0 to override this default. +// Rendering streams are not saved to a file by default. Use the registry value +// DoNotCreateDataFiles (DWORD) = 0 to override this default. // -DWORD g_DoNotCreateDataFiles = 0; // default is off. +DWORD g_DoNotCreateDataFiles = 1; // default is off. DWORD g_DisableToneGenerator = 0; // default is to generate tones. UNICODE_STRING g_RegistryPath; // This is used to store the registry settings path for the driver @@ -425,7 +425,8 @@ Returns: { NTSTATUS ntStatus; - UNICODE_STRING parametersPath; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DoNotCreateDataFiles", &g_DoNotCreateDataFiles, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DoNotCreateDataFiles, sizeof(ULONG)}, @@ -441,29 +442,27 @@ Returns: DPF(D_TERSE, ("[GetRegistrySettings]")); - PAGED_CODE(); - - RtlInitUnicodeString(¶metersPath, NULL); + PAGED_CODE(); + UNREFERENCED_PARAMETER(RegistryPath); - parametersPath.MaximumLength = - RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(WCHAR); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - parametersPath.Buffer = (PWCH) ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINADAPTER_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, RegistryPath->Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); - - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); if (!NT_SUCCESS(ntStatus)) { @@ -485,10 +484,10 @@ Returns: DPF(D_VERBOSE, ("DisableUsbSideband: %u", g_DisableUsbSideband)); #endif // SYSVAD_USB_SIDEBAND - // - // Cleanup. - // - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return STATUS_SUCCESS; } @@ -537,15 +536,6 @@ Return Value: ntStatus, DPF(D_ERROR, ("Registry path copy error 0x%x", ntStatus)), Done); - - // - // Get registry configuration. - // - ntStatus = GetRegistrySettings(RegistryPathName); - IF_FAILED_ACTION_JUMP( - ntStatus, - DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)), - Done); WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK); // @@ -569,6 +559,15 @@ Return Value: Done); // + // Get registry configuration. + // + ntStatus = GetRegistrySettings(RegistryPathName); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)), + Done); + + // // Tell the class driver to initialize the driver. // ntStatus = PcInitializeAdapterDriver(DriverObject, diff --git a/audio/sysvad/common.cpp b/audio/sysvad/common.cpp index 9bc3e644..1334411e 100644 --- a/audio/sysvad/common.cpp +++ b/audio/sysvad/common.cpp @@ -50,7 +50,6 @@ Abstract: // CSaveData statics //----------------------------------------------------------------------------- -PSAVEWORKER_PARAM CSaveData::m_pWorkItems = NULL; PDEVICE_OBJECT CSaveData::m_pDeviceObject = NULL; //============================================================================= // Classes @@ -642,8 +641,6 @@ Return Value: delete m_pHW; m_pHW = NULL; } - - CSaveData::DestroyWorkItems(); SAFE_RELEASE(m_pPortClsEtwHelper); SAFE_RELEASE(m_pServiceGroupWave); @@ -841,8 +838,6 @@ Return Value: // Initialize SaveData class. // CSaveData::SetDeviceObject(DeviceObject); //device object is needed by CSaveData - ntStatus = CSaveData::InitializeWorkItems(DeviceObject); - IF_FAILED_JUMP(ntStatus, Done); Done: return ntStatus; diff --git a/audio/sysvad/savedata.cpp b/audio/sysvad/savedata.cpp index cb5f5cfc..39789f3b 100644 --- a/audio/sysvad/savedata.cpp +++ b/audio/sysvad/savedata.cpp @@ -47,12 +47,13 @@ Abstract: #define DEFAULT_FRAME_SIZE PAGE_SIZE * 4 #define DEFAULT_BUFFER_SIZE DEFAULT_FRAME_SIZE * DEFAULT_FRAME_COUNT -#define DEFAULT_FILE_NAME L"\\DosDevices\\C:\\STREAM" -#define OSDATA_FILE_NAME L"\\DosDevices\\O:\\STREAM" +#define DEFAULT_FILE_FOLDER1 L"\\DriverData\\Audio_Samples" +#define DEFAULT_FILE_FOLDER2 L"\\DriverData\\Audio_Samples\\Sysvad" +#define DEFAULT_FILE_NAME L"\\DriverData\\Audio_Samples\\Sysvad\\STREAM" #define OFFLOAD_FILE_NAME L"OFFLOAD" #define HOST_FILE_NAME L"HOST" -#define MAX_WORKER_ITEM_COUNT 15 +#define MAX_WORKER_ITEM_COUNT 8 //============================================================================= // Statics @@ -91,6 +92,7 @@ CSaveData::CSaveData() m_DataHeader.dwData = DATA_TAG; m_DataHeader.dwDataLength = 0; + RtlZeroMemory(&m_FileName, sizeof(m_FileName)); RtlZeroMemory(&m_objectAttributes, sizeof(m_objectAttributes)); } // CSaveData @@ -101,6 +103,12 @@ CSaveData::~CSaveData() DPF_ENTER(("[CSaveData::~CSaveData]")); + // + // All write activity is done at this point (see acquire->stop stream transition). + // Safe to call even if the Initialize function failed. + // + DestroyWorkItems(); + // Update the wave header in data file with real file size. // if(m_pFilePtr) @@ -415,6 +423,7 @@ CSaveData::GetNewWorkItem { LARGE_INTEGER timeOut = { 0 }; NTSTATUS ntStatus; + PSAVEWORKER_PARAM saveWorker = NULL; for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) { @@ -430,13 +439,16 @@ CSaveData::GetNewWorkItem if (STATUS_SUCCESS == ntStatus) { if (m_pWorkItems[i].WorkItem) - return &(m_pWorkItems[i]); - else - return NULL; + { + saveWorker = &(m_pWorkItems[i]); + KeResetEvent(&saveWorker->EventDone); + break; + } } } - return NULL; + + return saveWorker; } // GetNewWorkItem #pragma code_seg("PAGE") @@ -449,13 +461,13 @@ CSaveData::Initialize { PAGED_CODE(); - NTSTATUS ntStatus = STATUS_SUCCESS; - WCHAR szTemp[MAX_PATH]; - size_t cLen; - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING osDataVolumeString; - HANDLE osDataFileHandle = NULL; - IO_STATUS_BLOCK ioStatusBlock; + NTSTATUS ntStatus = STATUS_SUCCESS; + WCHAR szTemp[MAX_PATH]; + size_t cLen = 0; + IO_STATUS_BLOCK ioStatusBlock = {0}; + HANDLE fileHandle; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING fileName; DPF_ENTER(("[CSaveData::Initialize]")); @@ -468,47 +480,74 @@ CSaveData::Initialize m_ulStreamId++; } - // Probe if OSData volume exists. - // - RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_probe.txt", OSDATA_FILE_NAME); - RtlInitUnicodeString(&osDataVolumeString, szTemp); - InitializeObjectAttributes - ( - &objectAttributes, - &osDataVolumeString, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL - ); + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER1); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); - ntStatus = - ZwCreateFile - ( - &osDataFileHandle, - GENERIC_WRITE | SYNCHRONIZE, + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, - FILE_OVERWRITE_IF, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, - 0 - ); + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER2); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, + &objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + } + } + if (NT_SUCCESS(ntStatus)) { - ZwClose(osDataFileHandle); + // Allocate data file name. + // + RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", DEFAULT_FILE_NAME, _bOffloaded ? OFFLOAD_FILE_NAME : HOST_FILE_NAME, _bOffloaded ? m_ulOffloadStreamId : m_ulStreamId); + m_FileName.Length = 0; + ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); } - // Allocate data file name. - // - RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", NT_SUCCESS(ntStatus) ? OSDATA_FILE_NAME : DEFAULT_FILE_NAME, _bOffloaded ? OFFLOAD_FILE_NAME : HOST_FILE_NAME, _bOffloaded ? m_ulOffloadStreamId : m_ulStreamId); - m_FileName.Length = 0; - ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); if (NT_SUCCESS(ntStatus)) { - m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL + m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL m_FileName.Buffer = (PWSTR) ExAllocatePool2 ( @@ -572,6 +611,13 @@ CSaveData::Initialize // KeInitializeMutex( &m_FileSync, 1 ) ; + // Allocate work-items. + // + if (NT_SUCCESS(ntStatus)) + { + ntStatus = InitializeWorkItems(m_pDeviceObject); + } + // Open the data file. // if (NT_SUCCESS(ntStatus)) @@ -586,7 +632,7 @@ CSaveData::Initialize ( &m_objectAttributes, &m_FileName, - OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); @@ -896,7 +942,6 @@ CSaveData::SaveFrame pParam->ulFrameNo = ulFrameNo; pParam->ulDataSize = ulDataSize; pParam->pData = m_pDataBuffer + ulFrameNo * m_ulFrameSize; - KeResetEvent(&pParam->EventDone); IoQueueWorkItem(pParam->WorkItem, SaveFrameWorkerCallback, CriticalWorkQueue, (PVOID)pParam); } diff --git a/audio/sysvad/savedata.h b/audio/sysvad/savedata.h index a1525bda..94221025 100644 --- a/audio/sysvad/savedata.h +++ b/audio/sysvad/savedata.h @@ -98,7 +98,7 @@ protected: static PDEVICE_OBJECT m_pDeviceObject; static ULONG m_ulStreamId; static ULONG m_ulOffloadStreamId; - static PSAVEWORKER_PARAM m_pWorkItems; + PSAVEWORKER_PARAM m_pWorkItems; BOOL m_fWriteDisabled; @@ -108,11 +108,11 @@ public: CSaveData(); ~CSaveData(); - static NTSTATUS InitializeWorkItems + NTSTATUS InitializeWorkItems ( _In_ PDEVICE_OBJECT DeviceObject ); - static void DestroyWorkItems + void DestroyWorkItems ( void ); @@ -120,7 +120,7 @@ public: ( _In_ BOOL fDisable ); - static PSAVEWORKER_PARAM GetNewWorkItem + PSAVEWORKER_PARAM GetNewWorkItem ( void ); diff --git a/audio/sysvad/sysvad.sln b/audio/sysvad/sysvad.sln index 39041665..8ee722a7 100644 --- a/audio/sysvad/sysvad.sln +++ b/audio/sysvad/sysvad.sln @@ -34,107 +34,73 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 - Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|ARM64 = Release|ARM64 - Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.ActiveCfg = Debug|ARM64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.Build.0 = Debug|ARM64 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.ActiveCfg = Debug|Win32 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.Build.0 = Debug|Win32 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.ActiveCfg = Debug|x64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.Build.0 = Debug|x64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.ActiveCfg = Release|ARM64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.Build.0 = Release|ARM64 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.ActiveCfg = Release|Win32 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.Build.0 = Release|Win32 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.ActiveCfg = Release|x64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Build.0 = Release|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM64.ActiveCfg = Debug|ARM64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM64.Build.0 = Debug|ARM64 - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|Win32.ActiveCfg = Debug|Win32 - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|Win32.Build.0 = Debug|Win32 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.ActiveCfg = Debug|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.Build.0 = Debug|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM64.ActiveCfg = Release|ARM64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM64.Build.0 = Release|ARM64 - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.ActiveCfg = Release|Win32 - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.Build.0 = Release|Win32 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.ActiveCfg = Release|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.Build.0 = Release|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.ActiveCfg = Debug|ARM64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.Build.0 = Debug|ARM64 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.ActiveCfg = Debug|Win32 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.Build.0 = Debug|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.ActiveCfg = Debug|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.Build.0 = Debug|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.ActiveCfg = Release|ARM64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.Build.0 = Release|ARM64 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.ActiveCfg = Release|Win32 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.Build.0 = Release|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.ActiveCfg = Release|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.Build.0 = Release|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.ActiveCfg = Debug|ARM64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.Build.0 = Debug|ARM64 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.ActiveCfg = Debug|Win32 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.Build.0 = Debug|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.ActiveCfg = Debug|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.Build.0 = Debug|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.ActiveCfg = Release|ARM64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.Build.0 = Release|ARM64 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.ActiveCfg = Release|Win32 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.Build.0 = Release|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.ActiveCfg = Release|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.Build.0 = Release|x64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|ARM64.ActiveCfg = Debug|ARM64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|ARM64.Build.0 = Debug|ARM64 - {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|Win32.ActiveCfg = Debug|Win32 - {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|Win32.Build.0 = Debug|Win32 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|x64.ActiveCfg = Debug|x64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|x64.Build.0 = Debug|x64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|ARM64.ActiveCfg = Release|ARM64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|ARM64.Build.0 = Release|ARM64 - {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|Win32.ActiveCfg = Release|Win32 - {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|Win32.Build.0 = Release|Win32 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|x64.ActiveCfg = Release|x64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|x64.Build.0 = Release|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|ARM64.ActiveCfg = Debug|ARM64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|ARM64.Build.0 = Debug|ARM64 - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|Win32.ActiveCfg = Debug|Win32 - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|Win32.Build.0 = Debug|Win32 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|x64.ActiveCfg = Debug|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|x64.Build.0 = Debug|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|ARM64.ActiveCfg = Release|ARM64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|ARM64.Build.0 = Release|ARM64 - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|Win32.ActiveCfg = Release|Win32 - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|Win32.Build.0 = Release|Win32 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|x64.ActiveCfg = Release|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|x64.Build.0 = Release|x64 {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|ARM64.ActiveCfg = Debug|ARM64 {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|ARM64.Build.0 = Debug|ARM64 - {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|Win32.ActiveCfg = Debug|Win32 - {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|Win32.Build.0 = Debug|Win32 {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|x64.ActiveCfg = Debug|x64 {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|x64.Build.0 = Debug|x64 {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|ARM64.ActiveCfg = Release|ARM64 {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|ARM64.Build.0 = Release|ARM64 - {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|Win32.ActiveCfg = Release|Win32 - {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|Win32.Build.0 = Release|Win32 {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|x64.ActiveCfg = Release|x64 {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|x64.Build.0 = Release|x64 {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Debug|ARM64.ActiveCfg = Debug|ARM64 {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Debug|ARM64.Build.0 = Debug|ARM64 - {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Debug|Win32.ActiveCfg = Debug|Win32 - {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Debug|Win32.Build.0 = Debug|Win32 {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Debug|x64.ActiveCfg = Debug|x64 {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Debug|x64.Build.0 = Debug|x64 {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Release|ARM64.ActiveCfg = Release|ARM64 {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Release|ARM64.Build.0 = Release|ARM64 - {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Release|Win32.ActiveCfg = Release|Win32 - {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Release|Win32.Build.0 = Release|Win32 {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Release|x64.ActiveCfg = Release|x64 {83A1B9B0-3CB7-4249-ADEC-C336B0EDDE76}.Release|x64.Build.0 = Release|x64 EndGlobalSection |
