From 995e20f6dbca7ad10a039fa62a2de69eed092ffc Mon Sep 17 00:00:00 2001 From: Girish Pattabiraman Date: Mon, 12 Nov 2018 18:08:19 -0800 Subject: RS5 Updates (#311) * Format Changes ============== * Add KSEVENT_PINCAPS_FORMATCHANGE to Bluetooth HFP Endpoints * Remove 8 bit formats from Bluetooth HFP Endpoints Name Template ============== * Bluetooth Endpoints are now based on templates in INF and then customized with endpoints specific data Sideband Common Interface for future Sideband buses =================================================== * Add ISidebandDevice * Add current directory to TabletAudioSample include path. Remove unused compiler flags. * RS4 bug fixes * Replace FastMutex with Spinlock for DeviceFormatsAndModes to work well at DISPATCH_LEVEL * Resync with Microsoft-master branch * Replace FastMutex with Spinlock for DeviceFormatsAndModes to work well at DISPATCH_LEVEL * RS5 updates: - USB Sideband implementation - Power management options: _USE_IPortClsRuntimePower, _USE_SingleComponentMultiFxStates --- audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj | 212 + audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj | 212 + .../sysvad/EndpointsCommon/EndpointsCommon.vcxproj | 168 +- .../MiniportStreamAudioEngineNode.cpp | 12 +- audio/sysvad/EndpointsCommon/UsbHsDeviceFormats.h | 272 ++ audio/sysvad/EndpointsCommon/mintopo.cpp | 18 +- audio/sysvad/EndpointsCommon/mintopo.h | 28 +- audio/sysvad/EndpointsCommon/minwavert.cpp | 12 +- audio/sysvad/EndpointsCommon/minwavert.h | 24 +- audio/sysvad/EndpointsCommon/minwavertstream.cpp | 40 +- audio/sysvad/EndpointsCommon/minwavertstream.h | 8 +- audio/sysvad/EndpointsCommon/sources | 6 +- audio/sysvad/EndpointsCommon/usbhsmictopo.cpp | 349 ++ audio/sysvad/EndpointsCommon/usbhsmictopo.h | 40 + audio/sysvad/EndpointsCommon/usbhsmictoptable.h | 297 ++ audio/sysvad/EndpointsCommon/usbhsmicwavtable.h | 483 ++ audio/sysvad/EndpointsCommon/usbhsminipairs.h | 204 + audio/sysvad/EndpointsCommon/usbhsminwavert.cpp | 211 + audio/sysvad/EndpointsCommon/usbhsspeakertopo.cpp | 113 + audio/sysvad/EndpointsCommon/usbhsspeakertopo.h | 30 + .../sysvad/EndpointsCommon/usbhsspeakertoptable.h | 176 + .../sysvad/EndpointsCommon/usbhsspeakerwavtable.h | 815 ++++ audio/sysvad/EndpointsCommon/usbhstopo.cpp | 538 +++ audio/sysvad/EndpointsCommon/usbhstopo.h | 65 + .../KeywordDetectorContosoAdapter.vcxproj | 192 + audio/sysvad/Package/package.VcxProj | 32 + .../PhoneAudioSample/PhoneAudioSample.vcxproj | 306 +- audio/sysvad/PhoneAudioSample/sources | 2 +- .../TabletAudioSample/TabletAudioSample.vcxproj | 308 +- audio/sysvad/TabletAudioSample/sources | 2 +- audio/sysvad/UsbHsDevice.cpp | 5036 ++++++++++++++++++++ audio/sysvad/UsbHsDevice.h | 623 +++ audio/sysvad/adapter.cpp | 72 +- audio/sysvad/common.cpp | 902 ++++ audio/sysvad/common.h | 34 +- audio/sysvad/sources.inc | 1 + audio/sysvad/sysvad.sln | 60 + 37 files changed, 11750 insertions(+), 153 deletions(-) create mode 100644 audio/sysvad/EndpointsCommon/UsbHsDeviceFormats.h create mode 100644 audio/sysvad/EndpointsCommon/usbhsmictopo.cpp create mode 100644 audio/sysvad/EndpointsCommon/usbhsmictopo.h create mode 100644 audio/sysvad/EndpointsCommon/usbhsmictoptable.h create mode 100644 audio/sysvad/EndpointsCommon/usbhsmicwavtable.h create mode 100644 audio/sysvad/EndpointsCommon/usbhsminipairs.h create mode 100644 audio/sysvad/EndpointsCommon/usbhsminwavert.cpp create mode 100644 audio/sysvad/EndpointsCommon/usbhsspeakertopo.cpp create mode 100644 audio/sysvad/EndpointsCommon/usbhsspeakertopo.h create mode 100644 audio/sysvad/EndpointsCommon/usbhsspeakertoptable.h create mode 100644 audio/sysvad/EndpointsCommon/usbhsspeakerwavtable.h create mode 100644 audio/sysvad/EndpointsCommon/usbhstopo.cpp create mode 100644 audio/sysvad/EndpointsCommon/usbhstopo.h create mode 100644 audio/sysvad/UsbHsDevice.cpp create mode 100644 audio/sysvad/UsbHsDevice.h diff --git a/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj b/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj index 8e6ce26d..5fc4b06a 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj +++ b/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj @@ -1,10 +1,26 @@ + + Debug + ARM + + + Debug + ARM64 + Debug Win32 + + Release + ARM + + + Release + ARM64 + Release Win32 @@ -37,6 +53,15 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + False + Universal + false + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 True @@ -46,6 +71,15 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + True + Universal + false + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 False @@ -55,6 +89,15 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + False + Universal + false + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 True @@ -64,6 +107,15 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + True + Universal + false + + WindowsApplicationForDrivers10.0 + DynamicLibrary + $(IntDir) @@ -71,64 +123,124 @@ + + + + + + + + + + + + DelayAPO + + DelayAPO + DelayAPO + + DelayAPO + DelayAPO + + DelayAPO + DelayAPO + + DelayAPO + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + Dynamic + + Dynamic + Dynamic + + Dynamic + Dynamic + + Dynamic + Dynamic + + Dynamic + true @@ -153,6 +265,31 @@ /ignore:4217,4049 %(AdditionalOptions) + + + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;. + + + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib + DelayAPODll.def + /ignore:4217,4049 %(AdditionalOptions) + + true @@ -177,6 +314,31 @@ /ignore:4217,4049 %(AdditionalOptions) + + + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;. + + + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib + DelayAPODll.def + /ignore:4217,4049 %(AdditionalOptions) + + true @@ -201,6 +363,31 @@ /ignore:4217,4049 %(AdditionalOptions) + + + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;. + + + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib + DelayAPODll.def + /ignore:4217,4049 %(AdditionalOptions) + + true @@ -225,6 +412,31 @@ /ignore:4217,4049 %(AdditionalOptions) + + + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;. + + + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib + DelayAPODll.def + /ignore:4217,4049 %(AdditionalOptions) + + diff --git a/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj b/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj index 295833ea..4ab6f2e4 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj +++ b/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj @@ -1,10 +1,26 @@  + + Debug + ARM + + + Debug + ARM64 + Debug Win32 + + Release + ARM + + + Release + ARM64 + Release Win32 @@ -37,6 +53,15 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + False + Universal + false + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 True @@ -46,6 +71,15 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + True + Universal + false + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 False @@ -55,6 +89,15 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + False + Universal + false + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 True @@ -64,6 +107,15 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + True + Universal + false + + WindowsApplicationForDrivers10.0 + DynamicLibrary + $(IntDir) @@ -71,64 +123,124 @@ + + + + + + + + + + + + SwapAPO + + SwapAPO + SwapAPO + + SwapAPO + SwapAPO + + SwapAPO + SwapAPO + + SwapAPO + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + Dynamic + + Dynamic + Dynamic + + Dynamic + Dynamic + + Dynamic + Dynamic + + Dynamic + true @@ -153,6 +265,31 @@ /ignore:4217,4049 %(AdditionalOptions) + + + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;. + + + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib + SwapAPODll.def + /ignore:4217,4049 %(AdditionalOptions) + + true @@ -177,6 +314,31 @@ /ignore:4217,4049 %(AdditionalOptions) + + + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;. + + + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib + SwapAPODll.def + /ignore:4217,4049 %(AdditionalOptions) + + true @@ -201,6 +363,31 @@ /ignore:4217,4049 %(AdditionalOptions) + + + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;. + + + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib + SwapAPODll.def + /ignore:4217,4049 %(AdditionalOptions) + + true @@ -225,6 +412,31 @@ /ignore:4217,4049 %(AdditionalOptions) + + + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;. + + + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib + SwapAPODll.def + /ignore:4217,4049 %(AdditionalOptions) + + diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj index 255bb57a..7fda3a23 100644 --- a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj +++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj @@ -1,10 +1,26 @@  + + Debug + ARM + + + Debug + ARM64 + Debug Win32 + + Release + ARM + + + Release + ARM64 + Release Win32 @@ -35,6 +51,14 @@ WindowsKernelModeDriver10.0 StaticLibrary + + Windows10 + False + Universal + KMDF + WindowsKernelModeDriver10.0 + StaticLibrary + Windows10 True @@ -43,6 +67,14 @@ WindowsKernelModeDriver10.0 StaticLibrary + + Windows10 + True + Universal + KMDF + WindowsKernelModeDriver10.0 + StaticLibrary + Windows10 False @@ -51,6 +83,14 @@ WindowsKernelModeDriver10.0 StaticLibrary + + Windows10 + False + Universal + KMDF + WindowsKernelModeDriver10.0 + StaticLibrary + Windows10 True @@ -59,6 +99,14 @@ WindowsKernelModeDriver10.0 StaticLibrary + + Windows10 + True + Universal + KMDF + WindowsKernelModeDriver10.0 + StaticLibrary + $(IntDir) @@ -66,94 +114,186 @@ + + + + + + + + + + + + EndpointsCommon + + EndpointsCommon + EndpointsCommon + + EndpointsCommon + EndpointsCommon + + EndpointsCommon + EndpointsCommon + + EndpointsCommon + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_ 4595;%(DisableSpecificWarnings) %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND + + + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_ + + + 4595;%(DisableSpecificWarnings) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_ + + + 4595;%(DisableSpecificWarnings) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND + + + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_ 4595;%(DisableSpecificWarnings) %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_ 4595;%(DisableSpecificWarnings) %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND + + + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_ + + + 4595;%(DisableSpecificWarnings) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_ + + + 4595;%(DisableSpecificWarnings) + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND + + + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_ 4595;%(DisableSpecificWarnings) %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND @@ -171,6 +311,10 @@ + + + + diff --git a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp index c3da83b9..1b0f13f1 100644 --- a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp +++ b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp @@ -776,13 +776,13 @@ NTSTATUS CMiniportWaveRTStream::SetCurrentWritePosition(_In_ ULONG _ulCurrentWr NTSTATUS ntStatus; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined (SYSVAD_USB_SIDEBAND) if (m_SidebandStarted) { ntStatus = GetSidebandStreamNtStatus(); IF_FAILED_JUMP(ntStatus, Done); } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined (SYSVAD_USB_SIDEBAND) // // Basic validation. WritePosition indicates the position (1-based) of the last valid byte. @@ -872,13 +872,13 @@ NTSTATUS CMiniportWaveRTStream::GetPositions NTSTATUS ntStatus; LARGE_INTEGER ilQPC; KIRQL oldIrql; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (m_SidebandStarted) { ntStatus = GetSidebandStreamNtStatus(); IF_FAILED_JUMP(ntStatus, Done); } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) // Update *_pullLinearBufferPosition with the the number of bytes fetched from waveRT ever since a stream got set into RUN // state. @@ -909,9 +909,9 @@ NTSTATUS CMiniportWaveRTStream::GetPositions ntStatus = STATUS_SUCCESS; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) Done: -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) return ntStatus; } diff --git a/audio/sysvad/EndpointsCommon/UsbHsDeviceFormats.h b/audio/sysvad/EndpointsCommon/UsbHsDeviceFormats.h new file mode 100644 index 00000000..720bfa9f --- /dev/null +++ b/audio/sysvad/EndpointsCommon/UsbHsDeviceFormats.h @@ -0,0 +1,272 @@ +//---------------------------------------------------------------------------- +// +// Formats +// This reflects the Data formats of the hardware mixer output +// Hardware vendor should retrieve these formats from the hardware and use to figure +// out an intersection with the sideband data-range +// +// Defines a data structure containing the KSDATAFORMAT_WAVEFORMATEXTENSIBLE +// structure for Audio Driver to build data range intersection +// +// NOTE: This is defined here because of the dependencies on the ks headers +//---------------------------------------------------------------------------- + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE UsbHsSpeakerSupportedDeviceFormats[] = +{ + { // 0 + { + 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) + } + }, + { // 1 + { + 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) + } + }, + { // 2 + { + 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) + } + }, + { // 3 + { + 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) + } + }, + { // 4 + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 288000, + 6, + 24, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE UsbHsMicSupportedDeviceFormats[] = +{ + { // 0 + { + 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) + } + }, + { // 1 + { + 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) + } + }, + { // 2 + { + 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) + } + }, + { // 3 + { + 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) + } + }, + { // 4 + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 288000, + 6, + 24, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + } +}; diff --git a/audio/sysvad/EndpointsCommon/mintopo.cpp b/audio/sysvad/EndpointsCommon/mintopo.cpp index d0ecd848..128fa15c 100644 --- a/audio/sysvad/EndpointsCommon/mintopo.cpp +++ b/audio/sysvad/EndpointsCommon/mintopo.cpp @@ -110,13 +110,13 @@ Return Value: DPF_ENTER(("[CMiniportTopology::~CMiniportTopology]")); -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (IsSidebandDevice()) { ASSERT(m_pSidebandDevice != NULL); // - // Register with BthHfpDevice to get notification events. + // Register with BthHfpDevice or UsbHsDevice to get notification events. // if(IsSidebandDevice()) { @@ -127,7 +127,7 @@ Return Value: SAFE_RELEASE(m_pSidebandDevice); // ISidebandDeviceCommon } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) } // ~CMiniportTopology @@ -281,7 +281,7 @@ Return Value: DPF(D_ERROR, ("Init: CMiniportTopologySYSVAD::Init failed, 0x%x", ntStatus)), Done); -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (IsSidebandDevice()) { PSIDEBANDDEVICECOMMON sidebandDevice = NULL; @@ -292,7 +292,7 @@ Return Value: // // Register with BthHfpDevice to get notification events. // - if (m_DeviceType == eBthHfpMicDevice) + if (m_DeviceType == eBthHfpMicDevice || m_DeviceType == eUsbHsMicDevice) { sidebandDevice->SetVolumeHandler( m_DeviceType, @@ -306,7 +306,7 @@ Return Value: } else { - ASSERT(m_DeviceType == eBthHfpSpeakerDevice); + ASSERT(m_DeviceType == eBthHfpSpeakerDevice || m_DeviceType == eUsbHsSpeakerDevice); sidebandDevice->SetVolumeHandler( m_DeviceType, @@ -319,7 +319,7 @@ Return Value: PCMiniportTopology(this)); // context. } } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) Done: return ntStatus; @@ -581,7 +581,7 @@ Return Value: return ntStatus; } -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) //============================================================================= #pragma code_seg() VOID @@ -685,7 +685,7 @@ CMiniportTopology::EvtMicConnectionStatusHandler FALSE, // do not use node ID. ULONG(-1)); // node ID, not used. } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) //============================================================================= #pragma code_seg("PAGE") diff --git a/audio/sysvad/EndpointsCommon/mintopo.h b/audio/sysvad/EndpointsCommon/mintopo.h index f25d0991..7f573237 100644 --- a/audio/sysvad/EndpointsCommon/mintopo.h +++ b/audio/sysvad/EndpointsCommon/mintopo.h @@ -35,9 +35,9 @@ class CMiniportTopology : eDeviceType m_DeviceType; union { PVOID m_DeviceContext; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) PSIDEBANDDEVICECOMMON m_pSidebandDevice; -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) }; public: @@ -55,7 +55,7 @@ public: m_DeviceType(DeviceType), m_DeviceContext(DeviceContext) { -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (IsSidebandDevice()) { if (m_pSidebandDevice != NULL) @@ -64,7 +64,7 @@ public: m_pSidebandDevice->AddRef(); // strong ref. } } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) } ~CMiniportTopology(); @@ -86,11 +86,13 @@ public: _In_ DWORD JackCapabilities ); -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) BOOL IsSidebandDevice() { return (m_DeviceType == eBthHfpMicDevice || - m_DeviceType == eBthHfpSpeakerDevice) ? TRUE : FALSE; + m_DeviceType == eBthHfpSpeakerDevice || + m_DeviceType == eUsbHsMicDevice || + m_DeviceType == eUsbHsSpeakerDevice ) ? TRUE : FALSE; } // Returns a weak ref to the Bluetooth HFP device. @@ -136,7 +138,7 @@ public: ( _In_opt_ PVOID Context ); -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) defined(SYSVAD_USB_SIDEBAND) PVOID GetDeviceContext() { return m_DeviceContext; } @@ -150,6 +152,18 @@ public: _In_ PPCPROPERTY_REQUEST PropertyRequest); friend NTSTATUS PropertyHandler_BthHfpSpeakerVolumeLevel( _In_ PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_UsbHsJackContainerId( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions); + friend NTSTATUS PropertyHandler_UsbHsVolumeLevel_BasicSupport( + _In_ PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_UsbHsMicVolumeLevel( + _In_ PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_UsbHsMute_BasicSupport( + _In_ PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_UsbHsMicMute( + _In_ PPCPROPERTY_REQUEST PropertyRequest); }; typedef CMiniportTopology *PCMiniportTopology; diff --git a/audio/sysvad/EndpointsCommon/minwavert.cpp b/audio/sysvad/EndpointsCommon/minwavert.cpp index d56462a6..f4a0599c 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.cpp +++ b/audio/sysvad/EndpointsCommon/minwavert.cpp @@ -196,13 +196,13 @@ Return Value: m_pAudioModules = NULL; } -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (IsSidebandDevice()) { m_pSidebandDevice->SetFormatChangeHandler(m_DeviceType, NULL, NULL); SAFE_RELEASE(m_pSidebandDevice); } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) } // ~CMiniportWaveRT @@ -1438,11 +1438,13 @@ CMiniportWaveRT::PropertyHandlerProposedFormat if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { ntStatus = STATUS_INVALID_DEVICE_REQUEST; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (IsSidebandDevice()) { if (m_DeviceType == eBthHfpMicDevice || - m_DeviceType == eBthHfpSpeakerDevice) + m_DeviceType == eBthHfpSpeakerDevice || + m_DeviceType == eUsbHsSpeakerDevice || + m_DeviceType == eUsbHsMicDevice) { KSDATAFORMAT_WAVEFORMATEXTENSIBLE *propFormat = (KSDATAFORMAT_WAVEFORMATEXTENSIBLE *)PropertyRequest->Value; ULONG numModes = 0; @@ -1500,7 +1502,7 @@ CMiniportWaveRT::PropertyHandlerProposedFormat ntStatus = STATUS_SUCCESS; } } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { diff --git a/audio/sysvad/EndpointsCommon/minwavert.h b/audio/sysvad/EndpointsCommon/minwavert.h index 848e4c9a..2472a872 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.h +++ b/audio/sysvad/EndpointsCommon/minwavert.h @@ -18,6 +18,9 @@ Abstract: #ifdef SYSVAD_BTH_BYPASS #include "bthhfpmicwavtable.h" #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND +#include "usbhsmicwavtable.h" +#endif // SYSVAD_USB_SIDEBAND //============================================================================= // Referenced Forward @@ -156,9 +159,9 @@ private: union { PVOID m_DeviceContext; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) PSIDEBANDDEVICECOMMON m_pSidebandDevice; -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) }; AUDIOMODULE * m_pAudioModules; @@ -330,7 +333,7 @@ public: } } -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (IsSidebandDevice()) { if (m_pSidebandDevice != NULL) @@ -417,6 +420,12 @@ public: _In_ PPCPROPERTY_REQUEST PropertyRequest ); #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + NTSTATUS PropertyHandler_UsbHsAudioEffectsDiscoveryEffectsList + ( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); +#endif // SYSVAD_USB_SIDEBAND //--------------------------------------------------------------------------------------------------------- // volume @@ -664,6 +673,7 @@ protected: m_DeviceType == eHdmiRenderDevice || m_DeviceType == eSpdifRenderDevice || m_DeviceType == eBthHfpSpeakerDevice || + m_DeviceType == eUsbHsSpeakerDevice || m_DeviceType == eHandsetSpeakerDevice) ? TRUE : FALSE; } @@ -844,13 +854,15 @@ protected: _In_ ULONG AudioModuleCount ); -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) public: #pragma code_seg() BOOL IsSidebandDevice() { return (m_DeviceType == eBthHfpMicDevice || - m_DeviceType == eBthHfpSpeakerDevice ) ? TRUE : FALSE; + m_DeviceType == eBthHfpSpeakerDevice || + m_DeviceType == eUsbHsMicDevice || + m_DeviceType == eUsbHsSpeakerDevice ) ? TRUE : FALSE; } // Returns a weak ref to the Bluetooth HFP device. @@ -870,7 +882,7 @@ public: return sidebandDevice; } #pragma code_seg() -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) #ifdef SYSVAD_BTH_BYPASS #pragma code_seg() diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.cpp b/audio/sysvad/EndpointsCommon/minwavertstream.cpp index e5dad74f..9ea47c56 100644 --- a/audio/sysvad/EndpointsCommon/minwavertstream.cpp +++ b/audio/sysvad/EndpointsCommon/minwavertstream.cpp @@ -252,10 +252,10 @@ Return Value: m_dwLoopbackCaptureToneInitialPhase = 0; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) m_SidebandOpen = FALSE; m_SidebandStarted = FALSE; -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) m_pPortStream = PortStream_; InitializeListHead(&m_NotificationList); @@ -843,13 +843,13 @@ NTSTATUS CMiniportWaveRTStream::GetPosition { NTSTATUS ntStatus; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (m_SidebandStarted) { ntStatus = GetSidebandStreamNtStatus(); IF_FAILED_JUMP(ntStatus, Done); } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) // Return failure if this is the keyword detector pin if (m_pMiniport->IsKeywordDetectorPin(m_ulPin)) @@ -876,9 +876,9 @@ NTSTATUS CMiniportWaveRTStream::GetPosition ntStatus = STATUS_SUCCESS; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) Done: -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) return ntStatus; } @@ -1178,7 +1178,7 @@ NTSTATUS CMiniportWaveRTStream::SetState if (m_KsState == KSSTATE_ACQUIRE) { // Acquire stream resources -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (m_SidebandOpen) { PSIDEBANDDEVICECOMMON sidebandDevice; @@ -1198,7 +1198,7 @@ NTSTATUS CMiniportWaveRTStream::SetState m_SidebandOpen = FALSE; } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) } KeAcquireSpinLock(&m_PositionSpinLock, &oldIrql); // Reset DMA @@ -1228,7 +1228,7 @@ NTSTATUS CMiniportWaveRTStream::SetState if (m_KsState == KSSTATE_STOP) { // Acquire stream resources -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (m_pMiniport->IsSidebandDevice()) { if (m_SidebandOpen == FALSE) @@ -1250,7 +1250,7 @@ NTSTATUS CMiniportWaveRTStream::SetState m_SidebandOpen = TRUE; } } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) } break; @@ -1288,7 +1288,7 @@ NTSTATUS CMiniportWaveRTStream::SetState } } -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (m_SidebandStarted) { PSIDEBANDDEVICECOMMON sidebandDevice; @@ -1308,7 +1308,7 @@ NTSTATUS CMiniportWaveRTStream::SetState m_SidebandStarted = FALSE; } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) } // This call updates the linear buffer and presentation positions. @@ -1317,7 +1317,7 @@ NTSTATUS CMiniportWaveRTStream::SetState case KSSTATE_RUN: -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (m_pMiniport->IsSidebandDevice()) { if (m_SidebandStarted == FALSE) @@ -1339,7 +1339,7 @@ NTSTATUS CMiniportWaveRTStream::SetState m_SidebandStarted = TRUE; } } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) // Start DMA LARGE_INTEGER ullPerfCounterTemp; @@ -1371,9 +1371,9 @@ NTSTATUS CMiniportWaveRTStream::SetState m_KsState = State_; -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) Done: -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) return ntStatus; } @@ -1649,7 +1649,7 @@ Return Value: return ntStatus; } // SetContentId -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) //============================================================================= #pragma code_seg() @@ -1687,7 +1687,7 @@ Return Value: return ntStatus; } -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) //============================================================================= #pragma code_seg("PAGE") @@ -1788,7 +1788,7 @@ TimerNotifyRT _this->m_llPacketCounter++; } -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) if (_this->m_SidebandStarted) { if (!NT_SUCCESS(_this->GetSidebandStreamNtStatus())) @@ -1796,7 +1796,7 @@ TimerNotifyRT goto End; } } -#endif //defined(SYSVAD_BTH_BYPASS) +#endif //defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) _this->m_pMiniport->DpcRoutine(qpc.QuadPart, qpcFrequency.QuadPart); diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.h b/audio/sysvad/EndpointsCommon/minwavertstream.h index b1fc4628..4e9e882c 100644 --- a/audio/sysvad/EndpointsCommon/minwavertstream.h +++ b/audio/sysvad/EndpointsCommon/minwavertstream.h @@ -140,10 +140,10 @@ protected: DWORD m_dwLoopbackCaptureToneInitialPhase; // must be between -31416 to 31416 // Member variable as config params for tone generator -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) BOOL m_SidebandOpen; BOOL m_SidebandStarted; -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) public: @@ -309,9 +309,9 @@ private: ); NTSTATUS ReadRegistrySettings(); -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) NTSTATUS GetSidebandStreamNtStatus(); -#endif // defined(SYSVAD_BTH_BYPASS) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) }; typedef CMiniportWaveRTStream *PCMiniportWaveRTStream; diff --git a/audio/sysvad/EndpointsCommon/sources b/audio/sysvad/EndpointsCommon/sources index 18b2ddc4..4ac1b852 100644 --- a/audio/sysvad/EndpointsCommon/sources +++ b/audio/sysvad/EndpointsCommon/sources @@ -11,7 +11,7 @@ INCLUDES= \ .. -C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS +C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS -DSYSVAD_USB_SIDEBAND #C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ DDK_TARGET_PLATFORM=Universal @@ -41,4 +41,8 @@ SOURCES=$(SOURCES) \ minwavertstream.cpp \ speakertopo.cpp \ speakerhptopo.cpp \ + usbhstopo.cpp \ + usbhsmictopo.cpp \ + usbhsspeakertopo.cpp \ + usbhsminwavert.cpp \ diff --git a/audio/sysvad/EndpointsCommon/usbhsmictopo.cpp b/audio/sysvad/EndpointsCommon/usbhsmictopo.cpp new file mode 100644 index 00000000..6814b5ce --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsmictopo.cpp @@ -0,0 +1,349 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsmictopo.cpp + +Abstract: + + Implementation of topology miniport for the mic (external: headphone). + +--*/ +#ifdef SYSVAD_USB_SIDEBAND + +#pragma warning (disable : 4127) + +#include +#include "simple.h" +#include "mintopo.h" +#include "usbhstopo.h" +#include "usbhsmictopo.h" +#include "usbhsmictoptable.h" + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsMicTopoFilter +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Redirects property request to miniport object + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[PropertyHandler_UsbHsMicTopoFilter]")); + + // PropertryRequest structure is filled by portcls. + // MajorTarget is a pointer to miniport object for miniports. + // + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + // + // This line shows how to get a pointer to the miniport topology object. + // + PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + UNREFERENCED_VAR(pMiniport); + + if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack)) + { + switch(PropertyRequest->PropertyItem->Id) + { + case KSPROPERTY_JACK_DESCRIPTION: + ntStatus = PropertyHandler_UsbHsJackDescription( + PropertyRequest, + ARRAYSIZE(UsbHsMicJackDescriptions), + UsbHsMicJackDescriptions); + break; + + case KSPROPERTY_JACK_DESCRIPTION2: + ntStatus = PropertyHandler_UsbHsJackDescription2( + PropertyRequest, + ARRAYSIZE(UsbHsMicJackDescriptions), + UsbHsMicJackDescriptions); + break; + + case KSPROPERTY_JACK_CONTAINERID: + ntStatus = PropertyHandler_UsbHsJackContainerId( + PropertyRequest, + ARRAYSIZE(UsbHsMicJackDescriptions), + UsbHsMicJackDescriptions); + break; + } + } + + return ntStatus; +} // PropertyHandler_UsbHsMicTopoFilter + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsMicVolumeLevel +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_VOLUMELEVEL ) + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[PropertyHandler_UsbHsMicVolumeLevel]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + PSIDEBANDDEVICECOMMON usbHsDevice = NULL; + ULONG channel = (ULONG)-1; + + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + if (usbHsDevice->IsVolumeSupported(miniport->m_DeviceType) == FALSE) + { + ntStatus = miniport->PropertyHandlerGeneric(PropertyRequest); + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ntStatus = PropertyHandler_UsbHsVolumeLevel_BasicSupport(PropertyRequest); + } + else if (PropertyRequest->InstanceSize >= sizeof(ULONG)) + { + // Instance is the channel #. + channel = *(PULONG(PropertyRequest->Instance)); + + ULONG cbNeeded = sizeof(LONG); + + if (PropertyRequest->ValueSize == 0) + { + PropertyRequest->ValueSize = cbNeeded; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (PropertyRequest->ValueSize < cbNeeded) + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + else + { + LONG* volume = (LONG*)PropertyRequest->Value; + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + ntStatus = usbHsDevice->GetVolume(eUsbHsMicDevice, channel, volume); + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) + { + ntStatus = usbHsDevice->SetVolume(eUsbHsMicDevice, channel, *volume); + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsMicMute +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MUTE ) + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[PropertyHandler_UsbHsMicMute]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + PSIDEBANDDEVICECOMMON usbHsDevice = NULL; + ULONG channel = (ULONG)-1; + + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + if (usbHsDevice->IsMuteSupported(miniport->m_DeviceType) == FALSE) + { + ntStatus = miniport->PropertyHandlerGeneric(PropertyRequest); + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ntStatus = PropertyHandler_UsbHsMute_BasicSupport(PropertyRequest); + } + else if (PropertyRequest->InstanceSize >= sizeof(ULONG)) + { + // Instance is the channel #. + channel = *(PULONG(PropertyRequest->Instance)); + + ULONG cbNeeded = sizeof(LONG); + + if (PropertyRequest->ValueSize == 0) + { + PropertyRequest->ValueSize = cbNeeded; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (PropertyRequest->ValueSize < cbNeeded) + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + else + { + LONG* mute = (LONG*)PropertyRequest->Value; + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + *mute = usbHsDevice->GetMute(eUsbHsMicDevice, channel); + + ntStatus = STATUS_SUCCESS; + + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) + { + ntStatus = usbHsDevice->SetMute(eUsbHsMicDevice, channel, *mute); + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsMicTopoNode +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Redirects property request to miniport object + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[PropertyHandler_UsbHsMicTopoNode]")); + + // PropertryRequest structure is filled by portcls. + // MajorTarget is a pointer to miniport object for miniports. + // + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + // + // This line shows how to get a pointer to the miniport topology object. + // + PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + UNREFERENCED_VAR(pMiniport); + + if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Audio)) + { + if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_VOLUMELEVEL) + { + ntStatus = PropertyHandler_UsbHsMicVolumeLevel(PropertyRequest); + } + else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MUTE) + { + ntStatus = PropertyHandler_UsbHsMicMute(PropertyRequest); + } + } + + return ntStatus; +} // PropertyHandler_UsbHsMicTopoFilter + +//============================================================================= +#pragma code_seg() +NTSTATUS +PropertyHandler_UsbHsMicTopoNodeEvent +( + _In_ PPCEVENT_REQUEST EventRequest +) +{ + ASSERT(EventRequest); + + DPF_ENTER(("[PropertyHandler_UsbHsMicTopoNodeEvent]")); + + // Validate the node. + if (EventRequest->Node != KSNODE_TOPO_VOLUME && + EventRequest->Node != KSNODE_TOPO_MUTE) + return STATUS_INVALID_PARAMETER; + + return PropertyHandler_UsbHsTopoNodeEvent(EventRequest); +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +PropertyHandler_UsbHsMicTopoFilterEvent +( + _In_ PPCEVENT_REQUEST EventRequest +) +{ + ASSERT(EventRequest); + + DPF_ENTER(("[PropertyHandler_UsbHsMicTopoFilterEvent]")); + + return PropertyHandler_UsbHsTopoNodeEvent(EventRequest); +} + +#pragma code_seg() +#endif // SYSVAD_USB_SIDEBAND + + diff --git a/audio/sysvad/EndpointsCommon/usbhsmictopo.h b/audio/sysvad/EndpointsCommon/usbhsmictopo.h new file mode 100644 index 00000000..e2a872c5 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsmictopo.h @@ -0,0 +1,40 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsmictopo.h + +Abstract: + + Declaration of topology miniport for the mic (external: headphone). + +--*/ + +#ifndef _SYSVAD_USBHSMICTOPO_H_ +#define _SYSVAD_USBHSMICTOPO_H_ + +// Function declarations. +NTSTATUS +PropertyHandler_UsbHsMicTopoFilter( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + +NTSTATUS +PropertyHandler_UsbHsMicTopoNode( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + +NTSTATUS +PropertyHandler_UsbHsMicTopoNodeEvent( + _In_ PPCEVENT_REQUEST EventRequest + ); + +NTSTATUS +PropertyHandler_UsbHsMicTopoFilterEvent( + _In_ PPCEVENT_REQUEST EventRequest + ); + +#endif // _SYSVAD_USBHSMICTOPO_H_ + diff --git a/audio/sysvad/EndpointsCommon/usbhsmictoptable.h b/audio/sysvad/EndpointsCommon/usbhsmictoptable.h new file mode 100644 index 00000000..ac3c89d0 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsmictoptable.h @@ -0,0 +1,297 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsmictopotable.h + +Abstract: + + Declaration of topology table for the USB Headset mic (external) + +--*/ + +#ifndef _SYSVAD_USBHSMICTOPTABLE_H_ +#define _SYSVAD_USBHSMICTOPTABLE_H_ + +#include "usbhsmictopo.h" + +// Function declarations. +NTSTATUS +PropertyHandler_UsbHsMicTopoFilter( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + +//============================================================================= +static +KSDATARANGE UsbHsMicTopoPinDataRangesBridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +//============================================================================= +static +PKSDATARANGE UsbHsMicTopoPinDataRangePointersBridge[] = +{ + &UsbHsMicTopoPinDataRangesBridge[0] +}; + +//============================================================================= +static +PCPIN_DESCRIPTOR UsbHsMicTopoMiniportPins[] = +{ + // KSPIN_TOPO_MIC_ELEMENTS + { + 0, + 0, + 0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(UsbHsMicTopoPinDataRangePointersBridge),// DataRangesCount + UsbHsMicTopoPinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_HEADSET_MICROPHONE, // Category + NULL, // Name + 0 // Reserved + } + }, + + // KSPIN_TOPO_BRIDGE + { + 0, + 0, + 0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(UsbHsMicTopoPinDataRangePointersBridge),// DataRangesCount + UsbHsMicTopoPinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_OUT, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSCATEGORY_AUDIO, // Category + NULL, // Name + 0 // Reserved + } + } +}; + +//============================================================================= +static +KSJACK_DESCRIPTION UsbHsMicJackDesc = +{ + KSAUDIO_SPEAKER_MONO, + JACKDESC_RGB(0, 0, 0), + eConnTypeOtherDigital, + eGeoLocBottom, + eGenLocPrimaryBox, + ePortConnJack, + FALSE // NOTE: For convenience, wired headset jacks will be "unplugged" at boot. +}; + +//============================================================================= +// Only return a KSJACK_DESCRIPTION for the physical bridge pin. +static +PKSJACK_DESCRIPTION UsbHsMicJackDescriptions[] = +{ + &UsbHsMicJackDesc, + NULL +}; + +//============================================================================= +static +PCPROPERTY_ITEM UsbHsMicPropertiesVolume[] = +{ + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_VOLUMELEVEL, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsMicTopoNode + } +}; + +static +PCEVENT_ITEM UsbHsMicPropertiesVolumeEvent[] = +{ + // This is a generic event for nearly every node property. + { + &KSEVENTSETID_AudioControlChange, // Something changed! + KSEVENT_CONTROL_CHANGE, // The only event-property defined. + KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsMicTopoNodeEvent + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationUsbHsMicVolumeWithEvent, + UsbHsMicPropertiesVolume, + UsbHsMicPropertiesVolumeEvent); + + +//============================================================================= +static +PCPROPERTY_ITEM UsbHsMicPropertiesMute[] = +{ + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_MUTE, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsMicTopoNode + } +}; + +static +PCEVENT_ITEM UsbHsMicPropertiesMuteEvent[] = +{ + // This is a generic event for nearly every node property. + { + &KSEVENTSETID_AudioControlChange, // Something changed! + KSEVENT_CONTROL_CHANGE, // The only event-property defined. + KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsMicTopoNodeEvent + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationUsbHsMicMuteWithEvent, + UsbHsMicPropertiesMute, + UsbHsMicPropertiesMuteEvent); + +//============================================================================= +static +PCPROPERTY_ITEM UsbHsMicPropertiesPeakMeter[] = +{ + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_PEAKMETER2, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_Topology + }, + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_CPU_RESOURCES, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_Topology + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationUsbHsMicPeakMeter, UsbHsMicPropertiesPeakMeter); + +//============================================================================= +static +PCNODE_DESCRIPTOR UsbHsMicTopologyNodes[] = +{ + // KSNODE_TOPO_VOLUME + { + 0, // Flags + &AutomationUsbHsMicVolumeWithEvent, // AutomationTable + &KSNODETYPE_VOLUME, // Type + &KSAUDFNAME_MIC_VOLUME // Name + }, + // KSNODE_TOPO_MUTE + { + 0, // Flags + &AutomationUsbHsMicMuteWithEvent, // AutomationTable + &KSNODETYPE_MUTE, // Type + &KSAUDFNAME_MIC_MUTE // Name + }, + // KSNODE_TOPO_PEAKMETER + { + 0, // Flags + &AutomationUsbHsMicPeakMeter, // AutomationTable + &KSNODETYPE_PEAKMETER, // Type + &KSAUDFNAME_PEAKMETER // Name + } +}; + +C_ASSERT( KSNODE_TOPO_VOLUME == 0 ); +C_ASSERT( KSNODE_TOPO_MUTE == 1 ); +C_ASSERT( KSNODE_TOPO_PEAKMETER == 2 ); + +//============================================================================= +static +PCCONNECTION_DESCRIPTOR UsbHsMicMiniportConnections[] = +{ + // FromNode, FromPin, ToNode, ToPin + { PCFILTER_NODE, KSPIN_TOPO_MIC_ELEMENTS, KSNODE_TOPO_VOLUME, 1 }, + { KSNODE_TOPO_VOLUME, 0, KSNODE_TOPO_MUTE, 1 }, + { KSNODE_TOPO_MUTE, 0, KSNODE_TOPO_PEAKMETER, 1 }, + { KSNODE_TOPO_PEAKMETER, 0, PCFILTER_NODE, KSPIN_TOPO_BRIDGE } +}; + + +//============================================================================= +static +PCPROPERTY_ITEM UsbHsMicPropertiesTopoFilter[] = +{ + { + &KSPROPSETID_Jack, + KSPROPERTY_JACK_DESCRIPTION, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsMicTopoFilter + }, + { + &KSPROPSETID_Jack, + KSPROPERTY_JACK_DESCRIPTION2, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsMicTopoFilter + }, + { + &KSPROPSETID_Jack, + KSPROPERTY_JACK_CONTAINERID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsMicTopoFilter + } + +}; + +static +PCEVENT_ITEM UsbHsMicTopoPropertiesFilterEvent[] = +{ + { + &KSEVENTSETID_PinCapsChange, // Something changed! + KSEVENT_PINCAPS_JACKINFOCHANGE, // The only event-property defined. + KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsMicTopoFilterEvent + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationUsbHsMicTopoFilterWithEvent, + UsbHsMicPropertiesTopoFilter, + UsbHsMicTopoPropertiesFilterEvent); + + +//============================================================================= +static +PCFILTER_DESCRIPTOR UsbHsMicTopoMiniportFilterDescriptor = +{ + 0, // Version + &AutomationUsbHsMicTopoFilterWithEvent, // AutomationTable + sizeof(PCPIN_DESCRIPTOR), // PinSize + SIZEOF_ARRAY(UsbHsMicTopoMiniportPins), // PinCount + UsbHsMicTopoMiniportPins, // Pins + sizeof(PCNODE_DESCRIPTOR), // NodeSize + SIZEOF_ARRAY(UsbHsMicTopologyNodes), // NodeCount + UsbHsMicTopologyNodes, // Nodes + SIZEOF_ARRAY(UsbHsMicMiniportConnections),// ConnectionCount + UsbHsMicMiniportConnections, // Connections + 0, // CategoryCount + NULL // Categories +}; + +#endif // _SYSVAD_USBHSMICTOPTABLE_H_ + diff --git a/audio/sysvad/EndpointsCommon/usbhsmicwavtable.h b/audio/sysvad/EndpointsCommon/usbhsmicwavtable.h new file mode 100644 index 00000000..2b456747 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsmicwavtable.h @@ -0,0 +1,483 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsmicwavtable.h + +Abstract: + + Declaration of wave miniport tables for the USB Headset Mic (external). + +--*/ + +#ifndef _SYSVAD_USBHSMICWAVTABLE_H_ +#define _SYSVAD_USBHSMICWAVTABLE_H_ + +// +// Function prototypes. +// +NTSTATUS PropertyHandler_UsbHsWaveFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest); + +// +// USB Headset Mic (external) range. +// +#define USBHSMIC_DEVICE_MAX_CHANNELS 1 // Max Channels. +#define USBHSMIC_MIN_BITS_PER_SAMPLE_PCM 16 // Min Bits Per Sample +#define USBHSMIC_MAX_BITS_PER_SAMPLE_PCM 24 // Max Bits Per Sample +#define USBHSMIC_MIN_SAMPLE_RATE 8000 // Min Sample Rate +#define USBHSMIC_MAX_SAMPLE_RATE 48000 // Max Sample Rate + +// +// Max # of pin instances. +// +#define USBHSMIC_MAX_INPUT_STREAMS 4 + +//============================================================================= +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE UsbHsMicPinSupportedDeviceFormats[] = +{ + { // 0 + { + 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) + } + }, + { // 1 + { + 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) + } + }, + { // 2 + { + 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) + } + }, + { // 3 + { + 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) + } + }, + { // 4 + { + 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) + } + }, + { // 5 + { + 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) + } + }, + { // 6 + { + 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) + } + }, + { // 7 + { + 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) + } + }, + { // 8 + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 48000, + 144000, + 3, + 24, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + } +}; + +// +// Supported modes (only on streaming pins). +// +static +MODE_AND_DEFAULT_FORMAT UsbHsMicPinSupportedDeviceModes[] = +{ + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW, + &UsbHsMicPinSupportedDeviceFormats[SIZEOF_ARRAY(UsbHsMicPinSupportedDeviceFormats) - 1].DataFormat, // 48KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + &UsbHsMicPinSupportedDeviceFormats[SIZEOF_ARRAY(UsbHsMicPinSupportedDeviceFormats) - 1].DataFormat, // 48KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_SPEECH, + &UsbHsMicPinSupportedDeviceFormats[2].DataFormat, // 16KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, + &UsbHsMicPinSupportedDeviceFormats[4].DataFormat, // 24KHz + } +}; + +// +// The entries here must follow the same order as the filter's pin +// descriptor array. +// +static +PIN_DEVICE_FORMATS_AND_MODES UsbHsMicPinDeviceFormatsAndModes[] = +{ + { + BridgePin, + NULL, + 0, + NULL, + 0 + }, + { + SystemCapturePin, + UsbHsMicPinSupportedDeviceFormats, + SIZEOF_ARRAY(UsbHsMicPinSupportedDeviceFormats), + UsbHsMicPinSupportedDeviceModes, + SIZEOF_ARRAY(UsbHsMicPinSupportedDeviceModes) + } +}; + +//============================================================================= +static +KSDATARANGE_AUDIO UsbHsMicPinDataRangesStream[] = +{ + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + USBHSMIC_DEVICE_MAX_CHANNELS, + USBHSMIC_MIN_BITS_PER_SAMPLE_PCM, + USBHSMIC_MAX_BITS_PER_SAMPLE_PCM, + USBHSMIC_MIN_SAMPLE_RATE, + USBHSMIC_MAX_SAMPLE_RATE + }, +}; + +static +PKSDATARANGE UsbHsMicPinDataRangePointersStream[] = +{ + PKSDATARANGE(&UsbHsMicPinDataRangesStream[0]), + PKSDATARANGE(&PinDataRangeAttributeList) +}; + +//============================================================================= +static +KSDATARANGE UsbHsMicPinDataRangesBridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +static +PKSDATARANGE UsbHsMicPinDataRangePointersBridge[] = +{ + &UsbHsMicPinDataRangesBridge[0] +}; + +//============================================================================= +static +PCPIN_DESCRIPTOR UsbHsMicWaveMiniportPins[] = +{ + // Wave In Bridge Pin (Capture - From Topology) KSPIN_WAVE_BRIDGE + { + 0, + 0, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(UsbHsMicPinDataRangePointersBridge), + UsbHsMicPinDataRangePointersBridge, + KSPIN_DATAFLOW_IN, + KSPIN_COMMUNICATION_NONE, + &KSCATEGORY_AUDIO, + NULL, + 0 + } + }, + + // Wave In Streaming Pin (Capture) KSPIN_WAVEIN_HOST + { + USBHSMIC_MAX_INPUT_STREAMS, + USBHSMIC_MAX_INPUT_STREAMS, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(UsbHsMicPinDataRangePointersStream), + UsbHsMicPinDataRangePointersStream, + KSPIN_DATAFLOW_OUT, + KSPIN_COMMUNICATION_SINK, + &KSCATEGORY_AUDIO, + &KSAUDFNAME_RECORDING_CONTROL, + 0 + } + } +}; + +//============================================================================= +static +PCNODE_DESCRIPTOR UsbHsMicWaveMiniportNodes[] = +{ + // KSNODE_WAVE_ADC + { + 0, // Flags + NULL, // AutomationTable + &KSNODETYPE_ADC, // Type + NULL // Name + } +}; + +//============================================================================= +static +PCCONNECTION_DESCRIPTOR UsbHsMicWaveMiniportConnections[] = +{ + { PCFILTER_NODE, KSPIN_WAVE_BRIDGE, KSNODE_WAVE_ADC, 1 }, + { KSNODE_WAVE_ADC, 0, PCFILTER_NODE, KSPIN_WAVEIN_HOST } +}; + +//============================================================================= +static +PCPROPERTY_ITEM PropertiesUsbHsMicWaveFilter[] = +{ + { + &KSPROPSETID_General, + KSPROPERTY_GENERAL_COMPONENTID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter + }, + { + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PROPOSEDATAFORMAT, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsWaveFilter + }, + { + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PROPOSEDATAFORMAT2, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsWaveFilter + }, + { + &KSPROPSETID_AudioEffectsDiscovery, + KSPROPERTY_AUDIOEFFECTSDISCOVERY_EFFECTSLIST, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsWaveFilter + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationUsbHsMicWaveFilter, PropertiesUsbHsMicWaveFilter); + +//============================================================================= +static +PCFILTER_DESCRIPTOR UsbHsMicWaveMiniportFilterDescriptor = +{ + 0, // Version + &AutomationUsbHsMicWaveFilter, // AutomationTable + sizeof(PCPIN_DESCRIPTOR), // PinSize + SIZEOF_ARRAY(UsbHsMicWaveMiniportPins), // PinCount + UsbHsMicWaveMiniportPins, // Pins + sizeof(PCNODE_DESCRIPTOR), // NodeSize + SIZEOF_ARRAY(UsbHsMicWaveMiniportNodes), // NodeCount + UsbHsMicWaveMiniportNodes, // Nodes + SIZEOF_ARRAY(UsbHsMicWaveMiniportConnections), // ConnectionCount + UsbHsMicWaveMiniportConnections, // Connections + 0, // CategoryCount + NULL // Categories - use defaults (audio, render, capture) +}; + +#endif // _SYSVAD_USBHSMICWAVTABLE_H_ diff --git a/audio/sysvad/EndpointsCommon/usbhsminipairs.h b/audio/sysvad/EndpointsCommon/usbhsminipairs.h new file mode 100644 index 00000000..0b71bce9 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsminipairs.h @@ -0,0 +1,204 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsminipairs.h + +Abstract: + + USB Sideband Audio endpoint filter definitions. + +--*/ + +#ifndef _SYSVAD_USBHSMINIPAIRS_H_ +#define _SYSVAD_USBHSMINIPAIRS_H_ + +#include "usbhsspeakertopo.h" +#include "usbhsspeakertoptable.h" +#include "usbhsspeakerwavtable.h" + +#include "usbhsmictopo.h" +#include "usbhsmictoptable.h" +#include "usbhsmicwavtable.h" + +NTSTATUS +CreateMiniportWaveRTSYSVAD +( + _Out_ PUNKNOWN *, + _In_ REFCLSID, + _In_opt_ PUNKNOWN, + _In_ POOL_TYPE, + _In_ PUNKNOWN, + _In_opt_ PVOID, + _In_ PENDPOINT_MINIPAIR +); + +NTSTATUS +CreateMiniportTopologySYSVAD +( + _Out_ PUNKNOWN *, + _In_ REFCLSID, + _In_opt_ PUNKNOWN, + _In_ POOL_TYPE, + _In_ PUNKNOWN, + _In_opt_ PVOID, + _In_ PENDPOINT_MINIPAIR +); + +/* +* USB Headset speaker miniports. +* +********************************************************************************************** +* Topology/Wave bridge connection for USB Headset Speaker * +* * +* +---------------------------------+ +-------+ * +* | Wave | | Topo | * +* | | | | * +* | +---------------------+ | | | * +* | | | | | | * +* System --->|0-----|1 HW Audio Engine 3|---2|---> Loopback | | * +* | | Node | | | | * +* Offload --->|1-----|2 0|---3|===============>|0---->1|---> Line Out * +* | +---------------------+ | | | * +* | | | | * +* +---------------------------------+ +-------+ * +* * +**********************************************************************************************/ + +static +PHYSICALCONNECTIONTABLE UsbHsSpeakerTopologyPhysicalConnections[] = +{ + { + KSPIN_TOPO_WAVEOUT_SOURCE, // TopologyIn + KSPIN_WAVE_RENDER_SOURCE, // WaveOut + CONNECTIONTYPE_WAVE_OUTPUT + } +}; + +// A subdevice is created for each HFP device using the reference string in the form of: +// - +// where Base_Reference_String is one of the following template names +#define USBHS_SPEAKER_TOPO_NAME L"TopologyUsbHsSpeaker" +#define USBHS_SPEAKER_WAVE_NAME L"WaveUsbHsSpeaker" +#define USBHS_MIC_TOPO_NAME L"TopologyUsbHsMic" +#define USBHS_MIC_WAVE_NAME L"WaveUsbHsMic" +// And Hashcode is 8-character long hexadecimal value + +// A reference string max length is being set to a value to accommodate them both +#define USBHS_INTERFACE_REFSTRING_MAX_LENGTH 100 + +static +ENDPOINT_MINIPAIR UsbHsSpeakerMiniports = +{ + eUsbHsSpeakerDevice, + NULL, // Will be generated based on BTHHFP_SPEAKER_TOPO_NAME and made unique for each side band interface + USBHS_SPEAKER_TOPO_NAME, // template name matches with KSNAME_TopologyBthHfpSpeaker in the inf's [Strings] section + CreateMiniportTopologySYSVAD, + &UsbHsSpeakerTopoMiniportFilterDescriptor, + 0, NULL, // Interface properties + NULL, // Will be generated based on BTHHFP_SPEAKER_WAVE_NAME and made unique for each side band interface + USBHS_SPEAKER_WAVE_NAME, // template name matches with KSNAME_WaveBthHfpSpeaker in the inf's [Strings] section + CreateMiniportWaveRTSYSVAD, + &UsbHsSpeakerWaveMiniportFilterDescriptor, + 0, NULL, // Interface properties + 1, + UsbHsSpeakerPinDeviceFormatsAndModes, + SIZEOF_ARRAY(UsbHsSpeakerPinDeviceFormatsAndModes), + UsbHsSpeakerTopologyPhysicalConnections, + SIZEOF_ARRAY(UsbHsSpeakerTopologyPhysicalConnections), + ENDPOINT_OFFLOAD_SUPPORTED +}; + + +/* +* Headset Microphone miniports. +* +* +************************************************************************************************************************************************ +* Topology/Wave bridge connection for USB Headset Microphone * +* +---------------------------------+ +---------------------------------------------------------+ * +* | +-------------+ | | +-------------+ +-------+ +--------+ | * +* Capture <---|1<-------|0 ADC 1|<-------0|<===============|1<----| peak meter |<----| mute |<----| volume |<---- 0|<---- Mic in * +* | +-------------+ | | +-------------+ +-------+ +--------+ | * +* +---------------------------------+ +---------------------------------------------------------+ * +* * +************************************************************************************************************************************************/ +static +PHYSICALCONNECTIONTABLE UsbHsMicTopologyPhysicalConnections[] = +{ + { + KSPIN_TOPO_BRIDGE, // TopologyOut + KSPIN_WAVE_BRIDGE, // WaveIn + CONNECTIONTYPE_TOPOLOGY_OUTPUT + } +}; + +static +ENDPOINT_MINIPAIR UsbHsMicMiniports = +{ + eUsbHsMicDevice, + NULL, // Will be generated based on BTHHFP_MIC_TOPO_NAME and made unique for each side band interface + USBHS_MIC_TOPO_NAME, // template name matches with KSNAME_TopologyBthHfpMic in the inf's [Strings] section + CreateMiniportTopologySYSVAD, + &UsbHsMicTopoMiniportFilterDescriptor, + 0, NULL, // Interface properties + NULL, // Will be generated based on BTHHFP_SPEAKER_WAVE_NAME and made unique for each side band interface + USBHS_MIC_WAVE_NAME, // template name matches with KSNAME_WaveBthHfpMic in the inf's [Strings] section + CreateMiniportWaveRTSYSVAD, + &UsbHsMicWaveMiniportFilterDescriptor, + 0, NULL, // Interface properties + 1, + UsbHsMicPinDeviceFormatsAndModes, + SIZEOF_ARRAY(UsbHsMicPinDeviceFormatsAndModes), + UsbHsMicTopologyPhysicalConnections, + SIZEOF_ARRAY(UsbHsMicTopologyPhysicalConnections), + ENDPOINT_NO_FLAGS +}; + +//============================================================================= +// +// Render miniport pairs. +// +static +PENDPOINT_MINIPAIR g_UsbHsRenderEndpoints[] = +{ + &UsbHsSpeakerMiniports +}; + +#define g_cUsbHsRenderEndpoints (SIZEOF_ARRAY(g_UsbHsRenderEndpoints)) + +// If the count of Render endpoints changes, update formula below +C_ASSERT(g_cUsbHsRenderEndpoints == 1); + +//============================================================================= +// +// Capture miniport pairs. +// +static +PENDPOINT_MINIPAIR g_UsbHsCaptureEndpoints[] = +{ + &UsbHsMicMiniports +}; + +#define g_cUsbHsCaptureEndpoints (SIZEOF_ARRAY(g_UsbHsCaptureEndpoints)) + +// If the count of Capture endpoints changes, update formula below +C_ASSERT(g_cUsbHsCaptureEndpoints == 1); + +//============================================================================= +// +// Total miniports = # endpoints * 2 (topology + wave) +// +// +// Allow 5 USB Headset Endpoints. +// +#define MAX_USBHS_DEVICES (5) +#define g_MaxUsbHsMiniports ((g_cUsbHsRenderEndpoints + g_cUsbHsCaptureEndpoints) * 2 * MAX_USBHS_DEVICES) + +// g_MaxUsbHsMiniports is used when calculating the MaxObjects inside AddDevice. +C_ASSERT(g_MaxUsbHsMiniports == 20); + +#endif // _SYSVAD_USBHSMINIPAIRS_H_ + diff --git a/audio/sysvad/EndpointsCommon/usbhsminwavert.cpp b/audio/sysvad/EndpointsCommon/usbhsminwavert.cpp new file mode 100644 index 00000000..a1fa3f15 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsminwavert.cpp @@ -0,0 +1,211 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsminwavert.cpp + +Abstract: + + Implementation of wavert miniport. + +--*/ +#ifdef SYSVAD_USB_SIDEBAND + +#pragma warning (disable : 4127) + +#include +#include +#include "simple.h" +#include "minwavert.h" +#include "minwavertstream.h" +#include "IHVPrivatePropertySet.h" + + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportWaveRT::PropertyHandler_UsbHsAudioEffectsDiscoveryEffectsList +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_AudioEffectsDiscovery, KSPROPERTY_AUDIOEFFECTSDISCOVERY_EFFECTSLIST ) + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + DPF_ENTER(("[PropertyHandler_UsbHsAudioEffectsDiscoveryEffectsList]")); + + NTSTATUS ntStatus = STATUS_INVALID_PARAMETER; + ULONG nPinId = (ULONG)-1; + + // + // Validate Pin ID. + // + if (PropertyRequest->InstanceSize >= sizeof(ULONG)) + { + nPinId = *(PULONG(PropertyRequest->Instance)); + + // This prop is valid only on streaming pins. + if (IsSystemRenderPin(nPinId) || IsSystemCapturePin(nPinId)) + { + ntStatus = STATUS_SUCCESS; + } + else if (IsBridgePin(nPinId) || + IsLoopbackPin(nPinId) || + IsOffloadPin(nPinId)) + { + ntStatus = STATUS_NOT_SUPPORTED; + } + } + + IF_FAILED_JUMP(ntStatus, Done); + + // + // Valid actions: get and basicsupport. + // + ntStatus = STATUS_INVALID_PARAMETER; + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ntStatus = + PropertyHandler_BasicSupport + ( + PropertyRequest, + KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET, + VT_ILLEGAL + ); + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + ASSERT(m_pSidebandDevice != NULL); + + + // If it is render pin (data flow in), + // return size 0 effect list + if (IsSystemRenderPin(nPinId)) + { + PropertyRequest->ValueSize = 0; + ntStatus = STATUS_SUCCESS; + } + else + { + // Compute total size, two effects: NS and EC (see below). + ULONG cbMinSize = sizeof(GUID) * 2; + + if (PropertyRequest->ValueSize == 0) + { + PropertyRequest->ValueSize = cbMinSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (PropertyRequest->ValueSize < cbMinSize) + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + else + { + PGUID effectList = PGUID(PropertyRequest->Value); + + *effectList = AUDIO_EFFECT_TYPE_ACOUSTIC_ECHO_CANCELLATION; + *(effectList + 1) = AUDIO_EFFECT_TYPE_NOISE_SUPPRESSION; + + PropertyRequest->ValueSize = cbMinSize; + ntStatus = STATUS_SUCCESS; + } + } + } + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsWaveFilter +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Redirects general property request to miniport object + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + CMiniportWaveRT* waveRt = reinterpret_cast(PropertyRequest->MajorTarget); + + if (waveRt == NULL) + { + return STATUS_INVALID_PARAMETER; + } + + waveRt->AddRef(); + + if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Pin)) + { + switch (PropertyRequest->PropertyItem->Id) + { + case KSPROPERTY_PIN_PROPOSEDATAFORMAT: + ntStatus = waveRt->PropertyHandlerProposedFormat(PropertyRequest); + break; + + case KSPROPERTY_PIN_PROPOSEDATAFORMAT2: + ntStatus = waveRt->PropertyHandlerProposedFormat2(PropertyRequest); + break; + + default: + DPF(D_TERSE, ("[PropertyHandler_UsbHsWaveFilter: Invalid Device Request]")); + } + } + else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioEffectsDiscovery)) + { + switch(PropertyRequest->PropertyItem->Id) + { + case KSPROPERTY_AUDIOEFFECTSDISCOVERY_EFFECTSLIST: + ntStatus = waveRt->PropertyHandler_UsbHsAudioEffectsDiscoveryEffectsList(PropertyRequest); + break; + + default: + DPF(D_TERSE, ("[PropertyHandler_UsbHsWaveFilter: Invalid Device Request]")); + } + } + + waveRt->Release(); + + return ntStatus; +} // PropertyHandler_UsbHsWaveFilter + +#pragma code_seg("PAGE") +#endif // SYSVAD_USB_SIDEBAND + + + + diff --git a/audio/sysvad/EndpointsCommon/usbhsspeakertopo.cpp b/audio/sysvad/EndpointsCommon/usbhsspeakertopo.cpp new file mode 100644 index 00000000..21d5fa8c --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsspeakertopo.cpp @@ -0,0 +1,113 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsspeakertopo.cpp + +Abstract: + + Implementation of topology miniport for the USB Headset speaker (external). + +--*/ +#ifdef SYSVAD_USB_SIDEBAND + +#pragma warning (disable : 4127) + +#include +#include "simple.h" +#include "mintopo.h" +#include "usbhstopo.h" +#include "usbhsspeakertopo.h" +#include "usbhsspeakertoptable.h" + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsSpeakerTopoFilter +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Redirects property request to miniport object + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[PropertyHandler_UsbHsSpeakerTopoFilter]")); + + // PropertryRequest structure is filled by portcls. + // MajorTarget is a pointer to miniport object for miniports. + // + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + // + // This line shows how to get a pointer to the miniport topology object. + // + PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + UNREFERENCED_VAR(pMiniport); + + if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack)) + { + switch(PropertyRequest->PropertyItem->Id) + { + case KSPROPERTY_JACK_DESCRIPTION: + ntStatus = PropertyHandler_UsbHsJackDescription( + PropertyRequest, + ARRAYSIZE(UsbHsSpeakerJackDescriptions), + UsbHsSpeakerJackDescriptions); + break; + + case KSPROPERTY_JACK_DESCRIPTION2: + ntStatus = PropertyHandler_UsbHsJackDescription2( + PropertyRequest, + ARRAYSIZE(UsbHsSpeakerJackDescriptions), + UsbHsSpeakerJackDescriptions); + break; + + case KSPROPERTY_JACK_CONTAINERID: + ntStatus = PropertyHandler_UsbHsJackContainerId( + PropertyRequest, + ARRAYSIZE(UsbHsSpeakerJackDescriptions), + UsbHsSpeakerJackDescriptions); + break; + } + } + + return ntStatus; +} // PropertyHandler_UsbHsSpeakerTopoFilter + +//============================================================================= +#pragma code_seg() +NTSTATUS +PropertyHandler_UsbHsSpeakerTopoFilterEvent +( + _In_ PPCEVENT_REQUEST EventRequest +) +{ + ASSERT(EventRequest); + + DPF_ENTER(("[PropertyHandler_UsbHsSpeakerTopoFilterEvent]")); + + return PropertyHandler_UsbHsTopoNodeEvent(EventRequest); +} + +#pragma code_seg() +#endif // SYSVAD_USB_SIDEBAND + + diff --git a/audio/sysvad/EndpointsCommon/usbhsspeakertopo.h b/audio/sysvad/EndpointsCommon/usbhsspeakertopo.h new file mode 100644 index 00000000..4e87253a --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsspeakertopo.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsspeakertopo.h + +Abstract: + + Declaration of topology miniport for the USB Headset speaker (external). + +--*/ + +#ifndef _SYSVAD_USBHSSPEAKERTOPO_H_ +#define _SYSVAD_USBHSSPEAKERTOPO_H_ + +// Function declarations. +NTSTATUS +PropertyHandler_UsbHsSpeakerTopoFilter( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + +NTSTATUS +PropertyHandler_UsbHsSpeakerTopoFilterEvent( + _In_ PPCEVENT_REQUEST EventRequest + ); + +#endif // _SYSVAD_USBHSSPEAKERTOPO_H_ + diff --git a/audio/sysvad/EndpointsCommon/usbhsspeakertoptable.h b/audio/sysvad/EndpointsCommon/usbhsspeakertoptable.h new file mode 100644 index 00000000..2f79024f --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsspeakertoptable.h @@ -0,0 +1,176 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsspeakertoptable.h + +Abstract: + + Declaration of topology tables for the USB Headset speaker (external). + +--*/ + +#ifndef _SYSVAD_USBHSSPEAKERTOPTABLE_H_ +#define _SYSVAD_USBHSSPEAKERTOPTABLE_H_ + +#include "usbhsspeakertopo.h" + +//============================================================================= +static +KSDATARANGE UsbHsSpeakerTopoPinDataRangesBridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +//============================================================================= +static +PKSDATARANGE UsbHsSpeakerTopoPinDataRangePointersBridge[] = +{ + &UsbHsSpeakerTopoPinDataRangesBridge[0] +}; + +//============================================================================= +static +PCPIN_DESCRIPTOR UsbHsSpeakerTopoMiniportPins[] = +{ + // KSPIN_TOPO_WAVEOUT_SOURCE + { + 0, + 0, + 0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(UsbHsSpeakerTopoPinDataRangePointersBridge),// DataRangesCount + UsbHsSpeakerTopoPinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSCATEGORY_AUDIO, // Category + NULL, // Name + 0 // Reserved + } + }, + // KSPIN_TOPO_LINEOUT_DEST + { + 0, + 0, + 0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(UsbHsSpeakerTopoPinDataRangePointersBridge),// DataRangesCount + UsbHsSpeakerTopoPinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_OUT, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_HEADSET_SPEAKERS, // Category + NULL, // Name + 0 // Reserved + } + } +}; + +//============================================================================= +static +KSJACK_DESCRIPTION UsbHsSpeakerJackDesc = +{ + KSAUDIO_SPEAKER_STEREO, + 0, // color + eConnTypeOtherDigital, + eGeoLocBottom, + eGenLocPrimaryBox, + ePortConnJack, + FALSE // run-time code sets this value. +}; + +// Only return a KSJACK_DESCRIPTION for the physical bridge pin. +static +PKSJACK_DESCRIPTION UsbHsSpeakerJackDescriptions[] = +{ + NULL, + &UsbHsSpeakerJackDesc +}; + +//============================================================================= +static +PCCONNECTION_DESCRIPTOR UsbHsSpeakerTopoMiniportConnections[] = +{ + // FromNode, FromPin, ToNode, ToPin + { PCFILTER_NODE, KSPIN_TOPO_WAVEOUT_SOURCE, PCFILTER_NODE, KSPIN_TOPO_LINEOUT_DEST } +}; + +//============================================================================= +static +PCPROPERTY_ITEM UsbHsSpeakerPropertiesTopoFilter[] = +{ + { + &KSPROPSETID_Jack, + KSPROPERTY_JACK_DESCRIPTION, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsSpeakerTopoFilter + }, + { + &KSPROPSETID_Jack, + KSPROPERTY_JACK_DESCRIPTION2, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsSpeakerTopoFilter + }, + { + &KSPROPSETID_Jack, + KSPROPERTY_JACK_CONTAINERID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsSpeakerTopoFilter + } +}; + +static +PCEVENT_ITEM UsbHsSpeakerPropertiesTopoFilterEvent[] = +{ + { + &KSEVENTSETID_PinCapsChange, // Something changed! + KSEVENT_PINCAPS_JACKINFOCHANGE, // The only event-property defined. + KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsSpeakerTopoFilterEvent + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationUsbHsSpeakerTopoFilterWithEvent, + UsbHsSpeakerPropertiesTopoFilter, + UsbHsSpeakerPropertiesTopoFilterEvent); + +//============================================================================= +static +PCFILTER_DESCRIPTOR UsbHsSpeakerTopoMiniportFilterDescriptor = +{ + 0, // Version + &AutomationUsbHsSpeakerTopoFilterWithEvent, // AutomationTable + sizeof(PCPIN_DESCRIPTOR), // PinSize + SIZEOF_ARRAY(UsbHsSpeakerTopoMiniportPins), // PinCount + UsbHsSpeakerTopoMiniportPins, // Pins + sizeof(PCNODE_DESCRIPTOR), // NodeSize + 0, // NodeCount + NULL, // Nodes + SIZEOF_ARRAY(UsbHsSpeakerTopoMiniportConnections), // ConnectionCount + UsbHsSpeakerTopoMiniportConnections, // Connections + 0, // CategoryCount + NULL // Categories +}; + +#endif // _SYSVAD_USBHSSPEAKERTOPTABLE_H_ + + diff --git a/audio/sysvad/EndpointsCommon/usbhsspeakerwavtable.h b/audio/sysvad/EndpointsCommon/usbhsspeakerwavtable.h new file mode 100644 index 00000000..619dd325 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhsspeakerwavtable.h @@ -0,0 +1,815 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhsspeakerwavtable.h + +Abstract: + + Declaration of wave miniport tables for the USB Headset speaker (external). + +--*/ + +#ifndef _SYSVAD_USBHSSPEAKERWAVTABLE_H_ +#define _SYSVAD_USBHSSPEAKERWAVTABLE_H_ + +// +// Function prototypes. +// +NTSTATUS PropertyHandler_UsbHsWaveFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest); + + + +#define USBHSSPEAKER_DEVICE_MAX_CHANNELS 2 // Max Channels. + +#define USBHSSPEAKER_HOST_MAX_CHANNELS 2 // Max Channels. +#define USBHSSPEAKER_HOST_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample +#define USBHSSPEAKER_HOST_MAX_BITS_PER_SAMPLE 24 // Max Bits Per Sample +#define USBHSSPEAKER_HOST_MIN_SAMPLE_RATE 24000 // Min Sample Rate +#define USBHSSPEAKER_HOST_MAX_SAMPLE_RATE 96000 // Max Sample Rate + +#define USBHSSPEAKER_OFFLOAD_MAX_CHANNELS 2 // Max Channels. +#define USBHSSPEAKER_OFFLOAD_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample +#define USBHSSPEAKER_OFFLOAD_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample +#define USBHSSPEAKER_OFFLOAD_MIN_SAMPLE_RATE 44100 // Min Sample Rate +#define USBHSSPEAKER_OFFLOAD_MAX_SAMPLE_RATE 48000 // Max Sample Rate + +#define USBHSSPEAKER_LOOPBACK_MAX_CHANNELS USBHSSPEAKER_HOST_MAX_CHANNELS // Must be equal to host pin's Max Channels. +#define USBHSSPEAKER_LOOPBACK_MIN_BITS_PER_SAMPLE USBHSSPEAKER_HOST_MIN_BITS_PER_SAMPLE // Must be equal to host pin's Min Bits Per Sample +#define USBHSSPEAKER_LOOPBACK_MAX_BITS_PER_SAMPLE USBHSSPEAKER_HOST_MAX_BITS_PER_SAMPLE // Must be equal to host pin's Max Bits Per Sample +#define USBHSSPEAKER_LOOPBACK_MIN_SAMPLE_RATE USBHSSPEAKER_HOST_MIN_SAMPLE_RATE // Must be equal to host pin's Min Sample Rate +#define USBHSSPEAKER_LOOPBACK_MAX_SAMPLE_RATE USBHSSPEAKER_HOST_MAX_SAMPLE_RATE // Must be equal to host pin's Max Sample Rate + +#define USBHSSPEAKER_DOLBY_DIGITAL_MAX_CHANNELS 2 // Max Channels. +#define USBHSSPEAKER_DOLBY_DIGITAL_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample +#define USBHSSPEAKER_DOLBY_DIGITAL_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample +#define USBHSSPEAKER_DOLBY_DIGITAL_MIN_SAMPLE_RATE 44100 // Min Sample Rate +#define USBHSSPEAKER_DOLBY_DIGITAL_MAX_SAMPLE_RATE 44100 // Max Sample Rate + +// +// Max # of pin instances. +// +#define USBHSSPEAKER_MAX_INPUT_SYSTEM_STREAMS 6 +#define USBHSSPEAKER_MAX_INPUT_OFFLOAD_STREAMS MAX_INPUT_OFFLOAD_STREAMS +#define USBHSSPEAKER_MAX_OUTPUT_LOOPBACK_STREAMS MAX_OUTPUT_LOOPBACK_STREAMS + +//============================================================================= +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE UsbHsSpeakerAudioEngineSupportedDeviceFormats[] = +{ + { // 0 + { + 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) + } + }, + { // 1 + { + 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) + } + }, + { // 2 + { + 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) + } + }, + { // 3 + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 288000, + 6, + 24, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + { // 4 + { + 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) + } + }, + { // 5 + { + 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 UsbHsSpeakerHostPinSupportedDeviceFormats[] = +{ + { // 0 + { + 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) + } + }, + { // 1 + { + 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) + } + }, + { // 2 + { + 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) + } + }, + { // 3 + { + 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) + } + }, + { // 4 + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 288000, + 6, + 24, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + { // 5 + { + 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) + } + }, + { // 6 + { + 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 UsbHsSpeakerOffloadPinSupportedDeviceFormats[] = +{ + { // 0 + { + 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) + } + }, + { // 1 + { + 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) + } + } +}; + +// +// Supported modes (only on streaming pins). +// +static +MODE_AND_DEFAULT_FORMAT UsbHsSpeakerHostPinSupportedDeviceModes[] = +{ + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW, + &UsbHsSpeakerHostPinSupportedDeviceFormats[3].DataFormat // 48KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + &UsbHsSpeakerHostPinSupportedDeviceFormats[4].DataFormat // 48KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_MEDIA, + &UsbHsSpeakerHostPinSupportedDeviceFormats[3].DataFormat // 48KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_MOVIE, + &UsbHsSpeakerHostPinSupportedDeviceFormats[3].DataFormat // 48KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, + &UsbHsSpeakerHostPinSupportedDeviceFormats[0].DataFormat // 24KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION, + &UsbHsSpeakerHostPinSupportedDeviceFormats[3].DataFormat // 48KHz + } +}; + +static +MODE_AND_DEFAULT_FORMAT UsbHsSpeakerOffloadPinSupportedDeviceModes[] = +{ + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + &UsbHsSpeakerOffloadPinSupportedDeviceFormats[1].DataFormat // 48KHz + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_MEDIA, + &UsbHsSpeakerOffloadPinSupportedDeviceFormats[1].DataFormat // 48KHz + } +}; + +// +// The entries here must follow the same order as the filter's pin +// descriptor array. +// +static +PIN_DEVICE_FORMATS_AND_MODES UsbHsSpeakerPinDeviceFormatsAndModes[] = +{ + { + SystemRenderPin, + UsbHsSpeakerHostPinSupportedDeviceFormats, + SIZEOF_ARRAY(UsbHsSpeakerHostPinSupportedDeviceFormats), + UsbHsSpeakerHostPinSupportedDeviceModes, + SIZEOF_ARRAY(UsbHsSpeakerHostPinSupportedDeviceModes) + }, + { + OffloadRenderPin, + UsbHsSpeakerOffloadPinSupportedDeviceFormats, + SIZEOF_ARRAY(UsbHsSpeakerOffloadPinSupportedDeviceFormats), + UsbHsSpeakerOffloadPinSupportedDeviceModes, + SIZEOF_ARRAY(UsbHsSpeakerOffloadPinSupportedDeviceModes), + }, + { + RenderLoopbackPin, + UsbHsSpeakerHostPinSupportedDeviceFormats, // Must support all the formats supported by host pin + SIZEOF_ARRAY(UsbHsSpeakerHostPinSupportedDeviceFormats), + NULL, // loopback doesn't support modes. + 0 + }, + { + BridgePin, + NULL, + 0, + NULL, + 0 + }, + { + NoPin, // For convenience, offload engine device formats appended here + UsbHsSpeakerAudioEngineSupportedDeviceFormats, + SIZEOF_ARRAY(UsbHsSpeakerAudioEngineSupportedDeviceFormats), + NULL, // no modes for this entry. + 0 + } +}; + +//============================================================================= +static +KSDATARANGE_AUDIO UsbHsSpeakerPinDataRangesStream[] = +{ + { // 0 + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + USBHSSPEAKER_HOST_MAX_CHANNELS, + USBHSSPEAKER_HOST_MIN_BITS_PER_SAMPLE, + USBHSSPEAKER_HOST_MAX_BITS_PER_SAMPLE, + USBHSSPEAKER_HOST_MIN_SAMPLE_RATE, + USBHSSPEAKER_HOST_MAX_SAMPLE_RATE + }, + { // 1 + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + USBHSSPEAKER_OFFLOAD_MAX_CHANNELS, + USBHSSPEAKER_OFFLOAD_MIN_BITS_PER_SAMPLE, + USBHSSPEAKER_OFFLOAD_MAX_BITS_PER_SAMPLE, + USBHSSPEAKER_OFFLOAD_MIN_SAMPLE_RATE, + USBHSSPEAKER_OFFLOAD_MAX_SAMPLE_RATE + }, + { // 2 + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + USBHSSPEAKER_LOOPBACK_MAX_CHANNELS, + USBHSSPEAKER_LOOPBACK_MIN_BITS_PER_SAMPLE, + USBHSSPEAKER_LOOPBACK_MAX_BITS_PER_SAMPLE, + USBHSSPEAKER_LOOPBACK_MIN_SAMPLE_RATE, + USBHSSPEAKER_LOOPBACK_MAX_SAMPLE_RATE + } +}; + +static +PKSDATARANGE UsbHsSpeakerPinDataRangePointersStream[] = +{ + PKSDATARANGE(&UsbHsSpeakerPinDataRangesStream[0]), + PKSDATARANGE(&PinDataRangeAttributeList) +}; + +static +PKSDATARANGE UsbHsSpeakerPinDataRangePointersOffloadStream[] = +{ + PKSDATARANGE(&UsbHsSpeakerPinDataRangesStream[1]), + PKSDATARANGE(&PinDataRangeAttributeList) +}; + +static +PKSDATARANGE UsbHsSpeakerPinDataRangePointersLoopbackStream[] = +{ + PKSDATARANGE(&UsbHsSpeakerPinDataRangesStream[2]) +}; + +//============================================================================= +static +KSDATARANGE UsbHsSpeakerPinDataRangesBridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +static +PKSDATARANGE UsbHsSpeakerPinDataRangePointersBridge[] = +{ + &UsbHsSpeakerPinDataRangesBridge[0] +}; + +//============================================================================= + +static +PCPROPERTY_ITEM PropertiesUsbHsSpeakerOffloadPin[] = +{ + { + &KSPROPSETID_OffloadPin, // define new property set + KSPROPERTY_OFFLOAD_PIN_GET_STREAM_OBJECT_POINTER, // define properties + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_OffloadPin + }, + { + &KSPROPSETID_OffloadPin, // define new property set + KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER, // define properties + KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_OffloadPin + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationUsbHsSpeakerOffloadPin, PropertiesUsbHsSpeakerOffloadPin); + +//============================================================================= +static +PCPIN_DESCRIPTOR UsbHsSpeakerWaveMiniportPins[] = +{ + // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER_SINK_SYSTEM + { + USBHSSPEAKER_MAX_INPUT_SYSTEM_STREAMS, + USBHSSPEAKER_MAX_INPUT_SYSTEM_STREAMS, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(UsbHsSpeakerPinDataRangePointersStream), + UsbHsSpeakerPinDataRangePointersStream, + KSPIN_DATAFLOW_IN, + KSPIN_COMMUNICATION_SINK, + &KSCATEGORY_AUDIO, + NULL, + 0 + } + }, + // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER_SINK_OFFLOAD + { + USBHSSPEAKER_MAX_INPUT_OFFLOAD_STREAMS, + USBHSSPEAKER_MAX_INPUT_OFFLOAD_STREAMS, + 0, + &AutomationUsbHsSpeakerOffloadPin, // AutomationTable + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(UsbHsSpeakerPinDataRangePointersOffloadStream), + UsbHsSpeakerPinDataRangePointersOffloadStream, + KSPIN_DATAFLOW_IN, + KSPIN_COMMUNICATION_SINK, + &KSCATEGORY_AUDIO, + NULL, + 0 + } + }, + // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER_SINK_LOOPBACK + { + USBHSSPEAKER_MAX_OUTPUT_LOOPBACK_STREAMS, + USBHSSPEAKER_MAX_OUTPUT_LOOPBACK_STREAMS, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(UsbHsSpeakerPinDataRangePointersLoopbackStream), + UsbHsSpeakerPinDataRangePointersLoopbackStream, + KSPIN_DATAFLOW_OUT, + KSPIN_COMMUNICATION_SINK, + &KSNODETYPE_AUDIO_LOOPBACK, + NULL, + 0 + } + }, + // Wave Out Bridge Pin (Renderer) KSPIN_WAVE_RENDER_SOURCE + { + 0, + 0, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(UsbHsSpeakerPinDataRangePointersBridge), + UsbHsSpeakerPinDataRangePointersBridge, + KSPIN_DATAFLOW_OUT, + KSPIN_COMMUNICATION_NONE, + &KSCATEGORY_AUDIO, + NULL, + 0 + } + }, +}; + +//============================================================================= +static +PCNODE_DESCRIPTOR UsbHsSpeakerWaveMiniportNodes[] = +{ + // KSNODE_WAVE_AUDIO_ENGINE + { + 0, // Flags + NULL, // AutomationTable + &KSNODETYPE_AUDIO_ENGINE, // Type KSNODETYPE_AUDIO_ENGINE + NULL // Name + } +}; +//============================================================================= +// +// ---------------------------- +// | | +// System Pin 0-->| |--> 2 Loopback Pin +// | HW Audio Engine node | +// Offload Pin 1-->| |--> 3 KSPIN_WAVE_RENDER_SOURCE +// | | +// ---------------------------- +static +PCCONNECTION_DESCRIPTOR UsbHsSpeakerWaveMiniportConnections[] = +{ + { PCFILTER_NODE, KSPIN_WAVE_RENDER_SINK_SYSTEM, KSNODE_WAVE_AUDIO_ENGINE, 1 }, + { PCFILTER_NODE, KSPIN_WAVE_RENDER_SINK_OFFLOAD, KSNODE_WAVE_AUDIO_ENGINE, 2 }, + { KSNODE_WAVE_AUDIO_ENGINE, 3, PCFILTER_NODE, KSPIN_WAVE_RENDER_SINK_LOOPBACK }, + { KSNODE_WAVE_AUDIO_ENGINE, 0, PCFILTER_NODE, KSPIN_WAVE_RENDER_SOURCE }, +}; + +//============================================================================= +static +PCPROPERTY_ITEM PropertiesUsbHsSpeakerWaveFilter[] = +{ + { + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PROPOSEDATAFORMAT, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsWaveFilter + }, + { + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PROPOSEDATAFORMAT2, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsWaveFilter + }, + { + &KSPROPSETID_AudioEffectsDiscovery, + KSPROPERTY_AUDIOEFFECTSDISCOVERY_EFFECTSLIST, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_UsbHsWaveFilter + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationUsbHsSpeakerWaveFilter, PropertiesUsbHsSpeakerWaveFilter); + +//============================================================================= +static +PCFILTER_DESCRIPTOR UsbHsSpeakerWaveMiniportFilterDescriptor = +{ + 0, // Version + &AutomationUsbHsSpeakerWaveFilter, // AutomationTable + sizeof(PCPIN_DESCRIPTOR), // PinSize + SIZEOF_ARRAY(UsbHsSpeakerWaveMiniportPins), // PinCount + UsbHsSpeakerWaveMiniportPins, // Pins + sizeof(PCNODE_DESCRIPTOR), // NodeSize + SIZEOF_ARRAY(UsbHsSpeakerWaveMiniportNodes), // NodeCount + UsbHsSpeakerWaveMiniportNodes, // Nodes + SIZEOF_ARRAY(UsbHsSpeakerWaveMiniportConnections),// ConnectionCount + UsbHsSpeakerWaveMiniportConnections, // Connections + 0, // CategoryCount + NULL // Categories - use defaults (audio, render, capture) +}; + +#endif // _SYSVAD_USBHSSPEAKERWAVTABLE_H_ + diff --git a/audio/sysvad/EndpointsCommon/usbhstopo.cpp b/audio/sysvad/EndpointsCommon/usbhstopo.cpp new file mode 100644 index 00000000..e32f2027 --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhstopo.cpp @@ -0,0 +1,538 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhstopo.cpp + +Abstract: + + Implementation of topology miniport for the USB Headset (external). + +--*/ +#ifdef SYSVAD_USB_SIDEBAND + +#pragma warning (disable : 4127) + +#include +#include "simple.h" +#include "mintopo.h" +#include "usbhstopo.h" + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsVolumeLevel_BasicSupport +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Handles basic support for USB Headset ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_VOLUMELEVEL ) + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG cbDescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); + ASSERT(PropertyRequest); + + if (PropertyRequest->ValueSize >= cbDescriptionSize) + { + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + ULONG volumeSettingsSize = 0; + PKSPROPERTY_DESCRIPTION volumeSettings; + PKSPROPERTY_DESCRIPTION propDesc; + PSIDEBANDDEVICECOMMON usbHsDevice; + + propDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + volumeSettings = (PKSPROPERTY_DESCRIPTION)usbHsDevice->GetVolumeSettings(miniport->m_DeviceType, &volumeSettingsSize); + ASSERT(volumeSettings != NULL); + ASSERT(volumeSettingsSize != 0); + + ULONG cbFullProperty = volumeSettings->DescriptionSize; + + // if return buffer can hold a range description, return it + if(PropertyRequest->ValueSize >= cbFullProperty) + { + RtlCopyMemory(propDesc, volumeSettings, volumeSettings->DescriptionSize); + // set the return value size + PropertyRequest->ValueSize = cbFullProperty; + } + else + { + // otherwise only return description header + RtlCopyMemory(propDesc, volumeSettings, cbDescriptionSize); + // set the return value size + PropertyRequest->ValueSize = cbDescriptionSize; + } + } + else if(PropertyRequest->ValueSize >= sizeof(ULONG)) + { + // if return buffer can hold a ULONG, return the access flags + PULONG AccessFlags = PULONG(PropertyRequest->Value); + + PropertyRequest->ValueSize = sizeof(ULONG); + *AccessFlags = KSPROPERTY_TYPE_ALL; + } + else + { + PropertyRequest->ValueSize = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsMute_BasicSupport +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Handles basic support for USB Headset ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MUTE ) + +Arguments: + + PropertyRequest - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG cbDescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); + ASSERT(PropertyRequest); + + if (PropertyRequest->ValueSize >= cbDescriptionSize) + { + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + ULONG muteSettingsSize = 0; + PKSPROPERTY_DESCRIPTION muteSettings; + PKSPROPERTY_DESCRIPTION propDesc; + PSIDEBANDDEVICECOMMON usbHsDevice; + + propDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + muteSettings = (PKSPROPERTY_DESCRIPTION)usbHsDevice->GetMuteSettings(miniport->m_DeviceType, &muteSettingsSize); + ASSERT(muteSettings != NULL); + ASSERT(muteSettingsSize != 0); + + ULONG cbFullProperty = muteSettings->DescriptionSize; + + // if return buffer can hold mute description, return it + if(PropertyRequest->ValueSize >= cbFullProperty) + { + RtlCopyMemory(propDesc, muteSettings, muteSettings->DescriptionSize); + // set the return value size + PropertyRequest->ValueSize = cbFullProperty; + } + else + { + // otherwise only return description header + RtlCopyMemory(propDesc, muteSettings, cbDescriptionSize); + // set the return value size + PropertyRequest->ValueSize = cbDescriptionSize; + } + } + else if(PropertyRequest->ValueSize >= sizeof(ULONG)) + { + // if return buffer can hold a ULONG, return the access flags + PULONG AccessFlags = PULONG(PropertyRequest->Value); + + PropertyRequest->ValueSize = sizeof(ULONG); + *AccessFlags = KSPROPERTY_TYPE_ALL; + } + else + { + PropertyRequest->ValueSize = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsJackDescription +( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION ) + +Arguments: + + PropertyRequest - + + cJackDescriptions - + + JackDescriptions - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + ULONG nPinId = (ULONG)-1; + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + + 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_DESCRIPTION); + + 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) + { + PSIDEBANDDEVICECOMMON usbHsDevice = NULL; + PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value; + PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1); + + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + pMI->Size = cbNeeded; + pMI->Count = 1; + + RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION)); + + pDesc->IsConnected = usbHsDevice->GetConnectionStatus() ? TRUE : FALSE; + + ntStatus = STATUS_SUCCESS; + } + } + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsJackDescription2 +( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 ) + +Arguments: + + PropertyRequest - + + cJackDescriptions - + + JackDescriptions - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[%!FUNC!]")); + + 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_DESCRIPTION2); + + 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_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI+1); + + pMI->Size = cbNeeded; + pMI->Count = 1; + + RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2)); + + // + // Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether + // the jack is currently active, streaming, idle, or hardware not ready. + // + pDesc->DeviceStateInfo = 0; + + // + // From MSDN: + // "If an audio device lacks jack presence detection, the IsConnected member of + // the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the + // ambiguity that results from this dual meaning of the TRUE value for IsConnected, + // a client application can call IKsJackDescription2::GetJackDescription2 to read + // the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has + // the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint + // does in fact support jack presence detection. In that case, the return value of + // the IsConnected member can be interpreted to accurately reflect the insertion status + // of the jack." + // + // Bit definitions: + // 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY + // 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY + // + pDesc->JackCapabilities = JACKDESC2_PRESENCE_DETECT_CAPABILITY; + + ntStatus = STATUS_SUCCESS; + } + } + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +PropertyHandler_UsbHsJackContainerId +( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_CONTAINERID ) + +Arguments: + + PropertyRequest - + + cJackDescriptions - + + JackDescriptions - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + PCMiniportTopology miniport = (PCMiniportTopology)PropertyRequest->MajorTarget; + ULONG nPinId = (ULONG)-1; + + if (PropertyRequest->InstanceSize >= sizeof(ULONG)) + { + nPinId = *(PULONG(PropertyRequest->Instance)); + + // This property is only valid on bridge pins. + 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(GUID); + + 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) + { + PSIDEBANDDEVICECOMMON usbHsDevice = NULL; + + GUID* guid = (GUID *)PropertyRequest->Value; + + usbHsDevice = miniport->GetSidebandDevice(); // weak ref. + ASSERT(usbHsDevice != NULL); + + *guid = usbHsDevice->GetContainerId(miniport->m_DeviceType); + + ntStatus = STATUS_SUCCESS; + } + } + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +PropertyHandler_UsbHsTopoNodeEvent +( + _In_ PPCEVENT_REQUEST EventRequest +) +{ + ASSERT(EventRequest); + + DPF_ENTER(("[%!FUNC!]")); + + // The major target is the object pointer to the topology miniport. + PCMiniportTopology pMiniport = (PCMiniportTopology)EventRequest->MajorTarget; + ASSERT (pMiniport); + + switch (EventRequest->Verb) + { + // Do we support event handling?!? + case PCEVENT_VERB_SUPPORT: + DPF(D_VERBOSE, ("BasicSupport Query for event.")); + break; + + // We should add the event now! + case PCEVENT_VERB_ADD: + DPF(D_VERBOSE, ("Adding event.")); + + // If we have the interface and EventEntry is defined ... + if (EventRequest->EventEntry) + { + pMiniport->AddEventToEventList(EventRequest->EventEntry); + } + else + { + return STATUS_UNSUCCESSFUL; + } + break; + + case PCEVENT_VERB_REMOVE: + // We cannot remove the event but we can stop generating the + // events. However, it also doesn't hurt to always generate them ... + DPF(D_VERBOSE, ("Removing event.")); + break; + + default: + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +#pragma code_seg() +#endif //SYSVAD_USB_SIDEBAND + + diff --git a/audio/sysvad/EndpointsCommon/usbhstopo.h b/audio/sysvad/EndpointsCommon/usbhstopo.h new file mode 100644 index 00000000..d3a3adab --- /dev/null +++ b/audio/sysvad/EndpointsCommon/usbhstopo.h @@ -0,0 +1,65 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + usbhstopo.h + +Abstract: + + Declaration of topology miniport for the mic (external: USB headphone). + +--*/ + +#ifndef _SYSVAD_USBHSTOPO_H_ +#define _SYSVAD_USBHSTOPO_H_ + +NTSTATUS +PropertyHandler_UsbHsVolumeLevel_BasicSupport( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + +NTSTATUS +PropertyHandler_UsbHsMicVolumeLevel( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + +NTSTATUS +PropertyHandler_UsbHsMute_BasicSupport( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + +NTSTATUS +PropertyHandler_UsbHsMicMute( + _In_ PPCPROPERTY_REQUEST PropertyRequest + ); + +NTSTATUS +PropertyHandler_UsbHsJackDescription( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions + ); + +NTSTATUS +PropertyHandler_UsbHsJackDescription2( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions + ); + +NTSTATUS +PropertyHandler_UsbHsJackContainerId( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions + ); + +NTSTATUS +PropertyHandler_UsbHsTopoNodeEvent( + _In_ PPCEVENT_REQUEST EventRequest + ); + +#endif // _SYSVAD_USBHSTOPO_H_ + diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj index 54913231..898fa184 100644 --- a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj +++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj @@ -1,10 +1,26 @@  + + Debug + ARM + + + Debug + ARM64 + Debug Win32 + + Release + ARM + + + Release + ARM64 + Release Win32 @@ -36,6 +52,14 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + False + Universal + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 True @@ -44,6 +68,14 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + True + Universal + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 False @@ -52,6 +84,14 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + False + Universal + + WindowsApplicationForDrivers10.0 + DynamicLibrary + Windows10 True @@ -60,6 +100,14 @@ WindowsApplicationForDrivers10.0 DynamicLibrary + + Windows10 + True + Universal + + WindowsApplicationForDrivers10.0 + DynamicLibrary + $(IntDir) @@ -67,52 +115,100 @@ + + + + + + + + + + + + KeywordDetectorContosoAdapter + + KeywordDetectorContosoAdapter + KeywordDetectorContosoAdapter + + KeywordDetectorContosoAdapter + KeywordDetectorContosoAdapter + + KeywordDetectorContosoAdapter + KeywordDetectorContosoAdapter + + KeywordDetectorContosoAdapter + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + _DllMainCRTStartup@12 _DllMainCRTStartup + + + _DllMainCRTStartup@12 + _DllMainCRTStartup + + MultiThreaded @@ -137,6 +233,30 @@ KeywordDetectorContosoAdapter.def + + + MultiThreaded + MultiThreadedDebug + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib + KeywordDetectorContosoAdapter.def + + MultiThreaded @@ -161,6 +281,30 @@ KeywordDetectorContosoAdapter.def + + + MultiThreaded + MultiThreadedDebug + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib + KeywordDetectorContosoAdapter.def + + MultiThreaded @@ -185,6 +329,30 @@ KeywordDetectorContosoAdapter.def + + + MultiThreaded + MultiThreadedDebug + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib + KeywordDetectorContosoAdapter.def + + MultiThreaded @@ -209,6 +377,30 @@ KeywordDetectorContosoAdapter.def + + + MultiThreaded + MultiThreadedDebug + true + Level4 + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + %(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\ + + + %(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib + KeywordDetectorContosoAdapter.def + + diff --git a/audio/sysvad/Package/package.VcxProj b/audio/sysvad/Package/package.VcxProj index 1188dbbd..2874ff42 100644 --- a/audio/sysvad/Package/package.VcxProj +++ b/audio/sysvad/Package/package.VcxProj @@ -1,10 +1,26 @@  + + Debug + ARM + + + Debug + ARM64 + Debug Win32 + + Release + ARM + + + Release + ARM64 + Release Win32 @@ -52,18 +68,34 @@ Windows10 true + + Windows10 + true + Windows10 false + + Windows10 + false + Windows10 true + + Windows10 + true + Windows10 false + + Windows10 + false + diff --git a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj index eeb7b6c6..595ccfa6 100644 --- a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj +++ b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj @@ -1,10 +1,26 @@  + + Debug + ARM + + + Debug + ARM64 + Debug Win32 + + Release + ARM + + + Release + ARM64 + Release Win32 @@ -37,6 +53,14 @@ WindowsKernelModeDriver10.0 Driver + + Windows10 + False + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + Windows10 True @@ -45,6 +69,14 @@ WindowsKernelModeDriver10.0 Driver + + Windows10 + True + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + Windows10 False @@ -53,6 +85,14 @@ WindowsKernelModeDriver10.0 Driver + + Windows10 + False + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + Windows10 True @@ -61,6 +101,14 @@ WindowsKernelModeDriver10.0 Driver + + Windows10 + True + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + $(IntDir) @@ -68,34 +116,68 @@ + + + + + + + + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. true Level4 %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + true + Level4 + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE @@ -105,19 +187,41 @@ %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + true + Level4 + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. true Level4 %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE @@ -127,19 +231,41 @@ %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. true Level4 %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + true + Level4 + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE @@ -149,19 +275,41 @@ %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + true + Level4 + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. true Level4 %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE @@ -169,35 +317,71 @@ PhoneAudioSample + + PhoneAudioSample + PhoneAudioSample + + PhoneAudioSample + PhoneAudioSample + + PhoneAudioSample + PhoneAudioSample + + PhoneAudioSample + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. + + + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower + %(AdditionalIncludeDirectories);..\EndpointsCommon + + + + + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. 4595;%(DisableSpecificWarnings) - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon @@ -206,21 +390,37 @@ %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. + + + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower + %(AdditionalIncludeDirectories);..\EndpointsCommon + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon + + + + + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. 4595;%(DisableSpecificWarnings) - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon @@ -229,21 +429,37 @@ %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. + + + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower + %(AdditionalIncludeDirectories);..\EndpointsCommon + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon + + + + + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. 4595;%(DisableSpecificWarnings) - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon @@ -252,21 +468,38 @@ %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. + + + 4595;%(DisableSpecificWarnings) + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower + %(AdditionalIncludeDirectories);..\EndpointsCommon + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon + + + + + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. 4595;%(DisableSpecificWarnings) - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_IPortClsRuntimePower + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon @@ -274,6 +507,7 @@ + diff --git a/audio/sysvad/PhoneAudioSample/sources b/audio/sysvad/PhoneAudioSample/sources index 46aa7bad..e16edb8e 100644 --- a/audio/sysvad/PhoneAudioSample/sources +++ b/audio/sysvad/PhoneAudioSample/sources @@ -11,7 +11,7 @@ TARGETLIBS= \ $(OBJ_PATH)\..\EndpointsCommon\$(O)\EndpointsCommon.lib -C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS +C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS -DSYSVAD_USB_SIDEBAND #C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ # diff --git a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj index 205ff309..ba22dcf1 100644 --- a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj +++ b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj @@ -1,10 +1,26 @@  + + Debug + ARM + + + Debug + ARM64 + Debug Win32 + + Release + ARM + + + Release + ARM64 + Release Win32 @@ -37,6 +53,14 @@ WindowsKernelModeDriver10.0 Driver + + Windows10 + False + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + Windows10 True @@ -45,6 +69,14 @@ WindowsKernelModeDriver10.0 Driver + + Windows10 + True + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + Windows10 False @@ -53,6 +85,14 @@ WindowsKernelModeDriver10.0 Driver + + Windows10 + False + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + Windows10 True @@ -61,6 +101,14 @@ WindowsKernelModeDriver10.0 Driver + + Windows10 + True + Universal + KMDF + WindowsKernelModeDriver10.0 + Driver + $(IntDir) @@ -68,34 +116,68 @@ + + + + + + + + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + true + Level4 + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. true Level4 %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE @@ -105,19 +187,41 @@ %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. true Level4 %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + true + Level4 + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE @@ -127,19 +231,41 @@ %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. true Level4 %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + true + Level4 + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE @@ -149,19 +275,41 @@ %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. true Level4 %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;. + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. + true + Level4 + %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION + %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);.. %(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION %(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE @@ -169,35 +317,70 @@ TabletAudioSample + + TabletAudioSample + TabletAudioSample + + TabletAudioSample + TabletAudioSample + + TabletAudioSample + TabletAudioSample + + TabletAudioSample + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates;_NEW_DELETE_OPERATORS_ + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. + + + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower + %(AdditionalIncludeDirectories);..\EndpointsCommon + + + + + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. - 4595;%(DisableSpecificWarnings) - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon @@ -206,21 +389,36 @@ %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. + + + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower + %(AdditionalIncludeDirectories);..\EndpointsCommon + + + + + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. - 4595;%(DisableSpecificWarnings) - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon @@ -229,21 +427,36 @@ %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. + + + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower + %(AdditionalIncludeDirectories);..\EndpointsCommon + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon + + + + + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. - 4595;%(DisableSpecificWarnings) - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon @@ -252,21 +465,37 @@ %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates;_NEW_DELETE_OPERATORS_ + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. + + + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower + %(AdditionalIncludeDirectories);..\EndpointsCommon + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon + + + + + %(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib + + + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_ + %(AdditionalIncludeDirectories);..\EndpointsCommon;. 4595;%(DisableSpecificWarnings) - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon - %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS - %(PreprocessorDefinitions);_USE_SingleComponentMultiFxStates + %(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower %(AdditionalIncludeDirectories);..\EndpointsCommon @@ -279,6 +508,7 @@ + diff --git a/audio/sysvad/TabletAudioSample/sources b/audio/sysvad/TabletAudioSample/sources index 91592397..07b14c18 100644 --- a/audio/sysvad/TabletAudioSample/sources +++ b/audio/sysvad/TabletAudioSample/sources @@ -11,7 +11,7 @@ TARGETLIBS= \ $(OBJ_PATH)\..\EndpointsCommon\$(O)\EndpointsCommon.lib \ -C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS +C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS -DSYSVAD_USB_SIDEBAND #C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ diff --git a/audio/sysvad/UsbHsDevice.cpp b/audio/sysvad/UsbHsDevice.cpp new file mode 100644 index 00000000..6bc42384 --- /dev/null +++ b/audio/sysvad/UsbHsDevice.cpp @@ -0,0 +1,5036 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + UsbHsDevice.cpp + +Abstract: + + Implementation of the UsbHsDevice class. + +--*/ + +#pragma warning (disable : 4127) + +#include +#include +#include "hw.h" +#include "savedata.h" +#include "IHVPrivatePropertySet.h" +#include "simple.h" + +#ifdef SYSVAD_USB_SIDEBAND +#include +#include +#include +#include +#include +#include // guild-arrival/removal +#include +#include "usbhsminipairs.h" +#include "UsbHsDevice.h" +#include "UsbHsDeviceFormats.h" + +// +// UsbHsDevice implementation. +// + +// # of sec before sync request is cancelled. +#define USB_SIDEBAND_SYNC_REQ_TIMEOUT_IN_SEC 60 +#define USB_SIDEBAND_NOTIFICATION_MAX_ERROR_COUNT 5 + +//============================================================================= +#pragma code_seg("PAGE") +STDMETHODIMP +UsbHsDevice::NonDelegatingQueryInterface +( + _In_ REFIID Interface, + _COM_Outptr_ PVOID * Object +) +/*++ + +Routine Description: + + QueryInterface routine for UsbHsDevice + +Arguments: + + Interface - + + Object - + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(Object); + + if (IsEqualGUIDAligned(Interface, IID_IUnknown)) + { + *Object = PVOID(PUNKNOWN(PSIDEBANDDEVICECOMMON(this))); + } + else if (IsEqualGUIDAligned(Interface, IID_IUsbHsDeviceCommon)) + { + *Object = PVOID(PSIDEBANDDEVICECOMMON(this)); + } + else + { + *Object = NULL; + } + + if (*Object) + { + PUNKNOWN(*Object)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} // NonDelegatingQueryInterface + +//============================================================================= +// Dummy stubs to override the default WDF behavior of closing the target +// on query remove. This driver closes and deletes the supporting objects +// when the target removes the USB Sideband interface. +// + +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::EvtUsbHsTargetQueryRemove +( + _In_ WDFIOTARGET IoTarget +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + UNREFERENCED_PARAMETER(IoTarget); + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +VOID +UsbHsDevice::EvtUsbHsTargetRemoveCanceled +( + _In_ WDFIOTARGET IoTarget +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + UNREFERENCED_PARAMETER(IoTarget); +} +#pragma code_seg("PAGE") +VOID +UsbHsDevice::EvtUsbHsTargetRemoveComplete +( + _In_ WDFIOTARGET IoTarget +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + UNREFERENCED_PARAMETER(IoTarget); +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::Init +( + _In_ IAdapterCommon * Adapter, + _In_ PUNICODE_STRING SymbolicLinkName +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationWorkItemContext *wiCtx = NULL; + UsbHsDeviceNotificationReqContext *reqCtx = NULL; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_IO_TARGET_OPEN_PARAMS openParams; + WDF_WORKITEM_CONFIG wiConfig; + + AddRef(); // first ref. + + // + // Basic init of all the class' members. + // + m_State = eUsbHsStateInitializing; + m_Adapter = Adapter; + + // Static config. + m_WdfIoTarget = NULL; + m_SpeakerMiniports = NULL; + m_MicMiniports = NULL; + m_UnknownSpeakerTopology = NULL; + m_UnknownSpeakerWave = NULL; + m_UnknownMicTopology = NULL; + m_UnknownMicWave = NULL; + m_Descriptor = NULL; + m_SpeakerVolumePropValues = NULL; + m_MicVolumePropValues = NULL; + m_SpeakerMutePropValues = NULL; + m_MicMutePropValues = NULL; + m_ulSpeakerMutePropValuesSize = 0; + m_ulMicMutePropValuesSize = 0; + + // Notification updates. + m_SpeakerVolumeLevel = 0; + m_MicVolumeLevel = 0; + m_SpeakerMute = 0; + m_MicMute = 0; + m_SpeakerStreamStatusLong = STATUS_SUCCESS; // USB stream is not open. + m_MicStreamStatusLong = STATUS_SUCCESS; // USB stream is not open. + + m_SpeakerStreamReq = NULL; + m_MicStreamReq = NULL; + m_SpeakerVolumeReq = NULL; + m_MicVolumeReq = NULL; + m_SpeakerMuteReq = NULL; + m_MicMuteReq = NULL; + + m_WorkItem = NULL; + m_ReqCollection = NULL; + + m_nSpeakerStreamsOpen = 0; + m_nMicStreamsOpen = 0; + + m_nSpeakerStreamsStart = 0; + m_nMicStreamsStart = 0; + + m_pSpeakerSupportedFormatsIntersection = NULL; + m_pMicSupportedFormatsIntersection = NULL; + + KeInitializeEvent(&m_SpeakerStreamStatusEvent, NotificationEvent, TRUE); + KeInitializeEvent(&m_MicStreamStatusEvent, NotificationEvent, TRUE); + + InitializeListHead(&m_ListEntry); + KeInitializeSpinLock(&m_Lock); + + RtlZeroMemory(&m_SymbolicLinkName, sizeof(m_SymbolicLinkName)); + + RtlZeroMemory(&m_SpeakerVolumeCallback, sizeof(m_SpeakerVolumeCallback)); + RtlZeroMemory(&m_MicVolumeCallback, sizeof(m_MicVolumeCallback)); + + RtlZeroMemory(&m_SpeakerMuteCallback, sizeof(m_SpeakerMuteCallback)); + RtlZeroMemory(&m_MicMuteCallback, sizeof(m_MicMuteCallback)); + + RtlZeroMemory(&m_SpeakerConnectionStatusCallback, sizeof(m_SpeakerConnectionStatusCallback)); + RtlZeroMemory(&m_MicConnectionStatusCallback, sizeof(m_MicConnectionStatusCallback)); + + RtlZeroMemory(&m_SpeakerFormatChangeCallback, sizeof(m_SpeakerFormatChangeCallback)); + RtlZeroMemory(&m_MicFormatChangeCallback, sizeof(m_MicFormatChangeCallback)); + + RtlZeroMemory(&m_SpeakerTransportResources, sizeof(USBHSDEVICE_EP_TRANSPORT_RESOURCES)); + RtlZeroMemory(&m_MicTransportResources , sizeof(USBHSDEVICE_EP_TRANSPORT_RESOURCES)); + + // + // Allocate a notification WDF work-item. + // + WDF_WORKITEM_CONFIG_INIT(&wiConfig, EvtUsbHsDeviceNotificationStatusWorkItem); + wiConfig.AutomaticSerialization = FALSE; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, UsbHsDeviceNotificationWorkItemContext); + attributes.ParentObject = Adapter->GetWdfDevice(); + ntStatus = WdfWorkItemCreate( &wiConfig, + &attributes, + &m_WorkItem); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfWorkItemCreate failed: 0x%x", ntStatus)), + Done); + + wiCtx = GetUsbHsDeviceNotificationWorkItemContext(m_WorkItem); + wiCtx->UsbHsDevice = this; // weak ref. + + // + // Allocate a collection to hold notification requests for the notification work-item. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfCollectionCreate( + &attributes, + &m_ReqCollection); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfCollectionCreate failed: 0x%x", ntStatus)), + Done); + + // + // Open the target interface. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfIoTargetCreate(m_Adapter->GetWdfDevice(), + &attributes, + &m_WdfIoTarget); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfIoTargetCreate failed: 0x%x", ntStatus)), + Done); + + WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( + &openParams, + SymbolicLinkName, + STANDARD_RIGHTS_ALL); + + openParams.EvtIoTargetQueryRemove = EvtUsbHsTargetQueryRemove; + openParams.EvtIoTargetRemoveCanceled = EvtUsbHsTargetRemoveCanceled; + openParams.EvtIoTargetRemoveComplete = EvtUsbHsTargetRemoveComplete; + + ntStatus = WdfIoTargetOpen(m_WdfIoTarget, &openParams); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfIoTargetOpen(%wZ) failed: 0x%x", SymbolicLinkName, ntStatus)), + Done); + + PDEVICE_OBJECT pdo = WdfIoTargetWdmGetTargetPhysicalDevice(m_WdfIoTarget); + m_Adapter->AddDeviceAsPowerDependency(pdo); + + // + // Make a copy of the symbolic link name. + // + m_SymbolicLinkName.MaximumLength = SymbolicLinkName->MaximumLength; + m_SymbolicLinkName.Length = SymbolicLinkName->Length; + m_SymbolicLinkName.Buffer = (PWSTR) ExAllocatePoolWithTag(NonPagedPoolNx, + SymbolicLinkName->MaximumLength, + MINADAPTER_POOLTAG); + if (m_SymbolicLinkName.Buffer == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: ExAllocatePoolWithTag failed, out of memory")), + Done); + + RtlCopyUnicodeString(&m_SymbolicLinkName, SymbolicLinkName); + + // + // Allocate the WDF requests for status notifications. + // + + // + // IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE + // SPEAKER + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, UsbHsDeviceNotificationReqContext); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &m_SpeakerVolumeReq); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate(Speaker-Volume) failed, 0x%x", ntStatus)), + Done); + + // Init context. + reqCtx = GetUsbHsDeviceNotificationReqContext(m_SpeakerVolumeReq); + reqCtx->UsbHsDevice = this; // weak ref. + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.Volume), + &reqCtx->MemIn); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.Volume), + &reqCtx->MemOut); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + // + // IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE + // MIC + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, UsbHsDeviceNotificationReqContext); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &m_MicVolumeReq); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate(Mic-Volume) failed, 0x%x", ntStatus)), + Done); + + // Init context. + reqCtx = GetUsbHsDeviceNotificationReqContext(m_MicVolumeReq); + reqCtx->UsbHsDevice = this; // weak ref. + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.Volume), + &reqCtx->MemIn); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.Volume), + &reqCtx->MemOut); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + // + // IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE + // SPEAKER + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, UsbHsDeviceNotificationReqContext); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &m_SpeakerMuteReq); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate(Speaker-Mute) failed, 0x%x", ntStatus)), + Done); + + // Init context. + reqCtx = GetUsbHsDeviceNotificationReqContext(m_SpeakerMuteReq); + reqCtx->UsbHsDevice = this; // weak ref. + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.Mute), + &reqCtx->MemIn); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.Mute), + &reqCtx->MemOut); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + // + // IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE + // MIC + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, UsbHsDeviceNotificationReqContext); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &m_MicMuteReq); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate(Mic-Mute) failed, 0x%x", ntStatus)), + Done); + + // Init context. + reqCtx = GetUsbHsDeviceNotificationReqContext(m_MicMuteReq); + reqCtx->UsbHsDevice = this; // weak ref. + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.Mute), + &reqCtx->MemIn); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.Mute), + &reqCtx->MemOut); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + // + // IOCTL_SBAUD_GET_STREAM_STATUS_UPDATE + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, UsbHsDeviceNotificationReqContext); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &m_SpeakerStreamReq); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate(Stream-Status) failed, 0x%x", ntStatus)), + Done); + + // Init context. + reqCtx = GetUsbHsDeviceNotificationReqContext(m_SpeakerStreamReq); + reqCtx->UsbHsDevice = this; // weak ref. + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.streamStatus), + &reqCtx->MemIn); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.streamStatus), + &reqCtx->MemOut); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + // + // IOCTL_SBAUD_GET_STREAM_STATUS_UPDATE + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, UsbHsDeviceNotificationReqContext); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &m_MicStreamReq); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate(Stream-Status) failed, 0x%x", ntStatus)), + Done); + + // Init context. + reqCtx = GetUsbHsDeviceNotificationReqContext(m_MicStreamReq); + reqCtx->UsbHsDevice = this; // weak ref. + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.streamStatus), + &reqCtx->MemIn); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + ntStatus = WdfMemoryCreatePreallocated( + WDF_NO_OBJECT_ATTRIBUTES, + &reqCtx->Buffer, + sizeof(reqCtx->Buffer.streamStatus), + &reqCtx->MemOut); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfMemoryCreatePreallocated failed, 0x%x", ntStatus)), + Done); + + // + // Create wave and filter names unique to this USB device + // + ntStatus = CreateFilterNames(SymbolicLinkName); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: Creating unqie filter names for the USB device failed, 0x%x", ntStatus)), + Done); + + // + // This remote device is now in running state. No need to use interlock operations + // b/c at this time this is the only thread accessing this info. + // + m_State = eUsbHsStateRunning; + + // + // Init successful. + // + ntStatus = STATUS_SUCCESS; + +Done: + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +UsbHsDevice::~UsbHsDevice +( + void +) +/*++ + +Routine Description: + + Destructor for UsbHsDevice. + +Arguments: + +Return Value: + + void + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + ASSERT(m_State != eUsbHsStateRunning); + ASSERT(IsListEmpty(&m_ListEntry)); + + // + // Release ref to remote stack. + // + if (m_WdfIoTarget != NULL) + { + PDEVICE_OBJECT pdo = WdfIoTargetWdmGetTargetPhysicalDevice(m_WdfIoTarget); + m_Adapter->RemoveDeviceAsPowerDependency(pdo); + + WdfObjectDelete(m_WdfIoTarget); + m_WdfIoTarget = NULL; + } + + // + // Free symbolic links. + // + if (m_SymbolicLinkName.Buffer != NULL) + { + ExFreePoolWithTag(m_SymbolicLinkName.Buffer, MINADAPTER_POOLTAG); + RtlZeroMemory(&m_SymbolicLinkName, sizeof(m_SymbolicLinkName)); + } + + DeleteCustomEndpointMinipair(m_SpeakerMiniports); + m_SpeakerMiniports = NULL; + + DeleteCustomEndpointMinipair(m_MicMiniports); + m_MicMiniports = NULL; + + if (m_Descriptor != NULL) + { + ExFreePoolWithTag(m_Descriptor, MINADAPTER_POOLTAG); + m_Descriptor = NULL; + } + + SAFE_DELETE_PTR_WITH_TAG(m_pSpeakerDescriptor, USBSIDEBANDTEST_POOLTAG02); + SAFE_DELETE_PTR_WITH_TAG(m_pMicDescriptor, USBSIDEBANDTEST_POOLTAG02); + + SAFE_DELETE_PTR_WITH_TAG(m_pSpeakerSupportedFormatsIntersection, USBSIDEBANDTEST_POOLTAG03); + SAFE_DELETE_PTR_WITH_TAG(m_pMicSupportedFormatsIntersection, USBSIDEBANDTEST_POOLTAG03); + + FreeTransportResources(&m_SpeakerTransportResources); + FreeTransportResources(&m_MicTransportResources); + + if (m_SpeakerVolumePropValues != NULL) + { + ExFreePoolWithTag(m_SpeakerVolumePropValues, USBSIDEBANDTEST_POOLTAG02); + m_SpeakerVolumePropValues = NULL; + } + + if (m_MicVolumePropValues != NULL) + { + ExFreePoolWithTag(m_MicVolumePropValues, USBSIDEBANDTEST_POOLTAG02); + m_MicVolumePropValues = NULL; + } + + if (m_SpeakerMutePropValues != NULL) + { + ExFreePoolWithTag(m_SpeakerMutePropValues, USBSIDEBANDTEST_POOLTAG06); + m_SpeakerMutePropValues = NULL; + m_ulSpeakerMutePropValuesSize = 0; + } + + if (m_MicMutePropValues != NULL) + { + ExFreePoolWithTag(m_MicMutePropValues, USBSIDEBANDTEST_POOLTAG06); + m_MicMutePropValues = NULL; + m_ulMicMutePropValuesSize = 0; + } + + // + // Free Irps. + // + if (m_SpeakerVolumeReq != NULL) + { + UsbHsDeviceNotificationReqContext * ctx; + + // Delete the associated memory objects. + ctx = GetUsbHsDeviceNotificationReqContext(m_SpeakerVolumeReq); + if (ctx->MemIn != NULL) + { + WdfObjectDelete(ctx->MemIn); + ctx->MemIn = NULL; + } + + if (ctx->MemOut != NULL) + { + WdfObjectDelete(ctx->MemOut); + ctx->MemOut = NULL; + } + + // Delete the request. + WdfObjectDelete(m_SpeakerVolumeReq); + m_SpeakerVolumeReq = NULL; + } + + if (m_MicVolumeReq != NULL) + { + UsbHsDeviceNotificationReqContext * ctx; + + // Delete the associated memory objects. + ctx = GetUsbHsDeviceNotificationReqContext(m_MicVolumeReq); + if (ctx->MemIn != NULL) + { + WdfObjectDelete(ctx->MemIn); + ctx->MemIn = NULL; + } + + if (ctx->MemOut != NULL) + { + WdfObjectDelete(ctx->MemOut); + ctx->MemOut = NULL; + } + + // Delete the request. + WdfObjectDelete(m_MicVolumeReq); + m_MicVolumeReq = NULL; + } + + if (m_SpeakerMuteReq != NULL) + { + UsbHsDeviceNotificationReqContext * ctx; + + // Delete the associated memory objects. + ctx = GetUsbHsDeviceNotificationReqContext(m_SpeakerMuteReq); + if (ctx->MemIn != NULL) + { + WdfObjectDelete(ctx->MemIn); + ctx->MemIn = NULL; + } + + if (ctx->MemOut != NULL) + { + WdfObjectDelete(ctx->MemOut); + ctx->MemOut = NULL; + } + + // Delete the request. + WdfObjectDelete(m_SpeakerMuteReq); + m_SpeakerMuteReq = NULL; + } + + if (m_MicMuteReq != NULL) + { + UsbHsDeviceNotificationReqContext * ctx; + + // Delete the associated memory objects. + ctx = GetUsbHsDeviceNotificationReqContext(m_MicMuteReq); + if (ctx->MemIn != NULL) + { + WdfObjectDelete(ctx->MemIn); + ctx->MemIn = NULL; + } + + if (ctx->MemOut != NULL) + { + WdfObjectDelete(ctx->MemOut); + ctx->MemOut = NULL; + } + + // Delete the request. + WdfObjectDelete(m_MicMuteReq); + m_MicMuteReq = NULL; + } + + if (m_SpeakerStreamReq != NULL) + { + UsbHsDeviceNotificationReqContext * ctx; + + // Delete the associated memory objects. + ctx = GetUsbHsDeviceNotificationReqContext(m_SpeakerStreamReq); + if (ctx->MemIn != NULL) + { + WdfObjectDelete(ctx->MemIn); + ctx->MemIn = NULL; + } + + if (ctx->MemOut != NULL) + { + WdfObjectDelete(ctx->MemOut); + ctx->MemOut = NULL; + } + + // Delete the request. + WdfObjectDelete(m_SpeakerStreamReq); + m_SpeakerStreamReq = NULL; + } + + if (m_MicStreamReq != NULL) + { + UsbHsDeviceNotificationReqContext * ctx; + + // Delete the associated memory objects. + ctx = GetUsbHsDeviceNotificationReqContext(m_MicStreamReq); + if (ctx->MemIn != NULL) + { + WdfObjectDelete(ctx->MemIn); + ctx->MemIn = NULL; + } + + if (ctx->MemOut != NULL) + { + WdfObjectDelete(ctx->MemOut); + ctx->MemOut = NULL; + } + + // Delete the request. + WdfObjectDelete(m_MicStreamReq); + m_MicStreamReq = NULL; + } + + // + // Notification work-item. + // + if (m_WorkItem != NULL) + { + WdfObjectDelete(m_WorkItem); + m_WorkItem = NULL; + } + + // + // Notification req. collection. + // + if (m_ReqCollection != NULL) + { + WdfObjectDelete(m_ReqCollection); + m_ReqCollection = NULL; + } + + ASSERT(m_UnknownSpeakerTopology == NULL); + SAFE_RELEASE(m_UnknownSpeakerTopology); + + ASSERT(m_UnknownSpeakerWave == NULL); + SAFE_RELEASE(m_UnknownSpeakerWave); + + ASSERT(m_UnknownMicTopology == NULL); + SAFE_RELEASE(m_UnknownMicTopology); + + ASSERT(m_UnknownMicWave == NULL); + SAFE_RELEASE(m_UnknownMicWave); + + ASSERT(m_nSpeakerStreamsOpen == 0); + ASSERT(m_nMicStreamsOpen == 0); + + ASSERT(m_nSpeakerStreamsStart == 0); + ASSERT(m_nMicStreamsStart == 0); + + ASSERT(m_SpeakerVolumeCallback.Handler == NULL); + ASSERT(m_MicVolumeCallback.Handler == NULL); + + ASSERT(m_SpeakerMuteCallback.Handler == NULL); + ASSERT(m_MicMuteCallback.Handler == NULL); + + ASSERT(m_SpeakerConnectionStatusCallback.Handler == NULL); + ASSERT(m_MicConnectionStatusCallback.Handler == NULL); + + ASSERT(m_SpeakerFormatChangeCallback.Handler == NULL); + ASSERT(m_MicFormatChangeCallback.Handler == NULL); +} // ~CAdapterCommon + +// +// ISidebandDeviceCommon implementation. +// + +//============================================================================= +#pragma code_seg("PAGE") +BOOL +UsbHsDevice::IsVolumeSupported +( + _In_ eDeviceType deviceType +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + return m_pSpeakerDescriptor->Capabilities.Volume; + } + else if (deviceType == eUsbHsMicDevice) + { + return m_pMicDescriptor->Capabilities.Volume; + } + + return FALSE; +} + +//============================================================================= +#pragma code_seg("PAGE") +PVOID +UsbHsDevice::GetVolumeSettings +( + _In_ eDeviceType deviceType, + _Out_ PULONG Size +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + ASSERT(Size != NULL); + + if (deviceType == eUsbHsSpeakerDevice) + { + *Size = m_pSpeakerDescriptor->VolumePropertyValuesSize; + return m_SpeakerVolumePropValues; + } + else if (deviceType == eUsbHsMicDevice) + { + *Size = m_pMicDescriptor->VolumePropertyValuesSize; + return m_MicVolumePropValues; + } + + return NULL; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetVolume +( + _In_ eDeviceType deviceType, + _In_ LONG Channel, + _Out_ LONG *pVolume +) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(Channel); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS status = STATUS_SUCCESS; + + ASSERT(pVolume); + + if (eUsbHsSpeakerDevice == deviceType) + { + status = GetUsbHsSpeakerVolume(Channel, pVolume); + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("Start: GetUsbHsSpeakerVolume: failed, 0x%x", status)), + Done); + + InterlockedExchange(&m_SpeakerVolumeLevel, *pVolume); + } + else if (eUsbHsMicDevice == deviceType) + { + status = GetUsbHsMicVolume(Channel, pVolume); + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("Start: GetUsbHsMicVolume: failed, 0x%x", status)), + Done); + + InterlockedExchange(&m_MicVolumeLevel, *pVolume); + } + else + { + status = STATUS_INVALID_PARAMETER; + } + +Done: + return status; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetVolume +( + _In_ eDeviceType deviceType, + _In_ LONG Channel, + _In_ LONG Volume +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS status = STATUS_SUCCESS; + + if (eUsbHsSpeakerDevice == deviceType) + { + status = SetUsbHsSpeakerVolume(Channel, Volume); + } + else if(eUsbHsMicDevice == deviceType) + { + status = SetUsbHsMicVolume(Channel, Volume); + } + else + { + status = STATUS_INVALID_PARAMETER; + } + + return status; +} + +//============================================================================= +#pragma code_seg("PAGE") +BOOL +UsbHsDevice::IsMuteSupported +( + _In_ eDeviceType deviceType +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + return m_pSpeakerDescriptor->Capabilities.Mute; + } + else if (deviceType == eUsbHsMicDevice) + { + return m_pMicDescriptor->Capabilities.Mute; + } + + return FALSE; +} + +//============================================================================= +#pragma code_seg("PAGE") +PVOID +UsbHsDevice::GetMuteSettings +( + _In_ eDeviceType deviceType, + _Out_ PULONG Size +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + ASSERT(Size != NULL); + + if (deviceType == eUsbHsSpeakerDevice) + { + *Size = m_ulSpeakerMutePropValuesSize; + return m_SpeakerMutePropValues; + } + else if (deviceType == eUsbHsMicDevice) + { + *Size = m_ulMicMutePropValuesSize; + return m_MicMutePropValues; + } + + return NULL; +} + +//============================================================================= +#pragma code_seg("PAGE") +LONG +UsbHsDevice::GetMute +( + _In_ eDeviceType deviceType, + _In_ LONG Channel +) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(Channel); + DPF_ENTER(("[%!FUNC!]")); + + LONG ulMute = 0; + NTSTATUS status = STATUS_SUCCESS; + + if (eUsbHsSpeakerDevice == deviceType) + { + status = GetUsbHsSpeakerMute(Channel, &ulMute); + } + else if (eUsbHsMicDevice == deviceType) + { + status = GetUsbHsMicVolume(Channel, &ulMute); + } + else + { + status = STATUS_INVALID_PARAMETER; + } + + if (NT_SUCCESS(status)) + { + return ulMute; + } + + return 0; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetMute +( + _In_ eDeviceType deviceType, + _In_ LONG Channel, + _In_ LONG Mute +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS status = STATUS_SUCCESS; + + if (eUsbHsSpeakerDevice == deviceType) + { + status = SetUsbHsSpeakerMute(Channel, Mute); + } + else if(eUsbHsMicDevice == deviceType) + { + status = SetUsbHsMicMute(Channel, Mute); + } + else + { + status = STATUS_INVALID_PARAMETER; + } + + return status; +} + +//============================================================================= +#pragma code_seg("PAGE") +BOOL +UsbHsDevice::GetConnectionStatus() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + return TRUE; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::Connect() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + return STATUS_DEVICE_FEATURE_NOT_SUPPORTED; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::Disconnect() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + return STATUS_DEVICE_FEATURE_NOT_SUPPORTED; +} + +//============================================================================= +#pragma code_seg() +BOOL +UsbHsDevice::GetStreamStatus(_In_ eDeviceType deviceType) +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (deviceType == eUsbHsSpeakerDevice) + { + ntStatus = (NTSTATUS)InterlockedCompareExchange(&m_SpeakerStreamStatusLong, 0, 0); + } + else if (deviceType == eUsbHsMicDevice) + { + ntStatus = (NTSTATUS)InterlockedCompareExchange(&m_MicStreamStatusLong, 0, 0); + } + + return NT_SUCCESS(ntStatus) ? TRUE : FALSE; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SpeakerStreamOpen() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + NTSTATUS ntStatus = STATUS_SUCCESS; + LONG nStreams = 0; + + ASSERT(m_nSpeakerStreamsOpen >= 0); + + nStreams = InterlockedIncrement(&m_nSpeakerStreamsOpen); + if (nStreams == 1) + { + BOOLEAN streamOpen = FALSE; + + ntStatus = SetUsbHsStreamOpen(m_SpeakerEpIndex, + &UsbHsSpeakerSupportedDeviceFormats[m_SpeakerSelectedFormat], + m_pSpeakerDescriptor); + + if (NT_SUCCESS(ntStatus)) + { + streamOpen = TRUE; + m_SpeakerStreamStatus = STATUS_SUCCESS; + ntStatus = EnableUsbHsSpeakerStreamStatusNotification(); + } + + // + // Cleanup if any error. + // + if (!NT_SUCCESS(ntStatus)) + { + nStreams = InterlockedDecrement(&m_nSpeakerStreamsOpen); + ASSERT(nStreams == 0); + UNREFERENCED_VAR(nStreams); + + if (streamOpen) + { + SetUsbHsStreamClose(m_SpeakerEpIndex); + } + + m_SpeakerStreamStatus = STATUS_INVALID_DEVICE_STATE; + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::MicStreamOpen() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + NTSTATUS ntStatus = STATUS_SUCCESS; + LONG nStreams = 0; + + ASSERT(m_nMicStreamsOpen >= 0); + + nStreams = InterlockedIncrement(&m_nMicStreamsOpen); + if (nStreams == 1) + { + BOOLEAN streamOpen = FALSE; + + ntStatus = SetUsbHsStreamOpen(m_MicEpIndex, + &UsbHsMicSupportedDeviceFormats[m_MicSelectedFormat], + m_pMicDescriptor); + + if (NT_SUCCESS(ntStatus)) + { + streamOpen = TRUE; + m_MicStreamStatus = STATUS_SUCCESS; + ntStatus = EnableUsbHsMicStreamStatusNotification(); + } + + // + // Cleanup if any error. + // + if (!NT_SUCCESS(ntStatus)) + { + nStreams = InterlockedDecrement(&m_nMicStreamsOpen); + ASSERT(nStreams == 0); + UNREFERENCED_VAR(nStreams); + + if (streamOpen) + { + SetUsbHsStreamClose(m_MicEpIndex); + } + + m_MicStreamStatus = STATUS_INVALID_DEVICE_STATE; + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::StreamOpen(_In_ eDeviceType deviceType) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + return SpeakerStreamOpen(); + } + else if (deviceType == eUsbHsMicDevice) + { + return MicStreamOpen(); + } + + return STATUS_INVALID_PARAMETER; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SpeakerStreamStart() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + NTSTATUS ntStatus = STATUS_SUCCESS; + LONG nStreams = 0; + + ASSERT(m_nSpeakerStreamsStart >= 0); + + nStreams = InterlockedIncrement(&m_nSpeakerStreamsStart); + if (nStreams == 1) + { + BOOLEAN streamStart = FALSE; + + ntStatus = SetTransportResources(m_pSpeakerDescriptor, m_SpeakerEpIndex); + + if (NT_SUCCESS(ntStatus)) + { + ntStatus = SetUsbHsStreamStart(m_SpeakerEpIndex); + } + + if (NT_SUCCESS(ntStatus)) + { + streamStart = TRUE; + } + + if (NT_SUCCESS(ntStatus)) + { + ntStatus = GetTransportResources(m_SpeakerEpIndex, m_pSpeakerDescriptor, &m_SpeakerTransportResources); + } + + // + // Cleanup if any error. + // + if (!NT_SUCCESS(ntStatus)) + { + nStreams = InterlockedDecrement(&m_nSpeakerStreamsStart); + ASSERT(nStreams == 0); + UNREFERENCED_VAR(nStreams); + + if (streamStart) + { + SetUsbHsStreamSuspend(m_SpeakerEpIndex); + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::MicStreamStart() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + NTSTATUS ntStatus = STATUS_SUCCESS; + LONG nStreams = 0; + + ASSERT(m_nMicStreamsStart >= 0); + + nStreams = InterlockedIncrement(&m_nMicStreamsStart); + if (nStreams == 1) + { + BOOLEAN streamStart = FALSE; + + ntStatus = SetTransportResources(m_pMicDescriptor, m_MicEpIndex); + + if (NT_SUCCESS(ntStatus)) + { + ntStatus = SetUsbHsStreamStart(m_MicEpIndex); + } + + if (NT_SUCCESS(ntStatus)) + { + streamStart = TRUE; + } + + if (NT_SUCCESS(ntStatus)) + { + ntStatus = GetTransportResources(m_MicEpIndex, m_pMicDescriptor, &m_MicTransportResources); + } + + // + // Cleanup if any error. + // + if (!NT_SUCCESS(ntStatus)) + { + nStreams = InterlockedDecrement(&m_nMicStreamsStart); + ASSERT(nStreams == 0); + UNREFERENCED_VAR(nStreams); + + if (streamStart) + { + SetUsbHsStreamSuspend(m_MicEpIndex); + } + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::StreamStart(_In_ eDeviceType deviceType) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + return SpeakerStreamStart(); + } + else if (deviceType == eUsbHsMicDevice) + { + return MicStreamStart(); + } + + return STATUS_INVALID_PARAMETER; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SpeakerStreamSuspend() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + LONG nStreams = 0; + + ASSERT(m_nSpeakerStreamsStart > 0); + + nStreams = InterlockedDecrement(&m_nSpeakerStreamsStart); + if (nStreams == 0) + { + ntStatus = SetUsbHsStreamSuspend(m_SpeakerEpIndex); + + FreeTransportResources(&m_SpeakerTransportResources); + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::MicStreamSuspend() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + LONG nStreams = 0; + + ASSERT(m_nMicStreamsStart > 0); + + nStreams = InterlockedDecrement(&m_nMicStreamsStart); + if (nStreams == 0) + { + ntStatus = SetUsbHsStreamSuspend(m_MicEpIndex); + + FreeTransportResources(&m_MicTransportResources); + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::StreamSuspend(_In_ eDeviceType deviceType) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + return SpeakerStreamSuspend(); + } + else if (deviceType == eUsbHsMicDevice) + { + return MicStreamSuspend(); + } + + return STATUS_INVALID_PARAMETER; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SpeakerStreamClose() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + LONG nStreams = 0; + + ASSERT(m_nSpeakerStreamsOpen > 0); + + nStreams = InterlockedDecrement(&m_nSpeakerStreamsOpen); + if (nStreams == 0) + { + ntStatus = SetUsbHsStreamClose(m_SpeakerEpIndex); + + StopUsbHsSpeakerStreamStatusNotification(); + + m_SpeakerStreamStatus = STATUS_INVALID_DEVICE_STATE; + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::MicStreamClose() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + LONG nStreams = 0; + + ASSERT(m_nMicStreamsOpen > 0); + + nStreams = InterlockedDecrement(&m_nMicStreamsOpen); + if (nStreams == 0) + { + ntStatus = SetUsbHsStreamClose(m_MicEpIndex); + + StopUsbHsMicStreamStatusNotification(); + + m_MicStreamStatus = STATUS_INVALID_DEVICE_STATE; + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::StreamClose(_In_ eDeviceType deviceType) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + return SpeakerStreamClose(); + } + else if (deviceType == eUsbHsMicDevice) + { + return MicStreamClose(); + } + + return STATUS_INVALID_PARAMETER; +} + +//============================================================================= +#pragma code_seg("PAGE") +GUID +UsbHsDevice::GetContainerId(_In_ eDeviceType deviceType) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + return m_pSpeakerDescriptor->ContainerId; + } + else if (deviceType == eUsbHsMicDevice) + { + return m_pMicDescriptor->ContainerId; + } + else + return { 0 }; +} + +//============================================================================= +#pragma code_seg("PAGE") +VOID +UsbHsDevice::SetVolumeHandler +( + _In_ eDeviceType deviceType, + _In_opt_ PFNEVENTNOTIFICATION EventHandler, + _In_opt_ PVOID EventHandlerContext +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + ASSERT(EventHandler == NULL || m_SpeakerVolumeCallback.Handler == NULL); + + m_SpeakerVolumeCallback.Handler = EventHandler; // weak ref. + m_SpeakerVolumeCallback.Context = EventHandlerContext; + } + else if (deviceType == eUsbHsMicDevice) + { + ASSERT(EventHandler == NULL || m_MicVolumeCallback.Handler == NULL); + + m_MicVolumeCallback.Handler = EventHandler; // weak ref. + m_MicVolumeCallback.Context = EventHandlerContext; + } +} + +//============================================================================= +#pragma code_seg("PAGE") +VOID +UsbHsDevice::SetMuteHandler +( + _In_ eDeviceType deviceType, + _In_opt_ PFNEVENTNOTIFICATION EventHandler, + _In_opt_ PVOID EventHandlerContext +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + ASSERT(EventHandler == NULL || m_SpeakerMuteCallback.Handler == NULL); + + m_SpeakerMuteCallback.Handler = EventHandler; // weak ref. + m_SpeakerMuteCallback.Context = EventHandlerContext; + } + else if (deviceType == eUsbHsMicDevice) + { + ASSERT(EventHandler == NULL || m_MicMuteCallback.Handler == NULL); + + m_MicMuteCallback.Handler = EventHandler; // weak ref. + m_MicMuteCallback.Context = EventHandlerContext; + } +} + +//============================================================================= +#pragma code_seg("PAGE") +VOID +UsbHsDevice::SetConnectionStatusHandler +( + _In_ eDeviceType deviceType, + _In_opt_ PFNEVENTNOTIFICATION EventHandler, + _In_opt_ PVOID EventHandlerContext +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + ASSERT(EventHandler == NULL || m_SpeakerConnectionStatusCallback.Handler == NULL); + + m_SpeakerConnectionStatusCallback.Handler = EventHandler; // weak ref. + m_SpeakerConnectionStatusCallback.Context = EventHandlerContext; + } + else if (deviceType == eUsbHsMicDevice) + { + ASSERT(EventHandler == NULL || m_MicConnectionStatusCallback.Handler == NULL); + + m_MicConnectionStatusCallback.Handler = EventHandler; // weak ref. + m_MicConnectionStatusCallback.Context = EventHandlerContext; + } + +} + +//============================================================================= +#pragma code_seg("PAGE") +VOID +UsbHsDevice::SetFormatChangeHandler +( + _In_ eDeviceType deviceType, + _In_opt_ PFNEVENTNOTIFICATION EventHandler, + _In_opt_ PVOID EventHandlerContext +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + if (deviceType == eUsbHsSpeakerDevice) + { + ASSERT(EventHandler == NULL || m_SpeakerFormatChangeCallback.Handler == NULL); + + m_SpeakerFormatChangeCallback.Handler = EventHandler; // weak ref. + m_SpeakerFormatChangeCallback.Context = EventHandlerContext; + } + else if (deviceType == eUsbHsMicDevice) + { + ASSERT(EventHandler == NULL || m_MicFormatChangeCallback.Handler == NULL); + + m_MicFormatChangeCallback.Handler = EventHandler; // weak ref. + m_MicFormatChangeCallback.Context = EventHandlerContext; + } + +} + +//============================================================================= +#pragma code_seg("PAGE") +PPIN_DEVICE_FORMATS_AND_MODES +UsbHsDevice::GetFormatsAndModes +( + _In_ eDeviceType deviceType +) +{ + UNREFERENCED_PARAMETER(deviceType); + PPIN_DEVICE_FORMATS_AND_MODES pFormatsAndModes = NULL; + return pFormatsAndModes; +} + +//============================================================================= +#pragma code_seg("PAGE") +BOOL +UsbHsDevice::IsNRECSupported() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + return FALSE; +} + +//============================================================================= +#pragma code_seg("PAGE") +BOOL +UsbHsDevice::GetNRECDisableStatus() +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + // Return TRUE if HF wants to disable the NREC on the AG. + return FALSE; +} + +// +// Helper functions. +// + +//============================================================================= +#pragma code_seg() +NTSTATUS +UsbHsDevice::SendIoCtrlAsynchronously +( + _In_ WDFREQUEST Request, + _In_ ULONG IoControlCode, + _In_opt_ WDFMEMORY MemIn, + _In_opt_ WDFMEMORY MemOut, + _In_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine, + _In_ WDFCONTEXT Context +) +/*++ + +Routine Description: + + This function aynchronously sends an I/O Ctrl request to the USB Headset + device. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + BOOLEAN fSent = FALSE; + + // + // Format and send the request. + // + ntStatus = WdfIoTargetFormatRequestForIoctl( + m_WdfIoTarget, + Request, + IoControlCode, + MemIn, + NULL, + MemOut, + NULL); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfIoTargetFormatRequestForIoctl(0x%x) failed, 0x%x", IoControlCode, ntStatus)), + Done); + + WdfRequestSetCompletionRoutine( + Request, + CompletionRoutine, + Context); + + fSent = WdfRequestSend(Request, m_WdfIoTarget, NULL); // no options. + if (fSent == FALSE) + { + ntStatus = WdfRequestGetStatus(Request); + if (NT_SUCCESS(ntStatus)) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + } + + DPF(D_ERROR, ("%!FUNC!: WdfRequestSend(0x%x) failed, 0x%x", IoControlCode, ntStatus)); + goto Done; + } + + // + // All Done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SendIoCtrlSynchronously +( + _In_opt_ WDFREQUEST Request, + _In_ ULONG IoControlCode, + _In_ ULONG InLength, + _In_ ULONG OutLength, + _When_(InLength > 0 || OutLength > 0, _In_) + _When_(InLength == 0 && OutLength == 0, _In_opt_) + PVOID Buffer +) +/*++ + +Routine Description: + + This function inits and synchronously sends an I/O Ctrl request to the USB headset + device. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + PWDF_MEMORY_DESCRIPTOR memInPtr = NULL; + PWDF_MEMORY_DESCRIPTOR memOutPtr = NULL; + WDF_MEMORY_DESCRIPTOR memIn; + WDF_MEMORY_DESCRIPTOR memOut; + WDF_REQUEST_SEND_OPTIONS reqOpts; + + // + // Format and send the request. + // + if (InLength) + { + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memIn, Buffer, InLength); + memInPtr = &memIn; + } + + if (OutLength) + { + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memOut, Buffer, OutLength); + memOutPtr = &memOut; + } + + WDF_REQUEST_SEND_OPTIONS_INIT( + &reqOpts, + WDF_REQUEST_SEND_OPTION_TIMEOUT | + WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); + + reqOpts.Timeout = WDF_REL_TIMEOUT_IN_SEC(USB_SIDEBAND_SYNC_REQ_TIMEOUT_IN_SEC); + + ntStatus = WdfIoTargetSendIoctlSynchronously( + m_WdfIoTarget, + Request, + IoControlCode, + memInPtr, + memOutPtr, + &reqOpts, + NULL); // bytes returned. + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_VERBOSE, ("%!FUNC!: WdfIoTargetSendIoctlSynchronously(0x%x) failed, 0x%x", IoControlCode, ntStatus)), + Done); + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SendIoCtrlSynchronously +( + _In_opt_ WDFREQUEST Request, + _In_ ULONG IoControlCode, + _In_ ULONG InLength, + _In_ ULONG OutLength, + _When_(InLength > 0, _In_) + _When_(InLength == 0, _In_opt_) + PVOID InBuffer, + _When_(OutLength > 0, _In_) + _When_(OutLength == 0, _In_opt_) + PVOID OutBuffer +) +/*++ + +Routine Description: + + This function inits and synchronously sends an I/O Ctrl request to the USB headset + device. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + PWDF_MEMORY_DESCRIPTOR memInPtr = NULL; + PWDF_MEMORY_DESCRIPTOR memOutPtr = NULL; + WDF_MEMORY_DESCRIPTOR memIn; + WDF_MEMORY_DESCRIPTOR memOut; + WDF_REQUEST_SEND_OPTIONS reqOpts; + + // + // Format and send the request. + // + if (InLength) + { + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memIn, InBuffer, InLength); + memInPtr = &memIn; + } + + if (OutLength) + { + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memOut, OutBuffer, OutLength); + memOutPtr = &memOut; + } + + WDF_REQUEST_SEND_OPTIONS_INIT( + &reqOpts, + WDF_REQUEST_SEND_OPTION_TIMEOUT | + WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); + + reqOpts.Timeout = WDF_REL_TIMEOUT_IN_SEC(USB_SIDEBAND_SYNC_REQ_TIMEOUT_IN_SEC); + + ntStatus = WdfIoTargetSendIoctlSynchronously( + m_WdfIoTarget, + Request, + IoControlCode, + memInPtr, + memOutPtr, + &reqOpts, + NULL); // bytes returned. + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_VERBOSE, ("%!FUNC!: WdfIoTargetSendIoctlSynchronously(0x%x) failed, 0x%x", IoControlCode, ntStatus)), + Done); + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +VOID +UsbHsDevice::EvtUsbHsDeviceNotificationStatusWorkItem +( + _In_ WDFWORKITEM WorkItem +) +/*++ + +Routine Description: + + The function processes status notification updates. + +Arguments: + + WorkItem - WDF work-item object. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDevice * This; + KIRQL oldIrql; + + if (WorkItem == NULL) + { + return; + } + + This = GetUsbHsDeviceNotificationWorkItemContext(WorkItem)->UsbHsDevice; + ASSERT(This != NULL); + + for (;;) + { + BOOL resend = TRUE; + WDFREQUEST req = NULL; + UsbHsDeviceNotificationReqContext * reqCtx; + WDF_REQUEST_COMPLETION_PARAMS params; + + // + // Retrieve a task. + // + KeAcquireSpinLock(&This->m_Lock, &oldIrql); + req = (WDFREQUEST) WdfCollectionGetFirstItem(This->m_ReqCollection); + if (req != NULL) + { + WdfCollectionRemove(This->m_ReqCollection, req); + } + KeReleaseSpinLock(&This->m_Lock, oldIrql); + + if (req == NULL) + { + break; + } + + // + // Get request parameters and context. + // + WDF_REQUEST_COMPLETION_PARAMS_INIT(¶ms); + WdfRequestGetCompletionParams(req, ¶ms); + + reqCtx = GetUsbHsDeviceNotificationReqContext(req); + ASSERT(reqCtx != NULL); + + // + // Handle this notification. + // + if (NT_SUCCESS(params.IoStatus.Status)) + { + switch(params.Parameters.Ioctl.IoControlCode) + { + case IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE: + { + LONG oldVolume; + + // Prepare for request resent + reqCtx->Buffer.Volume.Immediate = FALSE; + + if (reqCtx->Buffer.Volume.EpIndex == This->m_SpeakerEpIndex) + { + oldVolume = InterlockedExchange(&This->m_SpeakerVolumeLevel, reqCtx->Buffer.Volume.Value); + if (reqCtx->Buffer.Volume.Value != oldVolume) + { + // Notify audio miniport about this change. + if (This->m_SpeakerVolumeCallback.Handler != NULL) + { + This->m_SpeakerVolumeCallback.Handler( + This->m_SpeakerVolumeCallback.Context); + } + } + } + else if (reqCtx->Buffer.Volume.EpIndex == This->m_MicEpIndex) + { + oldVolume = InterlockedExchange(&This->m_MicVolumeLevel, reqCtx->Buffer.Volume.Value); + if (reqCtx->Buffer.Volume.Value != oldVolume) + { + // Notify audio miniport about this change. + if (This->m_MicVolumeCallback.Handler != NULL) + { + This->m_MicVolumeCallback.Handler( + This->m_MicVolumeCallback.Context); + } + } + } + + } + break; + + case IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE: + { + LONG oldMute; + + // Prepare for request resent + reqCtx->Buffer.Mute.Immediate = FALSE; + + if (reqCtx->Buffer.Mute.EpIndex == This->m_SpeakerEpIndex) + { + oldMute = InterlockedExchange(&This->m_SpeakerMute, reqCtx->Buffer.Mute.Value); + if (reqCtx->Buffer.Mute.Value != oldMute) + { + // Notify audio miniport about this change. + if (This->m_SpeakerMuteCallback.Handler != NULL) + { + This->m_SpeakerMuteCallback.Handler( + This->m_SpeakerMuteCallback.Context); + } + } + } + else if (reqCtx->Buffer.Mute.EpIndex == This->m_MicEpIndex) + { + oldMute = InterlockedExchange(&This->m_MicMute, reqCtx->Buffer.Mute.Value); + if (reqCtx->Buffer.Mute.Value != oldMute) + { + // Notify audio miniport about this change. + if (This->m_MicMuteCallback.Handler != NULL) + { + This->m_MicMuteCallback.Handler( + This->m_MicMuteCallback.Context); + } + } + } + + } + break; + + default: + // This should never happen. + resend = FALSE; + DPF(D_ERROR, ("%!FUNC!: invalid request ctrl 0x%x", + params.Parameters.Ioctl.IoControlCode)); + break; + } + } + + if (resend) + { + WDF_REQUEST_REUSE_PARAMS reuseParams; + + WDF_REQUEST_REUSE_PARAMS_INIT( + &reuseParams, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + ntStatus = WdfRequestReuse(req, &reuseParams); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_ERROR, ("%!FUNC!: WdfRequestReuse failed, 0x%x", ntStatus)); + break; + } + + // Resend status notification request. + ntStatus = This->SendIoCtrlAsynchronously( + req, + params.Parameters.Ioctl.IoControlCode, + reqCtx->MemIn, + reqCtx->MemOut, + EvtUsbHsDeviceNotificationStatusCompletion, + This); + + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlAsynchronously" + "(0x%x) failed, 0x%x", + params.Parameters.Ioctl.IoControlCode, ntStatus)); + break; + } + } + } +} + +//============================================================================= +#pragma code_seg() +void +UsbHsDevice::EvtUsbHsDeviceNotificationStatusCompletion +( + _In_ WDFREQUEST Request, + _In_ WDFIOTARGET Target, + _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, + _In_ WDFCONTEXT Context +) +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *ctx = NULL; + UsbHsDevice *This = NULL; + KIRQL oldIrql; + + UNREFERENCED_PARAMETER(Target); + UNREFERENCED_PARAMETER(Context); + + ctx = GetUsbHsDeviceNotificationReqContext(Request); + This = ctx->UsbHsDevice; + ASSERT(This != NULL); + + ntStatus = Params->IoStatus.Status; + if (ntStatus == STATUS_CANCELLED) + { + // USB device is shutting down. Do not re-send this request. + goto Done; + } + + // + // If something is wrong with the USB interface, do not loop forever. + // + if (!NT_SUCCESS(ntStatus)) + { + if (++ctx->Errors > USB_SIDEBAND_NOTIFICATION_MAX_ERROR_COUNT) + { + // Too many errors. Do not re-send this request. + goto Done; + } + } + else + { + // reset the # of errors. + ctx->Errors = 0; + } + + // + // Let the work-item thread process this request. + // + KeAcquireSpinLock(&This->m_Lock, &oldIrql); + + ntStatus = WdfCollectionAdd(This->m_ReqCollection, Request); + if (NT_SUCCESS(ntStatus)) + { + WdfWorkItemEnqueue(This->m_WorkItem); + } + + KeReleaseSpinLock(&This->m_Lock, oldIrql); + +Done:; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsDescriptor +( + _Out_ PSIDEBANDAUDIO_DEVICE_DESCRIPTOR *Descriptor +) +/*++ + +Routine Description: + + This function synchronously gets the remote USB Headset Device descriptor. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + WDFREQUEST req = NULL; + PSIDEBANDAUDIO_DEVICE_DESCRIPTOR descriptor = NULL; + ULONG length = 0; + ULONG_PTR information = 0; + WDF_REQUEST_REUSE_PARAMS reuseParams; + WDF_OBJECT_ATTRIBUTES attributes; + + *Descriptor = NULL; + + // + // Allocate and format a WDF request. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &req); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate failed, 0x%x", ntStatus)), + Done); + + // + // Get the size of the buffer. + // + ntStatus = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_DEVICE_DESCRIPTOR, + NULL, + NULL, + NULL); + + if (ntStatus != STATUS_BUFFER_TOO_SMALL) + { + if (NT_SUCCESS(ntStatus)) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + } + + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_DEVICE_DESCRIPTOR): failed, 0x%x", ntStatus)); + goto Done; + } + + ntStatus = STATUS_SUCCESS; + + information = WdfRequestGetInformation(req); + if (information == 0 || information > ULONG_MAX) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + DPF(D_ERROR, ("%!FUNC!: IOCTL_SBAUD_GET_DEVICE_DESCRIPTOR buffer too big (%Id): 0x%x", information, ntStatus)); + goto Done; + } + + length = (ULONG)information; + + // + // Allocate memory needed to hold the info. + // + descriptor = (PSIDEBANDAUDIO_DEVICE_DESCRIPTOR) ExAllocatePoolWithTag(NonPagedPoolNx, length, MINADAPTER_POOLTAG); + if (descriptor == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: ExAllocatePoolWithTag failed, out of memory")), + Done); + + // + // Get the USB Headset descriptor. + // + WDF_REQUEST_REUSE_PARAMS_INIT( + &reuseParams, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + ntStatus = WdfRequestReuse(req, &reuseParams); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestReuse failed, 0x%x", ntStatus)), + Done); + + ntStatus = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_DEVICE_DESCRIPTOR, + NULL, + length, + descriptor); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_DEVICE_DESCRIPTOR) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *Descriptor = descriptor; + ntStatus = STATUS_SUCCESS; + +Done: + if (!NT_SUCCESS(ntStatus)) + { + if (descriptor != NULL) + { + ExFreePoolWithTag(descriptor, MINADAPTER_POOLTAG); + } + } + + if (req != NULL) + { + WdfObjectDelete(req); + req = NULL; + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsEndpointDescriptor +( + _In_ ULONG EpIndex, + _Out_ PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR *EpDescriptor +) +/*++ + +Routine Description: + + This function synchronously gets the USB Headset Endpoint Descriptor. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + WDFREQUEST req = NULL; + PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR descriptor = NULL; + ULONG length = 0; + ULONG_PTR information = 0; + WDF_REQUEST_REUSE_PARAMS reuseParams; + WDF_OBJECT_ATTRIBUTES attributes; + + *EpDescriptor = NULL; + + // + // Allocate and format a WDF request. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &req); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate failed, 0x%x", ntStatus)), + Done); + + // + // Get the size of the buffer. + // + ntStatus = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_ENDPOINT_DESCRIPTOR, + sizeof(EpIndex), + NULL, + &EpIndex); + + if (ntStatus != STATUS_BUFFER_TOO_SMALL) + { + if (NT_SUCCESS(ntStatus)) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + } + + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_ENDPOINT_DESCRIPTOR): failed, 0x%x", ntStatus)); + goto Done; + } + + ntStatus = STATUS_SUCCESS; + + information = WdfRequestGetInformation(req); + if (information == 0 || information > ULONG_MAX) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + DPF(D_ERROR, ("%!FUNC!: IOCTL_SBAUD_GET_ENDPOINT_DESCRIPTOR buffer too big (%Id): 0x%x", information, ntStatus)); + goto Done; + } + + length = (ULONG)information; + + // + // Allocate memory needed to hold the info. + // + descriptor = (PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR) ExAllocatePoolWithTag(NonPagedPoolNx, length, MINADAPTER_POOLTAG); + if (descriptor == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: ExAllocatePoolWithTag failed, out of memory")), + Done); + + // + // Get the USB Headset descriptor. + // + WDF_REQUEST_REUSE_PARAMS_INIT( + &reuseParams, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + ntStatus = WdfRequestReuse(req, &reuseParams); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestReuse failed, 0x%x", ntStatus)), + Done); + + // Same buffer used for input and output + // Cast into ULONG to provide EpIndex + *((ULONG *)descriptor) = EpIndex; + + ntStatus = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_ENDPOINT_DESCRIPTOR, + sizeof(EpIndex), + length, + descriptor); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_ENDPOINT_DESCRIPTOR) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *EpDescriptor = descriptor; + ntStatus = STATUS_SUCCESS; + +Done: + if (!NT_SUCCESS(ntStatus)) + { + if (descriptor != NULL) + { + ExFreePoolWithTag(descriptor, MINADAPTER_POOLTAG); + } + } + + if (req != NULL) + { + WdfObjectDelete(req); + req = NULL; + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::VerifyEndpointFormatCompatibility +( + _In_ PSIDEBANDAUDIO_SUPPORTED_FORMATS EpSupportedFormats, + _In_ PKSDATAFORMAT_WAVEFORMATEXTENSIBLE pHardwareSupportedFormats, + _In_ ULONG NumHardwareSupportedFormats, + _Out_ PULONG pHardwareFormatIndex +) +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ULONG iHardwareFormats = 0; + ULONG iEpDataFormats = 0; + BOOL bFound = FALSE; + + // Verify here whether hardware/dsp mixer can support the USB device formats + // This format will be later used to open the ISOCH channel + + for (iHardwareFormats = 0; iHardwareFormats < NumHardwareSupportedFormats; iHardwareFormats++) + { + // for each format supported by hardware, search in EP data formats + for (iEpDataFormats = 0; iEpDataFormats < EpSupportedFormats->NumFormats; iEpDataFormats++) + { + PKSDATAFORMAT pEpDataFormat = (PKSDATAFORMAT)EpSupportedFormats->Formats[iEpDataFormats]; + + // Verify KSDATAFORMAT + if (pEpDataFormat->FormatSize >= sizeof(KSDATAFORMAT)) + { + if (pEpDataFormat->FormatSize >= sizeof(KSDATAFORMAT_WAVEFORMATEX)) + { + // Check other parameters as well + // Ignoring for simplicity + if ((((PKSDATAFORMAT_WAVEFORMATEX)pEpDataFormat)->WaveFormatEx.nSamplesPerSec == pHardwareSupportedFormats[iHardwareFormats].WaveFormatExt.Format.nSamplesPerSec) && + (((PKSDATAFORMAT_WAVEFORMATEX)pEpDataFormat)->WaveFormatEx.nChannels == pHardwareSupportedFormats[iHardwareFormats].WaveFormatExt.Format.nChannels) && + (((PKSDATAFORMAT_WAVEFORMATEX)pEpDataFormat)->WaveFormatEx.wBitsPerSample == pHardwareSupportedFormats[iHardwareFormats].WaveFormatExt.Format.wBitsPerSample)) + { + bFound = TRUE; + *pHardwareFormatIndex = iHardwareFormats; + status = STATUS_SUCCESS; + break; + } + } + } + } + } + + // Iterate through Sideband Device data range to figure out + // intersection with hardware supported formats + + return status; +} + + +NTSTATUS UsbHsDevice::FreeTransportResources +( + _In_ PUSBHSDEVICE_EP_TRANSPORT_RESOURCES pTransportResources +) +{ + SAFE_DELETE_PTR_WITH_TAG(pTransportResources->pUsbInterfaceDescriptor, USBSIDEBANDTEST_POOLTAG07); + SAFE_DELETE_PTR_WITH_TAG(pTransportResources->pUsbEndpointDescriptor, USBSIDEBANDTEST_POOLTAG08); + SAFE_DELETE_PTR_WITH_TAG(pTransportResources->pUsbOffloadInformation, USBSIDEBANDTEST_POOLTAG09); + SAFE_DELETE_PTR_WITH_TAG(pTransportResources->pUsbAudioTransportResources, USBSIDEBANDTEST_POOLTAG010); + SAFE_DELETE_PTR_WITH_TAG(pTransportResources->pSyncUsbEndpointDescriptor, USBSIDEBANDTEST_POOLTAG011); + SAFE_DELETE_PTR_WITH_TAG(pTransportResources->pSyncUsbOffloadInformation, USBSIDEBANDTEST_POOLTAG012); + SAFE_DELETE_PTR_WITH_TAG(pTransportResources->pSyncUsbAudioTransportResources, USBSIDEBANDTEST_POOLTAG013); + RtlZeroMemory(pTransportResources, sizeof(USBHSDEVICE_EP_TRANSPORT_RESOURCES)); + return STATUS_SUCCESS; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS UsbHsDevice::GetSiop +( + _In_ ULONG EpIndex, + _In_ ULONG SiopTypeId, + _In_ ULONG PoolTag, + _Out_ PBYTE *ppOutputBuffer +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS status = STATUS_SUCCESS; + WDFREQUEST req = NULL; + PBYTE pOutput = NULL; + ULONG length = 0; + ULONG_PTR information = 0; + WDF_REQUEST_REUSE_PARAMS reuseParams; + WDF_OBJECT_ATTRIBUTES attributes; + SIDEBANDAUDIO_SIOP_REQUEST_PARAM siop = { 0 }; + + *ppOutputBuffer = NULL; + + // + // Allocate and format a WDF request. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + status = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &req); + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate failed, 0x%x", status)), + Done); + + siop.EpIndex = EpIndex; + siop.RequestedSiop.ParamSet = SIDEBANDAUDIO_PARAMS_SET_USBAUDIO; + siop.RequestedSiop.TypeId = SiopTypeId; + siop.RequestedSiop.Size = 0; + + // + // Get the size of the buffer. + // + status = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_SIOP, + sizeof(siop), + 0, + &siop, + NULL); + + if (status != STATUS_BUFFER_TOO_SMALL) + { + if (NT_SUCCESS(status)) + { + status = STATUS_INVALID_DEVICE_STATE; + } + + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_SIOP): failed, 0x%x", status)); + goto Done; + } + + status = STATUS_SUCCESS; + + information = WdfRequestGetInformation(req); + if (information == 0 || information > ULONG_MAX) + { + status = STATUS_INVALID_DEVICE_STATE; + DPF(D_ERROR, ("%!FUNC!: IOCTL_SBAUD_GET_SIOP buffer too big (%Id): 0x%x", information, status)); + goto Done; + } + + length = (ULONG)information; + + // + // Allocate memory needed to hold the info. + // + pOutput = (PBYTE)ExAllocatePoolWithTag(NonPagedPoolNx, length, PoolTag); + if (pOutput == NULL) + { + status = STATUS_INSUFFICIENT_RESOURCES; + } + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("%!FUNC!: ExAllocatePoolWithTag failed, out of memory")), + Done); + + // + // Get the Siop + // + WDF_REQUEST_REUSE_PARAMS_INIT( + &reuseParams, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + status = WdfRequestReuse(req, &reuseParams); + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("%!FUNC!: WdfRequestReuse failed, 0x%x", status)), + Done); + + // Same buffer used for input and output + // Cast into ULONG to provide EpIndex + + status = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_SIOP, + sizeof(siop), + length, + &siop, + pOutput); + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_SIOP) failed, 0x%x", status)), + Done); + + // + // All done. + // + *ppOutputBuffer = pOutput; + status = STATUS_SUCCESS; + +Done: + if (!NT_SUCCESS(status)) + { + if (pOutput != NULL) + { + ExFreePoolWithTag(pOutput, PoolTag); + } + } + + if (req != NULL) + { + WdfObjectDelete(req); + req = NULL; + } + + return status; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetTransportResources +( + _In_ ULONG EpIndex, + _In_ PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR pEndpointDescriptor, + _Out_ PUSBHSDEVICE_EP_TRANSPORT_RESOURCES pTransportResources +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS status = STATUS_SUCCESS; + + // SIOP_TYPE_USBAUD_USBD_INTERFACE_DESCRIPTOR + status = GetSiop(EpIndex, SIOP_TYPE_USBAUD_USBD_INTERFACE_DESCRIPTOR, USBSIDEBANDTEST_POOLTAG07, (PBYTE *)&pTransportResources->pUsbInterfaceDescriptor); + if (!NT_SUCCESS(status)) + { + DPF(D_ERROR, ("%!FUNC!: GetSiop(SIOP_TYPE_USBAUD_USBD_INTERFACE_DESCRIPTOR) failed, 0x%x", status)); + goto Done; + } + + // SIOP_TYPE_USBAUD_EP_USBD_ENDPOINT_DESCRIPTOR + status = GetSiop(EpIndex, SIOP_TYPE_USBAUD_EP_USBD_ENDPOINT_DESCRIPTOR, USBSIDEBANDTEST_POOLTAG08, (PBYTE *)&pTransportResources->pUsbEndpointDescriptor); + if (!NT_SUCCESS(status)) + { + DPF(D_ERROR, ("%!FUNC!: GetSiop(SIOP_TYPE_USBAUD_EP_USBD_ENDPOINT_DESCRIPTOR) failed, 0x%x", status)); + goto Done; + } + + // SIOP_TYPE_USBAUD_EP_USBD_ENDPOINT_OFFLOAD_INFORMATION + status = GetSiop(EpIndex, SIOP_TYPE_USBAUD_EP_USBD_ENDPOINT_OFFLOAD_INFORMATION, USBSIDEBANDTEST_POOLTAG09, (PBYTE *)&pTransportResources->pUsbOffloadInformation); + if (!NT_SUCCESS(status)) + { + DPF(D_ERROR, ("%!FUNC!: GetSiop(SIOP_TYPE_USBAUD_EP_USBD_ENDPOINT_OFFLOAD_INFORMATION) failed, 0x%x", status)); + goto Done; + } + + // SIOP_TYPE_USBAUD_EP_USBAUDIO_TRANSPORT_RESOURCES + status = GetSiop(EpIndex, SIOP_TYPE_USBAUD_EP_USBAUDIO_TRANSPORT_RESOURCES, USBSIDEBANDTEST_POOLTAG010, (PBYTE *)&pTransportResources->pUsbAudioTransportResources); + if (!NT_SUCCESS(status)) + { + DPF(D_ERROR, ("%!FUNC!: GetSiop(SIOP_TYPE_USBAUD_EP_USBAUDIO_TRANSPORT_RESOURCES) failed, 0x%x", status)); + goto Done; + } + + if (pEndpointDescriptor->Capabilities.Feedback) + { + // SIOP_TYPE_USBAUD_FB_EP_USBD_ENDPOINT_DESCRIPTOR + status = GetSiop(EpIndex, SIOP_TYPE_USBAUD_FB_EP_USBD_ENDPOINT_DESCRIPTOR, USBSIDEBANDTEST_POOLTAG011, (PBYTE *)&pTransportResources->pSyncUsbEndpointDescriptor); + if (!NT_SUCCESS(status)) + { + DPF(D_ERROR, ("%!FUNC!: GetSiop(SIOP_TYPE_USBAUD_FB_EP_USBD_ENDPOINT_DESCRIPTOR) failed, 0x%x", status)); + goto Done; + } + + // SIOP_TYPE_USBAUD_FB_EP_USBD_ENDPOINT_OFFLOAD_INFORMATION + status = GetSiop(EpIndex, SIOP_TYPE_USBAUD_FB_EP_USBD_ENDPOINT_OFFLOAD_INFORMATION, USBSIDEBANDTEST_POOLTAG012, (PBYTE *)&pTransportResources->pSyncUsbOffloadInformation); + if (!NT_SUCCESS(status)) + { + DPF(D_ERROR, ("%!FUNC!: GetSiop(SIOP_TYPE_USBAUD_FB_EP_USBD_ENDPOINT_OFFLOAD_INFORMATION) failed, 0x%x", status)); + goto Done; + } + + // SIOP_TYPE_USBAUD_FB_EP_USBAUDIO_TRANSPORT_RESOURCES + status = GetSiop(EpIndex, SIOP_TYPE_USBAUD_FB_EP_USBAUDIO_TRANSPORT_RESOURCES, USBSIDEBANDTEST_POOLTAG013, (PBYTE *)&pTransportResources->pSyncUsbAudioTransportResources); + if (!NT_SUCCESS(status)) + { + DPF(D_ERROR, ("%!FUNC!: GetSiop(SIOP_TYPE_USBAUD_FB_EP_USBAUDIO_TRANSPORT_RESOURCES) failed, 0x%x", status)); + goto Done; + } + } + +Done: + if (!NT_SUCCESS(status)) + { + FreeTransportResources(pTransportResources); + } + return status; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetTransportResources +( + _In_ PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR pEndpointDescriptor, + _In_ ULONG EpIndex +) +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS status = STATUS_SUCCESS; + + typedef struct _SYSVAD_USBSBAUD_SIOP_RESOURCE_ID + { + SIDEBANDAUDIO_SIOP_REQUEST_PARAM srp; + ULONG resourceId; + }SYSVAD_USBSBAUD_SIOP_RESOURCE_ID, *PSYSVAD_USBSBAUD_SIOP_RESOURCE_ID; + + // + // Set the USB Resource ID for Endpoint + // + SYSVAD_USBSBAUD_SIOP_RESOURCE_ID siopResourceId = { 0 }; + siopResourceId.srp.EpIndex = EpIndex; + siopResourceId.srp.RequestedSiop.ParamSet = SIDEBANDAUDIO_PARAMS_SET_USBAUDIO; + siopResourceId.srp.RequestedSiop.TypeId = SIOP_TYPE_USBAUD_EP_OFFLOAD_RESOURCE_ID; + siopResourceId.srp.RequestedSiop.Size = sizeof(ULONG); + siopResourceId.resourceId = EpIndex + 7;// Just for testing. Real hardware will populate this with the DSP resource ID + + status = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_SET_SIOP, + sizeof(siopResourceId), + 0, + &siopResourceId); + + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_SET_SIOP) failed, 0x%x", status)), + Done); + + if (pEndpointDescriptor->Capabilities.Feedback) + { + // + // Set the USB Resource ID for Feedback Endpoint + // + siopResourceId.srp.RequestedSiop.TypeId = SIOP_TYPE_USBAUD_FB_EP_OFFLOAD_RESOURCE_ID; + siopResourceId.resourceId = EpIndex + 10;// Just for testing. Real hardware will populate this with the DSP resource ID + + status = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_SET_SIOP, + sizeof(siopResourceId), + 0, + &siopResourceId); + + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_SET_SIOP) Feedback failed, 0x%x", status)), + Done); + } + + // + // All done. + // + status = STATUS_SUCCESS; + +Done: + + return status; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsEndpointFormatsIntersection +( + _In_ PSIDEBANDAUDIO_SUPPORTED_FORMATS pDeviceFormats, + _Out_ PSIDEBANDAUDIO_SUPPORTED_FORMATS *ppSupportedFormatsIntersection +) +/*++ + +Routine Description: + + This function synchronously gets the USB Headset supported formats for + a given endpoint. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + WDFREQUEST req = NULL; + PSIDEBANDAUDIO_SUPPORTED_FORMATS formats = NULL; + ULONG length = 0; + ULONG_PTR information = 0; + WDF_REQUEST_REUSE_PARAMS reuseParams; + WDF_OBJECT_ATTRIBUTES attributes; + + *ppSupportedFormatsIntersection = NULL; + + // + // Allocate and format a WDF request. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &req); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate failed, 0x%x", ntStatus)), + Done); + + // + // Get the size of the buffer. + // + ntStatus = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_SUPPORTED_FORMATS, + pDeviceFormats->CbSize, + 0, + pDeviceFormats, + NULL); + + if (ntStatus != STATUS_BUFFER_TOO_SMALL) + { + if (NT_SUCCESS(ntStatus)) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + } + + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_SUPPORTED_FORMATS): failed, 0x%x", ntStatus)); + goto Done; + } + + ntStatus = STATUS_SUCCESS; + + information = WdfRequestGetInformation(req); + if (information == 0 || information > ULONG_MAX) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + DPF(D_ERROR, ("%!FUNC!: IOCTL_SBAUD_GET_SUPPORTED_FORMATS buffer too big (%Id): 0x%x", information, ntStatus)); + goto Done; + } + + length = (ULONG)information; + + // + // Allocate memory needed to hold the info. + // + formats = (PSIDEBANDAUDIO_SUPPORTED_FORMATS) ExAllocatePoolWithTag(NonPagedPoolNx, length, USBSIDEBANDTEST_POOLTAG03); + if (formats == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: ExAllocatePoolWithTag failed, out of memory")), + Done); + + // + // Get the USB Headset descriptor. + // + WDF_REQUEST_REUSE_PARAMS_INIT( + &reuseParams, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + ntStatus = WdfRequestReuse(req, &reuseParams); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestReuse failed, 0x%x", ntStatus)), + Done); + + // Same buffer used for input and output + // Cast into ULONG to provide EpIndex + + ntStatus = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_SUPPORTED_FORMATS, + pDeviceFormats->CbSize, + length, + pDeviceFormats, + formats); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_SUPPORTED_FORMATS) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *ppSupportedFormatsIntersection = formats; + ntStatus = STATUS_SUCCESS; + +Done: + if (!NT_SUCCESS(ntStatus)) + { + if (formats != NULL) + { + ExFreePoolWithTag(formats, USBSIDEBANDTEST_POOLTAG03); + } + } + + if (req != NULL) + { + WdfObjectDelete(req); + req = NULL; + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsVolumePropertyValues +( + _In_ ULONG EpIndex, + _In_ ULONG Length, + _Out_ PKSPROPERTY_DESCRIPTION *PropValues +) +/*++ + +Routine Description: + + This function synchronously gets the remote USB Headset volume values. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + PKSPROPERTY_DESCRIPTION propValues = NULL; + + *PropValues = NULL; + + // + // Allocate memory. + // + propValues = (PKSPROPERTY_DESCRIPTION) ExAllocatePoolWithTag(NonPagedPoolNx, Length, USBSIDEBANDTEST_POOLTAG02); + if (propValues == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: ExAllocatePoolWithTag failed, out of memory")), + Done); + + // + // Send EpIndex in same buffer as input param + // + *((ULONG *)propValues) = EpIndex; + + // + // Get the USB Headset volume property values. + // + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_GET_VOLUMEPROPERTYVALUES, + sizeof(EpIndex), + Length, + propValues); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_VOLUMEPROPERTYVALUES) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *PropValues = propValues; + ntStatus = STATUS_SUCCESS; + +Done: + if (!NT_SUCCESS(ntStatus)) + { + if (propValues != NULL) + { + ExFreePoolWithTag(propValues, MINADAPTER_POOLTAG); + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetUsbHsSpeakerVolume +( + _In_ LONG Channel, + _In_ LONG Volume +) +/*++ + +Routine Description: + + This function synchronously sets the remote USB Headset speaker volume. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + SIDEBANDAUDIO_VOLUME_PARAMS vp; + + // + // Set the USB Headset speaker volume. + // + + vp.EpIndex = m_SpeakerEpIndex; + vp.Value = Volume; + vp.Channel = Channel; + vp.Immediate = TRUE; // not required for SET + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_SET_VOLUME, + sizeof(vp), + 0, + &vp); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_SET_VOLUME) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsSpeakerVolume +( + _In_ LONG Channel, + _Out_ LONG * Volume +) +/*++ + +Routine Description: + + This function synchronously gets the remote USB Headset speaker volume. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationBuffer buffer = {0}; + + *Volume = 0; + + buffer.Volume.Immediate = TRUE; + buffer.Volume.EpIndex = m_SpeakerEpIndex; + buffer.Volume.Channel = Channel; + buffer.Volume.Value = 0; + + // + // Get the USB headset speaker volume. + // + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE, + sizeof(buffer.Volume), + sizeof(buffer.Volume), + &buffer); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *Volume = buffer.Volume.Value; + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +UsbHsDevice::EnableUsbHsSpeakerVolumeStatusNotification() +/*++ + +Routine Description: + + This function registers for USB Headset speaker + volume change notification. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *ctx = NULL; + + ctx = GetUsbHsDeviceNotificationReqContext(m_SpeakerVolumeReq); + + // + // This is a notification request. + // + ctx->Buffer.Volume.Immediate = FALSE; + ctx->Buffer.Volume.EpIndex = m_SpeakerEpIndex; + ctx->Buffer.Volume.Value = 0; + + // + // Register for speaker volume updates. + // + ntStatus = SendIoCtrlAsynchronously( + m_SpeakerVolumeReq, + IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE, + ctx->MemIn, + ctx->MemOut, + EvtUsbHsDeviceNotificationStatusCompletion, + this); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlAsynchronously(IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetUsbHsMicVolume +( + _In_ LONG Channel, + _In_ LONG Volume +) +/*++ + +Routine Description: + +This function synchronously sets the remote USB Headset mic volume. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + SIDEBANDAUDIO_VOLUME_PARAMS vp; + + // + // Get the USB Headset mic volume. + // + + vp.EpIndex = m_MicEpIndex; + vp.Value = Volume; + vp.Channel = Channel; + vp.Immediate = TRUE; // not required for SET + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_SET_VOLUME, + sizeof(vp), + 0, + &vp); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_SET_VOLUME) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsMicVolume +( + _In_ LONG Channel, + _Out_ LONG * Volume +) +/*++ + +Routine Description: + +This function synchronously gets the remote USB Headset mic volume. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationBuffer buffer = { 0 }; + + *Volume = 0; + + buffer.Volume.Immediate = TRUE; + buffer.Volume.EpIndex = m_MicEpIndex; + buffer.Volume.Channel = Channel; + buffer.Volume.Value = 0; + + // + // Get the USB Headset mic volume. + // + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE, + sizeof(buffer.Volume), + sizeof(buffer.Volume), + &buffer); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *Volume = buffer.Volume.Value; + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsMutePropertyValues +( + _In_ ULONG EpIndex, + _In_ PULONG pLength, + _Out_ PKSPROPERTY_DESCRIPTION *PropValues +) +/*++ + +Routine Description: + + This function synchronously gets the remote USB Headset mute values. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + WDFREQUEST req = NULL; + ULONG length = 0; + ULONG_PTR information = 0; + WDF_REQUEST_REUSE_PARAMS reuseParams; + WDF_OBJECT_ATTRIBUTES attributes; + PKSPROPERTY_DESCRIPTION propValues = NULL; + + *PropValues = NULL; + + // + // Allocate and format a WDF request. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = m_Adapter->GetWdfDevice(); + ntStatus = WdfRequestCreate( + &attributes, + m_WdfIoTarget, + &req); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestCreate failed, 0x%x", ntStatus)), + Done); + + // + // Get the size of the buffer. + // + ntStatus = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_MUTEPROPERTYVALUES, + sizeof(EpIndex), + 0, + &EpIndex); + + if (ntStatus != STATUS_BUFFER_TOO_SMALL) + { + if (NT_SUCCESS(ntStatus)) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + } + + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_MUTEPROPERTYVALUES): failed, 0x%x", ntStatus)); + goto Done; + } + + ntStatus = STATUS_SUCCESS; + + information = WdfRequestGetInformation(req); + if (information == 0 || information > ULONG_MAX) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + DPF(D_ERROR, ("%!FUNC!: IOCTL_SBAUD_GET_MUTEPROPERTYVALUES buffer too big (%Id): 0x%x", information, ntStatus)); + goto Done; + } + + length = (ULONG)information; + + // + // Allocate memory needed to hold the info. + // + propValues = (PKSPROPERTY_DESCRIPTION) ExAllocatePoolWithTag(NonPagedPoolNx, length, USBSIDEBANDTEST_POOLTAG06); + if (propValues == NULL) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: ExAllocatePoolWithTag failed, out of memory")), + Done); + + // + // Get the USB Headset Mute Property Values. + // + WDF_REQUEST_REUSE_PARAMS_INIT( + &reuseParams, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + ntStatus = WdfRequestReuse(req, &reuseParams); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: WdfRequestReuse failed, 0x%x", ntStatus)), + Done); + + // Same buffer used for input and output + // Cast into ULONG to provide EpIndex + *((ULONG *)propValues) = EpIndex; + + ntStatus = SendIoCtrlSynchronously( + req, + IOCTL_SBAUD_GET_MUTEPROPERTYVALUES, + sizeof(EpIndex), + length, + propValues); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_MUTEPROPERTYVALUES) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *PropValues = propValues; + *pLength = length; + ntStatus = STATUS_SUCCESS; + +Done: + if (!NT_SUCCESS(ntStatus)) + { + if (propValues != NULL) + { + ExFreePoolWithTag(propValues, USBSIDEBANDTEST_POOLTAG06); + } + } + + if (req != NULL) + { + WdfObjectDelete(req); + req = NULL; + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetUsbHsSpeakerMute +( + _In_ LONG Channel, + _In_ LONG Mute +) +/*++ + +Routine Description: + + This function synchronously sets the remote USB Headset speaker mute. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + SIDEBANDAUDIO_MUTE_PARAMS mp; + + // + // Set the USB Headset speaker mute. + // + + mp.EpIndex = m_SpeakerEpIndex; + mp.Value = Mute; + mp.Channel = Channel; + mp.Immediate = TRUE; // not required for SET + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_SET_MUTE, + sizeof(mp), + 0, + &mp); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_SET_MUTE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsSpeakerMute +( + _In_ LONG Channel, + _Out_ LONG *Mute +) +/*++ + +Routine Description: + + This function synchronously gets the remote USB Headset speaker mute. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationBuffer buffer = {0}; + + *Mute = 0; + + buffer.Mute.Immediate = TRUE; + buffer.Mute.EpIndex = m_SpeakerEpIndex; + buffer.Mute.Channel = Channel; + buffer.Mute.Value = 0; + + // + // Get the USB headset speaker mute. + // + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE, + sizeof(buffer.Mute), + sizeof(buffer.Mute), + &buffer); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *Mute = buffer.Mute.Value; + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +UsbHsDevice::EnableUsbHsSpeakerMuteStatusNotification() +/*++ + +Routine Description: + + This function registers for USB Headset speaker + mute change notification. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *ctx = NULL; + + ctx = GetUsbHsDeviceNotificationReqContext(m_SpeakerMuteReq); + + // + // This is a notification request. + // + ctx->Buffer.Mute.Immediate = FALSE; + ctx->Buffer.Mute.EpIndex = m_SpeakerEpIndex; + ctx->Buffer.Mute.Value = 0; + + // + // Register for speaker mute updates. + // + ntStatus = SendIoCtrlAsynchronously( + m_SpeakerMuteReq, + IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE, + ctx->MemIn, + ctx->MemOut, + EvtUsbHsDeviceNotificationStatusCompletion, + this); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlAsynchronously(IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetUsbHsMicMute +( + _In_ LONG Channel, + _In_ LONG Mute +) +/*++ + +Routine Description: + +This function synchronously sets the remote USB Headset mic mute. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + SIDEBANDAUDIO_MUTE_PARAMS mp; + + // + // Get the USB Headset mic mute. + // + + mp.EpIndex = m_MicEpIndex; + mp.Value = Mute; + mp.Channel = Channel; + mp.Immediate = TRUE; // not required for SET + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_SET_MUTE, + sizeof(mp), + 0, + &mp); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_SET_MUTE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::GetUsbHsMicMute +( + _In_ LONG Channel, + _Out_ LONG *Mute +) +/*++ + +Routine Description: + +This function synchronously gets the remote USB Headset mic mute. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationBuffer buffer = { 0 }; + + *Mute = 0; + + buffer.Mute.Immediate = TRUE; + buffer.Mute.EpIndex = m_MicEpIndex; + buffer.Mute.Channel = Channel; + buffer.Mute.Value = 0; + + // + // Get the USB Headset mic mute. + // + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE, + sizeof(buffer.Mute), + sizeof(buffer.Mute), + &buffer); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + *Mute = buffer.Mute.Value; + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +UsbHsDevice::EnableUsbHsMicMuteStatusNotification() +/*++ + +Routine Description: + + This function registers for USB Headset mic + mute change notification. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *ctx = NULL; + + ctx = GetUsbHsDeviceNotificationReqContext(m_MicMuteReq); + + // + // This is a notification request. + // + ctx->Buffer.Mute.Immediate = FALSE; + ctx->Buffer.Mute.EpIndex = m_MicEpIndex; + ctx->Buffer.Mute.Value = 0; + + // + // Register for mic mute updates. + // + ntStatus = SendIoCtrlAsynchronously( + m_MicMuteReq, + IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE, + ctx->MemIn, + ctx->MemOut, + EvtUsbHsDeviceNotificationStatusCompletion, + this); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlAsynchronously(IOCTL_SBAUD_GET_MUTE_STATUS_UPDATE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetSidebandClaimed(_In_ BOOL bClaimed) +/*++ + +Routine Description: + + This function synchronously requests an open ISOCH channel to transmit audio + data over transport. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_SET_DEVICE_CLAIMED, + sizeof(BOOL), + 0, + &bClaimed); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_SET_DEVICE_CLAIMED) failed, 0x%x", ntStatus)), + Done); + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +UsbHsDevice::EnableUsbHsMicVolumeStatusNotification() +/*++ + +Routine Description: + +This function registers for USB Headset mic +volume change notification. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *ctx = NULL; + + ctx = GetUsbHsDeviceNotificationReqContext(m_MicVolumeReq); + + // + // This is a notification request. + // + ctx->Buffer.Volume.Immediate = FALSE; + ctx->Buffer.Volume.EpIndex = m_MicEpIndex; + ctx->Buffer.Volume.Value = 0; + + // + // Register for mic volume updates. + // + ntStatus = SendIoCtrlAsynchronously( + m_MicVolumeReq, + IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE, + ctx->MemIn, + ctx->MemOut, + EvtUsbHsDeviceNotificationStatusCompletion, + this); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlAsynchronously(IOCTL_SBAUD_GET_VOLUME_STATUS_UPDATE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +void +UsbHsDevice::EvtUsbHsDeviceStreamStatusCompletion +( + _In_ WDFREQUEST Request, + _In_ WDFIOTARGET Target, + _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, + _In_ WDFCONTEXT Context +) +/*++ + +Routine Description: + + Completion callback for the USB Headset stream status notification. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *reqCtx = NULL; + UsbHsDevice *This = NULL; + NTSTATUS ntResult = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Target); + UNREFERENCED_PARAMETER(Context); + + // + // Get the USB stream status. + // + reqCtx = GetUsbHsDeviceNotificationReqContext(Request); + This = reqCtx->UsbHsDevice; + ASSERT(This != NULL); + + ntStatus = Params->IoStatus.Status; + if (!NT_SUCCESS(ntStatus)) + { + ntResult = STATUS_INVALID_DEVICE_STATE; + } + else + { + ntResult = reqCtx->Buffer.streamStatus.Status; + } + + if (reqCtx->Buffer.streamStatus.EpIndex == This->m_SpeakerEpIndex) + { + InterlockedExchange(&This->m_SpeakerStreamStatusLong, (LONG)ntResult); + + // + // Let the stop routine know we are done. Stop routine will + // re-init the request. + // + KeSetEvent(&This->m_SpeakerStreamStatusEvent, IO_NO_INCREMENT, FALSE); + } + else if (reqCtx->Buffer.streamStatus.EpIndex == This->m_MicEpIndex) + { + InterlockedExchange(&This->m_MicStreamStatusLong, (LONG)ntResult); + + // + // Let the stop routine know we are done. Stop routine will + // re-init the request. + // + KeSetEvent(&This->m_MicStreamStatusEvent, IO_NO_INCREMENT, FALSE); + } +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +UsbHsDevice::EnableUsbHsSpeakerStreamStatusNotification() +/*++ + +Routine Description: + + This function registers for USB Headset stream status notification. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *ctx = NULL; + + ASSERT(m_nSpeakerStreamsOpen > 0); + + ctx = GetUsbHsDeviceNotificationReqContext(m_SpeakerStreamReq); + ctx->Buffer.streamStatus.Immediate = FALSE; + ctx->Buffer.streamStatus.EpIndex = m_SpeakerEpIndex; + + KeClearEvent(&m_SpeakerStreamStatusEvent); + + // + // Get the USB Headset speaker stream status. + // + ntStatus = SendIoCtrlAsynchronously( + m_SpeakerStreamReq, + IOCTL_SBAUD_GET_STREAM_STATUS_UPDATE, + ctx->MemIn, + ctx->MemOut, + EvtUsbHsDeviceStreamStatusCompletion, + this); + + if (!NT_SUCCESS(ntStatus)) + { + KeSetEvent(&m_SpeakerStreamStatusEvent, IO_NO_INCREMENT, FALSE); + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlAsynchronously(IOCTL_SBAUD_GET_STREAM_STATUS_UPDATE) failed, 0x%x", ntStatus)); + goto Done; + } + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +UsbHsDevice::EnableUsbHsMicStreamStatusNotification() +/*++ + +Routine Description: + + This function registers for USB Headset stream status notification. + +--*/ +{ + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *ctx = NULL; + + ASSERT(m_nMicStreamsOpen > 0); + + ctx = GetUsbHsDeviceNotificationReqContext(m_MicStreamReq); + ctx->Buffer.streamStatus.Immediate = FALSE; + ctx->Buffer.streamStatus.EpIndex = m_MicEpIndex; + + KeClearEvent(&m_MicStreamStatusEvent); + + // + // Get the USB Headset mic stream status. + // + ntStatus = SendIoCtrlAsynchronously( + m_MicStreamReq, + IOCTL_SBAUD_GET_STREAM_STATUS_UPDATE, + ctx->MemIn, + ctx->MemOut, + EvtUsbHsDeviceStreamStatusCompletion, + this); + + if (!NT_SUCCESS(ntStatus)) + { + KeSetEvent(&m_MicStreamStatusEvent, IO_NO_INCREMENT, FALSE); + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlAsynchronously(IOCTL_SBAUD_GET_STREAM_STATUS_UPDATE) failed, 0x%x", ntStatus)); + goto Done; + } + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::StopUsbHsSpeakerStreamStatusNotification() +/*++ + +Routine Description: + + This function stops the USB Headset speaker stream status notification. + The function waits for the request to be done before returning. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *reqCtx = NULL; + WDF_REQUEST_REUSE_PARAMS reuseParams; + + WdfRequestCancelSentRequest(m_SpeakerStreamReq); + KeWaitForSingleObject(&m_SpeakerStreamStatusEvent, Executive, KernelMode, FALSE, NULL); + + reqCtx = GetUsbHsDeviceNotificationReqContext(m_SpeakerStreamReq); + ASSERT(reqCtx != NULL); + UNREFERENCED_VAR(reqCtx); + + // + // Re-init the request for later. + // + WDF_REQUEST_REUSE_PARAMS_INIT( + &reuseParams, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + ntStatus = WdfRequestReuse(m_SpeakerStreamReq, &reuseParams); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_ERROR, ("%!FUNC!: WdfRequestReuse failed, 0x%x", ntStatus)); + } + + return STATUS_SUCCESS; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::StopUsbHsMicStreamStatusNotification() +/*++ + +Routine Description: + + This function stops the USB Headset mic stream status notification. + The function waits for the request to be done before returning. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDeviceNotificationReqContext *reqCtx = NULL; + WDF_REQUEST_REUSE_PARAMS reuseParams; + + WdfRequestCancelSentRequest(m_MicStreamReq); + KeWaitForSingleObject(&m_MicStreamStatusEvent, Executive, KernelMode, FALSE, NULL); + + reqCtx = GetUsbHsDeviceNotificationReqContext(m_MicStreamReq); + ASSERT(reqCtx != NULL); + UNREFERENCED_VAR(reqCtx); + + // + // Re-init the request for later. + // + WDF_REQUEST_REUSE_PARAMS_INIT( + &reuseParams, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + ntStatus = WdfRequestReuse(m_MicStreamReq, &reuseParams); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_ERROR, ("%!FUNC!: WdfRequestReuse failed, 0x%x", ntStatus)); + } + + return STATUS_SUCCESS; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetUsbHsStreamOpen +( + ULONG EpIndex, + PKSDATAFORMAT_WAVEFORMATEXTENSIBLE pStreamFormat, + PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR pEndpointDescriptor +) +/*++ + +Routine Description: + + This function synchronously requests an open ISOCH channel to transmit audio + data over transport. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[UsbHsDevice::SetA2dpHpStreamOpen]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UNREFERENCED_PARAMETER(pEndpointDescriptor); + + SIDEBANDAUDIO_STREAM_OPEN_PARAMS sp = { 0 }; + sp.EpIndex = EpIndex; + sp.Format = (PKSDATAFORMAT)pStreamFormat; + sp.SiopCount = 0; + + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_STREAM_OPEN, + sizeof(sp), + 0, + &sp); + + if (ntStatus == STATUS_DEVICE_BUSY) + { + // The stream channel is already open. + DPF(D_VERBOSE, ("SetA2dpHpStreamOpen: the stream channel is already open")); + ntStatus = STATUS_SUCCESS; + } + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("SetA2dpHpStreamOpen: SendIoCtrlSynchronously(IOCTL_SBAUD_STREAM_OPEN) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetUsbHsStreamStart +( + ULONG EpIndex +) +/*++ + +Routine Description: + + This function synchronously requests an Start ISOCH channel to transmit audio + data over transport. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[UsbHsDevice::SetA2dpHpStreamStart]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_STREAM_START, + sizeof(EpIndex), + 0, + &EpIndex); + + if (ntStatus == STATUS_DEVICE_BUSY) + { + // The stream channel is already Start. + DPF(D_VERBOSE, ("SetA2dpHpStreamStart: the stream channel is already Start")); + ntStatus = STATUS_SUCCESS; + } + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("SetA2dpHpStreamStart: SendIoCtrlSynchronously(IOCTL_SBAUD_STREAM_START) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetUsbHsStreamSuspend +( + _In_ ULONG EpIndex +) +/*++ + +Routine Description: + + This function synchronously requests to Suspend the ISOCH channel. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_STREAM_SUSPEND, + sizeof(EpIndex), + 0, + &EpIndex); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_STREAM_SUSPEND) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::SetUsbHsStreamClose +( + _In_ ULONG EpIndex +) +/*++ + +Routine Description: + + This function synchronously requests to close the ISOCH channel. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + ntStatus = SendIoCtrlSynchronously( + NULL, + IOCTL_SBAUD_STREAM_CLOSE, + sizeof(EpIndex), + 0, + &EpIndex); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SendIoCtrlSynchronously(IOCTL_SBAUD_STREAM_CLOSE) failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +VOID +UsbHsDevice::Start() +/*++ + +Routine Description: + + Asynchronously called to start the audio device. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG speakerEndpoints = 0; + ULONG micEndpoints = 0; + + // + // Get USB headset descriptor + // + ntStatus = GetUsbHsDescriptor(&m_Descriptor); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsDescriptor: failed to retrieve USB Headset Descriptor, 0x%x", ntStatus)), + Done); + + for (ULONG i = 0; i < m_Descriptor->NumberOfEndpoints; i++) + { + PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR ed; + ntStatus = GetUsbHsEndpointDescriptor(i, &ed); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsEndpointDescriptor: failed to retrieve USB Headset Endpoint %d Descriptor, 0x%x", i, ntStatus)), + Done); + + if (ed->Direction == KSPIN_DATAFLOW_OUT) + { + speakerEndpoints++; + m_SpeakerEpIndex = i; + m_pSpeakerDescriptor = ed; + } + else if (ed->Direction == KSPIN_DATAFLOW_IN) + { + micEndpoints++; + m_MicEpIndex = i; + m_pMicDescriptor = ed; + } + } + + if (speakerEndpoints > 1 || + micEndpoints > 1) + { + ntStatus = STATUS_DEVICE_FEATURE_NOT_SUPPORTED; + m_SpeakerEpIndex = 0; + m_MicEpIndex = 0; + } + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: Number of endpoints on USB device not supported, 0x%x", ntStatus)), + Done); + + // + // Get volume settings. + // + if (m_pSpeakerDescriptor) + { + if (m_pSpeakerDescriptor->Capabilities.Volume) + { + PKSPROPERTY_DESCRIPTION volumePropValues = NULL; + LONG volume = 0; + + // Volume settings. + ntStatus = GetUsbHsVolumePropertyValues( + m_SpeakerEpIndex, + m_pSpeakerDescriptor->VolumePropertyValuesSize, + &volumePropValues); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsVolumePropertyValues: failed to retrieve KSPROPERTY_VALUES, 0x%x", ntStatus)), + Done); + + m_SpeakerVolumePropValues = volumePropValues; + + // Speaker volume. + ntStatus = GetUsbHsSpeakerVolume(0, &volume); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsSpeakerVolume: failed, 0x%x", ntStatus)), + Done); + + m_SpeakerVolumeLevel = volume; + } + + if (m_pSpeakerDescriptor->Capabilities.Mute) + { + PKSPROPERTY_DESCRIPTION mutePropValues = NULL; + ULONG ulMutePropValuesSize = 0; + LONG mute = 0; + + // Mute settings. + ntStatus = GetUsbHsMutePropertyValues( + m_SpeakerEpIndex, + &ulMutePropValuesSize, + &mutePropValues); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsMutePropertyValues: failed to retrieve KSPROPERTY_DESCRIPTION, 0x%x", ntStatus)), + Done); + + m_SpeakerMutePropValues = mutePropValues; + m_ulSpeakerMutePropValuesSize = ulMutePropValuesSize; + + // Speaker mute. + ntStatus = GetUsbHsSpeakerMute(0, &mute); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsSpeakerMute: failed, 0x%x", ntStatus)), + Done); + + m_SpeakerMute = mute; + } + + // Speaker Formats + PKSDATAFORMAT speakerFormatsArray[SIZEOF_ARRAY(UsbHsSpeakerSupportedDeviceFormats)]; + for (ULONG i = 0; i < SIZEOF_ARRAY(UsbHsSpeakerSupportedDeviceFormats); i++) + { + speakerFormatsArray[i] = (PKSDATAFORMAT)(&UsbHsSpeakerSupportedDeviceFormats[i]); + } + SIDEBANDAUDIO_SUPPORTED_FORMATS speakerDeviceFormats = + { + sizeof(SIDEBANDAUDIO_SUPPORTED_FORMATS), + m_SpeakerEpIndex, + SIZEOF_ARRAY(UsbHsSpeakerSupportedDeviceFormats), + speakerFormatsArray + }; + + ntStatus = GetUsbHsEndpointFormatsIntersection(&speakerDeviceFormats, &m_pSpeakerSupportedFormatsIntersection); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsEndpointFormats: failed for speaker, 0x%x", ntStatus)), + Done); + + // + // Customize the topology/wave descriptors for this instance + // + ntStatus = CreateCustomEndpointMinipair( + g_UsbHsRenderEndpoints[0], + &m_pSpeakerDescriptor->FriendlyName, + &m_pSpeakerDescriptor->Category, + &m_SpeakerMiniports); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: CreateCustomEndpointMinipair for Render: failed, 0x%x", ntStatus)), + Done); + m_SpeakerMiniports->TopoName = m_SpeakerTopologyNameBuffer; + m_SpeakerMiniports->WaveName = m_SpeakerWaveNameBuffer; + + // Verify format compat + ntStatus = VerifyEndpointFormatCompatibility( + m_pSpeakerSupportedFormatsIntersection, + UsbHsSpeakerSupportedDeviceFormats, + SIZEOF_ARRAY(UsbHsSpeakerSupportedDeviceFormats), + &m_SpeakerSelectedFormat); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: VerifyEndpointFormatCompatibility : failed for speaker, 0x%x", ntStatus)), + Done); + + ASSERT(m_SpeakerMiniports != NULL); + _Analysis_assume_(m_SpeakerMiniports != NULL); + + // + // Register topology and wave filters. + // + ntStatus = m_Adapter->InstallEndpointFilters( + NULL, + m_SpeakerMiniports, + PSIDEBANDDEVICECOMMON(this), + &m_UnknownSpeakerTopology, + &m_UnknownSpeakerWave, NULL, NULL + ); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: InstallEndpointRenderFilters (USB Headset): failed, 0x%x", ntStatus)), + Done); + + // + // Pend status notifications. + // + + if (m_pSpeakerDescriptor->Capabilities.Volume) + { + // Volume speaker status. + ntStatus = EnableUsbHsSpeakerVolumeStatusNotification(); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: EnableUsbHsSpeakerVolumeStatusNotification: failed, 0x%x", ntStatus)), + Done); + } + } + + if (m_pMicDescriptor) + { + if (m_pMicDescriptor->Capabilities.Volume) + { + PKSPROPERTY_DESCRIPTION volumePropValues = NULL; + LONG volume = 0; + + // Volume settings. + ntStatus = GetUsbHsVolumePropertyValues( + m_MicEpIndex, + m_pMicDescriptor->VolumePropertyValuesSize, + &volumePropValues); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsVolumePropertyValues: failed to retrieve KSPROPERTY_VALUES, 0x%x", ntStatus)), + Done); + + m_MicVolumePropValues = volumePropValues; + + // Mic volume. + ntStatus = GetUsbHsMicVolume(0, &volume); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsMicVolume: failed, 0x%x", ntStatus)), + Done); + + m_MicVolumeLevel = volume; + } + + if (m_pMicDescriptor->Capabilities.Mute) + { + PKSPROPERTY_DESCRIPTION mutePropValues = NULL; + ULONG ulMutePropValuesSize = 0; + LONG mute = 0; + + // Mute settings. + ntStatus = GetUsbHsMutePropertyValues( + m_MicEpIndex, + &ulMutePropValuesSize, + &mutePropValues); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsMutePropertyValues: failed to retrieve KSPROPERTY_DESCRIPTION, 0x%x", ntStatus)), + Done); + + m_MicMutePropValues = mutePropValues; + m_ulMicMutePropValuesSize = ulMutePropValuesSize; + + // Mic mute. + ntStatus = GetUsbHsMicMute(0, &mute); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsMicMute: failed, 0x%x", ntStatus)), + Done); + + m_MicMute = mute; + } + + // Mic Formats + PKSDATAFORMAT micFormatsArray[SIZEOF_ARRAY(UsbHsMicSupportedDeviceFormats)]; + for (ULONG i = 0; i < SIZEOF_ARRAY(UsbHsMicSupportedDeviceFormats); i++) + { + micFormatsArray[i] = (PKSDATAFORMAT)(&UsbHsMicSupportedDeviceFormats[i]); + } + SIDEBANDAUDIO_SUPPORTED_FORMATS micDeviceFormats = + { + sizeof(SIDEBANDAUDIO_SUPPORTED_FORMATS), + m_MicEpIndex, + SIZEOF_ARRAY(UsbHsMicSupportedDeviceFormats), + micFormatsArray + }; + + ntStatus = GetUsbHsEndpointFormatsIntersection(&micDeviceFormats, &m_pMicSupportedFormatsIntersection); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: GetUsbHsEndpointFormats: failed for mic, 0x%x", ntStatus)), + Done); + + ntStatus = CreateCustomEndpointMinipair( + g_UsbHsCaptureEndpoints[0], + &m_pMicDescriptor->FriendlyName, + &m_pMicDescriptor->Category, + &m_MicMiniports); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: CreateCustomEndpointMinipair for Capture: failed, 0x%x", ntStatus)), + Done); + m_MicMiniports->TopoName = m_MicTopologyNameBuffer; + m_MicMiniports->WaveName = m_MicWaveNameBuffer; + + // Verify format compat + ntStatus = VerifyEndpointFormatCompatibility( + m_pMicSupportedFormatsIntersection, + UsbHsMicSupportedDeviceFormats, + SIZEOF_ARRAY(UsbHsMicSupportedDeviceFormats), + &m_MicSelectedFormat); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: VerifyEndpointFormatCompatibility : failed for mic, 0x%x", ntStatus)), + Done); + + ASSERT(m_MicMiniports != NULL); + _Analysis_assume_(m_MicMiniports != NULL); + + ntStatus = m_Adapter->InstallEndpointFilters( + NULL, + m_MicMiniports, + PSIDEBANDDEVICECOMMON(this), + &m_UnknownMicTopology, + &m_UnknownMicWave, NULL, NULL + ); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: InstallEndpointCaptureFilters (USB Headset): failed, 0x%x", ntStatus)), + Done); + + // + // Pend status notifications. + // + + if (m_pMicDescriptor->Capabilities.Volume) + { + // Volume mic status. + ntStatus = EnableUsbHsMicVolumeStatusNotification(); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: EnableUsbHsMicVolumeStatusNotification: failed, 0x%x", ntStatus)), + Done); + } + } + + if (speakerEndpoints > 0 && micEndpoints > 0) + { + ntStatus = m_Adapter->NotifyEndpointPair( + m_SpeakerTopologyNameBuffer, + SIZEOF_ARRAY(m_SpeakerTopologyNameBuffer), + KSPIN_TOPO_LINEOUT_DEST, + m_MicTopologyNameBuffer, + SIZEOF_ARRAY(m_MicTopologyNameBuffer), + KSPIN_TOPO_MIC_ELEMENTS + ); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: NotifyEndpointPair: failed, 0x%x", ntStatus)), + Done); + } + + // Set Sideband claimed + ntStatus = SetSidebandClaimed(TRUE); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("%!FUNC!: SetSidebandClaimed TRUE: failed, 0x%x", ntStatus)), + Done); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + if (!NT_SUCCESS(ntStatus)) + { + ntStatus = SetSidebandClaimed(FALSE); + InterlockedExchange((PLONG)&m_State, eUsbHsStateFailed); + } +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::CreateCustomEndpointMinipair +( + _In_ PENDPOINT_MINIPAIR pBaseMinipair, + _In_ PUNICODE_STRING FriendlyName, + _In_ PGUID pCategory, + _Outptr_ PENDPOINT_MINIPAIR *ppCustomMinipair +) +{ + NTSTATUS ntStatus; + PENDPOINT_MINIPAIR pNewMinipair = NULL; + SYSVAD_DEVPROPERTY* pProperties = NULL; + PPCFILTER_DESCRIPTOR pNewTopoFilterDesc = NULL; + PPCPIN_DESCRIPTOR pNewTopoPins = NULL; + ULONG cProperties; + ULONG cTopoPins; + + PAGED_CODE(); + + // + // This routine will add one more property to whatever the base minipair describes for the topo filter interface properties + // It will also allocate and set up custom filter and pin descriptors to allow changing the KSNODETYPE for the usb device + // + cTopoPins = pBaseMinipair->TopoDescriptor->PinCount; + cProperties = pBaseMinipair->TopoInterfacePropertyCount + 1; + pProperties = (SYSVAD_DEVPROPERTY*)ExAllocatePoolWithTag(NonPagedPoolNx, cProperties * sizeof(SYSVAD_DEVPROPERTY), SYSVAD_POOLTAG); + pNewMinipair = (ENDPOINT_MINIPAIR*)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(ENDPOINT_MINIPAIR), SYSVAD_POOLTAG); + pNewTopoFilterDesc = (PCFILTER_DESCRIPTOR*)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(PCFILTER_DESCRIPTOR), SYSVAD_POOLTAG); + pNewTopoPins = (PCPIN_DESCRIPTOR*)ExAllocatePoolWithTag(NonPagedPoolNx, cTopoPins * sizeof(PCPIN_DESCRIPTOR), SYSVAD_POOLTAG); + + if ((pProperties != NULL) && (pNewMinipair != NULL) && (pNewTopoFilterDesc != NULL) && (pNewTopoPins != NULL)) + { + SYSVAD_DEVPROPERTY *pLastProperty; + + // Copy base minipair properties to new property list + if (pBaseMinipair->TopoInterfacePropertyCount > 0) + { + RtlCopyMemory(pProperties, pBaseMinipair->TopoInterfaceProperties, (cProperties - 1) * sizeof(SYSVAD_DEVPROPERTY)); + } + + // Add friendly name property to the list + NT_ASSERT(FriendlyName->Length + sizeof(UNICODE_NULL) <= FriendlyName->MaximumLength); // Assuming NULL terminated string + pLastProperty = &pProperties[cProperties - 1]; + pLastProperty->PropertyKey = &DEVPKEY_DeviceInterface_FriendlyName; + pLastProperty->Type = DEVPROP_TYPE_STRING_INDIRECT; + pLastProperty->BufferSize = FriendlyName->Length + sizeof(UNICODE_NULL); + pLastProperty->Buffer = FriendlyName->Buffer; + + // Copy base minipair structure + RtlCopyMemory(pNewMinipair, pBaseMinipair, sizeof(ENDPOINT_MINIPAIR)); + + RtlCopyMemory(pNewTopoFilterDesc, pBaseMinipair->TopoDescriptor, sizeof(PCFILTER_DESCRIPTOR)); + RtlCopyMemory(pNewTopoPins, pBaseMinipair->TopoDescriptor->Pins, cTopoPins * sizeof(PCPIN_DESCRIPTOR)); + + pNewTopoFilterDesc->Pins = pNewTopoPins; + pNewMinipair->TopoDescriptor = pNewTopoFilterDesc; + + // Update it to point to new property list + pNewMinipair->TopoInterfacePropertyCount = cProperties; + pNewMinipair->TopoInterfaceProperties = pProperties; + + ntStatus = UpdateCustomEndpointCategory(pNewTopoFilterDesc, pNewTopoPins, pCategory); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_ERROR, ("%!FUNC!: UpdateCustomEndpointCategory failed, 0x%x", ntStatus)); + } + else + { + *ppCustomMinipair = pNewMinipair; + + pProperties = NULL; + pNewMinipair = NULL; + pNewTopoFilterDesc = NULL; + pNewTopoPins = NULL; + + ntStatus = STATUS_SUCCESS; + } + } + else + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + if (pProperties != NULL) + { + ExFreePoolWithTag(pProperties, SYSVAD_POOLTAG); + } + if (pNewMinipair != NULL) + { + ExFreePoolWithTag(pNewMinipair, SYSVAD_POOLTAG); + } + if (pNewTopoFilterDesc != NULL) + { + ExFreePoolWithTag(pNewTopoFilterDesc, SYSVAD_POOLTAG); + } + if (pNewTopoPins != NULL) + { + ExFreePoolWithTag(pNewTopoPins, SYSVAD_POOLTAG); + } + + return ntStatus; +} +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +UsbHsDevice::UpdateCustomEndpointCategory +( + _In_ PPCFILTER_DESCRIPTOR pCustomMinipairTopoFilter, + _In_ PPCPIN_DESCRIPTOR pCustomMinipairTopoPins, + _In_ PGUID pCategory +) +{ + NTSTATUS ntStatus = STATUS_NOT_FOUND; + ULONG cPinCount = 0; + BOOL FoundCategoryAudio = FALSE; + BOOL FoundNodeType = FALSE; + + PAGED_CODE(); + + cPinCount = pCustomMinipairTopoFilter->PinCount; + + // Find the right pin: There should be two pins, one with Category KSCATEGORY_AUDIO, + // and one with a KSNODETYPE_* Category. We need to modify the KSNODETYPE category. + for (ULONG i = 0; i < cPinCount; ++i) + { + if (IsEqualGUID(*pCustomMinipairTopoPins[i].KsPinDescriptor.Category, KSCATEGORY_AUDIO)) + { + ASSERT(FoundCategoryAudio == FALSE); + if (FoundCategoryAudio) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + DPF(D_ERROR, ("%!FUNC!: KSCATEGORY_AUDIO found more than once, 0x%x", ntStatus)); + break; + } + + FoundCategoryAudio = TRUE; + continue; + } + + ASSERT(FoundNodeType == FALSE); + if (FoundNodeType) + { + ntStatus = STATUS_INVALID_DEVICE_STATE; + DPF(D_ERROR, ("%!FUNC!: Found more than one applicable Pin, 0x%x", ntStatus)); + break; + } + + pCustomMinipairTopoPins[i].KsPinDescriptor.Category = pCategory; + FoundNodeType = TRUE; + ntStatus = STATUS_SUCCESS; + } + + return ntStatus; +} +//============================================================================= +#pragma code_seg("PAGE") +VOID +UsbHsDevice::DeleteCustomEndpointMinipair +( + _In_ PENDPOINT_MINIPAIR pCustomMinipair +) +{ + PAGED_CODE(); + + if (pCustomMinipair != NULL) + { + if (pCustomMinipair->TopoInterfaceProperties != NULL) + { + ExFreePoolWithTag(const_cast(pCustomMinipair->TopoInterfaceProperties), SYSVAD_POOLTAG); + pCustomMinipair->TopoInterfaceProperties = NULL; + } + if (pCustomMinipair->TopoDescriptor != NULL) + { + if (pCustomMinipair->TopoDescriptor->Pins != NULL) + { + ExFreePoolWithTag((PVOID)pCustomMinipair->TopoDescriptor->Pins, SYSVAD_POOLTAG); + pCustomMinipair->TopoDescriptor->Pins = NULL; + } + ExFreePoolWithTag(pCustomMinipair->TopoDescriptor, SYSVAD_POOLTAG); + pCustomMinipair->TopoDescriptor = NULL; + } + ExFreePoolWithTag(pCustomMinipair, SYSVAD_POOLTAG); + } +} + +//============================================================================= +#pragma code_seg("PAGE") +VOID +UsbHsDevice::Stop() +/*++ + +Routine Description: + + Asynchronously called to stop the audio device. + After returning from this function, there are no more async notifications + pending (volume, etc.). + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + eUsbHsState state = eUsbHsStateInvalid; + + state = (eUsbHsState) InterlockedExchange((PLONG)&m_State, eUsbHsStateStopping); + ASSERT(state == eUsbHsStateRunning || state == eUsbHsStateFailed); + UNREFERENCED_VAR(state); + + // + // Stop async notifications. + // + WdfIoTargetPurge(m_WdfIoTarget, WdfIoTargetPurgeIoAndWait); + + // + // Wait for work-item. + // + WdfWorkItemFlush(m_WorkItem); + + // + // Remove the topology and wave render filters. + // + if (m_UnknownSpeakerTopology || m_UnknownSpeakerWave) + { + ntStatus = m_Adapter->RemoveEndpointFilters( + m_SpeakerMiniports, + m_UnknownSpeakerTopology, + m_UnknownSpeakerWave); + + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_ERROR, ("%!FUNC!: RemoveEndpointFilters (USB Headset Speaker): failed, 0x%x", ntStatus)); + } + } + + // + // Remove the topology and wave capture filters. + // + if (m_UnknownMicTopology || m_UnknownMicWave) + { + ntStatus = m_Adapter->RemoveEndpointFilters( + m_MicMiniports, + m_UnknownMicTopology, + m_UnknownMicWave); + + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_ERROR, ("%!FUNC!: RemoveEndpointFilters (USB Headset Capture): failed, 0x%x", ntStatus)); + } + } + + // + // Release port/miniport pointers. + // + SAFE_RELEASE(m_UnknownSpeakerTopology); + SAFE_RELEASE(m_UnknownSpeakerWave); + SAFE_RELEASE(m_UnknownMicTopology); + SAFE_RELEASE(m_UnknownMicWave); + + // + // The device is in the stopped state. + // + InterlockedExchange((PLONG)&m_State, eUsbHsStateStopped); + +} + +#pragma code_seg("PAGE") +NTSTATUS UsbHsDevice::CreateFilterNames( + PUNICODE_STRING UsbHsDeviceSymbolicLinkName +) +/*++ + +Routine Description: + +Creates unique wave and topology filter reference names. + +Since each subdevice representing a USB sideband interface arrival needs to have a unique +reference string, this function generates a hash on 'UsbHsDeviceSymbolicLinkName' parameter +and appends to static interface strings. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[%!FUNC!]")); + + NTSTATUS status = STATUS_SUCCESS; + ULONG hashValue = 0; + + status = RtlHashUnicodeString(UsbHsDeviceSymbolicLinkName, TRUE, HASH_STRING_ALGORITHM_X65599, &hashValue); + IF_FAILED_ACTION_JUMP( + status, + DPF(D_ERROR, ("%!FUNC!: Failed to create KSCATEGORY_REALTIME wave interface: 0x%x", status)), + End); + + // create wave interfaces for speaker + RtlStringCbPrintfW(m_SpeakerWaveNameBuffer, sizeof(m_SpeakerWaveNameBuffer), L"%s-%lu", USBHS_SPEAKER_WAVE_NAME, hashValue); + RtlUnicodeStringInit(&m_SpeakerWaveRefString, m_SpeakerWaveNameBuffer); + + // create topology interfaces for speaker + RtlStringCbPrintfW(m_SpeakerTopologyNameBuffer, sizeof(m_SpeakerTopologyNameBuffer), L"%s-%lu", USBHS_SPEAKER_TOPO_NAME, hashValue); + RtlUnicodeStringInit(&m_SpeakerTopologyRefString, m_SpeakerTopologyNameBuffer); + + // create wave interfaces for mic + RtlStringCbPrintfW(m_MicWaveNameBuffer, sizeof(m_MicWaveNameBuffer), L"%s-%lu", USBHS_MIC_WAVE_NAME, hashValue); + RtlUnicodeStringInit(&m_MicWaveRefString, m_MicWaveNameBuffer); + + // create topology interfaces for mic + RtlStringCbPrintfW(m_MicTopologyNameBuffer, sizeof(m_MicTopologyNameBuffer), L"%s-%lu", USBHS_MIC_TOPO_NAME, hashValue); + RtlUnicodeStringInit(&m_MicTopologyRefString, m_MicTopologyNameBuffer); +End: + return status; +} +#endif // SYSVAD_USB_SIDEBAND diff --git a/audio/sysvad/UsbHsDevice.h b/audio/sysvad/UsbHsDevice.h new file mode 100644 index 00000000..625352af --- /dev/null +++ b/audio/sysvad/UsbHsDevice.h @@ -0,0 +1,623 @@ +// +// This class represents a the Bluetooth Hands-Free Profile USB Headset device. +// There is one class for each interface (id = symbolic-link-name). +// +#ifdef SYSVAD_USB_SIDEBAND + + +//===================================================================== +// +// USB Sideband Headset class definition. +// + +class CAdapterCommon; +class UsbHsDevice; + +struct UsbHsWorkItemContext +{ + CAdapterCommon * Adapter; +}; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME +( + UsbHsWorkItemContext, + GetUsbHsWorkItemContext +) + +// start/stop the device +enum eUsbHsTaskAction +{ + eUsbHsTaskStart = 1, + eUsbHsTaskStop = 2, +}; + +struct UsbHsWorkTask +{ + LIST_ENTRY ListEntry; + UsbHsDevice * Device; + eUsbHsTaskAction Action; +}; + + +//===================================================================== +// +// Device: Bluetooth Hands-Free Profile USB Headset definitions. +// + +// BTH HFP device's notification work-item context. +struct UsbHsDeviceNotificationWorkItemContext +{ + UsbHsDevice * UsbHsDevice; +}; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME +( + UsbHsDeviceNotificationWorkItemContext, + GetUsbHsDeviceNotificationWorkItemContext +) + +// USB HS device's notification request context. +union UsbHsDeviceNotificationBuffer +{ + SIDEBANDAUDIO_VOLUME_PARAMS Volume; + SIDEBANDAUDIO_MUTE_PARAMS Mute; + SIDEBANDAUDIO_SIDETONE_PARAMS Sidetone; + SIDEBANDAUDIO_STREAM_STATUS_PARAMS streamStatus; +}; + +struct UsbHsDeviceNotificationReqContext +{ + UsbHsDevice *UsbHsDevice; + LONG Errors; + UsbHsDeviceNotificationBuffer Buffer; + WDFMEMORY MemIn; + WDFMEMORY MemOut; +}; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME +( + UsbHsDeviceNotificationReqContext, + GetUsbHsDeviceNotificationReqContext +) + +enum eUsbHsState +{ + eUsbHsStateInvalid = 0, + eUsbHsStateInitializing = 1, + eUsbHsStateRunning = 2, + eUsbHsStateStopping = 3, + eUsbHsStateStopped = 4, + eUsbHsStateFailed = 5, +}; + +// To support event notification. +struct UsbHsEventCallback +{ + PFNEVENTNOTIFICATION Handler; + PVOID Context; +}; + +typedef struct _USBHSDEVICE_EP_TRANSPORT_RESOURCES +{ + PUSB_INTERFACE_DESCRIPTOR pUsbInterfaceDescriptor; + PUSBD_ENDPOINT_OFFLOAD_INFORMATION pUsbOffloadInformation; + PUSBD_ENDPOINT_OFFLOAD_INFORMATION pSyncUsbOffloadInformation; + PSIDEBANDAUDIO_EP_USBAUDIO_TRANSPORT_RESOURCES pUsbAudioTransportResources; + PSIDEBANDAUDIO_EP_USBAUDIO_TRANSPORT_RESOURCES pSyncUsbAudioTransportResources; + PUSB_ENDPOINT_DESCRIPTOR pUsbEndpointDescriptor; + PUSB_ENDPOINT_DESCRIPTOR pSyncUsbEndpointDescriptor; +}USBHSDEVICE_EP_TRANSPORT_RESOURCES, *PUSBHSDEVICE_EP_TRANSPORT_RESOURCES; + +#endif // SYSVAD_USB_SIDEBAND +class UsbHsDevice : + ISidebandDeviceCommon, + public CUnknown +{ + private: + eUsbHsState m_State; + + IAdapterCommon * m_Adapter; + WDFIOTARGET m_WdfIoTarget; + + LIST_ENTRY m_ListEntry; + UNICODE_STRING m_SymbolicLinkName; + WCHAR m_SpeakerWaveNameBuffer[USBHS_INTERFACE_REFSTRING_MAX_LENGTH]; + UNICODE_STRING m_SpeakerWaveRefString; + WCHAR m_SpeakerTopologyNameBuffer[USBHS_INTERFACE_REFSTRING_MAX_LENGTH]; + UNICODE_STRING m_SpeakerTopologyRefString; + WCHAR m_MicWaveNameBuffer[USBHS_INTERFACE_REFSTRING_MAX_LENGTH]; + UNICODE_STRING m_MicWaveRefString; + WCHAR m_MicTopologyNameBuffer[USBHS_INTERFACE_REFSTRING_MAX_LENGTH]; + UNICODE_STRING m_MicTopologyRefString; + + // + // The Topo Filter Desc and Topo Pins structures referenced from + // the Miniports structure are deep copies: they start as copies of the + // static structures and are modified to allow USB-Device pin + // categories based on the info obtained from + // IOCTL_SBAUD_GET_ENDPOINT_DESCRIPTOR + // + PENDPOINT_MINIPAIR m_SpeakerMiniports; + PENDPOINT_MINIPAIR m_MicMiniports; + + PUNKNOWN m_UnknownSpeakerTopology; + PUNKNOWN m_UnknownSpeakerWave; + PUNKNOWN m_UnknownMicTopology; + PUNKNOWN m_UnknownMicWave; + + PSIDEBANDAUDIO_DEVICE_DESCRIPTOR m_Descriptor; + PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR m_pSpeakerDescriptor; + PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR m_pMicDescriptor; + PKSPROPERTY_DESCRIPTION m_SpeakerVolumePropValues; + LONG m_SpeakerVolumeLevel; + PKSPROPERTY_DESCRIPTION m_MicVolumePropValues; + LONG m_MicVolumeLevel; + + PKSPROPERTY_DESCRIPTION m_SpeakerMutePropValues; + ULONG m_ulSpeakerMutePropValuesSize; + LONG m_SpeakerMute; + PKSPROPERTY_DESCRIPTION m_MicMutePropValues; + ULONG m_ulMicMutePropValuesSize; + LONG m_MicMute; + + + ULONG m_SpeakerEpIndex; + ULONG m_MicEpIndex; + + union{ + NTSTATUS m_SpeakerStreamStatus; + LONG m_SpeakerStreamStatusLong; + }; // unnamed. + union{ + NTSTATUS m_MicStreamStatus; + LONG m_MicStreamStatusLong; + }; // unnamed. + + KEVENT m_SpeakerStreamStatusEvent; + KEVENT m_MicStreamStatusEvent; + + PSIDEBANDAUDIO_SUPPORTED_FORMATS m_pSpeakerSupportedFormatsIntersection; + ULONG m_SpeakerSelectedFormat; + PSIDEBANDAUDIO_SUPPORTED_FORMATS m_pMicSupportedFormatsIntersection; + ULONG m_MicSelectedFormat; + + USBHSDEVICE_EP_TRANSPORT_RESOURCES m_SpeakerTransportResources; + USBHSDEVICE_EP_TRANSPORT_RESOURCES m_MicTransportResources; + + // + // Set to TRUE when the HF (remote device) wants to disable the + // NR + EC of the AG (local system). + // + + WDFREQUEST m_SpeakerStreamReq; + WDFREQUEST m_MicStreamReq; + WDFREQUEST m_SpeakerVolumeReq; + WDFREQUEST m_MicVolumeReq; + WDFREQUEST m_SpeakerMuteReq; + WDFREQUEST m_MicMuteReq; + WDFWORKITEM m_WorkItem; + WDFCOLLECTION m_ReqCollection; + KSPIN_LOCK m_Lock; + + LONG m_nSpeakerStreamsOpen; // # of open streams. + LONG m_nMicStreamsOpen; // # of open streams. + + LONG m_nSpeakerStreamsStart; // # of Started streams. + LONG m_nMicStreamsStart; // # of Started streams. + + UsbHsEventCallback m_SpeakerVolumeCallback; + UsbHsEventCallback m_MicVolumeCallback; + + UsbHsEventCallback m_SpeakerMuteCallback; + UsbHsEventCallback m_MicMuteCallback; + + UsbHsEventCallback m_SpeakerConnectionStatusCallback; + UsbHsEventCallback m_MicConnectionStatusCallback; + + UsbHsEventCallback m_SpeakerFormatChangeCallback; + UsbHsEventCallback m_MicFormatChangeCallback; + + public: + //===================================================================== + // Default CUnknown + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(UsbHsDevice); + ~UsbHsDevice(); + + NTSTATUS Init + ( + _In_ IAdapterCommon * Adapter, + _In_ PUNICODE_STRING SymbolicLinkName + ); + + public: + //===================================================================== + // + // Public functions used by CAdapterCommon object. + // + VOID Start(); + VOID Stop(); + + PLIST_ENTRY GetListEntry() + { + return &m_ListEntry; + } + + PUNICODE_STRING GetSymbolicLinkName() + { + return &m_SymbolicLinkName; + } + + static + UsbHsDevice * + GetUsbHsDevice + ( + _In_ PLIST_ENTRY le + ) + { + return CONTAINING_RECORD(le, UsbHsDevice, m_ListEntry); + } + + public: + //===================================================================== + // + // ISidebandDeviceCommon functions. + // + STDMETHODIMP_(BOOL) IsVolumeSupported + ( + _In_ eDeviceType deviceType + ); + + STDMETHODIMP_(PVOID) GetVolumeSettings + ( + _In_ eDeviceType deviceType, + _Out_ PULONG Size + ); + + STDMETHODIMP_(NTSTATUS) GetVolume + ( + _In_ eDeviceType deviceType, + _In_ LONG Channel, + _Out_ LONG *pVolume + ); + + STDMETHODIMP_(NTSTATUS) SetVolume + ( + _In_ eDeviceType deviceType, + _In_ LONG Channel, + _In_ LONG Volume + ); + + STDMETHODIMP_(BOOL) IsMuteSupported + ( + _In_ eDeviceType deviceType + ); + + STDMETHODIMP_(PVOID) GetMuteSettings + ( + _In_ eDeviceType deviceType, + _Out_ PULONG Size + ); + + STDMETHODIMP_(LONG) GetMute + ( + _In_ eDeviceType deviceType, + _In_ LONG Channel + ); + + STDMETHODIMP_(NTSTATUS) SetMute + ( + _In_ eDeviceType deviceType, + _In_ LONG Channel, + _In_ LONG Mute + ); + + STDMETHODIMP_(BOOL) GetConnectionStatus(); + + STDMETHODIMP_(NTSTATUS) Connect(); + + STDMETHODIMP_(NTSTATUS) Disconnect(); + + STDMETHODIMP_(BOOL) GetStreamStatus(_In_ eDeviceType deviceType); + + STDMETHODIMP_(NTSTATUS) StreamOpen(_In_ eDeviceType deviceType); + + STDMETHODIMP_(NTSTATUS) StreamStart(_In_ eDeviceType deviceType); + + STDMETHODIMP_(NTSTATUS) StreamSuspend(_In_ eDeviceType deviceType); + + STDMETHODIMP_(NTSTATUS) StreamClose(_In_ eDeviceType deviceType); + + STDMETHODIMP_(GUID) GetContainerId(_In_ eDeviceType deviceType); + + STDMETHODIMP_(VOID) SetVolumeHandler + ( + _In_ eDeviceType deviceType, + _In_opt_ PFNEVENTNOTIFICATION EventHandler, + _In_opt_ PVOID EventHandlerContext + ); + + STDMETHODIMP_(VOID) SetMuteHandler + ( + _In_ eDeviceType deviceType, + _In_opt_ PFNEVENTNOTIFICATION EventHandler, + _In_opt_ PVOID EventHandlerContext + ); + + STDMETHODIMP_(VOID) SetConnectionStatusHandler + ( + _In_ eDeviceType deviceType, + _In_opt_ PFNEVENTNOTIFICATION EventHandler, + _In_opt_ PVOID EventHandlerContext + ); + + STDMETHODIMP_(VOID) SetFormatChangeHandler + ( + _In_ eDeviceType deviceType, + _In_opt_ PFNEVENTNOTIFICATION EventHandler, + _In_opt_ PVOID EventHandlerContext + ); + + STDMETHODIMP_(PPIN_DEVICE_FORMATS_AND_MODES) GetFormatsAndModes + ( + _In_ eDeviceType deviceType + ); + + STDMETHODIMP_(BOOL) IsNRECSupported(); + + STDMETHODIMP_(BOOL) GetNRECDisableStatus(); + + private: + //===================================================================== + // + // Helper functions. + // + NTSTATUS SendIoCtrlSynchronously + ( + _In_opt_ WDFREQUEST Request, + _In_ ULONG IoControlCode, + _In_ ULONG InLength, + _In_ ULONG OutLength, + _When_(InLength > 0 || OutLength > 0, _In_) + _When_(InLength == 0 && OutLength == 0, _In_opt_) + PVOID Buffer + ); + + NTSTATUS SendIoCtrlSynchronously + ( + _In_opt_ WDFREQUEST Request, + _In_ ULONG IoControlCode, + _In_ ULONG InLength, + _In_ ULONG OutLength, + _When_(InLength > 0, _In_) + _When_(InLength == 0, _In_opt_) + PVOID InBuffer, + _When_(OutLength > 0, _In_) + _When_(OutLength == 0, _In_opt_) + PVOID OutBuffer + ); + + NTSTATUS SendIoCtrlAsynchronously + ( + _In_ WDFREQUEST Request, + _In_ ULONG IoControlCode, + _In_opt_ WDFMEMORY MemIn, + _In_opt_ WDFMEMORY MemOut, + _In_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine, + _In_ WDFCONTEXT Context + ); + + NTSTATUS GetUsbHsDescriptor + ( + _Out_ PSIDEBANDAUDIO_DEVICE_DESCRIPTOR *Descriptor + ); + + NTSTATUS GetUsbHsEndpointDescriptor + ( + _In_ ULONG EpIndex, + _Out_ PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR *EpDescriptor + ); + + NTSTATUS GetUsbHsVolumePropertyValues + ( + _In_ ULONG EpIndex, + _In_ ULONG Length, + _Out_ PKSPROPERTY_DESCRIPTION *PropValues + ); + + NTSTATUS SetUsbHsSpeakerVolume + ( + _In_ LONG Channel, + _In_ LONG Volume + ); + + NTSTATUS GetUsbHsSpeakerVolume + ( + _In_ LONG Channel, + _Out_ LONG *Volume + ); + + NTSTATUS EnableUsbHsSpeakerVolumeStatusNotification(); + + NTSTATUS SetUsbHsMicVolume + ( + _In_ LONG Channel, + _In_ LONG Volume + ); + + NTSTATUS GetUsbHsMicVolume + ( + _In_ LONG Channel, + _Out_ LONG * Volume + ); + + NTSTATUS EnableUsbHsMicVolumeStatusNotification(); + + NTSTATUS GetUsbHsMutePropertyValues + ( + _In_ ULONG EpIndex, + _Out_ PULONG pLength, + _Out_ PKSPROPERTY_DESCRIPTION *PropValues + ); + + NTSTATUS SetUsbHsSpeakerMute + ( + _In_ LONG Channel, + _In_ LONG Mute + ); + + NTSTATUS GetUsbHsSpeakerMute + ( + _In_ LONG Channel, + _Out_ LONG *Mute + ); + + NTSTATUS EnableUsbHsSpeakerMuteStatusNotification(); + + NTSTATUS SetUsbHsMicMute + ( + _In_ LONG Channel, + _In_ LONG Mute + ); + + NTSTATUS GetUsbHsMicMute + ( + _In_ LONG Channel, + _Out_ LONG *Mute + ); + + NTSTATUS EnableUsbHsMicMuteStatusNotification(); + + NTSTATUS GetUsbHsEndpointFormatsIntersection + ( + _In_ PSIDEBANDAUDIO_SUPPORTED_FORMATS pDeviceFormats, + _Out_ PSIDEBANDAUDIO_SUPPORTED_FORMATS *ppSupportedFormatsIntersection + ); + + NTSTATUS VerifyEndpointFormatCompatibility + ( + _In_ PSIDEBANDAUDIO_SUPPORTED_FORMATS EpSupportedFormats, + _In_ PKSDATAFORMAT_WAVEFORMATEXTENSIBLE pHardwareSupportedFormats, + _In_ ULONG NumHardwareSupportedFormats, + _Out_ PULONG pHardwareFormatIndex + ); + + NTSTATUS FreeTransportResources + ( + _In_ PUSBHSDEVICE_EP_TRANSPORT_RESOURCES pTransportResources + ); + + NTSTATUS GetTransportResources + ( + _In_ ULONG EpIndex, + _In_ PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR pEndpointDescriptor, + _Out_ PUSBHSDEVICE_EP_TRANSPORT_RESOURCES pTransportResources + ); + + NTSTATUS SetTransportResources + ( + _In_ PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR pEndpointDescriptor, + _In_ ULONG EpIndex + ); + + NTSTATUS GetSiop + ( + _In_ ULONG EpIndex, + _In_ ULONG SiopTypeId, + _In_ ULONG PoolTag, + _Out_ PBYTE *ppOutputBuffer + ); + + static + NTSTATUS CreateCustomEndpointMinipair + ( + _In_ PENDPOINT_MINIPAIR pBaseMinipair, + _In_ PUNICODE_STRING FriendlyName, + _In_ PGUID pCategory, + _Outptr_ PENDPOINT_MINIPAIR *ppCustomMinipair + ); + + static + NTSTATUS UpdateCustomEndpointCategory + ( + _In_ PPCFILTER_DESCRIPTOR pCustomMinipairTopoFilter, + _In_ PPCPIN_DESCRIPTOR pCustomMinipairTopoPins, + _In_ PGUID pCategory + ); + + static + VOID DeleteCustomEndpointMinipair + ( + _In_ PENDPOINT_MINIPAIR CustomMinipair + ); + + NTSTATUS SetSidebandClaimed(_In_ BOOL bClaimed); + + NTSTATUS SpeakerStreamOpen(); + + NTSTATUS MicStreamOpen(); + + NTSTATUS SpeakerStreamStart(); + + NTSTATUS MicStreamStart(); + + NTSTATUS SpeakerStreamSuspend(); + + NTSTATUS MicStreamSuspend(); + + NTSTATUS SpeakerStreamClose(); + + NTSTATUS MicStreamClose(); + + NTSTATUS SetUsbHsStreamOpen(ULONG EpIndex, PKSDATAFORMAT_WAVEFORMATEXTENSIBLE pStreamFormat, PSIDEBANDAUDIO_ENDPOINT_DESCRIPTOR pEndpointDescriptor); + + NTSTATUS SetUsbHsStreamStart(ULONG EpIndex); + + NTSTATUS SetUsbHsStreamSuspend(ULONG EpIndex); + + NTSTATUS SetUsbHsStreamClose(ULONG EpIndex); + + NTSTATUS EnableUsbHsSpeakerStreamStatusNotification(); + + NTSTATUS StopUsbHsSpeakerStreamStatusNotification(); + + NTSTATUS EnableUsbHsMicStreamStatusNotification(); + + NTSTATUS StopUsbHsMicStreamStatusNotification(); + + NTSTATUS CreateFilterNames( + _In_ PUNICODE_STRING UsbHsDeviceSymbolicLinkName + ); + + +#if 0 + NTSTATUS GetSpeakerTransportResources(); + NTSTATUS FreeSpeakerTransportResources(); + NTSTATUS GetMicTransportResources(); + NTSTATUS FreeMicTransportResources(); +#endif + + // + // WDF I/O Target callback. + // + static + EVT_WDF_IO_TARGET_QUERY_REMOVE EvtUsbHsTargetQueryRemove; + + static + EVT_WDF_IO_TARGET_REMOVE_CANCELED EvtUsbHsTargetRemoveCanceled; + + static + EVT_WDF_IO_TARGET_REMOVE_COMPLETE EvtUsbHsTargetRemoveComplete; + + // + // Status notifications callbacks. + // + static + EVT_WDF_REQUEST_COMPLETION_ROUTINE EvtUsbHsDeviceStreamStatusCompletion; + + static + EVT_WDF_REQUEST_COMPLETION_ROUTINE EvtUsbHsDeviceNotificationStatusCompletion; + + static + EVT_WDF_WORKITEM EvtUsbHsDeviceNotificationStatusWorkItem; +}; diff --git a/audio/sysvad/adapter.cpp b/audio/sysvad/adapter.cpp index ab91a448..166b2283 100644 --- a/audio/sysvad/adapter.cpp +++ b/audio/sysvad/adapter.cpp @@ -29,6 +29,9 @@ Abstract: #ifdef SYSVAD_BTH_BYPASS #include "bthhfpminipairs.h" #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND +#include "usbhsminipairs.h" +#endif // SYSVAD_USB_SIDEBAND @@ -257,6 +260,15 @@ UNICODE_STRING g_RegistryPath; // This is used to store the registry settin DWORD g_DisableBthScoBypass = 0; // default is SCO bypass enabled. #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND +// +// This driver listens for arrival/removal of the USB Sideband interfaces by +// default. Use the registry value DisableUsbSideband (DWORD) > 0 to override +// this default. +// +DWORD g_DisableUsbSideband = 0; // default is USB bypass enabled. +#endif // SYSVAD_USB_SIDEBAND + //----------------------------------------------------------------------------- // Functions //----------------------------------------------------------------------------- @@ -409,6 +421,9 @@ Returns: #ifdef SYSVAD_BTH_BYPASS { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DisableBthScoBypass", &g_DisableBthScoBypass, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DisableBthScoBypass, sizeof(ULONG)}, #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DisableUsbSideband", &g_DisableUsbSideband, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DisableUsbSideband, sizeof(ULONG)}, +#endif // SYSVAD_USB_SIDEBAND { NULL, 0, NULL, NULL, 0, NULL, 0} }; @@ -456,6 +471,9 @@ Returns: #ifdef SYSVAD_BTH_BYPASS DPF(D_VERBOSE, ("DisableBthScoBypass: %u", g_DisableBthScoBypass)); #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + DPF(D_VERBOSE, ("DisableUsbSideband: %u", g_DisableUsbSideband)); +#endif // SYSVAD_USB_SIDEBAND // // Cleanup. @@ -635,7 +653,9 @@ Return Value: // maxObjects += g_MaxBthHfpMiniports; #endif // SYSVAD_BTH_BYPASS - +#ifdef SYSVAD_USB_SIDEBAND + maxObjects += g_MaxUsbHsMiniports; +#endif // SYSVAD_USB_SIDEBAND // Tell the class driver to add the device. // @@ -1073,6 +1093,16 @@ Return Value: IF_FAILED_JUMP(ntStatus, Exit); } #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + if (!g_DisableUsbSideband) + { + // + // Init infrastructure for USB Sideband devices. + // + ntStatus = pAdapterCommon->InitUsbSideband(); + IF_FAILED_JUMP(ntStatus, Exit); + } +#endif // SYSVAD_USB_SIDEBAND #ifdef _USE_SingleComponentMultiFxStates // @@ -1147,11 +1177,39 @@ Return Value: // stack = IoGetCurrentIrpStackLocation(_Irp); - - if ((IRP_MN_REMOVE_DEVICE == stack->MinorFunction) || - (IRP_MN_SURPRISE_REMOVAL == stack->MinorFunction) || - (IRP_MN_STOP_DEVICE == stack->MinorFunction)) + switch (stack->MinorFunction) { + + case IRP_MN_QUERY_DEVICE_RELATIONS: + + switch (stack->Parameters.QueryDeviceRelations.Type) + { + case PowerRelations: + + ext = static_cast(_DeviceObject->DeviceExtension); + + if (ext->m_pCommon != NULL) + { + ntStatus = ext->m_pCommon->UpdatePowerRelations(_Irp); + if (!NT_SUCCESS(ntStatus)) + { + // Complete the Irp with failure, no need to further process in PortCls + _Irp->IoStatus.Status = ntStatus; + IoCompleteRequest(_Irp, IO_NO_INCREMENT); + return ntStatus; + } + } + + break; + + default: + break; + } + break; + + case IRP_MN_REMOVE_DEVICE: + case IRP_MN_SURPRISE_REMOVAL: + case IRP_MN_STOP_DEVICE: ext = static_cast(_DeviceObject->DeviceExtension); if (ext->m_pCommon != NULL) @@ -1161,6 +1219,10 @@ Return Value: ext->m_pCommon->Release(); ext->m_pCommon = NULL; } + break; + + default: + break; } ntStatus = PcDispatchIrp(_DeviceObject, _Irp); diff --git a/audio/sysvad/common.cpp b/audio/sysvad/common.cpp index a0e148ca..bccef495 100644 --- a/audio/sysvad/common.cpp +++ b/audio/sysvad/common.cpp @@ -30,6 +30,15 @@ Abstract: #include "BthhfpDevice.h" #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND +#include +#include +#include +#include +#include "UsbHsMinipairs.h" +#include "UsbHsDevice.h" +#endif // SYSVAD_USB_SIDEBAND + //----------------------------------------------------------------------------- // CSaveData statics //----------------------------------------------------------------------------- @@ -43,6 +52,10 @@ PDEVICE_OBJECT CSaveData::m_pDeviceObject = NULL; class BthHfpDevice; // Forward declaration. #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND +class UsbHsDevice; // Forward declaration. +#endif // SYSVAD_USB_SIDEBAND + /////////////////////////////////////////////////////////////////////////////// // CAdapterCommon // @@ -65,6 +78,16 @@ class CAdapterCommon : DWORD m_dwIdleRequests; +#ifdef SYSVAD_USB_SIDEBAND + typedef struct _SysvadPowerRelationsDo + { + LIST_ENTRY ListEntry; + PDEVICE_OBJECT Pdo; + }SysVadPowerRelationsDo, *PSysVadPowerRelationsDo; + LIST_ENTRY m_PowerRelations; + FAST_MUTEX m_PowerRelationsLock; +#endif//SYSVAD_USB_SIDEBAND + public: //===================================================================== // Default CUnknown @@ -258,7 +281,25 @@ class CAdapterCommon : STDMETHODIMP_(VOID) CleanupBthScoBypass(); #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + STDMETHODIMP_(NTSTATUS) InitUsbSideband(); + + STDMETHODIMP_(VOID) CleanupUsbSideband(); + + STDMETHODIMP_(NTSTATUS) AddDeviceAsPowerDependency + ( + _In_ PDEVICE_OBJECT pdo + ); + + STDMETHODIMP_(NTSTATUS) RemoveDeviceAsPowerDependency + ( + _In_ PDEVICE_OBJECT pdo + ); +#endif // SYSVAD_USB_SIDEBAND + STDMETHODIMP_(VOID) Cleanup(); + + STDMETHODIMP_(NTSTATUS) UpdatePowerRelations(_In_ PIRP Irp); //===================================================================== // friends @@ -311,6 +352,45 @@ class CAdapterCommon : ); #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + //===================================================================== + // USB Sideband Audio support. + + private: + PVOID m_UsbSidebandNotificationHandle; + FAST_MUTEX m_UsbSidebandFastMutex; // To serialize access. + WDFWORKITEM m_UsbSidebandWorkItem; // Async work-item. + LIST_ENTRY m_UsbSidebandWorkTasks; // Work-item's tasks. + LIST_ENTRY m_UsbSidebandDevices; // USB Sideband devices. + NPAGED_LOOKASIDE_LIST m_UsbSidebandWorkTaskPool; // LookasideList + size_t m_UsbSidebandWorkTaskPoolElementSize; + BOOL m_UsbSidebandEnableCleanup; // Do cleanup if true. + + private: + static + DRIVER_NOTIFICATION_CALLBACK_ROUTINE EvtUsbSidebandInterfaceChange; + + static + EVT_WDF_WORKITEM EvtUsbSidebandInterfaceWorkItem; + + protected: + UsbHsDevice * UsbSidebandDeviceFind + ( + _In_ PUNICODE_STRING SymbolicLinkName + ); + + NTSTATUS UsbSidebandInterfaceArrival + ( + _In_ PUNICODE_STRING SymbolicLinkName + ); + + NTSTATUS UsbSidebandInterfaceRemoval + ( + _In_ PUNICODE_STRING SymbolicLinkName + ); + +#endif // SYSVAD_USB_SIDEBAND + private: LIST_ENTRY m_SubdeviceCache; @@ -524,6 +604,7 @@ Return Value: InterlockedDecrement(&CAdapterCommon::m_AdapterInstances); ASSERT(CAdapterCommon::m_AdapterInstances == 0); + ASSERT(IsListEmpty(&m_PowerRelations)); } // ~CAdapterCommon //============================================================================= @@ -640,6 +721,10 @@ Return Value: m_BthHfpEnableCleanup = FALSE; #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + m_UsbSidebandEnableCleanup = FALSE; +#endif // SYSVAD_USB_SIDEBAND + m_pServiceGroupWave = NULL; m_pDeviceObject = DeviceObject; m_pPhysicalDeviceObject = NULL; @@ -650,6 +735,11 @@ Return Value: InitializeListHead(&m_SubdeviceCache); +#ifdef SYSVAD_USB_SIDEBAND + InitializeListHead(&m_PowerRelations); + ExInitializeFastMutex(&m_PowerRelationsLock); +#endif//SYSVAD_USB_SIDEBAND + // // Get the PDO. // @@ -2193,9 +2283,143 @@ CAdapterCommon::Cleanup() CleanupBthScoBypass(); #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + // + // This ensures USB Sideband notifications are turned off when port class + // cleanups and unregisters the static subdevices. + // + CleanupUsbSideband(); +#endif // SYSVAD_USB_SIDEBAND + EmptySubdeviceCache(); } +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CAdapterCommon::UpdatePowerRelations(_In_ PIRP Irp) +{ + PDEVICE_RELATIONS priorRelations = NULL; + PDEVICE_RELATIONS newRelations = NULL; + ULONG qprPdosCount = 0; + ULONG count = 0; + size_t size; + NTSTATUS status = STATUS_SUCCESS; + ULONG i = 0; + PLIST_ENTRY pe = NULL; + + ExAcquireFastMutex(&m_PowerRelationsLock); + + pe = m_PowerRelations.Flink; + while (pe != &m_PowerRelations) + { + pe = pe->Flink; + qprPdosCount++; + } + + if (0 == qprPdosCount) + { + DPF(D_ERROR, ("CAdapterCommon::UpdatePowerRelations: No PDOs in power relations")); + // Not an error. Just nothing to do. + newRelations = (PDEVICE_RELATIONS)(Irp->IoStatus.Information); + goto Exit; + } + + count = qprPdosCount; + + priorRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information; + if (priorRelations != NULL) + { + // + // Another driver in the stack may have added some entries. + // Make sure we allocate space for these additional entries. + // + count = priorRelations->Count + count; + } + + // + // Allocate space for the DEVICE_RELATIONS structure (which includes + // space for one PDEVICE_OBJECT, and then allocate enough additional + // space for the extra PDEVICE_OBJECTs we need. + // + size = sizeof(DEVICE_RELATIONS) + (count - 1) * sizeof(PDEVICE_OBJECT); + newRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, size, USBSIDEBANDTEST_POOLTAG015); + ASSERT(newRelations); + if (NULL == newRelations) + { + status = STATUS_INSUFFICIENT_RESOURCES; + DPF(D_ERROR, ("CAdapterCommon::UpdatePowerRelations: could not allocate memory")); + goto Exit; + } + + // + // If there was an existing device relations structure, copy + // the entries to the new structure. + // + RtlZeroMemory(newRelations, size); + if (priorRelations != NULL && priorRelations->Count > 0) + { + size = sizeof(DEVICE_RELATIONS) + (priorRelations->Count - 1) * sizeof(PDEVICE_OBJECT); + RtlCopyMemory(newRelations, priorRelations, size); + } + + // + // Add new relations to the DEVICE_RELATIONS structure. Pnp dictates that + // each PDO in the list be referenced. Pnp manager will deref the PDO. + // + pe = m_PowerRelations.Flink; + while (pe != &m_PowerRelations) + { + PSysVadPowerRelationsDo powerDepDo = CONTAINING_RECORD(pe, SysVadPowerRelationsDo, ListEntry); + pe = pe->Flink; + + newRelations->Objects[newRelations->Count] = powerDepDo->Pdo; + + // Add a reference on the PDO before returning it as a dependency. + // PnP will remove the reference when appropriate as per msdn. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mn-query-device-relations#operation + ObReferenceObject(powerDepDo->Pdo); + + // + // update the count + // + newRelations->Count++; + } + +Exit: + ExReleaseFastMutex(&m_PowerRelationsLock); + + if (!NT_SUCCESS(status)) + { + // + // Dereference any previously reported relations before exiting. They + // are dereferenced here because the PNP manager will see error and not + // do anything while the driver which added these objects expects the + // pnp manager to do the dereference. Since this device is changing the + // status, it must act like the pnp manager. + // + if (priorRelations != NULL) + { + for (i = 0; i < priorRelations->Count; ++i) + { + ObDereferenceObject(priorRelations->Objects[i]); + } + } + + ASSERT(newRelations == NULL); + } + + if (priorRelations != NULL) + { + ExFreePool(priorRelations); + } + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = (ULONG_PTR)newRelations; + + return status; +} + //============================================================================= #pragma code_seg("PAGE") STDMETHODIMP_(NTSTATUS) @@ -3149,6 +3373,684 @@ Routine Description: } #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND +// +// CAdapterCommon USB Sideband function implementation. +// + +//============================================================================= +#pragma code_seg("PAGE") +VOID +CAdapterCommon::EvtUsbSidebandInterfaceWorkItem +( + _In_ WDFWORKITEM WorkItem +) +/*++ + +Routine Description: + +The function handles the arrival or removal of a USB Sideband interface. + +Arguments: + +WorkItem - WDF work-item object. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[EvtUsbSidebandInterfaceWorkItem]")); + + CAdapterCommon * This; + + if (WorkItem == NULL) + { + return; + } + + This = GetUsbHsWorkItemContext(WorkItem)->Adapter; + ASSERT(This != NULL); + + for (;;) + { + PLIST_ENTRY le = NULL; + UsbHsWorkTask * task = NULL; + + // + // Retrieve a taask. + // + ExAcquireFastMutex(&This->m_UsbSidebandFastMutex); + if (!IsListEmpty(&This->m_UsbSidebandWorkTasks)) + { + le = RemoveHeadList(&This->m_UsbSidebandWorkTasks); + task = CONTAINING_RECORD(le, UsbHsWorkTask, ListEntry); + InitializeListHead(le); + } + ExReleaseFastMutex(&This->m_UsbSidebandFastMutex); + + if (task == NULL) + { + break; + } + + ASSERT(task->Device != NULL); + _Analysis_assume_(task->Device != NULL); + + // + // Process the task. + // + switch (task->Action) + { + case eUsbHsTaskStart: + task->Device->Start(); + break; + + case eUsbHsTaskStop: + task->Device->Stop(); + break; + + default: + DPF(D_ERROR, ("EvtUsbSidebandInterfaceWorkItem: invalid action %d", task->Action)); + break; + } + + // + // Release the ref we took on the device when we inserted the task in the queue. + // For a stop operation this may be the last reference. + // + SAFE_RELEASE(task->Device); + + // + // Free the task. + // + ExFreeToNPagedLookasideList(&This->m_UsbSidebandWorkTaskPool, task); + } +} + +//============================================================================= +#pragma code_seg("PAGE") +UsbHsDevice * +CAdapterCommon::UsbSidebandDeviceFind +( + _In_ PUNICODE_STRING SymbolicLinkName +) +/*++ + +Routine Description: + +The function looks for the specified device in the adapter's list. + +Arguments: + +SymbolicLinkName - interface's symbolic link. + +Return Value: + +UsbSidebandDevice pointer or NULL. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[CAdapterCommon::UsbSidebandDeviceFind]")); + + PLIST_ENTRY le = NULL; + UsbHsDevice * usbDevice = NULL; + + ExAcquireFastMutex(&m_UsbSidebandFastMutex); + + for (le = m_UsbSidebandDevices.Flink; le != &m_UsbSidebandDevices; le = le->Flink) + { + UsbHsDevice * tmpUsbHsDevice = UsbHsDevice::GetUsbHsDevice(le); + ASSERT(tmpUsbHsDevice != NULL); + + PUNICODE_STRING unicodeStr = tmpUsbHsDevice->GetSymbolicLinkName(); + ASSERT(unicodeStr != NULL); + + if (unicodeStr->Length == SymbolicLinkName->Length && + 0 == wcsncmp(unicodeStr->Buffer, SymbolicLinkName->Buffer, unicodeStr->Length / sizeof(WCHAR))) + { + // Found it! + usbDevice = tmpUsbHsDevice; + usbDevice->AddRef(); + break; + } + } + + ExReleaseFastMutex(&m_UsbSidebandFastMutex); + + return usbDevice; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CAdapterCommon::UsbSidebandInterfaceArrival +( + _In_ PUNICODE_STRING SymbolicLinkName +) +/*++ + +Routine Description: + +The function handles the arrival of a new USB Sideband interface. + +Arguments: + +SymbolicLinkName - new interface's symbolic link. + +Return Value: + +NT status code. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[CAdapterCommon::UsbSidebandInterfaceArrival]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDevice *usbHsDevice = NULL; + UsbHsWorkTask *usbHsWorkTask = NULL; + + DPF(D_VERBOSE, ("UsbSidebandInterfaceArrival: SymbolicLinkName %wZ", SymbolicLinkName)); + + // + // Check if the USB device is already present. + // According to the docs it is possible to receive two notifications for the same + // interface. + // + usbHsDevice = UsbSidebandDeviceFind(SymbolicLinkName); + if (usbHsDevice != NULL) + { + DPF(D_VERBOSE, ("UsbSidebandInterfaceArrival: USB device already present")); + SAFE_RELEASE(usbHsDevice); + ntStatus = STATUS_SUCCESS; + goto Done; + } + + // + // Alloc a new structure for this USB device. + // + usbHsDevice = new (NonPagedPoolNx, MINADAPTER_POOLTAG) UsbHsDevice(NULL); // NULL -> OuterUnknown + if (NULL == usbHsDevice) + { + DPF(D_ERROR, ("UsbSidebandInterfaceArrival: unable to allocate UsbSidebandDevice, out of memory")); + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + DPF(D_VERBOSE, ("UsbSidebandInterfaceArrival: created UsbSidebandDevice 0x%p ", usbHsDevice)); + + // + // Basic initialization of the USB Sideband interface. + // The audio miniport creation is done later by the UsbSidebandDevice.Start() + // which is invoked asynchronously by a worker thread. + // UsbSidebandDevice->Init() must be invoked just after the creation of the object. + // + ntStatus = usbHsDevice->Init(this, SymbolicLinkName); + IF_FAILED_JUMP(ntStatus, Done); + + // + // Get and init a work task. + // + usbHsWorkTask = (UsbHsWorkTask*)ExAllocateFromNPagedLookasideList(&m_UsbSidebandWorkTaskPool); + if (NULL == usbHsWorkTask) + { + DPF(D_ERROR, ("UsbSidebandInterfaceArrival: unable to allocate UsbSidebandWorkTask, out of memory")); + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + // usbWorkTask->L.Size is set to sizeof(UsbSidebandWorkTask) in the Look Aside List configuration +#pragma warning(suppress: 6386) + RtlZeroMemory(usbHsWorkTask, sizeof(*usbHsWorkTask)); + usbHsWorkTask->Action = eUsbHsTaskStart; + InitializeListHead(&usbHsWorkTask->ListEntry); + // Note that usbDevice has one reference at this point. + usbHsWorkTask->Device = usbHsDevice; + + ExAcquireFastMutex(&m_UsbSidebandFastMutex); + + // + // Insert this new USB Sideband device in our list. + // + InsertTailList(&m_UsbSidebandDevices, usbHsDevice->GetListEntry()); + + // + // Add a new task for the worker thread. + // + InsertTailList(&m_UsbSidebandWorkTasks, &usbHsWorkTask->ListEntry); + usbHsDevice->AddRef(); // released when task runs. + + // + // Schedule a work-item if not already running. + // + WdfWorkItemEnqueue(m_UsbSidebandWorkItem); + + ExReleaseFastMutex(&m_UsbSidebandFastMutex); + +Done: + if (!NT_SUCCESS(ntStatus)) + { + // Release the last ref, this will delete the UsbSidebandDevice + SAFE_RELEASE(usbHsDevice); + + if (usbHsWorkTask != NULL) + { + ExFreeToNPagedLookasideList(&m_UsbSidebandWorkTaskPool, usbHsWorkTask); + usbHsWorkTask = NULL; + } + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CAdapterCommon::UsbSidebandInterfaceRemoval +( + _In_ PUNICODE_STRING SymbolicLinkName +) +/*++ + +Routine Description: + +The function handles the removal of a USB Sideband interface. + +Arguments: + +SymbolicLinkName - interface's symbolic link to remove. + +Return Value: + +NT status code. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[CAdapterCommon::UsbSidebandInterfaceRemoval]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + UsbHsDevice *usbHsDevice = NULL; + UsbHsWorkTask *usbHsWorkTask = NULL; + + DPF(D_VERBOSE, ("UsbSidebandInterfaceRemoval: SymbolicLinkName %wZ", SymbolicLinkName)); + + // + // Check if the USB device is present. + // + usbHsDevice = UsbSidebandDeviceFind(SymbolicLinkName); + if (usbHsDevice == NULL) + { + // This can happen if the init/start of the UsbSidebandDevice failed. + DPF(D_VERBOSE, ("UsbSidebandInterfaceRemoval: USB device not found")); + ntStatus = STATUS_SUCCESS; + goto Done; + } + + // + // Init a work task. + // + usbHsWorkTask = (UsbHsWorkTask*)ExAllocateFromNPagedLookasideList(&m_UsbSidebandWorkTaskPool); + if (NULL == usbHsWorkTask) + { + DPF(D_ERROR, ("UsbSidebandInterfaceRemoval: unable to allocate UsbSidebandWorkTask, out of memory")); + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + // usbWorkTask->L.Size is set to sizeof(UsbSidebandWorkTask) in the Look Aside List configuration +#pragma warning(suppress: 6386) + RtlZeroMemory(usbHsWorkTask, sizeof(*usbHsWorkTask)); + usbHsWorkTask->Action = eUsbHsTaskStop; + InitializeListHead(&usbHsWorkTask->ListEntry); + // Work-item callback will release the reference we got above from UsbSidebandDeviceFind. + usbHsWorkTask->Device = usbHsDevice; + + ExAcquireFastMutex(&m_UsbSidebandFastMutex); + + // + // Remove this USB device from our list and release the associated reference. + // + RemoveEntryList(usbHsDevice->GetListEntry()); + InitializeListHead(usbHsDevice->GetListEntry()); + usbHsDevice->Release(); // This is not the last ref. + + // + // Add a new task for the worker thread. + // + InsertTailList(&m_UsbSidebandWorkTasks, &usbHsWorkTask->ListEntry); + + // + // Schedule a work-item if not already running. + // + WdfWorkItemEnqueue(m_UsbSidebandWorkItem); + + ExReleaseFastMutex(&m_UsbSidebandFastMutex); + + // + // All done. + // + ntStatus = STATUS_SUCCESS; + +Done: + + if (!NT_SUCCESS(ntStatus)) + { + // Release the ref we got in find. + SAFE_RELEASE(usbHsDevice); + } + + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CAdapterCommon::EvtUsbSidebandInterfaceChange( + _In_ PVOID NotificationPointer, + _Inout_opt_ PVOID Context +) +/*++ + +Routine Description: + +This callback is invoked when a new USB Sideband interface is added or removed. + +Arguments: +NotificationPointer - Interface change notification +Context - CAdapterCommon ptr. + +Return Value: + +NT status code. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[EvtUsbSidebandInterfaceChange]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + CAdapterCommon * This = NULL; + PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationPointer; + + // + // Make sure this is the interface class we extect. Any other class guid + // is an error, but let it go since it is not fatal to the machine. + // + if (!IsEqualGUID(Notification->InterfaceClassGuid, GUID_DEVINTERFACE_USB_SIDEBAND_AUDIO_HS_HCIBYPASS)) + { + DPF(D_VERBOSE, ("EvtUsbSidebandInterfaceChange: bad interface ClassGuid")); + ASSERTMSG("EvtUsbSidebandInterfaceChange: bad interface ClassGuid ", FALSE); + + goto Done; + } + + This = (CAdapterCommon *)Context; + ASSERT(This != NULL); + _Analysis_assume_(This != NULL); + + // + // Take action based on the event. Any other event type is an error, + // but let it go since it is not fatal to the machine. + // + if (IsEqualGUID(Notification->Event, GUID_DEVICE_INTERFACE_ARRIVAL)) + { + ntStatus = This->UsbSidebandInterfaceArrival(Notification->SymbolicLinkName); + } + else if (IsEqualGUID(Notification->Event, GUID_DEVICE_INTERFACE_REMOVAL)) + { + ntStatus = This->UsbSidebandInterfaceRemoval(Notification->SymbolicLinkName); + } + else + { + DPF(D_VERBOSE, ("EvtUsbSidebandInterfaceChange: bad " + "GUID_DEVINTERFACE_USB_SIDEBAND_AUDIO_HCIBYPASS event")); + ASSERTMSG("EvtUsbSidebandInterfaceChange: bad " + "GUID_DEVINTERFACE_USB_SIDEBAND_AUDIO_HCIBYPASS event ", FALSE); + + goto Done; + } + +Done: + return ntStatus; +} + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CAdapterCommon::InitUsbSideband() +/*++ + +Routine Description: + +Initialize the USB Sideband environment. + +Return Value: + +NT status code. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[CAdapterCommon::InitUsbSideband]")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + WDF_WORKITEM_CONFIG wiConfig; + WDF_OBJECT_ATTRIBUTES attributes; + UsbHsWorkItemContext * wiContext; + + // + // Init spin-lock, linked lists, work-item, event, etc. + // Init all members to default values. This basic init should not fail. + // + m_UsbSidebandWorkItem = NULL; + m_UsbSidebandNotificationHandle = NULL; + ExInitializeFastMutex(&m_UsbSidebandFastMutex); + InitializeListHead(&m_UsbSidebandWorkTasks); + InitializeListHead(&m_UsbSidebandDevices); + m_UsbSidebandWorkTaskPoolElementSize = sizeof(UsbHsWorkTask); + ExInitializeNPagedLookasideList(&m_UsbSidebandWorkTaskPool, + NULL, + NULL, + POOL_NX_ALLOCATION, + m_UsbSidebandWorkTaskPoolElementSize, + MINADAPTER_POOLTAG, + 0); + // + // Enable USB Sideband Cleanup. + // Do any allocation/initialization that can fail after this point. + // + m_UsbSidebandEnableCleanup = TRUE; + + // + // Allocate a WDF work-item. + // + WDF_WORKITEM_CONFIG_INIT(&wiConfig, EvtUsbSidebandInterfaceWorkItem); + wiConfig.AutomaticSerialization = FALSE; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, UsbHsWorkItemContext); + attributes.ParentObject = GetWdfDevice(); + ntStatus = WdfWorkItemCreate(&wiConfig, + &attributes, + &m_UsbSidebandWorkItem); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("InitUsbSideband: WdfWorkItemCreate failed: 0x%x", ntStatus)), + Done); + + wiContext = GetUsbHsWorkItemContext(m_UsbSidebandWorkItem); + wiContext->Adapter = this; // weak ref. + + // + // Register for USB Sideband interface changes. + // + ntStatus = IoRegisterPlugPlayNotification( + EventCategoryDeviceInterfaceChange, + PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, + (PVOID)&GUID_DEVINTERFACE_USB_SIDEBAND_AUDIO_HS_HCIBYPASS, + m_pDeviceObject->DriverObject, + EvtUsbSidebandInterfaceChange, + (PVOID)this, + &m_UsbSidebandNotificationHandle); + + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("InitUsbSideband: IoRegisterPlugPlayNotification(GUID_DEVINTERFACE_USB_SIDEBAND_AUDIO_HCIBYPASS) failed: 0x%x", ntStatus)), + Done); + + // + // Initialization completed. + // + ntStatus = STATUS_SUCCESS; + +Done: + return ntStatus; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +CAdapterCommon::AddDeviceAsPowerDependency +( + _In_ PDEVICE_OBJECT pdo +) +{ + NTSTATUS status = STATUS_SUCCESS; + + // allocate SysVadPowerRelationsDo + PSysVadPowerRelationsDo powerDepDo = (PSysVadPowerRelationsDo)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SysVadPowerRelationsDo), USBSIDEBANDTEST_POOLTAG014); + if (NULL == powerDepDo) + { + status = STATUS_INSUFFICIENT_RESOURCES; + DPF(D_ERROR, ("CAdapterCommon::AddDeviceAsPowerDependency could not allocate memory for list entry")); + goto exit; + } + + InitializeListHead(&powerDepDo->ListEntry); + powerDepDo->Pdo = pdo; + ObReferenceObject(pdo); + + // Add to list + ExAcquireFastMutex(&m_PowerRelationsLock); + + InsertTailList(&m_PowerRelations, &powerDepDo->ListEntry); + + ExReleaseFastMutex(&m_PowerRelationsLock); + + IoInvalidateDeviceRelations(m_pPhysicalDeviceObject, PowerRelations); + +exit: + return status; +} + +//============================================================================= +#pragma code_seg() +NTSTATUS +CAdapterCommon::RemoveDeviceAsPowerDependency +( + _In_ PDEVICE_OBJECT pdo +) +{ + NTSTATUS status = STATUS_SUCCESS; + + // Find in list + ExAcquireFastMutex(&m_PowerRelationsLock); + + PLIST_ENTRY pe = m_PowerRelations.Flink; + while (pe != &m_PowerRelations) + { + PSysVadPowerRelationsDo powerDepDo = CONTAINING_RECORD(pe, SysVadPowerRelationsDo, ListEntry); + pe = pe->Flink; + + if (powerDepDo->Pdo == pdo) + { + ObDereferenceObject(powerDepDo->Pdo); + RemoveEntryList(&powerDepDo->ListEntry); + ExFreePoolWithTag(powerDepDo, USBSIDEBANDTEST_POOLTAG014); + } + } + + ExReleaseFastMutex(&m_PowerRelationsLock); + + IoInvalidateDeviceRelations(m_pPhysicalDeviceObject, PowerRelations); + + return status; +} + +//============================================================================= +#pragma code_seg("PAGE") +VOID +CAdapterCommon::CleanupUsbSideband() +/*++ + +Routine Description: + +Cleanup the USB Sideband environment. + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[CAdapterCommon::CleanupUsbSideband]")); + + // + // Do nothing if USB Sideband environment was not correctly initialized. + // + if (m_UsbSidebandEnableCleanup == FALSE) + { + return; + } + + // + // Unregister for USB Sideband interface changes. + // + if (m_UsbSidebandNotificationHandle != NULL) + { + (void)IoUnregisterPlugPlayNotificationEx(m_UsbSidebandNotificationHandle); + m_UsbSidebandNotificationHandle = NULL; + } + + // + // Wait for the USB Sideband worker thread to be done. + // + if (m_UsbSidebandWorkItem != NULL) + { + WdfWorkItemFlush(m_UsbSidebandWorkItem); + WdfObjectDelete(m_UsbSidebandWorkItem); + m_UsbSidebandWorkItem = NULL; + } + + ASSERT(IsListEmpty(&m_UsbSidebandWorkTasks)); + + // + // Stop and delete all UsbSidebandDevices. We are the only thread accessing this list, + // so there is no need to acquire the mutex. + // + while (!IsListEmpty(&m_UsbSidebandDevices)) + { + UsbHsDevice * usbHsDevice = NULL; + PLIST_ENTRY le = NULL; + + le = RemoveHeadList(&m_UsbSidebandDevices); + + usbHsDevice = UsbHsDevice::GetUsbHsDevice(le); + InitializeListHead(le); + + // usbDevice is invalid after this call. + usbHsDevice->Stop(); + + // This should be the last reference. + usbHsDevice->Release(); + } + + ASSERT(IsListEmpty(&m_UsbSidebandDevices)); + + // + // General cleanup. + // + ExDeleteNPagedLookasideList(&m_UsbSidebandWorkTaskPool); +} +#endif // SYSVAD_USB_SIDEBAND + #pragma code_seg("PAGE") NTSTATUS CopyRegistryValues(HANDLE _hSourceKey, HANDLE _hDestinationKey) diff --git a/audio/sysvad/common.h b/audio/sysvad/common.h index f138c1fb..98a3f9cd 100644 --- a/audio/sysvad/common.h +++ b/audio/sysvad/common.h @@ -120,6 +120,21 @@ Abstract: #define MINWAVERT_POOLTAG 'RWNM' #define MINTOPORT_POOLTAG 'RTNM' #define MINADAPTER_POOLTAG 'uAyS' +#define USBSIDEBANDTEST_POOLTAG01 '1AyS' +#define USBSIDEBANDTEST_POOLTAG02 '2AyS' +#define USBSIDEBANDTEST_POOLTAG03 '3AyS' +#define USBSIDEBANDTEST_POOLTAG04 '4AyS' +#define USBSIDEBANDTEST_POOLTAG05 '5AyS' +#define USBSIDEBANDTEST_POOLTAG06 '6AyS' +#define USBSIDEBANDTEST_POOLTAG07 '7AyS' +#define USBSIDEBANDTEST_POOLTAG08 '8AyS' +#define USBSIDEBANDTEST_POOLTAG09 '9AyS' +#define USBSIDEBANDTEST_POOLTAG010 'aAyS' +#define USBSIDEBANDTEST_POOLTAG011 'bAyS' +#define USBSIDEBANDTEST_POOLTAG012 'cAyS' +#define USBSIDEBANDTEST_POOLTAG013 'dAyS' +#define USBSIDEBANDTEST_POOLTAG014 'eAyS' +#define USBSIDEBANDTEST_POOLTAG015 'fAyS' typedef enum { @@ -637,8 +652,25 @@ DECLARE_INTERFACE_(IAdapterCommon, IUnknown) #endif // SYSVAD_BTH_BYPASS +#ifdef SYSVAD_USB_SIDEBAND + STDMETHOD_(NTSTATUS, InitUsbSideband)(); + + STDMETHOD_(NTSTATUS, AddDeviceAsPowerDependency) + ( + _In_ PDEVICE_OBJECT pdo + ); + + STDMETHOD_(NTSTATUS, RemoveDeviceAsPowerDependency) + ( + _In_ PDEVICE_OBJECT pdo + ); + +#endif // SYSVAD_USB_SIDEBAND + STDMETHOD_(VOID, Cleanup)(); + STDMETHOD_(NTSTATUS, UpdatePowerRelations)(_In_ PIRP Irp); + STDMETHOD_(NTSTATUS, NotifyEndpointPair) ( THIS_ @@ -670,7 +702,7 @@ NewAdapterCommon ); -#if defined(SYSVAD_BTH_BYPASS) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) // Event callback definition. typedef VOID (*PFNEVENTNOTIFICATION)( diff --git a/audio/sysvad/sources.inc b/audio/sysvad/sources.inc index 369014a0..31b879ab 100644 --- a/audio/sysvad/sources.inc +++ b/audio/sysvad/sources.inc @@ -31,5 +31,6 @@ SOURCES=\ ..\kshelper.cpp \ ..\savedata.cpp \ ..\tonegenerator.cpp \ + ..\UsbHsDevice.cpp \ ..\wavereader.cpp \ diff --git a/audio/sysvad/sysvad.sln b/audio/sysvad/sysvad.sln index 6fa08722..d73ed4d6 100644 --- a/audio/sysvad/sysvad.sln +++ b/audio/sysvad/sysvad.sln @@ -37,64 +37,124 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SwapAPO", "APO\SwapAPO\Swap EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM.ActiveCfg = Debug|ARM + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM.Build.0 = Debug|ARM + {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|ARM.ActiveCfg = Release|ARM + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM.Build.0 = Release|ARM + {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|ARM.ActiveCfg = Debug|ARM + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM.Build.0 = Debug|ARM + {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|ARM.ActiveCfg = Release|ARM + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM.Build.0 = Release|ARM + {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|ARM.ActiveCfg = Debug|ARM + {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM.Build.0 = Debug|ARM + {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|ARM.ActiveCfg = Release|ARM + {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM.Build.0 = Release|ARM + {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 + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM.ActiveCfg = Debug|ARM + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM.Build.0 = Debug|ARM + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM64.Build.0 = Debug|ARM64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|Win32.ActiveCfg = Debug|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|Win32.Build.0 = Debug|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.ActiveCfg = Debug|x64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.Build.0 = Debug|x64 + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM.ActiveCfg = Release|ARM + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM.Build.0 = Release|ARM + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM64.ActiveCfg = Release|ARM64 + {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM64.Build.0 = Release|ARM64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.ActiveCfg = Release|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.Build.0 = Release|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.ActiveCfg = Release|x64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.Build.0 = Release|x64 + {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM.ActiveCfg = Debug|ARM + {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM.Build.0 = Debug|ARM + {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|ARM.ActiveCfg = Release|ARM + {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM.Build.0 = Release|ARM + {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|ARM.ActiveCfg = Debug|ARM + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|ARM.Build.0 = Debug|ARM + {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|ARM.ActiveCfg = Release|ARM + {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|ARM.Build.0 = Release|ARM + {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|ARM.ActiveCfg = Debug|ARM + {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|ARM.Build.0 = Debug|ARM + {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|ARM.ActiveCfg = Release|ARM + {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|ARM.Build.0 = Release|ARM + {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 -- cgit v1.3.1